Generate Truth Table

705 views Asked by At

How to generate truth table by coding in Javascript for three literals (a, b, c) and also find a given boolean expression (![(a && b) || c])?

I am trying following code:

let input = ['a', 'b', 'c'];
let expression = ['(a&&b)', '((a&&b)||c)', '(!((a&&b)||c))'];
let tableValue = [];

function exp(input, expression) {
  for (let i = 0; i <= Math.pow(2, input.length) - 1; i++) {
    for (let j = 0; j <= input.length - 1; j++) {
      if (('a&&b')) {
        tableValue[j] = (i & Math.pow(2, j)) == false;
      }
    }
    console.log(tableValue);
  }
}
console.log(exp(input));

1

There are 1 answers

0
Bergi On

That if (('a&&b')) doesn't evaluate anything. It's a string, not a function that you can call with the values. That's something you should use instead, e.g.

const expression = (a, b, c) => (!((a&&b)||c));

Then you can fill your table by calling the function, like

const expression = (a, b, c) => !((a&&b)||c);
const tf = x => x?'T':'F'
for (let i = 0; i < 2; i++) {
  for (let j = 0; j < 2; j++) {
    for (let k = 0; k < 2; k++) {
      const a = Boolean(i), b = Boolean(j), c = Boolean(k);
      console.log(`a: ${tf(a)}, b: ${tf(b)}, c: ${tf(c)}, result: ${tf(expression(a, b, c))}`);
 //                                                                    ^^^^^^^^^^^^^^^^^^^
    }
  }
}

Instead of logging, you can also build a table row values object (and format it later), and using your approach with bitwise operators you can do it for an arbitrarily large number of boolean variables:

function exp(input, expression) {
  const rows = [];
  for (let i = 0; i < (1 << input.length); i++) {
    const entries = input.map((name, j) =>
      [name, (i >>> j) & 1 == 1]
    );
    const values = entries.map(e => e[1]);
    const obj = Object.fromEntries(entries);
    obj.result = expression(...values);
    rows.push(obj);
  }
  return rows;
}
const table = exp(
  ['a', 'b', 'c'],
  (a, b, c) => ((a&&b)||c)
);
for (const row of table) {
  console.log(Object.entries(row).map(([k, v]) => `${k}: ${v?'T':'F'}`).join(', '));
}

You can also do this with dynamic expressions that are given as strings, if you insist, using a form of eval:

const expressions = ['(a&&b)', '((a&&b)||c)', '(!((a&&b)||c))'];
const input = ['a', 'b', 'c'];
const functionsByExpr = Object.fromEntries(expressions.map(expr =>
  [expr, new Function(...input, `return ${expr};`)]
//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
));

const rows = [];
for (let i = 0; i < (1 << input.length); i++) {
  const entries = input.map((name, j) =>
    [name, (i >>> j) & 1 == 1]
  );
  const values = entries.map(e => e[1]);
  const obj = Object.fromEntries(entries);
  for (const expr of expressions) {
    obj[expr] = functionsByExpr[expr](...values);
  }
  rows.push(obj);
}

console.log(input.join(' ')+' → '+expressions.join(' '));
console.log('-'.repeat(input.reduce((s,i) => s+i.length+1, expressions.reduce((s,e) => s+e.length+1, 1))));
for (const row of rows) {
  const cell = c => ' '.repeat(c.length/2-1) + (row[c]?'T':'F') + ' '.repeat(c.length/2)
  console.log(input.map(cell).join(' ')+' | '+expressions.map(cell).join(' '));
}