summaryrefslogtreecommitdiff
path: root/2018/src
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2018-12-22 01:00:42 +0100
committertomsmeding <tom.smeding@gmail.com>2018-12-22 01:00:42 +0100
commit25844ee408f73893175a8dc999391df0a3ed377a (patch)
treec470133914af0233855827a3f683ac7686313936 /2018/src
parentdc9ba8162ff0a17fbafd6d589e53cdce1eada1b0 (diff)
Day 21
Diffstat (limited to '2018/src')
-rw-r--r--2018/src/day21.rs68
-rw-r--r--2018/src/device.rs2
-rw-r--r--2018/src/main.rs4
3 files changed, 72 insertions, 2 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()))
+}
diff --git a/2018/src/device.rs b/2018/src/device.rs
index 7eaf8d3..cf6d94e 100644
--- a/2018/src/device.rs
+++ b/2018/src/device.rs
@@ -181,7 +181,7 @@ impl fmt::Display for Instr {
}
}
-#[derive(PartialEq, Eq, Clone)]
+#[derive(PartialEq, Eq, Clone, Hash, Debug)]
pub struct Machine {
pub regs: [usize; 6],
}
diff --git a/2018/src/main.rs b/2018/src/main.rs
index 34c3964..fa1cab8 100644
--- a/2018/src/main.rs
+++ b/2018/src/main.rs
@@ -26,8 +26,9 @@ mod day17;
mod day18;
mod day19;
mod day20;
+mod day21;
-static NUM_DAYS: i32 = 20;
+static NUM_DAYS: i32 = 21;
fn day_switch<T: BufRead>(day: i32, reader: T) -> io::Result<(String, String)> {
match day {
@@ -51,6 +52,7 @@ fn day_switch<T: BufRead>(day: i32, reader: T) -> io::Result<(String, String)> {
18 => day18::main(reader),
19 => day19::main(reader),
20 => day20::main(reader),
+ 21 => day21::main(reader),
_ => Err(Error::new(ErrorKind::Other, "Invalid day"))
}
}