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

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

Към профила на Енислав Енчев

Резултати

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

Код

#[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 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(e) => match eval(e, truthy, falsy) {
Value::True => Value::False,
Value::False => Value::True,
Value::Expr(_) => Value::Expr(expr.clone()),
},
Expr::And(exprs) => {
let left : Value = eval(&exprs[0].clone(), &truthy, &falsy);
let right : Value = eval(&exprs[1].clone(), &truthy, &falsy);
match (left, right) {
(Value::True, Value::True) => Value::True,
(Value::False, _) | (_, Value::False) => Value::False,
(Value::True, v) | (v, Value::True) => v,
(Value::Expr(e1), Value::Expr(e2)) => Value::Expr(Expr::And(vec![e1, e2])),
}
}
Expr::Or(exprs) => {
let left : Value = eval(&exprs[0].clone(), &truthy, &falsy);
let right : Value = eval(&exprs[1].clone(), &truthy, &falsy);
match (left, right) {
(Value::True, _) | (_, Value::True) => Value::True,
(Value::False, Value::False) => Value::False,
(Value::False, v) | (v, Value::False) => v,
(Value::Expr(e1), Value::Expr(e2)) => Value::Expr(Expr::Or(vec![e1, e2])),
}
}
}
}
pub struct SimpleExprParser {
expression : Vec<char>,
err : Option<ParseError>,
}
impl SimpleExprParser {
pub fn new() -> SimpleExprParser {
SimpleExprParser{
expression : Vec::new(),
err : None}
}
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if c == '&' || c == '|' || c == '!' || c == ' '{
self.err = Some(ParseError::UnexpectedExpr);
return Result::Err(ParseError::UnexpectedExpr);
}
self.expression.push(c);
Result::Ok(())
}
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
if op == '!'{
self.expression.push('!');
return Result::Ok(());
}else if op == '&' || op == '|'{
if self.expression.len() == 0{
self.err = Some(ParseError::UnexpectedBinOp);
return Result::Err(ParseError::UnexpectedBinOp);
}
match self.expression[self.expression.len() - 1]{
'!' | '&' | '|' => {
self.err = Some(ParseError::UnexpectedBinOp);
return Result::Err(ParseError::UnexpectedBinOp)
},
_ => self.expression.push(op),
}
}else{
self.err = Some(ParseError::UnexpectedEnd);
return Result::Err(ParseError::UnexpectedEnd);
}
Result::Ok(())
}
pub fn finish(self) -> Result<Expr, ParseError> {
match self.err {
Some(msg) => return Result::Err(msg),
None => {
let mut s : u32 = 0;
let mut nd : bool = false;
let mut ro : bool = false;
let mut i : usize = 0;
let len : usize = self.expression.len();
while self.expression[i] == '!'{
i += 1;
s += 1;
}
let mut current : Expr = Expr::Atom(self.expression[i]);
while s >0 {
current = Expr::Not(Box::new(current.clone()));
s -= 1;
}
i += 1;
while i < len{
match self.expression[i]{
'!' => s += 1,
'&' => {
nd = true;
},
'|' => {
ro = true;
},
_ => {
let mut x : Expr = Expr::Atom(self.expression[i]);
while s > 0{
x = Expr::Not(Box::new(x));
s -= 1;
}
if nd{
current = Expr::And((&[current, x]).to_vec());
nd = false;
} else if ro{
current = Expr::Or((&[current, x]).to_vec());
ro = false;
}
},
}
i += 1;
}
Result::Ok(current)
}
}
}
}
pub struct ExprParser {
expression: Vec<char>,
err: Option<ParseError>,
paren_stack: Vec<char>,
}
impl ExprParser {
pub fn new() -> ExprParser {
ExprParser {
expression: Vec::new(),
err: None,
paren_stack: Vec::new(),
}
}
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if c == '&' || c == '|' || c == '!' || c == ' ' {
self.err = Some(ParseError::UnexpectedExpr);
return Err(ParseError::UnexpectedExpr);
}
self.expression.push(c);
Ok(())
}
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
if op == '!' {
self.expression.push('!');
return Ok(());
} else if op == '&' || op == '|' {
if self.expression.is_empty() {
self.err = Some(ParseError::UnexpectedBinOp);
return Err(ParseError::UnexpectedBinOp);
}
match self.expression[self.expression.len() - 1] {
'!' | '&' | '|' | '(' => {
self.err = Some(ParseError::UnexpectedBinOp);
return Err(ParseError::UnexpectedBinOp);
}
_ => self.expression.push(op),
}
} else {
self.err = Some(ParseError::UnexpectedEnd);
return Err(ParseError::UnexpectedEnd);
}
Ok(())
}
pub fn open_paren(&mut self) -> Result<(), ParseError> {
self.expression.push('(');
self.paren_stack.push('(');
Ok(())
}
pub fn close_paren(&mut self) -> Result<(), ParseError> {
if self.paren_stack.is_empty() {
self.err = Some(ParseError::UnexpectedExpr);
return Err(ParseError::UnexpectedExpr);
}
self.expression.push(')');
self.paren_stack.pop();
Ok(())
}
pub fn finish(self) -> Result<Expr, ParseError> {
if !self.paren_stack.is_empty() {
return Err(ParseError::UnexpectedExpr);
}
match self.err {
Some(msg) => Err(msg),
None => {
let mut s: u32 = 0;
let mut nd: bool = false;
let mut ro: bool = false;
let mut i: usize = 1;
let len: usize = self.expression.len();
let mut current: Expr = match self.expression[0] {
'!' => {
let mut x = Expr::Atom(self.expression[1]);
s += 1;
while s > 0 {
x = Expr::Not(Box::new(x));
s -= 1;
}
i += 1;
x
}
'(' => {
let mut sub_expr = Vec::new();
let mut paren_count = 1;
while i < len && paren_count > 0 {
match self.expression[i] {
'(' => paren_count += 1,
')' => paren_count -= 1,
_ => {}
}
if paren_count > 0 {
sub_expr.push(self.expression[i]);
}
i += 1;
}
let sub_parser = ExprParser {
expression: sub_expr,
err: None,
paren_stack: Vec::new(),
};
sub_parser.finish()?
}
x => Expr::Atom(x),
};
while i < len {
match self.expression[i] {
'!' => s += 1,
'&' => {
nd = true;
}
'|' => {
ro = true;
}
'(' => {
let mut sub_expr = Vec::new();
let mut paren_count = 1;
i += 1;
while i < len && paren_count > 0 {
match self.expression[i] {
'(' => paren_count += 1,
')' => paren_count -= 1,
_ => {}
}
if paren_count > 0 {
sub_expr.push(self.expression[i]);
}
i += 1;
}
let sub_parser = ExprParser {
expression: sub_expr,
err: None,
paren_stack: Vec::new(),
};
let sub_result = sub_parser.finish()?;
current = Expr::And(vec![current, sub_result]);
}
')' => {
return Err(ParseError::UnexpectedEnd);
}
_ => {
let mut x: Expr = Expr::Atom(self.expression[i]);
while s > 0 {
x = Expr::Not(Box::new(x));
s -= 1;
}
if nd {
current = Expr::And(vec![current, x]);
nd = false;
}
else if ro {
current = Expr::Or(vec![current, x]);
ro = false;
}
}
}
i += 1;
}
Ok(current)
}
}
}
}
fn main(){
// let mut simple_parser = SimpleExprParser::new();
// let c = simple_parser.push_op('!');
// let c = simple_parser.push_op('!');
// let a = simple_parser.push_atom('A');
// let b = simple_parser.push_op('&');
// let c = simple_parser.push_op('!');
// let c = simple_parser.push_op('!');
// let c = simple_parser.push_op('!');
// let d = simple_parser.push_atom('B');
// let expr = simple_parser.finish().unwrap();
// println!("{:?}", &expr);
// println!("{:?}", eval(&expr, &['A'], &['B']));
// let mut full_parser = ExprParser::new();
// let _ = full_parser.push_atom('A');
// let _ = full_parser.push_op('|');
// let _ = full_parser.open_paren();
// let _ = full_parser.push_atom('B');
// let _ = full_parser.push_op('&');
// let _ = full_parser.push_op('!');
// let _ = full_parser.push_atom('C');
// let _ = full_parser.close_paren();
// let expr = full_parser.finish().unwrap();
// println!("{:?}", eval(&expr, &['B'], &[]));
}

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

