From ccde9fa53983212cfef9de144c1dbb6026059c60 Mon Sep 17 00:00:00 2001 From: gbrochar Date: Thu, 25 Jan 2024 18:42:09 +0100 Subject: [PATCH] feat(ex06): generate karnaugh map func --- src/conjunctive_normal_form.rs | 68 ++++++++++++++++++++++++++++ src/conjunctive_normal_form/tests.rs | 48 ++++++++++++++++++++ src/gray_code/tests.rs | 20 ++++---- src/main.rs | 4 ++ 4 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 src/conjunctive_normal_form.rs create mode 100644 src/conjunctive_normal_form/tests.rs diff --git a/src/conjunctive_normal_form.rs b/src/conjunctive_normal_form.rs new file mode 100644 index 0000000..52fa604 --- /dev/null +++ b/src/conjunctive_normal_form.rs @@ -0,0 +1,68 @@ +mod tests; + +use crate::ast::Node; +use crate::boolean_evaluation::eval_formula; +use crate::gray_code::gray_code; + +fn get_variables(formula: &str) -> Vec { + let mut v: Vec = formula.chars().collect(); + v.sort(); + v.dedup(); + v.into_iter().filter(|x| x.is_ascii_uppercase()).collect() +} + +fn bool_to_str(a: u32) -> &'static str { + match a { + 0 => "0", + _ => "1" + } +} + +fn replace_var(formula: &str, variables: &[char], size: (usize, usize), coor: (u32, u32)) -> String { + let gray_x = gray_code(coor.0); + let gray_y = gray_code(coor.1); + let mut ret = String::from(formula); + dbg!(size); + dbg!(coor); + for i in 0..size.0 { + ret = ret.as_str().replace(variables[i], bool_to_str(gray_x & 1 << i)); + } + for i in 0..size.1 { + ret = ret.as_str().replace(variables[size.0 + i], bool_to_str(gray_y & 1 << i)); + } + dbg!(&ret); + String::from(ret) +} + +fn get_karnaugh_map(formula: &str, variables: &[char]) -> Vec> { + let lines = (variables.len()+1)/2; + let columns = variables.len() - lines; + let mut map = vec![]; + for y in 0..1<>, variables: &[char]) -> String { + dbg!(map); + String::from("") +} + +pub fn conjunctive_normal_form(formula: &str) -> String { + let variables = &get_variables(formula); + if variables.len() == 1 { + return match (eval_formula(formula.replace(variables[0], "0").as_str()), + eval_formula(formula.replace(variables[0], "1").as_str())) { + (false, false) => "AA!&".replace("A", &variables[0].to_string()), + (false, true) => String::from(variables[0]), + (true, false) => "A!".replace("A", &variables[0].to_string()), + (true, true) => "AA!|".replace("A", &variables[0].to_string()) + } + } + let map = get_karnaugh_map(formula, variables); + map_to_formula(map, variables) +} diff --git a/src/conjunctive_normal_form/tests.rs b/src/conjunctive_normal_form/tests.rs new file mode 100644 index 0000000..5886547 --- /dev/null +++ b/src/conjunctive_normal_form/tests.rs @@ -0,0 +1,48 @@ +#[cfg(test)] +mod tests { + use std::env::current_dir; + + use crate::conjunctive_normal_form::{conjunctive_normal_form, get_karnaugh_map}; + + #[test] + fn subject_tests() { + assert_eq!(conjunctive_normal_form("AB&!"), "A!B!|"); + assert_eq!(conjunctive_normal_form("AB|!"), "A!B!&"); + assert_eq!(conjunctive_normal_form("AB|C&"), "AB|C&"); + assert_eq!(conjunctive_normal_form("AB|C|D|"), "ABCD|||"); + assert_eq!(conjunctive_normal_form("AB&C&D&"), "ABCD&&&"); + assert_eq!(conjunctive_normal_form("AB&!C!|"), "A!B!C!||"); + assert_eq!(conjunctive_normal_form("AB|!C!&"), "A!B!C!&&"); + } + + #[test] + fn my_test() { + assert_eq!(conjunctive_normal_form("ABC&&"), "ABC&&"); + assert_eq!(conjunctive_normal_form("AAA&&"), "A"); + } + + #[test] + fn karnaugh_map() { + assert_eq!(get_karnaugh_map("ABC&&", &vec!['A', 'B', 'C']), vec![ + vec![false, false], + vec![false, false], + vec![false, true], + vec![false, false], + ]); + assert_eq!(get_karnaugh_map("AB^CD=&", &vec!['A', 'B', 'C', 'D']), vec![ + vec![false, false, false, false], + vec![true, false, true, false], + vec![false, false, false, false], + vec![true, false, true, false], + ]); + } + + #[test] + fn one_var() { + assert_eq!(conjunctive_normal_form("AAA&&"), "A"); + assert_eq!(conjunctive_normal_form("AAA!&&"), "AA!&"); + assert_eq!(conjunctive_normal_form("AAA!|&"), "A"); + assert_eq!(conjunctive_normal_form("AAA!||"), "AA!|"); + assert_eq!(conjunctive_normal_form("A!A!A!&&"), "A!"); + } +} diff --git a/src/gray_code/tests.rs b/src/gray_code/tests.rs index 6b4d321..4f84f84 100644 --- a/src/gray_code/tests.rs +++ b/src/gray_code/tests.rs @@ -4,16 +4,16 @@ mod tests { #[test] fn digits() { - assert_eq!(gray_code(0), 0); - assert_eq!(gray_code(1), 1); - assert_eq!(gray_code(2), 3); - assert_eq!(gray_code(3), 2); - assert_eq!(gray_code(4), 6); - assert_eq!(gray_code(5), 7); - assert_eq!(gray_code(6), 5); - assert_eq!(gray_code(7), 4); - assert_eq!(gray_code(8), 12); - assert_eq!(gray_code(9), 13); + assert_eq!(gray_code(0), 0b0000); + assert_eq!(gray_code(1), 0b0001); + assert_eq!(gray_code(2), 0b0011); + assert_eq!(gray_code(3), 0b0010); + assert_eq!(gray_code(4), 0b0110); + assert_eq!(gray_code(5), 0b0111); + assert_eq!(gray_code(6), 0b0101); + assert_eq!(gray_code(7), 0b0100); + assert_eq!(gray_code(8), 0b1100); + assert_eq!(gray_code(9), 0b1101); } #[test] diff --git a/src/main.rs b/src/main.rs index 83a0d5c..91b1582 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ mod boolean_evaluation; mod gray_code; mod multiplier; mod negation_normal_form; +mod conjunctive_normal_form; mod truth_table; use gray_code::gray_code; @@ -23,6 +24,7 @@ fn main() { println!("{}", gray_code(3)); print_truth_table("ZFG|&"); print_truth_table("ABC|&"); + print_truth_table("AY&BZ|&"); let formula = "AB=CD^|!AD!^!&!"; println!("{formula}"); print_truth_table(formula); @@ -30,4 +32,6 @@ fn main() { println!("{formula}"); print_truth_table(formula); + print_truth_table("AZ&BY|&"); + }