feat(ex04): boolean evaluation

This commit is contained in:
gbrochar 2024-01-05 17:11:59 +01:00
parent 8031391a61
commit afb5d7d105
6 changed files with 128 additions and 0 deletions

42
src/ast.rs Normal file
View File

@ -0,0 +1,42 @@
#[derive(Debug, Clone)]
pub enum Token {
Negation,
Conjunction,
Disjunction,
ExclusiveDisjunction,
MaterialCondition,
LogicalEquivalence
}
#[derive(Debug, Clone)]
pub enum Node<T> {
Leaf(T),
Unary {
operator: Token,
operand: Box<Node<T>>
},
Binary {
operator: Token,
lhs: Box<Node<T>>,
rhs: Box<Node<T>>,
},
}
pub fn add_unary_node<T>(stack: &mut Vec<Node<T>>, token: Token) {
let operand = Box::new(stack.pop().unwrap());
stack.push(Node::Unary {
operator: token,
operand,
});
}
pub fn add_binary_node<T>(stack: &mut Vec<Node<T>>, token: Token) {
let lhs = Box::new(stack.pop().unwrap());
let rhs = Box::new(stack.pop().unwrap());
stack.push(Node::Binary {
operator: token,
lhs,
rhs
});
}

13
src/ast/tests.rs Normal file
View File

@ -0,0 +1,13 @@
#[cfg(test)]
mod tests {
#[test]
fn add_nodes() {
let stack = vec![Node::Leaf(true), Node::Leaf(false)];
let rhs = vec![Node::Binary {
operator: Token::Conjunction,
lhs: Box::new(Node::Leaf(true)),
rhs: Box::new(Node::Leaf(false))
}];
assert_eq!(add_binary_node(&mut stack, Token::Conjunction), rhs);
}
}

45
src/boolean_evaluation.rs Normal file
View File

@ -0,0 +1,45 @@
mod tests;
use crate::ast::{ Token, Node, add_unary_node, add_binary_node };
fn parse_formula(formula: &str) -> Node<bool> {
let mut stack = vec![];
for c in formula.chars() {
match c {
'0' => stack.push(Node::Leaf(false)),
'1' => stack.push(Node::Leaf(true)),
'!' => add_unary_node(&mut stack, Token::Negation),
'&' => add_binary_node(&mut stack, Token::Conjunction),
'|' => add_binary_node(&mut stack, Token::Disjunction),
'^' => add_binary_node(&mut stack, Token::ExclusiveDisjunction),
'>' => add_binary_node(&mut stack, Token::MaterialCondition),
'=' => add_binary_node(&mut stack, Token::LogicalEquivalence),
_ => panic!("Error: {} is not a valid character", c)
}
}
stack.pop().unwrap()
}
fn compute(operator: Token, lhs: bool, rhs: bool) -> bool {
match operator {
Token::Negation => !lhs,
Token::Conjunction => lhs & rhs,
Token::Disjunction => lhs | rhs,
Token::ExclusiveDisjunction => lhs ^ rhs,
Token::MaterialCondition => !(lhs && !rhs),
Token::LogicalEquivalence => lhs == rhs
}
}
fn evaluate(tree: Node<bool>) -> bool {
match tree {
Node::Unary { operator, operand } => compute(operator, evaluate(*operand), false),
Node::Binary { operator, lhs, rhs } => compute(operator, evaluate(*lhs), evaluate(*rhs)),
Node::Leaf(b) => b,
}
}
fn eval_formula(formula: &str) -> bool {
let tree = parse_formula(formula);
evaluate(tree)
}

View File

@ -0,0 +1,26 @@
#[cfg(test)]
mod tests {
use crate::boolean_evaluation::eval_formula;
#[test]
fn only_binary() {
assert_eq!(eval_formula("10&"), false);
assert_eq!(eval_formula("10|"), true);
assert_eq!(eval_formula("11>"), true);
assert_eq!(eval_formula("10="), false);
assert_eq!(eval_formula("1011||="), true);
}
#[test]
fn only_unary() {
assert_eq!(eval_formula("1!"), false);
assert_eq!(eval_formula("0!"), true);
}
#[test]
fn binary_and_uneray() {
assert_eq!(eval_formula("10&!"), true);
assert_eq!(eval_formula("11&!"), false);
}
}

View File

@ -1,6 +1,8 @@
mod adder;
mod multiplier;
mod gray_code;
mod boolean_evaluation;
mod ast;
use gray_code::gray_code;

0
src/truth_table,rs Normal file
View File