From 6030065f95a13ad191b3aac0b93941dd5cead9db Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Wed, 3 Dec 2025 21:28:49 -0800 Subject: [PATCH] day4: part1 --- .aoc_tiles/tiles/2025/04.png | Bin 0 -> 6281 bytes README.md | 5 +++- src/day4.rs | 47 +++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + utils/grid/lib.rs | 22 ++++++++++++++++ 5 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 .aoc_tiles/tiles/2025/04.png create mode 100644 src/day4.rs diff --git a/.aoc_tiles/tiles/2025/04.png b/.aoc_tiles/tiles/2025/04.png new file mode 100644 index 0000000000000000000000000000000000000000..2b574ecec7196188c4510c8d48263097d4fdbdfa GIT binary patch literal 6281 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

- 2025 - 6 ⭐ - Rust + 2025 - 7 ⭐ - Rust

@@ -11,4 +11,7 @@ + + + diff --git a/src/day4.rs b/src/day4.rs new file mode 100644 index 0000000..ab98f5e --- /dev/null +++ b/src/day4.rs @@ -0,0 +1,47 @@ +use aoc_runner_derive::{aoc, aoc_generator}; +use grid::Grid; + +#[aoc_generator(day4)] +fn parse(input: &str) -> Grid { + input.parse().unwrap() +} + +#[aoc(day4, part1)] +fn part1(input: &Grid) -> u64 { + (0..input.height() * input.width()) + .filter(|i| *input.get(&input.coord(*i as i64).unwrap()).unwrap() == b'@') + .map(|i| input.neighbours_count(input.coord(i as i64).unwrap(), |c| *c == b'@')) + .filter(|n| *n < 4) + .count() as u64 +} + +#[aoc(day4, part2)] +fn part2(input: &Grid) -> u64 { + input.width() as u64 +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLE: &str = "..@@.@@@@. +@@@.@.@.@@ +@@@@@.@.@@ +@.@@@@..@. +@@.@@@@.@@ +.@@@@@@@.@ +.@.@.@.@@@ +@.@@@.@@@@ +.@@@@@@@@. +@.@.@@@.@."; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse(EXAMPLE)), 13); + } + + #[test] + fn part2_example() { + assert_eq!(part2(&parse(EXAMPLE)), 0); + } +} diff --git a/src/lib.rs b/src/lib.rs index 31454ef..3961a65 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ mod day1; mod day2; mod day3; +mod day4; use aoc_runner_derive::aoc_lib; diff --git a/utils/grid/lib.rs b/utils/grid/lib.rs index 67f810c..2b0b6e3 100644 --- a/utils/grid/lib.rs +++ b/utils/grid/lib.rs @@ -352,6 +352,28 @@ impl Grid { } } + /// Return the count of neighbours (8 directions) matching predicate p + pub fn neighbours_count(&self, c: C, mut p: P) -> usize + where + P: FnMut(&T) -> bool, + { + const DIRECTIONS: [(i64, i64); 8] = [ + (-1, -1), + (0, -1), + (1, -1), + (-1, 0), + (1, 0), + (1, 1), + (0, 1), + (-1, 1), + ]; + DIRECTIONS + .iter() + .map(|d| (c.x() + d.0, c.y() + d.1)) + .filter(|c| self.get(c).is_some_and(|x| p(x))) + .count() + } + // fn window_compare_impl(&self, needle: &[T]) -> Vec<(i64, i64)> { // if (self.width as usize) < needle.len() { // return Vec::new();