From 55833d081cf6e185aae9d9e0998d1696794a74ed Mon Sep 17 00:00:00 2001 From: uku Date: Tue, 10 Dec 2024 21:55:34 +0100 Subject: [PATCH] feat(day10): init --- src/solutions/day_10.rs | 140 ++++++++++++++++++++++++++++++++++++++++ src/solutions/mod.rs | 2 + 2 files changed, 142 insertions(+) create mode 100644 src/solutions/day_10.rs diff --git a/src/solutions/day_10.rs b/src/solutions/day_10.rs new file mode 100644 index 0000000..7eb532b --- /dev/null +++ b/src/solutions/day_10.rs @@ -0,0 +1,140 @@ +use std::collections::HashSet; + +use crate::common::{Answer, Solution}; + +pub struct Day10; + +impl Solution for Day10 { + fn name(&self) -> &'static str { + "Hoof It" + } + + fn part_a(&self, input: &str) -> Answer { + let grid = input + .lines() + .map(|l| { + l.chars() + .map(|c| c.to_digit(10).unwrap()) + .collect::>() + }) + .collect::>(); + + grid.iter() + .enumerate() + .flat_map(|(x, l)| { + l.iter() + .enumerate() + .filter(|(_, n)| **n == 0) + .map(move |(y, _)| (x, y)) + }) + .map(|(start_x, start_y)| { + let mut robots = HashSet::new(); + robots.insert(Robot(start_x, start_y)); + + while !robots.iter().all(|r| r.is_done(&grid)) { + robots = robots + .into_iter() + .flat_map(|r| r.propagate(&grid)) + .collect(); + } + + robots.len() + }) + .sum::() + .into() + } + + fn part_b(&self, input: &str) -> Answer { + let grid = input + .lines() + .map(|l| { + l.chars() + .map(|c| c.to_digit(10).unwrap()) + .collect::>() + }) + .collect::>(); + + grid.iter() + .enumerate() + .flat_map(|(x, l)| { + l.iter() + .enumerate() + .filter(|(_, n)| **n == 0) + .map(move |(y, _)| (x, y)) + }) + .map(|(start_x, start_y)| { + let mut robots = vec![Robot(start_x, start_y)]; + + while !robots.iter().all(|r| r.is_done(&grid)) { + robots = robots + .into_iter() + .flat_map(|r| r.propagate(&grid)) + .collect(); + } + + robots.len() + }) + .sum::() + .into() + } +} + +#[derive(Debug, Hash, PartialEq, Eq)] +struct Robot(usize, usize); + +impl Robot { + fn is_done(&self, grid: &[Vec]) -> bool { + grid[self.0][self.1] == 9 + } + + fn propagate(self, grid: &[Vec]) -> Vec { + if self.is_done(grid) { + vec![self] + } else { + let max_x = grid.len() - 1; + let max_y = grid[0].len() - 1; + let current = grid[self.0][self.1]; + + [ + self.0.checked_sub(1).map(|n| (n, self.1)), + (self.0 < max_x).then(|| (self.0 + 1, self.1)), + self.1.checked_sub(1).map(|n| (self.0, n)), + (self.1 < max_y).then(|| (self.0, self.1 + 1)), + ] + .iter() + .filter_map(|o| *o) + .filter(|(x, y)| grid[*x][*y] == current + 1) + .map(|(x, y)| Self(x, y)) + .collect() + } + } +} + +#[cfg(test)] +mod test { + use super::Day10; + use crate::common::Solution; + + use indoc::indoc; + + const INPUT: &str = indoc! {" + 89010123 + 78121874 + 87430965 + 96549874 + 45678903 + 32019012 + 01329801 + 10456732 + "}; + + #[test] + fn part_a() { + assert_eq!(Day10.part_a(INPUT), 36.into()); + } + + #[test] + fn part_b() { + assert_eq!(Day10.part_b(INPUT), 81.into()); + } +} diff --git a/src/solutions/mod.rs b/src/solutions/mod.rs index c5c69cf..c4d30ca 100644 --- a/src/solutions/mod.rs +++ b/src/solutions/mod.rs @@ -9,6 +9,7 @@ mod day_06; mod day_07; mod day_08; mod day_09; +mod day_10; pub const SOLUTIONS: &[&dyn Solution] = &[ &day_01::Day01, @@ -20,4 +21,5 @@ pub const SOLUTIONS: &[&dyn Solution] = &[ &day_07::Day07, &day_08::Day08, &day_09::Day09, + &day_10::Day10, ];