1
0
Files
AdventOfCode2025/src/solvers/printing_department.rs
T
2026-07-02 22:13:23 +02:00

91 lines
3.4 KiB
Rust

use crate::common::geometry::Point2;
use crate::solvers::Solver;
use grid::Grid;
use std::io::BufRead;
pub struct PrintingDepartment {}
impl PrintingDepartment {
const PAPER_ROLL_CHAR: char = '@';
const MAX_NEIGHBORS_ACCESSIBLE: u8 = 3;
fn init_paper_roll_grid<R: BufRead>(reader: R) -> Grid<Option<u8>> {
let mut grid = Grid::new(0, 0);
for line in reader.lines().map_while(Result::ok) {
grid.push_row(
line.bytes()
.map(|c| (c == Self::PAPER_ROLL_CHAR as u8).then_some(0_u8))
.collect(),
);
}
grid
}
fn count_neighbors(grid: &mut Grid<Option<u8>>) -> Vec<Point2> {
let mut removables = Vec::new();
let mut location = Point2(0, 0);
// Loops over the grid.
for j in 0..grid.rows() {
location.1 = i64::try_from(j).unwrap();
for i in 0..grid.cols() {
location.0 = i64::try_from(i).unwrap();
let mut count = 0;
if grid.get(j, i).unwrap().is_some() {
// Loops only over the four neighbors that have not yet been encountered. This
// still ensures that we handle each pair of neighbors.
for direction in Point2::FORWARD_DOWN_DIRECTIONS {
if let Some(Some(other)) =
grid.get_mut(location.1 + direction.1, location.0 + direction.0)
{
*other += 1;
count += 1;
}
}
// We know that the cell is Some because of the indices of the loops, and we
// also know that the value in the cell is Some because of the enclosing "if".
let cell_count = grid.get_mut(j, i).unwrap().as_mut().unwrap();
*cell_count += count;
if *cell_count <= Self::MAX_NEIGHBORS_ACCESSIBLE {
removables.push(location);
}
}
}
}
removables
}
fn count_removable_paper_rolls(mut grid: Grid<Option<u8>>, mut removables: Vec<Point2>) -> u64 {
// Considers everything in "removables" as already counted.
let mut result = removables.len() as u64;
while let Some(current) = removables.pop() {
// Updates the neighbors.
for direction in Point2::EIGHT_POINT_DIRECTIONS {
let neighbor = current + direction;
if let Some(Some(other)) = grid.get_mut(neighbor.1, neighbor.0) {
*other -= 1;
if *other == Self::MAX_NEIGHBORS_ACCESSIBLE {
result += 1;
removables.push(neighbor);
}
}
}
// Updates the current location.
let cell = grid.get_mut(current.1, current.0).unwrap();
*cell = None;
}
result
}
}
impl Solver for PrintingDepartment {
const PUZZLE_INDEX: u8 = 4;
const PUZZLE_NAME: &'static str = "Printing Department";
fn process_data<R: BufRead>(&self, reader: R) -> (u64, u64) {
let mut grid = Self::init_paper_roll_grid(reader);
let removables = Self::count_neighbors(&mut grid);
let part1 = removables.len() as u64;
(part1, Self::count_removable_paper_rolls(grid, removables))
}
}