Skip to content

Commit cc04148

Browse files
committed
Day 17
1 parent 564bcba commit cc04148

File tree

4 files changed

+279
-2
lines changed

4 files changed

+279
-2
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,17 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
1919
| [Day 6](./src/bin/06.rs) | `48.5µs` | `4.2ms` |
2020
| [Day 7](./src/bin/07.rs) | `316.2µs` | `319.6µs` |
2121
| [Day 8](./src/bin/08.rs) | `7.4µs` | `15.5µs` |
22-
| [Day 9](./src/bin/09.rs) | `152.3µs` | `141.1µs` |
22+
| [Day 9](./src/bin/09.rs) | `154.1µs` | `147.3µs` |
2323
| [Day 10](./src/bin/10.rs) | `31.1µs` | `28.6µs` |
2424
| [Day 11](./src/bin/11.rs) | `71.0µs` | `766.0µs` |
2525
| [Day 12](./src/bin/12.rs) | `434.7µs` | `674.6µs` |
2626
| [Day 13](./src/bin/13.rs) | `90.9µs` | `91.8µs` |
2727
| [Day 14](./src/bin/14.rs) | `30.8µs` | `3.5ms` |
2828
| [Day 15](./src/bin/15.rs) | `119.7µs` | `591.0µs` |
2929
| [Day 16](./src/bin/16.rs) | `158.9µs` | `202.6µs` |
30+
| [Day 17](./src/bin/17.rs) | `1.7µs` | `361.3µs` |
3031

31-
**Total: 13.08ms**
32+
**Total: 13.45ms**
3233
<!--- benchmarking table --->
3334

3435
---

data/examples/17-1.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Register A: 729
2+
Register B: 0
3+
Register C: 0
4+
5+
Program: 0,1,5,4,3,0

data/examples/17-2.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Register A: 2024
2+
Register B: 0
3+
Register C: 0
4+
5+
Program: 0,3,5,4,3,0

