use std::io::BufRead; use std::io::BufReader; use std::io::Read; use common::Solution; use cpu::OpCode; use cpu::CPU; #[derive(Default)] pub struct Day19 { program: Vec<(OpCode, [i32; 3])>, ip: usize, } impl Day19 { pub fn new() -> Self { Default::default() } fn read_input(&mut self, input: &mut dyn Read) { let reader = BufReader::new(input); for line in reader.lines() { let line = line.unwrap(); if line.starts_with('#') { self.ip = line.split(' ').last().unwrap().parse().unwrap(); } else { let mut parts = line.split(' '); let opcode = OpCode::from(parts.next().unwrap()); let mut operands = [0; 3]; for (target, part) in operands.iter_mut().zip(parts) { *target = part.parse().unwrap(); } self.program.push((opcode, operands)); } } } } impl Solution for Day19 { fn part1(&mut self, input: &mut dyn Read) -> String { self.read_input(input); let mut cpu = CPU::new(); while (cpu.registers[self.ip] as usize) < self.program.len() { let (opcode, operands) = &self.program[cpu.registers[self.ip] as usize]; cpu.execute(*opcode, operands).unwrap(); cpu.registers[self.ip] += 1; } cpu.registers[0].to_string() } fn part2(&mut self, input: &mut dyn Read) -> String { self.read_input(input); let mut cpu = CPU::new(); cpu.registers[0] = 1; // This is optimized for my input. assert_eq!(self.ip, 3); while (cpu.registers[3] as usize) < self.program.len() { if cpu.registers[3] == 1 { let reg = &mut cpu.registers; reg[0] = (1..=reg[5]).filter(|&x| reg[5] % x == 0).sum(); reg[3] = 16; } let (opcode, operands) = &self.program[cpu.registers[self.ip] as usize]; cpu.execute(*opcode, operands).unwrap(); cpu.registers[self.ip] += 1; } cpu.registers[0].to_string() } } #[cfg(test)] mod tests { use common::Solution; use day19::Day19; const SAMPLE_INPUT: &[u8] = include_bytes!("samples/19.txt"); #[test] fn sample_part1() { let mut instance = Day19::new(); assert_eq!("7", instance.part1(&mut SAMPLE_INPUT)); } }