知恵袋の判断推理の論理問題をPythonで解いてみた。

 知恵袋の判断推理の論理問題Pythonで解いてみました。(^_^;

 ある集団について調査をしたところ、次のA〜Dのことがわかった。ここから確実に言えるのは1〜5のうちどれか
A:数学が得意な人は英語が好きである。
B:音楽が好きな人は社会も数学も得意である。
C:社会が得意でない人は美術が好きである。
D:英語が好きな人や美術が好きでない人は国語が得意である

1.数学が得意な人は社会が得意である
2.国語が得意でない人は社会が得意でない
3.美術が好きな人は英語が好きである
4.音楽が好きな人は国語が得意である
5.英語が好きでない人は美術が好きである

 「数学が得意である」をm、「英語が好きである」をe、「音楽が好きである」をo、「社会が得意である」をs、「美術が好きである」をa、「国語が得意である」をjと置きました。
 論理包含「A⇒B」の真理値を得るImp(a,b)関数は、1番目の参考URLを参考にして作りました。
 ちなみに、not Imp(a,b) = not((not a) or b) = a and (not b)。

● Logic1.py

# coding: UTF-8
# Logic1.py

import itertools
from time import time

# 論理包含「A⇒B」の真理値を得る
def Imp(a,b):
    return not a or b

# 真理値表の1行を文字列で得る
def getRowOfTruthTable(lst):
    result = ""
    for b in lst:
        result += " T" if b else " F"
    return result

def main():
    tm=time()  # Timer Start
    print("[m,e,o,s,a,j]")  # m:数学; e:英語; o:音楽; s:社会; a:美術; j:国語
    choices = [True]*5
    for m,e,o,s,a,j in itertools.product([True,False],repeat=6):
        if not Imp(         m,      e): continue    # 条件A
        if not Imp(         o,s and m): continue    # 条件B
        if not Imp(     not s,      a): continue    # 条件C
        if not Imp(e or not a,      j): continue    # 条件D
        # チェックを潜り抜けたものだけを表示
        print(getRowOfTruthTable([m,e,o,s,a,j]))
        # 選択肢のチェック
        choices[0] &= Imp(    m,    s)
        choices[1] &= Imp(not j,not s)
        choices[2] &= Imp(not a,    e)
        choices[3] &= Imp(    o,    j)
        choices[4] &= Imp(not e,    a)

    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()

●実行結果

[m,e,o,s,a,j]
 T T T T T T
 T T T T F T
 T T F T T T
 T T F T F T
 T T F F T T
 F T F T T T
 F T F T F T
 F T F F T T
 F F F T T T
 F F F T T F
 F F F T F T
 F F F F T T
 F F F F T F
∴ 4
Runtime : 0.000 [sec]

P.S.
 条件を満たす場合の真理値表の横に選択肢の真理値表も付けると、次のようになります。
● Logic1a.py

# coding: UTF-8
# Logic1a.py

import itertools
from time import time

# 論理包含「A⇒B」の真理値を得る
def Imp(a,b):
    return not a or b

# 真理値表の1行を文字列で得る
def getRowOfTruthTable(li):
    return ' '.join(['T' if b else 'F' for b in li])

# 確実にいえる選択肢を1つ得る
def getAns(choices):
    if choices.count(True)!=1: print('Error!')
    return ','.join([str(i+1) for i in range(5) if choices[i]])

# Cのように1行で値を代入して比較するため
def let(li,elem):
    li.append(elem)
    return elem

def main():
    tm = time()  # Timer Start
    choices = [True]*5
    TF = (True,False)
    # m:数学; e:英語; o:音楽; s:社会; a:美術; j:国語
    print("[m,e,o,s,a,j] 1 2 3 4 5")
    for m,e,o,s,a,j in itertools.product(TF,repeat=6):
        if not Imp(         m,      e): continue    # 条件A
        if not Imp(         o,s and m): continue    # 条件B
        if not Imp(     not s,      a): continue    # 条件C
        if not Imp(e or not a,      j): continue    # 条件D
        pass # チェックを潜り抜けたものだけを表示
        s1 = getRowOfTruthTable([m,e,o,s,a,j])
        pass # 選択肢のチェック
        c = []
        choices[0] &= let(c, Imp(    m,    s))
        choices[1] &= let(c, Imp(not j,not s))
        choices[2] &= let(c, Imp(not a,    e))
        choices[3] &= let(c, Imp(    o,    j))
        choices[4] &= let(c, Imp(not e,    a))
        s2 = getRowOfTruthTable(c)
        print(' %s  %s'%(s1,s2))

    print(u"∴%s"%getAns(choices))
    print("Runtime : %.3f [sec]"%(time()-tm))   # Timer Stop & Disp

if __name__ == '__main__':
    main()

●実行結果

[m,e,o,s,a,j] 1 2 3 4 5
 T T T T T T  T T T T T
 T T T T F T  T T T T T
 T T F T T T  T T T T T
 T T F T F T  T T T T T
 T T F F T T  F T T T T
 F T F T T T  T T T T T
 F T F T F T  T T T T T
 F T F F T T  T T T T T
 F F F T T T  T T T T T
 F F F T T F  T F T T T
 F F F T F T  T T F T F
 F F F F T T  T T T T T
 F F F F T F  T T T T T
∴4
Runtime : 0.000 [sec]

※参考URL
@IT:連載:プロフェッショナルVB.NETプログラミング 第6回 論理演算と制御構造
論理包含 ‐ 通信用語の基礎知識
知恵袋の判断推理の論理問題をPythonで解いてみた。(2)
知恵袋の判断推理の論理問題をJavaで解いてみた。