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::collections::VecDeque;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
use color_eyre::{eyre};
|
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)]
|
#[allow(dead_code)]
|
||||||
impl<T> Vec2<T> {
|
impl<T> Vec2<T> {
|
||||||
pub fn new(columns: usize) -> Vec2<T> {
|
pub fn new(columns: usize) -> Vec2<T> {
|
||||||
@ -131,6 +169,11 @@ impl<T> Vec2<T> {
|
|||||||
(i / self.columns, i % self.columns)
|
(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]> {
|
pub fn rows(&self) -> impl Iterator<Item=&[T]> {
|
||||||
self.data.chunks_exact(self.columns)
|
self.data.chunks_exact(self.columns)
|
||||||
}
|
}
|
||||||
@ -142,6 +185,33 @@ impl<T> Vec2<T> {
|
|||||||
pub fn values(&self) -> impl Iterator<Item=&T> {
|
pub fn values(&self) -> impl Iterator<Item=&T> {
|
||||||
self.data.iter()
|
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)]
|
&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;
|
mod lib;
|
||||||
use lib::load;
|
use lib::load;
|
||||||
mod day10;
|
mod day11;
|
||||||
|
|
||||||
|
|
||||||
fn main() -> eyre::Result<()> {
|
fn main() -> eyre::Result<()> {
|
||||||
let data = load("data/10.txt")?;
|
let data = load("data/11.txt")?;
|
||||||
|
|
||||||
let start = Instant::now();
|
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 (dur, unit) = format_ns(start.elapsed().as_nanos());
|
||||||
|
|
||||||
let precision = 2.0 - dur.log10().floor();
|
let precision = 2.0 - dur.log10().floor();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user