day 11
This commit is contained in:
parent
584cad1690
commit
df55d78dec
76
2021/src/day11.rs
Normal file
76
2021/src/day11.rs
Normal file
@ -0,0 +1,76 @@
|
||||
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))
|
||||
}
|
@ -2,6 +2,7 @@ use std::io::Read;
|
||||
use std::collections::VecDeque;
|
||||
use std::str::FromStr;
|
||||
use std::fs::File;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
use color_eyre::{eyre};
|
||||
@ -108,6 +109,43 @@ pub struct Vec2<T> {
|
||||
}
|
||||
|
||||
|
||||
pub struct NeighborCoords {
|
||||
num_rows: usize,
|
||||
num_cols: usize,
|
||||
start_row: usize,
|
||||
start_col: usize,
|
||||
i: usize,
|
||||
}
|
||||
|
||||
impl Iterator for NeighborCoords {
|
||||
type Item = (usize, usize);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.i > 8 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (rel_row, rel_col) = (self.i / 3, self.i % 3);
|
||||
self.i += 1;
|
||||
if rel_row == 1 && rel_col == 1 {
|
||||
return self.next();
|
||||
}
|
||||
|
||||
let row_offset = self.start_row + rel_row;
|
||||
let col_offset = self.start_col + rel_col;
|
||||
// the "neighbor window" is off by 1, so we make the comparisons off by 1 as well
|
||||
if
|
||||
(row_offset > 0 && row_offset <= self.num_rows
|
||||
&& col_offset > 0 && col_offset <= self.num_cols)
|
||||
{
|
||||
Some((row_offset - 1, col_offset - 1))
|
||||
}
|
||||
else {
|
||||
self.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<T> Vec2<T> {
|
||||
pub fn new(columns: usize) -> Vec2<T> {
|
||||
@ -131,6 +169,11 @@ impl<T> Vec2<T> {
|
||||
(i / self.columns, i % self.columns)
|
||||
}
|
||||
|
||||
pub fn offset(&self, row: usize, col: usize) -> usize {
|
||||
// and the reverse
|
||||
self.columns * row + col
|
||||
}
|
||||
|
||||
pub fn rows(&self) -> impl Iterator<Item=&[T]> {
|
||||
self.data.chunks_exact(self.columns)
|
||||
}
|
||||
@ -142,6 +185,33 @@ impl<T> Vec2<T> {
|
||||
pub fn values(&self) -> impl Iterator<Item=&T> {
|
||||
self.data.iter()
|
||||
}
|
||||
|
||||
pub fn values_mut(&mut self) -> impl Iterator<Item=&mut T> {
|
||||
self.data.iter_mut()
|
||||
}
|
||||
|
||||
pub fn neighbor_coords(&self, row: usize, col: usize) -> NeighborCoords {
|
||||
NeighborCoords {
|
||||
num_rows: self.row_count(),
|
||||
num_cols: self.col_count(),
|
||||
start_row: row,
|
||||
start_col: col,
|
||||
i: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, row: usize, col: usize) -> &T {
|
||||
&self.data[self.offset(row, col)]
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, row: usize, col: usize) -> &mut T {
|
||||
self.data.index_mut(self.offset(row, col))
|
||||
}
|
||||
|
||||
pub fn set(&mut self, row: usize, col: usize, val: T) {
|
||||
let existing = self.data.index_mut(self.offset(row, col));
|
||||
*existing = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -160,3 +230,18 @@ impl<T> IndexMut<usize> for Vec2<T> {
|
||||
&mut self.data[start..(start + self.columns)]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T: Display> Display for Vec2<T> {
|
||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||
for row in self.rows() {
|
||||
write!(f, "[")?;
|
||||
for (i, v) in row.iter().enumerate() {
|
||||
if i > 0 {write!(f, ", ")?;}
|
||||
write!(f, "{}", v)?;
|
||||
}
|
||||
write!(f, "]\n")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,14 @@ use color_eyre::eyre;
|
||||
|
||||
mod lib;
|
||||
use lib::load;
|
||||
mod day10;
|
||||
mod day11;
|
||||
|
||||
|
||||
fn main() -> eyre::Result<()> {
|
||||
let data = load("data/10.txt")?;
|
||||
let data = load("data/11.txt")?;
|
||||
|
||||
let start = Instant::now();
|
||||
let (one, two) = day10::run(&data)?;
|
||||
let (one, two) = day11::run(&data)?;
|
||||
let (dur, unit) = format_ns(start.elapsed().as_nanos());
|
||||
|
||||
let precision = 2.0 - dur.log10().floor();
|
||||
|
Loading…
x
Reference in New Issue
Block a user