Решение на Forth от Ива Милушева

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

Към профила на Ива Милушева

Резултати

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

Код

use std::str;
use std::iter::Iterator;
use std::collections::HashMap;
/// Грешки, които могат да се срещнат по време на изпълнение на програмата
///
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RuntimeError {
DivideByZero,
StackUnderflow,
UnknownWord,
}
#[derive(Debug, Clone)]
pub struct Data {
item: String,
op_type: String
}
impl Data {
pub fn new(item: String, op_type: String) -> Self {
Data { item: item, op_type: op_type }
}
}
#[derive(Debug)]
pub struct ResultData {
item: i32,
count: i32
}
impl ResultData {
pub fn new(item: i32, count: i32) -> Self {
ResultData { item: item, count: count }
}
}
#[derive(Debug)]
pub struct Interpreter {
all_data: Vec<Data>,
variables: HashMap<String, i32>,
iterated: Vec<i32>,
}
impl Interpreter {
/// Създава нов интерпретатор
///
pub fn new() -> Self {
Interpreter {
all_data: vec![],
variables: HashMap::new(),
iterated: vec![]
}
}
/// Дефинира нова дума за променлива.
///
/// При срещане на думата `name` се добавя стойността `val`
/// на върха на стека.
///
pub fn def_var(&mut self, name: &str, val: i32) {
let variable = name.to_string();
&self.variables.insert(variable, val);
}
/// Дефинира нова дума за едноместен оператор
///
/// При срещане на думата `name` се изважда най-горният елемент
/// от стека, изпълнява се `op` и резултатът се добавя в стека.
///
pub fn def_unary_op<F>(&mut self, name: &str, op: F)
where
F: Fn(i32) -> i32 + 'static,
{
//&self.unary_operators.insert(name.to_string(), foo);
unimplemented!()
}
/// Дефинира нова дума за едноместен оператор
///
/// При срещане на думата `name` се изваждат най-горните два елемента
/// от стека, изпълнява се `op` и резултатът се добавя в стека.
///
pub fn def_binary_op<F>(&mut self, _name: &str, _op: F)
where
F: Fn(i32, i32) -> i32 + 'static,
{
unimplemented!()
}
/// Връща итератор по текущото съдържание на стека.
///
/// Първият елемент на итератора е върха на стека.
///
pub fn stack<'a>(&'a self) -> impl Iterator<Item = i32> + 'a {
let q: &i32 = self.iterated.iter().next().unwrap();
let r: i32 = *q;
Some(r).into_iter()
}
/// Изпълнява програмата `input` в този интерпретатор.
///
/// Ако програмата се изпълни успрешно се връща `Ok(top)`, където
/// `top` е елемента на върха на стека, или `None` ако стекът е празен.
///
/// Ако по време на изпълнението се срещне грешка се връща `Err`.
///
pub fn run(&mut self, input: &str) -> Result<Option<i32>, RuntimeError> {
let data = parse_string(input.to_string());
let mut current_data = vec![];
for x in &data {
match x.to_string().parse::<i32>() {
Ok(_) => {
&self.all_data.push(Data::new(x.to_string(), "number".to_string()));
current_data.push(Data::new(x.to_string(), "number".to_string()));
()
},
Err(_) => {
&self.all_data.push(Data::new(x.to_string(), "operator".to_string()));
current_data.push(Data::new(x.to_string(), "operator".to_string()));
()
},
}
};
let v = &self.all_data.clone();
let mut q: Vec<String> = v.iter()
.filter(|x| {
x.op_type != "operator"
})
.map(|val| {
let test = val.clone();
test.item
})
.collect();
q.reverse();
let res: Vec<i32> = q.iter()
.map(|val| {
let test = val.parse::<i32>();
test.unwrap()
})
.collect();
self.iterated = res;
let res = calculate_primary(current_data);
if res.is_ok() {
let z: ResultData = res.unwrap().unwrap();
let zero_vec = vec![0; z.count as usize];
for _x in zero_vec {
&self.all_data.pop();
}
&self.all_data.push(Data::new(z.item.to_string(), "number".to_string()));
return Ok(Some(z.item));
}
else {
let z: RuntimeError = res.unwrap_err();
return Err(z);
}
}
pub fn print(&mut self) {
for x in &self.all_data {
print!("{:?} ", x);
}
println!("");
}
}
fn parse_string(s: String) -> Vec<String> {
let trimed = s.trim();
let non_empty_ref = &trimed;
let result: Vec<&str> = non_empty_ref.split_terminator(' ').collect();
let filtered = result.iter()
.map(|&x| x.to_string())
.filter(|x| x != "")
.collect::<Vec<String>>();
filtered
}
fn calculate_primary(mut data: Vec<Data>) -> Result<Option<ResultData>, RuntimeError> {
if data.len() == 0 {
return Err(RuntimeError::StackUnderflow);
}
let last = data.pop().unwrap();
if last.op_type == "operator" {
let res: i32;
let count: i32;
if last.item == "ADD" {
let first = data.pop().unwrap().item.parse::<i32>().unwrap();
let second = data.pop().unwrap().item.parse::<i32>().unwrap();
res = first + second;
count = 3;
}
else if last.item == "SUB" {
let first = data.pop().unwrap().item.parse::<i32>().unwrap();
let second = data.pop().unwrap().item.parse::<i32>().unwrap();
res = first - second;
count = 3;
}
else if last.item == "MUL" {
let first = data.pop().unwrap().item.parse::<i32>().unwrap();
let second = data.pop().unwrap().item.parse::<i32>().unwrap();
res = first * second;
count = 3;
}
else if last.item == "DIV" {
let first = data.pop().unwrap().item.parse::<i32>().unwrap();
let second = data.pop().unwrap().item.parse::<i32>().unwrap();
res = first * second;
// TODO: / 0
count = 3;
}
else {
res = 0;
count = 0;
};
let returned_data = ResultData::new(res, count);
return Ok(Some(returned_data));
}
else {
return Err(RuntimeError::UnknownWord);
}
}

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

