我只是想知道如何编写一个函数,可以确定矩阵中任何方向上是否存在任何长度(此时为4)的算术序列,如果它是“#”; s True,函数返回列表中包含4个坐标(y,x)的列表。否则,它什么都不返回。请参阅下面的测试以获得澄清。
在数学中,算术级数(AP)或算术序列是一系列数字,使得连续项之间的差异是恒定的。例如,序列5,7,9,11,13,15 ......是一个算术级数,差异为2。
P.S。对于位置,组件首先以垂直位置开始,然后以水平为0,作为两个组件的初始位置,就像在索引中一样。
这是测试函数的方法。函数下面的名称为as1。
>>> as1([[1, 10, 18, 29, 2],
[2, 7, 5, 6, 34],
[21, 4, 3, 5, 2],
[9, 1, 6, 10, 3],
[16, -9, 9, 17, 4],
[32, -6, 0, 26, 5]])
[[0, 1],[1, 1], [2, 1], [3, 1]]
我的尝试只是成功使用了列表,而不是矩阵:
def as1(l):
list = []
delta = l[1] - l[0]
for index in range(len(l) - 1):
if (l[index + 1] - l[index] == delta):
list.append(index)
return list
我不知道如何为矩阵中的每个值和每个值识别长度为4的算术序列。此外,我不知道如何使函数识别并附加算术序列发生位置的2D位置。
聪明的程序员如何处理这样的问题?
欢迎任何提示。
我建议不要使用numpy,因为我在shell中安装它时遇到问题。
答案 0 :(得分:0)
这是使用动态编程的解决方案。它遍历矩阵,并为每个元素更新4个可能方向的传入序列的长度。迭代完矩阵之后,它会找到最大序列并回溯以生成结果:
def as1(matrix):
# Each element has 4 slots for incoming directions:
# 0: x - 1
# 1: y - 1, x - 1
# 2: y - 1
# 3: y - 1, x + 1
# Each slot is a pair two numbers: difference to parent and sequence length
cache = [[[[0, 0] for _ in range(4)] for _ in row] for row in matrix]
def update(y_0, x_0, y_1, x_1, slot):
if y_1 < len(matrix) and x_1 < len(matrix[y_1]):
diff = matrix[y_0][x_0] - matrix[y_1][x_1]
prev_diff, prev_len = cache[y_0][x_0][slot]
if prev_diff == diff:
length = prev_len + 1
else:
length = 1
cache[y_1][x_1][slot] = [diff, length]
# Populate working memory
for i in range(len(matrix)):
for j in range(len(matrix[i])):
update(i, j, i, j + 1, 0)
update(i, j, i + 1, j + 1, 1)
update(i, j, i + 1, j, 2)
update(i, j, i + 1, j - 1, 3)
# Find coordinate & slot for maximum sequence
y, x, slot = max(((i, j, s)
for i in range(len(matrix))
for j in range(len(matrix[i]))
for s in range(4)
),
key=lambda x: cache[x[0]][x[1]][x[2]][1])
# Backtrack to generate the result
length = cache[y][x][slot][1]
result = []
if length >= 3:
for _ in range(4):
result.append((y, x))
if slot == 0:
x -= 1
elif slot == 1:
x -= 1
y -= 1
elif slot == 2:
y -= 1
else:
y -= 1
x += 1
return list(reversed(result))
res = as1([[0, 10, 1, 1, 0],
[1, 7, 2, 2, 1],
[4, 4, 3, 5, 2],
[9, 1, 4, 10, 3],
[16, -2, 5, 17, 4],
[25, -5, 6, 26, 5]])
print(res)
输出:
[(2, 1), (3, 1), (4, 1), (5, 1)]
它具有线性运行时间,并且将始终返回最长序列的最后4项。如果你只需要第一个长度为4的序列,那么一旦找到这样的序列就可以改进终止算法。
更新:这是一个版本,只要找到长度为4的序列就会终止:
SLOTS = [
[0, -1],
[-1, -1],
[-1, 0],
[-1, 1]
]
def as2(matrix):
state = [[[[0, 0] for _ in range(4)] for _ in range(len(matrix[0]))] for _ in range(2)]
def update(y, x, d_y, d_x, slot):
if (y + d_y) >= 0 and 0 <= (x + d_x) < len(matrix[0]):
prev_diff, prev_len = state[1+d_y][x+d_x][slot]
diff = matrix[y+d_y][x+d_x] - matrix[y][x]
length = prev_len + 1 if diff == prev_diff else 1
state[1][x][slot] = [diff, length]
for y in range(len(matrix)):
for x in range(len(matrix[0])):
for slot, (d_y, d_x) in enumerate(SLOTS):
update(y, x, d_y, d_x, slot)
if state[1][x][slot][1] == 3:
return [(y + d_y * i, x + d_x * i) for i in range(3, -1, -1)]
state = state[::-1]
return []
当应用于与第一个版本相同的输入时,输出如下:
[(0, 1), (1, 1), (2, 1), (3, 1)]