diff --git a/src/expressions/truth_table.rs b/src/expressions/truth_table.rs index f2a4371..ce32b46 100644 --- a/src/expressions/truth_table.rs +++ b/src/expressions/truth_table.rs @@ -1,7 +1,8 @@ use serde::{Deserialize, Serialize}; use crate::expressions::expression::Expression; -use crate::utils::array::Distinct; +use crate::matrix; +use crate::utils::array::{alternating_array, Distinct}; type TruthMatrix = Vec>; @@ -76,26 +77,60 @@ impl TruthTable { } fn generate_truth_matrix(expression: &Expression) -> TruthMatrix { + let count = expression.count_distinct(); + if count == 0 { + return vec![]; + } + let helper = Self::helper_matrix(count); + let truths = Self::generate_truth_table(&helper, expression); todo!() } fn helper_matrix(number_of_atomics: usize) -> TruthMatrix { - todo!("Create a matrix with 2^number_of_atomics rows and number_of_atomics columns") + let len = 2usize.pow(number_of_atomics as u32); + let mut change_index = len / 2; + let mut rows: Vec> = matrix![false; 0 => number_of_atomics]; + for row in &mut rows { + *row = alternating_array(len, change_index); + change_index /= 2; + } + rows } - fn resolve_expression(expression: &Expression, row: &[bool]) -> bool { + // TODO store the expressions along with their values in a list tree structure + // For each node. Their left child is index * 2 + 1 and right child is index * 2 + 2 + // Ex: 0 -> (1, 2), 1 -> (3, 4), 2 -> (5, 6) + fn generate_truth_table<'a>(helper: &TruthMatrix, expression: &'a Expression) -> Vec> { + todo!("Generate the truth table for the given expression") + } + + fn resolve_expression(expression: &Expression, truths: &[Option<(&Expression, bool)>]) -> bool { todo!("Resolve the expression with the given row of booleans") } - - fn find_expression(expression: Expression, expressions: &[Expression]) -> Option { - todo!("Find the expression in the truth table and return index") - } } #[cfg(test)] mod tests { + use crate::matrix; + use super::*; + #[test] + fn test_helper_matrix_3() { + let helper = TruthTable::helper_matrix(3); + assert_eq!(helper, matrix![ + true, true, true, true, false, false, false, false; + true, true, false, false, true, true, false, false; + true, false, true, false, true, false, true, false + ]); + } + + #[test] + fn test_helper_matrix_1() { + let helper = TruthTable::helper_matrix(1); + assert_eq!(helper, matrix![true, false]); + } + #[test] fn test_atomic_expression() { let expression = atomic!("A"); diff --git a/src/utils/array.rs b/src/utils/array.rs index fce5722..a69466f 100644 --- a/src/utils/array.rs +++ b/src/utils/array.rs @@ -1,4 +1,6 @@ +use std::cmp::max; use std::ops::{Deref, DerefMut}; + #[macro_export] macro_rules! set { () => { std::collections::HashSet::new() }; @@ -13,6 +15,24 @@ macro_rules! set { }; } +#[macro_export] +macro_rules! matrix { + ($($($x:expr),*);*) => { + { + let mut temp_vec = vec![]; + {} // Needed to avoid clippy warning + $( + temp_vec.push(vec![$($x),*]); + )* + temp_vec + } + }; + ($x:expr; $m:expr => $n:expr) => { + vec![vec![$x; $m]; $n] + }; +} + + pub trait Distinct { fn distinct(&mut self); } @@ -29,10 +49,44 @@ impl Distinct for Vec { } } +pub fn alternating_array(n: usize, mut skip: usize) -> Vec { + skip = max(skip, 1); + let mut array = vec![false; n]; + let mut cell_value = false; + for (index, value) in array.iter_mut().enumerate() { + if index % skip == 0 { + cell_value = !cell_value; + } + *value = cell_value; + } + array +} + #[cfg(test)] mod tests { use super::*; + #[test] + fn test_alternating_array() { + assert_eq!(alternating_array(4, 2), vec![true, true, false, false]); + assert_eq!(alternating_array(5, 1), vec![true, false, true, false, true]); + } + + #[test] + fn test_alternating_array_0_skip() { + assert_eq!(alternating_array(4, 0), vec![true, false, true, false]); + } + + #[test] + fn test_alternating_array_0_length() { + assert_eq!(alternating_array(0, 2), vec![] as Vec); + } + + #[test] + fn test_alternating_array_skip_greater_than_length() { + assert_eq!(alternating_array(4, 5), vec![true, true, true, true]); + } + #[test] fn test_distinct() { let mut vec = vec![1, 2, 3, 1, 2, 3];