1use crate::util::hash::*;
9use crate::util::parse::*;
10
11pub fn parse(input: &str) -> Vec<u64> {
12 input.iter_unsigned().collect()
13}
14
15pub fn part1(input: &[u64]) -> u64 {
16 count(input, 25)
17}
18
19pub fn part2(input: &[u64]) -> u64 {
20 count(input, 75)
21}
22
23fn count(input: &[u64], blinks: usize) -> u64 {
24 let mut stones = Vec::with_capacity(5000);
26 let mut indices = FastMap::with_capacity(5000);
28 let mut todo = Vec::new();
30 let mut numbers = Vec::new();
31 let mut current = Vec::with_capacity(5000);
33 let mut next = Vec::with_capacity(5000);
34
35 for &number in input {
37 if let Some(&index) = indices.get(&number) {
38 current[index] += 1;
39 } else {
40 indices.insert(number, indices.len());
41 todo.push(number);
42 current.push(1);
43 }
44 }
45
46 for _ in 0..blinks {
47 (numbers, todo) = (todo, numbers);
50
51 let mut index_of = |number| {
52 let size = indices.len();
53 *indices.entry(number).or_insert_with(|| {
54 todo.push(number);
55 size
56 })
57 };
58
59 for number in numbers.drain(..) {
61 let (first, second) = if number == 0 {
62 (index_of(1), usize::MAX)
63 } else {
64 let digits = number.ilog10() + 1;
65 if digits.is_multiple_of(2) {
66 let power = 10_u64.pow(digits / 2);
67 (index_of(number / power), index_of(number % power))
68 } else {
69 (index_of(number * 2024), usize::MAX)
70 }
71 };
72
73 stones.push((first, second));
74 }
75
76 next.clear();
78 next.resize(indices.len(), 0);
79
80 for (&(first, second), &amount) in stones.iter().zip(¤t) {
81 next[first] += amount;
82 if second != usize::MAX {
83 next[second] += amount;
84 }
85 }
86
87 (current, next) = (next, current);
88 }
89
90 current.iter().sum()
91}