人形の持ち主の論理パズルをPythonで解いてみました。以前、Javaで書いたプログラムをPythonで書き直してみました。(^_^;
P、Q、Rの3人が人形を2つずつ持っている。それらの6つの人形は(A~Fとする)は目の色がそれぞれ異なり(黒、茶、青、緑、橙、灰)、髪の色もそれぞれ異なっている(茶、橙、金、銀、黒、赤)。
1.ある者はAと黒い目の人形の2つを持っていて、別の者はBと茶髪の人形の2つを持っている。また、さらに別の者は橙色の髪の人形(Eではない)と茶色の目の人形の2つを持っている。
2.Cの髪は金髪で、Qがこの人形を持っている。
3.青い目の人形の髪は銀色で、この人形を持っているのはR。
4.ある者はDと緑の目の人形の2つを持っている。
5.ある者は橙色の目の人形と黒髪の人形の2つを持っている。
さて、6つの人形それぞれの目の色、髪の色、持ち主は?
初め、枝刈りの条件チェックは、eye ループに書きましたが、高速化のために前に移せるものは出来るだけ前に移しました。
Java から翻訳するとき、次の関数を使うことも考えましたが、「if not 条件: continue」で直感的にわかりやすく書き直してみました。
def isSame(lc, la, x, lb, y):
z = getXof(lc, la, x)
return z == getXof(lc, lb, y) if z is not None else False
ちなみに、たとえば、getXof(DOLL, ownr, ~) のように、対応するものが2つあって関数になっていない場合は使えないことに注意しましょう。(^_^;
● DollPuzzle1.py
import itertools
from time import time
def getPos(la, x):
return la.index(x) if x in la else -1
def getXof(la, lb, y):
n = getPos(lb, y)
return la[n] if n >= 0 else None
def main():
DOLL = "ABCDEF"
OWNR = "PPQQRR"
EYES = "黒茶青緑橙灰"
HAIR = "茶橙金銀黒赤"
tm = time()
for ownr in set(itertools.permutations(OWNR)):
if not getXof(ownr, DOLL, 'C') == 'Q': continue
for hair in itertools.permutations(HAIR):
if not getXof(ownr, DOLL, 'B') == getXof(ownr, hair, '茶'): continue
if not getXof(DOLL, hair, '茶') != 'B': continue
if not getXof(ownr, DOLL, 'A') != getXof(ownr, hair, '茶'): continue
if not getXof(ownr, DOLL, 'A') != getXof(ownr, hair, '橙'): continue
if not getXof(ownr, DOLL, 'B') != getXof(ownr, hair, '橙'): continue
if not getXof(DOLL, hair, '橙') != 'E': continue
if not getXof(DOLL, hair, '金') == 'C': continue
for eye in itertools.permutations(EYES):
if not getXof(ownr, DOLL, 'A') == getXof(ownr, eye, '黒'): continue
if not getXof(DOLL, eye, '黒') != 'A': continue
if not getXof(ownr, hair, '橙') == getXof(ownr, eye, '茶'): continue
if not getXof(DOLL, hair, '橙') != getXof(DOLL, eye, '茶'): continue
if not getXof(ownr, DOLL, 'B') != getXof(ownr, eye, '黒'): continue
if not getXof(DOLL, eye, '青') == getXof(DOLL, hair, '銀'): continue
if not getXof(ownr, eye, '青') == 'R': continue
if not getXof(ownr, DOLL, 'D') == getXof(ownr, eye, '緑'): continue
if not getXof(DOLL, eye, '緑') != 'D': continue
if not getXof(ownr, eye, '橙') == getXof(ownr, hair, '黒'): continue
if not getXof(DOLL, eye, '橙') != getXof(DOLL, hair, '黒'): continue
pass
print(f"D: {DOLL}")
print(f"O: {''.join(ownr)}")
print(f"E: {''.join(eye )}")
print(f"H: {''.join(hair)}")
print()
print("Runtime : %.3f [sec]"%(time()-tm))
if __name__ == '__main__':
main()
●実行結果
D: ABCDEF
O: RPQPRQ
E: 青緑茶橙黒灰
H: 銀黒金茶赤橙
Runtime : 0.338 [sec]
P.S.
ちなみに、Excel の XLOOKUP() 関数もどきの lookUp() 関数を使って書き直すと次のようになります。getPos() 関数と getXof() 関数を一つにまとめて、XLOOKUP() 関数の引数の並び順に合わせました。getXof() 関数とは、引数の並びが逆になっているのに注意してください。実行結果は同じなので省略します。
● DollPuzzle1a.py
import itertools
from time import time
def lookUp(x,la,lb):
n = la.index(x) if x in la else -1
return lb[n] if n >= 0 else None
def main():
DOLL = "ABCDEF"
OWNR = "PPQQRR"
EYES = "黒茶青緑橙灰"
HAIR = "茶橙金銀黒赤"
tm = time()
for ownr in set(itertools.permutations(OWNR)):
if not lookUp('C', DOLL, ownr) == 'Q': continue
for hair in itertools.permutations(HAIR):
if not lookUp('B', DOLL, ownr) == lookUp('茶', hair, ownr): continue
if not lookUp('茶', hair, DOLL) != 'B': continue
if not lookUp('A', DOLL, ownr) != lookUp('茶', hair, ownr): continue
if not lookUp('A', DOLL, ownr) != lookUp('橙', hair, ownr): continue
if not lookUp('B', DOLL, ownr) != lookUp('橙', hair, ownr): continue
if not lookUp('橙', hair, DOLL) != 'E': continue
if not lookUp('金', hair, DOLL) == 'C': continue
for eye in itertools.permutations(EYES):
if not lookUp('A', DOLL, ownr) == lookUp('黒', eye, ownr ): continue
if not lookUp('黒', eye, DOLL) != 'A': continue
if not lookUp('橙', hair, ownr) == lookUp('茶', eye, ownr): continue
if not lookUp('橙', hair, DOLL) != lookUp('茶', eye, DOLL): continue
if not lookUp('B', DOLL, ownr) != lookUp('黒', eye, ownr): continue
if not lookUp('青', eye, DOLL) == lookUp('銀', hair, DOLL): continue
if not lookUp('青', eye, ownr) == 'R': continue
if not lookUp('D', DOLL, ownr) == lookUp('緑', eye, ownr): continue
if not lookUp('緑', eye, DOLL) != 'D': continue
if not lookUp('橙', eye, ownr) == lookUp('黒', hair, ownr): continue
if not lookUp('橙', eye, DOLL) != lookUp('黒', hair, DOLL): continue
pass
print(f"D: {DOLL}")
print(f"O: {''.join(ownr)}")
print(f"E: {''.join(eye )}")
print(f"H: {''.join(hair)}")
print()
print("Runtime : %.3f [sec]"%(time()-tm))
if __name__ == '__main__':
main()
※参考URL
●人形の持ち主の論理パズルをJavaで解いてみた - rscのブログ