diff options
author | tomsmeding <tom.smeding@gmail.com> | 2018-12-22 01:00:42 +0100 |
---|---|---|
committer | tomsmeding <tom.smeding@gmail.com> | 2018-12-22 01:00:42 +0100 |
commit | 25844ee408f73893175a8dc999391df0a3ed377a (patch) | |
tree | c470133914af0233855827a3f683ac7686313936 /2018/src | |
parent | dc9ba8162ff0a17fbafd6d589e53cdce1eada1b0 (diff) |
Day 21
Diffstat (limited to '2018/src')
-rw-r--r-- | 2018/src/day21.rs | 68 | ||||
-rw-r--r-- | 2018/src/device.rs | 2 | ||||
-rw-r--r-- | 2018/src/main.rs | 4 |
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")) } } |