判断推理のカードの問題をPythonで解いてみた。

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

 カードの表・裏2つの面を、赤、黒、青、黄のいずれかの色で塗ったカードが8枚ある。赤は5面、黒は3面、青、黄はそれぞれ4面ずつである。両面が同じ色のカードは1枚もない。
 いま、8枚のカードを並べたところ、4枚は赤、3枚は黒、1枚は黄色であった。このうち4枚のカードを裏返したところ、赤は2枚、黒は1枚、青は4枚、黄は1枚になった。以上のことから、カードの表・裏2つの面について、正しいものはどれか。

①黄・青のカードは全部で2枚ある。
②赤・青のカードは全部で2枚ある。
③赤・黄のカードは1枚もない。
④黒・黄のカードは全部で2枚ある。
⑤黒のカードの他の面の色は全て異なる。

 ただし、問題文が一部抜けているようなので補っておきました。(^_^;
 赤、黒、青、黄の色をそれぞれ、'r','k','b','y'として、「いま、…」以下の条件に出てくる仮の表・裏の色の並びを文字列F,Bとしました。F,Bの決め方は以下の通りです。(^_^;

 +----+----+----+----+----+
 |    | 赤 | 黒 | 青 | 黄 |
 +----+----+----+----+----+
 | 全 |  5 |  3 |  4 |  4 | → |rrrrr|kkk|bbbb|yyyy| → A = 'rrrrrkkkbbbbyyyy'
 +----+----+----+----+----+
 | 表 |  4 |  3 |  0 |  1 | → |rrrr |kkk|    |y   | → F = 'rrrrkkky'
 +----+----+----+----+----+
 | 裏 |  1 |  0 |  4 |  3 | → |    r|   |bbbb| yyy| → B = 'rbbbbyyy'
 +----+----+----+----+----+

 仮の表を固定して、裏の色を同じものを含む順列で回して、裏返す4枚のカードの位置を組合せで回してみました。(^_^;
 選択肢をチェックするために、表と裏のそれぞれの色のタプルtF,tBからカードの両面2色のリストのリストを作成して、その中で、sTargetが両面の色を表した2文字となるカードの枚数を求める関数countCard(sTarget,tF,tB)を作りました。
 ちなみに、「黒のカードの他の面の色は全て異なる。」ということは、「{黒・赤},{黒・青},{黒・黄}のカードが1枚ずつある」ってことですよね。(^_^;

P.S.
 両面が同色のカードは1枚もない条件「flg = False~if flg: continue」は、any()関数を使うと、次の1行に書き換えることができます。o(^-^)o

        if any([f[i]==b[i] for i in range(N)]): continue

● Cards1.py

# coding: UTF-8
# Cards1.py

from time import time
import itertools

# 表と裏のそれぞれの色のタプルtF,tBからカードの両面2色のリストのリストを作成して、
# その中で、sTargetが両面の色を表した2文字となるカードの枚数を求める
def countCard(sTarget,tF,tB):
    li = [sorted(tF[i]+tB[i]) for i in range(len(tF))]
    return li.count(sorted(sTarget))

def main():
    tm = time()  # Timer Start
    ch = [False]*5
    F = 'rrrrkkky'  # 仮の表
    B = 'rbbbbyyy'
    N = len(F)
    cnt = 0
    f = tuple(F)
    print('[%2d] %s'%(0,list(f)))   # 仮の表も参考までに表示
    for b in set(itertools.permutations(B)):  # 同じものを含む順列
        flg = False
        for i in range(N):
            if f[i]==b[i]: flg = True
            if flg: break
        if flg: continue    # 両面が同色のカードは1枚もない条件
        for c in itertools.combinations(range(N),4):
            s = ''    # 4枚のカードを裏返したときの色の状態
            for i in range(N):
                if i in c: s+=b[i]
                else:      s+=f[i]
            if sorted(s)!=sorted('rrkbbbby'): continue
            # チェックを潜り抜けたものだけを表示
            cnt+=1
            print('[%2d] %s'%(cnt,b))
            # 選択肢のチェック
            if cnt==1: ch = [True]*5
            ch[0] &= (countCard('yb',f,b)==2)
            ch[1] &= (countCard('rb',f,b)==2)
            ch[2] &= (countCard('ry',f,b)==0)
            ch[3] &= (countCard('ky',f,b)==2)
            pr = countCard('kb',f,b)*countCard('kr',f,b)*countCard('ky',f,b)
            ch[4] &= (pr==1)

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

●実行結果

[ 0] ['r', 'r', 'r', 'r', 'k', 'k', 'k', 'y']
[ 1] ('y', 'b', 'b', 'y', 'b', 'b', 'y', 'r')
[ 2] ('b', 'y', 'y', 'b', 'b', 'b', 'y', 'r')
[ 3] ('y', 'y', 'b', 'b', 'b', 'b', 'y', 'r')
[ 4] ('y', 'b', 'y', 'b', 'y', 'b', 'b', 'r')
[ 5] ('b', 'y', 'y', 'b', 'b', 'y', 'b', 'r')
[ 6] ('b', 'y', 'b', 'y', 'y', 'b', 'b', 'r')
[ 7] ('b', 'b', 'y', 'y', 'y', 'b', 'b', 'r')
[ 8] ('y', 'b', 'y', 'b', 'b', 'b', 'y', 'r')
[ 9] ('b', 'y', 'b', 'y', 'b', 'b', 'y', 'r')
[10] ('b', 'y', 'b', 'y', 'b', 'y', 'b', 'r')
[11] ('y', 'b', 'b', 'y', 'b', 'y', 'b', 'r')
[12] ('y', 'y', 'b', 'b', 'b', 'y', 'b', 'r')
[13] ('y', 'b', 'y', 'b', 'b', 'y', 'b', 'r')
[14] ('y', 'y', 'b', 'b', 'y', 'b', 'b', 'r')
[15] ('y', 'b', 'b', 'y', 'y', 'b', 'b', 'r')
[16] ('b', 'y', 'y', 'b', 'y', 'b', 'b', 'r')
[17] ('b', 'b', 'y', 'y', 'b', 'b', 'y', 'r')
[18] ('b', 'b', 'y', 'y', 'b', 'y', 'b', 'r')
∴ 2
Runtime : 0.078 [sec]

※参考URL
判断推理のカードの問題をJavaで解いてみた。

判断推理がみるみるわかる! 解法の玉手箱 改訂第2版 (公務員試験)

判断推理がみるみるわかる! 解法の玉手箱 改訂第2版 (公務員試験)

  • 発売日: 2016/08/26
  • メディア: 単行本(ソフトカバー)
公務員試験 判断推理必殺の解法パターン

公務員試験 判断推理必殺の解法パターン