Hide intermediate steps in truth table

This commit is contained in:
Martin Berg Alstad 2024-06-17 22:28:41 +02:00
parent 2e9f6cd171
commit bcf8b87f5f

View File

@ -38,7 +38,7 @@ pub enum Sort {
impl TruthTable { impl TruthTable {
pub fn new(expression: &Expression, options: TruthTableOptions) -> Self { pub fn new(expression: &Expression, options: TruthTableOptions) -> Self {
let header = Self::extract_header(expression); let header = Self::extract_header(expression);
let mut truth_matrix = Self::generate_truth_matrix(expression, &header, options.hide); let mut truth_matrix = Self::generate_truth_matrix(expression, &header, options.hide, options.hide_intermediate_steps);
if !matches!(options.sort, Sort::Default) { if !matches!(options.sort, Sort::Default) {
Self::sort_matrix(&mut truth_matrix, options.sort); Self::sort_matrix(&mut truth_matrix, options.sort);
} }
@ -85,7 +85,7 @@ impl TruthTable {
} }
} }
fn generate_truth_matrix(expression: &Expression, header: &[String], hide: Hide) -> TruthMatrix { fn generate_truth_matrix(expression: &Expression, header: &[String], hide: Hide, hide_intermediate: bool) -> TruthMatrix {
let mut atomics = expression.get_atomic_values() let mut atomics = expression.get_atomic_values()
.into_iter().collect::<Vec<String>>(); .into_iter().collect::<Vec<String>>();
if atomics.is_empty() { if atomics.is_empty() {
@ -97,7 +97,7 @@ impl TruthTable {
let expression = Self::resolve_expression(expression, &atomics.iter() let expression = Self::resolve_expression(expression, &atomics.iter()
.enumerate() .enumerate()
.map(|(index, value)| (value.clone(), combo[index])) .map(|(index, value)| (value.clone(), combo[index]))
.collect(), header); .collect(), header, hide_intermediate);
match (hide, expression.last()) { match (hide, expression.last()) {
(Hide::True, Some(false)) => Some(expression), (Hide::True, Some(false)) => Some(expression),
(Hide::False, Some(true)) => Some(expression), (Hide::False, Some(true)) => Some(expression),
@ -115,14 +115,30 @@ impl TruthTable {
).collect() ).collect()
} }
fn resolve_expression(expression: &Expression, booleans: &HashMap<String, bool>, header: &[String]) -> Vec<bool> { fn resolve_expression(expression: &Expression, booleans: &HashMap<String, bool>, header: &[String], hide_intermediate: bool) -> Vec<bool> {
let expression_map = Self::_resolve_expression(expression, booleans); let mut expression_map = Self::_resolve_expression(expression, booleans);
if hide_intermediate {
expression_map = Self::remove_intermediate_steps(expression_map);
}
let string_map = expression_map.iter() let string_map = expression_map.iter()
.map(|(key, value)| (key.to_string(), *value)) .map(|(key, value)| (key.to_string(), *value))
.collect::<HashMap<String, bool>>(); .collect::<HashMap<String, bool>>();
header.iter() header.iter()
.map(|s_expr| string_map.get(s_expr).copied().expect("Expression not found in map")) .filter_map(|s_expr| string_map.get(s_expr).copied())
.collect()
}
fn remove_intermediate_steps(expression_map: HashMap<&Expression, bool>) -> HashMap<&Expression, bool> {
expression_map.iter()
.enumerate()
.filter_map(|(index, (key, value))| {
if key.is_atomic() || index == expression_map.len() - 1 {
Some((*key, *value))
} else {
None
}
})
.collect() .collect()
} }
@ -279,7 +295,7 @@ mod tests {
let matrix = TruthTable::generate_truth_matrix( let matrix = TruthTable::generate_truth_matrix(
&and(atomic("A"), atomic("B")), &and(atomic("A"), atomic("B")),
&["A".into(), "B".into(), "A ⋀ B".into()], &["A".into(), "B".into(), "A ⋀ B".into()],
Hide::True, Hide::True, false,
); );
assert_eq!(expected, matrix); assert_eq!(expected, matrix);
} }
@ -292,7 +308,7 @@ mod tests {
let matrix = TruthTable::generate_truth_matrix( let matrix = TruthTable::generate_truth_matrix(
&and(atomic("A"), atomic("B")), &and(atomic("A"), atomic("B")),
&["A".into(), "B".into(), "A ⋀ B".into()], &["A".into(), "B".into(), "A ⋀ B".into()],
Hide::False, Hide::False, false,
); );
assert_eq!(expected, matrix); assert_eq!(expected, matrix);
} }
@ -308,7 +324,7 @@ mod tests {
let matrix = TruthTable::generate_truth_matrix( let matrix = TruthTable::generate_truth_matrix(
&and(atomic("A"), atomic("B")), &and(atomic("A"), atomic("B")),
&["A".into(), "B".into(), "A ⋀ B".into()], &["A".into(), "B".into(), "A ⋀ B".into()],
Hide::None, Hide::None, false,
); );
assert_eq!(expected, matrix); assert_eq!(expected, matrix);
} }
@ -339,12 +355,22 @@ mod tests {
]); ]);
} }
#[test]
fn test_resolve_expression_hide_intermediate_steps() {
let expression = and(atomic("A"), or(atomic("B"), atomic("C")));
let booleans = map!["A".into() => true, "B".into() => false, "C".into() => true];
let header = vec!["A".into(), "B".into(), "C".into(), "B C".into(), "A ⋀ (B C)".into()];
let values = TruthTable::resolve_expression(&expression, &booleans, &header, true);
assert_eq!(values.len(), 4);
assert_eq!(values, vec![true, false, true, true]);
}
#[test] #[test]
fn test_resolve_expression_and_all_true() { fn test_resolve_expression_and_all_true() {
let expression = and(atomic("A"), atomic("B")); let expression = and(atomic("A"), atomic("B"));
let booleans = map!["A".into() => true, "B".into() => true]; let booleans = map!["A".into() => true, "B".into() => true];
let header = vec!["A".into(), "B".into(), "A ⋀ B".into()]; let header = vec!["A".into(), "B".into(), "A ⋀ B".into()];
let values = TruthTable::resolve_expression(&expression, &booleans, &header); let values = TruthTable::resolve_expression(&expression, &booleans, &header, false);
assert_eq!(values, vec![true, true, true]); assert_eq!(values, vec![true, true, true]);
} }
@ -353,7 +379,7 @@ mod tests {
let expression = and(atomic("A"), atomic("B")); let expression = and(atomic("A"), atomic("B"));
let booleans = map!["A".into() => true, "B".into() => false]; let booleans = map!["A".into() => true, "B".into() => false];
let header = vec!["A".into(), "B".into(), "A ⋀ B".into()]; let header = vec!["A".into(), "B".into(), "A ⋀ B".into()];
let values = TruthTable::resolve_expression(&expression, &booleans, &header); let values = TruthTable::resolve_expression(&expression, &booleans, &header, false);
assert_eq!(values, vec![true, false, false]); assert_eq!(values, vec![true, false, false]);
} }
@ -362,7 +388,7 @@ mod tests {
let expression = or(atomic("A"), atomic("B")); let expression = or(atomic("A"), atomic("B"));
let booleans = map!["A".into() => true, "B".into() => false]; let booleans = map!["A".into() => true, "B".into() => false];
let header = vec!["A".into(), "B".into(), "A B".into()]; let header = vec!["A".into(), "B".into(), "A B".into()];
let values = TruthTable::resolve_expression(&expression, &booleans, &header); let values = TruthTable::resolve_expression(&expression, &booleans, &header, false);
assert_eq!(values, vec![true, false, true]); assert_eq!(values, vec![true, false, true]);
} }
@ -371,7 +397,7 @@ mod tests {
let expression = and(atomic("A"), atomic("A")); let expression = and(atomic("A"), atomic("A"));
let booleans = map!["A".into() => true]; let booleans = map!["A".into() => true];
let header = vec!["A".into(), "A ⋀ A".into()]; let header = vec!["A".into(), "A ⋀ A".into()];
let values = TruthTable::resolve_expression(&expression, &booleans, &header); let values = TruthTable::resolve_expression(&expression, &booleans, &header, false);
assert_eq!(values, vec![true, true]); assert_eq!(values, vec![true, true]);
} }
@ -380,7 +406,7 @@ mod tests {
let expression = and(atomic("A"), and(atomic("A"), and(atomic("A"), atomic("A")))); let expression = and(atomic("A"), and(atomic("A"), and(atomic("A"), atomic("A"))));
let booleans = HashMap::from([("A".into(), true)]); let booleans = HashMap::from([("A".into(), true)]);
let header = vec!["A".into(), "A ⋀ A".into(), "A ⋀ A ⋀ A".into(), "A ⋀ A ⋀ A ⋀ A".into()]; let header = vec!["A".into(), "A ⋀ A".into(), "A ⋀ A ⋀ A".into(), "A ⋀ A ⋀ A ⋀ A".into()];
let values = TruthTable::resolve_expression(&expression, &booleans, &header); let values = TruthTable::resolve_expression(&expression, &booleans, &header, false);
assert_eq!(values, vec![true, true, true, true]); assert_eq!(values, vec![true, true, true, true]);
} }