買い物の推理パズルをPythonで解いてみた。(2)

 ネットで見つけた買い物の推理パズルの問題Pythonで解いてみました。(^_^;
 問題は昔のニコリの例題のようです。今回は、マトリクス(グリッド)表も作成してみました。問題自体は簡単でしたが、マトリクス表を作るのが大変でした。(^_^;
 マトリクス表は、前の推理パズルの拙作プログラムでも使えるようになっています。ラベルが整数のときは、文字化して先頭2文字を取ります。ただし、1文字のときは先頭に空白を補います。
 問題の概要を記号や式で表すと、次の通りです。

 名前:{明,勇,洋,正}
 商品:{傘,靴,紙,糸}
 色 :{青,赤,白,黒}
(イ) {明}={白}≠{糸}
(ロ) {青}={紙}≠{勇}
(ハ) {正}={靴}≠{赤}

 ただし、等号「=」は数学的な意味ではなく、対応関係(リストの要素と見たときにインデックスが等しいこと)を記号的に表しています。
 ちなみに、プログラム中のラベル作成で、「isinstance(…,int)」を使っているのは、同じプログラムで、Python2でも3でも動くようにするためです。Python3では「isinstance(…,str)」、Python2では「isinstance(…,basestring)」を使わなければならないようです。(^_^;

● Shopping2.py

# coding: UTF-8
# Shopping2.py

from time import time
import itertools

def toStr(lst):
    return '(%s)'%'\t'.join(['%s'%x for x in lst])

# ラベルと答えのリスト等からマトリクス表を作成
def mkMatTbl(lbl,ans):
    m,n = len(lbl),len(lbl[0])
    li = [lbl[i] for i in range(1,m)]       # 横軸ラベルの作成
    s = '  '
    for i in range(m-1):
        for j in range(n):
            t = li[i][j]
            if not isinstance(t,int): s+=t
            else: s+=('%2s'%str(t))[:2]
    print(s)
    for h in range(m-1):
        for i in range(n):
            s,t = '',lbl[-h][i]
            if not isinstance(t,int): s+=t  # 縦軸ラベルの作成
            else: s+=('%2s'%str(t))[:2]
            g = ans[-h].index(t)
            for j in range(1,m-h):
                a = ans[j][g]
                for k in range(n):
                    s+=u'O' if lbl[j][k]==a else u'X'
            print(s)

def main():
    tm = time()  # Timer Start
    N = u'明勇洋正'     # 名前(固定)
    G = u'傘靴紙糸'     # 商品
    C = u'青赤白黒'     # 色
    for g in itertools.permutations(G):
        for c in itertools.permutations(C):
            if not N.index(u'明')==c.index(u'白')!=g.index(u'糸'): # 条件(イ)
                continue
            if not c.index(u'青')==g.index(u'紙')!=N.index(u'勇'): # 条件(ロ)
                continue
            if not N.index(u'正')==g.index(u'靴')!=c.index(u'赤'): # 条件(ハ)
                continue
            # チェックを潜り抜けたものだけを表示
            print(toStr(N))
            print(toStr(g))
            print(toStr(c))
            print('')
            mkMatTbl((N,G,C),(N,g,c))

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

if __name__ == '__main__':
    main()

●実行結果

(明     勇      洋      正)
(傘     糸      紙      靴)
(白     赤      青      黒)

  傘靴紙糸青赤白黒
明OXXXXXOX
勇XXXOXOXX
洋XXOXOXXX
正XOXXXXXO
青XXOX
赤XXXO
白OXXX
黒XOXX
Runtime : 0.002 [sec]

※参考URL
https://stackoverflow.com/questions/4843173/how-to-check-if-type-of-a-variable-is-string
買い物の推理パズルをPythonで解いてみた。
去年と今年の身長の推理パズルをPythonで解いてみた。
花火大会の推理パズルをPythonで解いてみた。
タワーの推理パズルをPythonで解いてみた。
昼食の推理パズルをPythonで解いてみた。
願い事の推理パズルをPythonで解いてみた。
Zebra PuzzleをPythonで解いてみた。(2)