Untitled
unknown
rust
4 months ago
5.6 kB
14
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