summaryrefslogtreecommitdiff
path: root/2025/04
diff options
context:
space:
mode:
Diffstat (limited to '2025/04')
-rw-r--r--2025/04/rust/src/main.rs68
1 files changed, 51 insertions, 17 deletions
diff --git a/2025/04/rust/src/main.rs b/2025/04/rust/src/main.rs
index 5d703c5..3b13140 100644
--- a/2025/04/rust/src/main.rs
+++ b/2025/04/rust/src/main.rs
@@ -1,4 +1,4 @@
-use std::io;
+use std::{collections::VecDeque, io};
fn main() {
let mut grid: Vec<Vec<Option<usize>>> = io::stdin()
@@ -7,26 +7,60 @@ fn main() {
.map(|line| line.chars().map(|ch| (ch == '@').then_some(0)).collect())
.collect();
- for (y, row) in grid.iter().enumerate() {
- for (x, p) in row.iter().enumerate() {
- let Some(_) = p else {
- continue;
- };
-
- for nx in x.saturating_sub(1)..=(x + 1).min(row.len() - 1) {
- for ny in y.saturating_sub(1)..=(y + 1).min(grid.len() - 1) {
- // lol quadruple for loop (this makes me sad)
- if (x, y) == (nx, ny) {
- continue;
- }
- let mut h = grid.get(ny).and_then(|r| r.get(nx)).unwrap();
- }
+ // count neighbours
+ points(&grid)
+ .collect::<Vec<_>>()
+ .into_iter()
+ .for_each(|p @ (x, y)| {
+ let ns = neighbours(p, &grid).count();
+ if let Some(n) = grid[y][x].as_mut() {
+ *n = ns;
}
+ });
+
+ let mut stack = points(&grid)
+ .filter(|&(x, y)| grid[y][x].is_some_and(|n| n < 4))
+ .collect::<VecDeque<_>>();
+ let silver = stack.len();
+ let mut gold = 0;
+
+ while let Some(p @ (x, y)) = stack.pop_back() {
+ if grid[y][x].take().is_none() {
+ continue;
}
+ gold += 1;
+ // reduce neighbours' neighbour counts by 1
+ neighbours(p, &grid)
+ .collect::<Vec<_>>()
+ .into_iter()
+ .for_each(|(nx, ny)| {
+ if let Some(n) = grid[ny][nx].as_mut() {
+ *n -= 1;
+ if *n < 4 {
+ stack.push_back((nx, ny))
+ }
+ }
+ });
}
- let silver: u64 = 0;
- let gold: u64 = 0;
println!("silver: {silver}");
println!("gold: {gold}");
}
+
+fn neighbours<T>(
+ (x, y): (usize, usize),
+ grid: &Vec<Vec<Option<T>>>,
+) -> impl Iterator<Item = (usize, usize)> {
+ let xs = x.saturating_sub(1)..=(x + 1).min(grid.first().unwrap().len() - 1);
+ let ys = y.saturating_sub(1)..=(y + 1).min(grid.len() - 1);
+
+ xs.flat_map(move |nx| ys.clone().map(move |ny| (nx, ny)))
+ .filter(move |n| *n != (x, y))
+ .filter(|&(nx, ny)| grid.get(ny).and_then(|row| row.get(nx)).unwrap().is_some())
+}
+
+fn points<T>(grid: &Vec<Vec<T>>) -> impl Iterator<Item = (usize, usize)> {
+ let xs = 0..grid.first().unwrap().len();
+ let ys = 0..grid.len();
+ xs.flat_map(move |x| ys.clone().map(move |y| (x, y)))
+}