From b5e48c41c4ba1ea314a09e8c5f5eda8e8de366cf Mon Sep 17 00:00:00 2001 From: gbrochar Date: Tue, 23 Jan 2024 21:20:03 +0100 Subject: [PATCH] feat(ex05): cancel double negation --- src/ast.rs | 52 ++++++++++++++++++++++--------- src/ast/tests.rs | 20 ++++++------ src/negation_normal_form.rs | 51 ++++++++++++++++++++++++++++-- src/negation_normal_form/tests.rs | 17 +++++++--- 4 files changed, 108 insertions(+), 32 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 3dd53a6..711ad0e 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,7 +1,7 @@ mod tests; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum Token { Negation, Conjunction, @@ -25,6 +25,28 @@ pub enum Node { }, } +impl Node +where T: Clone { + pub fn simplify(&mut self) { + match self { + Node::Unary { operator, operand } if *operator == Token::Negation => { + if let Node::Unary { operator: inner_op, operand: inner_operand } = &**operand { + if *inner_op == Token::Negation { + *self = *inner_operand.clone(); // Replace unary node with its operand + self.simplify(); // Continue simplification recursively + } + } + } + Node::Binary { lhs, rhs, .. } => { + lhs.simplify(); + rhs.simplify(); + } + _ => {} + } + } +} + + impl Node { pub fn parse_formula(formula: &str) -> Node { let mut stack = vec![]; @@ -44,19 +66,19 @@ impl Node { stack.pop().unwrap() } - pub fn ast_to_formula(ast: Node) -> String { + pub fn ast_to_formula(ast: &Node) -> String { let mut str = String::from(""); match ast { Node::Unary { operator, operand } => { - str.push_str(Self::ast_to_formula(*operand).as_str()); - str.push(token_to_char(operator)); + str.push_str(Self::ast_to_formula(operand).as_str()); + str.push(token_to_char(*operator)); }, Node::Binary { operator, lhs, rhs } => { - str.push_str(Self::ast_to_formula(*lhs).as_str()); - str.push_str(Self::ast_to_formula(*rhs).as_str()); - str.push(token_to_char(operator)); + str.push_str(Self::ast_to_formula(lhs).as_str()); + str.push_str(Self::ast_to_formula(rhs).as_str()); + str.push(token_to_char(*operator)); }, - Node::Leaf(b) => str.push(bool_to_char(b)), + Node::Leaf(b) => str.push(bool_to_char(*b)), }; str } @@ -80,19 +102,19 @@ impl Node { stack.pop().unwrap() } - pub fn ast_to_formula(ast: Node) -> String { + pub fn ast_to_formula(ast: &Node) -> String { let mut str = String::from(""); match ast { Node::Unary { operator, operand } => { - str.push_str(Self::ast_to_formula(*operand).as_str()); - str.push(token_to_char(operator)); + str.push_str(Self::ast_to_formula(operand).as_str()); + str.push(token_to_char(*operator)); }, Node::Binary { operator, lhs, rhs } => { - str.push_str(Self::ast_to_formula(*lhs).as_str()); - str.push_str(Self::ast_to_formula(*rhs).as_str()); - str.push(token_to_char(operator)); + str.push_str(Self::ast_to_formula(lhs).as_str()); + str.push_str(Self::ast_to_formula(rhs).as_str()); + str.push(token_to_char(*operator)); }, - Node::Leaf(c) => str.push(c), + Node::Leaf(c) => str.push(*c), }; str } diff --git a/src/ast/tests.rs b/src/ast/tests.rs index d878aaf..28f9c73 100644 --- a/src/ast/tests.rs +++ b/src/ast/tests.rs @@ -17,28 +17,28 @@ mod tests { #[test] fn ast_to_formula_bool() { let formula = "01&"; - assert_eq!(Node::::ast_to_formula(Node::::parse_formula(formula)), formula); + assert_eq!(Node::::ast_to_formula(&Node::::parse_formula(formula)), formula); let formula = "01&00|&"; - assert_eq!(Node::::ast_to_formula(Node::::parse_formula(formula)), formula); + assert_eq!(Node::::ast_to_formula(&Node::::parse_formula(formula)), formula); let formula = "01&00|&11^&"; - assert_eq!(Node::::ast_to_formula(Node::::parse_formula(formula)), formula); + assert_eq!(Node::::ast_to_formula(&Node::::parse_formula(formula)), formula); let formula = "01&00|&11=^"; - assert_eq!(Node::::ast_to_formula(Node::::parse_formula(formula)), formula); + assert_eq!(Node::::ast_to_formula(&Node::::parse_formula(formula)), formula); let formula = "01&00|&0!="; - assert_eq!(Node::::ast_to_formula(Node::::parse_formula(formula)), formula); + assert_eq!(Node::::ast_to_formula(&Node::::parse_formula(formula)), formula); } #[test] fn ast_to_formula_char() { let formula = "AB&"; - assert_eq!(Node::::ast_to_formula(Node::::parse_formula(formula)), formula); + assert_eq!(Node::::ast_to_formula(&Node::::parse_formula(formula)), formula); let formula = "AB&CD|&"; - assert_eq!(Node::::ast_to_formula(Node::::parse_formula(formula)), formula); + assert_eq!(Node::::ast_to_formula(&Node::::parse_formula(formula)), formula); let formula = "AB&AC|&DE^&"; - assert_eq!(Node::::ast_to_formula(Node::::parse_formula(formula)), formula); + assert_eq!(Node::::ast_to_formula(&Node::::parse_formula(formula)), formula); let formula = "AB&CD|&EF=^"; - assert_eq!(Node::::ast_to_formula(Node::::parse_formula(formula)), formula); + assert_eq!(Node::::ast_to_formula(&Node::::parse_formula(formula)), formula); let formula = "AB&CD|&E!="; - assert_eq!(Node::::ast_to_formula(Node::::parse_formula(formula)), formula); + assert_eq!(Node::::ast_to_formula(&Node::::parse_formula(formula)), formula); } } \ No newline at end of file diff --git a/src/negation_normal_form.rs b/src/negation_normal_form.rs index 88439d8..2da9cb1 100644 --- a/src/negation_normal_form.rs +++ b/src/negation_normal_form.rs @@ -2,6 +2,25 @@ mod tests; use crate::ast::Node; +// fn cancel_double_negation(ast: &mut Node, parent: Option<&mut Node>) -> Node { +// match ast { +// Node::Unary { operator: _, operand } => { +// if let Some(node) = parent { + +// } else { +// *ast = cancel_double_negation(&mut *operand, Some(ast)); +// } +// }, +// Node::Binary { operator: _, lhs, rhs } => { +// *ast = cancel_double_negation(&mut *lhs, None); +// *ast = cancel_double_negation(&mut *rhs, None); +// }, +// Node::Leaf(c) => (), +// } + +// ast +// } + // fn cancel_double_negation(ast: Node) { // let mut new_ast = ast.clone(); @@ -24,7 +43,35 @@ use crate::ast::Node; // } fn negation_normal_form(formula: &str) -> String { - let ast = Node::::parse_formula(formula); + let mut ast = Node::::parse_formula(formula); + // let mut tmp = Node::::parse_formula((formula.to_string() + "!").as_str()); + // let mut clone = ast.clone(); - Node::::ast_to_formula(ast) + // while Node::::ast_to_formula(&clone) != Node::::ast_to_formula(&tmp) { + // let copy = ast.clone(); + // clone = ast.clone(); + + // dbg!(&ast); + + // tmp = match copy { + // Node::Unary { operator: _, operand } => { + // match *operand { + // Node::Unary { operator: _, operand } => { + // println!("salut"); + // dbg!(&*operand); + // *operand + // } + // Node::Binary { operator: _, lhs: _, rhs: _ } => ast, + // Node::Leaf(_) => ast, + + // } + // } + // Node::Binary { operator: _, lhs: _, rhs: _ } => ast, + // Node::Leaf(_) => ast, + // }; + + // ast = tmp.clone(); + // } + ast.simplify(); + Node::::ast_to_formula(&ast) } \ No newline at end of file diff --git a/src/negation_normal_form/tests.rs b/src/negation_normal_form/tests.rs index ff08058..8318195 100644 --- a/src/negation_normal_form/tests.rs +++ b/src/negation_normal_form/tests.rs @@ -3,12 +3,19 @@ mod tests { use crate::negation_normal_form::negation_normal_form; #[test] - fn double_neg() { + fn double_neg_simple() { assert_eq!(negation_normal_form("A!!"), "A"); - assert_eq!(negation_normal_form("A!!!!"), "A"); - assert_eq!(negation_normal_form("A!!!"), "A!"); - assert_eq!(negation_normal_form("A!!!!!!!!!!!!!!!!"), "A"); - assert_eq!(negation_normal_form("A!!!!!!!!!!!!!!!"), "A!"); + assert_eq!(negation_normal_form("B!!!!"), "B"); + assert_eq!(negation_normal_form("C!!!"), "C!"); + assert_eq!(negation_normal_form("D!!!!!!!!!!!!!!!!"), "D"); + assert_eq!(negation_normal_form("E!!!!!!!!!!!!!!!"), "E!"); + } + + #[test] + fn double_neg() { + assert_eq!(negation_normal_form("A!!B&"), "AB&"); + assert_eq!(negation_normal_form("A!!B!!&"), "AB&"); + assert_eq!(negation_normal_form("A!!B!&"), "AB!&"); } #[test]