算法思维训练逻辑任务(18) 谁偷了钻石

2022-08-26  本文已影响0人  Python_Camp

逻辑推理任务。
珠宝店失窃,能够确定是员工内盗。共四名员工对侦探的回答:
A:我没有偷钻石。B:D是一个罪犯。C:B是偷窃这颗钻石的罪犯。D:B有动机陷害我。
假设已经掌握的情况看,只有一个人说真话,但不知道具体是谁说真话。那么能否决定了谁偷了这颗钻石。
答案是:说真话的是D,罪犯是A,逻辑思维过程枚举每个人说真话而其他人说假话。
分析思路
首先,A、B、C、D四个人都是犯罪嫌疑人,我们把这四种可能性放到一个列表中 state = ["A"、"B"、"C"、"D"]。然后再去看这四种情况,可以知道4个人中只有一个人说的是真话,所以我说这四个人说。
A:我没有偷钻石。犯罪者不是一个 代码表示 state['A']! = not "A"
B:D偷钻石。代码表示 state['B'] == "D"
C:B偷钻石。理解:罪犯是B 代码表示 state ['C'] == "B"
D:B陷害我。B是错误的,罪犯不是D 代码表示 state['D']! = not "D"
遍历每个人说真话,其他3人说假话


def find(state, true_man):
    for x in range(len(state)): 
    #遍历一个人说真话,其他3人说假话
        states = (state[x]!="A"), 
                  (state[x]=="D"), 
                  (state[x]=="B"),
                  (state[x]!="D")                  
    
        if sum(states) == true_man:
            return ("Criminals are:% s" %state[x])

true_man = 1 #Number of people saying
state = ["A", "B", "C", "D"] 
#Who is the 4 cases of criminals?

print(find(state, true_man))
Criminals are:A

在上面例子中,枚举每个人说真话,其他人说假话,只有一种情况满足题目中的约束条件:只有D说真话时,4个人中有三个人说谎。我们可以稍微修改上述代码获取遍历的每一步结果:


def find(state, true_man):
    for x in range(len(state)): 
    #遍历一个人说真话,其他3人说假话
        states = (state[x]!="A"), 
                  (state[x]=="D"), 
                  (state[x]=="B"),
                  (state[x]!="D")                  
        print(states)
        if sum(states) == true_man:
            return ("Criminals are:% s" %state[x])

true_man = 1 #Number of people saying
state = ["A", "B", "C", "D"] 

输出:
[False, False, False, True]
[True, False, True, True]
[True, False, False, True]
[True, True, False, False]

上述任务难度升级 ****

在上面例子中,如果已知是2人、或者3人说真话,那么又该如何找到谁是窃贼?
枚举['A','B','C','D'] 四人中说真话或假话的所有可能情况,考虑这种方式:
['1','0','0,'0'] 代表四人中只有‘A’说真话,其他三人说谎;

依此类推可以用二进制穷举所有情况。
函数statement(person) 运用字典结构初始化每个人的申明:
values是包含2个元素的列表, 角标位置为 0 :此人说谎 角标位置为 1:此人说真话
输出 字典结构sates.keys是['A','B','C','D']

def statement(person):
    states = dict(zip(person,[]*len(person)))
    states['A'] = ['A',['B','C','D']]
    states['B'] = [['A','B','C'],"D"]
    states['C'] = [['A','C','D'],"B"]
    states['D'] = ['D',['A','B','C']]
    return states
person = ['A','B','C','D']
print(statement(person))

主函数 find(state, true_man) 函数find传入参数state是子函数statement返回结果 缺省true_man时,则返回所有遍历结果

def find(state, true_man):    
    enum = range(int('0b0000',2),int('0b1111',2)+1)
    status = ['{:0>4}'.format(bin(i)[2:]) for i in enum]

    key = list(state.keys())
    ans = {}
    for elem in status:
        sets = set(state[key[0]][int(elem[0])])
        for i, c in enumerate(elem):
            sets &= set(state[key[i]][int(c)])
        ans[elem] = set(sets)
    return [[k,v] for k,v in ans.items() if len(v)]

states = statement(person,states={})

print(find(states,true_man=1))

[['0001', {'A'}], ['1001', {'C'}], 
['1011', {'B'}], ['1100', {'D'}]]

输出结果又一次支持结论:已知只有一个人说真话的前提下,只有['0001', {'A'}符合

若有2个人说谎,2人说真话,那么 窃贼只会在'C'和‘D'之间的某一个;

若有1个人说谎,3人说真话,那么 窃贼只能是'B'

上一篇 下一篇

猜你喜欢

热点阅读