判断推理のお弁当のおかずの種類の問題をPythonで解いてみた。

 判断推理のお弁当のおかずの種類の問題Pythonで解いてみました。(^_^;

 ある幼稚園では、図のように4人ずつのグループで円卓を囲んでお弁当を食べる。
 ある日のA〜Dの4人のお弁当に入っているおかずの種類を数えると、ハンバーグ、ベーコン巻き、春巻き、トマト、ブロッコリー、ポテトサラダの6種類だった。
 どの子供のお弁当も3種類ずつ入っており、向かいの人と同じおかずは一つもないが、隣の人とは同じおかずが少なくとも一つあった。・・・条件ア
 4人のお弁当のおかずについて次のことがわかっているとき、確実にいえるのはどれか。
 〇 Aには、ハンバーグとポテトサラダが入っていた。・・・条件イ
 〇 Bには、Aと同じおかずが二つあった。・・・条件ウ
 〇 Cには、トマトと春巻きが入っていた。・・・条件エ
 〇 Dには、春巻きもブロッコリーも入っていなかった。・・・条件オ

1. AとBのお弁当には、どちらもブロッコリーが入っていた。
2. AとDのお弁当には、どちらもハンバーグが入っていた。
3. BとCのお弁当には、どちらもハンバーグは入っていなかった。
4. BとDのお弁当には、どちらもポテトサラダは入っていなかった。
5. CとDのお弁当には、どちらもポテトサラダは入っていなかった。

    A
  /|\
 D--+--B
  \|/
    C

 ただし、条件にア〜オの名前を付けました。また、プログラムでは、次のような略号を用いました。

 おかず:(ハンバーグ,ベーコン巻き,春巻き,トマト,ブロッコリー,ポテトサラダ)
    ⇒(ハ,ベ,春,ト,ブ,ポ)

 プログラムで、条件ア-1の向かいの人の条件と条件ア-2の隣の人の条件は、それぞれ次式で表すことができます。
 条件ア-1:len(set(x+y))==6
 条件ア-2:len(set(x+y))< 6
ただし、x,yは、向かい合う二人または、隣り合う二人のお弁当のおかずのタプルです。(^_^;
 ちなみに、向かいの人の条件から、c,dを次式のように決めると、ループを2つ省くことができます。
 c = tuple(set(B)-set(a))
 d = tuple(set(B)-set(b))

● Bento1.py

# coding: UTF-8
# Bento1.py

import itertools
from time import time

def toStr(lst):
    return '[%s]'%','.join(lst)

def main():
    tm = time()  # Timer Start
    ch = [False]*5
    B = u'ハベ春トブポ'
    cnt = 0
    for a in itertools.combinations(B,3):
        if not u'ハ' in a: continue                     # 条件イ
        if not u'ポ' in a :continue                     # 条件イ
        for b in itertools.combinations(B,3):
            if not len(set(a+b))==6-2: continue         # 条件ウ
            for c in itertools.combinations(B,3):
                if not u'ト' in c: continue             # 条件エ
                if not u'春' in c: continue             # 条件エ
                if not len(set(a+c))==6: continue       # 条件ア-1
                if not len(set(b+c))< 6: continue       # 条件ア-2
                for d in itertools.combinations(B,3):
                    if u'春' in d: continue             # 条件オ
                    if u'ブ' in d: continue             # 条件オ
                    if not len(set(b+d))==6: continue   # 条件ア-1
                    if not len(set(c+d))< 6: continue   # 条件ア-2
                    if not len(set(d+a))< 6: continue   # 条件ア-2
                    # チェックを潜り抜けたものだけを表示
                    cnt+=1
                    print("[%d]"%cnt)
                    print('A: '+toStr(a))
                    print('B: '+toStr(b))
                    print('C: '+toStr(c))
                    print('D: '+toStr(d))
                    # 選択肢のチェック
                    if cnt==1: ch = [True]*5
                    ch[0] &= (u'ブ' in a and u'ブ' in b)
                    ch[1] &= (u'ハ' in a and u'ハ' in d)
                    ch[2] &= (u'ハ' not in b and u'ハ' not in c)
                    ch[3] &= (u'ポ' not in b and u'ポ' not in d)
                    ch[4] &= (u'ポ' not in c and u'ポ' not in d)
    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]
A: [ハ,ブ,ポ]
B: [ハ,春,ブ]
C: [ベ,春,ト]
D: [ベ,ト,ポ]
[2]
A: [ハ,ブ,ポ]
B: [春,ブ,ポ]
C: [ベ,春,ト]
D: [ハ,ベ,ト]
∴ 1
Runtime : 0.015 [sec]