feat(ex05): cancel double negation

This commit is contained in:
gbrochar 2024-01-23 21:20:03 +01:00
parent a13dfeaeeb
commit b5e48c41c4
4 changed files with 108 additions and 32 deletions

View File

@ -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<T> {
},
}
impl<T> Node<T>
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<bool> {
pub fn parse_formula(formula: &str) -> Node<bool> {
let mut stack = vec![];
@ -44,19 +66,19 @@ impl Node<bool> {
stack.pop().unwrap()
}
pub fn ast_to_formula(ast: Node<bool>) -> String {
pub fn ast_to_formula(ast: &Node<bool>) -> 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<char> {
stack.pop().unwrap()
}
pub fn ast_to_formula(ast: Node<char>) -> String {
pub fn ast_to_formula(ast: &Node<char>) -> 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
}

View File

@ -17,28 +17,28 @@ mod tests {
#[test]
fn ast_to_formula_bool() {
let formula = "01&";
assert_eq!(Node::<bool>::ast_to_formula(Node::<bool>::parse_formula(formula)), formula);
assert_eq!(Node::<bool>::ast_to_formula(&Node::<bool>::parse_formula(formula)), formula);
let formula = "01&00|&";
assert_eq!(Node::<bool>::ast_to_formula(Node::<bool>::parse_formula(formula)), formula);
assert_eq!(Node::<bool>::ast_to_formula(&Node::<bool>::parse_formula(formula)), formula);
let formula = "01&00|&11^&";
assert_eq!(Node::<bool>::ast_to_formula(Node::<bool>::parse_formula(formula)), formula);
assert_eq!(Node::<bool>::ast_to_formula(&Node::<bool>::parse_formula(formula)), formula);
let formula = "01&00|&11=^";
assert_eq!(Node::<bool>::ast_to_formula(Node::<bool>::parse_formula(formula)), formula);
assert_eq!(Node::<bool>::ast_to_formula(&Node::<bool>::parse_formula(formula)), formula);
let formula = "01&00|&0!=";
assert_eq!(Node::<bool>::ast_to_formula(Node::<bool>::parse_formula(formula)), formula);
assert_eq!(Node::<bool>::ast_to_formula(&Node::<bool>::parse_formula(formula)), formula);
}
#[test]
fn ast_to_formula_char() {
let formula = "AB&";
assert_eq!(Node::<char>::ast_to_formula(Node::<char>::parse_formula(formula)), formula);
assert_eq!(Node::<char>::ast_to_formula(&Node::<char>::parse_formula(formula)), formula);
let formula = "AB&CD|&";
assert_eq!(Node::<char>::ast_to_formula(Node::<char>::parse_formula(formula)), formula);
assert_eq!(Node::<char>::ast_to_formula(&Node::<char>::parse_formula(formula)), formula);
let formula = "AB&AC|&DE^&";
assert_eq!(Node::<char>::ast_to_formula(Node::<char>::parse_formula(formula)), formula);
assert_eq!(Node::<char>::ast_to_formula(&Node::<char>::parse_formula(formula)), formula);
let formula = "AB&CD|&EF=^";
assert_eq!(Node::<char>::ast_to_formula(Node::<char>::parse_formula(formula)), formula);
assert_eq!(Node::<char>::ast_to_formula(&Node::<char>::parse_formula(formula)), formula);
let formula = "AB&CD|&E!=";
assert_eq!(Node::<char>::ast_to_formula(Node::<char>::parse_formula(formula)), formula);
assert_eq!(Node::<char>::ast_to_formula(&Node::<char>::parse_formula(formula)), formula);
}
}

View File

@ -2,6 +2,25 @@ mod tests;
use crate::ast::Node;
// fn cancel_double_negation(ast: &mut Node<char>, parent: Option<&mut Node<char>>) -> Node<char> {
// 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<char>) {
// let mut new_ast = ast.clone();
@ -24,7 +43,35 @@ use crate::ast::Node;
// }
fn negation_normal_form(formula: &str) -> String {
let ast = Node::<char>::parse_formula(formula);
let mut ast = Node::<char>::parse_formula(formula);
// let mut tmp = Node::<char>::parse_formula((formula.to_string() + "!").as_str());
// let mut clone = ast.clone();
Node::<char>::ast_to_formula(ast)
// while Node::<char>::ast_to_formula(&clone) != Node::<char>::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::<char>::ast_to_formula(&ast)
}

View File

@ -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]