Решение на Reversible Interpreter от Иван Иванов

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

Към профила на Иван Иванов

Резултати

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

Код

use std::collections::VecDeque;
const PUSH : &str= "PUSH";
const POP : &str= "POP";
const ADD : &str= "ADD";
const MUL : &str= "MUL";
const SUB : &str= "SUB";
const DIV : &str= "DIV";
const MAX_COMMAND_PARTS: usize = 2;
const MIN_COMMAND_PARTS: usize = 1;
const COMMANDS: [&'static str; 6] = [PUSH,POP,ADD,MUL,SUB,DIV];
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RuntimeError {
DivideByZero,
StackUnderflow,
InvalidCommand,
NoInstructions,
}
#[derive(Debug, Default)]
pub struct Interpreter {
pub instructions: VecDeque<String>,
pub stack: Vec<i32>,
pub reverse_stack: Vec<String>,
pub reverse_instructions: Vec<Vec<String>>,
}
impl Interpreter {
pub fn new() -> Self {
let instructions: VecDeque<String> = VecDeque::new();
let stack: Vec<i32> = Vec::new();
let reverse_stack: Vec<String> = Vec::new();
let reverse_instructions: Vec<Vec<String>> = Vec::new();
return Interpreter {
instructions,
stack,
reverse_stack,
reverse_instructions
}
}
pub fn add_instructions(&mut self, instructions: &[&str]) {
for instruction in instructions {
self.instructions.push_back(String::from(*instruction));
}
}
pub fn current_instruction(&mut self) -> Option<&mut String> {
return 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 instruction_clone = instruction.clone();
let instruction_parts: Vec<&str> = instruction.split_whitespace().collect();
if instruction_parts.is_empty(){
return Err(RuntimeError::InvalidCommand);
}
let instruction_parts_count = instruction_parts.iter().count();
let instruction_part_one = instruction_parts.iter().nth(0);
if instruction_part_one.is_none(){
return Err(RuntimeError::InvalidCommand);
}
let instruction_part_one_unwraped = instruction_part_one.unwrap();
if instruction_parts_count > MAX_COMMAND_PARTS ||!COMMANDS.contains(instruction_part_one_unwraped) || (&PUSH != instruction_part_one_unwraped && instruction_parts_count > MIN_COMMAND_PARTS) || (&PUSH == instruction_part_one_unwraped && instruction_parts_count != MAX_COMMAND_PARTS) {
return Err(RuntimeError::InvalidCommand);
}
if instruction_part_one_unwraped == &PUSH {
let second_argument = instruction_parts.iter().nth(1).unwrap().parse::<i32>();
if second_argument.is_err(){
return Err(RuntimeError::InvalidCommand);
}
self.stack.push(second_argument.unwrap());
self.instructions.pop_front();
let mut vector_of_reverse_instructions = Vec::new();
vector_of_reverse_instructions.push(POP.to_string());
self.reverse_instructions.push(vector_of_reverse_instructions);
} else if instruction_part_one_unwraped == &POP {
let popped = self.stack.pop();
if popped == None{
return Err(RuntimeError::StackUnderflow);
}
self.instructions.pop_front();
let mut vector_of_reverse_instructions = Vec::new();
let instruction_string = PUSH.to_owned()+ " " + &popped.unwrap().to_string();
vector_of_reverse_instructions.push(instruction_string);
self.reverse_instructions.push(vector_of_reverse_instructions);
} else if instruction_part_one_unwraped == &ADD {
let result = self.execute_binary_operation(&|a,b|{a+b});
if result.is_err(){
return result;
}
} else if instruction_part_one_unwraped == &SUB {
let result = self.execute_binary_operation(&|a,b|{a-b});
if result.is_err(){
return result;
}
} else if instruction_part_one_unwraped == &MUL {
let result = self.execute_binary_operation(&|a,b|{a*b});
if result.is_err(){
return result;
}
} else if instruction_part_one_unwraped == &DIV {
let first = self.stack.pop();
let second = self.stack.pop();
if first == None && second == None{
return Err(RuntimeError::StackUnderflow);
}
if first == None && second != None{
self.stack.push(second.unwrap());
return Err(RuntimeError::StackUnderflow);
}
if first != None && second == None{
self.stack.push(first.unwrap());
return Err(RuntimeError::StackUnderflow);
}
if second.unwrap()==0{
self.stack.push(second.unwrap());
self.stack.push(first.unwrap());
return Err(RuntimeError::DivideByZero);
}
self.stack.push(first.unwrap()/second.unwrap());
self.instructions.pop_front();
let mut vector_of_reverse_instructions = Vec::new();
let instruction_string_one = PUSH.to_owned()+ " " + &first.unwrap().to_string();
let instruction_string_two = PUSH.to_owned()+ " " + &second.unwrap().to_string();
vector_of_reverse_instructions.push(POP.to_string());
vector_of_reverse_instructions.push(instruction_string_two);
vector_of_reverse_instructions.push(instruction_string_one);
self.reverse_instructions.push(vector_of_reverse_instructions);
}
self.reverse_stack.push(instruction_clone.to_string());
Ok(())
}
fn forward_for_back(&mut self) -> Result<(), RuntimeError> {
if self.instructions.is_empty(){
return Err(RuntimeError::NoInstructions);
}
let instruction = self.instructions.front().unwrap();
let instruction_parts: Vec<&str> = instruction.split_whitespace().collect();
if instruction_parts.is_empty(){
return Err(RuntimeError::InvalidCommand);
}
let instruction_parts_count = instruction_parts.iter().count();
let instruction_part_one = instruction_parts.iter().nth(0);
if instruction_part_one.is_none(){
return Err(RuntimeError::InvalidCommand);
}
let instruction_part_one_unwraped = instruction_part_one.unwrap();
if instruction_parts_count > MAX_COMMAND_PARTS ||!COMMANDS.contains(instruction_part_one_unwraped) || (&PUSH != instruction_part_one_unwraped && instruction_parts_count > MIN_COMMAND_PARTS) || (&PUSH == instruction_part_one_unwraped && instruction_parts_count != MAX_COMMAND_PARTS) {
return Err(RuntimeError::InvalidCommand);
}
if instruction_part_one_unwraped == &PUSH {
let second_argument = instruction_parts.iter().nth(1).unwrap().parse::<i32>();
if second_argument.is_err(){
return Err(RuntimeError::InvalidCommand);
}
self.stack.push(second_argument.unwrap());
self.instructions.pop_front();
} else if instruction_part_one_unwraped == &POP {
let popped = self.stack.pop();
if popped == None{
return Err(RuntimeError::StackUnderflow);
}
self.instructions.pop_front();
} else if instruction_part_one_unwraped == &ADD {
let result = self.execute_binary_operation_for_back(&|a,b|{a+b});
if result.is_err(){
return result;
}
} else if instruction_part_one_unwraped == &SUB {
let result = self.execute_binary_operation_for_back(&|a,b|{a-b});
if result.is_err(){
return result;
}
} else if instruction_part_one_unwraped == &MUL {
let result = self.execute_binary_operation_for_back(&|a,b|{a*b});
if result.is_err(){
return result;
}
} else if instruction_part_one_unwraped == &DIV {
let first = self.stack.pop();
let second = self.stack.pop();
if first == None && second == None{
return Err(RuntimeError::StackUnderflow);
}
if first == None && second != None{
self.stack.push(second.unwrap());
return Err(RuntimeError::StackUnderflow);
}
if first != None && second == None{
self.stack.push(first.unwrap());
return Err(RuntimeError::StackUnderflow);
}
if second.unwrap()==0{
self.stack.push(second.unwrap());
self.stack.push(first.unwrap());
return Err(RuntimeError::DivideByZero);
}
self.stack.push(first.unwrap()/second.unwrap());
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> {
if self.reverse_stack.is_empty() || self.reverse_instructions.is_empty(){
return Err(RuntimeError::NoInstructions);
}
let last_reverse_command_as_string = self.reverse_stack.pop().unwrap();
let last_reverse_instruction_as_string = self.reverse_instructions.pop().unwrap();
for instruction in last_reverse_instruction_as_string.iter(){
self.instructions.push_front(instruction.to_string());
let result = self.forward_for_back();
if result.is_err(){
return result;
}
}
self.instructions.push_front(last_reverse_command_as_string);
return Ok(());
}
fn execute_binary_operation(&mut self,f: &dyn Fn(i32,i32) -> i32) -> Result<(), RuntimeError> {
let first = self.stack.pop();
let second = self.stack.pop();
if first == None && second == None{
return Err(RuntimeError::StackUnderflow);
}
if first == None && second != None{
self.stack.push(second.unwrap());
return Err(RuntimeError::StackUnderflow);
}
if first != None && second == None{
self.stack.push(first.unwrap());
return Err(RuntimeError::StackUnderflow);
}
self.stack.push(f(first.unwrap(), second.unwrap()));
self.instructions.pop_front();
let mut vector_of_reverse_instructions = Vec::new();
let instruction_string_one = PUSH.to_owned()+ " " + &first.unwrap().to_string();
let instruction_string_two = PUSH.to_owned()+ " " + &second.unwrap().to_string();
vector_of_reverse_instructions.push(POP.to_string());
vector_of_reverse_instructions.push(instruction_string_two);
vector_of_reverse_instructions.push(instruction_string_one);
self.reverse_instructions.push(vector_of_reverse_instructions);
return Ok(());
}
fn execute_binary_operation_for_back(&mut self,f: &dyn Fn(i32,i32) -> i32) -> Result<(), RuntimeError> {
let first = self.stack.pop();
let second = self.stack.pop();
if first == None && second == None{
return Err(RuntimeError::StackUnderflow);
}
if first == None && second != None{
self.stack.push(second.unwrap());
return Err(RuntimeError::StackUnderflow);
}
if first != None && second == None{
self.stack.push(first.unwrap());
return Err(RuntimeError::StackUnderflow);
}
self.stack.push(f(first.unwrap(), second.unwrap()));
self.instructions.pop_front();
return Ok(());
}
}

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

Compiling solution v0.1.0 (/tmp/d20210120-1538662-1e7y796/solution)
    Finished test [unoptimized + debuginfo] target(s) in 2.64s
     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 коментара)

Иван качи първо решение на 19.01.2021 23:14 (преди над 4 години)