1use crate::util::hash::*;
15use crate::util::parse::*;
16
17const THRESHOLD: usize = 1_000_000;
18
19pub fn parse(input: &str) -> Vec<usize> {
20 input.iter_unsigned().collect()
21}
22
23pub fn part1(input: &[usize]) -> usize {
24 play(input, 2020)
25}
26
27pub fn part2(input: &[usize]) -> usize {
28 play(input, 30_000_000)
29}
30
31fn play(input: &[usize], rounds: usize) -> usize {
32 let size = input.len() - 1;
33 let mut last = input[size];
34
35 let mut spoken_low = vec![0; rounds.min(THRESHOLD)];
36 let mut spoken_high = FastMap::with_capacity(rounds / 5);
37
38 for i in 0..size {
39 spoken_low[input[i]] = (i + 1) as u32;
40 }
41
42 for i in input.len()..rounds {
43 if last < THRESHOLD {
44 let previous = spoken_low[last] as usize;
45 spoken_low[last] = i as u32;
46 last = if previous == 0 { 0 } else { i - previous };
47 } else {
48 spoken_high
49 .entry(last as u32)
50 .and_modify(|previous| {
51 last = i - *previous as usize;
52 *previous = i as u32;
53 })
54 .or_insert_with(|| {
55 last = 0;
56 i as u32
57 });
58 }
59 }
60
61 last
62}