Решение на Reversible Interpreter от Георги Гергинов

Обратно към всички решения

Към профила на Георги Гергинов

Резултати

  • 15 точки от тестове
  • 0 бонус точки
  • 15 точки общо
  • 12 успешни тест(а)
  • 0 неуспешни тест(а)

Код

use std::collections::VecDeque;
#[derive(Debug, Default)]
pub struct Interpreter {
pub instructions: VecDeque<String>,
pub stack: Vec<i32>,
reversed_destructured_instructions: Vec<(String, Option<i32>)>,
reversed_stack: Vec<i32>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RuntimeError {
DivideByZero,
StackUnderflow,
InvalidCommand,
NoInstructions,
}
impl Interpreter {
pub fn new() -> Self {
Interpreter {
instructions: VecDeque::<String>::new(),
stack: Vec::<i32>::new(),
reversed_destructured_instructions: Vec::<(String, Option<i32>)>::new(),
reversed_stack: Vec::<i32>::new(),
}
}
pub fn add_instructions(&mut self, instructions: &[&str]) {
for s in instructions {
self.instructions.push_back(s.to_string())
}
}
pub fn current_instruction(&mut self) -> Option<&mut String> {
self.instructions.front_mut()
}
pub fn forward(&mut self) -> Result<(), RuntimeError> {
let curr_instruction = match self.instructions.front() {
None => return Err(RuntimeError::NoInstructions),
Some(s) => s,
};
let split_instruction = curr_instruction.trim().split_whitespace().collect::<Vec<_>>();
let destr_instruction: (&str, Option::<i32>);
match split_instruction.len() {
1 => match *split_instruction.first().unwrap() {
"PUSH" => return Err(RuntimeError::InvalidCommand),
"POP" | "ADD" | "MUL" | "SUB" | "DIV" => destr_instruction = (*split_instruction.first().unwrap(), None),
_ => return Err(RuntimeError::InvalidCommand),
},
2 => match *split_instruction.first().unwrap() {
"PUSH" => match (*split_instruction.last().unwrap()).parse::<i32>() {
Err(_) => return Err(RuntimeError::InvalidCommand),
Ok(i) => destr_instruction = (*split_instruction.first().unwrap(), Some(i)),
},
"POP" | "ADD" | "MUL" | "SUB" | "DIV" => return Err(RuntimeError::InvalidCommand),
_ => return Err(RuntimeError::InvalidCommand),
}
_ => return Err(RuntimeError::InvalidCommand),
}
match destr_instruction {
("PUSH", Some(i)) => {
self.stack.push(i);
},
("POP", None) => if self.stack.is_empty() {
return Err(RuntimeError::StackUnderflow);
} else {
self.reversed_stack.push(self.stack.pop().unwrap());
},
("ADD", None) => if self.stack.len() < 2 {
return Err(RuntimeError::StackUnderflow);
} else {
let addend1 = self.stack.pop().unwrap();
let addend2 = self.stack.pop().unwrap();
self.stack.push(addend1 + addend2);
self.reversed_stack.push(addend1);
self.reversed_stack.push(addend2);
},
("MUL", None) => if self.stack.len() < 2 {
return Err(RuntimeError::StackUnderflow);
} else {
let factor1 = self.stack.pop().unwrap();
let factor2 = self.stack.pop().unwrap();
self.stack.push(factor1 * factor2);
self.reversed_stack.push(factor1);
self.reversed_stack.push(factor2);
},
("SUB", None) => if self.stack.len() < 2 {
return Err(RuntimeError::StackUnderflow);
} else {
let minuend = self.stack.pop().unwrap();
let subtrahend = self.stack.pop().unwrap();
self.stack.push(minuend - subtrahend);
self.reversed_stack.push(minuend);
self.reversed_stack.push(subtrahend);
},
("DIV", None) => if self.stack.len() < 2 {
return Err(RuntimeError::StackUnderflow);
} else {
let dividend = self.stack.pop().unwrap();
if let Some(0) = self.stack.last() {
self.stack.push(dividend);
return Err(RuntimeError::DivideByZero);
}
let divisor = self.stack.pop().unwrap();
self.stack.push(dividend / divisor);
self.reversed_stack.push(dividend);
self.reversed_stack.push(divisor);
},
_ => return Err(RuntimeError::InvalidCommand),
}
self.reversed_destructured_instructions.push((destr_instruction.0.to_string(), destr_instruction.1));
self.instructions.pop_front();
Ok(())
}
pub fn run(&mut self) -> Result<(), RuntimeError> {
loop {
match self.forward() {
Err(RuntimeError::NoInstructions) => return Ok(()),
Err(e) => return Err(e),
_ => (),
}
}
}
pub fn back(&mut self) -> Result<(), RuntimeError> {
self.instructions.push_front(
match self.reversed_destructured_instructions.pop() {
None => return Err(RuntimeError::NoInstructions),
Some(s) => {
match s.0.as_str() {
"PUSH" => {
self.stack.pop();
let mut structured = s.0.clone();
structured.push(' ');
structured.push_str(&s.1.unwrap().to_string());
structured
},
"POP" => {
self.stack.push(self.reversed_stack.pop().unwrap());
s.0.to_string()
},
"ADD" | "MUL" | "SUB" | "DIV" => {
self.stack.pop();
self.stack.push(self.reversed_stack.pop().unwrap());
self.stack.push(self.reversed_stack.pop().unwrap());
s.0.to_string()
},
_ => return Err(RuntimeError::InvalidCommand),
}
},
}
);
Ok(())
}
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20210120-1538662-ptl8qr/solution)
    Finished test [unoptimized + debuginfo] target(s) in 2.88s
     Running target/debug/deps/solution_test-8916805fc40a2dab

running 12 tests
test solution_test::test_arg_number ... ok
test solution_test::test_arithmetic_back ... ok
test solution_test::test_arithmetic_basic ... ok
test solution_test::test_div_1 ... ok
test solution_test::test_div_2 ... ok
test solution_test::test_errors_1 ... ok
test solution_test::test_errors_2 ... ok
test solution_test::test_instructions_after_error ... ok
test solution_test::test_invalid_args ... ok
test solution_test::test_pop ... ok
test solution_test::test_push ... ok
test solution_test::test_restoring_instructions ... ok

test result: ok. 12 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

История (1 версия и 0 коментара)

Георги качи първо решение на 20.01.2021 16:03 (преди 6 месеца)