1use std::collections::VecDeque;
2use utils::hash::FastMap;
3use utils::prelude::*;
4
5#[derive(Clone, Debug)]
7pub struct Day11 {
8 pub counts: Vec<u64>,
9 pub next: Vec<(usize, usize)>,
10 pub max_idx: Vec<usize>,
11}
12
13const PLACEHOLDER: u64 = u64::MAX;
15
16impl Day11 {
17 pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
18 let mut builder = Builder::new(75);
19
20 let mut counts = Vec::new();
21 for n in parser::u64().repeat(b' ', 1).parse_complete(input)? {
22 let idx = builder.index(n, 0);
23 if idx >= counts.len() {
24 counts.resize(idx + 1, 0);
25 }
26 counts[idx] += 1;
27 }
28
29 let (next, max_idx) = builder.finish();
31
32 Ok(Self {
33 counts,
34 next,
35 max_idx,
36 })
37 }
38
39 #[must_use]
40 pub fn part1(&self) -> u64 {
41 self.stones(25)
42 }
43
44 #[must_use]
45 pub fn part2(&self) -> u64 {
46 self.stones(75)
47 }
48
49 fn stones(&self, blinks: usize) -> u64 {
50 let mut counts = vec![0; self.next.len()];
51 let mut next = vec![0; self.next.len()];
52 counts[..self.counts.len()].copy_from_slice(&self.counts);
53
54 for blink in 0..blinks {
55 for (c, &(a, b)) in counts[..=self.max_idx[blink]].iter_mut().zip(&self.next) {
56 if *c > 0 {
57 next[a] += *c;
58 next[b] += *c;
59 *c = 0;
60 }
61 }
62
63 next[0] = 0;
65
66 (counts, next) = (next, counts);
67 }
68
69 counts.iter().sum()
70 }
71}
72
73struct Builder {
74 num_map: FastMap<u64, usize>,
75 next: Vec<(usize, usize)>,
76 max_idx: Vec<usize>,
77 todo: VecDeque<(u64, usize, u32)>,
78}
79
80impl Builder {
81 fn new(blinks: u32) -> Self {
82 let mut num_map = FastMap::with_capacity(5000);
83 let mut next = Vec::with_capacity(5000);
84
85 num_map.insert(PLACEHOLDER, 0);
87 next.push((0, 0));
88
89 Self {
90 num_map,
91 next,
92 todo: VecDeque::with_capacity(500),
93 max_idx: vec![0; blinks as usize],
94 }
95 }
96
97 fn index(&mut self, n: u64, blinks: u32) -> usize {
98 let next_idx = self.num_map.len();
99 *self.num_map.entry(n).or_insert_with(|| {
100 self.next.push((0, 0));
101 if (blinks as usize) < self.max_idx.len() {
102 self.max_idx[blinks as usize] = self.max_idx[blinks as usize].max(next_idx);
103 self.todo.push_back((n, next_idx, blinks));
104 }
105 next_idx
106 })
107 }
108
109 fn finish(mut self) -> (Vec<(usize, usize)>, Vec<usize>) {
110 while let Some((n, idx, blink)) = self.todo.pop_front() {
111 self.next[idx] = if n == 0 {
112 (self.index(1, blink + 1), 0)
113 } else {
114 let log = n.ilog10() + 1;
115 if log.is_multiple_of(2) {
116 let pow = 10u64.pow(log / 2);
117 (
118 self.index(n / pow, blink + 1),
119 self.index(n % pow, blink + 1),
120 )
121 } else {
122 (self.index(n * 2024, blink + 1), 0)
123 }
124 };
125 }
126
127 for i in 1..self.max_idx.len() {
132 self.max_idx[i] = self.max_idx[i].max(self.max_idx[i - 1]);
133 }
134
135 (self.next, self.max_idx)
136 }
137}
138
139examples!(Day11 -> (u64, u64) [
140 {input: "125 17", part1: 55312},
141]);