Решение на Логически изрази от Силвия Земеделска

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

Към профила на Силвия Земеделска

Резултати

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

Код

#[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,
}
pub struct SimpleExprParser {
atoms_stack: Vec<Expr>,
operators: Vec<char>,
expect_atom: bool,
}
impl SimpleExprParser {
pub fn new() -> SimpleExprParser {
let atoms_stack:Vec<Expr> = Vec::new();
let operators:Vec<char> = Vec::new();
let expect_atom = true;
SimpleExprParser{atoms_stack: atoms_stack, operators: operators, expect_atom: expect_atom}
}
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if c == '&' || c == '|' {
return Err(ParseError::UnexpectedBinOp);
} else if c == '!' {
return Err(ParseError::UnexpectedUnaryOp);
} else if !self.expect_atom || c == ' ' {
return Err(ParseError::UnexpectedExpr);
}
self.atoms_stack.push(Expr::Atom(c));
self.expect_atom = false;
Ok(())
}
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
if op == '&' || op == '|' {
if self.expect_atom {
return Err(ParseError::UnexpectedBinOp);
}
self.operators.push(op);
self.expect_atom = true;
return Ok(());
} else if op == '!' {
if !self.expect_atom {
return Err(ParseError::UnexpectedUnaryOp);
}
self.operators.push(op);
self.expect_atom = true;
return Ok(())
}
Err(ParseError::UnexpectedBinOp)
}
pub fn finish(self) -> Result<Expr, ParseError> {
let mut parser = self;
while let Some(op) = parser.operators.pop() {
parser.parse(op);
}
if parser.atoms_stack.len() == 1 {
Ok(parser.atoms_stack.pop().unwrap())
} else {
Err(ParseError::UnexpectedEnd)
}
}
fn parse(&mut self, op: char) -> Result<(), ParseError> {
let mut stack = Vec::new();
while let Some(expr) = self.atoms_stack.pop() {
stack.push(expr);
}
let expr: Expr;
if op == '&' {
expr = Expr::And(stack);
} else if op == '|' {
expr = Expr::Or(stack);
} else {
return Err(ParseError::UnexpectedBinOp);
}
self.atoms_stack.push(expr);
Ok(())
}
}
pub struct ExprParser {
expr: String,
expects_atom: bool,
}
impl ExprParser {
pub fn new() -> ExprParser {
let expr: String = String::new();
let expects_atom = true;
ExprParser { expr: expr, expects_atom: expects_atom }
}
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if c == '&' || c == '|' {
return Err(ParseError::UnexpectedBinOp);
}
else if c == '&' || c == '|' {
return Err(ParseError::UnexpectedUnaryOp);
}
else if c == ' ' || !self.expects_atom {
return Err(ParseError::UnexpectedExpr);
}
self.expr.push(c);
self.expects_atom = true;
Ok(())
}
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
if op == '&' || op == '|' {
if self.expects_atom {
return Err(ParseError::UnexpectedBinOp);
}
self.expr.push(op);
self.expects_atom = true;
return Ok(())
}
if op == '&' || op == '|' || op == '!' {
if !self.expects_atom {
return Err(ParseError::UnexpectedUnaryOp);
}
self.expr.push(op);
return Ok(())
}
Err(ParseError::UnexpectedBinOp)
}
pub fn open_paren(&mut self) -> Result<(), ParseError> {
if !self.expects_atom {
return Err(ParseError::UnexpectedParen);
}
self.expr.push('(');
Ok(())
}
pub fn close_paren(&mut self) -> Result<(), ParseError> {
if self.expects_atom {
return Err(ParseError::UnexpectedParen);
}
self.expr.push(')');
Ok(())
}
pub fn finish(self) -> Result<Expr, ParseError> {
let expr = self.expr.clone();
Ok(self.parse(expr))
}
fn parse(&self, expr:String) -> Expr {
if expr.len() == 1 {
let c:char = expr.chars().next().unwrap();
return Expr::Atom(c);
}
let mut count:usize = 0;
for i in 0..expr.len() {
if expr.chars().nth(i).unwrap() == '(' {
count += 1;
} else if expr.chars().nth(i).unwrap() == ')' {
count -= 1;
} else if count == 0 {
if expr.chars().nth(i).unwrap() == '!' {
Expr::Not(Box::new(self.parse(expr[i+1..expr.len()].to_string())));
} else if expr.chars().nth(i).unwrap() == '&' {
let mut vec:Vec<Expr> = Vec::new();
vec.push(self.parse(expr[0..i].to_string()));
vec.push(self.parse(expr[i+1..expr.len()].to_string()));
Expr::And(vec);
}
else if expr.chars().nth(i).unwrap() == '|' {
let mut vec:Vec<Expr> = Vec::new();
vec.push(self.parse(expr[0..i].to_string()));
vec.push(self.parse(expr[i+1..expr.len()].to_string()));
Expr::Or(vec);
}
}
}
Expr::Atom('A')
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Value {
True,
False,
Expr(Expr),
}
pub fn eval(expr: &Expr, truthy: &[char], falsy: &[char]) -> Value {
match expr {
Expr::And(c) => {
let mut unparsed_values:Vec<Expr> = Vec::new();
for i in 0..c.len() {
let val = eval(&c[i], truthy, falsy);
if val == Value::False {
return Value::False;
} else if val != Value::True {
match val {
Value::Expr(val1) => { unparsed_values.push(val1);}
_ => { }
}
}
}
if unparsed_values.is_empty() {
return Value::True;
} else if unparsed_values.len() == 1 {
return Value::Expr(unparsed_values[0].clone());
} else {
let result:Expr = Expr::And(unparsed_values);
return Value::Expr(result);
}
}
Expr::Or(c) => {
let mut unparsed_values:Vec<Expr> = Vec::new();
for i in 0..c.len() {
let val = eval(&c[i], truthy, falsy);
if val == Value::True {
return Value::True;
} else if val != Value::False {
match val {
Value::Expr(val1) => { unparsed_values.push(val1);}
_ => { }
}
}
}
if unparsed_values.is_empty() {
return Value::False;
} else if unparsed_values.len() == 1 {
return Value::Expr(unparsed_values[0].clone());
} else {
let result:Expr = Expr::Or(unparsed_values);
return Value::Expr(result);
}
}
Expr::Not(c) => {
let val = eval(*&c, truthy,falsy);
if val == Value::True {
return Value::False;
} else if val == Value::False {
return Value::True;
} else {
let result:Expr;
match val {
Value::Expr(val1) => { result = val1;}
_ => { result = Expr::Atom('A') }
}
let result2:Expr = Expr::Not(Box::new(result));
return Value::Expr(result2);
}
}
Expr::Atom(c) => {
if truthy.contains(c) {
return Value::True;
} else if falsy.contains(c) {
return Value::False;
} else {
let result:Expr = Expr::Atom(c.clone());
return Value::Expr(result);
}
}
}
}

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

Compiling solution v0.1.0 (/tmp/d20241224-258381-1rj2zyk/solution)
warning: unused `Result` that must be used
  --> src/lib.rs:71:13
   |
71 |             parser.parse(op);
   |             ^^^^^^^^^^^^^^^^
   |
   = note: this `Result` may be an `Err` variant, which should be handled
   = note: `#[warn(unused_must_use)]` on by default

warning: `solution` (lib) generated 1 warning
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.76s
     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_and_or ... ok
test solution_test::test_eval_unwrap_nested ... ok
test solution_test::test_paren_around_expr ... FAILED
test solution_test::test_paren_expr_priority ... 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_atom ... ok
test solution_test::test_parser_and_or ... FAILED
test solution_test::test_parser_error_unexpected_end ... FAILED
test solution_test::test_parser_errors_basic ... ok
test solution_test::test_parser_expr_and_not ... FAILED
test solution_test::test_parser_multiple_atoms_same_op ... FAILED
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 'called `Result::unwrap()` on an `Err` value: UnexpectedBinOp', tests/solution_test.rs:336:29
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'solution_test::test_error_paren_mismatched' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedBinOp', tests/solution_test.rs:325:5

---- solution_test::test_paren_around_expr stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedParen', tests/solution_test.rs:178:39
thread 'solution_test::test_paren_around_expr' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedParen', tests/solution_test.rs:176:5

---- solution_test::test_paren_expr_priority stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedBinOp', tests/solution_test.rs:199:47
thread 'solution_test::test_paren_expr_priority' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedBinOp', tests/solution_test.rs:197:5

---- solution_test::test_paren_nested stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedBinOp', tests/solution_test.rs:254:58
thread 'solution_test::test_paren_nested' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedBinOp', tests/solution_test.rs:252:5

---- solution_test::test_paren_not stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedBinOp', tests/solution_test.rs:218:48
thread 'solution_test::test_paren_not' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedBinOp', tests/solution_test.rs:216:5

---- solution_test::test_paren_surrounded stdout ----
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedBinOp', tests/solution_test.rs:237:61
thread 'solution_test::test_paren_surrounded' panicked at 'called `Result::unwrap()` on an `Err` value: UnexpectedBinOp', tests/solution_test.rs:235:5

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

---- solution_test::test_parser_and_or stdout ----
thread '<unnamed>' panicked at 'assertion failed: `(left == right)`
  left: `And([Atom('B'), Atom('A')])`,
 right: `And([Atom('A'), Atom('B')])`', tests/solution_test.rs:88:9
thread 'solution_test::test_parser_and_or' panicked at 'assertion failed: `(left == right)`
  left: `And([Atom('B'), Atom('A')])`,
 right: `And([Atom('A'), Atom('B')])`', tests/solution_test.rs:84:5

---- solution_test::test_parser_error_unexpected_end stdout ----
thread '<unnamed>' panicked at 'assertion failed: matches!(parser.finish(), Err(_))', tests/solution_test.rs:311:9
thread 'solution_test::test_parser_error_unexpected_end' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:305:5

---- solution_test::test_parser_expr_and_not stdout ----
thread '<unnamed>' panicked at 'assertion failed: `(left == right)`
  left: `And([])`,
 right: `And([Atom('A'), Not(Atom('B'))])`', tests/solution_test.rs:110:9
thread 'solution_test::test_parser_expr_and_not' panicked at 'assertion failed: `(left == right)`
  left: `And([])`,
 right: `And([Atom('A'), Not(Atom('B'))])`', tests/solution_test.rs:107:5

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

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

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


failures:
    solution_test::test_error_paren_mismatched
    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_and_or
    solution_test::test_parser_error_unexpected_end
    solution_test::test_parser_expr_and_not
    solution_test::test_parser_multiple_atoms_same_op
    solution_test::test_parser_multiple_not
    solution_test::test_parser_not

test result: FAILED. 7 passed; 13 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 23:58 (преди 9 месеца)