Advent of code day 17, rough doing the decompilation

This commit is contained in:
2025-01-06 16:47:43 +01:00
parent 6c949c0657
commit a2dbfb47da
5 changed files with 199 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
[package]
name = "main"
version = "0.1.0"
edition = "2021"

View File

@@ -0,0 +1,5 @@
Register A: 52042868
Register B: 0
Register C: 0
Program: 2,4,1,7,7,5,0,3,4,4,1,7,5,5,3,0

View File

@@ -0,0 +1,180 @@
fn parse(input: &str) -> (u64, u64, u64, Vec<u64>) {
let lines: Vec<Vec<&str>> = input
.lines()
.map(|l| l.split_whitespace().collect())
.collect();
(
lines[0].last().unwrap().parse().unwrap(),
lines[1].last().unwrap().parse().unwrap(),
lines[2].last().unwrap().parse().unwrap(),
lines
.last()
.unwrap()
.last()
.unwrap()
.split(',')
.map(|i| i.parse().unwrap())
.collect(),
)
}
fn combo(a: u64, b: u64, c: u64, op: u64) -> u64 {
match op {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => a,
5 => b,
6 => c,
_ => unreachable!(),
}
}
fn solve_1(input: &str) -> String {
let (a, b, c, ops) = parse(input);
stringify(solve(a, b, c, ops))
}
fn solve(mut a: u64, mut b: u64, mut c: u64, ops: Vec<u64>) -> Vec<u64> {
let mut ip = 0;
let mut out: Vec<u64> = vec![];
while ip < ops.len() {
let ins = *ops.get(ip).unwrap();
let op = *ops.get(ip + 1).unwrap();
match ins {
0 => {
// adv
let result = a >> combo(a, b, c, op);
a = result;
ip += 2;
}
1 => {
// bxl
let result = b ^ op;
b = result;
ip += 2;
}
2 => {
// bst
let result = combo(a, b, c, op) % 8;
b = result;
ip += 2;
}
3 => {
// jnz
if a != 0 {
ip = op as usize;
} else {
ip += 2;
}
}
4 => {
// bxc
let result = b ^ c;
b = result;
ip += 2;
}
5 => {
// out
out.push(combo(a, b, c, op) % 8);
ip += 2;
}
6 => {
// bdv
let result = a >> combo(a, b, c, op);
b = result;
ip += 2;
}
7 => {
// cdv
let result = a >> combo(a, b, c, op);
c = result;
ip += 2;
}
_ => unreachable!(),
}
}
out
}
fn stringify(ops: Vec<u64>) -> String {
let out = ops
.into_iter()
.fold("".to_string(), |result, n| result + "," + &n.to_string());
out.as_str()[1..].to_string()
}
// Decompilation of my program yields the following
// 2,4,1,7,7,5,0,3,4,4,1,7,5,5,3,0
//
// while a:
// b = a % 8
// b = b ^ 7
// c = a >> b
// a = a >> 3
// b = b ^ c
// b = b ^ 7
// out(b % 8)
fn solve_2(input: &str) -> u64 {
fn find(ops: &[u64], ans: u64) -> Option<u64> {
if ops.is_empty() {
return Some(ans);
}
for t in 0..8 {
let a = ans << 3 | t;
let mut b = a % 8;
b = b ^ 7;
let c = a >> b;
b = b ^ c;
b = b ^ 7;
let output = b % 8;
if output == *ops.last().unwrap() {
let sub = find(&ops[..ops.len() - 1], a);
if sub.is_some() {
return sub;
}
}
}
return None;
}
let (_a, _b, _c, ops) = parse(input);
find(&ops[..], 0).unwrap()
}
fn main() {
println!("Hello, this is Patrick!");
let input = include_str!("../input.txt");
let result_1 = solve_1(input);
println!("The final output of the program is {}", result_1);
let result_2 = solve_2(input);
println!(
"The lowest positive initial value for register A to get a copy of the program is {}",
result_2
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
let test_input = include_str!("../test.txt");
assert_eq!(solve_1(test_input), "4,6,3,5,6,3,5,2,1,0");
}
}

View File

@@ -0,0 +1,5 @@
Register A: 729
Register B: 0
Register C: 0
Program: 0,1,5,4,3,0

View File

@@ -0,0 +1,5 @@
Register A: 2024
Register B: 0
Register C: 0
Program: 0,3,5,4,3,0