From 6c4bb78c98d44d7853e801782aa257016db22fd0 Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Thu, 5 Jan 2017 08:25:20 -0800 Subject: [PATCH] [2016][rust][12.1] Use a vec instead of hashmap for moar speed --- 2016/rust/src/assembunny.rs | 76 ++++++++++++++++++++++++++----------- 2016/rust/src/day_12.rs | 5 ++- 2 files changed, 56 insertions(+), 25 deletions(-) diff --git a/2016/rust/src/assembunny.rs b/2016/rust/src/assembunny.rs index 0013bb3..bf6d680 100644 --- a/2016/rust/src/assembunny.rs +++ b/2016/rust/src/assembunny.rs @@ -1,10 +1,10 @@ -use std::collections::HashMap; +use std::ops; use std::str; use errors::*; pub struct Assembunny { - pub registers: HashMap, + pub registers: Registers, pub instructions: Instructions, } @@ -12,17 +12,16 @@ impl Assembunny { fn value>(&self, v: V) -> isize { let v: Variable = v.into(); match v { - Variable::Register(r) => { - self.registers.get(&r).cloned().unwrap_or(0) - } + Variable::Register(r) => self.registers[r], Variable::Value(i) => i, } } } impl Iterator for Assembunny { - type Item = HashMap; - fn next(&mut self) -> Option> { + type Item = Registers; + + fn next(&mut self) -> Option { let pc = self.value(Register::PC) as usize; let instruction = match self.instructions.0.get(pc) { Some(i) => i, @@ -34,21 +33,21 @@ impl Iterator for Assembunny { match *instruction { Instruction::Cpy(v, r) => { let value = self.value(v); - self.registers.insert(r, value); - *self.registers.entry(Register::PC).or_insert(0) += 1; + self.registers[r] = value; + self.registers[Register::PC] += 1; } Instruction::Inc(r) => { - *self.registers.entry(r).or_insert(0) += 1; - *self.registers.entry(Register::PC).or_insert(0) += 1; + self.registers[r] += 1; + self.registers[Register::PC] += 1; } Instruction::Dec(r) => { - *self.registers.entry(r).or_insert(0) -= 1; - *self.registers.entry(Register::PC).or_insert(0) += 1; + self.registers[r] -= 1; + self.registers[Register::PC] += 1; } Instruction::Jnz(v, i) => { let delta = if self.value(v) == 0 { 1 } else { i }; let pc = self.value(Register::PC) + delta; - self.registers.insert(Register::PC, pc); + self.registers[Register::PC] = pc; } } @@ -56,8 +55,39 @@ impl Iterator for Assembunny { } } +#[derive(Clone)] +pub struct Registers(Vec); pub struct Instructions(Vec); +impl Registers { + pub fn new() -> Self { + Registers(vec![0; 5]) + } + + fn index(r: Register) -> usize { + match r { + Register::PC => 0, + Register::A => 1, + Register::B => 2, + Register::C => 3, + Register::D => 4, + } + } +} + +impl ops::Index for Registers { + type Output = isize; + + fn index(&self, _index: Register) -> &isize { + self.0.index(Self::index(_index)) + } +} +impl ops::IndexMut for Registers { + fn index_mut(&mut self, _index: Register) -> &mut isize { + self.0.index_mut(Self::index(_index)) + } +} + #[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] pub enum Register { PC, @@ -179,8 +209,8 @@ impl<'a> SplitWhitespaceExt for str::SplitWhitespace<'a> { #[cfg(test)] mod tests { - use super::{Assembunny, Instructions, Instruction, Register, Variable}; - use std::collections::HashMap; + use super::*; + use super::{Instruction, Variable}; use std::str::FromStr; #[test] @@ -194,21 +224,21 @@ dec a" .parse() .unwrap(); let mut assembunny = Assembunny { - registers: HashMap::new(), + registers: Registers::new(), instructions: instructions, }; let registers = assembunny.next().unwrap(); - assert_eq!(registers.get(&Register::A), Some(&41)); - assert_eq!(registers.get(&Register::B), None); + assert_eq!(registers[Register::A], 41); + assert_eq!(registers[Register::B], 0); let registers = assembunny.next().unwrap(); - assert_eq!(registers.get(&Register::A), Some(&42)); - assert_eq!(registers.get(&Register::C), None); + assert_eq!(registers[Register::A], 42); + assert_eq!(registers[Register::C], 0); let registers = assembunny.last().unwrap(); - assert_eq!(registers.get(&Register::A), Some(&42)); - assert_eq!(registers.get(&Register::PC), Some(&6)); + assert_eq!(registers[Register::A], 42); + assert_eq!(registers[Register::PC], 6); } #[test] diff --git a/2016/rust/src/day_12.rs b/2016/rust/src/day_12.rs index 080ab4d..372c58b 100644 --- a/2016/rust/src/day_12.rs +++ b/2016/rust/src/day_12.rs @@ -3,10 +3,11 @@ use errors::*; pub fn solve(input: &str) -> Result { let instructions: Instructions = input.parse()?; - let registers = vec![(Register::C, 1)].into_iter().collect(); + let mut registers = Registers::new(); + registers[Register::C] = 1; let assembunny = Assembunny{registers: registers, instructions: instructions}; let registers = assembunny.last().ok_or("")?; - let a = registers.get(&Register::A).ok_or("")?; + let a = registers[Register::A]; Ok(a.to_string()) }