2020-12-10 12:44:07 +01:00
#![ feature(test, map_first_last, binary_heap_into_iter_sorted) ]
2020-12-05 09:50:09 +01:00
extern crate test ;
2020-12-10 14:44:42 +01:00
use aoc2020 ::common ::* ;
2020-12-05 14:41:54 +01:00
use itertools ::Itertools ;
2020-12-10 14:44:42 +01:00
use std ::collections ::BinaryHeap ;
2020-12-05 09:50:09 +01:00
2020-12-05 10:24:11 +01:00
const NUM_ROWS : usize = 128 ;
const NUM_COLS : usize = 8 ;
2020-12-05 14:41:54 +01:00
#[ derive(Debug, PartialEq) ]
2020-12-05 09:50:09 +01:00
struct Position {
row : usize ,
col : usize ,
}
2020-12-05 14:41:54 +01:00
#[ inline ]
2020-12-05 09:50:09 +01:00
fn get_position ( pass : & str ) -> Position {
2020-12-05 10:24:11 +01:00
Position {
2020-12-05 14:41:54 +01:00
row : find_spot ( & pass [ 0 .. 7 ] , 'B' , NUM_ROWS ) ,
col : find_spot ( & pass [ 7 .. ] , 'R' , NUM_COLS ) ,
2020-12-05 10:24:11 +01:00
}
2020-12-05 09:50:09 +01:00
}
2020-12-05 14:41:54 +01:00
fn find_spot ( s : & str , needle : char , max : usize ) -> usize {
s . chars ( )
. zip ( 1 .. )
. filter ( | ( c , _ ) | * c = = needle )
. fold ( 0 , | acc , ( _ , n ) | acc + ( max > > n ) )
}
#[ inline ]
2020-12-05 09:50:09 +01:00
fn calculate_id ( p : & Position ) -> usize {
2020-12-05 10:24:11 +01:00
p . row * 8 + p . col
2020-12-05 09:50:09 +01:00
}
2020-12-08 14:22:12 +01:00
fn collect_ids ( s : & str ) -> BinaryHeap < usize > {
2020-12-05 14:41:54 +01:00
s . lines ( ) . map ( get_position ) . map ( | p | calculate_id ( & p ) ) . collect ( )
}
2020-12-08 14:22:12 +01:00
fn find_missing ( ids : BinaryHeap < usize > ) -> usize {
ids . into_iter_sorted ( ) . tuple_windows ( ) . find ( | ( a , b ) | a - b = = 2 ) . unwrap ( ) . 0 - 1
2020-12-05 14:41:54 +01:00
}
2020-12-05 09:50:09 +01:00
fn main ( ) {
2020-12-05 14:41:54 +01:00
let ids = collect_ids ( & read_input ( ) ) ;
2020-12-08 14:22:12 +01:00
let p1 = ids . peek ( ) . unwrap ( ) ;
2020-12-05 10:24:11 +01:00
println! ( " Part 1: {} " , p1 ) ;
2020-12-08 14:22:12 +01:00
let p2 = find_missing ( ids ) ;
2020-12-05 10:24:11 +01:00
println! ( " Part 2: {} " , p2 ) ;
2020-12-05 09:50:09 +01:00
}
fn read_input ( ) -> String {
2020-12-10 14:44:42 +01:00
read_file ( 5 )
2020-12-05 09:50:09 +01:00
}
#[ cfg(test) ]
mod tests {
use super ::* ;
use test ::black_box ;
const PASS_1 : & str = " BFFFBBFRRR " ;
const PASS_2 : & str = " FFFBBBFRRR " ;
const PASS_3 : & str = " BBFFBBFRLL " ;
const POS_1 : Position = Position { row : 70 , col : 7 } ;
const POS_2 : Position = Position { row : 14 , col : 7 } ;
const POS_3 : Position = Position { row : 102 , col : 4 } ;
const SID_1 : usize = 567 ;
const SID_2 : usize = 119 ;
const SID_3 : usize = 820 ;
#[ test ]
fn test_get_position ( ) {
assert_eq! ( get_position ( PASS_1 ) , POS_1 ) ;
assert_eq! ( get_position ( PASS_2 ) , POS_2 ) ;
assert_eq! ( get_position ( PASS_3 ) , POS_3 ) ;
}
#[ test ]
fn test_calculate_id ( ) {
assert_eq! ( calculate_id ( & POS_1 ) , SID_1 ) ;
assert_eq! ( calculate_id ( & POS_2 ) , SID_2 ) ;
assert_eq! ( calculate_id ( & POS_3 ) , SID_3 ) ;
}
2020-12-05 14:41:54 +01:00
#[ bench ]
fn bench_part_1 ( b : & mut test ::Bencher ) {
let raw = read_input ( ) ;
2020-12-08 14:22:12 +01:00
b . iter ( | | assert_eq! ( collect_ids ( black_box ( & raw ) ) . peek ( ) , Some ( & 913 ) ) )
2020-12-05 14:41:54 +01:00
}
#[ bench ]
fn bench_part_2 ( b : & mut test ::Bencher ) {
let ids = collect_ids ( & read_input ( ) ) ;
2020-12-08 14:22:12 +01:00
b . iter ( | | assert_eq! ( find_missing ( black_box ( ids . clone ( ) ) ) , 717 ) )
2020-12-05 14:41:54 +01:00
}
2020-12-05 09:50:09 +01:00
}