Reputation: 1321
There are times when I have an area in a 2D array, and I need to check for adjacent cells. Normally I would do the following:
adjacentCells = (world[y+1][x]==1)+(world[y-1]==1)+(world[y][x+1]==1)+(world[y][x-1]==1)
This would calculate how many orthogonally adjacent cells to the point (x,y) are equal to 1. The issue is, doing things this way wraps around the matrix if my x or y coordinates are 0 (the top or left edge), and it causes an exception if the point (x,y) is on a different edge. This makes the code look like this:
def adjacentCells(x,y):
total=0
if x==0:
total += 1
else:
total += world[y][x-1]
if y==0:
total += 1
else:
total += world[y-1][x]
try:
total += world[y][x+1]
except:
total += 1
try:
total += world[y+1][x]
except:
total += 1
return total
Is there a way to fix this issue, in a way about as simple as the uppermost example?
Upvotes: 0
Views: 2280
Reputation: 123473
For doing something as trivial as adding up the values of up to 4 cells, I'd just write the code for each case—it only requires one line per cell location. It may be longer than using a loop construct, but avoids looping overhead and it's all pretty much boilerplate.
It's also relatively easy to read and understand, and would make it easier to special-case one of the locations should doing that be needed for some reason.
Here's what I mean:
world = [[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]]
MIN_X, MAX_X = 0, len(world[0])-1
MIN_Y, MAX_Y = 0, len(world)-1
def adjacentCells(x, y):
return((world[ y][x-1] if MIN_Y <= y <= MAX_Y and MIN_X <= x-1 <= MAX_X else 1)
+ (world[ y][x+1] if MIN_Y <= y <= MAX_Y and MIN_X <= x+1 <= MAX_X else 1)
+ (world[y-1][ x] if MIN_Y <= y-1 <= MAX_Y and MIN_X <= x <= MAX_X else 1)
+ (world[y+1][ x] if MIN_Y <= y+1 <= MAX_Y and MIN_X <= x <= MAX_X else 1))
print(adjacentCells(0, 0)) # -> 4
print(adjacentCells(1, 1)) # -> 4
Upvotes: 1
Reputation: 95692
I would do it something like this:
def adjacentCells(x, y):
neighbours = [(x-1, y), (x, y-1), (x+1, y), (x, y+1)]
return sum(
world[b][a] if 0 <= b < len(world) and 0 <= a < len(world[b])
else 1
for (a,b) in neighbours)
So get a list of potential neighbours but check each one is valid before you use it.
If the neighbours of border cells counted as 0 instead of 1 it would be simpler, then you would simply filter the list of neighbours before using it.
Upvotes: 1