summaryrefslogtreecommitdiff
path: root/2018/src/day21.rs
diff options
context:
space:
mode:
Diffstat (limited to '2018/src/day21.rs')
-rw-r--r--2018/src/day21.rs68
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()))
+}