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

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

 次のことがわかっているとき、論理的に正しく言えるのはどれか。
・A:野球が好きでない者はゴルフが好きである。
・B:サッカーが好きでかつ野球が好きな者はゴルフが好きである。

1.野球が好きでない者はサッカーが好きではない。
2.サッカーが好きな者はゴルフが好きである。
3.サッカーが好きでない者は野球が好きである。
4.ゴルフが好きな者は野球が好きではない。
5.ゴルフが好きでない者はサッカーが好きである。

 ただし、わかっている条件にA,Bと名前を付けました。(^_^;
 ちなみに、自力で解くとすれば、1番目の参考URLのようなキャロル表で考えるか、次のように真理値表を使います。でも、真理値表は時間がかかり過ぎかな。(^_^;
 「野球が好きである」をb、「ゴルフが好きである」をg、「サッカーが好きである」をsとすると、
一般に、「P⇒Q」≡「¬P∨Q」だから、
条件 A:「 ¬(¬b)∨g 」≡「 b∨g 」
条件 B:「 ¬(s∧b)∨g 」≡「 ¬s∨¬b∨g 」≡「 ¬b∨g∨¬s 」
選択肢1:「 ¬(¬b)∨¬s 」≡「 b∨¬s 」
選択肢2:「 ¬s∨g 」≡「 g∨¬s 」
選択肢3:「 ¬(¬s)∨b 」≡「 s∨b 」≡「 b∨s 」
選択肢4:「 ¬g∨¬b 」≡「 ¬b∨¬g 」
選択肢5:「 ¬(¬g)∨s 」≡「 g∨s 」

              cond.A     cond.B       cho.1    cho.2    cho.3    cho.4    cho.5
+---+---+---++-------+-------------++--------+--------+-------+---------+-------+
| b | g | s || b V g | ~b V g V ~s || b V ~s | g V ~s | b V s | ~b V ~g | g V s |
+---+---+---++-------+-------------++--------+--------+-------+---------+-------+
| T | T | T ||   T   |      T      ||    T   |    T   |   T   |    F    |   T   |
+---+---+---++-------+-------------++--------+--------+-------+---------+-------+
| T | T | F ||   T   |      T      ||    T   |    T   |   T   |    F    |   T   |
+---+---+---++-------+-------------++--------+--------+-------+---------+-------+
| T | F | T ||   T   |      F      ||    -   |    -   |   -   |    -    |   -   |
+---+---+---++-------+-------------++--------+--------+-------+---------+-------+
| T | F | F ||   T   |      T      ||    T   |    T   |   T   |    T    |   F   |
+---+---+---++-------+-------------++--------+--------+-------+---------+-------+
| F | T | T ||   T   |      T      ||    F   |    T   |   T   |    T    |   T   |
+---+---+---++-------+-------------++--------+--------+-------+---------+-------+
| F | T | F ||   T   |      T      ||    T   |    T   |   F   |    T    |   T   |
+---+---+---++-------+-------------++--------+--------+-------+---------+-------+
| F | F | T ||   F   |      T      ||    -   |    -   |   -   |    -    |   -   |
+---+---+---++-------+-------------++--------+--------+-------+---------+-------+
| F | F | F ||   F   |      T      ||    -   |    -   |   -   |    -    |   -   |
+---+---+---++-------+-------------++--------+--------+-------+---------+-------+
                                         x        o       x        x        x

 今回は、真理値表を書いたので、検算のため、条件を満たす場合の真理値表の横に選択肢の真理値表も付けてみました。

● Logic2.py

# coding: UTF-8
# Logic2.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("[b,g,s] 1 2 3 4 5")  # b:野球; g:ゴルフ; s:サッカー
    choices = [True]*5
    for b,g,s in itertools.product([True,False],repeat=3):
        if not Imp(  not b,g): continue     # 条件A
        if not Imp(s and b,g): continue     # 条件B
        # チェックを潜り抜けたものだけを表示
        t = getRowOfTruthTable([b,g,s])
        # 選択肢のチェック
        c1 = Imp(not b,not s); choices[0] &= c1
        c2 = Imp(    s,    g); choices[1] &= c2
        c3 = Imp(not s,    b); choices[2] &= c3
        c4 = Imp(    g,not b); choices[3] &= c4
        c5 = Imp(not g,    s); choices[4] &= c5
        print("%s %s"%(t,getRowOfTruthTable([c1,c2,c3,c4,c5])))

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

●実行結果

[b,g,s] 1 2 3 4 5
 T T T  T T T F T
 T T F  T T T F T
 T F F  T T T T F
 F T T  F T T T T
 F T F  T T F T T
∴ 2
Runtime : 0.000 [sec]

※参考URL
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1285925947
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1294266062
http://okwave.jp/qa/q8095915.html
論理包含 ‐ 通信用語の基礎知識
知恵袋の判断推理の論理問題をPythonで解いてみた。

P.S.
 ちなみに、真理値表による解法をPythonでそのまま再現すると次のようになります。(^_^;
● Logic2a.py

# coding: UTF-8
# Logic2a.py

import itertools
from time import time

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

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

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

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

def main():
    tm = time() # Timer Start
    choices = [True]*5
    TF = (True,False)
    SW = TF[0]  # 0: 全表示; 1:部分表示
    S0 = ' '.join(['-']*5)  # 空欄
    print("[b,g,s](A B) 1 2 3 4 5")  # b:野球; g:ゴルフ; s:サッカー
    for b,g,s in itertools.product(TF,repeat=3):
        A = Imp(  not b,g)  # 条件A
        B = Imp(s and b,g)  # 条件B
        s1 = getRowOfTruthTable([b,g,s])
        s2 = getRowOfTruthTable([A,B])
        if not all([A,B]):
            if SW: print(' %s  %s  %s'%(s1,s2,S0))
            continue
        pass # チェックを潜り抜けたものを表示
        pass # 選択肢のチェック
        c = []
        choices[0] &= let(c, Imp(not b,not s))
        choices[1] &= let(c, Imp(    s,    g))
        choices[2] &= let(c, Imp(not s,    b))
        choices[3] &= let(c, Imp(    g,not b))
        choices[4] &= let(c, Imp(not g,    s))
        s3 = getRowOfTruthTable(c)
        print(' %s  %s  %s'%(s1,s2,s3))

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

if __name__ == '__main__':
    main()

●実行結果

[b,g,s](A B) 1 2 3 4 5
 T T T  T T  T T T F T
 T T F  T T  T T T F T
 T F T  T F  - - - - -
 T F F  T T  T T T T F
 F T T  T T  F T T T T
 F T F  T T  T T F T T
 F F T  F T  - - - - -
 F F F  F T  - - - - -
∴2
Runtime : 0.001 [sec]