From 051be932a389b8bc3ea5d4626575454844639066 Mon Sep 17 00:00:00 2001 From: June McEnroe Date: Mon, 27 Nov 2017 17:11:18 -0500 Subject: Move to 2016 directory --- 2016/src/bin/day12.rs | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 2016/src/bin/day12.rs (limited to '2016/src/bin/day12.rs') diff --git a/2016/src/bin/day12.rs b/2016/src/bin/day12.rs new file mode 100644 index 0000000..6655947 --- /dev/null +++ b/2016/src/bin/day12.rs @@ -0,0 +1,143 @@ +use std::io::{self, Read}; +use std::str::FromStr; + +#[derive(Clone, Copy)] +enum Operand { + Register(u8), + Immediate(i32), +} + +impl FromStr for Operand { + type Err = (); + fn from_str(s: &str) -> Result { + match s { + "a" => Ok(Operand::Register(0)), + "b" => Ok(Operand::Register(1)), + "c" => Ok(Operand::Register(2)), + "d" => Ok(Operand::Register(3)), + _ => Ok(Operand::Immediate(s.parse().map_err(|_| ())?)), + } + } +} + +#[derive(Clone, Copy)] +enum Operation { + Cpy(Operand, Operand), + Inc(Operand), + Dec(Operand), + Jnz(Operand, Operand), +} + +impl FromStr for Operation { + type Err = (); + fn from_str(s: &str) -> Result { + let mut iter = s.split(' '); + match iter.next() { + Some("cpy") => { + let src = iter.next().ok_or(())?.parse()?; + let dest = iter.next().ok_or(())?.parse()?; + Ok(Operation::Cpy(src, dest)) + }, + Some("inc") => Ok(Operation::Inc(iter.next().ok_or(())?.parse()?)), + Some("dec") => Ok(Operation::Dec(iter.next().ok_or(())?.parse()?)), + Some("jnz") => { + let cond = iter.next().ok_or(())?.parse()?; + let jump = iter.next().ok_or(())?.parse()?; + Ok(Operation::Jnz(cond, jump)) + }, + _ => Err(()), + } + } +} + +#[derive(Default)] +struct Vm { + registers: [i32; 4], + operations: Vec, + index: i32, +} + +impl FromStr for Vm { + type Err = (); + fn from_str(s: &str) -> Result { + let mut vm = Self::default(); + for line in s.lines() { + vm.operations.push(line.parse()?); + } + Ok(vm) + } +} + +impl Vm { + fn step(&mut self) -> bool { + match self.operations[self.index as usize] { + Operation::Cpy(Operand::Immediate(imm), Operand::Register(reg)) => { + self.registers[reg as usize] = imm; + self.index += 1; + }, + Operation::Cpy(Operand::Register(src), Operand::Register(dest)) => { + self.registers[dest as usize] = self.registers[src as usize]; + self.index += 1; + }, + Operation::Inc(Operand::Register(reg)) => { + self.registers[reg as usize] += 1; + self.index += 1; + }, + Operation::Dec(Operand::Register(reg)) => { + self.registers[reg as usize] -= 1; + self.index += 1; + }, + Operation::Jnz(Operand::Immediate(cond), Operand::Immediate(jump)) => { + if cond != 0 { + self.index += jump; + } else { + self.index += 1; + } + }, + Operation::Jnz(Operand::Register(reg), Operand::Immediate(jump)) => { + if self.registers[reg as usize] != 0 { + self.index += jump; + } else { + self.index += 1; + } + }, + _ => panic!("invalid operation"), + } + + (self.index as usize) < self.operations.len() + } +} + +fn solve1(input: &str) -> i32 { + let mut vm: Vm = input.parse().unwrap(); + while vm.step() { } + vm.registers[0] +} + +fn solve2(input: &str) -> i32 { + let mut vm: Vm = input.parse().unwrap(); + vm.registers[2] = 1; + while vm.step() { } + vm.registers[0] +} + +fn main() { + let mut input = String::new(); + io::stdin().read_to_string(&mut input).unwrap(); + + println!("Part 1: {}", solve1(&input)); + println!("Part 2: {}", solve2(&input)); +} + +#[test] +fn part1() { + let input = " +cpy 41 a +inc a +inc a +dec a +jnz a 2 +dec a +"; + assert_eq!(42, solve1(input.trim())); +} -- cgit 1.4.1