Work in progress day 10 part 2

This commit is contained in:
Tyler Hallada 2019-12-28 02:21:37 -05:00
parent 3c5f8e52bb
commit e007f0b3f9

View File

@ -1,7 +1,9 @@
use std::collections::HashMap; use std::cmp::Ordering;
use std::collections::{HashMap, VecDeque};
use std::error::Error; use std::error::Error;
use std::fs::File; use std::fs::File;
use std::io::{prelude::*, BufReader}; use std::io::{prelude::*, BufReader};
use std::iter::FromIterator;
use std::result; use std::result;
use num::integer::gcd; use num::integer::gcd;
@ -22,14 +24,12 @@ struct AsteroidField {
} }
impl AsteroidField { impl AsteroidField {
fn find_monitoring_station(&self) -> (&Point, usize) { fn get_lines_of_sight(&self, from_point: &Point) -> HashMap<(i32, i32), VecDeque<&Point>> {
let mut asteroid_detect_scores = HashMap::new(); let mut lines_of_sight: HashMap<(i32, i32), VecDeque<&Point>> = HashMap::new();
for asteroid in self.asteroids.iter() { for asteroid in self.asteroids.iter() {
let mut lines_of_sight: HashMap<(i32, i32), Point> = HashMap::new(); if from_point != asteroid {
for other in self.asteroids.iter() { let x_dist: i32 = asteroid.x as i32 - from_point.x as i32;
if asteroid != other { let y_dist: i32 = asteroid.y as i32 - from_point.y as i32;
let x_dist: i32 = other.x as i32 - asteroid.x as i32;
let y_dist: i32 = other.y as i32 - asteroid.y as i32;
let mut x_ratio: i32 = 0; let mut x_ratio: i32 = 0;
let mut y_ratio: i32 = 0; let mut y_ratio: i32 = 0;
if x_dist == 0 { if x_dist == 0 {
@ -49,20 +49,40 @@ impl AsteroidField {
x_ratio = x_dist / gcd; x_ratio = x_dist / gcd;
y_ratio = y_dist / gcd; y_ratio = y_dist / gcd;
} }
lines_of_sight lines_of_sight
.entry((x_ratio, y_ratio)) .entry((x_ratio, y_ratio))
.and_modify(|current| { .and_modify(|deque| {
if (current.x as i32 - asteroid.x as i32).abs() > x_dist.abs() let mut insertion_index = None;
&& (current.y as i32 - asteroid.y as i32).abs() > y_dist.abs() for (index, current) in deque.iter().enumerate() {
if (current.x as i32 - from_point.x as i32).abs() > x_dist.abs()
&& (current.y as i32 - from_point.y as i32).abs() > y_dist.abs()
{ {
current.x = other.x; insertion_index = Some(index);
current.y = other.y; break;
}
}
if let Some(index) = insertion_index {
deque.insert(index, asteroid);
} else {
deque.push_back(asteroid);
} }
}) })
.or_insert(other.clone()); .or_insert_with(|| {
let mut deque = VecDeque::new();
deque.push_back(asteroid);
deque
});
} }
} }
lines_of_sight
}
fn find_monitoring_station(&self) -> (&Point, usize) {
let mut asteroid_detect_scores = HashMap::new();
for asteroid in self.asteroids.iter() {
let lines_of_sight = self.get_lines_of_sight(asteroid);
asteroid_detect_scores.insert(asteroid, lines_of_sight.len()); asteroid_detect_scores.insert(asteroid, lines_of_sight.len());
} }
@ -71,6 +91,48 @@ impl AsteroidField {
.max_by_key(|score| score.1) .max_by_key(|score| score.1)
.expect("No asteroid detect scores") .expect("No asteroid detect scores")
} }
fn vaporize_asteroids(&mut self, laser_point: &Point) -> Option<&Point> {
let mut vaporized_counter = 0;
let mut lines_of_sight = self.get_lines_of_sight(laser_point);
let mut directions: Vec<(i32, i32)> = lines_of_sight.keys().map(|key| *key).collect();
directions.sort_by(|a, b| {
let det = a.0 * b.1 - b.0 * a.1;
if det > 0 {
Ordering::Less
} else if det < 0 {
Ordering::Greater
} else {
Ordering::Equal
}
});
let up = directions
.iter()
.position(|&dir| dir == (0, -1))
.expect("No asteroid directly up from laser");
directions.rotate_left(up);
dbg!(&directions);
for direction in directions.iter() {
// dbg!(direction);
let in_sight = lines_of_sight.get_mut(direction);
if let Some(in_sight) = in_sight {
// dbg!(&in_sight);
if let Some(vaporized_asteroid) = in_sight.pop_back() {
vaporized_counter += 1;
// dbg!(&vaporized_counter);
// dbg!(&vaporized_asteroid);
if vaporized_counter == 200 {
return Some(vaporized_asteroid);
}
}
}
}
None
}
} }
fn read_asteroid_field(filename: &str) -> Result<AsteroidField> { fn read_asteroid_field(filename: &str) -> Result<AsteroidField> {
@ -94,8 +156,10 @@ fn solve_part1() -> Result<usize> {
Ok(asteroid_field.find_monitoring_station().1) Ok(asteroid_field.find_monitoring_station().1)
} }
fn solve_part2() -> Result<i64> { fn solve_part2() -> Result<usize> {
Ok(1) let mut asteroid_field = read_asteroid_field("input/test5.txt")?;
let vaporized200 = asteroid_field.vaporize_asteroids(&Point { x: 11, y: 13 }).unwrap();
Ok(vaporized200.x * 100 + vaporized200.y)
} }
fn main() -> Result<()> { fn main() -> Result<()> {