From c473ee4fc798f0499aff2c13874d6bc0c9234a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Christian=20Gr=C3=BCnhage?= Date: Sat, 11 Dec 2021 14:47:15 +0100 Subject: [PATCH] implement day 11 --- src/day_11/mod.rs | 67 ++++++++++++++++++++++++++++++++++ src/day_11/model.rs | 85 +++++++++++++++++++++++++++++++++++++++++++ src/day_11/parsing.rs | 14 +++++++ src/lib.rs | 1 + 4 files changed, 167 insertions(+) create mode 100644 src/day_11/mod.rs create mode 100644 src/day_11/model.rs create mode 100644 src/day_11/parsing.rs diff --git a/src/day_11/mod.rs b/src/day_11/mod.rs new file mode 100644 index 0000000..61fd5bd --- /dev/null +++ b/src/day_11/mod.rs @@ -0,0 +1,67 @@ +mod model; +mod parsing; + +use aoc_runner_derive::{aoc, aoc_generator}; +pub use model::OctopusGrid; +pub use parsing::parse_octopus_grid; +use yap::IntoTokens; + +#[aoc_generator(day11)] +pub fn parse_input(input: &str) -> OctopusGrid { + parse_octopus_grid(&mut input.into_tokens()).unwrap() +} + +#[aoc(day11, part1)] +pub fn part1(input: &OctopusGrid) -> usize { + let mut grid = input.clone(); + let mut sum = 0; + for _ in 0..100 { + sum += grid.step(); + } + sum +} + +#[aoc(day11, part2)] +pub fn part2(input: &OctopusGrid) -> usize { + let mut grid = input.clone(); + let mut counter = 0; + loop { + counter += 1; + if grid.step() == 100 { + return counter; + } + } +} + +#[cfg(test)] +mod test { + const EXAMPLE_INPUT: &str = "5483143223 +2745854711 +5264556173 +6141336146 +6357385478 +4167524645 +2176841721 +6882881134 +4846848554 +5283751526"; + const RESULT_PART_1: usize = 1656; + const RESULT_PART_2: usize = 195; + + #[test] + fn part1_example() { + let result = super::part1(&super::parse_input(EXAMPLE_INPUT)); + assert_eq!(result, RESULT_PART_1); + } + + #[test] + fn part2_example() { + let result = super::part2(&super::parse_input(EXAMPLE_INPUT)); + assert_eq!(result, RESULT_PART_2); + } + + #[test] + fn parse_example() { + super::parse_input(EXAMPLE_INPUT); + } +} diff --git a/src/day_11/model.rs b/src/day_11/model.rs new file mode 100644 index 0000000..c8ed576 --- /dev/null +++ b/src/day_11/model.rs @@ -0,0 +1,85 @@ +use itertools::Itertools; + +#[derive(Clone)] +pub struct OctopusGrid { + pub grid: [[u8; 10]; 10], +} + +impl OctopusGrid { + pub fn step(&mut self) -> usize { + let mut flash_grid: [[bool; 10]; 10] = Default::default(); + grid_iter().for_each(|(x, y)| self.grid[y][x] += 1); + let mut flash_count = 0; + loop { + grid_iter().for_each(|(x, y)| { + if self.grid[y][x] > 9 && !flash_grid[y][x] { + flash_grid[y][x] = true; + surrounding((x, y)).for_each(|(x, y)| self.grid[y][x] += 1); + } + }); + let new_flash_count = flash_grid + .iter() + .flat_map(|col| col.iter()) + .filter(|val| **val) + .count(); + if new_flash_count == flash_count { + break; + } else { + flash_count = new_flash_count; + } + } + grid_iter().for_each(|(x, y)| { + if flash_grid[y][x] { + self.grid[y][x] = 0; + } + }); + flash_count + } +} + +impl ToString for OctopusGrid { + fn to_string(&self) -> String { + self.grid + .iter() + .map(|line| line.iter().map(u8::to_string).collect::()) + .join("\n") + } +} + +fn surrounding((x, y): (usize, usize)) -> impl Iterator { + let (x, y) = (x as isize, y as isize); + (-1..=1) + .cartesian_product(-1..=1) + .filter_map(move |(x_off, y_off)| { + if x + x_off >= 0 + && x + x_off < 10 + && y + y_off >= 0 + && y + y_off < 10 + && (x_off != 0 || y_off != 0) + { + Some(((x + x_off) as usize, (y + y_off) as usize)) + } else { + None + } + }) +} + +fn grid_iter() -> impl Iterator { + (0..10).cartesian_product(0..10) +} + +#[cfg(test)] +mod test { + use super::OctopusGrid; + + #[test] + fn flash() { + let mut grid = OctopusGrid { + grid: Default::default(), + }; + for _ in 0..9 { + assert_eq!(grid.step(), 0); + } + assert_eq!(grid.step(), 100); + } +} diff --git a/src/day_11/parsing.rs b/src/day_11/parsing.rs new file mode 100644 index 0000000..74e4f8a --- /dev/null +++ b/src/day_11/parsing.rs @@ -0,0 +1,14 @@ +use yap::Tokens; + +use crate::parsing::{newline, parse_digit, parse_n}; + +use super::OctopusGrid; + +pub fn parse_octopus_grid(tokens: &mut impl Tokens) -> Option { + parse_n( + tokens, + &|t| parse_n(t, &|t| parse_digit(t), &|_| true), + &|t| newline(t), + ) + .map(|grid| OctopusGrid { grid }) +} diff --git a/src/lib.rs b/src/lib.rs index 5eb57f2..a579490 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,5 +12,6 @@ pub mod day_07; pub mod day_08; pub mod day_09; pub mod day_10; +pub mod day_11; aoc_lib! { year = 2021 }