use std::io; use std::io::BufRead; use std::collections::HashSet; use crate::device::*; #[allow(dead_code)] fn optimise(mut instrs: Vec, ip_reg: usize) -> Vec { for i in 0..instrs.len() { instrs[i].inline_reg(ip_reg, Oper::Num(i)); } instrs } #[allow(dead_code)] fn run_program(instrs: &[Instr], r0: usize, ip_reg: usize) -> usize { let mut m = Machine { regs: [r0, 0, 0, 0, 0, 0] }; m.exec_program(&instrs, ip_reg); m.regs[0] } pub fn main(reader: T) -> io::Result<(String, String)> { let (ip_reg, instrs) = parse_program(reader)?; let instrs = optimise(instrs, ip_reg); // for instr in &instrs { println!("{}", instr); } let part1; let mut ip = 0; let mut m = Machine { regs: [0, 0, 0, 0, 0, 0] }; loop { assert!(ip < instrs.len()); if ip == 28 { part1 = m.regs[4]; break; } m.regs[ip_reg] = ip; m.exec(&instrs[ip]); ip = m.regs[ip_reg] + 1; } let mut part2 = None; let mut seen_machines = HashSet::new(); let mut seen_values = HashSet::new(); loop { assert!(ip < instrs.len()); if ip == 28 { // println!("{:?}", m); if seen_machines.contains(&m) { break; } seen_machines.insert(m.clone()); if !seen_values.contains(&m.regs[4]) { part2 = Some(m.regs[4]); seen_values.insert(m.regs[4]); } } m.regs[ip_reg] = ip; m.exec(&instrs[ip]); ip = m.regs[ip_reg] + 1; } Ok((part1.to_string(), part2.unwrap().to_string())) }