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)
就是您所需要的。范围内的每个数字代表真值表中的一行。当且仅当表的第k
th 行中的i
th 变量为真时,数字k
的二进制表示的i
th 位为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构建一个动态增长的真值表的主要内容,如果未能解决你的问题,请参考以下文章