命题逻辑以解释两个论点

时间:2018-09-30 15:18:52

标签: python recursion

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

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

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

但是,由于我不太了解该程序是如何首先遍历列表和嵌套列表的,所以现在我已经停留了一段时间。然后遍历字典,挑选与键相关的值(在列表中),然后将列表中的值与逻辑语句相互比较。我了解到可能需要某种形式的递归才能遍历嵌套列表,但无法真正弄清楚如何将它们组合在一起。

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

2 个答案:

答案 0 :(得分:0)

您可以将运算符拆分为各自的功能,但是我不确定只有三个时会增加多少清晰度。我写了实际的函数来使用布尔值,因为我认为它最终会更简洁。

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

答案 1 :(得分:-1)

答案here的改进版本。

这里没有完成异常处理,所以我认为如果代码保证传递的列表(参数)具有有效的结构(例如OR),并且如果存在于列表中的AND运算符的两端都应具有操作数,那么代码就可以正常工作。 / p>

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

通过该指令将调用您编写的

helper函数。

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

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

使用递归可以解决此问题,无论何时1)都没有像在执行AND函数调用时那样解释该项目,我们是从右侧获取该项目,即尚未访问的项目(因为我们从从左到右,即从索引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'