Reputation: 7961
I have a N
by N
grid. I have a certain grid cell labeled with 0
:
I intend to loop over grid cells, starting with 0
cell, in this order:
0
1
2
How can I compose the loop?
I tried to follow this post. But I cannot adapt it to suit my situation.
Upvotes: 1
Views: 398
Reputation: 36682
You can fill the entire grid using a Breadth First Search: Starting with the cell with value zero, it will expand in concentric waves, adding one to each subsequent layer further away from the center.
Here is an example in Python3
from collections import deque
from typing import List, Tuple
class Grid:
"""represents a grid of cells indexed like a matrix:
rows first, then columns
rows, cols, r, c, row, col, cr, cc are ints
rowcol = tuple of ints
"""
eight_offsets = [(1, 1), (1, 0), (1, -1), (0, 1), (0, -1), (-1, 1), (-1, 0), (-1, -1)]
def __init__(self, rows: int, cols: int):
self.rows = rows
self.cols = cols
self.cells = [[None for col in range(cols)] for row in range(rows)]
def fill_grid_BFS(self, rowcol: Tuple[int, int]) -> None:
"""fills each cell with its distance from the cell at rowcol which is zero
"""
row, col = rowcol
self.cells[row][col] = 0
queue = deque([rowcol])
visited = set()
while queue:
current = queue.popleft()
cr, cc = current
rank = self.cells[cr][cc] + 1
visited.add(current)
for neigh in self.get_eight_neighbors(current):
if neigh in visited:
continue
r, c = neigh
self.cells[r][c] = rank
queue.append(neigh)
print(self)
def get_eight_neighbors(self, rowcol: Tuple[int, int]) -> List[Tuple[int, int]]:
"""returns the valid Moore's neighbors that have not been assigned a value yet
"""
row, col = rowcol
neighbors = []
for dr, dc in Grid.eight_offsets:
r, c = row + dr, col + dc
try:
if self.cells[r][c] is None:
neighbors.append((r, c))
except IndexError:
pass
return neighbors
def __str__(self) -> str:
res = []
for row in self.cells:
res.append(' '.join(str(elt) for elt in row))
res.append('\n')
return ''.join(res)
g = Grid(8, 8)
g.fill_grid_BFS((5, 5))
5 5 5 5 5 5 5 5
5 4 4 4 4 4 4 4
5 4 3 3 3 3 3 3
5 4 3 2 2 2 2 2
5 4 3 2 1 1 1 2
5 4 3 2 1 0 1 2
5 4 3 2 1 1 1 2
5 4 3 2 2 2 2 2
Upvotes: 1
Reputation: 184
The property all cells labeled one is that the maximum distance in both axes is equal one, the same goes on for every cell that is if the 0 cell is on the cell (x0, y0) label of cell (x, y) will be equal to max(|x - x0|, |y - y0|)
Thus, to iterate over all labels, we can use something like this:
for (l = 0 -> min(x0, y0, N - x0, N - y0) + 1:
for (x = x0 - l -> x0 + l)
#checking cell (x, y0 - l)
for (y = y0 - l -> y0 + l)
#checking cell (x0 + l, y)
for (x = x0 + l - 1 -> x0 + l)
#checking cell (x, y0 + l)
for (y = y0 - l -> y0 + l)
#checking cell (x0 - l, y)
#checking cell (x0 - l, y0 + l)
you can merge loops iterating over x and y if you don't care that you iterate over adjacent cells.
ps: loop ranges are assumed to be closed on start and open in end. i.e. (x = a -> b) means range (a, a+1, ..., b-1)
Upvotes: 0