1
0

Add solution for "Day 4: Printing Department", part 2

This commit is contained in:
Stefan Müller
2026-02-05 09:58:16 +01:00
parent b746cad9ae
commit 7a55f0be92
5 changed files with 106 additions and 38 deletions
+23
View File
@@ -1,9 +1,24 @@
use std::ops;
use std::str::FromStr;
#[derive(Hash, PartialEq, Eq, Debug, Copy, Clone)]
pub struct Point2(pub i64, pub i64);
impl Point2 {
pub const EIGHT_POINT_DIRECTIONS: &'static [Point2] = &[
Point2(-1, -1),
Point2(-1, 0),
Point2(-1, 1),
Point2(0, 1),
Point2(1, 1),
Point2(1, 0),
Point2(1, -1),
Point2(0, -1),
];
pub const FORWARD_DOWN_DIRECTIONS: &'static [Point2] =
&[Point2(-1, 1), Point2(0, 1), Point2(1, 1), Point2(1, 0)];
const POINT_SPLIT_CHAR: char = ',';
pub fn rect_area(&self, other: &Self) -> u64 {
@@ -24,6 +39,14 @@ impl FromStr for Point2 {
}
}
impl ops::Add<&Self> for Point2 {
type Output = Self;
fn add(self, rhs: &Self) -> Self {
Self(self.0 + rhs.0, self.1 + rhs.1)
}
}
#[derive(Hash, PartialEq, Eq, Debug)]
pub struct Point3(pub i64, pub i64, pub i64);
+77 -36
View File
@@ -1,3 +1,4 @@
use crate::common::geometry::Point2;
use crate::solvers::Solver;
use grid::Grid;
use std::io::BufRead;
@@ -6,6 +7,78 @@ pub struct PrintingDepartment {}
impl PrintingDepartment {
const PAPER_ROLL_CHAR: char = '@';
const MAX_NEIGHBORS_ACCESSIBLE: u8 = 3;
fn init_paper_roll_grid<R: BufRead>(&self, 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(&self, 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(
&self,
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 {
@@ -13,41 +86,9 @@ impl Solver for PrintingDepartment {
const PUZZLE_NAME: &'static str = "Printing Department";
fn process_data<R: BufRead>(&self, reader: R) -> (u64, u64) {
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)
.collect(),
);
}
let mut part1 = 0;
'cells: for cell in grid.indexed_iter() {
if *cell.1 {
let mut count = 0;
// TODO: This could be a loop over eight directions instead.
for i in -1i32..=1 {
for j in -1i32..=1 {
if i != 0 || j != 0 {
if let Some(&blocked) = grid.get(
i32::try_from(cell.0.0).unwrap() + i,
i32::try_from(cell.0.1).unwrap() + j,
) {
if blocked {
if count <= 2 {
count += 1;
} else {
continue 'cells;
}
}
}
}
}
}
part1 += 1;
}
}
(part1, 0)
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))
}
}