From a2dbfb47dab5a0c071a29d1ae148b1e4591bb0c0 Mon Sep 17 00:00:00 2001 From: Philippe Zwietering Date: Mon, 6 Jan 2025 16:47:43 +0100 Subject: [PATCH] Advent of code day 17, rough doing the decompilation --- advent_of_code/2024/17/Cargo.toml | 4 + advent_of_code/2024/17/input.txt | 5 + advent_of_code/2024/17/src/main.rs | 180 +++++++++++++++++++++++++++++ advent_of_code/2024/17/test.txt | 5 + advent_of_code/2024/17/test2.txt | 5 + 5 files changed, 199 insertions(+) create mode 100644 advent_of_code/2024/17/Cargo.toml create mode 100644 advent_of_code/2024/17/input.txt create mode 100644 advent_of_code/2024/17/src/main.rs create mode 100644 advent_of_code/2024/17/test.txt create mode 100644 advent_of_code/2024/17/test2.txt diff --git a/advent_of_code/2024/17/Cargo.toml b/advent_of_code/2024/17/Cargo.toml new file mode 100644 index 0000000..015227a --- /dev/null +++ b/advent_of_code/2024/17/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "main" +version = "0.1.0" +edition = "2021" diff --git a/advent_of_code/2024/17/input.txt b/advent_of_code/2024/17/input.txt new file mode 100644 index 0000000..97c9616 --- /dev/null +++ b/advent_of_code/2024/17/input.txt @@ -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 diff --git a/advent_of_code/2024/17/src/main.rs b/advent_of_code/2024/17/src/main.rs new file mode 100644 index 0000000..a5941e5 --- /dev/null +++ b/advent_of_code/2024/17/src/main.rs @@ -0,0 +1,180 @@ +fn parse(input: &str) -> (u64, u64, u64, Vec) { + let lines: Vec> = 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) -> Vec { + let mut ip = 0; + let mut out: Vec = 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) -> 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 { + 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"); + } +} diff --git a/advent_of_code/2024/17/test.txt b/advent_of_code/2024/17/test.txt new file mode 100644 index 0000000..f09839b --- /dev/null +++ b/advent_of_code/2024/17/test.txt @@ -0,0 +1,5 @@ +Register A: 729 +Register B: 0 +Register C: 0 + +Program: 0,1,5,4,3,0 diff --git a/advent_of_code/2024/17/test2.txt b/advent_of_code/2024/17/test2.txt new file mode 100644 index 0000000..4a91c26 --- /dev/null +++ b/advent_of_code/2024/17/test2.txt @@ -0,0 +1,5 @@ +Register A: 2024 +Register B: 0 +Register C: 0 + +Program: 0,3,5,4,3,0