Given an n by n matrix M, at row i and column j, I\'d like to iterate over all the neighboring values in a c
One way for yielding points with increasing distance is to break it down into easy parts, and then merge the results of the parts together. It's rather obvious that itertools.merge should do the merging. The easy parts are columns, because for fixed x the points (x, y) can be ordered by looking at the value of y only.
Below is a (simplistic) implementation of that algorithm. Note that the squared Euclidian distance is used, and that the center point is included. Most importantly, only points (x, y) with x in range(x_end) are considered, but I think that's OK for your use case (where x_end would be n in your notation above).
from heapq import merge
from itertools import count
def distance_column(x0, x, y0):
dist_x = (x - x0) ** 2
yield dist_x, (x, y0)
for dy in count(1):
dist = dist_x + dy ** 2
yield dist, (x, y0 + dy)
yield dist, (x, y0 - dy)
def circle_around(x0, y0, end_x):
for dist_point in merge(*(distance_column(x0, x, y0) for x in range(end_x))):
yield dist_point
Edit: Test code:
def show(circle):
d = dict((p, i) for i, (dist, p) in enumerate(circle))
max_x = max(p[0] for p in d) + 1
max_y = max(p[1] for p in d) + 1
return "\n".join(" ".join("%3d" % d[x, y] if (x, y) in d else " " for x in range(max_x + 1)) for y in range(max_y + 1))
import itertools
print(show(itertools.islice(circle_around(5, 5, 11), 101)))
Result of test (points are numbered in the order they are yielded by circle_around):
92 84 75 86 94
98 73 64 52 47 54 66 77 100
71 58 40 32 27 34 42 60 79
90 62 38 22 16 11 18 24 44 68 96
82 50 30 14 6 3 8 20 36 56 88
69 45 25 9 1 0 4 12 28 48 80
81 49 29 13 5 2 7 19 35 55 87
89 61 37 21 15 10 17 23 43 67 95
70 57 39 31 26 33 41 59 78
97 72 63 51 46 53 65 76 99
91 83 74 85 93
Edit 2: If you really do need negative values of i, replace range(end_x) with range(-end_x, end_x) in the cirlce_around function.