知恵袋で見つけた判断推理の円卓問題をPythonで解いてみた。

 知恵袋で見つけた判断推理の円卓問題Pythonで解いてみました。(^_^;

 A〜E の5人が円卓に等間隔で着席している。5人のうち女性は2人で、この2人の席は隣り合っていない。5人はそれぞれ赤,青,白,黒,緑のシャツを着ており,同じ色のシャツを着ている者はいない。A〜D の4人が以下のように述べているとき,確実にいえるものはどれか。
 A「私の左隣には黒いシャツを着た人が座っており,その左隣は男性である。」
 B「私の右隣には白いシャツを着た人が座っており,その右隣は女性である。」
 C「私の左隣には緑のシャツを着た人が座っており,その左隣は男性である。」
 D「私の隣には青いシャツを着た人が座っている。私とその両隣に座っている(青いシャツを着た人は勿論のこと、もう1人の)人のシャツは黒ではない。」
1 A は青いシャツを着ている。
2 B は女性である。
3 C は白いシャツを着ている。
4 D は男性である。
5 E は赤いシャツを着ている。

ただし、条件Dが分かりにくいので分かり易く書き直したり、選択肢等を補ったりしておきました。
 左隣・右隣の条件を考えやすくするために、円卓の座席に反時計回りに次のような座席番号を付けました。また、円順列を考えるので、Aを座席番号[0]に固定して考えました。

       [0]

 [1]         [4]


    [2]   [3]

 ちなみに、Aの左隣と右隣の人の座席番号は、それぞれ次式で表すことができます。

・左隣:(p.index('A')-1)%5
・右隣:(p.index('A')+1)%5

ただし、pは下記プログラム参照。

● RoundTableCh1.py

# coding: UTF-8
# RoundTableCh1.py

import itertools
from time import time

def main():
    tm=time()  # Timer Start
    choices = [True]*5
    P = 'ABCDE' # 名
    Q = 'BCGRW' # 色(B:黒; C:青; G:緑; R:赤; W:白)
    R = 'FFMMM' # 性(F:女; M:男)
    count = 0
    for p in itertools.permutations(P,5):
        if p[0]!='A': continue                                  # Aを固定
        a,b,c = 0, p.index('B'), p.index('C')                   # 座席番号
        d,e   =    p.index('D'), p.index('E')
        for q in itertools.permutations(Q,5):
            if q[(a-1)%5]!='B': continue                        # 条件A
            if q[(b+1)%5]!='W': continue                        # 条件B
            if q[(c-1)%5]!='G': continue                        # 条件C
            if q[(d-1)%5]!='C' and q[(d+1)%5]!='C': continue    # 条件D
            if q[d]=='B': continue                              # 条件D
            if q[(d-1)%5]=='B' or  q[(d+1)%5]=='B': continue    # 条件D
            for r in set(itertools.permutations(R,5)):  # 同じものを含む順列
                s = ''.join(r)*2
                if 'FF' in s: continue
                if r[(a-2)%5]!='M': continue                    # 条件A
                if r[(b+2)%5]!='F': continue                    # 条件B
                if r[(c-2)%5]!='M': continue                    # 条件C
                # チェックを潜り抜けたものだけを表示
                count+=1
                print(u'[ %d ]       %s    '%(count, p[0]))
                print(u'%s | %s/⌒\%s'%(''.join(p),p[1],p[4]))
                print(u'%s |  \__/   '%(''.join(q)))
                print(u'%s |   %s  %s  '%(''.join(r),p[2],p[3]))
                # 選択肢のチェック
                choices[0] &= (q[a]=='C')
                choices[1] &= (r[b]=='F')
                choices[2] &= (q[c]=='W')
                choices[3] &= (r[d]=='M')
                choices[4] &= (q[e]=='R')

    if count==0: choices = [False]*5
    s = ""
    for c in choices:
        if c : s+=" %s"%(choices.index(c)+1)
    print(u"∴%s"%s)
    print("Runtime : %.3f [sec]"%(time()-tm))   # Timer Stop & Disp

if __name__ == '__main__':
    main()

●実行結果

[ 1 ]       A
ADBCE | D/⌒\E
CRGWB |  \__/
MMFMF |   B  C
[ 2 ]       A
ADCEB | D/⌒\B
WGCRB |  \__/
MFMMF |   C  E
∴ 2
Runtime : 0.003 [sec]

※参考URL
判断推理の円卓問題をPythonで解いてみた。
知恵袋で見つけた判断推理の円卓問題をPythonで解いてみた。(2)
知恵袋で見つけた判断推理の円卓問題をPythonで解いてみた。(3)