1use crate::util::parse::*;
12
13type Input = [u8; 144];
14
15pub fn parse(input: &str) -> Input {
16 let mut grid = [0; 144];
17
18 for (y, row) in input.lines().enumerate() {
19 for (x, b) in row.bytes().enumerate() {
20 grid[12 * (y + 1) + (x + 1)] = b.to_decimal();
21 }
22 }
23
24 grid
25}
26
27pub fn part1(input: &Input) -> usize {
28 let (total, _) = simulate(input, |_, steps| steps < 100);
29 total
30}
31
32pub fn part2(input: &Input) -> usize {
33 let (_, steps) = simulate(input, |flashes, _| flashes < 100);
34 steps
35}
36
37fn simulate(input: &Input, predicate: fn(usize, usize) -> bool) -> (usize, usize) {
38 let mut grid = *input;
39 let mut flashed = [true; 144];
40 let mut todo = Vec::with_capacity(100);
41
42 let mut flashes = 0;
43 let mut steps = 0;
44 let mut total = 0;
45
46 while predicate(flashes, steps) {
47 flashes = 0;
48
49 for y in 0..10 {
51 for x in 0..10 {
52 let index = 12 * (y + 1) + (x + 1);
53 flashed[index] = false;
54 bump_octopus(&mut grid, &mut flashed, &mut todo, index);
55 }
56 }
57
58 while let Some(i) = todo.pop() {
60 flashes += 1;
61
62 for next in [i + 1, i + 11, i + 12, i + 13, i - 1, i - 11, i - 12, i - 13] {
63 if !flashed[next] {
64 bump_octopus(&mut grid, &mut flashed, &mut todo, next);
65 }
66 }
67 }
68
69 steps += 1;
70 total += flashes;
71 }
72
73 (total, steps)
74}
75
76#[inline]
78fn bump_octopus(grid: &mut [u8], flashed: &mut [bool], todo: &mut Vec<usize>, index: usize) {
79 if grid[index] < 9 {
80 grid[index] += 1;
81 } else {
82 grid[index] = 0;
83 flashed[index] = true;
84 todo.push(index);
85 }
86}