20

我的问题很简单:“如何以优雅的方式在 python 中构建动态增长的真值表?”

对于 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))

对于 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))

我想要一个以n为参数并建立表格的函数,不需要打印表格,返回代表表格的数据结构也可以。

4

8 回答 8

46

使用itertools.product()

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

结果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)]
于 2011-06-13T21:14:10.203 回答
6

当然,列表推导更 Pythonic。

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

结果,为了清晰而缩进:

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] ]

作为生成器函数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]

此外,只需将返回从数组推导式更改为生成器表达式,即可使返回类型等效于yield版本的生成器函数:

def truthtable (n):
  if n < 1:
    return [[]]
  subtable = truthtable(n-1)
  return ( row + [v] for row in subtable for v in [0,1] )
于 2011-06-13T21:35:40.067 回答
5

itertools正如大家所指出的那样,确实是要走的路。但是,如果您真的想了解此所需算法的具体细节,您应该查找recursive descent。以下是它在您的情况下的工作方式:

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

测试,工作

希望这可以帮助

于 2011-06-13T21:27:55.017 回答
2

看看itertools模块

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)]
于 2011-06-13T21:17:53.807 回答
2

返回表示表的数据结构很好

...在这种情况下range(2 ** n),您只需要。范围内的每个数字代表真值表中的一行。当且仅当表的第 th 行中的th 变量为真时,数字的二进制表示的第ith 位为 1。kik

如果你想要一个实际的表,你可以使用:

[ [ ((row >> bit_index) & 1) == 1 for bit_index in range(n)] 
  for bit_index in range(2 ** n) ]
于 2011-06-14T01:58:18.587 回答
2

简单的数学方法:

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]

编辑:

更通用的格式是:

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

这只会将结果打印为:

>>> 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]
于 2020-02-03T20:58:17.757 回答
2

这里谁喜欢原始的 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% 测试和工作。
(无法复制/粘贴结果或以上代码,因为我正在打电话上网)

于 2017-04-23T01:56:37.143 回答
0

这是一个使用函数式编程、不使用循环且不导入任何外部库的实现:

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

然后get_bits使用所需数量的参数调用:

>>> 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]]

查看我的GitHub 存储库,了解我从布尔表达式字符串生成真值表的充实项目。

于 2021-04-30T06:53:31.497 回答