2020-12-15 10:21:03 +01:00
#![ feature(test) ]
2021-04-29 19:14:28 +02:00
#![ allow(clippy::ptr_arg) ]
2020-12-15 10:21:03 +01:00
extern crate test ;
use std ::collections ::HashMap ;
2020-12-16 16:12:41 +01:00
use aoc2020 ::common ::* ;
2020-12-15 10:21:03 +01:00
type Parsed = Vec < usize > ;
fn read_input ( ) -> String {
String ::from ( " 15,12,0,14,3,1 " )
}
2020-12-16 16:12:41 +01:00
#[ inline ]
2020-12-15 10:21:03 +01:00
fn parse_input ( raw : & str ) -> Parsed {
2020-12-16 16:12:41 +01:00
parse_nums ( raw )
2020-12-15 10:21:03 +01:00
}
2020-12-15 10:57:59 +01:00
#[ rustfmt::skip ]
fn part1 ( initial : & Parsed , limit : usize ) -> usize {
( initial . len ( ) .. limit - 1 ) . fold (
( initial . iter ( ) . enumerate ( ) . map ( | ( i , n ) | ( * n , i ) ) . collect ::< HashMap < _ , _ > > ( ) , 0 ) ,
| ( mut prev , curr ) , i | {
let next = prev . get ( & curr ) . map ( | p | i - p ) . unwrap_or ( 0 ) ;
prev . insert ( curr , i ) ;
( prev , next )
} ,
) . 1
2020-12-15 10:21:03 +01:00
}
// only here so the test/bench macro works
2020-12-17 14:51:05 +01:00
#[ allow(unused) ]
2020-12-15 10:32:11 +01:00
#[ inline ]
2020-12-15 10:21:03 +01:00
fn part2 ( parsed : & Parsed , limit : usize ) -> usize {
part1 ( parsed , limit )
}
fn main ( ) {
let input = parse_input ( & read_input ( ) ) ;
println! ( " Part 1: {} " , part1 ( & input , 2020 ) ) ;
println! ( " Part 2: {} " , part1 ( & input , 30000000 ) ) ;
}
#[ cfg(test) ]
mod tests {
use super ::* ;
use aoc2020 ::* ;
use paste ::paste ;
use test ::black_box ;
const TEST_INPUT : & str = " 0,3,6 " ;
test! ( part1 ( 2020 ) = = 436 ) ;
test! ( part2 ( 30000000 ) = = 175594 ) ;
2020-12-15 10:32:11 +01:00
bench! ( part1 ( 2020 ) = = 249 ) ;
// bench!(part2(30000000) == 41687);
2020-12-15 10:21:03 +01:00
bench_input! ( len = = 6 ) ;
}