summaryrefslogtreecommitdiff
path: root/11/src/part-2.rs
blob: 3bdb50e2c17a52fd442b024c92caac2c6434dece (plain)
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
mod tensor;

use std::io::{BufRead};

pub type Matrix<T> = tensor::Tensor<T, 2>;
pub type Index = tensor::Index<2>;


pub fn main() {
    let stdin = std::io::stdin();
    let handle = stdin.lock();

    let mut energy: Matrix<usize> = {
        let mut tmp: Vec<usize> = Vec::new();
        let mut m: usize = 0;
        for l in handle.lines() {
            let line = l.unwrap();
            tmp.extend(line.chars().map(|c| c.to_digit(10).unwrap() as usize));
            m += 1;
        }
        let n = tmp.len()/m;
        Matrix::new_from([m, n], tmp)
    };
    let m = energy.shape()[0];
    let n = energy.shape()[1];

    let mut can_flash: Matrix<bool> = Matrix::new(energy.shape().clone(), true);
    let mut to_increase: Vec<Index> = Vec::new();
    for s in 0.. {
        can_flash.fill(true);
        to_increase.clear();
        for i in 0..m {
            for j in 0..n {
                to_increase.push([i, j]);
            }
        }

        while let Some(idx) = to_increase.pop() {
            if can_flash[idx] {
                energy[idx] += 1;
                if energy[idx] > 9 {
                    let neighbors: [Index; 8] = [[idx[0]                 , idx[1].wrapping_sub(1)], [idx[0]  , idx[1]+1],
                                                 [idx[0].wrapping_sub(1) , idx[1]                ], [idx[0]+1, idx[1]  ],
                                                 [idx[0].wrapping_sub(1) , idx[1].wrapping_sub(1)], [idx[0]+1, idx[1]+1],
                                                 [idx[0].wrapping_sub(1) , idx[1]+1              ], [idx[0]+1, idx[1].wrapping_sub(1)] ];
                    energy[idx] = 0;
                    can_flash[idx] = false;
                    for neighbor in (& neighbors).into_iter().filter(|neighbor| energy.in_bounds(neighbor)) {
                        to_increase.push(*neighbor);
                    }
                }
            }
        }

        let e = energy[[0,0]];
        if energy.data().into_iter().all(|& x| x == e) {
            println!("Synchronized after step {} (so answer is step {})", s, s+1);
            break;
        }
    }

}