計算ブロックの問題をPythonで解いてみた。(2)

 ネットで見つけた計算ブロックの問題Pythonで解いてみました。(^_^;
 ルールの概要は次の通りです。前回は和でしたが、今回は積と商を使います。

①1〜9までの数字…(ry
②太線で囲まれたブロック内のマスが2つのとき、ブロック内に書かれた数字はマスに入る数字の積または商を表す。
③太線で囲まれたブロック内のマスが3つ以上のとき、ブロック内に書かれた数字はマスに入る数字の積を表す。

     0   1   2   3   4   5   6   7   8
   +---+---+---+---+---+---+---+---+---+
 0 |72         |50 |28 |54     |2  |24 |
   +---+---+---+   +   +---+   +   +   +
 1 |294    |       |   |72 |   |   |   |
   +---+   +---+---+---+   +---+---+   +
 2 |576|   |42 |15     |   |4      |   |
   +   +---+   +---+---+---+---+---+   +
 3 |       |   |24     |10         |   |
   +---+---+---+---+---+---+---+---+---+
 4 |24 |2  |432        |12     |35     |
   +   +   +---+---+---+---+---+---+---+
 5 |   |       |252        |30 |432    |
   +   +---+---+---+---+---+   +   +---+
 6 |   |48         |3  |35 |   |   |63 |
   +---+---+---+---+   +   +---+---+   +
 7 |120        |       |   |4      |   |
   +---+---+---+---+---+---+---+---+---+
 8 |20     |3      |3      |56         |
   +---+---+---+---+---+---+---+---+---+

 ただし、外側の数字は、プログラム用の配列のインデックスです。
 今回は、さすがに「Perm = [list(itertools.permutations(R))]*8」で回すのは大変なので、各ループを必要条件で絞り込んでみました。例えば、上の[0][3]の位置に入る数は、50の約数である必要があります。
 よって、これを用いて、プログラム中の「if 50%p[3]!=0: continue」のようにして、Perm[0]の候補を絞り込みました。
 ちなみに、このブロックは、縦横違う数字という条件より、m[0][3]=5,m[1][3]=2,m[1][2]=5と決定するのですが、そこまでは使いませんでした。(^_^;
 この他にも、3つのマスからなるL型および逆L型のもので、ブロック内に書かれた数字が2,3,294,576などのものも決定することができます。こういうのも使うと、もう少し速くなります。(^_^;

● CalcBlocks2.py

# coding: UTF-8
# CalcBlocks2.py

from time import time
import itertools

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

# 列がダブっていないか調べる
def isDuplicated(n,li2D):
    m = len(li2D)
    for i in range(m):
        li = [li2D[j][i] for j in range(n)]
        if len(set(li))!=n: return True
    return False

def chk2Cells(a,b,c):
    if a*b==c: return True
    l,s = max(a,b),min(a,b)
    return l%s==0 and l//s==c

def main():
    tm = time()  # Timer Start
    m = [[0]*9]*9
    R = range(1,10)
##    Perm = [list(itertools.permutations(R))]*8
    Perm = [[],[],[],[],[],[],[],[]]
    for p in itertools.permutations(R):     # Perm[0]
        if p[0]*p[1]*p[2]!= 72: continue
        if  50%p[3]!=0: continue
        if  28%p[4]!=0: continue
        if  54%(p[5]*p[6])!=0: continue
        if  24%p[8]!=0: continue
        Perm[0].append(p)

    for p in itertools.permutations(R):     # Perm[1]
        if 294%(p[0]*p[1])!=0: continue
        if  50%(p[2]*p[3])!=0: continue
        if  28%p[4]!=0: continue
        if  72%p[5]!=0: continue
        if  54%p[6]!=0: continue
        if  24%p[8]!=0: continue
        Perm[1].append(p)

    for p in itertools.permutations(R):     # Perm[2]
        if 576%p[0]!=0: continue
        if 294%p[1]!=0: continue
        if  42%p[2]!=0: continue
        if p[3]*p[4]!=15: continue
        if  72%p[5]!=0: continue
        if  24%p[8]!=0: continue
        Perm[2].append(p)

    for p in itertools.permutations(R):     # Perm[3]
        if 576%(p[0]*p[1])!=0: continue
        if  42%p[2]!=0: continue
        if p[3]*p[4]!=24: continue
        if p[5]*p[6]*p[7]!=10: continue
        if  24%p[8]!=0: continue
        Perm[3].append(p)

    for p in itertools.permutations(R):     # Perm[4]
        if  24%p[0]!=0: continue
        if   2%p[1]!=0: continue
        if p[2]*p[3]*p[4]!=432: continue
        if p[5]*p[6]!=12: continue
        if p[7]*p[8]!=35: continue
        Perm[4].append(p)

    for p in itertools.permutations(R):     # Perm[5]
        if  24%p[0]!=0: continue
        if   2%(p[1]*p[2])!=0: continue
        if p[3]*p[4]*p[5]!=252: continue
        if  30%p[6]!=0: continue
        if 432%(p[7]*p[8])!=0: continue
        Perm[5].append(p)

    for p in itertools.permutations(R):     # Perm[6]
        if  24%p[0]!=0: continue
        if p[1]*p[2]*p[3]!=48: continue
        if   3%p[4]!=0: continue
        if  35%p[5]!=0: continue
        if  30%p[6]!=0: continue
        if 432%p[7]!=0: continue
        if  63%p[8]!=0: continue
        Perm[6].append(p)

    for p in itertools.permutations(R):     # Perm[7]
        if p[0]*p[1]*p[2]!=120: continue
        if   3%(p[3]*p[4])!=0: continue
        if  35%p[5]!=0: continue
        if  63%p[8]!=0: continue
        Perm[7].append(p)
##    for n in range(8): print(len(Perm[n]))
##    exit()
    for m[0] in Perm[0]:
##        if m[0][0]*m[0][1]*m[0][2]!= 72: continue
        for m[1] in Perm[1]:
            if m[0][3]*m[1][2]*m[1][3]!= 50: continue
            if m[0][4]*m[1][4]!= 28: continue
            if m[0][5]*m[0][6]*m[1][6]!= 54: continue
            if not chk2Cells(m[0][7],m[1][7],2): continue
            if isDuplicated(2,m): continue
            for m[2] in Perm[2]:
                if m[1][0]*m[1][1]*m[2][1]!=294: continue
##                if m[2][3]*m[2][4]!= 15: continue
                if m[1][5]*m[2][5]!= 72: continue
                if not chk2Cells(m[2][6],m[2][7],4): continue
                if isDuplicated(3,m): continue
                for m[3] in Perm[3]:
                    if m[2][0]*m[3][0]*m[3][1]!=576: continue
                    if m[2][2]*m[3][2]!= 42: continue
##                    if m[3][3]*m[3][4]!= 24: continue
##                    if m[3][5]*m[3][6]*m[3][7]!= 10: continue
                    if m[0][8]*m[1][8]*m[2][8]*m[3][8]!= 24: continue
                    if isDuplicated(4,m): continue
                    for m[4] in Perm[4]:
##                        if m[4][2]*m[4][3]*m[4][4]!=432: continue
##                        if m[4][5]*m[4][6]!= 12: continue
##                        if m[4][7]*m[4][8]!= 35: continue
                        if isDuplicated(5,m): continue
                        for m[5] in Perm[5]:
                            if m[4][1]*m[5][1]*m[5][2]!=  2: continue
##                            if m[5][3]*m[5][4]*m[5][5]!=252: continue
                            if isDuplicated(6,m): continue
                            for m[6] in Perm[6]:
                                if m[4][0]*m[5][0]*m[6][0]!= 24: continue
##                                if m[6][1]*m[6][2]*m[6][3]!= 48: continue
                                if m[5][6]*m[6][6]!= 30: continue
                                if m[5][7]*m[5][8]*m[6][7]!=432: continue
                                if isDuplicated(7,m): continue
                                for m[7] in Perm[7]:
##                                    if m[7][0]*m[7][1]*m[7][2]!=120: continue
                                    if m[6][4]*m[7][3]*m[7][4]!=  3: continue
                                    if m[6][5]*m[7][5]!= 35: continue
                                    if m[6][8]*m[7][8]!= 63: continue
                                    if not chk2Cells(m[7][6],m[7][7],4): continue
                                    if isDuplicated(8,m): continue
                                    for i in range(9):
                                        li = [m[j][i] for j in range(8)]
                                        m[8][i] = 45-sum(li)
                                    if m[8][0]*m[8][1]!= 20: continue
                                    if m[8][6]*m[8][7]*m[8][8]!= 56: continue
                                    if not chk2Cells(m[8][2],m[8][3],3): continue
                                    if not chk2Cells(m[8][4],m[8][5],3): continue
                                    # チェックを潜り抜けたものだけを表示
                                    for n in range(9):
                                        print(toStr(m[n]))

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

if __name__ == '__main__':
    main()

●実行結果

[1,9,8,5,7,2,3,6,4]
[7,6,5,2,4,8,9,3,1]
[8,7,6,3,5,9,1,4,2]
[9,8,7,4,6,1,2,5,3]
[2,1,9,6,8,3,4,7,5]
[3,2,1,7,9,4,5,8,6]
[4,3,2,8,1,5,6,9,7]
[6,5,4,1,3,7,8,2,9]
[5,4,3,9,2,6,7,1,8]
Runtime : 2.125 [sec]

※参考URL
判断推理のダンスのペアの問題をPythonで解いてみた。
計算ブロックの問題をPythonで解いてみた。









賢くなるパズル かけ算 上級 (宮本算数教室の教材)

賢くなるパズル かけ算 上級 (宮本算数教室の教材)