知恵袋で見つけた判断推理のリーグ戦の問題をPythonで解いてみました。以前、Javaで作ったのをPythonで作り直してみました。今回は選択肢のチェックもしておきました。
A〜Fの6チームで野球のリーグ戦を行ったところ、対戦結果について次のア〜カのことがわかった。このとき確実にいえるのはどれか。
ア、Aは1勝2敗2引き分けであった。
イ、BはAに勝った。
ウ、CはFにのみ勝った。
エ、Dは3勝2敗であった。
オ、EはAに敗れ、2勝3敗であった。
カ、FはDに敗れ、1勝3敗1引き分けであった。
選択肢
1、AはFに勝った。
2、Bは無敗であった。
3、Cは1勝2敗2引き分けであった。
4、DはEに勝った。
5、FはEに敗れた。
勝ち点p[i]を勝ち100点、引分け10点、負け1点とすると、表中の反対称な得点q[i]は100/p[i]で表すことができます。また、合計点の百の位が勝ち数、十の位が引分け数、一の位が負け数になります。
空欄を変数p[i],q[i](ただし、i=0〜10)でおいて、条件を表であらわすと次のようになります。
それから、扱いやすいように表の1行をそれぞれリストla〜lfにしました。(^_^;
+------+------+------+------+------+------+------+ | | A | B | C | D | E | F |(相手) +------+------+------+------+------+------+------+ | A | \ | X | p[0] | p[1] | 〇 | p[2] | 1勝2敗2分⇒122 +------+------+------+------+------+------+------+ | B | 〇 | \ | p[3] | p[4] | p[5] | p[6] | +------+------+------+------+------+------+------+ | C | q[0] | q[3] | \ | p[7] | p[8] | 〇 | 1勝のみ ⇒1?? +------+------+------+------+------+------+------+ | D | q[1] | q[4] | q[7] | \ | p[9] | 〇 | 3勝2敗 ⇒302 +------+------+------+------+------+------+------+ | E | X | q[5] | q[8] | q[9] | \ | p[10]| 2勝3敗 ⇒203 +------+------+------+------+------+------+------+ | F | q[2] | q[6] | X | X | q[10]| \ | 1勝3敗1分⇒113 +------+------+------+------+------+------+------+ ※〇:勝(100); △:分(10); X:敗(1)
ループを分けてネストを深くした方が高速ですが、最近のPCの高速化に甘えて、ネストが深くならない方を選びました。(^_^;
形は悪くなりますが、qのリストを生成する前にAの勝敗数で枝狩りした方が高速化するようなので、この枝狩りだけ前の方にもって来ました。(^_^;
ちなみに、リストをタプルに変更すると少しだけ速くなります。(^_^;
● LeagueMatch.py
# coding: UTF-8 # LeagueMatch.py import itertools from time import time def PrintResult(lst): n = len(lst) S = u' ABCDEF' print(S) for i in range(n): s = S[i+1] for j in range(n): k = lst[i][j] if k==100: s+=u'〇' # 勝:100 elif k== 10: s+=u'△' # 分: 10 elif k== 1: s+=u'X' # 敗: 1 else: s+=u'\' print(s) def main(): tm = time() # Timer Start NAME = 'ABCDEF' N = 11 ch = [True]*5 cnt = 0 for p in itertools.product([100,10,1],repeat=N): # 勝:100; 分:10; 敗:1 la = [ 0 , 1 ,p[ 0],p[ 1], 100 ,p[ 2]] # 条件イ,オ if sum(la)!=122: continue # 条件ア q = [100//p[i] for i in range(N)] # 反対称な得点 lb = [ 100 , 0 ,p[ 3],p[ 4],p[ 5],p[ 6]] # 条件イ lc = [q[ 0],q[ 3], 0 ,p[ 7],p[ 8], 100 ] # 条件ウ ld = [q[ 1],q[ 4],q[ 7], 0 ,p[ 9], 100 ] # 条件カ le = [ 1 ,q[ 5],q[ 8],q[ 9], 0 ,p[10]] # 条件オ lf = [q[ 2],q[ 6], 1 , 1 ,q[10], 0 ] # 条件ウ,カ if sum(lc)//100!=1: continue # 条件ウ if sum(ld)!=302: continue # 条件エ if sum(le)!=203: continue # 条件オ if sum(lf)!=113: continue # 条件カ # チェックを潜り抜けたものだけを表示 cnt+=1 print("[%d]"%cnt) PrintResult([la,lb,lc,ld,le,lf]) # 選択肢のチェック ch[0] &= (la[NAME.index('F')]==100) ch[1] &= (sum(lb)%10==0) ch[2] &= (sum(lc)==122) ch[3] &= (ld[NAME.index('E')]==100) ch[4] &= (lf[NAME.index('E')]== 1) 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] ABCDEF A\X△X〇△ B〇\〇〇〇〇 C△X\XX〇 D〇X〇\X〇 EXX〇〇\X F△XXX〇\ [2] ABCDEF A\X△X〇△ B〇\△〇〇〇 C△△\XX〇 D〇X〇\X〇 EXX〇〇\X F△XXX〇\ ∴ 2 Runtime : 0.359 [sec]
※参考URL
●知恵袋で見つけた判断推理のリーグ戦の問題をJavaで解いてみた。
●知恵袋で見つけた判断推理のリーグ戦の問題をPythonで解いてみた。