advent2023/ten.py

76 lines
2.5 KiB
Python
Executable File

#!/usr/bin/env python3
import cv2 as cv
from useful import *
bit = {(-1, 0): 8,
(1, 0): 4,
(0, -1): 2,
(0, 1): 1}
udlr = {'|': 12, # 1<<3 (u) + 1<<2 (d)
'J': 10,
'L': 9,
'7': 6,
'F': 5,
'-': 3,
'.': 0,
'S': 65535}
cs = [[udlr[c] for c in l] for l in lines(open(0))]
ca = np.pad(np.array(cs, dtype=int), 1)
visited = np.zeros(ca.shape, dtype=int)
pos = next(zip(*np.nonzero(ca == 65535)))
def sub(a, b):
return (a[0] - b[0], a[1] - b[1])
def neg(a):
return (-a[0], -a[1])
def cango(origin, step):
test = sub(origin, step) # note: subtraction to match udlr
return ca[test] & bit[step] and ca[origin] & bit[neg(step)] and not visited[test]
time = 1
while True:
visited[pos] = time
#ic(visited[pos[0]-3:pos[0]+3,pos[1]-3:pos[1]+3])
time += 1
goto = [s for s in bit.keys() if cango(pos, s)] # should give one result except in the beginning
if not goto:
break
pos = sub(pos, goto[0])
print(time // 2)
canvas = np.kron(visited > 0, np.ones((3, 3), dtype='uint8')) # 1 if part of loop...
for (y, x), bend in np.ndenumerate(ca):
canvas[y*3:y*3+3,x*3:x*3+3] &= np.asarray([[False, bend & 8, False], # ...and part of the bend
[bend & 2, True, bend & 1],
[False, bend & 4, False]], dtype=bool)
mask = np.pad(canvas, (1,1))
for color in count(2): # outside: 2, inside: 3
try:
empty = next(zip(*np.nonzero(canvas == 0)))
except StopIteration: # all filled!
break
cv.floodFill(canvas, mask, empty, color)
assert color == 4
smallvas = canvas[1::3,1::3]
print(len(np.where(smallvas == 3)[0]))
if len(sys.argv) > 1 and sys.argv[1] == '-v':
# only draw the pipes, so as to not spoil anything
for (y, x), bend in np.ndenumerate(ca):
canvas[y*3:y*3+3,x*3:x*3+3] = 2 - np.asarray([[False, bend & 8, False], # ...and part of the bend
[bend & 2, bend, bend & 1],
[False, bend & 4, False]], dtype=bool).astype('uint8')
palette = [(x & 255, x >> 8 & 255, x >> 16)
for x in [0x433c34, 0x7f9aa5, 0xae8c67]]
colored = np.transpose(np.asarray(np.vectorize(
lambda x: palette[x])(
canvas[3:-3,3:-3] - 1)), axes=(1, 2, 0)).astype('uint8')
cv.imshow('pipes', np.kron(colored, np.ones((2, 2, 1), dtype='uint8')))
cv.imwrite('ten.png', colored)
cv.waitKey(0)