From b468b66ed2bef2c07f45a0f552acf6a5ea3c6854 Mon Sep 17 00:00:00 2001 From: kageru Date: Tue, 10 Dec 2019 20:55:40 +0100 Subject: [PATCH] Add D10P2 --- 2019/10/src/main.rs | 176 +++++++++++++++----------------------------- 1 file changed, 60 insertions(+), 116 deletions(-) diff --git a/2019/10/src/main.rs b/2019/10/src/main.rs index db746f8..f0430b1 100644 --- a/2019/10/src/main.rs +++ b/2019/10/src/main.rs @@ -1,11 +1,11 @@ -use std::collections::HashSet; +use std::collections::HashMap; use std::io::{self, BufRead}; -#[derive(Clone)] +#[derive(Clone, Debug)] struct Asteroid { x: i64, y: i64, - visible_asteroids: HashSet, + visible_asteroids: HashMap>, } impl Asteroid { @@ -13,23 +13,55 @@ impl Asteroid { Self { x: x as i64, y: y as i64, - visible_asteroids: HashSet::new(), + visible_asteroids: HashMap::new(), } } - fn compute_visibles(mut self, all_asteroids: &Vec) -> Self { - // Technically incorrect because we add ourself here, but since the asteroid with most - // visibles has some legitimate asteroid at an angle of 0°, this doesn’t actually matter. + fn compute_visibles(mut self, all_asteroids: &[Asteroid]) -> Self { for ast in all_asteroids { + if ast.x == self.x && ast.y == self.y { + continue; + } + let angle = calculate_angle(self.x - ast.x, self.y - ast.y); + self.visible_asteroids.entry(angle).or_insert_with(Vec::new); self.visible_asteroids - .insert(calculate_angle(self.x - ast.x, self.y - ast.y)); + .get_mut(&angle) + .unwrap() + .push(ast.to_owned()); } self } + + fn fire_mah_laz0r(self, limit: usize) -> Asteroid { + let x = self.x; + let y = self.y; + let mut visibles: Vec<(i64, Vec)> = self + .visible_asteroids + .into_iter() + .map(|(angle, mut asts)| { + asts.sort_by_key(|a| -((a.x - x).abs() + (a.y - y).abs())); + (angle, asts) + }) + .collect(); + visibles.sort_by_key(|&(angle, _)| angle); + let mut num_destroyed = 0; + for (_, mut asts) in visibles.into_iter().cycle() { + match asts.pop() { + None => (), + Some(ast) => { + num_destroyed += 1; + if num_destroyed == limit { + return ast; + } + } + } + } + unreachable!() + } } -fn main() { - let input: Vec = io::stdin() +fn read_input() -> Vec { + io::stdin() .lock() .lines() .enumerate() @@ -41,8 +73,11 @@ fn main() { .map(move |(x, _)| Asteroid::new(x, y)) .collect::>() }) - .collect(); + .collect() +} +fn main() { + let input = read_input(); let part1 = input .clone() .into_iter() @@ -50,121 +85,30 @@ fn main() { .max_by_key(|ast| ast.visible_asteroids.len()) .unwrap(); println!("Part 1: {}", part1.visible_asteroids.len()); + let part2 = part1.fire_mah_laz0r(200); + println!("Part 2: {}", part2.x * 100 + part2.y); } fn calculate_angle(x_offset: i64, y_offset: i64) -> i64 { - return ((y_offset as f64).atan2(x_offset as f64).to_degrees() * 1000.0).round() as i64; + // Angles in the assignment start at 0 degrees when pointing up (negative y), so we have to + // offset them here. + let mut raw_angle = + (((y_offset as f64).atan2(x_offset as f64).to_degrees() * 1000.0).round() as i64) - 90_000; + if raw_angle < 0 { + raw_angle += 360_000; + } + raw_angle } -//fn part1(asteroids: &HashSet<(i32, i32)>) -> Asteroid { - //unimplemented!() -//} - #[cfg(test)] mod tests { use super::*; #[test] fn test_angle_calculation() { - assert_eq!(calculate_angle(1, 1), 45_000); - assert_eq!(calculate_angle(1, 0), 0); - assert_eq!(calculate_angle(0, -1), -90_000); - assert_eq!(calculate_angle(2, 1), 26_565); - assert_eq!(calculate_angle(1, 1), calculate_angle(3, 3)); - assert_eq!(calculate_angle(-2, -2), -135_000); - assert_eq!(calculate_angle(-2, 2), 135_000); - assert_ne!(calculate_angle(1, 1), calculate_angle(3, -3)); + assert_eq!(calculate_angle(0, -1), 0); + assert_eq!(calculate_angle(1, 0), 90_000); + assert_eq!(calculate_angle(1, 1), 135_000); + assert_eq!(calculate_angle(-1, -1), 315_000); } - - /* - #[test] - fn test_part_1() { - assert_eq!( - part1(&parse_input( - ".#..# - ..... - ##### - ....# - ...##" - .lines() - )).visible_asteroids, - HashSet::new() - ); - - assert_eq!( - part1(&parse_input( - "#.#...#.#. - .###....#. - .#....#... - ##.#.#.#.# - ....#.#.#. - .##..###.# - ..#...##.. - ..##....## - ......#... - .####.###." - .lines() - )), - (1, 2) - ); - assert_eq!( - part1(&parse_input( - ".#..#..### - ####.###.# - ....###.#. - ..###.##.# - ##.##.#.#. - ....###..# - ..#.#..#.# - #..#.#.### - .##...##.# - .....#.#.." - .lines() - )), - (6, 3) - ); - assert_eq!( - part1(&parse_input( - "......#.#. - #..#.#.... - ..#######. - .#.#.###.. - .#..#..... - ..#....#.# - #..#....#. - .##.#..### - ##...#..#. - .#....####" - .lines() - )), - (5, 8) - ); - assert_eq!( - part1(&parse_input( - ".#..##.###...####### - ##.############..##. - .#.######.########.# - .###.#######.####.#. - #####.##.#.##.###.## - ..#####..#.######### - #################### - #.####....###.#.#.## - ##.################# - #####.##.###..####.. - ..######..##.####### - ####.##.####...##..# - .#####..#.######.### - ##...#.##########... - #.##########.####### - .####.#.###.###.#.## - ....##.##.###..##### - .#.#.###########.### - #.#.#.#####.####.### - ###.##.####.##.#..##" - .lines() - )), - (11, 13) - ); - } - */ }