diff --git a/src/boolean_evaluation/tests.rs b/src/boolean_evaluation/tests.rs index 3ecffe4..daa6150 100644 --- a/src/boolean_evaluation/tests.rs +++ b/src/boolean_evaluation/tests.rs @@ -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); diff --git a/src/main.rs b/src/main.rs index b32469d..79b9e84 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod adder; mod multiplier; mod gray_code; mod boolean_evaluation; +mod truth_table; mod ast; use gray_code::gray_code; diff --git a/src/truth_table,rs b/src/truth_table,rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/truth_table.rs b/src/truth_table.rs new file mode 100644 index 0000000..3ec29f5 --- /dev/null +++ b/src/truth_table.rs @@ -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 { + 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 { + 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 { + 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, 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 = get_hashset(formula); + let mut vec: Vec = 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 +} \ No newline at end of file diff --git a/src/truth_table/tests.rs b/src/truth_table/tests.rs new file mode 100644 index 0000000..e092e43 --- /dev/null +++ b/src/truth_table/tests.rs @@ -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&&&") + } +}