2020-12-12 14:31:40 +01:00
#![ feature(test) ]
extern crate test ;
use aoc2020 ::{ common ::* , grid ::* } ;
type Parsed = Vec < ( char , i64 ) > ;
fn read_input ( ) -> String {
read_file ( 12 )
}
fn parse_input ( raw : & str ) -> Parsed {
raw . lines ( )
. map ( | l | ( l . bytes ( ) . next ( ) . unwrap ( ) as char , l [ 1 .. ] . parse ( ) . unwrap ( ) ) )
. collect ( )
}
fn part1 ( parsed : & Parsed ) -> i64 {
let end_pos = parsed
. iter ( )
. fold ( ( Direction ::Right , Position2D { x : 0 , y : 0 } ) , | ( dir , pos ) , ( cmd , dist ) | match cmd {
'N' = > ( dir , pos + Position2D ::from ( ( 0 , * dist ) ) ) ,
'S' = > ( dir , pos - Position2D ::from ( ( 0 , * dist ) ) ) ,
'E' = > ( dir , pos + Position2D ::from ( ( * dist , 0 ) ) ) ,
'W' = > ( dir , pos - Position2D ::from ( ( * dist , 0 ) ) ) ,
'R' = > ( dir + ( dist / 90 ) as i8 , pos ) ,
'L' = > ( dir + - ( dist / 90 ) as i8 , pos ) ,
'F' = > ( dir , pos + Position2D ::from ( dir ) * * dist ) ,
_ = > unreachable! ( ) ,
} )
. 1 ;
end_pos . x . abs ( ) + end_pos . y . abs ( )
}
fn rotate_waypoint ( mut wp : Position2D , deg : i64 ) -> Position2D {
2020-12-13 12:26:59 +01:00
for _ in 0 .. ( ( deg / 90 + 4 ) & 3 ) {
2020-12-12 14:31:40 +01:00
wp = Position2D { x : wp . y , y : - wp . x } ;
}
wp
}
fn part2 ( parsed : & Parsed ) -> i64 {
let end_pos = parsed
. iter ( )
. fold (
( Position2D { x : 10 , y : 1 } , Position2D { x : 0 , y : 0 } ) ,
| ( wp , pos ) , ( cmd , dist ) | match cmd {
'N' = > ( wp + Position2D ::from ( ( 0 , * dist ) ) , pos ) ,
'S' = > ( wp - Position2D ::from ( ( 0 , * dist ) ) , pos ) ,
'E' = > ( wp + Position2D ::from ( ( * dist , 0 ) ) , pos ) ,
'W' = > ( wp - Position2D ::from ( ( * dist , 0 ) ) , pos ) ,
'R' = > ( rotate_waypoint ( wp , * dist ) , pos ) ,
'L' = > ( rotate_waypoint ( wp , - dist ) , pos ) ,
'F' = > ( wp , pos + wp * * dist ) ,
_ = > unreachable! ( ) ,
} ,
)
. 1 ;
end_pos . x . abs ( ) + end_pos . y . abs ( )
}
fn main ( ) {
let input = parse_input ( & read_input ( ) ) ;
println! ( " Part 1: {} " , part1 ( & input ) ) ;
println! ( " Part 2: {} " , part2 ( & input ) ) ;
}
#[ cfg(test) ]
mod tests {
use super ::* ;
use aoc2020 ::* ;
use paste ::paste ;
use test ::black_box ;
const TEST_INPUT : & str = " F10
N3
F7
R90
F11 " ;
test! ( part1 ( ) = = 25 ) ;
test! ( part2 ( ) = = 286 ) ;
bench! ( part1 ( ) = = 1838 ) ;
bench! ( part2 ( ) = = 89936 ) ;
bench_input! ( len = = 786 ) ;
}