2023-12-15 09:37:42 +01:00
#![ feature(test, type_alias_impl_trait) ]
extern crate test ;
use aoc2023 ::{ boilerplate , common ::* } ;
const DAY : usize = 15 ;
2023-12-15 10:22:31 +01:00
type I = usize ;
2023-12-15 09:37:42 +01:00
type Parsed < ' a > = impl Iterator < Item = & ' a str > + Clone ;
fn parse_input ( raw : & str ) -> Parsed {
raw . trim_end_matches ( '\n' ) . split ( ',' )
}
2023-12-15 10:22:31 +01:00
fn hash ( s : & [ u8 ] ) -> I {
s . iter ( ) . fold ( 0 , | acc , & b | ( acc + b as I ) * 17 & 255 )
2023-12-15 09:37:42 +01:00
}
fn part1 ( parsed : & Parsed ) -> I {
2023-12-15 10:22:31 +01:00
parsed . clone ( ) . map ( | s | hash ( s . as_bytes ( ) ) ) . sum ( )
2023-12-15 09:37:42 +01:00
}
fn part2 ( parsed : & Parsed ) -> I {
2023-12-15 10:22:31 +01:00
let mut boxes : Vec < Vec < ( & [ u8 ] , u8 ) > > = vec! [ vec! [ ] ; 256 ] ;
for s in parsed . clone ( ) {
match s . as_bytes ( ) {
[ label @ .. , b '-' ] = > {
let hash = hash ( & label ) ;
if let Some ( p ) = boxes [ hash ] . iter ( ) . position ( | ( l , _ ) | l = = & label ) {
boxes [ hash ] . remove ( p ) ;
}
}
[ label @ .. , b '=' , focal_strength ] = > {
let hash = hash ( & label ) ;
match boxes [ hash ] . iter ( ) . position ( | ( l , _ ) | l = = & label ) {
Some ( p ) = > boxes [ hash ] [ p ] = ( & label , focal_strength - b '0' ) ,
None = > boxes [ hash ] . push ( ( & label , focal_strength - b '0' ) ) ,
}
}
_ = > unreachable! ( ) ,
}
}
boxes . into_iter ( ) . zip ( 1 .. ) . flat_map ( | ( b , i ) | b . into_iter ( ) . zip ( 1 .. ) . map ( move | ( ( _ , f ) , j ) | i * j * f as I ) ) . sum ( )
2023-12-15 09:37:42 +01:00
}
boilerplate! {
TEST_INPUT = = " rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7 "
for tests : {
part1 : { TEST_INPUT = > 1320 } ,
2023-12-15 10:22:31 +01:00
part2 : { TEST_INPUT = > 145 } ,
2023-12-15 09:37:42 +01:00
} ,
bench1 = = 510273 ,
2023-12-15 10:22:31 +01:00
bench2 = = 212449 ,
2023-12-15 09:37:42 +01:00
bench_parse : | i : & Parsed | i . clone ( ) . count ( ) = > 4000 ,
}