Skip to content

Commit 9ca42ee

Browse files
committed
Day 22
1 parent a1d3e0a commit 9ca42ee

File tree

5 files changed

+178
-1
lines changed

5 files changed

+178
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
3232
| [Day 19](./src/bin/19.rs) | `204.0µs` | `693.5µs` |
3333
| [Day 20](./src/bin/20.rs) | `308.3µs` | `1.8ms` |
3434
| [Day 21](./src/bin/21.rs) | `10.9µs` | `112.6µs` |
35+
| [Day 22](./src/bin/22.rs) | `610.4µs` | `9.0s` |
3536

36-
**Total: 16.69ms**
37+
**Total: 9017.30ms**
3738
<!--- benchmarking table --->
3839

3940
---

data/examples/22-1.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
1
2+
10
3+
100
4+
2024

data/examples/22-2.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
123

data/examples/22-3.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
1
2+
2
3+
3
4+
2024

src/bin/22.rs

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
use memoize::memoize;
2+
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
3+
4+
advent_of_code::solution!(22);
5+
6+
type Secret = u32;
7+
8+
// println!("{:#032b}", 16777216);
9+
// println!("{:#032b}", 0b000001000000000000000000000000);
10+
// println!("{:#032b}", (1 << 24) - 1);
11+
// println!("{:#032b}", 2048); -> 2**11
12+
const MASK: Secret = (1 << 24) - 1;
13+
14+
#[inline]
15+
fn next_secret(n: Secret) -> Secret {
16+
let n = (n ^ n << 6) & MASK;
17+
let n = (n ^ n >> 5) & MASK;
18+
let n = (n ^ n << 11) & MASK;
19+
n
20+
}
21+
22+
#[inline]
23+
fn get_secret(s: Secret, nth: usize) -> Secret {
24+
let mut secret = s;
25+
for _ in 0..nth {
26+
secret = next_secret(secret)
27+
}
28+
secret
29+
}
30+
31+
#[inline]
32+
fn parse_input<'a>(input: &'a str) -> impl Iterator<Item = Secret> + 'a {
33+
input
34+
.lines()
35+
.filter(|&l| !l.is_empty())
36+
.map(|l| l.parse::<Secret>().unwrap())
37+
}
38+
39+
#[memoize]
40+
fn gen_all_seq() -> Vec<u32> {
41+
(-9..9)
42+
.flat_map(|a| {
43+
(-9..9).flat_map(move |b| {
44+
(-9..9).flat_map(move |c| {
45+
(-9..9).map(move |d| {
46+
(diff_to_seq_part(a) << 24)
47+
| (diff_to_seq_part(b) << 16)
48+
| (diff_to_seq_part(c) << 8)
49+
| diff_to_seq_part(d)
50+
})
51+
})
52+
})
53+
})
54+
.collect()
55+
}
56+
57+
pub fn part_one(input: &str) -> Option<u64> {
58+
let seeds = parse_input(input).collect::<Vec<_>>();
59+
let res = seeds
60+
.par_iter()
61+
.map(|&s| get_secret(s, 2000))
62+
.map(|s| s as u64)
63+
.sum();
64+
Some(res)
65+
}
66+
67+
type Seq = u32;
68+
type SeqDiff = i8;
69+
70+
#[inline]
71+
fn diff_to_seq_part(diff: SeqDiff) -> Seq {
72+
(diff as Seq) & 0xFF
73+
}
74+
75+
#[inline]
76+
fn push_seq(seq: Seq, diff: SeqDiff) -> u32 {
77+
// we are working mod 10 so + 10 is fine
78+
(seq << 8) | diff_to_seq_part(diff)
79+
}
80+
81+
pub fn part_two(input: &str) -> Option<i32> {
82+
let seeds = parse_input(input).collect::<Vec<_>>();
83+
let seeds_prices = seeds
84+
.par_iter()
85+
.map(|seed| {
86+
let mut prices = [(0_i8, 0_u32); 2000];
87+
88+
let mut prev_price = 0;
89+
let mut secret = *seed;
90+
let mut seq = 0;
91+
for i in 0..2000 {
92+
secret = next_secret(secret);
93+
let new_price = (secret % 10) as i8;
94+
seq = push_seq(seq, new_price - prev_price);
95+
prices[i] = (new_price, seq);
96+
prev_price = new_price;
97+
}
98+
prices
99+
})
100+
.collect::<Vec<_>>();
101+
102+
let seq_to_test = gen_all_seq();
103+
104+
let max_bananas = seq_to_test
105+
.par_iter()
106+
.map(|&target_seq| {
107+
let bananas = seeds_prices
108+
.iter()
109+
.map(|&seed_data| {
110+
let bananas = seed_data
111+
.iter()
112+
.skip(4)
113+
.find(|&(_, seq)| *seq == target_seq)
114+
.map(|(p, _)| *p)
115+
.unwrap_or(0);
116+
117+
bananas as i32
118+
})
119+
.sum();
120+
121+
bananas
122+
})
123+
.max();
124+
125+
Some(max_bananas.unwrap())
126+
}
127+
128+
#[cfg(test)]
129+
mod tests {
130+
use super::*;
131+
#[test]
132+
fn test_next_secrets() {
133+
let seed = 123;
134+
135+
[
136+
15887950, 16495136, 527345, 704524, 1553684, 12683156, 11100544, 12249484, 7753432,
137+
5908254,
138+
]
139+
.iter()
140+
.enumerate()
141+
.for_each(|(i, &expected)| assert_eq!(get_secret(seed, i + 1), expected));
142+
}
143+
144+
#[test]
145+
fn test_part_one() {
146+
let result = part_one(&advent_of_code::template::read_file_part(
147+
"examples", DAY, 1,
148+
));
149+
assert_eq!(result, Some(37327623));
150+
}
151+
152+
#[test]
153+
fn test_part_two_0() {
154+
let result = part_two(&advent_of_code::template::read_file_part(
155+
"examples", DAY, 2,
156+
));
157+
assert_eq!(result, Some(9));
158+
}
159+
160+
#[test]
161+
fn test_part_two_1() {
162+
let result = part_two(&advent_of_code::template::read_file_part(
163+
"examples", DAY, 3,
164+
));
165+
assert_eq!(result, Some(23));
166+
}
167+
}

0 commit comments

Comments
 (0)