判断推理の幼稚園児の並び順の問題をPythonで解いてみた。

 知恵袋で見つけた判断推理の幼稚園児の並び順の問題Pythonで解いてみました。(^_^;

 東工大附属幼稚園の園児8 人が次の1~14 の条件を全て満たすように横一列に並んでこちらを向いています。
なお、下記文中のアルファベット大文字(A,B,C など)は、個人名を表し、同じ名前の園児はいないものとします。

 条件以下、長いので省略(知恵袋を参照してください。)
 難しいのは、たとえば、「A から見て左」(条件5)というのは、「横一列に並んでこちらを向いています」というとこで、「列に向かって」(条件8)見ると逆の右になります。これに気付くのに時間がかかてしまいました。(^_^;
 ベストアンサーでは、園児から見て左右をとっていますが、プログラムでは、「列に向かって」見て左右をとりました。したがって、結果がベストアンサーとは逆になっています。(^_^;
 それから、帽子とリボンの設定ですが、全員帽子をかぶっていて、3人だけ、リボン付きということにしました。(^_^;
また、リボンは、(橙、赤、桃)と全部わかっていますが、帽子の色は、黄色しか分かっていません。それで、条件3は、黄色だけチェックしてみましたが、コメントアウトしても結果が変わらないので省略しました。(^_^;
 問(4)の条件を加えると、確定するようなので、プログラムに加えてみました。(^_^;
 問題に出てくる要素、プログラムで用いた略号等の概要は次の通りです。

場所    PLACE   12345678  12345678
名前    NAME    ABCDEFGH  ABCDEFGH
性別    SEX     男男男男女女女女  mmmmffff
服の色  WEAR    黄黄緑緑桃白橙水  YYGGPWOC
帽子色  HAT     橙赤桃黄無無無無  ORPYxxxx
リボン  RIBBON  有有有無無無無無  rrrhhhhh
鞄の色  BAG     白赤黒黄緑水無無  WRBYGCxx
時計    WATCH   有有有有無無無無  ooooxxxx

● KinderGarten1.py

# coding: UTF-8
# KinderGarten1.py

import itertools
from time import time

# 条件チェック: a[]の要素xからm個右側にb[]の要素yがあるか調べる
def chkCond(m, a, x, b, y):
    n = a.index(x)
    if n==ValueError:
        return False
    if not 0<=m+n< len(a):
        return False
    return b[m+n]==y

# 同じものを含むb[]の要素yに対応するa[]の要素をすべて求める
def getXsOf(a, b, y):
    r = []
    for n in range(len(a)):
        if b[n]==y:
            r.append(a[n])
    return r

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

def main():
    tm = time()  # Timer Start
    # 要素を昇順にソートしたもの
    PLACE  = "12345678"    # 場所(列に向かって左右の並び順、園児から見て逆)
    NAME   = "ABCDEFGH"    # 園児の名前
    SEX    = "ffffmmmm"    # 性別      (女女女女男男男男)
    WEAR   = "CGGOPWYY"    # 服の色    (水緑緑橙桃白黄黄)
    HAT    = "OPRYxxxx"    # 帽子の色  (橙桃赤黄無無無無) 無:分からない
    RIBBON = "hhhhhrrr"    # リボン有無(無無無無無有有有)
    BAG    = "BCGRWYxx"    # 鞄の色    (黒水緑赤白黄無無)
    WATCH  = "ooooxxxx"    # 時計の有無(有有有有無無無無)

    place = tuple(PLACE)   # 固定
    Sexes = []
    for sex in set(itertools.permutations(SEX)):
        s = toStr(sex)
        if 'mm' in s or 'ff' in s: continue # 条件01
        if not s[-1]=='f': continue         # 条件04,08
        Sexes.append(sex)
##    print(Sexes); exit()
    sex = Sexes[0]    # 1通りしかないので
    Watches = []
    for watch in set(itertools.permutations(WATCH)):
        s = toStr(watch)
        if 'oo' in s: continue  # 条件10
        Watches.append(watch)
##    print(Watches); exit()
    Names   = tuple(itertools.permutations(NAME))
    Wears   = tuple(set(itertools.permutations((WEAR))))
    Hats    = tuple(set(itertools.permutations((HAT))))
    Ribbons = tuple(set(itertools.permutations((RIBBON))))
    Bags    = tuple(set(itertools.permutations((BAG))))
##    print(len(Sexes))
##    print(len(Watches))
##    print(len(Names))
##    print(len(Wears))
##    print(len(Hats))
##    print(len(Ribbons))
##    print(len(Bags))
    cnt = 0
    for watch in Watches:               # watch loop
        for name in Names:              # name loop
            if not chkCond( 0,name,'A',sex,  'm'): continue # 条件05
            if not chkCond( 0,name,'E',sex,  'f'): continue # 条件06
            if not chkCond(-2,name,'G',name, 'E'): continue # 条件06
            if not chkCond( 0,name,'H',sex,  'f'): continue # 条件09
            if not chkCond(-1,name,'B',watch,'o'): continue # 条件11
            if not chkCond( 1,name,'B',watch,'o'): continue # 条件11
            if not chkCond( 0,name,'A',watch,'o'): continue # 問(4)の条件

            for ribbon in Ribbons:      # ribbon loop
                if not chkCond( 0,name, 'F',ribbon,'r'): continue   # 条件07
                if not chkCond( 1,name, 'F',ribbon,'h'): continue   # 条件07
                if not chkCond( 0,place,'8',ribbon,'r'): continue   # 条件08
                if not chkCond(-1,name, 'B',ribbon,'r'): continue   # 条件11
                if not chkCond( 1,name, 'B',ribbon,'r'): continue   # 条件11
                if not chkCond(-1,name, 'C',ribbon,'r'): continue   # 条件14
                if not chkCond( 1,name, 'C',ribbon,'r'): continue   # 条件14

                for hat in Hats:        # hat loop
                    if not chkCond( 0,name, 'F',hat, 'O'): continue # 条件07
                    if not chkCond( 1,name, 'F',hat, 'Y'): continue # 条件07
                    if not chkCond( 0,place,'8',hat, 'R'): continue # 条件08
                    if not chkCond(-1,name, 'C',hat, 'O'): continue # 条件14
                    if not chkCond( 1,name, 'C',hat, 'P'): continue # 条件14

                    for bag in Bags:    # bag loop
                        if not chkCond( 3,name, 'A',bag,'W'): continue  # 条件05
                        if not chkCond( 0,place,'1',bag,'R'): continue  # 条件08
                        if not chkCond( 0,place,'8',bag,'G'): continue  # 条件08
                        if not chkCond( 0,name, 'H',bag,'C'): continue  # 条件09
                        if     chkCond(-1,name, 'H',bag,'C'): continue  # 条件09
                        if not chkCond( 1,name, 'H',bag,'x'): continue  # 条件09
                        if not chkCond( 0,name, 'B',bag,'Y'): continue  # 条件11
                        s = toStr(getXsOf(bag,watch,'o'))
                        if 'x' in s: continue   # 条件10

                        for wear in Wears:              # wear loop
                            s = toStr(wear)
                            if 'yy' in s or 'gg' in s: continue         # 条件01
##                            n = hat.index('Y')
##                            if sex[n]=='m' and wear[n]=='Y': continue   # 条件03
                            if not chkCond( 3,name,'A',wear,'Y'): continue  # 条件05
                            if not chkCond( 0,name,'E',wear,'P'): continue  # 条件06
                            if not chkCond(-1,name,'F',wear,'W'): continue  # 条件07
                            if not chkCond( 0,name,'H',wear,'O'): continue  # 条件09
                            if not chkCond(-1,name,'H',wear,'C'): continue  # 条件09
                            if not chkCond( 1,name,'H',wear,'W'): continue  # 条件09
                            if not chkCond( 0,name,'C',wear,'G'): continue  # 条件14
                            if not chkCond( 3,name,'C',wear,'G'): continue  # 条件14
                            s = toStr(getXsOf(wear,sex,'f'))
                            if 'yy' in s or 'gg' in s: continue         # 条件02
                            s = toStr(getXsOf(wear,sex,'m'))
                            if 'yy' in s or 'gg' in s: continue         # 条件02
                            pass # チェックを潜り抜けたものだけを表示
                            cnt+=1
                            print('[%d]'%cnt)
                            print('#:'+toStr(place ))
                            print('N:'+toStr(name  ))
                            print('S:'+toStr(sex   ))
                            print('W:'+toStr(wear  ))
                            print('H:'+toStr(hat   ))
                            print('R:'+toStr(ribbon))
                            print('B:'+toStr(bag   ))
                            print('W:'+toStr(watch ))
                            print('')
                            P = set(getXsOf(name,sex,'f'))
                            Q = set(getXsOf(name,ribbon,'h'))
                            print('(1) %s'%toStr(P&Q))
                            print('(2) %s'%name[bag.index('B')])
                            print('(3) %s'%wear[name.index('D')-1])
                            P = set(getXsOf(name,watch,'o'))
                            n = name.index('B')
                            Q = {'A',name[n-1],name[n+1]}
                            print('(4) %s'%toStr(P-Q))

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

if __name__ == '__main__':
    main()

●実行結果

[1]
#:12345678
N:AHDFCEBG
S:mfmfmfmf
W:COWYGPYG
H:xxxOYPxR
R:hhhrhrhr
B:RCxWxBYG
W:oxxoxoxo

(1) H
(2) E
(3) O
(4) F
Runtime : 0.953 [sec]

※参考URL
Zebra PuzzleをPythonで解いてみた。 - rscのブログ
【Python入門】すぐわかる!set型(集合型)の基本まとめ | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト