Решение на Логически изрази от Илиян Георгиев

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

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

Резултати

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

Код

use std::collections::VecDeque;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr {
Atom(char),
Not(Box<Expr>),
And(Vec<Expr>),
Or(Vec<Expr>),
}
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
UnexpectedExpr,
UnexpectedUnaryOp,
UnexpectedBinOp,
UnexpectedParen,
UnexpectedEnd,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Value {
True,
False,
Expr(Expr),
}
pub struct SimpleExprParser {
stack: VecDeque<Expr>,
last_op: Option<char>,
expecting_atom: bool,
expection_operation: bool,
}
impl SimpleExprParser {
pub fn new() -> SimpleExprParser {
SimpleExprParser {
stack: VecDeque::new(),
last_op: None,
expecting_atom: true,
expection_operation: false
}
}
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if !self.expecting_atom {
return Err(ParseError::UnexpectedExpr);
}
self.stack.push_back(Expr::Atom(c));
self.expecting_atom = false;
self.expection_operation = true;
Ok(())
}
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
match op {
'&' | '|' => {
if self.expecting_atom || self.stack.is_empty() {
return Err(ParseError::UnexpectedBinOp);
}
self.last_op = Some(op);
self.expecting_atom = true;
}
'!' => {
if !self.expecting_atom {
return Err(ParseError::UnexpectedUnaryOp);
}
if !self.expection_operation {
return Err(ParseError::UnexpectedUnaryOp);
}
self.stack.push_back(Expr::Not(Box::new(Expr::Atom('#'))));
self.last_op = Some(op);
}
_ => panic!("Невалиден оператор: {}", op),
}
Ok(())
}
pub fn finish(mut self) -> Result<Expr, ParseError> {
if self.expecting_atom {
return Err(ParseError::UnexpectedEnd);
}
let mut result_stack = Vec::new();
while let Some(expr) = self.stack.pop_front() {
if let Some(op) = self.last_op {
match op {
'&' => {
if let Some(Expr::And(vec)) = result_stack.last_mut() {
vec.push(expr);
} else {
result_stack.push(Expr::And(vec![expr]));
}
}
'|' => {
if let Some(Expr::Or(vec)) = result_stack.last_mut() {
vec.push(expr);
} else {
result_stack.push(Expr::Or(vec![expr]));
}
}
'!' => {
if self.expection_operation == false {
return Err(ParseError::UnexpectedUnaryOp);
}
if let Expr::Not(_) = expr {
if let Some(last) = result_stack.pop() {
result_stack.push(Expr::Not(Box::new(last)));
}
} else {
return Err(ParseError::UnexpectedUnaryOp);
}
}
_ => unreachable!(),
}
} else {
result_stack.push(expr);
}
}
if result_stack.len() == 1 {
Ok(result_stack.pop().unwrap())
} else {
Err(ParseError::UnexpectedEnd)
}
}
}
pub fn eval(expr: &Expr, truthy: &[char], falsy: &[char]) -> Value {
match expr {
Expr::Atom(c) => {
if truthy.contains(c) {
Value::True
} else if falsy.contains(c) {
Value::False
} else {
Value::Expr(expr.clone())
}
}
Expr::Not(inner) => match eval(inner, truthy, falsy) {
Value::True => Value::False,
Value::False => Value::True,
Value::Expr(inner_expr) => Value::Expr(Expr::Not(Box::new(inner_expr))),
},
Expr::And(operands) => {
let mut new_operands = Vec::new();
let mut all_true = true;
for operand in operands {
match eval(operand, truthy, falsy) {
Value::True => continue,
Value::False => return Value::False,
Value::Expr(inner_expr) => {
all_true = false;
new_operands.push(inner_expr);
}
}
}
if all_true {
Value::True
} else if new_operands.is_empty() {
Value::True
} else {
Value::Expr(Expr::And(new_operands))
}
}
Expr::Or(operands) => {
let mut new_operands = Vec::new();
let mut any_true = false;
for operand in operands {
match eval(operand, truthy, falsy) {
Value::True => return Value::True,
Value::False => continue,
Value::Expr(inner_expr) => {
any_true = true;
new_operands.push(inner_expr);
}
}
}
if any_true {
Value::Expr(Expr::Or(new_operands))
} else {
Value::False
}
}
}
}
/// Парсър за пълния израз
pub struct ExprParser {
// ...
}
impl ExprParser {
pub fn new() -> ExprParser {
todo!();
}
/// Приема атом.
///
/// `c` ще бъде валиден символ за атом.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
todo!()
}
/// Приема символ за операция.
///
/// `op` ще бъде едно от '&', '|', '!'.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
todo!()
}
/// Приема отваряща скоба.
pub fn open_paren(&mut self) -> Result<(), ParseError> {
todo!()
}
/// Приема затваряща скоба.
pub fn close_paren(&mut self) -> Result<(), ParseError> {
todo!()
}
/// Завършва парсването и връща построения израз.
pub fn finish(self) -> Result<Expr, ParseError> {
todo!()
}
}

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

