diff --git a/day11/src/main.rs b/day11/src/main.rs index 8c938e9..fd87547 100644 --- a/day11/src/main.rs +++ b/day11/src/main.rs @@ -8,13 +8,13 @@ fn main() { } fn pt1(stones: &[u128]) -> usize { - blink3(stones.to_vec(), 25) + blink2(stones, 25) } fn pt2(stones: &[u128]) -> usize { let mut total = 0; for stone in stones { - total += blink3(vec![*stone], 75); + total += b4(vec![*stone], 75); } total } @@ -56,6 +56,63 @@ fn blink2(stones: &[u128], blinks: usize) -> usize { stones.len() } +fn b4(stones: Vec<u128>, blinks: usize) -> usize { + let mut total = stones.len(); + let mut stones = VecDeque::from_iter(stones); + + for blink in 0..blinks { + let len = stones.len(); + if len > 10_000_000 { + println!("splitting; started with {blinks} blinks to go, blinked {blink} times"); + let mid = len / 2; + let stones = stones.make_contiguous().to_vec(); + let iter = &mut stones.into_iter(); + let left: Vec<_> = iter.take(mid).collect(); + let right: Vec<_> = iter.collect(); + // otherwise it gets double-counted at the start of the function in the + // recursive call + total -= left.len(); + total -= right.len(); + let blinks = blinks - blink; + total += b4(left, blinks); + total += b4(right, blinks); + break; + } else { + let mut rots = 0; + while rots < stones.len() { + let stone = stones[0]; + let digits = stone.to_string(); + + match stone { + 0 => { + stones[0] = 1; + stones.rotate_left(1); + rots += 1; + } + _ if digits.len() % 2 == 0 => { + let mid = digits.len() / 2; + let left = digits[0..mid].parse().unwrap(); + let right = digits[mid..].parse().unwrap(); + stones[0] = left; + stones.rotate_left(1); + stones.push_front(right); + stones.rotate_left(1); + rots += 2; + total += 1; + } + _ => { + stones[0] = stone * 2024; + stones.rotate_left(1); + rots += 1; + } + } + } + stones.rotate_right(rots); + } + } + total +} + fn blink3(mut stones: Vec<u128>, blinks: usize) -> usize { let mut total = stones.len(); for blink in 0..blinks { @@ -106,6 +163,6 @@ mod test { #[test] fn p2() { let stones = parse("125 17"); - assert_eq!(55312, blink3(stones, 25)); + assert_eq!(55312, b4(stones, 25)); } }