diff --git a/Cargo.lock b/Cargo.lock
index ee53bf0..185b8ef 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -60,6 +60,10 @@ version = "0.1.0"
 name = "day10"
 version = "0.1.0"
 
+[[package]]
+name = "day11"
+version = "0.1.0"
+
 [[package]]
 name = "memchr"
 version = "2.7.4"
diff --git a/Cargo.toml b/Cargo.toml
index 5785a84..834a35e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [workspace]
 resolver = "2"
-members = ["day01", "day02", "day03", "day04", "day05", "day06", "day07", "day08", "day09", "day10"]
+members = ["day01", "day02", "day03", "day04", "day05", "day06", "day07", "day08", "day09", "day10", "day11"]
 
 [workspace.dependencies]
 winnow = "0.6"
diff --git a/day11/Cargo.toml b/day11/Cargo.toml
new file mode 100644
index 0000000..864e412
--- /dev/null
+++ b/day11/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "day11"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
diff --git a/day11/src/main.rs b/day11/src/main.rs
new file mode 100644
index 0000000..5f19ef4
--- /dev/null
+++ b/day11/src/main.rs
@@ -0,0 +1,82 @@
+use std::collections::VecDeque;
+
+fn main() {
+    let input = std::fs::read_to_string("input").unwrap();
+    let stones = parse(&input);
+    println!("{}", pt1(&stones));
+    println!("{}", pt2(&stones));
+}
+
+fn pt1(stones: &[u128]) -> usize {
+    blink2(stones, 25)
+}
+
+fn pt2(stones: &[u128]) -> usize {
+    let mut total = 0;
+    for stone in stones {
+        total += blink2(&[*stone], 75);
+    }
+    total
+}
+
+fn blink2(stones: &[u128], blinks: usize) -> usize {
+    let mut stones = VecDeque::from_iter(stones.iter().copied());
+
+    for _blink in 0..blinks {
+        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;
+                }
+                _ => {
+                    stones[0] = stone * 2024;
+                    stones.rotate_left(1);
+                    rots += 1;
+                }
+            }
+        }
+        stones.rotate_right(rots);
+    }
+    stones.len()
+}
+
+fn parse(input: &str) -> Vec<u128> {
+    input
+        .trim()
+        .split(' ')
+        .map(|v| v.parse().unwrap())
+        .collect()
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn p1() {
+        let stones = parse("125 17");
+        assert_eq!(55312, pt1(&stones));
+    }
+
+    #[test]
+    fn p2() {
+        let stones = parse("125 17");
+        assert_eq!(22, blink2(&stones, 6));
+    }
+}