-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday11.rs
105 lines (87 loc) · 2.79 KB
/
day11.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! [Day 11: Plutonian Pebbles](https://adventofcode.com/2024/day/11)
use rustc_hash::FxHashMap;
struct Puzzle {
stones: Vec<u64>,
}
impl Puzzle {
const fn new() -> Self {
Self { stones: Vec::new() }
}
/// Get the puzzle input.
fn configure(&mut self, data: &str) {
self.stones = data
.split_ascii_whitespace()
.filter_map(|s| s.parse().ok())
.collect();
}
/// Blink all stone within the frequency map according to the blink process:
/// - stone 0 becomes stone 1
/// - stone with a even length number splits into two
/// - otherwise stone number is multiplied by 2024
fn blink(stone_counts: &FxHashMap<u64, u64>) -> FxHashMap<u64, u64> {
let mut new_counts = FxHashMap::default();
for (&stone, &count) in stone_counts {
let new_stones = {
// engraved with the number 0 => 1
if stone == 0 {
vec![1]
} else {
let s = stone.to_string();
let len = s.len();
if len % 2 == 0 {
// engraved with a number that has an even number of digits => split it into two stones
let mid = len / 2;
let left = s[0..mid].parse::<u64>().unwrap();
let right = s[mid..].parse::<u64>().unwrap();
vec![left, right]
} else {
// otherwise, multiply by 2024
vec![stone * 2024]
}
}
};
for new_stone in new_stones {
*new_counts.entry(new_stone).or_insert(0) += count;
}
}
new_counts
}
/// Blink `blinks` times and returns the total number of stones.
fn solve(&self, blinks: usize) -> u64 {
let mut stone_counts = FxHashMap::default();
for &stone in &self.stones {
*stone_counts.entry(stone).or_insert(0) += 1;
}
for _ in 0..blinks {
stone_counts = Self::blink(&stone_counts);
}
stone_counts.values().sum()
}
/// Solve part one.
fn part1(&self) -> u64 {
self.solve(25)
}
/// Solve part two.
fn part2(&self) -> u64 {
self.solve(75)
}
}
fn main() {
let args = aoc::parse_args();
let mut puzzle = Puzzle::new();
puzzle.configure(&args.input);
println!("{}", puzzle.part1());
println!("{}", puzzle.part2());
}
/// Test from puzzle input
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test01() {
let mut puzzle = Puzzle::new();
let data = aoc::load_input_data("test.txt");
puzzle.configure(&data);
assert_eq!(puzzle.part1(), 55312);
}
}