Truth tables for logical expressions
与P302类似,只是表达式中可包含任意多个变量,比如A and (B or C) equ A and B or A and C
。
我们可以重用大部份P302中的实现,仅需修改直值表构造和变量值解柝两步,使其支持任意个数变量。
照例,先写单元测试:
from python99.logic_codes.p303 import table
def test_table():
assert table({'A': [True, False], 'B': [True, False], 'C': [True, False]}, 'A and B or C') == [
(True, True, True, True),
(True, True, False, True),
(True, False, True, True),
(True, False, False, False),
(False, True, True, True),
(False, True, False, False),
(False, False, True, True),
(False, False, False, False)
]
首先,构造如下形式的输入表:
A | B | C | ... |
---|---|---|---|
True | True | True | ... |
True | True | False | ... |
True | False | True | ... |
... | ... | ... | ... |
这个可以使用递归构造。分别构造每一个变量的取值选项,再列出所有排列。代码实现:
def constructInputs(variables):
if len(variables)==1:
e = variables[0]
return [[(e[0],v)] for v in e[1]]
e = variables[0]
kv = [(e[0],v) for v in e[1]]
print(kv)
return [[first] + remain for first in kv for remain in constructInputs(variables[1:])]
然后,逐一使用输入表中的变量值,计算表达式值。在将变量值替换进青达式时,可以将变量值先转换成字典,方便查找。代码实现:
def resolveVariable(expr, input):
resolved = []
kv = {}
for e in input:
kv[e[0]]=e[1]
for e in expr:
if e in kv:
resolved.append(kv[e])
else:
resolved.append(e)
return resolved
最后,转换一下结果直值表结构,将每一行从列表转换为元组。
def table(variables, expr):
postExpr = postOrderTraversal(buildTreeFrom(tokenize(expr)))
inputTable = constructInputs([(k,v) for k,v in variables.items()])
result = [extractValue(input) +[evaluate(resolveVariable(postExpr,input))] for input in inputTable]
return [tuple(e) for e in result]