知恵袋の「ウソつき問題」をPythonで解いてみた。(8)

 知恵袋の「ウソつき問題」をPythonで解いてみました。(^_^;

 ある事件の容疑者のA~Eの5人がそれぞれ次のような発言をした。事件はA~Eの中の2人の共犯であることが分かっている。5人の中には正直者と嘘つきがいて、正直者は正しいこと嘘つきは正しくないことしか発言しない。またそれ以外の3人の発言は一つが正しく一つが正しくない。犯人の2人はだれか。
A「私は正直者ではない」「Bは嘘つきではない」
B「私は犯人ではない」「Dは犯人である」
C「私は犯人ではない」「Aも犯人ではない」
D「私は犯人である」「Aは正直者ではない」
E「Bは犯人ではない」「Cも犯人ではない」

 犯人2人をxとして、A~Eの5人から2人をとる組合せで回しました。
 正直者を'H'、嘘つきを'L'、それ以外の3人を'b'としました。直積で回しましたが、同じものを含む順列で回してもいいです。(^_^;
 通過すべき条件は、発言者をs、発言1をst1、発言2をst2として、
「Imp(s!='b',Eqv(s=='H',st1) and Eqv(s=='H',st2))」、
「Imp(s=='b',Xor(st1,st2))」
としてみました。ここで、「s=='H'」で正直者かどうかを判定しました。

● Liar8.py

# coding: UTF-8
# Liar8.py

import itertools
from time import time

# 排他的論理和Xor
def Xor(p,q):
    return bool(p)^bool(q)

# 論理等価Eqv
def Eqv(p,q):
    return not Xor(p,q)

# 論理包含Imp
def Imp(p,q):
    return not p or q

def toStr(li):
    return '[%s]'%','.join(li)

# s:発言者; st1:発言1; st2:発言2
def check(s,st1,st2):
    if not Imp(s!='b',Eqv(s=='H',st1) and Eqv(s=='H',st2)): return True
    if not Imp(s=='b',Xor(st1,st2)): return True
    return False

def main():
    tm = time() # Timer Start
    X = 'ABCDE' # 犯人
    P = 'HLb'   # H:正直者; L:ウソつき; b:両方
    for x in itertools.combinations(X,2):
        ax,bx,cx,dx = 'A' in x,'B' in x,'C' in x,'D' in x
        for p in itertools.product(P,repeat=5):
            if not p.count('H')==1: continue
            if not p.count('L')==1: continue
            if not p.count('b')==3: continue
            a,b,c,d,e = p
            if check(a,a!='H',b!='L'): continue
            if check(b,not bx,    dx): continue
            if check(c,not cx,not ax): continue
            if check(d,    dx,a!='H'): continue
            if check(e,not bx,not cx): continue
            pass # チェックを潜り抜けたものだけを表示
            print('[A,B,C,D,E]')
            print(toStr(p))
            print(u'犯人: %s'%toStr(x))

    print("Runtime : %.3f [sec]"%(time()-tm))   # Timer Stop & Disp

if __name__ == '__main__':
    main()

●実行結果

[A,B,C,D,E]
[b,L,H,b,b]
犯人: [B,E]
Runtime : 0.000 [sec]

※参考URL
知恵袋の「ウソつき問題」をPythonで解いてみた。 - rscのブログ
知恵袋の「ウソつき問題」をPythonで解いてみた。(2) - rscのブログ
知恵袋の「ウソつき問題」をPythonで解いてみた。(3) - rscのブログ
知恵袋の「ウソつき問題」をPythonで解いてみた。(4) - rscのブログ
知恵袋の「ウソつき問題」をPythonで解いてみた。(5) - rscのブログ
知恵袋の「ウソつき問題」をPythonで解いてみた。(6) - rscのブログ
知恵袋の「ウソつき問題」をPythonで解いてみた。(7) - rscのブログ
知恵袋の「ウソつき問題」をPythonで解いてみた。(8) - rscのブログ
知恵袋の「ウソつき問題」をPythonで解いてみた。(9) - rscのブログ
OKWAVEの「ウソつき問題」をPythonで解いてみた。 - rscのブログ
天使と悪魔と道化の「ウソつき問題」をPythonで解いてみた。 - rscのブログ
知恵袋の「うそつき問題」をJavaで解いてみた。
ネットで見つけた「うそつき問題」をJavaで解いてみた。
ネットで見つけた「うそつき問題」を自分で解いてみた。
2つの発言の「うそつき問題」をJavaで解いてみた。