2020-12-10 10:56:13 +01:00
#![ feature(test) ]
extern crate test ;
2020-12-10 11:05:02 +01:00
use std ::env ;
2020-12-10 10:56:13 +01:00
use itertools ::Itertools ;
type Parsed = Vec < usize > ;
2020-12-10 11:05:02 +01:00
const STEP_SIZE : usize = 3 ;
2020-12-10 10:56:13 +01:00
fn read_input ( ) -> String {
std ::fs ::read_to_string (
env ::args ( )
. nth ( 1 )
. filter ( | n | n ! = " --bench " )
. unwrap_or ( String ::from ( " inputs/day10 " ) ) ,
)
. unwrap ( )
}
fn parse_input ( raw : & str ) -> Parsed {
let mut xs : Vec < usize > = raw . lines ( ) . map ( | l | l . parse ( ) . unwrap ( ) ) . collect ( ) ;
2020-12-10 11:05:02 +01:00
xs . push ( 0 ) ;
2020-12-10 10:56:13 +01:00
// faster than using sorted() directly on the iterator
xs . sort_unstable ( ) ;
xs
}
fn part1 ( input : & Parsed ) -> ( usize , usize ) {
2020-12-10 11:05:02 +01:00
input . iter ( ) . tuple_windows ( ) . fold ( ( 0 , 1 ) , | ( one , three ) , ( a , b ) | match b - a {
1 = > ( one + 1 , three ) ,
2 = > ( one , three ) ,
3 = > ( one , three + 1 ) ,
_ = > unreachable! ( ) ,
} )
2020-12-10 10:56:13 +01:00
}
fn part2 ( input : & Parsed ) -> usize {
2020-12-10 11:05:02 +01:00
let mut iter = input . iter ( ) . rev ( ) ;
let max = * iter . next ( ) . unwrap ( ) ;
let mut paths = vec! [ 0 ; max + STEP_SIZE ] ;
2020-12-10 10:56:13 +01:00
paths [ max ] = 1 ;
2020-12-10 11:05:02 +01:00
for & i in iter {
paths [ i ] = ( 1 ..= STEP_SIZE ) . map ( | j | paths [ i + j ] ) . sum ( ) ;
2020-12-10 10:56:13 +01:00
}
2020-12-10 11:05:02 +01:00
paths [ 0 ]
2020-12-10 10:56:13 +01:00
}
fn main ( ) {
let input = parse_input ( & read_input ( ) ) ;
let ( ones , threes ) = part1 ( & input ) ;
println! ( " Part 1: {} " , ones * threes ) ;
println! ( " Part 2: {} " , part2 ( & input ) ) ;
}
#[ cfg(test) ]
mod tests {
use super ::* ;
use test ::black_box ;
const TEST_INPUT : & str = " 28
33
18
42
31
14
46
20
48
47
24
23
49
45
19
38
39
11
1
32
25
35
8
17
7
9
4
2
34
10
3 " ;
#[ test ]
fn part1_test ( ) {
let input = parse_input ( TEST_INPUT ) ;
assert_eq! ( part1 ( & input ) , ( 22 , 10 ) ) ;
}
#[ test ]
fn part2_test ( ) {
let input = parse_input ( TEST_INPUT ) ;
assert_eq! ( part2 ( & input ) , 19208 ) ;
}
#[ bench ]
fn bench_input_parsing ( b : & mut test ::Bencher ) {
let raw = read_input ( ) ;
b . iter ( | | parse_input ( black_box ( & raw ) ) )
}
#[ bench ]
fn bench_part1 ( b : & mut test ::Bencher ) {
let input = parse_input ( & read_input ( ) ) ;
b . iter ( | | assert_eq! ( part1 ( black_box ( & input ) ) , ( 69 , 24 ) ) ) ;
}
#[ bench ]
fn bench_part2 ( b : & mut test ::Bencher ) {
let input = parse_input ( & read_input ( ) ) ;
b . iter ( | | assert_eq! ( part2 ( black_box ( & input ) ) , 56693912375296 ) ) ;
}
}