168 Zeilen
4,7 KiB
Rust
168 Zeilen
4,7 KiB
Rust
use advent_of_code::strings::{convert_to_array, parsenumber};
|
|
use advent_of_code_macros::include_aoc;
|
|
use log::*;
|
|
use thousands::Separable;
|
|
|
|
include_aoc!(DATA 2024 17);
|
|
|
|
const ADV: u64 = 0;
|
|
const BXL: u64 = 1;
|
|
const BST: u64 = 2;
|
|
const JNZ: u64 = 3;
|
|
const BXC: u64 = 4;
|
|
const OUT: u64 = 5;
|
|
const BDV: u64 = 6;
|
|
const CDV: u64 = 7;
|
|
|
|
const BASE: u64 = 2;
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct GenericCPU {
|
|
a: u64,
|
|
b: u64,
|
|
c: u64,
|
|
pos: usize,
|
|
ops: Vec<u64>,
|
|
output: Vec<u64>,
|
|
}
|
|
|
|
impl GenericCPU {
|
|
fn generic_process(&mut self) {
|
|
let mut opcode;
|
|
let mut operand;
|
|
loop {
|
|
opcode = match self.ops.get(self.pos) {
|
|
None => break,
|
|
Some(x) => *x,
|
|
};
|
|
operand = *self.ops.get(self.pos + 1).unwrap();
|
|
match opcode {
|
|
ADV => {
|
|
debug!("truncating A({}) >> {} = {}", self.a, self.comboop(operand), self.a >> self.comboop(operand));
|
|
self.a >>= self.comboop(operand);
|
|
},
|
|
BXL => {
|
|
debug!("XOR B({}) with {} = {}", self.b, operand, self.b ^ operand);
|
|
self.b ^= operand;
|
|
},
|
|
BST => {
|
|
self.b = self.comboop(operand) % 8;
|
|
debug!("Setting B to comboop({}) = ({})", operand, self.b)
|
|
},
|
|
JNZ => {
|
|
if self.a != 0 {
|
|
debug!("Jumping to {}", operand);
|
|
self.pos = operand as usize;
|
|
continue;
|
|
}
|
|
debug!("Do nothing");
|
|
},
|
|
BXC => {
|
|
debug!("XORing B and C");
|
|
self.b ^= self.c;
|
|
},
|
|
OUT => {
|
|
debug!("printing {} % 8 = {}", self.comboop(operand), self.comboop(operand) % 8);
|
|
self.output.push(self.comboop(operand) % 8);
|
|
},
|
|
BDV => {
|
|
debug!("truncating A({}) >> {} = B({})", self.a, self.comboop(operand), self.a >> self.comboop(operand));
|
|
self.b = self.a >> self.comboop(operand);
|
|
},
|
|
CDV => {
|
|
debug!("truncating A({}) >> {} = C({})", self.a, self.comboop(operand), self.a >> self.comboop(operand));
|
|
self.c = self.a >> self.comboop(operand);
|
|
},
|
|
x => {
|
|
debug!("opcode {x} unimplemented");
|
|
break;
|
|
},
|
|
}
|
|
self.pos += 2;
|
|
}
|
|
}
|
|
fn comboop(&self, op: u64) -> u64 {
|
|
match op {
|
|
0..=3 => op,
|
|
4 => self.a,
|
|
5 => self.b,
|
|
6 => self.c,
|
|
7 => unimplemented!(),
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
fn reset(&mut self) {
|
|
self.a = 0;
|
|
self.b = 0;
|
|
self.c = 0;
|
|
self.pos = 0;
|
|
self.output.clear();
|
|
}
|
|
}
|
|
|
|
fn get_content(i: &str) -> String {
|
|
if i == "" {
|
|
i.to_string()
|
|
} else {
|
|
i.split_once(':').unwrap().1.trim().to_string()
|
|
}
|
|
}
|
|
|
|
fn round(n: u64) -> u64 {
|
|
let mut b = n % 8;
|
|
b ^= 6;
|
|
b ^= n >> b;
|
|
b ^= 7;
|
|
b % 8
|
|
}
|
|
|
|
fn main() {
|
|
let data = convert_to_array::<_, _, '\n'>(DATA, get_content);
|
|
let mut mem = GenericCPU {
|
|
a: parsenumber(&data[0]),
|
|
b: parsenumber(&data[1]),
|
|
c: parsenumber(&data[2]),
|
|
pos: 0,
|
|
ops: data[4].split(',').map(|op| parsenumber(op)).collect(),
|
|
output: Vec::new(),
|
|
};
|
|
let mut n = mem.a;
|
|
while n > 0 {
|
|
println!("Round: {}", round(n));
|
|
n >>= 3;
|
|
}
|
|
mem.generic_process();
|
|
let output = mem.output.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
|
|
println!("output: {}", output);
|
|
let mut n: u64 = 0;
|
|
'numloop: for (pos, num) in mem.ops.iter().enumerate().map(|(x, y)| (x * 3, *y)).rev() {
|
|
for i in 0..64 {
|
|
println!("Testing round({}) == {}", ((n >> pos) + i).separate_with_underscores(), num);
|
|
if round((n >> pos) + i) == num {
|
|
println!("Adding {}, the source of {}", i, num);
|
|
n += i << pos;
|
|
continue 'numloop;
|
|
}
|
|
}
|
|
println!("Not Possible to find equivalent of {}", num);
|
|
}
|
|
println!("Testing {}", format!("{:018b}", n).separate_with_dots());
|
|
if n >= 48331947862051 {
|
|
println!("Failed");
|
|
return;
|
|
}
|
|
mem.reset();
|
|
mem.a = n;
|
|
mem.generic_process();
|
|
if mem.output == mem.ops {
|
|
println!("A: {n}")
|
|
} else {
|
|
println!("{:?}\n{:?}", mem.ops, mem.output);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
}
|