Compare commits

...

2 Commits

Author SHA1 Message Date
4b51bcac08 day4: part2 2025-12-03 21:36:47 -08:00
6030065f95 day4: part1 2025-12-03 21:28:53 -08:00
5 changed files with 93 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -1,6 +1,6 @@
<!-- AOC TILES BEGIN --> <!-- AOC TILES BEGIN -->
<h1 align="center"> <h1 align="center">
2025 - 6 ⭐ - Rust 2025 - 7 ⭐ - Rust
</h1> </h1>
<a href="src/day1.rs"> <a href="src/day1.rs">
<img src=".aoc_tiles/tiles/2025/01.png" width="161px"> <img src=".aoc_tiles/tiles/2025/01.png" width="161px">
@@ -11,4 +11,7 @@
<a href="src/day3.rs"> <a href="src/day3.rs">
<img src=".aoc_tiles/tiles/2025/03.png" width="161px"> <img src=".aoc_tiles/tiles/2025/03.png" width="161px">
</a> </a>
<a href="src/day4.rs">
<img src=".aoc_tiles/tiles/2025/04.png" width="161px">
</a>
<!-- AOC TILES END --> <!-- AOC TILES END -->

66
src/day4.rs Normal file
View File

@@ -0,0 +1,66 @@
use aoc_runner_derive::{aoc, aoc_generator};
use grid::Grid;
#[aoc_generator(day4)]
fn parse(input: &str) -> Grid<u8> {
input.parse().unwrap()
}
#[aoc(day4, part1)]
fn part1(input: &Grid<u8>) -> 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<u8>) -> u64 {
let mut grid = input.clone();
let mut removed = 0;
loop {
let mut removed_iteration = 0;
for i in 0..grid.width() * grid.height() {
let pos = grid.coord(i as i64).unwrap();
if grid.get(&pos).is_some_and(|c| *c == b'@')
&& grid.neighbours_count(pos, |c| *c == b'@') < 4
{
// remove the roll
grid.set(&pos, b'.');
removed_iteration += 1;
}
}
if removed_iteration == 0 {
return removed;
}
removed += removed_iteration
}
}
#[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)), 43);
}
}

View File

@@ -1,6 +1,7 @@
mod day1; mod day1;
mod day2; mod day2;
mod day3; mod day3;
mod day4;
use aoc_runner_derive::aoc_lib; use aoc_runner_derive::aoc_lib;

View File

@@ -352,6 +352,28 @@ impl<T: Clone + Eq + PartialEq + Debug> Grid<T> {
} }
} }
/// Return the count of neighbours (8 directions) matching predicate p
pub fn neighbours_count<C: AsCoord2d, P>(&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<const REV: bool>(&self, needle: &[T]) -> Vec<(i64, i64)> { // fn window_compare_impl<const REV: bool>(&self, needle: &[T]) -> Vec<(i64, i64)> {
// if (self.width as usize) < needle.len() { // if (self.width as usize) < needle.len() {
// return Vec::new(); // return Vec::new();