2020-12-09 08:57:54 +01:00
#![ feature(test) ]
extern crate test ;
use std ::env ;
2020-12-09 10:45:38 +01:00
use itertools ::{ Itertools , MinMaxResult } ;
2020-12-09 08:57:54 +01:00
fn read_input ( ) -> String {
2020-12-09 10:45:38 +01:00
std ::fs ::read_to_string (
env ::args ( )
. nth ( 1 )
. filter ( | n | n ! = " --bench " )
2020-12-10 12:44:07 +01:00
. unwrap_or_else ( | | String ::from ( " inputs/day09 " ) ) ,
2020-12-09 10:45:38 +01:00
)
. unwrap ( )
}
fn parse_input ( raw : & str ) -> Vec < usize > {
raw . lines ( ) . map ( | l | l . parse ( ) . unwrap ( ) ) . collect ( )
}
fn part1 ( input : & [ usize ] , window_size : usize ) -> usize {
* input
. windows ( window_size + 1 )
. find_map ( | xs | {
xs . last ( )
. filter ( | last | ! xs [ .. window_size ] . iter ( ) . tuple_combinations ( ) . any ( | ( a , b ) | a + b = = * * last ) )
} )
. unwrap ( )
2020-12-09 08:57:54 +01:00
}
2020-12-09 10:45:38 +01:00
fn part2 ( input : & [ usize ] , bad_num : usize ) -> usize {
( 0 .. input . len ( ) ) . find_map ( | i | sum_up_to ( & input [ i .. ] , bad_num ) ) . unwrap ( )
}
fn sum_up_to ( input : & [ usize ] , n : usize ) -> Option < usize > {
let mut acc = input [ 0 ] ;
for x in 1 .. input . len ( ) {
acc + = input [ x ] ;
if acc = = n {
return match input [ .. x ] . iter ( ) . minmax ( ) {
MinMaxResult ::MinMax ( min , max ) = > Some ( min + max ) ,
_ = > unreachable! ( ) ,
} ;
}
if acc > n {
return None ;
}
}
return None ;
2020-12-09 08:57:54 +01:00
}
fn main ( ) {
let input = parse_input ( & read_input ( ) ) ;
2020-12-09 10:45:38 +01:00
let p1 = part1 ( & input , 25 ) ;
println! ( " Part 1: {} " , p1 ) ;
println! ( " Part 2: {} " , part2 ( & input , p1 ) ) ;
2020-12-09 08:57:54 +01:00
}
#[ cfg(test) ]
mod tests {
use super ::* ;
use test ::black_box ;
2020-12-09 10:45:38 +01:00
const TEST_INPUT : & str = " 35
20
15
25
47
40
62
55
65
95
102
117
150
182
127
219
299
277
309
576 " ;
#[ test ]
fn part1_test ( ) {
let input = parse_input ( TEST_INPUT ) ;
assert_eq! ( part1 ( & input , 5 ) , 127 ) ;
}
#[ test ]
fn part2_test ( ) {
let input = parse_input ( TEST_INPUT ) ;
assert_eq! ( part2 ( & input , 127 ) , 62 ) ;
}
#[ bench ]
fn bench_part1 ( b : & mut test ::Bencher ) {
let input = parse_input ( & read_input ( ) ) ;
b . iter ( | | assert_eq! ( part1 ( black_box ( & input ) , 25 ) , 393911906 ) ) ;
}
2020-12-09 08:57:54 +01:00
2020-12-09 10:45:38 +01:00
#[ bench ]
fn bench_part2 ( b : & mut test ::Bencher ) {
let input = parse_input ( & read_input ( ) ) ;
b . iter ( | | assert_eq! ( part2 ( black_box ( & input ) , 393911906 ) , 59341885 ) ) ;
}
2020-12-09 08:57:54 +01:00
}