python build a dynamic growing truth table
Asked Answered
O

9

24

My question is simple: "how to build a dynamic growing truth table in python in an elegant way?"

for n=3

for p in False, True:
    for q in False, True:
        for r in False, True:
            print '|{0} | {1} | {2} |'.format(int(p),int(q), int(r))

for n=4

for p in False, True:
    for q in False, True:
        for r in False, True:
            for s in False, True:
                print '|{0} | {1} | {2} | {3}'.format(int(p),int(q), int(r), int(s))

I would like to have a function which takes n as a parameter and builds up the table, it is not necessary to print the table, returning a data structure representing the table is fine also.

Oriflamme answered 13/6, 2011 at 21:12 Comment(0)
F
54

Use itertools.product():

table = list(itertools.product([False, True], repeat=n))

Result for n = 3:

[(False, False, False),
 (False, False, True),
 (False, True, False),
 (False, True, True),
 (True, False, False),
 (True, False, True),
 (True, True, False),
 (True, True, True)]
Flabellum answered 13/6, 2011 at 21:14 Comment(1)
this is they way to go indeed. Thank you all for the answers. I will do it like here described, but the implementations under here are worth to look at and to vote up!Oriflamme
B
6

List comprehensions are, of course, more Pythonic.

def truthtable (n):
  if n < 1:
    return [[]]
  subtable = truthtable(n-1)
  return [ row + [v] for row in subtable for v in [0,1] ]

Results, indented for clairity:

truthtable(1)
[ [0],
  [1] ]

truthtable(3)
[ [0, 0, 0],
  [0, 0, 1],
  [0, 1, 0],
  [0, 1, 1],
  [1, 0, 0],
  [1, 0, 1],
  [1, 1, 0],
  [1, 1, 1] ]

As a generator function with yield:

def truthtable (n): 
  if n < 1:
    yield []
    return
  subtable = truthtable(n-1)
  for row in subtable:
    for v in [0,1]:
      yield row + [v]

Also simply changing the return from an array comprehension to a generator expression makes the return type equivalent to the yield version's generator function:

def truthtable (n):
  if n < 1:
    return [[]]
  subtable = truthtable(n-1)
  return ( row + [v] for row in subtable for v in [0,1] )
Bombastic answered 13/6, 2011 at 21:35 Comment(1)
how would it look like using yield? I'm kinda new in python.Oriflamme
B
5

itertools really is the way to go as has been pointed out by everyone. But if you really want to see the nuts and bolts of the algorithm required for this, you should look up recursive descent. Here's how it would work in your case:

def tablize(n, truths=[]):
    if not n:
        print truths
    else:
        for i in [True, False]:
            tablize(n-1, truths+[i])

Tested, working

Hope this helps

Burcham answered 13/6, 2011 at 21:27 Comment(1)
can you give me a version which uses yield? Would be very helpful for further problems :) I like yield in scala so much ;)Oriflamme
L
2

Have a look at the itertools module

In [7]: [i for i in itertools.product([0,1], repeat=3)]
Out[7]: 
[(0, 0, 0),
 (0, 0, 1),
 (0, 1, 0),
 (0, 1, 1),
 (1, 0, 0),
 (1, 0, 1),
 (1, 1, 0),
 (1, 1, 1)]
Leavelle answered 13/6, 2011 at 21:17 Comment(0)
M
2

returning a datastructure representing the table is fine

...in that case range(2 ** n) is all you need. Each number in the range represents a row in the truth table. The ith bit of the binary representation of the number k is 1 if and only if the ith variable is true in the kth row of the table.

If you want an actual table you can use:

[ [ ((row >> bit_index) & 1) == 1 for bit_index in range(n)] 
  for bit_index in range(2 ** n) ]
Meat answered 14/6, 2011 at 1:58 Comment(0)
S
2

who here likes raw 1-liners?

>>> truthtable = lambda n: [[(v>>i)&1 for i in range(n-1,-1,-1)] for v in range(1<<n)] if n>0 else [[]]

100% tested and working.
(can't copy/paste result, or above code, cause I'm on a phone for Internet)

Strapped answered 23/4, 2017 at 1:56 Comment(1)
tip: if you want yield-like functionality, just replace all brackets (except after else) with parentheses, the lambda function will then return a double generator object.Strapped
N
2

Easy math aproach:

a = lambda x: [x//4%2,x//2%2,x%2]

for i in range(8):
    print(a(i))

[0, 0, 0]
[0, 0, 1]
[0, 1, 0]
[0, 1, 1]
[1, 0, 0]
[1, 0, 1]
[1, 1, 0]
[1, 1, 1]

EDIT:

A more general format wold be:

def truth_table(n):
    for i in range(2**n):
        line = [i//2**j%2 for j in reversed(range(n))]
        print(line)

This will only print the result as:

>>> truth_table(3)
[0, 0, 0]
[0, 0, 1]
[0, 1, 0]
[0, 1, 1]
[1, 0, 0]
[1, 0, 1]
[1, 1, 0]
[1, 1, 1]
Norbert answered 3/2, 2020 at 20:58 Comment(2)
This is not a generalization, it will only work for n = 3Cutin
here you go, try nowNorbert
P
0

Here's an implementation that uses functional programming, doesn't use loops, and doesn't import any external libraries:

get_bits = lambda n: [*map(lambda x:[*map(int,bin(x)[2:].zfill(n))],range(2**n))]

Then call get_bits with the desired number of parameters:

>>> get_bits(3)
[[0, 0, 0],
 [0, 0, 1],
 [0, 1, 0],
 [0, 1, 1],
 [1, 0, 0],
 [1, 0, 1],
 [1, 1, 0],
 [1, 1, 1]]

Check out my GitHub repo to see my fleshed-out project for generating Truth Tables from boolean expression strings.

Ploce answered 30/4, 2021 at 6:53 Comment(0)
B
-1
tt = np.array(truthtable(np.size(A,1)))
Butyraceous answered 11/7, 2024 at 6:49 Comment(1)
Welcome to Stack Overflow! "We're a little bit different from other sites." Your answer could be improved with additional supporting information. If possible, please edit your post to add further details, such as explanations or documentation, so that others can understand how to solve the problem. You can find more information in How do I write a good answer? - "Brevity is acceptable, but fuller explanations are better." It might be helpful to review some highly upvoted answers as examples to follow. Thanks!Sportscast

© 2022 - 2025 — McMap. All rights reserved.