Compiling solution v0.1.0 (/tmp/d20241224-258381-1wkp3an/solution)
warning: unused variable: `c`
   --> src/lib.rs:208:33
    |
208 |     pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
    |                                 ^ help: if this is intentional, prefix it with an underscore: `_c`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `op`
   --> src/lib.rs:216:31
    |
216 |     pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
    |                               ^^ help: if this is intentional, prefix it with an underscore: `_op`

warning: `solution` (lib) generated 2 warnings
warning: variable does not need to be mutable
   --> tests/solution_test.rs:306:13
    |
306 |         let mut parser = SimpleExprParser::new();
    |             ----^^^^^^
    |             |
    |             help: remove this `mut`
    |
    = note: `#[warn(unused_mut)]` on by default

warning: `solution` (test "solution_test") generated 1 warning
    Finished test [unoptimized + debuginfo] target(s) in 1.69s
     Running tests/solution_test.rs (target/debug/deps/solution_test-1428e1090729d165)

running 20 tests
test solution_test::test_eval_full ... ok
test solution_test::test_error_paren_mismatched ... FAILED
test solution_test::test_eval_not_and_or ... ok
test solution_test::test_eval_partial ... ok
test solution_test::test_eval_unwrap_nested ... FAILED
test solution_test::test_eval_unwrap_and_or ... FAILED
test solution_test::test_paren_expr_priority ... FAILED
test solution_test::test_paren_around_expr ... FAILED
test solution_test::test_paren_nested ... FAILED
test solution_test::test_paren_not ... FAILED
test solution_test::test_paren_surrounded ... FAILED
test solution_test::test_parser_alternating_ops ... FAILED
test solution_test::test_parser_and_or ... ok
test solution_test::test_parser_atom ... ok
test solution_test::test_parser_errors_basic ... FAILED
test solution_test::test_parser_error_unexpected_end ... FAILED
test solution_test::test_parser_expr_and_not ... FAILED
test solution_test::test_parser_multiple_atoms_same_op ... ok
test solution_test::test_parser_multiple_not ... FAILED
test solution_test::test_parser_not ... FAILED

failures:

---- solution_test::test_error_paren_mismatched stdout ----
thread '<unnamed>' panicked at 'not yet implemented', src/lib.rs:201:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'solution_test::test_error_paren_mismatched' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:325:5

---- solution_test::test_eval_unwrap_nested stdout ----
thread '<unnamed>' panicked at 'assertion failed: `(left == right)`
  left: `Expr(Or([Atom('X'), And([Atom('B')]), Not(And([Atom('D')])), Atom('Y')]))`,
 right: `Expr(Or([Atom('X'), Atom('B'), Not(Atom('D')), Atom('Y')]))`', tests/solution_test.rs:480:9
thread 'solution_test::test_eval_unwrap_nested' panicked at 'assertion failed: `(left == right)`
  left: `Expr(Or([Atom('X'), And([Atom('B')]), Not(And([Atom('D')])), Atom('Y')]))`,
 right: `Expr(Or([Atom('X'), Atom('B'), Not(Atom('D')), Atom('Y')]))`', tests/solution_test.rs:479:5

