標籤: python 矩陣 算法python
[TOC]git
這幾天在處理一個棋盤狀態數據,須要對棋盤狀態狀態是否爲「同一個狀態」,這裏就須要對棋盤狀態進行旋轉,左右翻轉等操做。一個棋盤總共能夠旋轉:0度,90度,180度,270度4種;每種旋轉後還能夠左右翻轉2種,總共有4x2=8種狀態。爲了方便,須要先用python把這8種狀態表示出來,因而引出了題目的問題:在python裏如何對矩陣進行變化,這裏的變化指旋轉和左右翻轉等。 這裏使用的版本是python3.6算法
爲了簡便,使用一個最簡單的數據來模擬:一個2X2的棋盤用List來保存下數據code
lstDat = [ [1,2], [3,4], ]
指望的最終結果有8個,分別是這樣的: 其中1,3,5,7 分別是旋轉0度,90度,180度,270度; 二、四、六、8 分鐘是一、三、五、7進行左右翻轉獲得的結果。orm
NO.1 1 2 3 4 No.2: 2 1 4 3 No.3: 2 4 1 3 No.4 4 2 3 1 No.5 4 3 2 1 No.6 3 4 1 2 No.7 1 3 2 4 N0.8 3 1 4 2
對於矩陣的處理有不少,但在這裏只須要用到兩種:ip
因此最終問題轉變爲如何實現對List表示的二維矩陣進行上述的兩種操做。get
列表生成式就是使用如下的方式來遍歷生成一個新的表列: [ 變量表達式 for 變量 in 表達式 ] 固然是循環是能夠嵌套的。源碼
#--------------------------------------- ## 使用列表生成式 def listGen (lstDat): #transpose print('-'* 30) print ('轉置矩陣:') tp = [[row[i] for row in lstDat ] for i in range(len(lstDat[0]))] for item in tp: print (item) print('-'* 30) #逆時針轉90度 print ('逆時針轉90度:') rt90 = [[row[i] for row in lstDat ] for i in range(len(lstDat[0])-1,-1,-1) ] for item in rt90: print (item) print('-'* 30) #順時針轉90度 print ('順時針轉90度:') rt90 = [[lstDat[j][i] for j in range(len(lstDat)-1,-1,-1) ] for i in range(len(lstDat[0]))] for item in rt90: print (item) print('-'* 30) print ('左右翻轉:') flip = [[row[i] for i in range(len(row)-1,-1,-1) ] for row in lstDat] for item in flip: print (item)
運行結果:it
---------- python36 ---------- 原始數據: [1, 2] [3, 4] 使用列表生成器: ------------------------------ 轉置矩陣: [1, 3] [2, 4] ------------------------------ 逆時針轉90度: [2, 4] [1, 3] ------------------------------ 順時針轉90度: [3, 1] [4, 2] ------------------------------ 左右翻轉: [2, 1] [4, 3] 輸出完成 (耗時: 0 秒)
使用map能夠方便對矩陣進行轉置,也就是把(行,列)變成 (列,行)的方式。對於旋轉是有直接的方法的,可是左右翻轉沒有,因此須要先逆時針旋轉90度,再進行轉置。ast
def mapzip (lstDat): print('-'* 30) print ('轉置矩陣:') matrix = lstDat.copy() matrix[:] = map(list,zip(*matrix)) for item in matrix: print (item) #順時針轉90度 print ('順時針轉90度:') matrix = lstDat.copy() matrix[:] = map(list,zip(*matrix[::-1])) for item in matrix: print (item) #逆時針轉90度 print ('逆時針轉90度:') matrix = lstDat.copy() matrix[:] = map(list,zip(*matrix)) matrix[:] = matrix[::-1] for item in matrix: print (item) #左右翻轉 print ('左右翻轉:') matrix = lstDat.copy() matrix[:] = map(list,zip(*matrix)) matrix[:] = matrix[::-1] matrix[:] = map(list,zip(*matrix)) for item in matrix: print (item)
運行結果:
---------- python36 ---------- 原始數據: [1, 2] [3, 4] ============================== 使用Map+Zip: ------------------------------ 轉置矩陣: [1, 3] [2, 4] 順時針轉90度: [3, 1] [4, 2] 逆時針轉90度: [2, 4] [1, 3] 左右翻轉: [2, 1] [4, 3] 輸出完成 (耗時: 0 秒)
最後一種方法就是直接用現成的庫了,numpy提供了豐富的方法,這裏只須要用到兩個就夠了。與map的方式相同,對於旋轉是有直接的方法的,可是左右翻轉沒有,因此也須要先逆時針旋轉90度,再進行轉置。
import numpy ## 使用numpy def usenumpy (lstDat): nd = numpy.array(lstDat) #逆時針轉90度: print ('逆時針轉90度:') nd1 = numpy.rot90(nd) print (nd1) print ('順時針轉90度:') nd1 = numpy.rot90(nd,k = -1) print (nd1) print ('左右翻轉:') nd1 = numpy.rot90(nd) nd1 = numpy.transpose(nd1) print (nd1)
運行結果
---------- python36 ---------- 原始數據: [1, 2] [3, 4] ============================== 使用numpy: 逆時針轉90度: [[2 4] [1 3]] 順時針轉90度: [[3 1] [4 2]] 左右翻轉: [[2 1] [4 3]] 輸出完成 (耗時: 0 秒)
研究了那麼多種旋轉,左右翻轉的方式,最終仍是爲了獲得8種狀態,這裏就用numpy方式來調用實現。
import numpy ## 輸出全部狀態 def getstatus (lstDat): nd = numpy.array(lstDat) index = 0 for i in range (4) : index +=1 print('-'* 10 + str(index) + '-' * 10) print (nd) # #print (','.join([str(y) for x in nd.tolist() for y in x])) index +=1 print('-'* 10 + str(index) + '-' * 10) nd2 = numpy.rot90(nd) #,k = -1,axes=(1, 0)) nd2 = numpy.transpose(nd2) print (nd2) #print (','.join([str(y) for x in nd2.tolist() for y in x])) nd = numpy.rot90(nd)
運行結果:
---------- python36 ---------- 原始數據: [1, 2] [3, 4] ============================== 輸出全部狀態: ----------1---------- [[1 2] [3 4]] ----------2---------- [[2 1] [4 3]] ----------3---------- [[2 4] [1 3]] ----------4---------- [[4 2] [3 1]] ----------5---------- [[4 3] [2 1]] ----------6---------- [[3 4] [1 2]] ----------7---------- [[3 1] [4 2]] ----------8---------- [[1 3] [2 4]] 輸出完成 (耗時: 0 秒)
三種思路的對比: 1.列表生成器。感受這個比較傳統,仍是老思路,一個個去循環。做爲練手能夠用用。 2. 使用map 具備py的新思惟,語句也比較簡潔,建議要熟悉這種方式。 3. 使用numpy。 若是是大規模的數據,涉及到大量計算,好比ML,DL之類,仍是直接用庫吧。
最後附上完整的代碼: 完整源碼