1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
use std::{collections::VecDeque, io};
fn main() {
let mut grid: Vec<Vec<Option<usize>>> = io::stdin()
.lines()
.flatten()
.map(|line| line.chars().map(|ch| (ch == '@').then_some(0)).collect())
.collect();
// 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))
}
}
});
}
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)))
}
|