Skip to content

Commit d7ad7cb

Browse files
committed
Clean up day 17
1 parent c190f0d commit d7ad7cb

File tree

3 files changed

+135
-0
lines changed

3 files changed

+135
-0
lines changed

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

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: 729
2+
Register B: 0
3+
Register C: 0
4+
5+
Program: 0,1,5,4,3,0

src/bin/17.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
advent_of_code::solution!(17);
2+
fn load_program(lines: Vec<&str>) -> Vec<u64> {
3+
lines[4][9..]
4+
.split(',')
5+
.map(|s| s.parse::<u64>().unwrap())
6+
.collect::<Vec<_>>()
7+
}
8+
9+
fn call_computer_output(program: &[u64], mut a: u64, mut b: u64, mut c: u64) -> Vec<u64> {
10+
let mut ip = 0;
11+
let mut output = Vec::new();
12+
13+
while ip < program.len() {
14+
let opcode = program[ip];
15+
let literal = program[ip + 1];
16+
17+
let combo = match literal {
18+
0..=3 => literal,
19+
4 => a,
20+
5 => b,
21+
6 => c,
22+
_ => unreachable!(),
23+
};
24+
25+
match opcode {
26+
0 => a >>= combo,
27+
1 => b ^= literal,
28+
2 => b = combo % 8,
29+
3 => {
30+
if a != 0 {
31+
ip = literal as usize;
32+
continue;
33+
}
34+
}
35+
4 => b ^= c,
36+
5 => output.push(combo % 8),
37+
6 => b = a >> combo,
38+
7 => c = a >> combo,
39+
_ => unreachable!(), //println!("wrong {:?}", opcode),
40+
};
41+
42+
ip += 2;
43+
}
44+
output
45+
}
46+
47+
pub fn part_one(input: &str) -> Option<String> {
48+
let lines = input.lines().collect::<Vec<_>>();
49+
50+
//read register
51+
let a = lines[0][12..].parse::<u64>().ok()?;
52+
let b = lines[1][12..].parse::<u64>().ok()?;
53+
let c = lines[2][12..].parse::<u64>().ok()?;
54+
55+
let program = load_program(lines);
56+
57+
// println!("{:?} {:?}",a, program);
58+
let output = call_computer_output(&program, a, b, c);
59+
60+
Some(
61+
output
62+
.into_iter()
63+
.map(|s| s.to_string())
64+
.collect::<Vec<_>>()
65+
.join(","),
66+
)
67+
}
68+
69+
pub fn part_two(input: &str) -> Option<usize> {
70+
// we know what suppose to be register A
71+
let lines = input.lines().collect::<Vec<_>>();
72+
73+
// read register
74+
let _a = lines[0][12..].parse::<u64>().ok()?;
75+
let b = lines[1][12..].parse::<u64>().ok()?;
76+
let c = lines[2][12..].parse::<u64>().ok()?;
77+
78+
// println!("a: {} b: {} c: {}", a, b, c);
79+
80+
let program = load_program(lines);
81+
82+
let mut possibilities = vec![0; program.len()];
83+
84+
loop {
85+
let mut init_a = 0;
86+
for (i, f) in possibilities.iter().enumerate() {
87+
init_a += 8u64.pow(i as u32) * f
88+
}
89+
90+
let output = call_computer_output(&program, init_a, b, c);
91+
92+
if output == program {
93+
return Some(init_a as usize);
94+
}
95+
96+
for i in (0..program.len()).rev() {
97+
if output.len() < i || output[i] != program[i] {
98+
possibilities[i] += 1;
99+
for f in possibilities.iter_mut().take(i) {
100+
*f = 0;
101+
}
102+
break;
103+
}
104+
}
105+
}
106+
}
107+
108+
#[cfg(test)]
109+
mod tests {
110+
use super::*;
111+
112+
#[test]
113+
fn test_part_one() {
114+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
115+
assert_eq!(result, Some("4,6,3,5,6,3,5,2,1,0".into()));
116+
}
117+
118+
#[test]
119+
fn test_part_two() {
120+
let result = part_two(&advent_of_code::template::read_file_part(
121+
"examples", DAY, 2,
122+
));
123+
assert_eq!(result, Some(117440));
124+
}
125+
}

0 commit comments

Comments
 (0)