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

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

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

Резултати

  • 14 точки от тестове
  • 0 бонус точки
  • 14 точки общо
  • 11 успешни тест(а)
  • 1 неуспешни тест(а)

Код

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RuntimeError {
DivideByZero,
StackUnderflow,
InvalidCommand,
NoInstructions,
}
use std::collections::VecDeque;
#[derive(Debug, Default)]
pub struct Interpreter {
pub instructions: VecDeque<String>,
pub stack: Vec<i32>,
finished_instructions: Vec<String>,
reverce_numbers: Vec<i32>,
}
impl Interpreter {
pub fn new() -> Self {
Interpreter {
instructions: VecDeque::<String>::new(),
stack: Vec::<i32>::new(),
finished_instructions: Vec::<String>::new(),
reverce_numbers: Vec::<i32>::new(),
}
}
pub fn add_instructions(&mut self, instructions: &[&str]) {
for instruction in instructions {
self.instructions.push_back(instruction.to_string())
}
}
pub fn current_instruction(&mut self) -> Option<&mut String> {
self.instructions.front_mut()
}
pub fn forward(&mut self) -> Result<(), RuntimeError> {
if self.instructions.is_empty() {
return Err(RuntimeError::NoInstructions);
}
let instruction = self.instructions.front().unwrap();
let split_instruction: Vec<&str> = instruction.split_whitespace().collect();
let instruction_size = split_instruction.len();
if instruction_size > 2 {
return Err(RuntimeError::InvalidCommand);
} else if instruction_size == 2 {
let value = match split_instruction[1].parse::<i32>() {
Ok(number) => number,
Err(_) => return Err(RuntimeError::InvalidCommand),
};
match split_instruction[0] {
"PUSH" => self.stack.push(value),
_ => return Err(RuntimeError::InvalidCommand),
}
} else {
match split_instruction[0] {
"POP" => match self.stack.pop() {
Some(_) => (),
None => return Err(RuntimeError::StackUnderflow),
},
"ADD" => {
if self.stack.len() < 2 {
return Err(RuntimeError::StackUnderflow);
}
let first = self.stack.pop().unwrap();
let second = self.stack.pop().unwrap();
self.reverce_numbers.push(first);
self.reverce_numbers.push(second);
self.stack.push(first + second);
}
"MUL" => {
if self.stack.len() < 2 {
return Err(RuntimeError::StackUnderflow);
}
let first = self.stack.pop().unwrap();
let second = self.stack.pop().unwrap();
self.stack.push(first * second);
}
"SUB" => {
if self.stack.len() < 2 {
return Err(RuntimeError::StackUnderflow);
}
let first = self.stack.pop().unwrap();
let second = self.stack.pop().unwrap();
self.reverce_numbers.push(first);
self.reverce_numbers.push(second);
self.stack.push(first - second);
}
"DIV" => {
if self.stack.len() < 2 {
return Err(RuntimeError::StackUnderflow);
}
let first = self.stack.pop().unwrap();
let second = self.stack.pop().unwrap();
if second == 0 {
return Err(RuntimeError::DivideByZero);
}
self.reverce_numbers.push(first);
self.reverce_numbers.push(second);
self.stack.push(first / second);
}
_ => return Err(RuntimeError::InvalidCommand),
}
}
self.finished_instructions
.push(self.instructions.pop_front().unwrap());
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> {
if self.finished_instructions.is_empty() {
return Err(RuntimeError::NoInstructions);
}
let instruction = self.finished_instructions.pop().unwrap();
let split_instruction: Vec<&str> = instruction.split_whitespace().collect();
let instruction_size = split_instruction.len();
if instruction_size == 2 {
self.stack.pop();
} else {
match split_instruction[0] {
"POP" => self.stack.push(self.reverce_numbers.pop().unwrap()),
"ADD" => {
self.stack.pop();
self.stack.push(self.reverce_numbers.pop().unwrap());
self.stack.push(self.reverce_numbers.pop().unwrap());
}
"MUL" => {
self.stack.pop();
self.stack.push(self.reverce_numbers.pop().unwrap());
self.stack.push(self.reverce_numbers.pop().unwrap());
}
"SUB" => {
self.stack.pop();
self.stack.push(self.reverce_numbers.pop().unwrap());
self.stack.push(self.reverce_numbers.pop().unwrap());
}
"DIV" => {
self.stack.pop();
self.stack.push(self.reverce_numbers.pop().unwrap());
self.stack.push(self.reverce_numbers.pop().unwrap());
}
_ => return Err(RuntimeError::InvalidCommand),
}
}
self.instructions.push_front(instruction);
Ok(())
}
}

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

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

running 12 tests
test solution_test::test_arg_number ... ok
test solution_test::test_arithmetic_back ... FAILED
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

failures:

---- solution_test::test_arithmetic_back stdout ----
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `[1, 2]`,
 right: `[3, 3]`', tests/solution_test.rs:113:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    solution_test::test_arithmetic_back

test result: FAILED. 11 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test solution_test'

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

Георги качи първо решение на 20.01.2021 13:41 (преди над 4 години)