哪个是最佳且更清洁的解决方案?

时间:2019-07-16 05:52:20

标签: python matrix chess

我和我的同事对矩阵步骤有两种不同的处理方法。我们有一个矩阵:

mylist=[
 [0,0,1,1],
 [0,0,1,0],
 [0,1,0,1],
 [0,0,1,1],
]

练习是,如果具有'1'的索引在其自身的其他'1'之后拥有,则代码应返回true。它可以是水平,垂直,对角线_向左,对角线_向右。那是我的方法:

horizonatal= False
vertical = False
diagonal_right_to_left = False
diagonal_left_to_right = False

mylist=[
 [0,0,1,1],
 [0,0,1,0],
 [0,1,0,1],
 [0,0,1,1],
]


for row in range(len(mylist)):
    for index in range(len(mylist[row])):
        if mylist[row][index]==1:
            #here we find horizaontal line
            if index < len(mylist[row])-1:
                if mylist[row][index+1]==1:
                    horizonatal=True
            #here we find vertical
            if row < len(mylist)-1:
                if mylist[row+1][index]==1:
                    vertical=True
            #here we find diagonal_right_to_left
            if index < len(mylist[row])-1 and row < len(mylist)-1:
                if mylist[row+1][index+1]==1:
                    diagonal_left_to_right=True
            #here we find diagonal_left_to_right
            if index!=0 and row < len(mylist)-1:
                if  mylist[row+1][index-1]==1:
                    diagonal_left_to_right==True


print('Horizontal: ', horizonatal)
print('Vertical: ', vertical)
print('diagonal_left_to_right: ', diagonal_left_to_right)
print('diagonal_left_to_right: ', diagonal_left_to_right)

这是我的同事方法:

def calc_columns(matrix, index, len_row):
  current_row_arr = []
  for inner_index in range(len_row):
   current_row_arr.append(matrix[inner_index][index])
  current_row = sum(current_row_arr)
  return current_row

def find_repeated(matrix):
  row_hits = []
  col_hits = []
  diagonal_left_hits = []
  diagonal_right_hits = []

  for index, data in enumerate(matrix):
    len_row = len(data)
    col_hits.append(calc_columns(matrix,index, len_row))
    row_hits.append(sum(data))
    diagonal_right_hits.append(matrix[index][index])
    diagonal_left_hits.append(matrix[index][(len_row-1) - index])

  diagonal_left_hits = sum(diagonal_left_hits)
  diagonal_right_hits = sum(diagonal_right_hits)
  print_result(row_hits,'Row Contact Found')
  print_result(diagonal_left_hits,'Diagonal Left Contact Found')
  print_result(diagonal_right_hits,'Diagonal Right Contact Found')
  print_result(col_hits,'Column Contact Found')

def print_result(array, message):
  if isinstance(array,list):
    for value in array:
      if value > 1:
        print(message)
  else:
    if array > 1:
      print(message)

# test here
matrix = [[1,0,0,0],
          [0,0,0,0],
          [0,1,0,0],
          [0,1,0,1]]

    find_repeated(matrix)

与精度无关,它与速度和最佳方法有关。我们正在等待您的回复。

2 个答案:

答案 0 :(得分:0)

使用.count()方法

序列类型(列表,元组,str,范围)具有.count(arg)方法,该方法对列表中arg出现的次数进行计数。

for row in mylist是一种遍历行的更Python方式。如果该行具有两个或多个'1',则row.count(1) > 1为true。因此,any(row.count(1) > 1 for row in mylist)为真,如果任何行具有两个或多个'1'。

for col in zip(*mylist)遍历各列。

for i,row in enumerate(mylist)产生一个元组序列:(0, mylist[0]), (1,mylist[1]), (2, mylist[2]), (3,mylist[3])。因此[row[i] for i,row in enumerate(mylist)]创建右对角线:[mylist[0][0], mylist[1][1], mylist[2][2], mylist[3][3]]。左对角线相似,但是-1-i从列表末尾开始索引。

mylist=[
 [0,0,1,1],
 [0,0,1,0],
 [0,1,0,1],
 [0,0,1,1],
]

horizontal = any(row.count(1) > 1 for row in mylist)
vertical = any(col.count(1) > 1 for col in zip(*mylist))
diagonal_right = [row[i] for i,row in enumerate(mylist)].count(1) > 1
diagonal_left = [row[-1-i] for i,row in enumerate(mylist)].count(1) > 1

print(horizontal, vertical, diagonal_right, diagonal_left)

答案 1 :(得分:0)

如果您的目标是速度,那么请尽可能避免循环。

以下是纯numpy / scipy解决方案,它返回mylist中的索引,您所声明的条件成立。我希望代码中的注释和代码本身足以作为解释:

from scipy.ndimage import convolve
import numpy as np

mylist=[
 [0,0,1,1],
 [0,0,1,0],
 [0,1,0,1],
 [0,0,1,1],
]

arr = np.array(mylist)

# for horizontal and vertical we multiply the array with a shifted version of itself.
# anywhere where there is a one left there have been two neighboring ones in the original
# array. argwhere returns the indices where this is the case
horizontal = np.argwhere(arr*np.hstack((arr[:,1:],np.zeros([4,1],dtype=int))))
vertical = np.argwhere(arr*np.vstack((arr[1:,:],np.zeros([1,4],dtype=int))))

# for diagonal values we apply a convolution with appropriate kernels. anywhere where
# the result of the convolution is 2, there are two consecutive ones.

kerdiagr = [[1,0],
            [0,1]]
kerdiagl = [[0,1],
            [1,0]]
diagonalr = np.argwhere(convolve(arr,kerdiagr, mode='constant',cval=0)==2)
diagonall = np.argwhere(convolve(arr,kerdiagl, mode='constant',cval=0)==2)