1type Input = [u8; 144];
12const NEIGHBORS: [u8; 8] = [1, 11, 12, 13, 243, 244, 245, 255];
15
16pub fn parse(input: &str) -> Input {
17 let bytes: Vec<_> = input.lines().map(str::as_bytes).collect();
18 let mut grid = [0; 144];
19
20 for y in 0..10 {
21 for x in 0..10 {
22 grid[12 * (y + 1) + (x + 1)] = bytes[y][x] - b'0';
23 }
24 }
25
26 grid
27}
28
29pub fn part1(input: &Input) -> usize {
30 let (total, _) = simulate(input, |_, steps| steps < 100);
31 total
32}
33
34pub fn part2(input: &Input) -> usize {
35 let (_, steps) = simulate(input, |flashes, _| flashes < 100);
36 steps
37}
38
39fn simulate(input: &Input, predicate: impl Fn(usize, usize) -> bool) -> (usize, usize) {
40 let mut grid = *input;
41 let mut flashed = [true; 144];
42 let mut todo = Vec::with_capacity(100);
43
44 let mut flashes = 0;
45 let mut steps = 0;
46 let mut total = 0;
47
48 while predicate(flashes, steps) {
49 flashes = 0;
50
51 for y in 0..10 {
53 for x in 0..10 {
54 let index = 12 * (y + 1) + (x + 1);
55
56 if grid[index] < 9 {
57 grid[index] += 1;
58 flashed[index] = false;
59 } else {
60 grid[index] = 0;
61 flashed[index] = true;
62 todo.push(index as u8);
63 }
64 }
65 }
66
67 while let Some(index) = todo.pop() {
69 flashes += 1;
70
71 for offset in NEIGHBORS {
72 let next = index.wrapping_add(offset) as usize;
73 if flashed[next] {
74 continue;
75 }
76
77 if grid[next] < 9 {
78 grid[next] += 1;
79 } else {
80 grid[next] = 0;
81 flashed[next] = true;
82 todo.push(next as u8);
83 }
84 }
85 }
86
87 steps += 1;
88 total += flashes;
89 }
90
91 (total, steps)
92}