diff options
Diffstat (limited to '2018/src/day21.rs')
-rw-r--r-- | 2018/src/day21.rs | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/2018/src/day21.rs b/2018/src/day21.rs new file mode 100644 index 0000000..e0983a3 --- /dev/null +++ b/2018/src/day21.rs @@ -0,0 +1,68 @@ +use std::io; +use std::io::BufRead; +use std::collections::HashSet; +use crate::device::*; + +#[allow(dead_code)] +fn optimise(mut instrs: Vec<Instr>, ip_reg: usize) -> Vec<Instr> { + 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<T: BufRead>(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())) +} |