2021-12-10 14:08:55 +01:00
#![ feature(test) ]
extern crate test ;
use aoc2021 ::common ::* ;
const DAY : usize = 10 ;
2021-12-10 15:09:09 +01:00
fn solve ( input : & str ) -> ( usize , usize ) {
let mut p1_score = 0 ;
let mut p2_scores = Vec ::new ( ) ;
let mut stack = Vec ::new ( ) ;
for line in input . lines ( ) {
match is_well_formed ( line , & mut stack ) {
Ok ( s ) = > p2_scores . push ( autocomplete_points ( s ) ) , // <- clears the stack internally
Err ( p ) = > {
p1_score + = p ;
stack . clear ( ) ;
}
}
}
let p2_len = p2_scores . len ( ) ;
( p1_score , * p2_scores . select_nth_unstable ( p2_len / 2 ) . 1 )
2021-12-10 14:08:55 +01:00
}
2021-12-10 15:09:09 +01:00
fn is_well_formed < ' a > ( line : & str , stack : & ' a mut Vec < u8 > ) -> Result < & ' a mut Vec < u8 > , usize > {
for c in line . bytes ( ) {
match ( stack . last ( ) , c ) {
( _ , b '(' | b '[' | b '<' | b '{' ) = > stack . push ( c ) ,
( Some ( b '(' ) , b ')' ) | ( Some ( b '[' ) , b ']' ) | ( Some ( b '{' ) , b '}' ) | ( Some ( b '<' ) , b '>' ) = > {
stack . pop ( ) ;
2021-12-10 14:08:55 +01:00
}
2021-12-10 15:09:09 +01:00
( _ , b ')' ) = > return Err ( 3 ) ,
( _ , b ']' ) = > return Err ( 57 ) ,
( _ , b '}' ) = > return Err ( 1197 ) ,
( _ , b '>' ) = > return Err ( 25137 ) ,
_ = > unreachable! ( ) ,
2021-12-10 14:08:55 +01:00
}
}
2021-12-10 15:09:09 +01:00
Ok ( stack )
2021-12-10 14:08:55 +01:00
}
2021-12-10 15:09:09 +01:00
fn autocomplete_points ( stack : & mut Vec < u8 > ) -> usize {
2021-12-10 14:08:55 +01:00
let mut points = 0 ;
2021-12-10 15:09:09 +01:00
for p in stack . drain ( .. ) . rev ( ) {
2021-12-10 14:08:55 +01:00
points * = 5 ;
match p {
b '(' = > points + = 1 ,
b '[' = > points + = 2 ,
b '{' = > points + = 3 ,
b '<' = > points + = 4 ,
_ = > unreachable! ( ) ,
}
}
points
}
fn main ( ) {
let raw = read_file ( DAY ) ;
2021-12-10 15:09:09 +01:00
let ( p1 , p2 ) = solve ( & raw ) ;
2021-12-10 14:08:55 +01:00
println! ( " Part 1: {p1} " ) ;
println! ( " Part 2: {p2} " ) ;
}
#[ cfg(test) ]
mod tests {
use super ::* ;
use aoc2021 ::* ;
const TEST_INPUT : & str = " [({(<(())[]>[[{[]{<()<>>
[ ( ( ) [ < > ] ) ] ( { [ < { < < [ ] > > (
{ ( [ ( < { } [ < > [ ] } > { [ ] { [ ( < ( ) >
( ( ( ( { < > } < { < { < > } { [ ] { [ ] { }
[ [ < [ ( [ ] ) ) < ( [ [ { } [ [ ( ) ] ] ]
[ { [ { ( { } ] { } } ( [ { [ { { { } } ( [ ]
{ < [ [ ] ] > } < { [ { [ { [ ] { ( ) [ [ [ ]
[ < ( < ( < ( < { } ) ) > < ( [ ] ( [ ] ( )
< { ( [ ( [ [ ( < > ( ) ) { } ] > ( < < { {
< { ( [ { { } } [ < [ [ [ < > { } ] ] ] > [ ] ] " ;
2021-12-10 15:09:09 +01:00
#[ bench ]
fn bench_autocomplete_points ( b : & mut test ::Bencher ) {
let sample_stack = vec! [ b '<' , b '{' , b '(' , b '[' ] ;
b . iter ( | | assert_eq! ( autocomplete_points ( test ::black_box ( & mut sample_stack . clone ( ) ) ) , 294 ) ) ;
2021-12-10 14:08:55 +01:00
}
#[ test ]
fn part1_test ( ) {
2021-12-10 15:09:09 +01:00
assert_eq! ( solve ( TEST_INPUT ) . 0 , 26397 ) ;
2021-12-10 14:08:55 +01:00
}
#[ test ]
fn part2_test ( ) {
2021-12-10 15:09:09 +01:00
assert_eq! ( solve ( TEST_INPUT ) . 1 , 288957 ) ;
2021-12-10 14:08:55 +01:00
}
#[ bench ]
fn bench_solution ( b : & mut test ::Bencher ) {
let raw = read_file ( DAY ) ;
2021-12-10 15:09:09 +01:00
b . iter ( | | assert_eq! ( solve ( test ::black_box ( & raw ) ) , ( 358737 , 4329504793 ) ) )
2021-12-10 14:08:55 +01:00
}
}