src/bin/17.rs

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
advent_of_code::solution!(17);
2+
3+
#[derive(Debug, Clone)]
4+
struct Machine {
5+
reg_a: u64,
6+
reg_b: u64,
7+
reg_c: u64,
8+
9+
ip: usize, // idx into tape
10+
tape: Vec<u64>,
11+
output: Vec<u64>,
12+
}
13+
14+
impl Machine {
15+
fn parse(input: &str) -> Self {
16+
let lines = input.lines().collect::<Vec<_>>();
17+
18+
Self {
19+
reg_a: lines[0].split_whitespace().nth(2).unwrap().parse().unwrap(),
20+
reg_b: lines[1].split_whitespace().nth(2).unwrap().parse().unwrap(),
21+
reg_c: lines[2].split_whitespace().nth(2).unwrap().parse().unwrap(),
22+
ip: 0,
23+
tape: lines[4]
24+
.split_whitespace()
25+
.nth(1)
26+
.unwrap()
27+
.split(',')
28+
.map(|s| s.parse().unwrap())
29+
.collect(),
30+
output: vec![],
31+
}
32+
}
33+
34+
#[inline]
35+
fn combo(&self, op: u64) -> u64 {
36+
match op {
37+
0..=3 => op,
38+
4 => self.reg_a,
39+
5 => self.reg_b,
40+
6 => self.reg_c,
41+
_ => unreachable!(),
42+
}
43+
}
44+
45+
#[inline]
46+
fn literal(&self, op: u64) -> u64 {
47+
return op;
48+
}
49+
50+
#[inline]
51+
fn _div(&self, op: u64) -> u64 {
52+
let l = self.reg_a;
53+
let r = 2_u64.pow(self.combo(op) as u32);
54+
l.div_euclid(r)
55+
}
56+
57+
#[inline]
58+
fn adv(&mut self, op: u64) {
59+
self.reg_a = self._div(op);
60+
}
61+
62+
#[inline]
63+
fn bdv(&mut self, op: u64) {
64+
self.reg_b = self._div(op);
65+
}
66+
67+
#[inline]
68+
fn cdv(&mut self, op: u64) {
69+
self.reg_c = self._div(op);
70+
}
71+
72+
#[inline]
73+
fn bxl(&mut self, op: u64) {
74+
self.reg_b = self.reg_b ^ self.literal(op);
75+
}
76+
77+
#[inline]
78+
fn bst(&mut self, op: u64) {
79+
self.reg_b = self.combo(op) % 8;
80+
}
81+
82+
#[inline]
83+
fn jnz(&mut self, op: u64) {
84+
if self.reg_a != 0 {
85+
self.ip = self.literal(op) as usize;
86+
}
87+
}
88+
89+
#[inline]
90+
fn bxc(&mut self, _op: u64) {
91+
self.reg_b = self.reg_b ^ self.reg_c;
92+
}
93+
94+
#[inline]
95+
fn out(&mut self, op: u64) {
96+
let v = self.combo(op) % 8;
97+
self.output.push(v);
98+
}
99+
100+
pub fn step(&mut self) -> bool {
101+
if self.ip + 1 >= self.tape.len() {
102+
return false;
103+
}
104+
105+
let (inst, op) = (self.tape[self.ip], self.tape[self.ip + 1]);
106+
self.ip += 2;
107+
108+
match inst {
109+
0 => self.adv(op),
110+
1 => self.bxl(op),
111+
2 => self.bst(op),
112+
3 => self.jnz(op),
113+
4 => self.bxc(op),
114+
5 => self.out(op),
115+
6 => self.bdv(op),
116+
7 => self.cdv(op),
117+
_ => unreachable!(),
118+
}
119+
120+
return true;
121+
}
122+
}
123+
124+
pub fn part_one(input: &str) -> Option<String> {
125+
let mut machine = Machine::parse(input);
126+
127+
while machine.step() {}
128+
129+
Some(
130+
machine
131+
.output
132+
.iter()
133+
.map(|c| c.to_string())
134+
.collect::<Vec<_>>()
135+
.join(","),
136+
)
137+
}
138+
139+
pub fn part_two(input: &str) -> Option<u64> {
140+
let machine = Machine::parse(input);
141+
let len = machine.tape.len();
142+
143+
let mut reg_a = 0;
144+
for take_len in 1..=len {
145+
let mut new_a = reg_a << 3;
146+
loop {
147+
let mut m = machine.clone();
148+
m.reg_a = new_a;
149+
150+
while m.step() {}
151+
152+
if m.output.eq(&machine.tape[len - take_len..]) {
153+
reg_a = new_a;
154+
break;
155+
}
156+
157+
new_a += 1;
158+
}
159+
}
160+
161+
Some(reg_a)
162+
}
163+
164+
#[cfg(test)]
165+
mod tests {
166+
use super::*;
167+
168+
// #[test]
169+
// fn test_ex_1() {
170+
// let mut machine = Machine {
171+
// reg_a: 0,
172+
// reg_b: 0,
173+
// reg_c: 9,
174+
// ip: 0,
175+
// tape: vec![2, 6],
176+
// output: vec![],
177+
// };
178+
// machine.step();
179+
// assert_eq!(machine.reg_b, 1);
180+
// }
181+
182+
// #[test]
183+
// fn test_ex_2() {
184+
// let mut machine = Machine {
185+
// reg_a: 10,
186+
// reg_b: 0,
187+
// reg_c: 0,
188+
// ip: 0,
189+
// tape: vec![5, 0, 5, 1, 5, 4],
190+
// output: vec![],
191+
// };
192+
// while machine.step() {}
193+
// assert_eq!(machine.output, vec![0, 1, 2]);
194+
// }
195+
196+
// #[test]
197+
// fn test_ex_3() {
198+
// let mut machine = Machine {
199+
// reg_a: 2024,
200+
// reg_b: 0,
201+
// reg_c: 0,
202+
// ip: 0,
203+
// tape: vec![0, 1, 5, 4, 3, 0],
204+
// output: vec![],
205+
// };
206+
// while machine.step() {}
207+
// assert_eq!(machine.output, vec![4, 2, 5, 6, 7, 7, 7, 7, 3, 1, 0]);
208+
// assert_eq!(machine.reg_a, 0);
209+
// }
210+
211+
// #[test]
212+
// fn test_ex_4() {
213+
// let mut machine = Machine {
214+
// reg_a: 0,
215+
// reg_b: 29,
216+
// reg_c: 0,
217+
// ip: 0,
218+
// tape: vec![1, 7],
219+
// output: vec![],
220+
// };
221+
// machine.step();
222+
// assert_eq!(machine.reg_b, 26);
223+
// }
224+
225+
// #[test]
226+
// fn test_ex_5() {
227+
// let mut machine = Machine {
228+
// reg_a: 0,
229+
// reg_b: 2024,
230+
// reg_c: 43690,
231+
// ip: 0,
232+
// tape: vec![4, 0],
233+
// output: vec![],
234+
// };
235+
// machine.step();
236+
// assert_eq!(machine.reg_b, 44354);
237+
// }
238+
239+
// #[test]
240+
// fn test_ex_6() {
241+
// let mut machine = Machine {
242+
// reg_a: 117440,
243+
// reg_b: 0,
244+
// reg_c: 0,
245+
// ip: 0,
246+
// tape: vec![0, 3, 5, 4, 3, 0],
247+
// output: vec![],
248+
// };
249+
// while machine.step() {}
250+
// assert_eq!(machine.output, vec![0, 3, 5, 4, 3, 0]);
251+
// }
252+
253+
// #[test]
254+
// fn test_part_one() {
255+
// let result = part_one(&advent_of_code::template::read_file_part("examples", DAY, 1));
256+
// assert_eq!(result, Some("4,6,3,5,6,3,5,2,1,0".to_string()));
257+
// }
258+
259+
#[test]
260+
fn test_part_two() {
261+
let result = part_two(&advent_of_code::template::read_file_part(
262+
"examples", DAY, 2,
263+
));
264+
assert_eq!(result, Some(117440));
265+
}
266+
}

0 commit comments

Comments
 (0)