Is there any way to reduce this huge mass ?
Yes. =)
Think about places where you have duplicate, or nearly duplicate code, and write a function that does it for you.
Also think about ways you could store data in a new matrix while looping through your matrix.
rough pseudo code:
answers = [[]]
for x in matrix:
answers[x] = count_neighbors_at_x(matrix,x)
One crazy way of doing this is using complex numbers. Let me know if you want an explanation the whole thing takes only a couple of lines.
But a very simple way is to use a dictionary instead of a nested list, and then use sum() with a comprehension.
from random import randint
values = { (r,c):randint(0, 9) for r in range(5) for c in range(5) }
def neighbors(values,x,y):
return sum( values[x+dx, y+dy]
for dx,dy in [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] if (x+dx, y+dy) in values )
tot = sum( neighbors(values, x,y) for x,y in values )
print(values)
print(tot, tot/25)
If you don't know what a comprehension is, now's a fine time to learn. It's a shortcut for having loops and temporary values, and just returns the object instead.
tot = sum(neighbors(values, x,y) for x,y in values)
is the same as:
tot = 0
for x,y in values:
tot += neighbors(values, x,y)
It's just shorter and easier to follow once you understand it.
similarly
return sum( values[x+dx, y+dy]
for dx,dy in [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] if (x+dx, y+dy) in values )
is the same as:
tot = 0
for dx,dy in [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]:
if (x+dx, y+dy) in values):
tot += v[x+dx, y+dy]