【发布时间】:2012-02-17 05:59:59
【问题描述】:
给定一个n by n 矩阵M,在行i 和列j,我想以圆形螺旋遍历所有相邻值。
这样做的目的是测试某个函数f,它依赖于M,以找到远离(i, j) 的半径,其中f 返回True。所以,f 看起来像这样:
def f(x, y):
"""do stuff with x and y, and return a bool"""
并且会这样调用:
R = numpy.zeros(M.shape, dtype=numpy.int)
# for (i, j) in M
for (radius, (cx, cy)) in circle_around(i, j):
if not f(M[i][j], M[cx][cy]):
R[cx][cy] = radius - 1
break
其中circle_around 是返回(迭代器到)圆形螺旋中的索引的函数。因此,对于M 中的每个点,此代码将计算并存储从f 返回True 的那个点的半径。
如果有更有效的计算 R 的方法,我也愿意接受。
更新:
感谢所有提交答案的人。我编写了一个简短的函数来绘制 circle_around 迭代器的输出,以显示它们的作用。如果您更新答案或发布新答案,则可以使用此代码来验证您的解决方案。
from matplotlib import pyplot as plt
def plot(g, name):
plt.axis([-10, 10, -10, 10])
ax = plt.gca()
ax.yaxis.grid(color='gray')
ax.xaxis.grid(color='gray')
X, Y = [], []
for i in xrange(100):
(r, (x, y)) = g.next()
X.append(x)
Y.append(y)
print "%d: radius %d" % (i, r)
plt.plot(X, Y, 'r-', linewidth=2.0)
plt.title(name)
plt.savefig(name + ".png")
结果如下:
plot(circle_around(0, 0), "F.J"):
plot(circle_around(0, 0, 10), "WolframH"):
我将 Magnesium 的建议编码如下:
def circle_around_magnesium(x, y):
import math
theta = 0
dtheta = math.pi / 32.0
a, b = (0, 1) # are there better params to use here?
spiral = lambda theta : a + b*theta
lastX, lastY = (x, y)
while True:
r = spiral(theta)
X = r * math.cos(theta)
Y = r * math.sin(theta)
if round(X) != lastX or round(Y) != lastY:
lastX, lastY = round(X), round(Y)
yield (r, (lastX, lastY))
theta += dtheta
plot(circle_around(0, 0, 10), "magnesium"):
如您所见,满足我正在寻找的接口的结果都没有产生一个圆形螺旋,该螺旋覆盖了 0、0 附近的所有索引。FJ 是最接近的,尽管 WolframH 的命中点是正确的,只是不是按螺旋顺序。
【问题讨论】:
-
您能否确认您的数组非常大,或者您必须多次这样做,或者真值函数很昂贵或者......?我可以想出一些东西,但这似乎是过早的优化,除非你真的需要避免在半径之外进行测试。当然,简单的解决方案是找到数组中每个假点的半径,然后找到最小的半径。如果你真的需要它的话,这是一个很好的问题。
-
@yakiimo,数组有 1-2 百万个条目。
-
F.J 的答案对你有用还是你需要一个真正的圈子?
-
我更喜欢真正的圆圈。
-
仅供参考,我的待办事项清单上还有这个,但现在很长。
标签: python matrix loops geometry spiral