2023-12-01 07:00:46 +01:00
#![ feature(test) ]
extern crate test ;
use aoc2023 ::{ boilerplate , common ::* } ;
const DAY : usize = 1 ;
type Parsed < ' a > = Vec < & ' a str > ;
fn parse_input ( raw : & str ) -> Parsed < '_ > {
raw . lines ( ) . collect ( )
}
fn part1 ( parsed : & Parsed ) -> usize {
parsed
. iter ( )
. map ( | l | {
2023-12-01 14:01:38 +01:00
let l : Vec < _ > = l . bytes ( ) . filter_map ( digit_as_usize ) . collect ( ) ;
2023-12-01 07:00:46 +01:00
l [ 0 ] * 10 + l . last ( ) . unwrap ( )
} )
. sum ( )
}
const DIGITS : [ & str ; 9 ] = [ " one " , " two " , " three " , " four " , " five " , " six " , " seven " , " eight " , " nine " ] ;
2023-12-01 14:01:38 +01:00
fn digit_as_usize ( b : u8 ) -> Option < usize > {
b . is_ascii_digit ( ) . then_some ( ( b - b '0' ) as usize )
}
2023-12-01 07:00:46 +01:00
fn find_digit ( s : & str ) -> Option < usize > {
2023-12-01 14:01:38 +01:00
digit_as_usize ( s . as_bytes ( ) [ 0 ] ) . or_else ( | | DIGITS . iter ( ) . position ( | d | s . starts_with ( d ) ) . map ( | x | x + 1 ) )
2023-12-01 07:00:46 +01:00
}
fn part2 ( parsed : & Parsed ) -> usize {
parsed
. iter ( )
. map ( | l | {
let first = ( 0 .. l . len ( ) ) . find_map ( | s | find_digit ( & l [ s .. ] ) ) . unwrap ( ) ;
let last = ( 0 .. l . len ( ) ) . rev ( ) . find_map ( | s | find_digit ( & l [ s .. ] ) ) . unwrap ( ) ;
first * 10 + last
} )
. sum ( )
}
#[ cfg(test) ]
const TEST_INPUT_2 : & str = " two1nine
eightwothree
abcone2threexyz
xtwone3four
4 nineeightseven2
zoneight234
7 pqrstsixteen " ;
boilerplate! {
TEST_INPUT = = " 1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet " ,
tests : {
part1 : { TEST_INPUT = > 142 } ,
part2 : { TEST_INPUT_2 = > 281 } ,
} ,
bench1 = = 54916 ,
bench2 = = 54728 ,
bench_parse : Vec ::len = > 1000 ,
}