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));
     }
 }