summaryrefslogtreecommitdiffstats
path: root/src/2021/11/mod.rs
blob: f7f3b99129bbc1773370caaf6d08d3b08e8b509f (plain) (blame)
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
67
68
69
70
71
72
73
74
75
76
77
78
use crate::util::grid::*;

fn iterate(grid: &mut Grid<(u8, bool)>) -> i64 {
    let mut flashes = 0;
    for (cell, _) in grid.cells_mut() {
        *cell += 1;
    }

    loop {
        let mut new_flashes = 0;
        let mut updates: Grid<u8> = Grid::default();
        updates.grow(grid.rows(), grid.cols());
        for ((row, col), (cell, flashed)) in grid.indexed_cells_mut() {
            if *flashed {
                continue;
            }
            if *cell > 9 {
                *flashed = true;
                new_flashes += 1;
                for (row, col) in updates.adjacent(row, col, true) {
                    updates[row][col] += 1;
                }
            }
        }
        if new_flashes > 0 {
            flashes += new_flashes;
            for ((row, col), val) in updates.indexed_cells() {
                grid[row][col].0 += val;
            }
        } else {
            break;
        }
    }

    for (cell, flashed) in grid.cells_mut() {
        if *flashed {
            *cell = 0;
            *flashed = false;
        }
    }

    flashes
}

pub fn part1() -> anyhow::Result<i64> {
    let mut map = data_digit_grid!()
        .indexed_cells()
        .map(|((row, col), cell)| ((row, col), (*cell, false)))
        .collect();
    let mut flashes = 0;
    for _ in 0..100 {
        flashes += iterate(&mut map);
    }
    Ok(flashes)
}

pub fn part2() -> anyhow::Result<i64> {
    let mut map = data_digit_grid!()
        .indexed_cells()
        .map(|((row, col), cell)| ((row, col), (*cell, false)))
        .collect();

    let mut step = 1;
    loop {
        let flashes = iterate(&mut map);
        if flashes == (map.rows().0 * map.cols().0).try_into()? {
            break;
        }
        step += 1;
    }
    Ok(step)
}

#[test]
fn test() {
    assert_eq!(part1().unwrap(), 1673);
    assert_eq!(part2().unwrap(), 279);
}