-
Notifications
You must be signed in to change notification settings - Fork 0
/
17.rs
94 lines (85 loc) · 2.32 KB
/
17.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#![feature(test)]
use std::fmt::Write;
struct Input {
registers: [u64; 3],
program: Vec<u64>,
}
fn setup(input: &str) -> Input {
let mut blocks = input.trim().split("\n\n");
let registers = blocks
.next()
.unwrap()
.lines()
.map(|l| l.rsplit_once(' ').unwrap().1.parse().unwrap())
.collect::<Vec<_>>()
.try_into()
.unwrap();
let program = blocks
.next()
.unwrap()
.split(' ')
.nth(1)
.unwrap()
.split(',')
.map(|n| n.parse().unwrap())
.collect();
Input { registers, program }
}
fn run(mut reg: [u64; 3], program: &[u64]) -> Vec<u64> {
let mut out = Vec::new();
let mut pc = 0;
while pc < program.len() {
let inst = program[pc];
let arg = program[pc + 1];
let combo = || match arg {
0..=3 => arg,
4..=6 => reg[arg as usize - 4],
_ => panic!("invalid combo arg: {arg}"),
};
match inst {
0 => reg[0] >>= combo(),
1 => reg[1] ^= arg,
2 => reg[1] = combo() & 0b111,
3 if reg[0] == 0 => {}
3 => {
pc = arg as usize;
continue;
}
4 => reg[1] ^= reg[2],
5 => out.push(combo() & 0b111),
6 => reg[1] = reg[0] >> combo(),
7 => reg[2] = reg[0] >> combo(),
8.. => panic!("Invalid instruction: {inst}"),
}
pc += 2;
}
out
}
fn part1(input: &Input) -> String {
let mut out = String::new();
for n in run(input.registers, &input.program) {
write!(&mut out, "{n},").unwrap();
}
out.truncate(out.len() - (out.ends_with(',') as usize));
out
}
fn part2(input: &Input) -> u64 {
let mut stack = vec![(0, 0)];
let mut result = u64::MAX;
while let Some((a, i)) = stack.pop() {
if i == input.program.len() {
result = result.min(a);
continue;
}
for j in 0..1 << 3 {
let a = a << 3 | j;
let mut registers = input.registers;
registers[0] = a;
if run(registers, &input.program) == input.program[input.program.len() - i - 1..] {
stack.push((a, i + 1));
}
}
}
result
}
aoc::main!(2024, 17, ex: 1, 2);