Compiling solution v0.1.0 (/tmp/d20241224-258381-1bnkr1k/solution)
warning: function `main` is never used
   --> src/lib.rs:330:4
    |
330 | fn main(){
    |    ^^^^
    |
    = note: `#[warn(dead_code)]` 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.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 ... FAILED
test solution_test::test_eval_unwrap_and_or ... ok
test solution_test::test_paren_around_expr ... ok
test solution_test::test_eval_unwrap_nested ... 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 ... ok
test solution_test::test_parser_and_or ... ok
test solution_test::test_parser_atom ... ok
test solution_test::test_parser_error_unexpected_end ... FAILED
test solution_test::test_parser_errors_basic ... FAILED
test solution_test::test_parser_expr_and_not ... ok
test solution_test::test_parser_multiple_not ... ok
test solution_test::test_parser_multiple_atoms_same_op ... FAILED
test solution_test::test_parser_not ... ok

failures:

---- solution_test::test_error_paren_mismatched stdout ----
thread '<unnamed>' panicked at 'assertion failed: matches!(parser.close_paren(), Err(_))', tests/solution_test.rs:331: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_partial stdout ----
thread '<unnamed>' panicked at 'assertion failed: `(left == right)`
  left: `Expr(Atom('A'))`,
 right: `Expr(And([Atom('A'), Atom('C')]))`', tests/solution_test.rs:416:9
thread 'solution_test::test_eval_partial' panicked at 'assertion failed: `(left == right)`
  left: `Expr(Atom('A'))`,
 right: `Expr(And([Atom('A'), Atom('C')]))`', tests/solution_test.rs:409:5

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

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

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

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

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

---- solution_test::test_parser_error_unexpected_end stdout ----
thread '<unnamed>' panicked at 'index out of bounds: the len is 0 but the index is 0', src/lib.rs:117:23
thread 'solution_test::test_parser_error_unexpected_end' panicked at 'index out of bounds: the len is 0 but the index is 0', tests/solution_test.rs:305:5

---- solution_test::test_parser_errors_basic stdout ----
thread '<unnamed>' panicked at 'assertion failed: matches!(parser.push_atom(\'B\'), Err(_))', tests/solution_test.rs:274:9
thread 'solution_test::test_parser_errors_basic' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:265:5

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


failures:
    solution_test::test_error_paren_mismatched
    solution_test::test_eval_partial
    solution_test::test_eval_unwrap_nested
    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_error_unexpected_end
    solution_test::test_parser_errors_basic
    solution_test::test_parser_multiple_atoms_same_op

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

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

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

Енислав качи първо решение на 22.12.2024 23:17 (преди 9 месеца)

Енислав качи решение на 22.12.2024 23:54 (преди 9 месеца)

#[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 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(e) => match eval(e, truthy, falsy) {
Value::True => Value::False,
Value::False => Value::True,
Value::Expr(_) => Value::Expr(expr.clone()),
},
Expr::And(exprs) => {
let left : Value = eval(&exprs[0].clone(), &truthy, &falsy);
let right : Value = eval(&exprs[1].clone(), &truthy, &falsy);
match (left, right) {
(Value::True, Value::True) => Value::True,
(Value::False, _) | (_, Value::False) => Value::False,
(Value::True, v) | (v, Value::True) => v,
(Value::Expr(e1), Value::Expr(e2)) => Value::Expr(Expr::And(vec![e1, e2])),
}
}
Expr::Or(exprs) => {
let left : Value = eval(&exprs[0].clone(), &truthy, &falsy);
let right : Value = eval(&exprs[1].clone(), &truthy, &falsy);
match (left, right) {
(Value::True, _) | (_, Value::True) => Value::True,
(Value::False, Value::False) => Value::False,
(Value::False, v) | (v, Value::False) => v,
(Value::Expr(e1), Value::Expr(e2)) => Value::Expr(Expr::Or(vec![e1, e2])),
}
}
}
}
pub struct SimpleExprParser {
expression : Vec<char>,
err : Option<ParseError>,
}
impl SimpleExprParser {
pub fn new() -> SimpleExprParser {
SimpleExprParser{
expression : Vec::new(),
err : None}
}
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if c == '&' || c == '|' || c == '!' || c == ' '{
self.err = Some(ParseError::UnexpectedExpr);
return Result::Err(ParseError::UnexpectedExpr);
}
self.expression.push(c);
Result::Ok(())
}
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
if op == '!'{
self.expression.push('!');
return Result::Ok(());
}else if op == '&' || op == '|'{
if self.expression.len() == 0{
self.err = Some(ParseError::UnexpectedBinOp);
return Result::Err(ParseError::UnexpectedBinOp);
}
match self.expression[self.expression.len() - 1]{
'!' | '&' | '|' => {
self.err = Some(ParseError::UnexpectedBinOp);
return Result::Err(ParseError::UnexpectedBinOp)
},
_ => self.expression.push(op),
}
}else{
self.err = Some(ParseError::UnexpectedEnd);
return Result::Err(ParseError::UnexpectedEnd);
}
Result::Ok(())
}
pub fn finish(self) -> Result<Expr, ParseError> {
match self.err {
Some(msg) => return Result::Err(msg),
None => {
let mut s : u32 = 0;
let mut nd : bool = false;
let mut ro : bool = false;
let mut i : usize = 0;
let len : usize = self.expression.len();
while self.expression[i] == '!'{
i += 1;
s += 1;
}
let mut current : Expr = Expr::Atom(self.expression[i]);
while s >0 {
current = Expr::Not(Box::new(current.clone()));
s -= 1;
}
i += 1;
while i < len{
match self.expression[i]{
'!' => s += 1,
'&' => {
nd = true;
},
'|' => {
ro = true;
},
_ => {
let mut x : Expr = Expr::Atom(self.expression[i]);
while s > 0{
x = Expr::Not(Box::new(x));
s -= 1;
}
if nd{
current = Expr::And((&[current, x]).to_vec());
nd = false;
} else if ro{
current = Expr::Or((&[current, x]).to_vec());
ro = false;
}
},
}
i += 1;
}
Result::Ok(current)
}
}
}
}
+pub struct ExprParser {
+ expression: Vec<char>,
+ err: Option<ParseError>,
+ paren_stack: Vec<char>,
+}
+impl ExprParser {
+ pub fn new() -> ExprParser {
+ ExprParser {
+ expression: Vec::new(),
+ err: None,
+ paren_stack: Vec::new(),
+ }
+ }
+
+ pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
+ if c == '&' || c == '|' || c == '!' || c == ' ' {
+ self.err = Some(ParseError::UnexpectedExpr);
+ return Err(ParseError::UnexpectedExpr);
+ }
+ self.expression.push(c);
+ Ok(())
+ }
+
+ pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
+ if op == '!' {
+ self.expression.push('!');
+ return Ok(());
+ } else if op == '&' || op == '|' {
+ if self.expression.is_empty() {
+ self.err = Some(ParseError::UnexpectedBinOp);
+ return Err(ParseError::UnexpectedBinOp);
+ }
+ match self.expression[self.expression.len() - 1] {
+ '!' | '&' | '|' | '(' => {
+ self.err = Some(ParseError::UnexpectedBinOp);
+ return Err(ParseError::UnexpectedBinOp);
+ }
+ _ => self.expression.push(op),
+ }
+ } else {
+ self.err = Some(ParseError::UnexpectedEnd);
+ return Err(ParseError::UnexpectedEnd);
+ }
+ Ok(())
+ }
+
+ pub fn open_paren(&mut self) -> Result<(), ParseError> {
+ self.expression.push('(');
+ self.paren_stack.push('(');
+ Ok(())
+ }
+
+ pub fn close_paren(&mut self) -> Result<(), ParseError> {
+ if self.paren_stack.is_empty() {
+ self.err = Some(ParseError::UnexpectedExpr);
+ return Err(ParseError::UnexpectedExpr);
+ }
+ self.expression.push(')');
+ self.paren_stack.pop();
+ Ok(())
+ }
+
+ pub fn finish(self) -> Result<Expr, ParseError> {
+ if !self.paren_stack.is_empty() {
+ return Err(ParseError::UnexpectedExpr);
+ }
+ match self.err {
+ Some(msg) => Err(msg),
+ None => {
+ let mut s: u32 = 0;
+ let mut nd: bool = false;
+ let mut ro: bool = false;
+ let mut i: usize = 1;
+ let len: usize = self.expression.len();
+ let mut current: Expr = match self.expression[0] {
+ '!' => {
+ let mut x = Expr::Atom(self.expression[1]);
+ s += 1;
+ while s > 0 {
+ x = Expr::Not(Box::new(x));
+ s -= 1;
+ }
+ i += 1; // Skip the next character since it's part of the Not expression
+ x
+ }
+ '(' => {
+ let mut sub_expr = Vec::new();
+ let mut paren_count = 1;
+ while i < len && paren_count > 0 {
+ match self.expression[i] {
+ '(' => paren_count += 1,
+ ')' => paren_count -= 1,
+ _ => {}
+ }
+ if paren_count > 0 {
+ sub_expr.push(self.expression[i]);
+ }
+ i += 1;
+ }
+ let sub_parser = ExprParser {
+ expression: sub_expr,
+ err: None,
+ paren_stack: Vec::new(),
+ };
+ sub_parser.finish()?
+
+ }
+ x => Expr::Atom(x),
+ };
+ while i < len {
+ match self.expression[i] {
+ '!' => s += 1,
+ '&' => {
+ nd = true;
+ }
+ '|' => {
+ ro = true;
+ }
+ '(' => {
+ let mut sub_expr = Vec::new();
+ let mut paren_count = 1;
+ i += 1;
+ while i < len && paren_count > 0 {
+ match self.expression[i] {
+ '(' => paren_count += 1,
+ ')' => paren_count -= 1,
+ _ => {}
+ }
+ if paren_count > 0 {
+ sub_expr.push(self.expression[i]);
+ }
+ i += 1;
+ }
+ let sub_parser = ExprParser {
+ expression: sub_expr,
+ err: None,
+ paren_stack: Vec::new(),
+ };
+ let sub_result = sub_parser.finish()?;
+ current = Expr::And(vec![current, sub_result]);
+ }
+ ')' => {
+ return Err(ParseError::UnexpectedEnd);
+ }
+ _ => {
+ let mut x: Expr = Expr::Atom(self.expression[i]);
+ while s > 0 {
+ x = Expr::Not(Box::new(x));
+ s -= 1;
+ }
+ if nd {
+ current = Expr::And(vec![current, x]);
+ nd = false;
+ }
+ else if ro {
+ current = Expr::Or(vec![current, x]);
+ ro = false;
+ }
+ }
+ }
+ i += 1;
+ }
+ Ok(current)
+ }
+ }
+ }
+}
+
+
+
fn main(){
// let mut simple_parser = SimpleExprParser::new();
// let c = simple_parser.push_op('!');
// let c = simple_parser.push_op('!');
// let a = simple_parser.push_atom('A');
// let b = simple_parser.push_op('&');
// let c = simple_parser.push_op('!');
// let c = simple_parser.push_op('!');
// let c = simple_parser.push_op('!');
// let d = simple_parser.push_atom('B');
// let expr = simple_parser.finish().unwrap();
// println!("{:?}", &expr);
// println!("{:?}", eval(&expr, &['A'], &['B']));
+
+ // let mut full_parser = ExprParser::new();
+ // let _ = full_parser.open_paren();
+ // let _ = full_parser.push_atom('A');
+ // let _ = full_parser.push_op('&');
+ // let _ = full_parser.push_atom('B');
+ // let _ = full_parser.close_paren();
+ // let _ = full_parser.push_op('|');
+ // let _ = full_parser.push_op('!');
+ // let _ = full_parser.push_atom('C');
+ // let expr = full_parser.finish().unwrap();
+
+ // println!("{:?}", eval(&expr, &['A', 'B'], &[]));
}

