advent/2021/src/day11.rs

77 lines
1.7 KiB
Rust
Raw Normal View History

2021-12-26 00:57:34 +00:00
use std::collections::HashSet;
use color_eyre::eyre;
use eyre::eyre;
use crate::lib::Vec2;
struct Octopi {
grid: Vec2<u8>,
flashed: HashSet<(usize, usize)>,
}
impl Octopi {
fn step(&mut self) -> usize {
for row in 0..self.grid.row_count() {
for col in 0..self.grid.col_count() {
self.inc(row, col);
}
}
let count = self.flashed.len();
self.flashed.clear();
count
}
fn inc(&mut self, row: usize, col: usize) {
if self.flashed.contains(&(row, col)) {
return;
}
let energy = self.grid.get_mut(row, col);
*energy += 1;
if *energy > 9 {
self.flashed.insert((row, col));
*energy = 0;
for (n_row, n_col) in self.grid.neighbor_coords(row, col) {
self.inc(n_row, n_col);
}
}
}
}
fn load(data: &str) -> eyre::Result<Octopi> {
let mut grid = Vec2::new(10);
for line in data.lines() {
let mut row = Vec::with_capacity(10); // kinda inefficient but whatever, it only happens once
for c in line.chars() {
match c.to_digit(10) {
Some(d) => row.push(d as u8),
None => return Err(eyre!("Invalid digit: {}", c)),
}
}
grid.push(row);
}
Ok(Octopi {grid, flashed: HashSet::new()})
}
pub fn run(data: &str) -> eyre::Result<(usize, usize)> {
let mut octopi = load(data)?;
let mut num_flashes = 0;
let mut two = None;
for i in 0.. {
let n = octopi.step();
if i < 100 {
num_flashes += n;
}
if n == 100 {
two = Some(i);
break;
}
}
Ok((num_flashes, two.unwrap() + 1))
}