知恵袋の判断推理の座席の位置関係の問題をPythonで解いてみた。

 知恵袋の判断推理の座席の位置関係の問題Pythonで解いてみました。(^_^;

 A〜Hの8人が図のような配置に着いて、赤ワインと白ワインのいずれかを選択して飲んでいる。次のア〜オのことが分かっているとき、確実にいえるのはどれか。なお、テーブルの角をはさんで座っている場合は、隣に座っているとは言わない。

    ロロロ
  +---+
ロ|      |ロ
  +---+
    ロロロ

ア: Aは白ワインを飲んでおり、Aの両隣の人は赤ワインを飲んでいる。
イ: Bの正面には白ワインを飲んでいるFが座っている。
ウ: 隣合わせに座っているCとHは、二人とも白ワインを飲んでいる。
エ: CはGの正面から一人おいた隣に座っている。
オ: Dの左隣も正面も白ワインを飲んでいる。
選択肢
1. Bは赤ワインを飲んでいて、両隣には誰も座っていない。
2. Cの左隣はHで、Hの左隣はDである。
3. Dは白ワインを飲んでいて、正面はCである。
4. Eの正面は赤ワインを飲んでいるGである。
5. Hの右隣はEで正面はDである。

 左隣・右隣の条件を考えやすくするために、次のように座席番号を付けました。A〜Hの順列と赤(r)と白(w)の重複順列を生成し条件をチェックしました。

    [7][6][5]
   +---------+
[0]|         |[4]
   +---------+
    [1][2][3]

 ちなみに、条件エは、{C,G}の組は座席番号{[1],[5]}または、{[3],[7]}の組ということで、組を識別するのに積を使いました。(^_^;

● seating2.py

# coding: UTF-8
# seating2.py

import itertools
from time import time

# 座席リストpからcの左隣の座席番号を得る
def seatNoL(c,p):
    s = '|%s|%s%s%s|%s|%s%s%s|'%p
    r = s[s.index(c)-1]
    if r=='|': return -1    # 誰も座っていないときは-1を返す
    return p.index(r)

# 座席リストpからcの正面の座席番号を得る
def seatNoF(c,p):
    i = p.index(c)
    return 8-i if i%4!=0 else 4-i

def main():
    tm=time()  # Timer Start
    choices = [True]*5
    P = 'ABCDEFGH'
    count = 0
    for p in itertools.permutations(P):
        s = '|%s|%s%s%s|%s|%s%s%s|'%p                   # 座席表
        if '|A' in s or 'A|' in s: continue             # 条件ア
        if p[seatNoF('B',p)]!='F': continue             # 条件イ
        if 'CH' not in s and 'HC' not in s: continue    # 条件ウ
        m = p.index('C')*p.index('G')
        if m!=21 and m!=5: continue                     # 条件エ
        if '|D' in s: continue                          # 条件オ
        for q in itertools.product('rw',repeat=8): # r:赤; w:白
            a = p.index('A')                            # Aの座席番号
            if q[a-1]!='r': continue                    # 条件ア
            if q[a  ]!='w': continue                    # 条件ア
            if q[a+1]!='r': continue                    # 条件ア
            if q[p.index('F')]!='w': continue           # 条件イ
            if q[p.index('C')]!='w': continue           # 条件ウ
            if q[p.index('H')]!='w': continue           # 条件ウ
            if q[seatNoL('D',p)]!='w': continue         # 条件オ
            if q[seatNoF('D',p)]!='w': continue         # 条件オ
            # チェックを潜り抜けたものだけを表示
            count+=1
            print('- %2d -'%count)
            print("     [%s:%s][%s:%s][%s:%s]"%(p[7],q[7],p[6],q[6],p[5],q[5]))
            print("[%s:%s][             ][%s:%s]"%(p[0],q[0],p[4],q[4]))
            print("     [%s:%s][%s:%s][%s:%s]"%(p[1],q[1],p[2],q[2],p[3],q[3]))
            # 選択肢のチェック
            choices[0] &= q[p.index('B')]=='r'
            choices[0] &= '|B|' in s
            choices[1] &= 'DHC' in s
            choices[2] &= q[p.index('D')]=='w'
            choices[2] &= p[seatNoF('D',p)]=='C'
            choices[3] &= p[seatNoF('E',p)]=='G'
            choices[3] &= q[p.index('G')]=='r'
            choices[4] &= 'HE'  in s
            choices[4] &= p[seatNoF('H',p)]=='D'

    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 -
     [D:r][A:w][G:r]
[B:r][             ][F:w]
     [C:w][H:w][E:r]
-  2 -
     [D:r][A:w][G:r]
[B:r][             ][F:w]
     [C:w][H:w][E:w]
       …(省略)…
- 16 -
     [E:w][H:w][C:w]
[F:w][             ][B:w]
     [G:r][A:w][D:r]
∴ 4
Runtime : 0.063 [sec]