---- solution_test::test_eval_unwrap_and_or stdout ----
thread '<unnamed>' panicked at 'assertion failed: `(left == right)`
  left: `Expr(And([Atom('B')]))`,
 right: `Expr(Atom('B'))`', tests/solution_test.rs:457:9
thread 'solution_test::test_eval_unwrap_and_or' panicked at 'assertion failed: `(left == right)`
  left: `Expr(And([Atom('B')]))`,
 right: `Expr(Atom('B'))`', tests/solution_test.rs:456:5

---- solution_test::test_paren_expr_priority stdout ----
thread '<unnamed>' panicked at 'not yet implemented', src/lib.rs:201:9
thread 'solution_test::test_paren_expr_priority' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:197:5

---- solution_test::test_paren_around_expr stdout ----
thread '<unnamed>' panicked at 'not yet implemented', src/lib.rs:201:9
thread 'solution_test::test_paren_around_expr' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:176:5

---- solution_test::test_paren_nested stdout ----
thread '<unnamed>' panicked at 'not yet implemented', src/lib.rs:201:9
thread 'solution_test::test_paren_nested' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:252:5

---- solution_test::test_paren_not stdout ----
thread '<unnamed>' panicked at 'not yet implemented', src/lib.rs:201:9
thread 'solution_test::test_paren_not' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:216:5

---- solution_test::test_paren_surrounded stdout ----
thread '<unnamed>' panicked at 'not yet implemented', src/lib.rs:201:9
thread 'solution_test::test_paren_surrounded' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:235:5

---- solution_test::test_parser_alternating_ops stdout ----
thread '<unnamed>' panicked at 'assertion failed: `(left == right)`
  left: `And([Atom('A'), Atom('B'), Atom('C'), Atom('D')])`,
 right: `And([Or([And([Atom('A'), Atom('B')]), Atom('C')]), Atom('D')])`', tests/solution_test.rs:160:9
thread 'solution_test::test_parser_alternating_ops' panicked at 'assertion failed: `(left == right)`
  left: `And([Atom('A'), Atom('B'), Atom('C'), Atom('D')])`,
 right: `And([Or([And([Atom('A'), Atom('B')]), Atom('C')]), Atom('D')])`', tests/solution_test.rs:157:5

---- solution_test::test_parser_errors_basic stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedUnaryOp', tests/solution_test.rs:281:29
thread 'solution_test::test_parser_errors_basic' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedUnaryOp', tests/solution_test.rs:265:5

---- solution_test::test_parser_error_unexpected_end stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedUnaryOp', tests/solution_test.rs:318:39
thread 'solution_test::test_parser_error_unexpected_end' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedUnaryOp', tests/solution_test.rs:305:5

---- solution_test::test_parser_expr_and_not stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedUnaryOp', tests/solution_test.rs:110:36
thread 'solution_test::test_parser_expr_and_not' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedUnaryOp', tests/solution_test.rs:107:5

---- solution_test::test_parser_multiple_not stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedUnaryOp', tests/solution_test.rs:142:42
thread 'solution_test::test_parser_multiple_not' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedUnaryOp', tests/solution_test.rs:140:5

---- solution_test::test_parser_not stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedUnaryOp', tests/solution_test.rs:100:40
thread 'solution_test::test_parser_not' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedUnaryOp', tests/solution_test.rs:98:5


failures:
    solution_test::test_error_paren_mismatched
    solution_test::test_eval_unwrap_and_or
    solution_test::test_eval_unwrap_nested
    solution_test::test_paren_around_expr
    solution_test::test_paren_expr_priority
    solution_test::test_paren_nested
    solution_test::test_paren_not
    solution_test::test_paren_surrounded
    solution_test::test_parser_alternating_ops
    solution_test::test_parser_error_unexpected_end
    solution_test::test_parser_errors_basic
    solution_test::test_parser_expr_and_not
    solution_test::test_parser_multiple_not
    solution_test::test_parser_not

test result: FAILED. 6 passed; 14 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

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

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

Илиян качи първо решение на 22.12.2024 22:02 (преди 9 месеца)