エイプリルフールなので、金貨と銅貨と空箱の「うそつき問題」をPythonで解いてみました。(^_^;
A~Eの五つの箱があり、これらの箱は、金貨の入った箱、銅貨の入った箱、空箱の3種類の場合がある。
また、それぞれの箱にはラベルが付いているが、そのラベルの記述の内容は、金貨の入った箱のものは真(真実に一致している)であるが、銅貨の入った箱のものは偽(真実に反している)であり、空箱のものは真の場合も偽の場合もあるという。
このとき、銅貨の入った箱が二つあるとすると、確実に銅貨の入った箱はどれか。
[ラベル]
A:「Bのラベルの記述の内容は真である。」
B:「Aが空箱ならば、この箱も空箱である。」
C:「この箱は、銅貨の入った箱である。」
D:「AかEの少なくとも一方は、銅貨の入った箱である。」
E:「この箱は、金貨の入った箱である。」
これは、天使と悪魔と人間の「うそつき問題」の類題です。
Aのラベルの記述の条件で、「b!='C'」のとこは、「b=='G' or b=='E'」や「Imp(a=='E',b=='E')」でもいいです。
● Liar12.py
# coding: UTF-8 # Liar12.py import itertools from time import time # 論理等価Eqv def Eqv(p,q): return not(p^q) # 論理包含Imp def Imp(p,q): return not p or q # 確実にいえる選択肢を1つ得る def getAns(cho,lbl='12345'): if cho.count(True)!=1: print('Error!') return ','.join([lbl[i] for i in range(len(cho)) if cho[i]]) def main(): tm = time() # Timer Start choices = [True]*5 P = 'CEG' for p in itertools.product(P,repeat=5): if not p.count('C')*p.count('E')*p.count('G')!=0: continue if not p.count('C')==2: continue a,b,c,d,e = p if not Imp(a!='E',Eqv(a=='G',b!='C')): continue if not Imp(b!='E',Eqv(b=='G',Imp(a=='E',b=='E'))): continue if not Imp(c!='E',Eqv(c=='G',c=='C')): continue if not Imp(d!='E',Eqv(d=='G',a=='C' or e=='C')): continue if not Imp(e!='E',Eqv(e=='G',e=='G')): continue pass # チェックを潜り抜けたものを表示 print(p) pass # 選択肢のチェック choices[0] &= (a=='C') choices[1] &= (b=='C') choices[2] &= (c=='C') choices[3] &= (d=='C') choices[4] &= (e=='C') print(u"∴%s"%getAns(choices,'ABCDE')) print("Runtime : %.3f [sec]"%(time()-tm)) # Timer Stop & Disp if __name__ == '__main__': main()
●実行結果
('E', 'C', 'E', 'C', 'G') ('E', 'C', 'E', 'G', 'C') ∴B
※参考URL
●天使と悪魔と道化の「ウソつき問題」をPythonで解いてみた。 - rscのブログ