Untitled
unknown
rust
10 months ago
5.6 kB
16
Indexable
pub fn solution(test: bool) -> ((usize, Duration), (usize, Duration)) {
let lines;
if test {
lines = include_str!("../../../AdventOfCodeInputs/problem_inputs_2024/day_17_test.txt");
} else {
lines = include_str!("../../../AdventOfCodeInputs/problem_inputs_2024/day_17.txt");
}
(solve01(lines), solve02(lines))
}
fn solve01(lines: &str) -> (usize, Duration) {
let now = Instant::now();
let mut comp = Computer::from_str(lines);
println!(
"Part 1: '{}' computed in {:?}",
comp.run().iter().map(|f| f.to_string()).join(","),
now.elapsed()
);
(0, now.elapsed())
}
fn solve02(lines: &str) -> (usize, Duration) {
let now = Instant::now();
let comp = Computer::from_str(lines);
let mut a: usize = 0;
let mut ind = comp.rom.len() - 1;
loop {
let mut comp_try = Computer {
registers: [a as isize, 0, 0],
ip: 0,
rom: comp.rom.clone(),
};
let mut output = comp_try.run();
while output.len() < comp.rom.len() {
output.push(isize::MAX);
}
if output[ind..] == comp.rom[ind..] {
if ind == 0 {
break;
} else {
ind -= 1;
}
} else {
a += 8_usize.pow(ind as u32);
}
}
let mut sanity = Computer {
registers: [a as isize, 0, 0],
ip: 0,
rom: comp.rom.clone(),
};
assert_eq!(sanity.run(), comp.rom);
(a, now.elapsed())
}
#[derive(Debug, Clone, Copy)]
enum Instruction {
Adv,
Bxl,
Bst,
Jnz,
Bxc,
Out,
Bdv,
Cdv,
}
impl Instruction {
fn from_int(i: u32) -> Self {
match i {
0 => Self::Adv,
1 => Self::Bxl,
2 => Self::Bst,
3 => Self::Jnz,
4 => Self::Bxc,
5 => Self::Out,
6 => Self::Bdv,
7 => Self::Cdv,
_ => panic!("Invalid instruction"),
}
}
}
#[derive(Debug, Clone)]
struct Computer {
registers: [isize; 3],
ip: usize,
rom: Vec<isize>,
}
impl Computer {
fn from_str(lines: &str) -> Self {
let mut registers = [0; 3];
let ip = 0;
let rom;
let mut lines = lines.lines();
for i in 0..3 {
registers[i] = lines
.next()
.unwrap()
.split(':')
.nth(1)
.unwrap()
.trim()
.parse()
.unwrap();
}
lines.next();
rom = lines
.next()
.unwrap()
.split(": ")
.nth(1)
.unwrap()
.split(',')
.map(|c| c.parse().unwrap())
.collect();
Self { registers, ip, rom }
}
fn get_register_value(&self, register: usize) -> isize {
self.registers[register]
}
fn run(&mut self) -> Vec<isize> {
let mut ans = Vec::new();
while self.ip < self.rom.len() - 1 {
if let Some(output) = self.step() {
ans.push(output);
}
}
ans
}
fn step(&mut self) -> Option<isize> {
let instr = Instruction::from_int(self.rom[self.ip] as u32);
let operand = self.rom[self.ip + 1];
let out = self.apply_instr(instr, operand as usize);
return out;
}
fn parse_combo(&self, combo: usize) -> usize {
match combo {
0..=3 => combo,
4..=6 => self.get_register_value(combo - 4) as usize,
_ => panic!("Invalid operand"),
}
}
fn apply_instr(&mut self, instr: Instruction, operand: usize) -> Option<isize> {
match instr {
Instruction::Adv => {
let numerator = self.get_register_value(0);
let operand = self.parse_combo(operand);
self.registers[0] = numerator >> operand;
self.ip += 2;
}
Instruction::Bxl => {
let x = self.get_register_value(1);
self.registers[1] = x ^ operand as isize;
self.ip += 2;
}
Instruction::Bst => {
let x = self.parse_combo(operand);
self.registers[1] = (x % 8) as isize;
self.ip += 2;
}
Instruction::Jnz => {
if self.get_register_value(0) != 0 {
self.ip = operand;
} else {
self.ip += 2;
}
}
Instruction::Bxc => {
let b = self.get_register_value(1);
let c = self.get_register_value(2);
self.registers[1] = b ^ c;
self.ip += 2;
}
Instruction::Out => {
let x = self.parse_combo(operand);
self.ip += 2;
return Some((x % 8) as isize);
}
Instruction::Bdv => {
let numerator = self.get_register_value(0);
let operand = self.parse_combo(operand);
self.registers[1] = numerator >> operand;
self.ip += 2;
}
Instruction::Cdv => {
let numerator = self.get_register_value(0);
let operand = self.parse_combo(operand);
self.registers[2] = numerator >> operand;
self.ip += 2;
}
}
None
}
}Editor is loading...
Leave a Comment