boolean-expression-solve
Version:
Boolean expression solver, simplifier, truth-table generator
300 lines (249 loc) โข 10.4 kB
JavaScript
const { simplify, getTruthTable, getVariables, isValidExpression, evaluate } = require('./index');
/**
* Test runner utility
*/
class TestRunner {
constructor() {
this.passed = 0;
this.failed = 0;
this.tests = [];
}
test(description, testFunction) {
try {
console.log(`\n๐งช Testing: ${description}`);
const result = testFunction();
if (result === true || result === undefined) {
console.log(`โ
PASSED: ${description}`);
this.passed++;
} else {
console.log(`โ FAILED: ${description} - ${result}`);
this.failed++;
}
} catch (error) {
console.log(`โ ERROR: ${description} - ${error.message}`);
this.failed++;
}
this.tests.push({ description, passed: this.failed === 0 });
}
expect(actual, expected, message = '') {
if (JSON.stringify(actual) === JSON.stringify(expected)) {
return true;
} else {
return `Expected: ${JSON.stringify(expected)}, Got: ${JSON.stringify(actual)} ${message}`;
}
}
summary() {
console.log('\n' + '='.repeat(60));
console.log('๐ TEST SUMMARY');
console.log('='.repeat(60));
console.log(`โ
Passed: ${this.passed}`);
console.log(`โ Failed: ${this.failed}`);
console.log(`๐ Total: ${this.passed + this.failed}`);
console.log(`๐ฏ Success Rate: ${((this.passed / (this.passed + this.failed)) * 100).toFixed(1)}%`);
if (this.failed === 0) {
console.log('\n๐ All tests passed!');
} else {
console.log('\nโ ๏ธ Some tests failed. Check the output above.');
}
}
}
// Initialize test runner
const test = new TestRunner();
console.log('๐ Starting Boolean Expression Simplifier Tests...\n');
// Test 1: Basic simplification
test.test('Basic OR simplification: A + A should equal A', () => {
const result = simplify('A + A');
return test.expect(result, 'A');
});
test.test('Basic AND simplification: A . A should equal A', () => {
const result = simplify('A . A');
return test.expect(result, 'A');
});
// Test 2: Identity laws
test.test('Identity law: A + 0 should equal A', () => {
const result = simplify('A + 0');
return test.expect(result, 'A');
});
test.test('Identity law: A . 1 should equal A', () => {
const result = simplify('A . 1');
return test.expect(result, 'A');
});
// Test 3: Domination laws
test.test('Domination law: A + 1 should equal 1', () => {
const result = simplify('A + 1');
return test.expect(result, '1');
});
test.test('Domination law: A . 0 should equal 0', () => {
const result = simplify('A . 0');
return test.expect(result, '0');
});
// Test 4: Complement laws
test.test('Complement law: A + A\' should equal 1', () => {
const result = simplify('A + A\'');
return test.expect(result, '1');
});
test.test('Complement law: A . A\' should equal 0', () => {
const result = simplify('A . A\'');
return test.expect(result, '0');
});
// Test 5: Absorption laws
test.test('Absorption law: A + A.B should equal A', () => {
const result = simplify('A + A.B');
return test.expect(result, 'A');
});
test.test('Absorption law: A.(A + B) should equal A', () => {
const result = simplify('A.(A + B)');
return test.expect(result, 'A');
});
// Test 6: Complex expressions
test.test('Complex expression: (A+B).(A+B\') should equal A', () => {
const result = simplify('(A+B).(A+B\')');
return test.expect(result, 'A');
});
test.test('Your original complex expression', () => {
const result = simplify('(A+B\'+C).(A\'+B+C)(A\'+B+C\')(A\'+B\'+C).(A\'+B\'+C\')');
// This should simplify to something shorter
return result.length < 50; // Just check if it's simplified (shorter)
});
// Test 7: getVariables function
test.test('Extract variables from A + B.C', () => {
const result = getVariables('A + B.C');
return test.expect(result, ['A', 'B', 'C']);
});
test.test('Extract variables from complex expression', () => {
const result = getVariables('(X+Y\'+Z).(W\'+X+Y)');
return test.expect(result, ['W', 'X', 'Y', 'Z']);
});
test.test('Extract variables from expression with no variables (constants)', () => {
const result = getVariables('1 + 0');
return test.expect(result, []);
});
// Test 8: isValidExpression function
test.test('Valid expression: A + B should be valid', () => {
const result = isValidExpression('A + B');
return test.expect(result, true);
});
test.test('Valid complex expression should be valid', () => {
const result = isValidExpression('(A+B\').(C+D)');
return test.expect(result, true);
});
test.test('Invalid expression with double operators should be invalid', () => {
const result = isValidExpression('A + + B');
return test.expect(result, false);
});
// Test 9: evaluate function
test.test('Evaluate A + B with A=0, B=1 should equal 1', () => {
const result = evaluate('A + B', { A: 0, B: 1 });
return test.expect(result, 1);
});
test.test('Evaluate A . B with A=1, B=0 should equal 0', () => {
const result = evaluate('A . B', { A: 1, B: 0 });
return test.expect(result, 0);
});
test.test('Evaluate A\' with A=1 should equal 0', () => {
const result = evaluate('A\'', { A: 1 });
return test.expect(result, 0);
});
test.test('Evaluate complex expression (A+B).C with A=0, B=1, C=1 should equal 1', () => {
const result = evaluate('(A+B).C', { A: 0, B: 1, C: 1 });
return test.expect(result, 1);
});
// Test 10: getTruthTable function (string format)
test.test('Truth table string for A + B should contain correct header', () => {
const result = getTruthTable('A + B', 'string');
return result.includes('| A | B | A + B |');
});
test.test('Truth table string should contain 4 data rows for 2 variables', () => {
const result = getTruthTable('A + B', 'string');
const lines = result.split('\n');
const dataRows = lines.filter(line => line.match(/^\| [01] \| [01] \|/));
return test.expect(dataRows.length, 4);
});
// Test 11: getTruthTable function (array format)
test.test('Truth table array for A + B should have 4 rows', () => {
const result = getTruthTable('A + B', 'array');
return test.expect(result.length, 4);
});
test.test('Truth table array should have correct structure', () => {
const result = getTruthTable('A + B', 'array');
const firstRow = result[0];
const hasRequiredProps = firstRow.hasOwnProperty('inputs') &&
firstRow.hasOwnProperty('output') &&
firstRow.hasOwnProperty('expression');
return test.expect(hasRequiredProps, true);
});
test.test('Truth table array for A + B should have correct first row', () => {
const result = getTruthTable('A + B', 'array');
const expectedFirstRow = { inputs: { A: 0, B: 0 }, output: 0, expression: 'A + B' };
return test.expect(result[0], expectedFirstRow);
});
// Test 12: Error handling
test.test('getTruthTable with invalid type should return Error', () => {
const result = getTruthTable('A + B', 'invalid');
return result instanceof Error;
});
test.test('evaluate with missing variables should throw error', () => {
try {
evaluate('A + B', { A: 1 }); // Missing B
return 'Should have thrown an error';
} catch (error) {
return true; // Expected to throw
}
});
// Test 13: Case insensitivity
test.test('Case insensitive input: a + b should work', () => {
const result = getVariables('a + b');
return test.expect(result, ['A', 'B']); // Variables should be normalized to uppercase
});
// Test 14: Edge cases
test.test('Single variable should remain unchanged', () => {
const result = simplify('A');
return test.expect(result, 'A');
});
test.test('Constant 1 should remain 1', () => {
const result = simplify('1');
return test.expect(result, '1');
});
test.test('Constant 0 should remain 0', () => {
const result = simplify('0');
return test.expect(result, '0');
});
// Test 15: Performance test with large expression
test.test('Performance test: Complex expression should complete in reasonable time', () => {
const start = Date.now();
const result = simplify('(A+B+C).(A+B+C\').(A+B\'+C).(A+B\'+C\').(A\'+B+C).(A\'+B+C\').(A\'+B\'+C)');
const end = Date.now();
const duration = end - start;
console.log(` โฑ๏ธ Execution time: ${duration}ms`);
console.log(` ๐ Result: ${result}`);
return duration < 5000; // Should complete in less than 5 seconds
});
// Display comprehensive test results
console.log('\n' + '='.repeat(60));
console.log('๐ DETAILED FUNCTION TESTING');
console.log('='.repeat(60));
// Demo of actual outputs
console.log('\n๐ Sample Function Outputs:');
console.log('โ'.repeat(40));
console.log('\n1. simplify() examples:');
console.log(` simplify('A + A.B') = "${simplify('A + A.B')}"`);
console.log(` simplify('(A+B).(A+B\\')') = "${simplify('(A+B).(A+B\')')}"`);
console.log('\n2. getVariables() examples:');
console.log(` getVariables('A + B.C') = [${getVariables('A + B.C').join(', ')}]`);
console.log('\n3. evaluate() examples:');
console.log(` evaluate('A + B', {A: 0, B: 1}) = ${evaluate('A + B', { A: 0, B: 1 })}`);
console.log(` evaluate('A . B', {A: 1, B: 0}) = ${evaluate('A . B', { A: 1, B: 0 })}`);
console.log('\n4. getTruthTable() array example:');
const sampleTruthArray = getTruthTable('A . B', 'array');
console.log(' getTruthTable(\'A . B\', \'array\'):');
sampleTruthArray.forEach((row, index) => {
console.log(` [${index}] ${JSON.stringify(row)}`);
});
console.log('\n5. getTruthTable() string example:');
console.log(' getTruthTable(\'A + B\', \'string\'):');
const sampleTruthString = getTruthTable('A + B', 'string');
sampleTruthString.split('\n').forEach(line => {
console.log(` ${line}`);
});
// Run test summary
test.summary();