Skip to content

Commit eb79323

Browse files
committed
2024: Add solution to Day 11
1 parent 70ac675 commit eb79323

File tree

6 files changed

+83
-19
lines changed

6 files changed

+83
-19
lines changed

2024/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ cargo run --bin day01
2020
8. [Resonant Collinearity](day08) 🌟🌟
2121
9. [Disk Fragmenter](day09) 🌟🌟
2222
10. [Hoof It](day10) 🌟🌟
23-
11. [](day11)
23+
11. [Plutonian Pebbles](day11) 🌟🌟
2424
12. [](day12)
2525
13. [](day13)
2626
14. [](day14)

2024/day11/example1.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0 1 10 99 999

2024/day11/example2.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
125 17

2024/day11/input.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2 54 992917 5270417 2514 28561 0 990

2024/day11/src/main.rs

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
//! https://adventofcode.com/2024/day/11
33
44
use std::{fs, io};
5+
use std::collections::BTreeMap;
56
use std::path::Path;
67

78
fn main() {
89
let input = Input::from_file(format!("{}/input.txt", env!("CARGO_MANIFEST_DIR"))).expect("failed to read input");
9-
//let input = Input::from_file(format!("{}/example1.txt", env!("CARGO_MANIFEST_DIR"))).expect("failed to read input");
10-
println!("{input:?}");
10+
//let input = Input::from_file(format!("{}/example2.txt", env!("CARGO_MANIFEST_DIR"))).expect("failed to read input");
11+
//println!("{input:?}");
1112

1213
// Part 1
1314
println!("Part 1: {}", part1(&input));
@@ -16,23 +17,90 @@ fn main() {
1617
println!("Part 2: {}", part2(&input));
1718
}
1819

20+
fn digits(n: usize) -> usize {
21+
if n == 0 {
22+
return 1;
23+
}
24+
25+
(n.ilog10() + 1) as usize
26+
}
27+
1928
fn part1(input: &Input) -> usize {
20-
0
29+
// `slow` and `fast` give identical results.
30+
slow(&input.values, 25)
2131
}
2232

2333
fn part2(input: &Input) -> usize {
24-
0
34+
// `slow` and `fast` give identical results, but `slow` will never complete.
35+
fast(&input.values, 75)
36+
}
37+
38+
fn slow(stones: &[usize], n: usize) -> usize {
39+
let mut stones = stones.iter().copied().collect();
40+
41+
for _ in 0..n {
42+
let mut new_stones = Vec::new();
43+
44+
for stone in stones {
45+
let digits = digits(stone);
46+
match stone {
47+
0 => { new_stones.push(1); },
48+
x if digits % 2 == 0 => {
49+
let factor = 10usize.pow(digits as u32 / 2);
50+
new_stones.push(x / factor);
51+
new_stones.push(x % factor);
52+
},
53+
x => { new_stones.push(x * 2024); }
54+
}
55+
}
56+
57+
stones = new_stones;
58+
}
59+
60+
stones.len()
61+
}
62+
63+
fn fast(stones: &[usize], n: usize) -> usize {
64+
let mut counts: BTreeMap<usize, usize> = BTreeMap::new();
65+
for value in stones.iter().copied() {
66+
*counts.entry(value).or_default() += 1;
67+
}
68+
69+
for _ in 0..n {
70+
let mut new_counts = BTreeMap::new();
71+
72+
for (stone, n) in counts {
73+
let digits = digits(stone);
74+
match stone {
75+
0 => {
76+
*new_counts.entry(1).or_default() += n;
77+
},
78+
x if digits % 2 == 0 => {
79+
let factor = 10usize.pow(digits as u32 / 2);
80+
*new_counts.entry(x / factor).or_default() += n;
81+
*new_counts.entry(x % factor).or_default() += n;
82+
},
83+
x => {
84+
*new_counts.entry(x * 2024).or_default() += n;
85+
}
86+
}
87+
}
88+
89+
counts = new_counts
90+
}
91+
92+
counts.values().sum()
2593
}
2694

2795
#[derive(Debug, Clone)]
2896
struct Input {
29-
values: Vec<String>,
97+
values: Vec<usize>,
3098
}
3199

32100
impl Input {
33101
fn from_file(path: impl AsRef<Path>) -> io::Result<Self> {
34102
let input = fs::read_to_string(path)?;
35-
let values = input.lines().map(str::to_string).collect();
103+
let values = input.trim().split_ascii_whitespace().map(|s| s.parse().unwrap()).collect();
36104

37105
Ok(Self { values })
38106
}
@@ -44,29 +112,22 @@ mod test {
44112

45113
#[test]
46114
fn test_part1() {
47-
let input = Input::from_file("example1.txt").unwrap();
115+
let input = Input::from_file("example2.txt").unwrap();
48116

49-
assert_eq!(part1(&input), 0);
117+
assert_eq!(part1(&input), 55312);
50118
}
51119

52120
#[test]
53121
fn test_part1_solution() {
54122
let input = Input::from_file("input.txt").unwrap();
55123

56-
assert_eq!(part1(&input), 0);
57-
}
58-
59-
#[test]
60-
fn test_part2() {
61-
let input = Input::from_file("example1.txt").unwrap();
62-
63-
assert_eq!(part2(&input), 0);
124+
assert_eq!(part1(&input), 222461);
64125
}
65126

66127
#[test]
67128
fn test_part2_solution() {
68129
let input = Input::from_file("input.txt").unwrap();
69130

70-
assert_eq!(part2(&input), 0);
131+
assert_eq!(part2(&input), 264350935776416);
71132
}
72133
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ These are mostly written in [Rust](https://www.rust-lang.org/).
77
I can also be found on BlueSky: [@dcoles.net](https://bsky.app/profile/dcoles.net)
88

99
## Solutions
10-
- [Advent of Code 2024](2024#readme): 20🌟
10+
- [Advent of Code 2024](2024#readme): 22🌟
1111
- [Advent of Code 2023](2023#readme): 45🌟
1212
- [Advent of Code 2022](2022#readme): 50🌟!
1313
- [Advent of Code 2021](2021#readme): 50🌟!

0 commit comments

Comments
 (0)