Option to sort truthTable

This commit is contained in:
Martin Berg Alstad 2024-06-16 00:12:52 +02:00
parent 32d5089b44
commit b9998ce7bf
2 changed files with 112 additions and 12 deletions

View File

@ -62,3 +62,23 @@ GET {{url}}/simplify/{{expression}}?simplify=false
expression("A & B | C")
%}
GET {{url}}/simplify/table/{{expression}}
### GET with table sorted by true first
< {%
import {expression} from "./common";
expression("A & B | C")
%}
GET {{url}}/simplify/table/{{expression}}?sort=TRUE_FIRST
> {%
client.test("Response body is sorted by true first", () => {
const table = response.body.truthTable;
const results = table.truthMatrix.map(arr => arr[arr.length - 1])
const expected = results.slice() // Creates a copy of the array
expected.sort((a, b) => b - a)
for (let i = 0; i < results.length; i++) {
client.assert(results[i] === expected[i], "Response body is not sorted by true first")
}
});
%}

View File

@ -1,3 +1,4 @@
use std::cmp::Ordering;
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
@ -40,13 +41,24 @@ pub struct TruthTableOptions {
}
impl TruthTable {
// TODO options
// TODO hide option
pub fn new(expression: &Expression, options: TruthTableOptions) -> Self {
let header = Self::extract_header(expression);
let truth_matrix = Self::generate_truth_matrix(expression, &header);
let mut truth_matrix = Self::generate_truth_matrix(expression, &header);
if !matches!(options.sort, Sort::Default) {
Self::sort_matrix(&mut truth_matrix, options.sort);
}
Self { header, truth_matrix }
}
fn sort_matrix(truth_matrix: &mut TruthMatrix, sort: Sort) {
truth_matrix.sort_by(|row_a, row_b| match sort {
Sort::TrueFirst => row_b.last().cmp(&row_a.last()),
Sort::FalseFirst => row_a.last().cmp(&row_b.last()),
Sort::Default => Ordering::Equal,
})
}
/// Extracts the header for the truth table from the expression
/// Duplicate values are removed.
/// - Arguments
@ -62,16 +74,16 @@ impl TruthTable {
/// ```
fn extract_header(expression: &Expression) -> Vec<String> {
match expression {
not @ Expression::Not(expr) => {
Expression::Not(expr) => {
let mut header = Self::extract_header(expr);
header.push(not.to_string());
header.push(expression.to_string());
header.distinct();
header
}
binary @ Expression::Binary { left, right, .. } => {
Expression::Binary { left, right, .. } => {
let mut header = Self::extract_header(left);
header.extend(Self::extract_header(right));
header.push(binary.to_string());
header.push(expression.to_string());
header.distinct();
header
}
@ -116,26 +128,26 @@ impl TruthTable {
fn _resolve_expression<'a>(expression: &'a Expression, booleans: &HashMap<String, bool>) -> HashMap<&'a Expression, bool> {
match expression {
not @ Expression::Not(expr) => {
Expression::Not(expr) => {
let mut map = Self::_resolve_expression(expr, booleans);
if let Some(value) = map.get(expr.as_ref()) {
map.insert(not, !value);
map.insert(expression, !value);
}
map
}
binary @ Expression::Binary { left, right, operator } => {
Expression::Binary { left, right, operator } => {
let left_map = Self::_resolve_expression(left, booleans);
let right_map = Self::_resolve_expression(right, booleans);
let mut map = left_map;
map.extend(right_map);
if let (Some(left_value), Some(right_value)) = (map.get(left.as_ref()), map.get(right.as_ref())) {
map.insert(binary, operator.eval(*left_value, *right_value));
map.insert(expression, operator.eval(*left_value, *right_value));
}
map
}
atomic @ Expression::Atomic(value) => {
Expression::Atomic(value) => {
if let Some(value) = booleans.get(value) {
map!(atomic => *value)
map!(expression => *value)
} else {
unreachable!("Atomic value not found in booleans")
}
@ -189,6 +201,74 @@ mod tests {
assert_eq!(truth_table.truth_matrix[7], vec![false, false, false, false, false, false]);
}
#[test]
fn test_sort_matrix_true_first() {
let mut matrix = matrix![
true, true, true;
true, false, false;
false, true, true;
false, false, false
];
TruthTable::sort_matrix(&mut matrix, Sort::TrueFirst);
assert_eq!(matrix, matrix![
true, true, true;
false, true, true;
true, false, false;
false, false, false
]);
}
#[test]
fn test_sort_matrix_true_first_all_false_should_not_change() {
let mut matrix = matrix![
false, true, false;
false, true, false;
true, false, false;
true, false, false
];
TruthTable::sort_matrix(&mut matrix, Sort::TrueFirst);
assert_eq!(matrix, matrix![
false, true, false;
false, true, false;
true, false, false;
true, false, false
]);
}
#[test]
fn test_sort_matrix_default_should_not_change() {
let mut matrix = matrix![
true, true, true;
true, false, false;
false, true, true;
false, false, false
];
TruthTable::sort_matrix(&mut matrix, Sort::Default);
assert_eq!(matrix, matrix![
true, true, true;
true, false, false;
false, true, true;
false, false, false
]);
}
#[test]
fn test_sort_matrix_false_first() {
let mut matrix = matrix![
true, true, true;
true, false, false;
false, true, true;
false, false, false
];
TruthTable::sort_matrix(&mut matrix, Sort::FalseFirst);
assert_eq!(matrix, matrix![
true, false, false;
false, false, false;
true, true, true;
false, true, true
]);
}
#[test]
fn test_truth_combinations_2() {
let combinations = TruthTable::truth_combinations(2);