2017-09-15 29 views
1

Detect duplicate in each 3*3 block in a 9*9 matrixPython的檢查3×3矩陣,如在數獨

我的方法:使用numpy.vsplit和hsplit分裂9 * 9成9 3×3塊 和使用.flat功能趨於平緩每個3×3塊,然後使用set()來檢查,如果列表中包含重複

import numpy as np 
def validSolution(board): 


    b=np.array(board) 
    b=np.vsplit(b,3) 
    for n,ar in enumerate(b): 
     b[n]=np.hsplit(ar,3) 

    for ar in b: 
     for arr in ar: 
      print(len(set(arr.flat))==len(arr.flat)) 

validSolution([[5, 3, 4, 6, 7, 8, 9, 1, 2], 
       [6, 7, 2, 1, 9, 5, 3, 4, 8], 
       [1, 9, 8, 3, 4, 2, 5, 6, 7], 
       [8, 5, 9, 7, 6, 1, 4, 2, 3], 
       [4, 2, 6, 8, 5, 3, 7, 9, 1], 
       [7, 1, 3, 9, 2, 4, 8, 5, 6], 
       [9, 6, 1, 5, 3, 7, 2, 8, 4], 
       [2, 8, 7, 4, 1, 9, 6, 3, 5], 
       [3, 4, 5, 2, 8, 6, 1, 7, 9]]) 

正如我在Python和numpy的相當缺乏經驗,我想問一個更有效的方式來完成這項工作。

+0

發佈的解決方案是否適合您? – Divakar

+0

是的,非常感謝 – lilpig

回答

3

設置:比方說,a9x9電網和b3x3子矩陣(小格),您在a尋找。

步驟:形狀(3,3,3,3)a4D,從而每個窗口將是沿着第二和第四軸:解決它將被重塑a4D

  • 一種方式。

  • 我們需要使得第一軸線與從a4D所述第二軸線和所述第二個與來自a4D第四個對準延伸到b3D

  • 執行比較,這將是有效的,禮貌的NumPy廣播,給我們一個4D布爾數組。尋找沿着這兩個模糊的所有匹配,並簡單地獲得匹配的索引。

因此,實施 -

np.argwhere((a.reshape(3,3,3,3) == b[:,None]).all((1,3))) 

採樣運行 -

In [190]: a 
Out[190]: 
array([[5, 3, 4, 6, 7, 8, 9, 1, 2], 
     [6, 7, 2, 1, 9, 5, 3, 4, 8], 
     [1, 9, 8, 3, 4, 2, 5, 6, 7], 
     [8, 5, 9, 7, 6, 1, 4, 2, 3], 
     [4, 2, 6, 8, 5, 3, 7, 9, 1], 
     [7, 1, 3, 9, 2, 4, 8, 5, 6], 
     [9, 6, 1, 5, 3, 7, 2, 8, 4], 
     [2, 8, 7, 4, 1, 9, 6, 3, 5], 
     [3, 4, 5, 2, 8, 6, 1, 7, 9]]) 

In [196]: b = a[-3:,-6:-3] # (2,1) grid 

In [197]: b 
Out[197]: 
array([[5, 3, 7], 
     [4, 1, 9], 
     [2, 8, 6]]) 

In [198]: np.argwhere((a.reshape(3,3,3,3) == b[:,None]).all((1,3))) 
Out[198]: array([[2, 1]]) 

In [199]: b = a[:3:,:3] # (0,0) grid 

In [200]: b 
Out[200]: 
array([[5, 3, 4], 
     [6, 7, 2], 
     [1, 9, 8]]) 

In [201]: np.argwhere((a.reshape(3,3,3,3) == b[:,None]).all((1,3))) 
Out[201]: array([[0, 0]]) 

如果由於某種原因,看起來雜亂無章,你喜歡與built-ins工作,我們可以使用view_as_blocksscikit-image,有形狀不可知的解決方案 -

In [206]: from skimage.util.shape import view_as_blocks 

In [207]: np.argwhere((view_as_blocks(a, b.shape) == b).all((2,3))) 
Out[207]: array([[0, 0]]) 

請注意,這些reshapes都只是views,所以沒有額外的內存空間需要他們。雖然比較會導致創建一個與a相同形狀的布爾數組,但它是一個比int/float數組更輕(在Linux系統上輕8倍)的布爾數組,因此在存儲器效率方面不會太差。