Skip to content

Commit c29ade1

Browse files
day 17
1 parent e0a70a9 commit c29ade1

File tree

3 files changed

+176
-1
lines changed

3 files changed

+176
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
4848
| [Day 14](./src/bin/14.rs) | `33.1µs` | `-` |
4949
| [Day 15](./src/bin/15.rs) | `1.4ms` | `4.3ms` |
5050
| [Day 16](./src/bin/16.rs) | `77.3ms` | `545.3ms` |
51+
| [Day 17](./src/bin/17.rs) | `1.3µs` | `33.1µs` |
5152

52-
**Total: 939.38ms**
53+
**Total: 939.42ms**
5354
<!--- benchmarking table --->

data/examples/17.txt

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

src/bin/17.rs

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
use itertools::Itertools;
2+
3+
advent_of_code::solution!(17);
4+
5+
#[derive(Debug, Eq, Hash, PartialEq, Clone, Copy)]
6+
struct Machine {
7+
a: u64,
8+
b: u64,
9+
c: u64,
10+
11+
pc: usize,
12+
}
13+
14+
impl Machine {
15+
pub fn perform_cycle(&mut self, program: &[u8]) -> Option<u64> {
16+
let op_code = program[self.pc];
17+
let operand = program[self.pc + 1];
18+
19+
match op_code {
20+
0 => {
21+
self.a /= 2u64.pow(self.get_combo_operand(operand) as u32);
22+
self.pc += 2;
23+
None
24+
}
25+
1 => {
26+
self.b ^= operand as u64;
27+
self.pc += 2;
28+
None
29+
}
30+
2 => {
31+
self.b = self.get_combo_operand(operand) % 8;
32+
self.pc += 2;
33+
None
34+
}
35+
3 => {
36+
if self.a == 0 {
37+
self.pc += 2;
38+
return None;
39+
};
40+
41+
self.pc = operand as usize;
42+
None
43+
}
44+
4 => {
45+
self.b ^= self.c;
46+
self.pc += 2;
47+
None
48+
}
49+
5 => {
50+
self.pc += 2;
51+
Some(self.get_combo_operand(operand) % 8)
52+
}
53+
6 => {
54+
self.b = self.a / 2u64.pow(self.get_combo_operand(operand) as u32);
55+
self.pc += 2;
56+
None
57+
}
58+
7 => {
59+
self.c = self.a / 2u64.pow(self.get_combo_operand(operand) as u32);
60+
self.pc += 2;
61+
None
62+
}
63+
_ => None,
64+
}
65+
}
66+
67+
fn get_combo_operand(&self, operand: u8) -> u64 {
68+
match operand {
69+
0..=3 => operand as u64,
70+
4 => self.a,
71+
5 => self.b,
72+
6 => self.c,
73+
7.. => panic!("Bad stuff"),
74+
}
75+
}
76+
}
77+
78+
pub fn part_one(input: &str) -> Option<String> {
79+
let lines = input.lines().collect_vec();
80+
81+
let mut machine = Machine {
82+
a: lines[0].split_once(":").unwrap().1.trim().parse().unwrap(),
83+
b: lines[1].split_once(":").unwrap().1.trim().parse().unwrap(),
84+
c: lines[2].split_once(":").unwrap().1.trim().parse().unwrap(),
85+
pc: 0,
86+
};
87+
88+
let program: Vec<u8> = lines[4]
89+
.split_once(":")
90+
.unwrap()
91+
.1
92+
.trim()
93+
.split(",")
94+
.map(|n| n.parse().unwrap())
95+
.collect_vec();
96+
97+
let mut result: Vec<String> = vec![];
98+
while machine.pc < program.len() {
99+
if let Some(out) = machine.perform_cycle(&program) {
100+
result.push(out.to_string())
101+
};
102+
}
103+
104+
Some(result.join(","))
105+
}
106+
107+
pub fn part_two(input: &str) -> Option<u64> {
108+
let lines = input.lines().collect_vec();
109+
110+
let program: Vec<u8> = lines[4]
111+
.split_once(":")
112+
.unwrap()
113+
.1
114+
.trim()
115+
.split(",")
116+
.map(|n| n.parse().unwrap())
117+
.collect_vec();
118+
119+
dfs(0, &program, 0)
120+
}
121+
122+
fn dfs(a: u64, program: &[u8], depth: u64) -> Option<u64> {
123+
if depth == program.len() as u64 {
124+
return Some(a);
125+
}
126+
127+
let mut p_copy = program.to_owned();
128+
p_copy.reverse();
129+
130+
for i in 0..8 {
131+
let mut machine = Machine {
132+
a: a * 8 + i,
133+
b: 0,
134+
c: 0,
135+
pc: 0,
136+
};
137+
let mut result: Vec<u8> = vec![];
138+
while machine.pc < program.len() {
139+
if let Some(out) = machine.perform_cycle(program) {
140+
result.push(out as u8)
141+
};
142+
}
143+
144+
if p_copy[depth as usize] == result[0] {
145+
if let Some(out) = dfs(a * 8 + i, program, depth + 1) {
146+
return Some(out);
147+
};
148+
}
149+
}
150+
151+
None
152+
}
153+
154+
#[cfg(test)]
155+
mod tests {
156+
use super::*;
157+
158+
#[test]
159+
fn test_part_one() {
160+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
161+
assert_eq!(result, None);
162+
}
163+
164+
#[test]
165+
fn test_part_two() {
166+
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
167+
assert_eq!(result, None);
168+
}
169+
}

0 commit comments

Comments
 (0)