2021-12-02 06:13:01 +01:00
#![ feature(test) ]
extern crate test ;
use aoc2021 ::common ::* ;
2021-12-02 10:31:23 +01:00
const DAY : usize = 2 ;
type Parsed = Vec < Movement > ;
2021-12-02 06:13:01 +01:00
#[ derive(Debug, Clone, Copy) ]
enum Movement {
Up ( i64 ) ,
Down ( i64 ) ,
Forward ( i64 ) ,
}
fn parse_input ( raw : & str ) -> Parsed {
raw . lines ( )
. filter_map ( | l | l . split_once ( ' ' ) )
. map ( | ( dir , dist ) | match dir {
" up " = > Movement ::Up ( dist . parse ( ) . unwrap ( ) ) ,
" down " = > Movement ::Down ( dist . parse ( ) . unwrap ( ) ) ,
" forward " = > Movement ::Forward ( dist . parse ( ) . unwrap ( ) ) ,
_ = > unreachable! ( ) ,
} )
. collect ( )
}
fn part1 ( parsed : & Parsed ) -> i64 {
let ( depth , distance ) = parsed . iter ( ) . fold ( ( 0 , 0 ) , | ( depth , distance ) , & mov | match mov {
Movement ::Up ( x ) = > ( depth - x , distance ) ,
Movement ::Down ( x ) = > ( depth + x , distance ) ,
Movement ::Forward ( x ) = > ( depth , distance + x ) ,
} ) ;
depth * distance
}
fn part2 ( parsed : & Parsed ) -> i64 {
let ( depth , distance , _ ) = parsed . iter ( ) . fold ( ( 0 , 0 , 0 ) , | ( depth , distance , aim ) , & mov | match mov {
Movement ::Up ( x ) = > ( depth , distance , aim - x ) ,
Movement ::Down ( x ) = > ( depth , distance , aim + x ) ,
Movement ::Forward ( x ) = > ( depth + aim * x , distance + x , aim ) ,
} ) ;
depth * distance
}
fn main ( ) {
2021-12-02 10:31:23 +01:00
let input = parse_input ( & read_file ( DAY ) ) ;
2021-12-02 06:13:01 +01:00
println! ( " Part 1: {} " , part1 ( & input ) ) ;
println! ( " Part 2: {} " , part2 ( & input ) ) ;
}
#[ cfg(test) ]
mod tests {
use super ::* ;
use aoc2021 ::* ;
const TEST_INPUT : & str = " forward 5
down 5
forward 8
up 3
down 8
forward 2 " ;
test! ( part1 ( ) = = 150 ) ;
test! ( part2 ( ) = = 900 ) ;
bench! ( part1 ( ) = = 1698735 ) ;
bench! ( part2 ( ) = = 1594785890 ) ;
2021-12-03 17:05:53 +01:00
bench_input! ( Vec ::len = > 1000 ) ;
2021-12-02 06:13:01 +01:00
}