所以我有一个像这样的4x4矩阵
|0 1 2 3
-+-------
0|0 1 3 6
1|2 4 7 a
2|5 8 b d
3|9 c e f
,并且我按其中的十六进制字符指定的顺序遍历它。所以从(0,0)开始,然后从(1,0),(0,1),(2,0),(1,1),(0,2)...
下面是代码:
def diagonal(n):
for a in range(n):
for b in range(a + 1):
yield a - b, b
for a in range(n - 1):
for b in range(n - a - 1):
yield n - b - 1, b + 1 + a
重复给出
for x, y in diagonal(4):
print((x, y))
# (0, 0)
# (1, 0)
# (0, 1)
# (2, 0)
# (1, 1)
# (0, 2)
# (3, 0)
# (2, 1)
# (1, 2)
# (0, 3)
# (3, 1)
# (2, 2)
# (1, 3)
# (3, 2)
# (2, 3)
# (3, 3)
这完全符合我的预期。我所停留的部分试图在我给它赋予索引的位置上创建一个函数,并为其提供坐标。因此,对于我的4x4矩阵,(仍然是十六进制)
0 -> (0, 0)
1 -> (1, 0)
2 -> (0, 1)
3 -> (2, 0)
4 -> (1, 1)
5 -> (0, 2)
6 -> (3, 0)
7 -> (2, 1)
8 -> (1, 2)
9 -> (0, 3)
a -> (3, 1)
b -> (2, 2)
c -> (1, 3)
d -> (3, 2)
e -> (2, 3)
f -> (3, 3)
我打算继续使用可变大小的平方矩阵,所以我不能仅仅将这些值硬编码为字典。
我已经花了好几个小时试图使它起作用,但是我一生都无法使它起作用。
这不是家庭作业,只是我在业余时间正在做的事情,它正在慢慢把我推向高潮。
如果不清楚,请随时询问。
先谢谢了。
编辑: 我想有人会对这篇文章Traverse Matrix in Diagonal strips发表评论,这很相似,但是和我的第一个函数一样,它只迭代坐标,而我无法从索引中得出坐标。
答案 0 :(得分:4)
这是一个似乎可以执行您想要的功能的函数。代码后有解释。
from math import sqrt
def triangular(n):
return n * (n + 1) // 2
def coords_from_index(ndx, n=4):
if ndx < triangular(n):
basecol = (int(sqrt(8 * ndx + 1)) - 1) // 2
row = ndx - triangular(basecol)
col = basecol - row
else:
oldcol, oldrow = coords_from_index(n**2 - 1 - ndx, n)
row = n - 1 - oldrow
col = n - 1 - oldcol
return col, row
# Test code
n = 4
for ndx in range(n**2):
print(hex(ndx)[2:], '->', coords_from_index(ndx, n))
该测试代码的打印输出为:
0 -> (0, 0)
1 -> (1, 0)
2 -> (0, 1)
3 -> (2, 0)
4 -> (1, 1)
5 -> (0, 2)
6 -> (3, 0)
7 -> (2, 1)
8 -> (1, 2)
9 -> (0, 3)
a -> (3, 1)
b -> (2, 2)
c -> (1, 3)
d -> (3, 2)
e -> (2, 3)
f -> (3, 3)
这是我的代码的简要说明。
就像您的代码按顺序生成坐标一样,我将正方形的左上三角形与右下三角形区别对待。首先让我们看一下左上角的三角形,对于大小为4
的正方形,它包括索引0
至9
。
如果查看每列的顶部数字,则会看到它们是“三角数”,即从0
开始的连续整数之和。因此,第一行是0
,0+1
,0+1+2
和0+1+2+3
。这些数字的众所周知的公式是
triangular(n) = n * (n + 1) // 2
所以我为此写了一个小例程。如果您知道三角数(称为ndx
)并想找到n
,则可以使用代数来求解二次方程,然后得到
n = (sqrt(8 * ndx + 1) - 1) // 2
如果将sqrt
替换为int(sqrt(
,则得到相同的三角数结果,并且还获得介于两个三角数之间的任何ndx
的“基数” 。然后,您可以使用索引和“基数”来找到索引的相应列和行。
现在,如果查看右下角的三角形,其中包括索引a
至f
,则可以看到与左上角三角形对称。我选择使用这种对称性来计算任何这些索引的行和列。我本可以更直接地计算它们,但是我使用的方法效果很好。
请注意,如果您使用非常大的n
和ndx
值,由于浮点算法的变数,int(sqrt(
并不总是给出正确的答案。但是在发生这种情况之前,ndx
必须真的大,大约为2**50
。让我知道您是否需要一个更可靠的例程来计算整数平方根。
答案 1 :(得分:3)
这基本上是一个算法问题:)
我建议使用以下算法:
我建议的实现如下:
首先,准备每个对角线中第一个线性索引的数组。
例如在4x4矩阵中,数组将如下所示:[0, 1, 3, 6, 10, 30, 15]
。
通知这些基本上是垃圾箱。这意味着在第i个对角线中找到所有维护a[i] <= index < a[i+1]
的线性索引。
比,当收到索引时:
查找找到所请求索引的对角线。
您可以通过找到满足bin[d] <= index < bin[d]
找到该对角线上的位置。
这是bin [d]与索引之间的距离。这意味着如果 index-bin [d] = k ,则索引位于该对角线上的第k个位置。
推断坐标。
到目前为止,您已经发现索引位于第d个对角线上的第k个位置。
让我们表示矩阵的大小为 MxM 。
如果x <= M-1比对角线(k,d-k)
如果x> M-1比我们在对角线上(d-(m-1)+ k,(m-1)-k)
当我们插入之前找到的k时,我们将找到所需的坐标。
def ind2cor(index):
d = bisect_left(a, index)
if index != a[d]:
d -= 1
k = index - a[d]
if d <= m-1:
return k, d - k
else:
return d - (m - 1) + k, (m - 1) - k
m = 4
a = [0, 3, 6, 10, 13, 15]
for i in range(16):
print('{}: {}'.format(i, ind2cor(i)))
收益:
0: (0, 0)
1: (0, 1)
2: (1, 0)
3: (0, 2)
4: (1, 1)
5: (2, 0)
6: (0, 3)
7: (1, 2)
8: (2, 1)
9: (3, 0)
10: (1, 3)
11: (2, 2)
12: (3, 1)
13: (2, 3)
14: (3, 2)
15: (3, 3)
我还可以提供一种生成对角线索引的方法:
def genereate_diagonal_indices(m):
a = [0]
for i in range(1, m):
a.append(a[-1] + i)
for i in range(m, 1, -1):
a.append(a[-1] + i)
return a
因此您可以在上面的代码中使用a = genereate_diagonal_indices(m)
。