From 2ee1c8779d964cdd1a82dbba04dc773882a1212b Mon Sep 17 00:00:00 2001 From: kageru Date: Fri, 13 Dec 2019 10:20:29 +0100 Subject: [PATCH] Add command buffer to intcode computer --- 2019/intcode/src/intcomputer.rs | 54 ++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/2019/intcode/src/intcomputer.rs b/2019/intcode/src/intcomputer.rs index 2f55867..425fc44 100644 --- a/2019/intcode/src/intcomputer.rs +++ b/2019/intcode/src/intcomputer.rs @@ -3,6 +3,7 @@ pub struct IntComputer { pub tape: Vec, pub params: Vec, relative_base: i64, + cmd_buffer: Vec, } pub enum IntComputerResult { @@ -26,18 +27,19 @@ impl IntComputer { tape, params, relative_base: 0, + cmd_buffer: Vec::new(), } } pub fn run(&mut self) -> IntComputerResult { loop { - match self.decode_next() { - Some(op) => { - if let Some(o) = self.execute(op) { + match self.cmd_buffer.pop().unwrap_or_else(|| self.decode_next()) { + Operation::Halt {} => return IntComputerResult::Halt, + op => { + if let Some(o) = self.execute(op.to_owned()) { return IntComputerResult::Output(o); } } - None => return IntComputerResult::Halt, } } } @@ -73,7 +75,7 @@ impl IntComputer { value } - fn decode_next(&mut self) -> Option { + fn decode_next(&mut self) -> Operation { let next = self.get_next(Mode::Immediate); let mut full_opcode: Vec<_> = next.to_string().chars().collect(); full_opcode.reverse(); @@ -82,50 +84,50 @@ impl IntComputer { full_opcode[0], ]; match raw_opcode { - ['0', '1'] => Some(Operation::Add { + ['0', '1'] => Operation::Add { x: self.get_next(get_mode(&full_opcode, ParameterPosition::First)), y: self.get_next(get_mode(&full_opcode, ParameterPosition::Second)), addr: self.get_next_address(get_mode(&full_opcode, ParameterPosition::Third)) as usize, - }), - ['0', '2'] => Some(Operation::Multiply { + }, + ['0', '2'] => Operation::Multiply { x: self.get_next(get_mode(&full_opcode, ParameterPosition::First)), y: self.get_next(get_mode(&full_opcode, ParameterPosition::Second)), addr: self.get_next_address(get_mode(&full_opcode, ParameterPosition::Third)) as usize, - }), - ['0', '3'] => Some(Operation::Input { + }, + ['0', '3'] => Operation::Input { value: self.params.pop().unwrap(), addr: self.get_next_address(get_mode(&full_opcode, ParameterPosition::First)) as usize, - }), - ['0', '4'] => Some(Operation::Output { + }, + ['0', '4'] => Operation::Output { value: self.get_next(get_mode(&full_opcode, ParameterPosition::First)), - }), - ['0', '5'] => Some(Operation::JumpIfTrue { + }, + ['0', '5'] => Operation::JumpIfTrue { value: self.get_next(get_mode(&full_opcode, ParameterPosition::First)), addr: self.get_next(get_mode(&full_opcode, ParameterPosition::Second)) as usize, - }), - ['0', '6'] => Some(Operation::JumpIfFalse { + }, + ['0', '6'] => Operation::JumpIfFalse { value: self.get_next(get_mode(&full_opcode, ParameterPosition::First)), addr: self.get_next(get_mode(&full_opcode, ParameterPosition::Second)) as usize, - }), - ['0', '7'] => Some(Operation::LessThan { + }, + ['0', '7'] => Operation::LessThan { first: self.get_next(get_mode(&full_opcode, ParameterPosition::First)), second: self.get_next(get_mode(&full_opcode, ParameterPosition::Second)), addr: self.get_next_address(get_mode(&full_opcode, ParameterPosition::Third)) as usize, - }), - ['0', '8'] => Some(Operation::Equals { + }, + ['0', '8'] => Operation::Equals { first: self.get_next(get_mode(&full_opcode, ParameterPosition::First)), second: self.get_next(get_mode(&full_opcode, ParameterPosition::Second)), addr: self.get_next_address(get_mode(&full_opcode, ParameterPosition::Third)) as usize, - }), - ['0', '9'] => Some(Operation::AdjustRelativeBase { + }, + ['0', '9'] => Operation::AdjustRelativeBase { value: self.get_next(get_mode(&full_opcode, ParameterPosition::First)), - }), - ['9', '9'] => None, + }, + ['9', '9'] => Operation::Halt {}, _ => unreachable!("Unknown opcode"), } } @@ -165,6 +167,7 @@ impl IntComputer { Operation::Output { value } => { return Some(value); } + Operation::Halt {} => unreachable!(), }; None } @@ -175,7 +178,7 @@ fn get_mode(raw_opcode: &[char], pos: ParameterPosition) -> Mode { raw_opcode.get::(pos.into()).unwrap_or(&'0').into() } -#[derive(Debug)] +#[derive(Debug, Clone)] enum Operation { Add { x: i64, @@ -215,6 +218,7 @@ enum Operation { AdjustRelativeBase { value: i64, }, + Halt {}, } #[derive(Debug)]