day 10 much faster fill with numpy

main
magical 2023-12-10 07:37:50 +00:00
parent 3b5b9f3839
commit 55158903e6
1 changed files with 21 additions and 25 deletions

View File

@ -64,7 +64,9 @@ def find_loop(grid, start):
def enclosedby(grid, points): def enclosedby(grid, points):
# upsample by 3x3 # upsample by 3x3
fill = [[0]*(X*3) for _ in range(Y*3)] import numpy
fill = numpy.zeros((Y*3,X*3+1), dtype='uint8')
#fill = [[0]*(X*3) for _ in range(Y*3)]
for i,j in points: for i,j in points:
d = grid[i,j] d = grid[i,j]
if d == N|S: t=[[0,1,0],[0,1,0],[0,1,0]] if d == N|S: t=[[0,1,0],[0,1,0],[0,1,0]]
@ -76,7 +78,7 @@ def enclosedby(grid, points):
else: raise Exception("invalid d=%d at (%s,%s)" % (d, i, j)) else: raise Exception("invalid d=%d at (%s,%s)" % (d, i, j))
for k in range(3): for k in range(3):
for l in range(3): for l in range(3):
fill[i*3+k][j*3+l] = t[k][l] fill[i*3+k, j*3+l] = t[k][l]
def draw(fill): def draw(fill):
for row in fill: for row in fill:
@ -86,39 +88,33 @@ def enclosedby(grid, points):
# fill edges # fill edges
for i in range(Y*3): for i in range(Y*3):
if fill[i][ 0 ] == 0: fill[i][ 0 ] = 2 if fill[i, 0 ] == 0: fill[i, 0 ] = 2
if fill[i][X*3-1] == 0: fill[i][X*3-1] = 2 if fill[i, X*3-1] == 0: fill[i, X*3-1] = 2
for j in range(X*3): for j in range(X*3):
if fill[ 0 ][j] == 0: fill[ 0 ][j] = 2 if fill[ 0 , j] == 0: fill[ 0 , j] = 2
if fill[Y*3-1][j] == 0: fill[Y*3-1][j] = 2 if fill[Y*3-1, j] == 0: fill[Y*3-1, j] = 2
# flood fill # flood fill
next = {} changed = True
def set(i,j): while changed:
if 0 <= i < Y*3 and 0 <= j < X*3:
if fill[i][j] == 0:
next[i,j] = 2
while True:
#draw(fill) #draw(fill)
next.clear() changed = False
for i in range(Y*3): for i in range(Y*3):
for j in range(X*3): f = (fill[i] == 2)
if fill[i][j] == 2: f = numpy.roll(f, 1) | numpy.roll(f, -1)
set(i-1,j) if i > 0: f |= (fill[i-1] == 2)
set(i+1,j) if i < Y*3-1: f |= (fill[i+1] == 2)
set(i,j-1) f[-1] = False
set(i,j+1) f &= (fill[i] == 0)
if next: if f.any():
for (i,j),c in next.items(): fill[i, f] = 2
fill[i][j] = c changed = True
continue
break
draw(fill) draw(fill)
# downsample # downsample
inside = [] inside = []
for i,j in grid: for i,j in grid:
f = [fill[i*3+k][j*3+l]==0 for k in range(3) for l in range(3)] f = [fill[i*3+k, j*3+l]==0 for k in range(3) for l in range(3)]
if all(f): if all(f):
inside.append((i,j)) inside.append((i,j))