2021-12-11 13:36:15 +01:00
#![ feature(bool_to_option) ]
2021-12-11 13:07:08 +01:00
#![ feature(test) ]
extern crate test ;
use aoc2021 ::{
common ::* ,
2021-12-11 22:54:57 +01:00
grid ::{ Grid , HashGrid , PositionND } ,
2021-12-11 13:07:08 +01:00
} ;
const DAY : usize = 11 ;
const ROUNDS : usize = 100 ;
2021-12-11 22:54:57 +01:00
type Parsed = HashGrid < u8 , 2 > ;
2021-12-11 13:07:08 +01:00
fn parse_input ( raw : & str ) -> Parsed {
2021-12-11 22:54:57 +01:00
HashGrid ::< u8 , 2 > ::from_bytes_2d ( raw , | b : u8 | b - b '0' )
2021-12-11 13:07:08 +01:00
}
fn part1 ( parsed : & Parsed ) -> usize {
let mut grid = parsed . to_owned ( ) ;
2021-12-11 13:36:15 +01:00
( 0 .. ROUNDS ) . map ( | _ | make_step ( & mut grid ) ) . sum ( )
}
fn part2 ( parsed : & Parsed ) -> usize {
let mut grid = parsed . to_owned ( ) ;
( 0 .. ) . position ( | _ | make_step ( & mut grid ) = = parsed . len ( ) ) . unwrap ( ) + 1
}
fn make_step ( grid : & mut Parsed ) -> usize {
let mut flashed : Vec < _ > = grid
. fields
. iter_mut ( )
. filter_map ( | ( p , energy ) | {
2021-12-11 13:07:08 +01:00
* energy + = 1 ;
2021-12-11 13:36:15 +01:00
( * energy = = 10 ) . then_some ( * p )
} )
. collect ( ) ;
for p in flashed . clone ( ) {
flash ( grid , & p , & mut flashed ) ;
2021-12-11 13:07:08 +01:00
}
2021-12-11 13:36:15 +01:00
for p in & flashed {
* grid . fields . get_mut ( p ) . unwrap ( ) = 0 ;
}
flashed . len ( )
2021-12-11 13:07:08 +01:00
}
2021-12-11 13:36:15 +01:00
fn flash ( grid : & mut Parsed , position : & PositionND < 2 > , flashed : & mut Vec < PositionND < 2 > > ) {
2021-12-11 13:07:08 +01:00
for n in position . neighbors ( ) {
if let Some ( p ) = grid . fields . get_mut ( & n ) {
* p + = 1 ;
if p = = & 10 {
flashed . push ( n ) ;
2021-12-11 13:36:15 +01:00
flash ( grid , & n , flashed ) ;
2021-12-11 13:07:08 +01:00
}
}
}
}
fn main ( ) {
let input = parse_input ( & read_file ( DAY ) ) ;
println! ( " Part 1: {} " , part1 ( & input ) ) ;
println! ( " Part 2: {} " , part2 ( & input ) ) ;
}
#[ cfg(test) ]
mod tests {
use super ::* ;
use aoc2021 ::* ;
const TEST_INPUT : & str = " 5483143223
2745854711
5264556173
6141336146
6357385478
4167524645
2176841721
6882881134
4846848554
5283751526 " ;
test! ( part1 ( ) = = 1656 ) ;
test! ( part2 ( ) = = 195 ) ;
bench! ( part1 ( ) = = 1741 ) ;
bench! ( part2 ( ) = = 440 ) ;
2021-12-11 22:54:57 +01:00
bench_input! ( HashGrid ::len = > 100 ) ;
2021-12-11 13:07:08 +01:00
}