Енислав качи решение на 22.12.2024 23:57 (преди 9 месеца)

#[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 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(e) => match eval(e, truthy, falsy) {
Value::True => Value::False,
Value::False => Value::True,
Value::Expr(_) => Value::Expr(expr.clone()),
},
Expr::And(exprs) => {
let left : Value = eval(&exprs[0].clone(), &truthy, &falsy);
let right : Value = eval(&exprs[1].clone(), &truthy, &falsy);
match (left, right) {
(Value::True, Value::True) => Value::True,
(Value::False, _) | (_, Value::False) => Value::False,
(Value::True, v) | (v, Value::True) => v,
(Value::Expr(e1), Value::Expr(e2)) => Value::Expr(Expr::And(vec![e1, e2])),
}
}
Expr::Or(exprs) => {
let left : Value = eval(&exprs[0].clone(), &truthy, &falsy);
let right : Value = eval(&exprs[1].clone(), &truthy, &falsy);
match (left, right) {
(Value::True, _) | (_, Value::True) => Value::True,
(Value::False, Value::False) => Value::False,
(Value::False, v) | (v, Value::False) => v,
(Value::Expr(e1), Value::Expr(e2)) => Value::Expr(Expr::Or(vec![e1, e2])),
}
}
}
}
pub struct SimpleExprParser {
expression : Vec<char>,
err : Option<ParseError>,
}
impl SimpleExprParser {
pub fn new() -> SimpleExprParser {
SimpleExprParser{
expression : Vec::new(),
err : None}
}
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if c == '&' || c == '|' || c == '!' || c == ' '{
self.err = Some(ParseError::UnexpectedExpr);
return Result::Err(ParseError::UnexpectedExpr);
}
self.expression.push(c);
Result::Ok(())
}
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
if op == '!'{
self.expression.push('!');
return Result::Ok(());
}else if op == '&' || op == '|'{
if self.expression.len() == 0{
self.err = Some(ParseError::UnexpectedBinOp);
return Result::Err(ParseError::UnexpectedBinOp);
}
match self.expression[self.expression.len() - 1]{
'!' | '&' | '|' => {
self.err = Some(ParseError::UnexpectedBinOp);
return Result::Err(ParseError::UnexpectedBinOp)
},
_ => self.expression.push(op),
}
}else{
self.err = Some(ParseError::UnexpectedEnd);
return Result::Err(ParseError::UnexpectedEnd);
}
Result::Ok(())
}
pub fn finish(self) -> Result<Expr, ParseError> {
match self.err {
Some(msg) => return Result::Err(msg),
None => {
let mut s : u32 = 0;
let mut nd : bool = false;
let mut ro : bool = false;
let mut i : usize = 0;
let len : usize = self.expression.len();
while self.expression[i] == '!'{
i += 1;
s += 1;
}
let mut current : Expr = Expr::Atom(self.expression[i]);
while s >0 {
current = Expr::Not(Box::new(current.clone()));
s -= 1;
}
i += 1;
while i < len{
match self.expression[i]{
'!' => s += 1,
'&' => {
nd = true;
},
'|' => {
ro = true;
},
_ => {
let mut x : Expr = Expr::Atom(self.expression[i]);
while s > 0{
x = Expr::Not(Box::new(x));
s -= 1;
}
if nd{
current = Expr::And((&[current, x]).to_vec());
nd = false;
} else if ro{
current = Expr::Or((&[current, x]).to_vec());
ro = false;
}
},
}
i += 1;
}
Result::Ok(current)
}
}
}
}
pub struct ExprParser {
expression: Vec<char>,
err: Option<ParseError>,
paren_stack: Vec<char>,
}
impl ExprParser {
pub fn new() -> ExprParser {
ExprParser {
expression: Vec::new(),
err: None,
paren_stack: Vec::new(),
}
}
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if c == '&' || c == '|' || c == '!' || c == ' ' {
self.err = Some(ParseError::UnexpectedExpr);
return Err(ParseError::UnexpectedExpr);
}
self.expression.push(c);
Ok(())
}
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
if op == '!' {
self.expression.push('!');
return Ok(());
} else if op == '&' || op == '|' {
if self.expression.is_empty() {
self.err = Some(ParseError::UnexpectedBinOp);
return Err(ParseError::UnexpectedBinOp);
}
match self.expression[self.expression.len() - 1] {
'!' | '&' | '|' | '(' => {
self.err = Some(ParseError::UnexpectedBinOp);
return Err(ParseError::UnexpectedBinOp);
}
_ => self.expression.push(op),
}
} else {
self.err = Some(ParseError::UnexpectedEnd);
return Err(ParseError::UnexpectedEnd);
}
Ok(())
}
pub fn open_paren(&mut self) -> Result<(), ParseError> {
self.expression.push('(');
self.paren_stack.push('(');
Ok(())
}
pub fn close_paren(&mut self) -> Result<(), ParseError> {
if self.paren_stack.is_empty() {
self.err = Some(ParseError::UnexpectedExpr);
return Err(ParseError::UnexpectedExpr);
}
self.expression.push(')');
self.paren_stack.pop();
Ok(())
}
pub fn finish(self) -> Result<Expr, ParseError> {
if !self.paren_stack.is_empty() {
return Err(ParseError::UnexpectedExpr);
}
match self.err {
Some(msg) => Err(msg),
None => {
let mut s: u32 = 0;
let mut nd: bool = false;
let mut ro: bool = false;
let mut i: usize = 1;
let len: usize = self.expression.len();
let mut current: Expr = match self.expression[0] {
'!' => {
let mut x = Expr::Atom(self.expression[1]);
s += 1;
while s > 0 {
x = Expr::Not(Box::new(x));
s -= 1;
}
- i += 1; // Skip the next character since it's part of the Not expression
+ i += 1;
x
}
'(' => {
let mut sub_expr = Vec::new();
let mut paren_count = 1;
while i < len && paren_count > 0 {
match self.expression[i] {
'(' => paren_count += 1,
')' => paren_count -= 1,
_ => {}
}
if paren_count > 0 {
sub_expr.push(self.expression[i]);
}
i += 1;
}
let sub_parser = ExprParser {
expression: sub_expr,
err: None,
paren_stack: Vec::new(),
};
sub_parser.finish()?
}
x => Expr::Atom(x),
};
while i < len {
match self.expression[i] {
'!' => s += 1,
'&' => {
nd = true;
}
'|' => {
ro = true;
}
'(' => {
let mut sub_expr = Vec::new();
let mut paren_count = 1;
i += 1;
while i < len && paren_count > 0 {
match self.expression[i] {
'(' => paren_count += 1,
')' => paren_count -= 1,
_ => {}
}
if paren_count > 0 {
sub_expr.push(self.expression[i]);
}
i += 1;
}
let sub_parser = ExprParser {
expression: sub_expr,
err: None,
paren_stack: Vec::new(),
};
let sub_result = sub_parser.finish()?;
current = Expr::And(vec![current, sub_result]);
}
')' => {
return Err(ParseError::UnexpectedEnd);
}
_ => {
let mut x: Expr = Expr::Atom(self.expression[i]);
while s > 0 {
x = Expr::Not(Box::new(x));
s -= 1;
}
if nd {
current = Expr::And(vec![current, x]);
nd = false;
}
else if ro {
current = Expr::Or(vec![current, x]);
ro = false;
}
}
}
i += 1;
}
Ok(current)
}
}
}
}
fn main(){
// let mut simple_parser = SimpleExprParser::new();
// let c = simple_parser.push_op('!');
// let c = simple_parser.push_op('!');
// let a = simple_parser.push_atom('A');
// let b = simple_parser.push_op('&');
// let c = simple_parser.push_op('!');
// let c = simple_parser.push_op('!');
// let c = simple_parser.push_op('!');
// let d = simple_parser.push_atom('B');
// let expr = simple_parser.finish().unwrap();
// println!("{:?}", &expr);
// println!("{:?}", eval(&expr, &['A'], &['B']));
// let mut full_parser = ExprParser::new();
- // let _ = full_parser.open_paren();
// let _ = full_parser.push_atom('A');
- // let _ = full_parser.push_op('&');
- // let _ = full_parser.push_atom('B');
- // let _ = full_parser.close_paren();
// let _ = full_parser.push_op('|');
+ // let _ = full_parser.open_paren();
+ // let _ = full_parser.push_atom('B');
+ // let _ = full_parser.push_op('&');
// let _ = full_parser.push_op('!');
// let _ = full_parser.push_atom('C');
+ // let _ = full_parser.close_paren();
// let expr = full_parser.finish().unwrap();
- // println!("{:?}", eval(&expr, &['A', 'B'], &[]));
+ // println!("{:?}", eval(&expr, &['B'], &[]));
}