python构建一个动态增长的真值表

Posted

技术标签:

【中文标题】python构建一个动态增长的真值表【英文标题】:python build a dynamic growing truth table 【发布时间】:2011-09-14 06:02:50 【问题描述】:

我的问题很简单: “如何用优雅的方式在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为参数并建立表格的函数,没有必要 打印表格,返回代表表格的数据结构也可以。

【问题讨论】:

【参考方案1】:

使用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)]

【讨论】:

这确实是他们要走的路。谢谢大家的回答。我会像这里描述的那样做,但是这里的实现值得一看和投票!【参考方案2】:

当然,列表推导更加 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] )

【讨论】:

使用yield会是什么样子?我是 python 的新手。【参考方案3】:

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

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

测试,工作

希望对你有帮助

【讨论】:

你能给我一个使用yield的版本吗?对于进一步的问题将非常有帮助:) 我非常喜欢 scala 中的产量;)【参考方案4】:

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

【讨论】:

【参考方案5】:

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

【讨论】:

提示:如果您想要类似 yield 的功能,只需将所有括号(除了 else 之后)替换为括号,然后 lambda 函数将返回一个双生成器对象。【参考方案6】:

返回代表表的数据结构就可以了

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

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

[ [ ((row >> bit_index) & 1) == 1 for bit_index in range(n)] 
  for bit_index in range(2 ** n) ]

【讨论】:

【参考方案7】:

简单的数学方法:

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]

【讨论】:

这不是一个概括,它只适用于n = 3 给你,现在试试【参考方案8】:

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

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 repo,了解我的充实项目,用于从布尔表达式字符串生成真值表。

【讨论】:

以上是关于python构建一个动态增长的真值表的主要内容,如果未能解决你的问题,请参考以下文章

如何找到逻辑真值表的输入数量?

离散数学——python实现真值表和打印主范式

分配给它时动态增长一个python数组

布尔逻辑和真值表解释

将一个真值表附加到另一个

斑马谜题真值表