ready_set_boole/src/truth_table.rs

103 lines
3.1 KiB
Rust

mod tests;
use crate::ast::{add_binary_node, add_unary_node, Node, Token};
use std::collections::HashSet;
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 |"),
}
}
}
pub 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.into_iter().rev().collect(), String::from("|"));
// call eval formula a lot
}