implement day 11

This commit is contained in:
Jan Christian Grünhage 2021-12-11 14:47:15 +01:00
parent 743f1e46fc
commit c473ee4fc7
4 changed files with 167 additions and 0 deletions

67
src/day_11/mod.rs Normal file
View file

@ -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);
}
}

85
src/day_11/model.rs Normal file
View file

@ -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::<String>())
.join("\n")
}
}
fn surrounding((x, y): (usize, usize)) -> impl Iterator<Item = (usize, usize)> {
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<Item = (usize, usize)> {
(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);
}
}

14
src/day_11/parsing.rs Normal file
View file

@ -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<Item = char>) -> Option<OctopusGrid> {
parse_n(
tokens,
&|t| parse_n(t, &|t| parse_digit(t), &|_| true),
&|t| newline(t),
)
.map(|grid| OctopusGrid { grid })
}

View file

@ -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 }