Mainly Tech projects on Python and Electronic Design Automation.

Sunday, July 20, 2025

All Truth in Truthtables!

 

  

 

(Best viewed on a larger than phone screen)

To crib from my RosettaCode tasks description and examples:

A truth table is a display of the inputs to, and the output of a Boolean equation organised as a table where each row gives one combination of input values and the corresponding value of the equation.

And as examples:

Boolean expression: A ^ B A B : A ^ B 0 0 : 0 0 1 : 1 1 0 : 1 1 1 : 0 Boolean expression: S | ( T ^ U ) S T U : S | ( T ^ U ) 0 0 0 : 0 0 0 1 : 1 0 1 0 : 1 0 1 1 : 0 1 0 0 : 1 1 0 1 : 1 1 1 0 : 1 1 1 1 : 1

 Format

A truth table has a header row of columns showing first the names of inputs assigned to each column; a visual separator - e.g. ':'; then the column name for the output result.

The body of the table, under the inputs section, contains rows of all binary combinations of the inputs. It is usually arranged as each row of the input section being a binary count from zero to 2**input_count - 1  

The body of the table, under the result section, contains rows showing the binary output produced from the input configuration in the same row, to the left.

Format used

 I am interested in the number of inputs rather than their names so will show vector i with the most significant indices to the left, (so the binary count in the input sections body looks right).

Similarly I am interested in the bits in the result column rather than a name so will just call the result column r.

From one result to many

 Here's the invocation, and truth tables produced for some simple boolean operators:

print("\nOR\n")
pp_ttable(2, 0b1110)

 OR i[1] i[0] : r ================= 0 0 : 0 0 1 : 1 1 0 : 1 1 1 : 1

print("\nXOR\n")
pp_ttable(2, 0b110)

XOR i[1] i[0] : r ================= 0 0 : 0 0 1 : 1 1 0 : 1 1 1 : 0

print("\nAND\n")
pp_ttable(2, 0b1000)

AND i[1] i[0] : r ================= 0 0 : 0 0 1 : 0 1 0 : 0 1 1 : 1

For those three inputs, we can extend the table to show result columns for OR, XOR and then AND, like this:

print("\nOR, XOR, then AND result *columns*\n")
pp_ttable(2, [14, 6, 8])  # A list of results, (in decimal this time)

OR, XOR, then AND result *columns* i[1] i[0] : r[0] r[1] r[2] =========================== 0 0 : 0 0 0 0 1 : 1 1 0 1 0 : 1 1 0 1 1 : 1 0 1

All Truth

 Just how many results are possible?

Well, i = 2 inputs gives 2**i = 4 possible input boolean combinations; so a result column has 2**i = 4  bits.
The number of different result columns is therefore 2**(2**i) = 2**4 = 16

We can show all possible results by successive results being a binary count, but this time by column in the results section, (with the LSB being closest to the header row)

The pp_table function automatically  generates all possible results if a second parameter of None is used

print("\nAll Truths of two inputs!\n")
pp_ttable(2, None)

All Truths of two inputs! i[1] i[0] : r[0] r[1] r[2] r[3] r[4] r[5] r[6] r[7] r[8] r[9] r[10] r[11] r[12] r[13] r[14] r[15] ============================================================================================================== 0 0 : 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 : 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 0 : 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 : 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1  

We might say that it shows all possible truths for up-to-and-including two inputs. That is because results include outputs not dependent on any or all of those two inputs. For example r[0], and r[15] do not depend on any input as they give constant outputs of 0 and 1, respectively. r[5] is simply ~i[0] and does not depend on i[1]

It's Big, Oh!

The results grow as  2**(2**i), sometimes called double exponential growth! it gets large, quickly!! 

i | 2**(2**i) --|---------- 0 | 2 1 | 4 2 | 16 3 | 256 4 | 65_536 5 | 4_294_967_296

The code

 Contemplating using AI and needing to get it to understand what I wanted, as well as endless prompting to get it to do what I want, the way I wanted it; I decided on writing it all by myself - I knew I wanted it just so, and the coding would be nothing new to me, just nailing what I wanted to show.

 

"""
Truthtable prettyprinter

Author: Paddy3118  2025/07/19


# Regions of a truthtable

```text
+----------------- --+---------+
|      Inputs        | Result  |
+------------------- +---------+
| I[2] | I[1] | I[0] |   R     |
|------|------|------|---------|
|  0   |  0   |  0   |   0     |
|  0   |  0   |  1   |   1     |
|  0   |  1   |  0   |   0     |
|  0   |  1   |  1   |   1     |
|  1   |  0   |  0   |   1     |
|  1   |  0   |  1   |   0     |
|  1   |  1   |  0   |   1     |
|  1   |  1   |  1   |   0     |
+--------------------+---------+
```

"""

# %%
def pp_ttable(input_count:int,
              result_vector: int | list[int] | None,
              input_vector_name: str='i',
              result_vector_name: str='r'
              ) -> None:
    r_single = r_mult = False
    match result_vector:
        case int():     # single result
            r_single = True
            r_width = len(f" {result_vector_name}")
            result_vector = [result_vector]
        case list():    # multiple results
            r_mult = True
            r_width = len(f" {result_vector_name}[{len(result_vector) - 1}]")
        case None:      # All possible results
            assert input_count < 4, f"Refuse to write {2**(2**input_count)} result columns."
            r_mult = True
            result_vector = list(range(2**(2**input_count)))
            r_width = len(f" {result_vector_name}[{len(result_vector) - 1}]")
        case _:
            raise Typeerror("result must be an int, a list of ints, or None.")

    col_width = max(len(f" {input_vector_name}[{input_count - 1}]"), r_width)

    rows = []
    header = []
    for i in range(input_count-1, -1, -1):
        col = f"{input_vector_name}[{i:}]"
        header.append(f"{col:{col_width}}")
    header.append(': ')
    if r_single:
        header.append(f"{result_vector_name:^{col_width}}")
    else:
        for i in range(len(result_vector)):
            col = f"{result_vector_name}[{i:}]"
            header.append(f"{col:^{col_width}}")
    rows.append(''.join(header))
    rows.append('=' * len(rows[-1]))    # header row spacer

    result_bits = [f"{res:0{2**input_count}b}"[::-1]
                    for res in result_vector]
   
    for r in range(2**input_count):
        row = []
        col_bits = f"{r:0{input_count}b}"
        for bit in col_bits:
            row.append(f"{bit:^{col_width}}")
       
        row.append(': ')

        for res_bits in result_bits:
            row.append(f"{res_bits[r]:^{col_width}}")
               
        rows.append(''.join(row))


    print('\n'.join(rows))

# %%
print("\nOR\n")
pp_ttable(2, 0b1110)
print("\nXOR\n")
pp_ttable(2, 0b110)
print("\nAND\n")
pp_ttable(2, 0b1000)
   

# %%

print("\nOR, XOR, then AND result *columns*\n")
pp_ttable(2, [14, 6, 8])  # A list of results, (in decimal this time)

# %%
print("\nAll Truths of two inputs!\n")
pp_ttable(2, None)


# %%

 

END. 

  

 

 

Followers

Subscribe Now: google

Add to Google Reader or Homepage

Go deh too!

whos.amung.us

Blog Archive