feat(ex05): truth table

This commit is contained in:
gbrochar 2024-01-08 15:54:10 +01:00
parent afb5d7d105
commit b8c12047a5
5 changed files with 130 additions and 0 deletions

View File

@ -18,6 +18,15 @@ mod tests {
}
#[test]
fn chained_unary() {
assert_eq!(eval_formula("1!!"), true);
assert_eq!(eval_formula("0!!"), false);
assert_eq!(eval_formula("0!!!"), true);
assert_eq!(eval_formula("1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"), true);
}
#[test]
fn binary_and_uneray() {
assert_eq!(eval_formula("10&!"), true);

View File

@ -2,6 +2,7 @@ mod adder;
mod multiplier;
mod gray_code;
mod boolean_evaluation;
mod truth_table;
mod ast;
use gray_code::gray_code;

View File

92
src/truth_table.rs Normal file
View File

@ -0,0 +1,92 @@
mod tests;
use std::collections::HashSet;
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 get_hashset(formula: &str) -> HashSet<char> {
let mut hashset = HashSet::new();
for c in formula.chars() {
match c {
'A'..='Z' => { hashset.insert(c); },
'!' | '&' | '|' | '^' | '>' | '=' => (),
_ => panic!("Error: {} is not a valid character", c),
}
}
hashset
}
fn eval_formula(formula: &str) -> bool {
let tree = parse_formula(formula);
evaluate(tree)
}
fn recursive_fn(formula: &str, mut vec: Vec<char>, format: String) {
let char = vec.pop();
if let Some(c) = char {
recursive_fn(formula.replace(c, "0").as_str(), vec.clone(), format!("{format} 0 |"));
recursive_fn(formula.replace(c, "1").as_str(), vec.clone(), format!("{format} 1 |"));
} else {
match eval_formula(formula) {
false => println!("{format} 0 |"),
true => println!("{format} 1 |"),
}
}
}
fn print_truth_table(formula: &str) {
let set: HashSet<char> = get_hashset(formula);
let mut vec: Vec<char> = set.iter().cloned().collect();
vec.sort();
let mut format = String::from("|");
let mut separator = String::from("|");
for i in vec.clone() {
format = format!("{format} {i} |");
separator = format!("{separator}---|");
}
format = format!("{format} = |");
separator = format!("{separator}---|");
println!("{format}");
println!("{separator}");
recursive_fn(formula, vec, String::from("|"));
// call eval formula a lot
}

28
src/truth_table/tests.rs Normal file
View File

@ -0,0 +1,28 @@
#[cfg(test)]
mod tests {
use crate::truth_table::print_truth_table;
#[test]
fn only_binary() {
print_truth_table("AB&");
print_truth_table("AB|");
print_truth_table("AB>");
print_truth_table("AB=");
print_truth_table("ABCD||=");
}
#[test]
fn only_unary() {
print_truth_table("A!");
}
#[test]
fn binary_and_uneray() {
print_truth_table("AB&!");
}
#[test]
fn big() {
print_truth_table("AB&CD&&EF&GH&&&IJ&KL&&MN&OP&&&QR&ST&&UV&WX&&&YZ&&&")
}
}