2022-12-20 22:14:25 +01:00
#![ feature(test) ]
extern crate test ;
use aoc2022 ::{ boilerplate , common ::* } ;
2022-12-20 22:52:25 +01:00
use std ::{
collections ::VecDeque ,
iter ::{ repeat , repeat_with } ,
} ;
2022-12-20 22:14:25 +01:00
const DAY : usize = 20 ;
2022-12-20 22:39:21 +01:00
type Parsed = Vec < isize > ;
2022-12-20 22:14:25 +01:00
fn parse_input ( raw : & str ) -> Parsed {
2022-12-20 22:39:21 +01:00
raw . lines ( ) . map ( | l | l . parse ( ) . unwrap ( ) ) . collect ( )
2022-12-20 22:14:25 +01:00
}
fn part1 ( parsed : & Parsed ) -> isize {
2022-12-20 22:52:25 +01:00
let mut xs : VecDeque < _ > = repeat ( false ) . zip ( parsed . iter ( ) . copied ( ) ) . collect ( ) ;
2022-12-20 22:14:25 +01:00
let mut moved = 0 ;
while moved < parsed . len ( ) {
let x = xs . pop_front ( ) . unwrap ( ) ;
2022-12-20 22:52:25 +01:00
if x . 0 {
// already processed, just put it in the back
2022-12-20 22:14:25 +01:00
xs . push_back ( x ) ;
} else {
2022-12-20 22:52:25 +01:00
// casting :notLikeMiya:
xs . insert ( ( ( x . 1 + ( xs . len ( ) * 2 ) as isize ) % xs . len ( ) as isize ) as usize , ( true , x . 1 ) ) ;
2022-12-20 22:14:25 +01:00
moved + = 1 ;
}
}
2022-12-20 22:52:25 +01:00
get_coords ( & mut xs )
2022-12-20 22:14:25 +01:00
}
2022-12-20 22:39:21 +01:00
const DECRYPTION_KEY : isize = 811589153 ;
fn part2 ( parsed : & Parsed ) -> isize {
let mut xs : VecDeque < _ > = parsed . iter ( ) . enumerate ( ) . map ( | ( p , x ) | ( p , x * DECRYPTION_KEY ) ) . collect ( ) ;
2022-12-20 22:52:25 +01:00
// Effective length is reduced by one because the element that’s being moved is no longer in the collection.
let len = xs . len ( ) as isize - 1 ;
// Add this to each element to make it guaranteed positive before modulo-ing for the index.
let make_positive = len * 2 * DECRYPTION_KEY ;
for _ in 0 .. 10 {
for current in 0 .. parsed . len ( ) {
let i = xs . iter ( ) . position ( | ( x , _ ) | x = = & current ) . unwrap ( ) ;
2022-12-20 22:39:21 +01:00
xs . rotate_left ( i ) ;
let x = xs . pop_front ( ) . unwrap ( ) ;
2022-12-20 22:52:25 +01:00
xs . insert ( ( ( x . 1 + make_positive ) % len ) as usize , x ) ;
2022-12-20 22:39:21 +01:00
}
}
2022-12-20 22:52:25 +01:00
get_coords ( & mut xs )
}
fn get_coords < T > ( xs : & mut VecDeque < ( T , isize ) > ) -> isize {
xs . rotate_left ( xs . iter ( ) . position ( | ( _ , x ) | x = = & 0 ) . unwrap ( ) ) ;
repeat_with ( | | {
xs . rotate_left ( 1000 % xs . len ( ) ) ;
xs . front ( ) . unwrap ( ) . 1
} )
. take ( 3 )
. sum ( )
2022-12-20 22:14:25 +01:00
}
boilerplate! {
TEST_INPUT = = " 1
2
- 3
3
- 2
0
4 " ,
tests : {
part1 : { TEST_INPUT = > 3 } ,
2022-12-20 22:39:21 +01:00
part2 : { TEST_INPUT = > 1623178306 } ,
2022-12-20 22:14:25 +01:00
} ,
bench1 = = 23321 ,
2022-12-20 22:39:21 +01:00
bench2 = = 1428396909280 ,
bench_parse : Vec ::len = > 5000 ,
2022-12-20 22:14:25 +01:00
}