Advent of Code solutions
1use std::collections::{HashMap, HashSet};
2
3use advent_core::{day_stuff, ex_for_day, Day};
4
5pub struct Day22;
6
7fn next_secret(mut num: usize) -> usize {
8 num = ((num * 64) ^ num) % 16777216;
9 num = ((num / 32) ^ num) % 16777216;
10 num = ((num * 2048) ^ num) % 16777216;
11 num
12}
13
14fn secret_n_times(init: usize, times: usize) -> usize {
15 let mut num = init;
16 for _ in 0..times {
17 num = next_secret(num);
18 }
19 num
20}
21
22fn get_all_four_unique_changes(init: usize, times: usize) -> HashMap<[isize; 4], usize> {
23 let mut last = 0;
24 let mut changes = Vec::with_capacity(times + 1);
25 let mut curr = init;
26 for _ in 0..times {
27 curr = next_secret(curr);
28 let val = curr % 10;
29 changes.push(((val as isize) - (last as isize), val));
30 last = val;
31 }
32
33 changes
34 .windows(4)
35 .fold(HashMap::with_capacity(times / 4), |mut acc, w| {
36 let changes = [w[0].0, w[1].0, w[2].0, w[3].0];
37 let final_val = w[3].1;
38 acc.entry(changes).or_insert(final_val);
39 acc
40 })
41}
42
43impl Day for Day22 {
44 day_stuff!(22, "37327623", "23", Vec<usize>);
45
46 fn part_1(input: Self::Input) -> Option<String> {
47 let ans = input
48 .into_iter()
49 .map(|init| secret_n_times(init, 2000))
50 .sum::<usize>();
51
52 Some(ans.to_string())
53 }
54
55 fn part_2(input: Self::Input) -> Option<String> {
56 let change_to_val = input
57 .into_iter()
58 .map(|init| get_all_four_unique_changes(init, 2000))
59 .collect::<Vec<_>>();
60 let all_changes = change_to_val
61 .iter()
62 .flat_map(|h| h.keys().copied())
63 .collect::<HashSet<_>>();
64
65 let ans = all_changes
66 .into_iter()
67 .map(|c| {
68 change_to_val
69 .iter()
70 .map(|h| h.get(&c).unwrap_or(&0))
71 .sum::<usize>()
72 })
73 .max()
74 .unwrap();
75
76 Some(ans.to_string())
77 }
78
79 fn parse_input(input: &str) -> Self::Input {
80 input
81 .trim()
82 .lines()
83 .map(|l| l.parse::<usize>().unwrap())
84 .collect()
85 }
86}