From 45603e36bfb66e4da96e8438bccb24b7ea818d7e Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Sat, 6 Jul 2024 22:17:02 +0200 Subject: [PATCH] day(21): add solution Signed-off-by: Matej Focko --- samples/day21.txt | 11 +++++ src/bin/day21.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 samples/day21.txt create mode 100644 src/bin/day21.rs diff --git a/samples/day21.txt b/samples/day21.txt new file mode 100644 index 0000000..c66328c --- /dev/null +++ b/samples/day21.txt @@ -0,0 +1,11 @@ +........... +.....###.#. +.###.##..#. +..#.#...#.. +....#.#.... +.##..S####. +.##..#...#. +.......##.. +.##.#.####. +.##..##.##. +........... \ No newline at end of file diff --git a/src/bin/day21.rs b/src/bin/day21.rs new file mode 100644 index 0000000..814c338 --- /dev/null +++ b/src/bin/day21.rs @@ -0,0 +1,111 @@ +use std::collections::HashSet; + +use aoc_2023::*; +use itertools::iproduct; + +type Position = Vector2D; + +lazy_static! { + static ref DIRECTIONS: Vec = vec![ + Position::new(0, 1), + Position::new(0, -1), + Position::new(1, 0), + Position::new(-1, 0), + ]; +} +const WIDTH: isize = 131; + +fn _mod(n: isize, m: isize) -> isize { + (m + (n % m)) % m +} + +type Output1 = usize; +type Output2 = f64; + +struct Steps<'a> { + plots: &'a HashSet, + positions: HashSet, +} + +impl<'a> Steps<'a> { + fn new(plots: &'a HashSet) -> Self { + Self { + plots, + positions: HashSet::from([Position::new(65, 65)]), + } + } + + fn move_gardener(&mut self) { + let mut next_positions = HashSet::new(); + + for (&pos, &dir) in iproduct!(self.positions.iter(), DIRECTIONS.iter()) { + let next_pos = pos + dir; + let cropped = Position::new(_mod(next_pos.x(), WIDTH), _mod(next_pos.y(), WIDTH)); + if self.plots.contains(&cropped) { + next_positions.insert(next_pos); + } + } + + self.positions = next_positions; + } +} + +impl<'a> Iterator for Steps<'a> { + type Item = usize; + + fn next(&mut self) -> Option { + let current = self.positions.len(); + self.move_gardener(); + Some(current) + } +} + +struct Day21 { + plots: HashSet, +} +impl Solution for Day21 { + fn new>(pathname: P) -> Self { + let lines: Vec = file_to_lines(pathname); + + let plots = (0_isize..) + .zip(lines.iter()) + .flat_map(move |(y, row)| { + (0_isize..).zip(row.chars()).filter_map(move |(x, c)| { + if c != '#' { + Some(Position::new(x, y)) + } else { + None + } + }) + }) + .collect(); + + Self { plots } + } + + fn part_1(&mut self) -> Output1 { + Steps::new(&self.plots).nth(64).unwrap() + } + + fn part_2(&mut self) -> Output2 { + let steps = Steps::new(&self.plots).take(328).collect_vec(); + + let (x0, y0) = (65_f64, steps[65] as f64); + let (x1, y1) = (196_f64, steps[196] as f64); + let (x2, y2) = (327_f64, steps[327] as f64); + + let y01 = (y1 - y0) / (x1 - x0); + let y12 = (y2 - y1) / (x2 - x1); + let y012 = (y12 - y01) / (x2 - x0); + + let n = 26501365_f64; + + y0 + y01 * (n - x0) + y012 * (n - x0) * (n - x1) + } +} + +fn main() -> Result<()> { + Day21::main() +} + +test_sample!(day_21, Day21, 0, 0);