1use self::implementation::*;
24use crate::util::parse::*;
25use crate::util::thread::*;
26
27type Input = (u64, u16);
28type Result = (u64, Vec<u16>);
29
30pub fn parse(input: &str) -> Input {
31 let result = parallel(input);
32
33 let mut part_one = 0;
35 let mut part_two = vec![0; 130_321];
36
37 for (first, second) in result {
38 part_one += first;
39 part_two.iter_mut().zip(second).for_each(|(a, b)| *a += b);
40 }
41
42 (part_one, part_two.into_iter().max().unwrap())
43}
44
45pub fn part1(input: &Input) -> u64 {
46 input.0
47}
48
49pub fn part2(input: &Input) -> u16 {
50 input.1
51}
52
53#[cfg(not(feature = "simd"))]
54mod implementation {
55 use super::*;
56
57 pub(super) fn parallel(input: &str) -> Vec<Result> {
59 let numbers: Vec<_> = input.iter_unsigned().collect();
60 spawn_parallel_iterator(&numbers, worker)
61 }
62
63 fn worker(iter: ParIter<'_, u32>) -> Result {
64 let mut part_one = 0;
65 let mut part_two = vec![0; 130_321];
66 let mut seen = vec![u16::MAX; 130_321];
67
68 for (id, &number) in iter.enumerate() {
69 let id = id as u16;
70
71 let zeroth = number;
72 let first = hash(zeroth);
73 let second = hash(first);
74 let third = hash(second);
75
76 let mut a;
77 let mut b = to_index(zeroth, first);
78 let mut c = to_index(first, second);
79 let mut d = to_index(second, third);
80
81 let mut number = third;
82 let mut previous = third % 10;
83
84 for _ in 3..2000 {
85 number = hash(number);
86 let price = number % 10;
87
88 (a, b, c, d) = (b, c, d, to_index(previous, price));
90 let index = (6859 * a + 361 * b + 19 * c + d) as usize;
91 previous = price;
92
93 if seen[index] != id {
97 part_two[index] += price as u16;
98 seen[index] = id;
99 }
100 }
101
102 part_one += number as u64;
103 }
104
105 (part_one, part_two)
106 }
107
108 fn hash(mut n: u32) -> u32 {
111 n = (n ^ (n << 6)) & 0xffffff;
112 n = (n ^ (n >> 5)) & 0xffffff;
113 (n ^ (n << 11)) & 0xffffff
114 }
115
116 fn to_index(previous: u32, current: u32) -> u32 {
118 9 + current % 10 - previous % 10
119 }
120}
121
122#[cfg(feature = "simd")]
123mod implementation {
124 use std::simd::prelude::*;
125
126 use super::*;
127
128 type Vector = Simd<u32, 8>;
129
130 pub(super) fn parallel(input: &str) -> Vec<Result> {
131 let mut numbers: Vec<_> = input.iter_unsigned().collect();
132
133 numbers.resize(numbers.len().next_multiple_of(8), 0);
136 let chunks: Vec<_> = numbers.chunks_exact(8).collect();
137
138 spawn_parallel_iterator(&chunks, worker)
139 }
140
141 fn worker(iter: ParIter<'_, &[u32]>) -> Result {
145 let ten = Simd::splat(10);
146 let x = Simd::splat(6859);
147 let y = Simd::splat(361);
148 let z = Simd::splat(19);
149
150 let mut part_one = 0;
151 let mut part_two = vec![0; 130_321];
152
153 for slice in iter {
154 let mut seen = vec![u8::MAX; 130_321];
156
157 let zeroth = Simd::from_slice(slice);
158 let first = hash(zeroth);
159 let second = hash(first);
160 let third = hash(second);
161
162 let mut a;
163 let mut b = to_index(zeroth, first);
164 let mut c = to_index(first, second);
165 let mut d = to_index(second, third);
166
167 let mut number = third;
168 let mut previous = third % ten;
169
170 for _ in 3..2000 {
171 number = hash(number);
172 let prices = number % ten;
173
174 (a, b, c, d) = (b, c, d, to_index(previous, prices));
176 let indices = x * a + y * b + z * c + d;
177 previous = prices;
178
179 let indices = indices.to_array();
181 let prices = prices.to_array();
182
183 for i in 0..8 {
184 let index = indices[i] as usize;
185
186 let bit = (seen[index] >> i) & 1;
189 seen[index] &= !(1 << i);
190
191 part_two[index] += prices[i] as u16 * bit as u16;
192 }
193 }
194
195 part_one += number.reduce_sum() as u64;
196 }
197
198 (part_one, part_two)
199 }
200
201 #[inline]
204 fn hash(mut n: Vector) -> Vector {
205 let mask = Simd::splat(0xffffff);
206 n = (n ^ (n << 6)) & mask;
207 n = (n ^ (n >> 5)) & mask;
208 (n ^ (n << 11)) & mask
209 }
210
211 #[inline]
212 fn to_index(previous: Vector, current: Vector) -> Vector {
213 let nine = Simd::splat(9);
214 let ten = Simd::splat(10);
215 nine + (current % ten) - (previous % ten)
216 }
217}