判断推理の円卓問題をPythonで解いてみた。

 ネットで見つけた判断推理の円卓問題Pythonで解いてみました。(^_^;
 「A〜Hの8人が丸いテーブルのまわりに等間隔に腰かけた。」という設定で、左隣・右隣の条件を考えやすくするために、円卓の座席に反時計回りに次のような座席番号を付けました。また、円順列を考えるので、Aを座席番号[0]に固定して考えました。

       [0]
   [1]     [7]

 [2]         [6]

   [3]     [5]
       [4]

 次のように条件を記号化すると、

「PはQと向かい合っていた。」⇒「P ⇔ Q」
「PはQの隣であった。」⇒「PQ / QP」
「Pの左隣はQである。」⇒「QP」
「Pの右隣はQである。」⇒「PQ」
「Pの1人おいた隣はQであった。」⇒「P口Q / Q口P」
「Pの右3人目はQである。」⇒「P口口Q」

 条件ア〜カと選択肢1〜5は以下のように表すことができます。

 ア:A口D / D口A | 1:A ⇔ F
 イ:B口D / D口B | 2:B口口G
 ウ:CB / BC     | 3:BC
 エ:E ⇔ C        | 4:D ⇔ H
 オ:FD / DF     | 5:EA
 カ:GA / AG     |

 隣接条件等を調べるのに、正規表現を使いました。
 また、条件「PはQと向かい合っていた。」をPythonの式で表すと、ざっと思い付いただけで次の3つが考えられますが、他の条件に合わせて正規表現を使ってみました。(^_^;

    abs(p.index('P')-p.index('Q'))==4
    p[(p.index('P')+4)%8]=='Q'
    re.search(r'P...Q',t)!=None

ただし、p,tについては下記プログラム参照。

RoundTable.py

# coding: UTF-8
# RoundTable.py

import itertools
import re
from time import time

def main():
    tm=time()  # Timer Start
    choices = [True]*5
    P = 'ABCDEFGH'
    count = 0
    for p in itertools.permutations(P):
        if p[0]!='A': continue                      # Aを固定
        s = ''.join(p)                              # 座席表
        t = s*2
        if not re.search(r'A.D|D.A',t): continue    # 条件ア
        if not re.search(r'B.D|D.B',t): continue    # 条件イ
        if not re.search( r'BC|CB' ,t): continue    # 条件ウ
        if not re.search( r'C...E' ,t): continue    # 条件エ
        if not re.search( r'DF|FD' ,t): continue    # 条件オ
        if not re.search( r'AG|GA' ,t): continue    # 条件カ
        # チェックを潜り抜けたものだけを表示
        count+=1
        print( '[%2d] %s'%(count,s))
        print(u'      %s     '% p[0])
        print(u'  %s/⌒\%s '%(p[1],p[7]))
        print(u' %s|    |%s'%(p[2],p[6]))
        print(u'  %s\_/%s '%(p[3],p[5]))
        print(u'     %s      '% p[4])
        # 選択肢のチェック
        choices[0] &= re.search(r'A...F',t)!=None
        choices[1] &= re.search(r'B..G' ,t)!=None
        choices[2] &= 'BC' in t
        choices[3] &= re.search(r'D...H',t)!=None
        choices[4] &= 'EA' in t

    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] AEDFBCHG
      A
  E/⌒\G
 D|    |H
  F\_/C
     B
[ 2] AGHCBFDE
      A
  G/⌒\E
 H|    |D
  C\_/F
     B
∴ 4
Runtime : 0.031 [sec]

※参考URL
お気楽 Python プログラミング入門 第 4 回 正規表現とジェネレータ
Pythonの正規表現 - 手習い録 - ココログ
知恵袋で見つけた判断推理の円卓問題をPythonで解いてみた。