Day 11 part 1 and 2

This commit is contained in:
Bill Thiede 2021-12-10 22:35:59 -08:00
parent 69a9bb276d
commit 197fc4dc2c
5 changed files with 633 additions and 0 deletions

38
2021/Cargo.lock generated
View File

@ -10,6 +10,7 @@ dependencies = [
"anyhow", "anyhow",
"aoc-runner", "aoc-runner",
"aoc-runner-derive", "aoc-runner-derive",
"pretty_assertions",
"thiserror", "thiserror",
] ]
@ -57,12 +58,49 @@ dependencies = [
"serde_json", "serde_json",
] ]
[[package]]
name = "ctor"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "diff"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "0.4.8" version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "output_vt100"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
dependencies = [
"winapi",
]
[[package]]
name = "pretty_assertions"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0cfe1b2403f172ba0f234e500906ee0a3e493fb81092dac23ebefe129301cc"
dependencies = [
"ansi_term",
"ctor",
"diff",
"output_vt100",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.32" version = "1.0.32"

View File

@ -10,4 +10,5 @@ ansi_term = "0.12.1"
anyhow = "1.0.45" anyhow = "1.0.45"
aoc-runner = "0.3.0" aoc-runner = "0.3.0"
aoc-runner-derive = "0.3.0" aoc-runner-derive = "0.3.0"
pretty_assertions = "1.0.0"
thiserror = "1.0.30" thiserror = "1.0.30"

10
2021/input/2021/day11.txt Normal file
View File

@ -0,0 +1,10 @@
7313511551
3724855867
2374331571
4438213437
6511566287
6727245532
3736868662
2348138263
2417483121
8812617112

583
2021/src/day11.rs Normal file
View File

@ -0,0 +1,583 @@
use std::{
collections::HashSet,
convert::Infallible,
fmt::{Debug, Error, Formatter},
num::ParseIntError,
ops::{Index, IndexMut},
str::FromStr,
};
use anyhow::Result;
use aoc_runner_derive::{aoc, aoc_generator};
use thiserror::Error;
struct Image {
width: usize,
height: usize,
pixels: Vec<u8>,
flashes: usize,
}
impl Image {
fn kernel3x3<F>(&mut self, (x, y): (usize, usize), func: F)
where
F: Fn(u8) -> u8,
{
println!("flash @ ({}, {})", x, y);
if x > 0 {
self[(x - 1, y)] = func(self[(x - 1, y)]);
if y > 0 {
self[(x - 1, y - 1)] = func(self[(x - 1, y - 1)]);
}
if y < self.height - 1 {
self[(x - 1, y + 1)] = func(self[(x - 1, y + 1)]);
}
}
if y > 0 {
self[(x, y - 1)] = func(self[(x, y - 1)]);
}
if y < self.height - 1 {
self[(x, y + 1)] = func(self[(x, y + 1)]);
}
if x < self.width - 1 {
self[(x + 1, y)] = func(self[(x + 1, y)]);
if y > 0 {
self[(x + 1, y - 1)] = func(self[(x + 1, y - 1)]);
}
if y < self.height - 1 {
self[(x + 1, y + 1)] = func(self[(x + 1, y + 1)]);
}
}
}
fn step(&mut self) {
self.pixels.iter_mut().for_each(|p| *p += 1);
let mut flashed: HashSet<(usize, usize)> = HashSet::new();
loop {
let mut flashes = 0;
// Apply the effect of a flash on neighbors
dbg!(&self);
let mut need_to_flash = Vec::new();
for y in 0..self.height {
for x in 0..self.width {
if self[(x, y)] > 9 && !flashed.contains(&(x, y)) {
need_to_flash.push((x, y));
}
}
}
for (x, y) in need_to_flash {
self.kernel3x3((x, y), |x| x + 1);
flashed.insert((x, y));
flashes += 1;
}
if flashes == 0 {
break;
}
self.flashes += flashes;
}
self.pixels.iter_mut().for_each(|p| {
if *p > 9 {
*p = 0
}
});
}
fn sync(&self) -> bool {
let sentinel = self[(0, 0)];
for p in &self.pixels {
if *p != sentinel {
return false;
}
}
true
}
}
impl PartialEq for Image {
fn eq(&self, other: &Self) -> bool {
self.width == other.width && self.height == other.height && self.pixels == other.pixels
}
}
impl Debug for Image {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
writeln!(f)?;
for y in 0..self.height {
for x in 0..self.width {
write!(f, "{:3}", self[(x, y)])?;
}
writeln!(f)?;
}
Ok(())
}
}
impl FromStr for Image {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let rows: Vec<_> = s.lines().collect();
let width = rows[0].len();
let height = rows.len();
let pixels = rows
.iter()
.flat_map(|row| row.as_bytes().iter().map(|b| b - b'0'))
.collect();
Ok(Image {
width,
height,
pixels,
flashes: 0,
})
}
}
impl Index<(usize, usize)> for Image {
type Output = u8;
fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
&self.pixels[x + y * self.width]
}
}
impl IndexMut<(usize, usize)> for Image {
fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output {
&mut self.pixels[x + y * self.width]
}
}
#[aoc(day11, part1)]
fn part1(input: &str) -> Result<usize> {
let mut im: Image = input.parse()?;
for _ in 0..100 {
im.step();
}
if im.width > 11 {
assert!(im.flashes > 1355);
}
Ok(im.flashes)
}
#[aoc(day11, part2)]
fn part2(input: &str) -> Result<usize> {
let mut im: Image = input.parse()?;
for i in 1.. {
im.step();
if im.sync() {
return Ok(i);
}
}
unreachable!();
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::{assert_eq, assert_ne};
#[test]
fn test_part1() -> Result<()> {
let input = r#"
5483143223
2745854711
5264556173
6141336146
6357385478
4167524645
2176841721
6882881134
4846848554
5283751526
"#
.trim();
assert_eq!(part1(input)?, 1656);
Ok(())
}
#[test]
fn test_step() -> Result<()> {
let mut im: Image = r#"
11111
19991
19191
19991
11111
"#
.trim()
.parse()?;
let step1: Image = r#"
34543
40004
50005
40004
34543
"#
.trim()
.parse()?;
let step2: Image = r#"
45654
51115
61116
51115
45654
"#
.trim()
.parse()?;
im.step();
assert_eq!(im, step1);
im.step();
assert_eq!(im, step2);
Ok(())
}
#[test]
fn test_many_iterations() -> Result<()> {
let mut im: Image = r#"
5483143223
2745854711
5264556173
6141336146
6357385478
4167524645
2176841721
6882881134
4846848554
5283751526
"#
.trim()
.parse()?;
let step1: Image = r#"
6594254334
3856965822
6375667284
7252447257
7468496589
5278635756
3287952832
7993992245
5957959665
6394862637
"#
.trim()
.parse()?;
let step2: Image = r#"
8807476555
5089087054
8597889608
8485769600
8700908800
6600088989
6800005943
0000007456
9000000876
8700006848
"#
.trim()
.parse()?;
let step3: Image = r#"
0050900866
8500800575
9900000039
9700000041
9935080063
7712300000
7911250009
2211130000
0421125000
0021119000
"#
.trim()
.parse()?;
let step4: Image = r#"
2263031977
0923031697
0032221150
0041111163
0076191174
0053411122
0042361120
5532241122
1532247211
1132230211
"#
.trim()
.parse()?;
let step5: Image = r#"
4484144000
2044144000
2253333493
1152333274
1187303285
1164633233
1153472231
6643352233
2643358322
2243341322
"#
.trim()
.parse()?;
let step6: Image = r#"
5595255111
3155255222
3364444605
2263444496
2298414396
2275744344
2264583342
7754463344
3754469433
3354452433
"#
.trim()
.parse()?;
let step7: Image = r#"
6707366222
4377366333
4475555827
3496655709
3500625609
3509955566
3486694453
8865585555
4865580644
4465574644
"#
.trim()
.parse()?;
let step8: Image = r#"
7818477333
5488477444
5697666949
4608766830
4734946730
4740097688
6900007564
0000009666
8000004755
6800007755
"#
.trim()
.parse()?;
let step9: Image = r#"
9060000644
7800000976
6900000080
5840000082
5858000093
6962400000
8021250009
2221130009
9111128097
7911119976
"#
.trim()
.parse()?;
let step10: Image = r#"
0481112976
0031112009
0041112504
0081111406
0099111306
0093511233
0442361130
5532252350
0532250600
0032240000
"#
.trim()
.parse()?;
let step10_flashes = 204;
let step20: Image = r#"
3936556452
5686556806
4496555690
4448655580
4456865570
5680086577
7000009896
0000000344
6000000364
4600009543
"#
.trim()
.parse()?;
let step30: Image = r#"
0643334118
4253334611
3374333458
2225333337
2229333338
2276733333
2754574565
5544458511
9444447111
7944446119
"#
.trim()
.parse()?;
let step40: Image = r#"
6211111981
0421111119
0042111115
0003111115
0003111116
0065611111
0532351111
3322234597
2222222976
2222222762
"#
.trim()
.parse()?;
let step50: Image = r#"
9655556447
4865556805
4486555690
4458655580
4574865570
5700086566
6000009887
8000000533
6800000633
5680000538
"#
.trim()
.parse()?;
let step60: Image = r#"
2533334200
2743334640
2264333458
2225333337
2225333338
2287833333
3854573455
1854458611
1175447111
1115446111
"#
.trim()
.parse()?;
let step70: Image = r#"
8211111164
0421111166
0042111114
0004211115
0000211116
0065611111
0532351111
7322235117
5722223475
4572222754
"#
.trim()
.parse()?;
let step80: Image = r#"
1755555697
5965555609
4486555680
4458655580
4570865570
5700086566
7000008666
0000000990
0000000800
0000000000
"#
.trim()
.parse()?;
let step90: Image = r#"
7433333522
2643333522
2264333458
2226433337
2222433338
2287833333
2854573333
4854458333
3387779333
3333333333
"#
.trim()
.parse()?;
let step100: Image = r#"
0397666866
0749766918
0053976933
0004297822
0004229892
0053222877
0532222966
9322228966
7922286866
6789998766
"#
.trim()
.parse()?;
im.step();
assert_eq!(im, step1, "step1");
im.step();
assert_eq!(im, step2, "step2");
im.step();
assert_eq!(im, step3, "step3");
im.step();
assert_eq!(im, step4, "step4");
im.step();
assert_eq!(im, step5, "step5");
im.step();
assert_eq!(im, step6, "step6");
im.step();
assert_eq!(im, step7, "step7");
im.step();
assert_eq!(im, step8, "step8");
im.step();
assert_eq!(im, step9, "step9");
im.step();
assert_eq!(im, step10, "step10");
assert_eq!(im.flashes, step10_flashes, "step10 wrong flashes");
Ok(())
}
#[test]
fn test_part2() -> Result<()> {
let input = r#"
5483143223
2745854711
5264556173
6141336146
6357385478
4167524645
2176841721
6882881134
4846848554
5283751526
"#
.trim();
assert_eq!(part2(input)?, 195);
Ok(())
}
}

View File

@ -1,5 +1,6 @@
pub mod day1; pub mod day1;
pub mod day10; pub mod day10;
pub mod day11;
pub mod day2; pub mod day2;
pub mod day3; pub mod day3;
pub mod day4; pub mod day4;