2022-12-09 11:41:51 +01:00
#![ feature(test) ]
extern crate test ;
2022-12-09 12:25:09 +01:00
use fnv ::FnvHashSet as HashSet ;
2022-12-09 11:41:51 +01:00
use aoc2022 ::{ boilerplate , common ::* } ;
const DAY : usize = 9 ;
type Parsed = Vec < ( u8 , usize ) > ;
fn parse_input ( raw : & str ) -> Parsed {
raw . lines ( ) . map ( | l | ( l . as_bytes ( ) [ 0 ] , parse_num ( & l [ 2 .. ] ) ) ) . collect ( )
}
fn part1 ( parsed : & Parsed ) -> usize {
2022-12-09 12:12:03 +01:00
rope ::< 2 > ( parsed )
}
fn part2 ( parsed : & Parsed ) -> usize {
rope ::< 10 > ( parsed )
}
fn rope < const KNOTS : usize > ( parsed : & Parsed ) -> usize {
let mut knots = [ ( 0 i32 , 0 i32 ) ; KNOTS ] ;
2022-12-09 12:25:09 +01:00
let mut positions = HashSet ::default ( ) ;
positions . insert ( ( 0 , 0 ) ) ;
2022-12-09 11:41:51 +01:00
for & ( dir , n ) in parsed {
2022-12-09 13:05:41 +01:00
' outer : for _ in 0 .. n {
2022-12-09 11:41:51 +01:00
match dir {
2022-12-09 12:12:03 +01:00
b 'U' = > knots [ 0 ] . 1 + = 1 ,
b 'D' = > knots [ 0 ] . 1 - = 1 ,
b 'L' = > knots [ 0 ] . 0 - = 1 ,
b 'R' = > knots [ 0 ] . 0 + = 1 ,
2022-12-09 11:41:51 +01:00
_ = > unreachable! ( ) ,
}
2022-12-09 12:12:03 +01:00
for i in 0 .. KNOTS - 1 {
2022-12-09 13:05:41 +01:00
if let Some ( p ) = step_towards ( knots [ i + 1 ] , knots [ i ] ) {
knots [ i + 1 ] = p ;
} else {
continue 'outer ;
2022-12-09 12:12:03 +01:00
}
2022-12-09 11:41:51 +01:00
}
2022-12-09 13:05:41 +01:00
positions . insert ( knots [ KNOTS - 1 ] ) ;
2022-12-09 11:41:51 +01:00
}
}
positions . len ( )
}
2022-12-09 12:25:09 +01:00
#[ inline ]
2022-12-09 13:05:41 +01:00
fn step_towards ( tail : ( i32 , i32 ) , head : ( i32 , i32 ) ) -> Option < ( i32 , i32 ) > {
2022-12-09 11:41:51 +01:00
let xdiff = head . 0 - tail . 0 ;
let ydiff = head . 1 - tail . 1 ;
2022-12-09 12:25:09 +01:00
match ( xdiff , ydiff ) {
2022-12-09 13:05:41 +01:00
( - 1 | 0 | 1 , - 1 | 0 | 1 ) = > None ,
_ = > Some ( ( tail . 0 + xdiff . signum ( ) , tail . 1 + ydiff . signum ( ) ) ) ,
2022-12-09 11:41:51 +01:00
}
}
boilerplate! {
2022-12-09 12:50:12 +01:00
TEST_INPUT = = " \
R 4 \ n \
U 4 \ n \
L 3 \ n \
D 1 \ n \
R 4 \ n \
D 1 \ n \
L 5 \ n \
R 2 \
" ,
2022-12-09 11:41:51 +01:00
tests : {
part1 : { TEST_INPUT = > 13 } ,
2022-12-09 12:12:03 +01:00
part2 : {
TEST_INPUT = > 1 ,
2022-12-09 12:50:12 +01:00
" R 5 \n \
U 8 \ n \
L 8 \ n \
D 3 \ n \
R 17 \ n \
D 10 \ n \
L 25 \ n \
U 20 " => 36,
2022-12-09 12:12:03 +01:00
} ,
2022-12-09 11:41:51 +01:00
} ,
bench1 = = 6367 ,
2022-12-09 12:12:03 +01:00
bench2 = = 2536 ,
2022-12-09 11:41:51 +01:00
bench_parse : Vec ::len = > 2000 ,
}