summaryrefslogtreecommitdiff
path: root/2018/src/bin/day_21.rs
diff options
context:
space:
mode:
Diffstat (limited to '2018/src/bin/day_21.rs')
-rw-r--r--2018/src/bin/day_21.rs137
1 files changed, 137 insertions, 0 deletions
diff --git a/2018/src/bin/day_21.rs b/2018/src/bin/day_21.rs
new file mode 100644
index 0000000..0d9a97c
--- /dev/null
+++ b/2018/src/bin/day_21.rs
@@ -0,0 +1,137 @@
+extern crate advent_of_code_2018;
+use advent_of_code_2018::*;
+
+use std::error::Error;
+use std::path::PathBuf;
+use std::u32;
+
+use std::collections::HashMap;
+// cargo watch -cs "cargo run --release --bin day_21"
+
+use std::i32;
+
+#[derive(Debug)]
+struct Instruction {
+ op: Op,
+ a: i32,
+ b: i32,
+ c: i32
+}
+
+impl Instruction {
+ fn execute(&self, counter_register: usize, registers: &mut [i32; 6]) -> i32{
+ use Op::*;
+
+ registers[self.c as usize] = match self.op {
+ Addr => registers[self.a as usize].wrapping_add(registers[self.b as usize]),
+ Addi => registers[self.a as usize].wrapping_add(self.b),
+ Mulr => registers[self.a as usize].wrapping_mul(registers[self.b as usize]),
+ Muli => registers[self.a as usize].wrapping_mul(self.b),
+ Banr => registers[self.a as usize] & registers[self.b as usize],
+ Bani => registers[self.a as usize] & self.b,
+ Borr => registers[self.a as usize] | registers[self.b as usize],
+ Bori => registers[self.a as usize] | self.b,
+ Setr => registers[self.a as usize],
+ Seti => self.a,
+ Gtir => if self.a > registers[self.b as usize] { 1 } else { 0 },
+ Gtri => if registers[self.a as usize] > self.b { 1 } else { 0 },
+ Gtrr => if registers[self.a as usize] > registers[self.b as usize] { 1 } else { 0 },
+ Eqir => if self.a == registers[self.b as usize] { 1 } else { 0 },
+ Eqri => if registers[self.a as usize] == self.b { 1 } else { 0 },
+ Eqrr => if registers[self.a as usize] == registers[self.b as usize] { 1 } else { 0 },
+ };
+
+ registers[counter_register]+1
+ }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+enum Op {
+ Addr,
+ Addi,
+ Mulr,
+ Muli,
+ Banr,
+ Bani,
+ Borr,
+ Bori,
+ Setr,
+ Seti,
+ Gtir,
+ Gtri,
+ Gtrr,
+ Eqir,
+ Eqri,
+ Eqrr
+}
+
+
+fn main() -> Result<(), Box<Error>> {
+ let input = read_file(&PathBuf::from("inputs/21.txt"))?;
+
+ let mut input_iter = input.iter();
+ let counter_register: usize = input_iter.next()
+ .map(|line| line.split_whitespace().nth(1).unwrap().parse().unwrap())
+ .unwrap();
+
+ let instructions: Vec<Instruction> = input_iter
+ .map(|line| {
+ let mut instruction_iter = line.split_whitespace();
+ Instruction {
+ op: match instruction_iter.next().unwrap() {
+ "addr" => Op::Addr,
+ "addi" => Op::Addi,
+ "mulr" => Op::Mulr,
+ "muli" => Op::Muli,
+ "banr" => Op::Banr,
+ "bani" => Op::Bani,
+ "borr" => Op::Borr,
+ "bori" => Op::Bori,
+ "setr" => Op::Setr,
+ "seti" => Op::Seti,
+ "gtir" => Op::Gtir,
+ "gtri" => Op::Gtri,
+ "gtrr" => Op::Gtrr,
+ "eqir" => Op::Eqir,
+ "eqri" => Op::Eqri,
+ "eqrr" => Op::Eqrr,
+ _ => panic!("unknown instruction")
+ },
+ a: instruction_iter.next().unwrap().parse().unwrap(),
+ b: instruction_iter.next().unwrap().parse().unwrap(),
+ c: instruction_iter.next().unwrap().parse().unwrap(),
+ }
+ })
+ .collect();
+
+ execute_program(&instructions, counter_register, [0, 0, 0, 0, 0, 0]);
+
+ Ok(())
+}
+
+fn execute_program(instructions: &Vec<Instruction>, counter_register: usize, registers: [i32; 6]) {
+ let mut instructions_executed: u64 = 0;
+ let mut counter_val: i32 = 0;
+ let mut registers = registers.clone();
+ let mut halting_values = HashMap::new();
+
+ while counter_val >= 0 && counter_val < instructions.len() as i32 {
+ if counter_val == 28 {
+ if halting_values.contains_key(&registers[4]) {
+ break;
+ }
+ halting_values.entry(registers[4]).or_insert(instructions_executed+2);
+ }
+ registers[counter_register] = counter_val;
+ counter_val = instructions[counter_val as usize].execute(counter_register, &mut registers);
+ instructions_executed += 1;
+ }
+
+ let (min_halting, min_halting_time) = halting_values.iter().min_by_key(|&(_, v)| v).unwrap();
+ debug!(min_halting);
+ debug!(min_halting_time);
+ let (max_halting, max_halting_time) = halting_values.iter().max_by_key(|&(_, v)| v).unwrap();
+ debug!(max_halting);
+ debug!(max_halting_time);
+
+}