2022-12-05 12:04:32 +01:00
#![ feature(test, slice_take, get_many_mut) ]
2022-12-05 10:02:52 +01:00
extern crate test ;
2022-12-05 11:35:34 +01:00
2022-12-05 10:02:52 +01:00
use aoc2022 ::{ boilerplate , common ::* } ;
const DAY : usize = 5 ;
2022-12-05 11:15:40 +01:00
type Parsed = ( Vec < Vec < u8 > > , Vec < Move > ) ;
#[ derive(Debug) ]
struct Move {
n : usize ,
src : usize ,
dst : usize ,
}
2022-12-05 10:02:52 +01:00
fn parse_input ( raw : & str ) -> Parsed {
2022-12-05 11:15:40 +01:00
let mut lines = raw . lines ( ) ;
let mut raw_stacks = Vec ::new ( ) ;
let stack_numbers = loop {
match lines . next ( ) {
Some ( line ) if line . contains ( '[' ) = > raw_stacks . push ( line ) ,
Some ( line ) = > break line ,
None = > unreachable! ( ) ,
}
} ;
let num_stacks = ( stack_numbers . trim ( ) . bytes ( ) . last ( ) . unwrap ( ) - b '0' ) as usize ;
let mut stacks = vec! [ vec! [ ] ; num_stacks ] ;
2022-12-05 11:35:34 +01:00
for & s in raw_stacks . iter ( ) . rev ( ) {
for ( n , stack ) in stacks . iter_mut ( ) . enumerate ( ) {
2022-12-05 11:15:40 +01:00
match s . as_bytes ( ) . get ( 1 + 4 * n ) {
Some ( b ' ' ) | None = > ( ) ,
2022-12-05 11:35:34 +01:00
Some ( & c ) = > stack . push ( c ) ,
2022-12-05 11:15:40 +01:00
}
}
}
let moves = lines
. skip ( 1 )
2022-12-05 11:35:34 +01:00
. map ( | l | match l . as_bytes ( ) {
[ _ , _ , _ , _ , _ , n , _ , _ , _ , _ , _ , _ , src , _ , _ , _ , _ , dst ] = > {
Move { n : ( n - b '0' ) as usize , src : ( src - b '1' ) as _ , dst : ( dst - b '1' ) as _ }
}
[ _ , _ , _ , _ , _ , n1 , n2 , _ , _ , _ , _ , _ , _ , src , _ , _ , _ , _ , dst ] = > {
Move { n : ( ( n1 - b '0' ) * 10 + n2 - b '0' ) as _ , src : ( src - b '1' ) as _ , dst : ( dst - b '1' ) as _ }
}
_ = > unreachable! ( " Operations can’t be repeated more than 99 times " ) ,
2022-12-05 11:15:40 +01:00
} )
. collect ( ) ;
( stacks , moves )
2022-12-05 10:02:52 +01:00
}
2022-12-05 12:04:32 +01:00
fn part1 ( parsed : & Parsed ) -> String {
rearrange ::< false > ( parsed )
}
fn part2 ( parsed : & Parsed ) -> String {
rearrange ::< true > ( parsed )
2022-12-05 10:02:52 +01:00
}
2022-12-05 12:04:32 +01:00
fn rearrange < const GRAB_MULTIPLE : bool > ( ( stacks , moves ) : & Parsed ) -> String {
2022-12-05 11:15:40 +01:00
let mut stacks = stacks . to_owned ( ) ;
for mov in moves {
let start_index = stacks [ mov . src ] . len ( ) - mov . n ;
2022-12-05 12:04:32 +01:00
if let Ok ( [ src , dst ] ) = stacks . get_many_mut ( [ mov . src , mov . dst ] ) {
if GRAB_MULTIPLE {
dst . extend ( src . drain ( start_index .. ) ) ;
} else {
dst . extend ( src . drain ( start_index .. ) . rev ( ) ) ;
}
2022-12-05 11:15:40 +01:00
}
}
stacks . iter ( ) . filter_map ( | s | s . last ( ) ) . map ( | & b | b as char ) . collect ( )
2022-12-05 10:02:52 +01:00
}
boilerplate! {
2022-12-05 11:15:40 +01:00
TEST_INPUT = =
" [D]
[ N ] [ C ]
[ Z ] [ M ] [ P ]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2 " ,
2022-12-05 10:02:52 +01:00
tests : {
2022-12-05 11:15:40 +01:00
part1 : { TEST_INPUT = > " CMZ " } ,
part2 : { TEST_INPUT = > " MCD " } ,
2022-12-05 10:02:52 +01:00
} ,
2022-12-05 11:15:40 +01:00
bench1 = = " QMBMJDFTD " ,
bench2 = = " NBTVTJNFJ " ,
bench_parse : check_input = > 504 ,
}
#[ cfg(test) ]
fn check_input ( ( _ , moves ) : & Parsed ) -> usize {
moves . len ( )
2022-12-05 10:02:52 +01:00
}