知恵袋で見つけた判断推理のトーナメントの問題をPythonで解いてみた。(2)

 知恵袋で見つけた判断推理のトーナメントの問題Pythonで解いてみました。(^_^;

 ある大学のテニス大会で、AからGの7チームが、下図のようなトーナメント戦を行ったところ、次のア〜オのことが分かった。
ア Aは1回だけ勝ち、Bには負けた。
イ Cは初戦でGに敗退した。
ウ AとDは、ともにEとは対戦しなかった。
エ Dは2回戦で敗退した。
オ Gは2回勝ち、決勝戦で敗退した。
以上から判断して、確実にいえるのはどれか。

1.Aは1回戦でFと戦った。
2.BはFに勝った。
3.Cは2回戦からの登場だった。
4.Dは2回戦でBと戦った。
5.GはEに勝った。

 下図のようなトーナメント戦のそれぞれの位置に入るチーム名を、K,L,M,N,Q,R,S,X,Y,Z,U,V,Wとおいて、対称性からK<L, M<N, Q<R, K<Mと順序を与えることにします。

            W
      +-----+-----+    3回戦
      |           |
      U           V
   +--+--+     +--+--+ 2回戦
   |     |     |     |
   X     Y     Z     S
 +-+-+ +-+-+ +-+-+   | 1回戦
 |   | |   | |   |   |
 K < L M < N Q < R   S
 K  <  M

● TournamentTennis.py

# coding: UTF-8
# TournamentTennis.py

import itertools
from time import time

# cが何回戦まで出場したかを対戦データlstから求める
def getRound(c, lst):
    if c not in lst: return 1
    n = lst.index(c)+1
    if   n< 2: return 4
    elif n< 4: return 3
    else:      return 2

# aとbの対戦が対戦リストlst内にあるか調べる
def hasMatched(a, b, lst):
    if [a,b] in lst: return True
    if [b,a] in lst: return True
    return False

# aがbと対戦して勝ったかを対戦データlstから調べる
def hasWon(a, b, lst):
    if [a,b,a] in lst: return True
    if [b,a,a] in lst: return True
    return False

# 次元を下げる
def flatten(lst):
    return list(itertools.chain.from_iterable(lst))

def main():
    tm = time()  # Timer Start
    ch = [True]*5
        #1234567
    P = 'ABCDEFG'
    cnt = 0
    for p in itertools.permutations(P):
        k,l,m,n,q,r,s = p
        if k>=l or m>=n or k>=m or q>=r: continue
        lFst = [[k,l],[m,n],[q,r]]

        for b in itertools.product([True,False],repeat=6):
            x,y,z = k if b[0] else l, m if b[1] else n, q if b[2] else r
            u,v   = x if b[3] else y, z if b[4] else s
            w     = u if b[5] else v

            lSnd = [[x,y],[z,s]]
            lTrd = [[u,v]]
            lAll = lFst+lSnd+lTrd
            lgRd = [w]+flatten(lTrd+lSnd)           # getRound用データ
            lWin = lgRd[:-1]                        # 勝者のリスト[w,u,v,x,y,z]
            lhWn = [[k,l,x],[m,n,y],[q,r,z],[x,y,u],[z,s,v],[u,v,w]] # hasWon用

            if lWin.count('A')!=1:       continue   # 条件ア
            if not hasWon('B','A',lhWn): continue   # 条件ア
            if lWin.count('C')!=0:       continue   # 条件イ
            if not hasWon('G','C',lhWn): continue   # 条件イ
            if hasMatched('A','E',lAll): continue   # 条件ウ
            if hasMatched('D','E',lAll): continue   # 条件ウ
            if getRound('D',lgRd)!= 2:   continue   # 条件エ
            if lWin.count('G')!=2:       continue   # 条件オ
            if w=='G':                   continue   # 条件オ
            # チェックを潜り抜けたものだけを表示
            cnt+=1
            print("[%2d]        %c         "%(cnt,w))
            print("      +-----+-----+   ")
            print("      |           |   ")
            print("      %c           %c   "%(u,v))
            print("   +--+--+     +--+--+")
            print("   |     |     |     |")
            print("   %c     %c     %c     %c"%(x,y,z,s))
            print(" +-+-+ +-+-+ +-+-+   |")
            print(" |   | |   | |   |   |")
            print(" %c   %c %c   %c %c   %c   %c"%(k,l,m,n,q,r,s))
            print("")
            # 選択肢のチェック
            ch[0] &= hasMatched('A','F',lFst)
            ch[1] &= hasWon    ('B','F',lhWn)
            ch[2] &= (s=='C')
            ch[3] &= hasMatched('B','D',lSnd)
            ch[4] &= hasWon    ('G','E',lhWn)

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

if __name__ == '__main__':
    main()

●実行結果

[ 1]        B         
      +-----+-----+   
      |           |   
      B           G   
   +--+--+     +--+--+
   |     |     |     |
   A     B     G     D
 +-+-+ +-+-+ +-+-+   |
 |   | |   | |   |   |
 A   F B   E C   G   D

∴ 1
Runtime : 0.275 [sec]

※参考URL
http://stackoverflow.com/questions/103844/how-do-i-merge-a-2d-array-in-python-into-one-string-with-list-comprehension
Pythonでリストをflattenする方法まとめ - Soleil cou coupe
知恵袋で見つけた判断推理のトーナメントの問題をPythonで解いてみた。
知恵袋で見つけた判断推理のトーナメントの問題をPythonで解いてみた。(3)

Pythonスタートブック

Pythonスタートブック

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

Python入門[2&3対応]

Python入門[2&3対応]