103 lines
3.1 KiB
Rust
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
|
|
}
|