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::fs::File;
use std::io::{prelude::*, BufReader};
use std::iter::FromIterator;
use std::result;
use num::integer::gcd;
@ -22,47 +24,65 @@ struct AsteroidField {
}
impl AsteroidField {
fn get_lines_of_sight(&self, from_point: &Point) -> HashMap<(i32, i32), VecDeque<&Point>> {
let mut lines_of_sight: HashMap<(i32, i32), VecDeque<&Point>> = HashMap::new();
for asteroid in self.asteroids.iter() {
if from_point != asteroid {
let x_dist: i32 = asteroid.x as i32 - from_point.x as i32;
let y_dist: i32 = asteroid.y as i32 - from_point.y as i32;
let mut x_ratio: i32 = 0;
let mut y_ratio: i32 = 0;
if x_dist == 0 {
if y_dist > 0 {
y_ratio = 1;
} else {
y_ratio = -1;
}
} else if y_dist == 0 {
if x_dist > 0 {
x_ratio = 1;
} else {
x_ratio = -1;
}
} else {
let gcd = gcd(x_dist, y_dist);
x_ratio = x_dist / gcd;
y_ratio = y_dist / gcd;
}
lines_of_sight
.entry((x_ratio, y_ratio))
.and_modify(|deque| {
let mut insertion_index = None;
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()
{
insertion_index = Some(index);
break;
}
}
if let Some(index) = insertion_index {
deque.insert(index, asteroid);
} else {
deque.push_back(asteroid);
}
})
.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 mut lines_of_sight: HashMap<(i32, i32), Point> = HashMap::new();
for other in self.asteroids.iter() {
if asteroid != other {
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 y_ratio: i32 = 0;
if x_dist == 0 {
if y_dist > 0 {
y_ratio = 1;
} else {
y_ratio = -1;
}
} else if y_dist == 0 {
if x_dist > 0 {
x_ratio = 1;
} else {
x_ratio = -1;
}
} else {
let gcd = gcd(x_dist, y_dist);
x_ratio = x_dist / gcd;
y_ratio = y_dist / gcd;
}
lines_of_sight
.entry((x_ratio, y_ratio))
.and_modify(|current| {
if (current.x as i32 - asteroid.x as i32).abs() > x_dist.abs()
&& (current.y as i32 - asteroid.y as i32).abs() > y_dist.abs()
{
current.x = other.x;
current.y = other.y;
}
})
.or_insert(other.clone());
}
}
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());
}
@ -71,6 +91,48 @@ impl AsteroidField {
.max_by_key(|score| score.1)
.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> {
@ -94,8 +156,10 @@ fn solve_part1() -> Result<usize> {
Ok(asteroid_field.find_monitoring_station().1)
}
fn solve_part2() -> Result<i64> {
Ok(1)
fn solve_part2() -> Result<usize> {
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<()> {