Skip to content

Commit 688652f

Browse files
committed
Day 22 solutions
1 parent d1ff216 commit 688652f

File tree

5 files changed

+1917
-4
lines changed

5 files changed

+1917
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,4 @@ This should start the server at `localhost:8080`.
107107
❄️ [Day 19](aoc-solver/src/y2024/day19.rs)
108108
❄️ [Day 20](aoc-solver/src/y2024/day20.rs)
109109
❄️ [Day 21](aoc-solver/src/y2024/day21.rs)
110+
❄️ [Day 22](aoc-solver/src/y2024/day22.rs)

aoc-solver/src/y2024/day22.rs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
use std::collections::HashMap;
2+
3+
use itertools::Itertools;
4+
5+
use crate::solution::{AocError, Solution};
6+
7+
fn parse(input: &str) -> Result<Vec<u64>, AocError> {
8+
input
9+
.lines()
10+
.map(|row| row.parse::<u64>().map_err(|err| AocError::parse(row, err)))
11+
.try_collect()
12+
}
13+
14+
fn evolve(mut secret: u64) -> u64 {
15+
// Calculate the result of multiplying the secret number by 64.
16+
// Then, mix this result into the secret number.
17+
// Finally, prune the secret number.
18+
secret ^= secret * 64;
19+
secret %= 16777216;
20+
21+
// Calculate the result of dividing the secret number by 32.
22+
// Then, mix this result into the secret number.
23+
// Finally, prune the secret number.
24+
secret ^= secret / 32;
25+
secret %= 16777216;
26+
27+
// Calculate the result of multiplying the secret number by 2048.
28+
// Then, mix this result into the secret number.
29+
// Finally, prune the secret number.
30+
secret ^= secret * 2048;
31+
secret %= 16777216;
32+
33+
secret
34+
}
35+
36+
pub struct Day22;
37+
impl Solution for Day22 {
38+
type A = u64;
39+
type B = u64;
40+
41+
fn default_input(&self) -> &'static str {
42+
include_str!("../../../inputs/2024/day22.txt")
43+
}
44+
45+
fn part_1(&self, input: &str) -> Result<u64, AocError> {
46+
let secrets = parse(input)?;
47+
48+
let sum = secrets
49+
.into_iter()
50+
.map(|initial_secret| (0..2000).fold(initial_secret, |secret, _| evolve(secret)))
51+
.sum();
52+
53+
Ok(sum)
54+
}
55+
56+
fn part_2(&self, input: &str) -> Result<u64, AocError> {
57+
let secrets = parse(input)?;
58+
59+
let every_buyer_sequences = secrets
60+
.into_iter()
61+
.map(|mut secret| {
62+
let mut prices = Vec::new();
63+
let mut diffs = Vec::new();
64+
65+
for _ in 1..2000 {
66+
let prev_price = secret % 10;
67+
secret = evolve(secret);
68+
let price = secret % 10;
69+
70+
prices.push(price);
71+
diffs.push(price as i64 - prev_price as i64);
72+
}
73+
74+
let price_by_sequence = diffs.windows(4).enumerate().fold(
75+
HashMap::new(),
76+
|mut sequences, (i, window)| {
77+
sequences.entry(window.to_vec()).or_insert(prices[i + 3]);
78+
sequences
79+
},
80+
);
81+
82+
price_by_sequence
83+
})
84+
.collect::<Vec<_>>();
85+
86+
let mut bananas_by_sequence: HashMap<Vec<i64>, u64> = HashMap::new();
87+
88+
for sequences in every_buyer_sequences {
89+
for (sequence, price) in sequences.into_iter() {
90+
*bananas_by_sequence.entry(sequence).or_insert(0) += price;
91+
}
92+
}
93+
94+
let most_bananas = bananas_by_sequence
95+
.into_values()
96+
.max()
97+
.ok_or_else(|| AocError::logic("No bananas?"))?;
98+
99+
Ok(most_bananas)
100+
}
101+
}
102+
103+
#[cfg(test)]
104+
mod tests {
105+
use super::*;
106+
107+
#[test]
108+
fn it_solves_part1_example() {
109+
assert_eq!(
110+
Day22.part_1(
111+
"1\n\
112+
10\n\
113+
100\n\
114+
2024"
115+
),
116+
Ok(37327623)
117+
);
118+
}
119+
120+
#[test]
121+
fn it_solves_part2_example() {
122+
assert_eq!(
123+
Day22.part_2(
124+
"1\n\
125+
2\n\
126+
3\n\
127+
2024"
128+
),
129+
Ok(23)
130+
);
131+
}
132+
133+
#[test]
134+
fn it_evolves_correctly() {
135+
assert_eq!(evolve(123), 15887950);
136+
}
137+
}

aoc-solver/src/y2024/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ pub mod day18;
2121
pub mod day19;
2222
pub mod day20;
2323
pub mod day21;
24-
// pub mod day22;
24+
pub mod day22;
2525
// pub mod day23;
2626
// pub mod day24;
2727
// pub mod day25;
2828

29-
pub const MAX_DAYS: u8 = 21;
29+
pub const MAX_DAYS: u8 = 22;
3030

3131
pub struct Y2024;
3232

@@ -54,7 +54,7 @@ impl Solver for Y2024 {
5454
19 => day19::Day19.run(input, 19, 2024),
5555
20 => day20::Day20.run(input, 20, 2024),
5656
21 => day21::Day21.run(input, 21, 2024),
57-
// 22 => day22::Day22.run(input, 22, 2024),
57+
22 => day22::Day22.run(input, 22, 2024),
5858
// 23 => day23::Day23.run(input, 23, 2024),
5959
// 24 => day24::Day24.run(input, 24, 2024),
6060
// 25 => day25::Day25.run(input, 25, 2024),
@@ -96,7 +96,7 @@ impl Solver for Y2024 {
9696
19 => include_str!("./day19.rs"),
9797
20 => include_str!("./day20.rs"),
9898
21 => include_str!("./day21.rs"),
99-
// 22 => include_str!("./day22.rs"),
99+
22 => include_str!("./day22.rs"),
100100
// 23 => include_str!("./day23.rs"),
101101
// 24 => include_str!("./day24.rs"),
102102
// 25 => include_str!("./day25.rs"),

aoc-web/src/header.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub fn header(props: &HeaderProps) -> Html {
4242
<NavLink route={Route::Solution { year: 2024, day: 19 }} current={props.route.clone()} text={"19"}/>
4343
<NavLink route={Route::Solution { year: 2024, day: 20 }} current={props.route.clone()} text={"20"}/>
4444
<NavLink route={Route::Solution { year: 2024, day: 21 }} current={props.route.clone()} text={"21"}/>
45+
<NavLink route={Route::Solution { year: 2024, day: 22 }} current={props.route.clone()} text={"22"}/>
4546
</>
4647
}
4748
},

0 commit comments

Comments
 (0)