diff --git a/src/solutions/day_08.rs b/src/solutions/day_08.rs new file mode 100644 index 0000000..4ae79cf --- /dev/null +++ b/src/solutions/day_08.rs @@ -0,0 +1,113 @@ +use itertools::Itertools; + +use crate::common::{Answer, Solution}; + +pub struct Day08; + +impl Solution for Day08 { + fn name(&self) -> &'static str { + "Resonant Collinearity" + } + + fn part_a(&self, input: &str) -> Answer { + let bound_x = 0..(input.lines().count() as i64); + let bound_y = 0..(input.lines().next().unwrap().len() as i64); + + let antennas = input + .lines() + .enumerate() + .flat_map(|(x, l)| { + l.chars() + .enumerate() + .filter(|(_, c)| *c != '.') + .map(move |(y, c)| (c, (x as i64, y as i64))) + }) + .into_group_map(); + + antennas + .iter() + .flat_map(|(_, pos)| pos.iter().tuple_combinations::<(_, _)>()) + .flat_map(|((x1, y1), (x2, y2))| { + let diff_x = x1 - x2; + let diff_y = y1 - y2; + + [(x1 + diff_x, y1 + diff_y), (x2 - diff_x, y2 - diff_y)] + }) + .filter(|(x, y)| bound_x.contains(x) && bound_y.contains(y)) + .unique() + .count() + .into() + } + + fn part_b(&self, input: &str) -> Answer { + let bound_x = 0..(input.lines().count() as i64); + let bound_y = 0..(input.lines().next().unwrap().len() as i64); + + let antennas = input + .lines() + .enumerate() + .flat_map(|(x, l)| { + l.chars() + .enumerate() + .filter(|(_, c)| *c != '.') + .map(move |(y, c)| (c, (x as i64, y as i64))) + }) + .into_group_map(); + + antennas + .iter() + .flat_map(|(_, pos)| pos.iter().tuple_combinations::<(_, _)>()) + .flat_map(|((x1, y1), (x2, y2))| { + let diff_x = x1 - x2; + let diff_y = y1 - y2; + + // we go from 0 because antennas also count as antinodes here + let before = (0..) + .map(move |n| (x1 + diff_x * n, y1 + diff_y * n)) + .take_while(|(x, y)| bound_x.contains(x) && bound_y.contains(y)); + + let after = (0..) + .map(move |n| (x2 - diff_x * n, y2 - diff_y * n)) + .take_while(|(x, y)| bound_x.contains(x) && bound_y.contains(y)); + + before.chain(after) + }) + .filter(|(x, y)| bound_x.contains(x) && bound_y.contains(y)) + .unique() + .count() + .into() + } +} + +#[cfg(test)] +mod test { + use super::Day08; + use crate::common::Solution; + + use indoc::indoc; + + const INPUT: &str = indoc! {" + ............ + ........0... + .....0...... + .......0.... + ....0....... + ......A..... + ............ + ............ + ........A... + .........A.. + ............ + ............ + "}; + + #[test] + fn part_a() { + assert_eq!(Day08.part_a(INPUT), 14.into()); + } + + #[test] + fn part_b() { + assert_eq!(Day08.part_b(INPUT), 34.into()); + } +} diff --git a/src/solutions/mod.rs b/src/solutions/mod.rs index 43cb192..798dee2 100644 --- a/src/solutions/mod.rs +++ b/src/solutions/mod.rs @@ -7,6 +7,7 @@ mod day_04; mod day_05; mod day_06; mod day_07; +mod day_08; pub const SOLUTIONS: &[&dyn Solution] = &[ &day_01::Day01, @@ -16,4 +17,5 @@ pub const SOLUTIONS: &[&dyn Solution] = &[ &day_05::Day05, &day_06::Day06, &day_07::Day07, + &day_08::Day08, ];