Compiling solution v0.1.0 (/tmp/d20190128-22631-10pc3j2/solution)
warning: unused variable: `name`
  --> src/lib.rs:71:39
   |
71 |     pub fn def_unary_op<F>(&mut self, name: &str, op: F)
   |                                       ^^^^ help: consider using `_name` instead
   |
   = note: #[warn(unused_variables)] on by default

warning: unused variable: `op`
  --> src/lib.rs:71:51
   |
71 |     pub fn def_unary_op<F>(&mut self, name: &str, op: F)
   |                                                   ^^ help: consider using `_op` instead

warning: unused variable: `name`
  --> src/lib.rs:71:39
   |
71 |     pub fn def_unary_op<F>(&mut self, name: &str, op: F)
   |                                       ^^^^ help: consider using `_name` instead
   |
   = note: #[warn(unused_variables)] on by default

warning: unused variable: `op`
  --> src/lib.rs:71:51
   |
71 |     pub fn def_unary_op<F>(&mut self, name: &str, op: F)
   |                                                   ^^ help: consider using `_op` instead

    Finished dev [unoptimized + debuginfo] target(s) in 7.14s
     Running target/debug/deps/solution-2e785d603b538f71

running 0 tests

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

     Running target/debug/deps/solution_test-29808948fb50ed3a

running 10 tests
test solution_test::test_builtin_arithmetic ... FAILED
test solution_test::test_builtin_dup ... FAILED
test solution_test::test_builtin_pop ... FAILED
test solution_test::test_builtin_swap ... FAILED
test solution_test::test_def_binary ... FAILED
test solution_test::test_def_unary ... FAILED
test solution_test::test_def_var ... FAILED
test solution_test::test_multiple_run ... FAILED
test solution_test::test_unknown_word ... FAILED
test solution_test::test_whitespace ... FAILED

failures:

---- solution_test::test_builtin_arithmetic stdout ----
thread 'solution_test::test_builtin_arithmetic' panicked at 'called `Option::unwrap()` on a `None` value', libcore/option.rs:355:21
note: Run with `RUST_BACKTRACE=1` for a backtrace.

---- solution_test::test_builtin_dup stdout ----
thread 'solution_test::test_builtin_dup' panicked at 'assertion failed: `(left == right)`
  left: `Ok(Some(0))`,
 right: `Ok(Some(2))`', tests/solution_test.rs:51:9

---- solution_test::test_builtin_pop stdout ----
thread 'solution_test::test_builtin_pop' panicked at 'assertion failed: `(left == right)`
  left: `Ok(Some(0))`,
 right: `Ok(Some(2))`', tests/solution_test.rs:40:9

---- solution_test::test_builtin_swap stdout ----
thread 'solution_test::test_builtin_swap' panicked at 'assertion failed: `(left == right)`
  left: `Ok(Some(0))`,
 right: `Ok(Some(2))`', tests/solution_test.rs:62:9

---- solution_test::test_def_binary stdout ----
thread 'solution_test::test_def_binary' panicked at 'not yet implemented', src/lib.rs:88:9

---- solution_test::test_def_unary stdout ----
thread 'solution_test::test_def_unary' panicked at 'not yet implemented', src/lib.rs:76:9

---- solution_test::test_def_var stdout ----
thread 'solution_test::test_def_var' panicked at 'assertion failed: `(left == right)`
  left: `Ok(Some(0))`,
 right: `Ok(Some(3))`', tests/solution_test.rs:75:5

---- solution_test::test_multiple_run stdout ----
thread 'solution_test::test_multiple_run' panicked at 'assertion failed: `(left == right)`
  left: `Err(UnknownWord)`,
 right: `Ok(Some(2))`', tests/solution_test.rs:114:5

---- solution_test::test_unknown_word stdout ----
thread 'solution_test::test_unknown_word' panicked at 'assertion failed: `(left == right)`
  left: `Ok(Some(0))`,
 right: `Err(UnknownWord)`', tests/solution_test.rs:101:5

---- solution_test::test_whitespace stdout ----
thread 'solution_test::test_whitespace' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', libcore/result.rs:1009:5


failures:
    solution_test::test_builtin_arithmetic
    solution_test::test_builtin_dup
    solution_test::test_builtin_pop
    solution_test::test_builtin_swap
    solution_test::test_def_binary
    solution_test::test_def_unary
    solution_test::test_def_var
    solution_test::test_multiple_run
    solution_test::test_unknown_word
    solution_test::test_whitespace

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

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

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

Ива качи първо решение на 27.01.2019 16:59 (преди над 6 години)

Добър опит, но не се е получило :). Ще разгледам по някое време кода по-внимателно да ти дам някакви съвети. Иначе, можеш да видиш моето решение (което този път е предимно на Никола), за едно работещо решение на задачата.