Refactor day 4 to use Cell enum

This commit is contained in:
Russell Champoux committed 2025-12-05 09:28:58 -05:00
1 parent 52c3f31f54
commit 702221e78f
2 files changed
+46 -27

No files matched your search

+2 -2
View File
@@ -14,9 +14,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
| [Day 1](./src/bin/01.rs) | `102.5µs` | `123.5µs` | | [Day 1](./src/bin/01.rs) | `102.5µs` | `123.5µs` |
| [Day 2](./src/bin/02.rs) | `45.0ms` | `69.6ms` | | [Day 2](./src/bin/02.rs) | `45.0ms` | `69.6ms` |
| [Day 3](./src/bin/03.rs) | `85.1µs` | `121.6µs` | | [Day 3](./src/bin/03.rs) | `85.1µs` | `121.6µs` |
| [Day 4](./src/bin/04.rs) | `260.1µs` | `4.0ms` | | [Day 4](./src/bin/04.rs) | `244.2µs` | `4.1ms` |
**Total: 119.29ms** **Total: 119.38ms**
<!--- benchmarking table ---> <!--- benchmarking table --->
--- ---
+44 -25
View File
@@ -1,7 +1,35 @@
advent_of_code::solution!(4); advent_of_code::solution!(4);
#[derive(Clone, Copy, PartialEq, Eq)]
enum Cell {
Empty,
Paper,
}
impl Cell {
fn from_char(c: char) -> Self {
match c {
'@' => Cell::Paper,
_ => Cell::Empty,
}
}
fn is_paper(self) -> bool {
self == Cell::Paper
}
}
/// Parse input into a grid of cells
fn parse_grid(input: &str) -> Vec<Vec<Cell>> {
input
.lines()
.filter(|line| !line.trim().is_empty())
.map(|line| line.chars().map(Cell::from_char).collect())
.collect()
}
/// Count adjacent paper rolls (8 directions) for a given position /// Count adjacent paper rolls (8 directions) for a given position
fn count_neighbors(grid: &[Vec<char>], row: usize, col: usize) -> usize { fn count_neighbors(grid: &[Vec<Cell>], row: usize, col: usize) -> usize {
let rows = grid.len() as i32; let rows = grid.len() as i32;
let cols = grid[0].len() as i32; let cols = grid[0].len() as i32;
let mut count = 0; let mut count = 0;
@@ -14,7 +42,7 @@ fn count_neighbors(grid: &[Vec<char>], row: usize, col: usize) -> usize {
let nr = row as i32 + dr; let nr = row as i32 + dr;
let nc = col as i32 + dc; let nc = col as i32 + dc;
if nr >= 0 && nr < rows && nc >= 0 && nc < cols { if nr >= 0 && nr < rows && nc >= 0 && nc < cols {
if grid[nr as usize][nc as usize] == '@' { if grid[nr as usize][nc as usize].is_paper() {
count += 1; count += 1;
} }
} }
@@ -24,46 +52,37 @@ fn count_neighbors(grid: &[Vec<char>], row: usize, col: usize) -> usize {
count count
} }
pub fn part_one(input: &str) -> Option<u64> { /// Check if a paper roll at (row, col) is accessible (fewer than 4 neighbors)
let grid: Vec<Vec<char>> = input fn is_accessible(grid: &[Vec<Cell>], row: usize, col: usize) -> bool {
.lines() grid[row][col].is_paper() && count_neighbors(grid, row, col) < 4
.filter(|line| !line.trim().is_empty()) }
.map(|line| line.chars().collect())
.collect();
pub fn part_one(input: &str) -> Option<u64> {
let grid = parse_grid(input);
let mut accessible = 0u64; let mut accessible = 0u64;
for (row, line) in grid.iter().enumerate() { for row in 0..grid.len() {
for (col, &ch) in line.iter().enumerate() { for col in 0..grid[0].len() {
// Only check paper rolls if is_accessible(&grid, row, col) {
if ch == '@' {
// Accessible if fewer than 4 neighbors
if count_neighbors(&grid, row, col) < 4 {
accessible += 1; accessible += 1;
} }
} }
} }
}
Some(accessible) Some(accessible)
} }
pub fn part_two(input: &str) -> Option<u64> { pub fn part_two(input: &str) -> Option<u64> {
let mut grid: Vec<Vec<char>> = input let mut grid = parse_grid(input);
.lines()
.filter(|line| !line.trim().is_empty())
.map(|line| line.chars().collect())
.collect();
let mut total_removed = 0u64; let mut total_removed = 0u64;
loop { loop {
// Find all accessible rolls (fewer than 4 neighbors) // Find all accessible rolls (fewer than 4 neighbors)
let mut to_remove: Vec<(usize, usize)> = Vec::new(); let mut to_remove: Vec<(usize, usize)> = Vec::new();
for (row, line) in grid.iter().enumerate() { for row in 0..grid.len() {
for (col, &ch) in line.iter().enumerate() { for col in 0..grid[0].len() {
if ch == '@' && count_neighbors(&grid, row, col) < 4 { if is_accessible(&grid, row, col) {
to_remove.push((row, col)); to_remove.push((row, col));
} }
} }
@@ -76,7 +95,7 @@ pub fn part_two(input: &str) -> Option<u64> {
// Remove all accessible rolls // Remove all accessible rolls
for (row, col) in &to_remove { for (row, col) in &to_remove {
grid[*row][*col] = '.'; grid[*row][*col] = Cell::Empty;
} }
total_removed += to_remove.len() as u64; total_removed += to_remove.len() as u64;