命题逻辑,以便解释两个论点



我正在尝试编写一个函数,该函数将接受两个参数(一个列表和一个字典(并返回输出,如下所示:

>>>interpret(["door_open", "AND", "cat_gone"], 
{"door_open" : "false", "cat_gone" : "true", "cat_asleep" : "true"})
'false'    

interpret(["cat_asleep", "OR", ["NOT", "cat_gone"]],
{"door_open" : "false", "cat_gone" : "true", "cat_asleep" : "true"})
'true'

.......

由于我想在这个特定函数中使用尽可能少的逻辑语句,因此我创建了几个单独的函数来执行此操作:

def and_function(expression1, expression2):
if expression1=="true" and expression2=="true":
return "true"
else:
return "false"

def or_function(expression1, expression2):
if expression1== "true" or expression2=="true":
return "true"
else:
return "false"

def not_function(expression):
if expression == "true":
return "false"
elif expression == "false":
return "true"

.......

但是,现在我已经卡了一段时间,因为我不太明白程序应该如何首先浏览列表和嵌套列表。然后通过字典挑选出与键相关的值(在列表中(,然后将列表中的值与逻辑语句一起进行比较。我得到可能需要某种形式的递归才能浏览嵌套列表,但无法真正弄清楚如何将它们放在一起。

关于如何解决此类问题的任何想法?

您可以将运算符拆分为它们自己的函数,但我不确定当只有三个运算符时,这会增加多少清晰度。我编写了实际函数来处理布尔值,因为我认为它最终会更干净一些。

def interpret(conditions, states):
return "true" if _interpret(
conditions,
{k: v == "true" for k, v in states.items()},
) else "false"
def _interpret(conditions, states):
# NOT is a special case; just one argument in position 1
if conditions[0] == "NOT":
if type(conditions[1]) == list:
value = _interpret(conditions[1], states)
else:
value = states[conditions[1]]
return not value
if type(conditions[0]) == list:
first = _interpret(conditions[0], states)
else:
first = states[conditions[0]]
if type(conditions[2]) == list:
second = _interpret(conditions[2], states)
else:
second = states[conditions[2]]
return (first and second) if (conditions[1] == "AND") else (first or second)

缩短一点:

import operator
def _interpret(c, s):
if c[0] == "NOT":
return not (_interpret(c[1], s) if (type(c[1]) == list) else s[c[1]])
return (operator.and_ if (c[1] == "AND") else operator.or_)(
_interpret(c[0], s) if (type(c[0]) == list) else s[c[0]],
_interpret(c[2], s) if (type(c[2]) == list) else s[c[2]],
)

此处答案的改进版本。

这里没有进行异常处理,所以我认为如果代码保证传递的列表(参数(具有有效的结构,例如 OR,AND 运算符如果存在于列表中,则代码将正常工作,如果列表中存在,则两边都应该有操作数。

............

您编写的帮助程序函数将通过此字典调用。

binary_bool_dict = {'AND':and_function, 'OR':or_function}
unary_bool_dict = {'NOT':not_function}

............

使用递归我们可以解决这个问题,每当我们没有像执行 AND 函数调用时那样解释项目1)我们就从右侧获取项目,即我们尚未访问的项目(因为我们从左到右遍历,即从索引0 --> len(list)(或2)项目是一个列表,我们将进行递归调用。

函数interpret将返回'true''false'

def interpret( lst, dct):
if isinstance( lst, list):
temp_result = None 
#print( lst)
for idx, item in enumerate( lst):
#print( idx,'item',item)
if item == 'true' or item == 'false':
continue
elif isinstance( item, list):
lst[idx] = interpret( item,dct)
elif item in dct:
lst[idx] = dct[item]
else:
lst[idx+1] = interpret( lst[ idx+1],dct)
if item in binary_bool_dict:
if temp_result == None:
temp_result = binary_bool_dict[item]( lst[ idx-1], lst[idx+1])
else:
temp_result = binary_bool_dict[item]( temp_result, lst[idx+1])
else:
# item in unary_bool_dict:
temp_result  = unary_bool_dict[item](lst[idx+1])
return temp_result # eventually temp_result will become our final answer
else:
return dct.get( lst,lst) # if key: lst is present in dct get its value else just return lst ( it must be already a 'true' or 'false')

............

print(interpret(["door_open", "AND", "cat_gone"], 
{"door_open" : "false", "cat_gone" : "true", "cat_asleep" : "true"} )) #'false'
print(interpret(["cat_asleep", "OR", ["NOT", "cat_gone"]],
{"door_open" : "false", "cat_gone" : "true", "cat_asleep" : "true"})) #'true'
print(interpret(["true", "OR", "true"], {}))  #'true'
print(interpret("cat_gone", {"door_open": "false", "cat_gone": "true"})) #'true'
print(interpret(["NOT", ["NOT", ["NOT", ["cat_asleep", "OR", ["NOT", "cat_asleep"]]]]],
{"cat_asleep": "false"})) #'false'
print(interpret(["NOT", "AND", "true"], {"NOT":"true"})) #'true'
print(interpret(["NOT", "AND"], {"AND": "false"})) #'true'

相关内容

最新更新