animate 16

This commit is contained in:
basicbonobo 2023-12-17 14:37:10 +01:00
parent 3d6bf4f154
commit a7dfd81d21
2 changed files with 87 additions and 14 deletions

View File

@ -21,3 +21,7 @@ or
```
kotlinc -include-runtime -d seven.jar seven.kt && java -jar seven.jar < input7
```
or
```
./sechszehn.py -vv <input16
```

View File

@ -1,12 +1,8 @@
#!/usr/bin/env python3
from useful import *
import cv2 as cv
def draw(pic, backup):
for y in range(pic.shape[0]):
for x in range(pic.shape[1]):
print('#' if pic[y,x] else {45:'/',135:'\\',0:'-',90:'|'}.get(backup[y,x], '.'), end='')
print()
from useful import *
sin = {0:0,90:-1,180:0,270:1}
cos = {0:1,90:0,180:-1,270:0}
@ -15,11 +11,56 @@ mirrors = np.array([[{'/':45,'\\':135,'-':0,'|':90,'.':69}[c] for c in l] for l
size = mirrors.shape[0] # w = h anyway, don't bother genericizing
done = np.zeros((size * 4, 4, size, size), dtype=bool)
totest=deque()
verbose = len(sys.argv) > 1 and '-v' in sys.argv[1]
draw_every = 1 if verbose and '-vv' in sys.argv[1] else 666
if verbose:
"""
why aren't there single characters identifiers for top left or northwest?
let's use initials of countries: canada, soviet, brazil, australia
in addition to udlr and also "middle"
"""
initials = {letter: np.asarray(coords) / 2 for coords, letter in
np.ndenumerate(np.array(list('cuslmrbda')).reshape((3, 3)))}
mirror_rections = {45:'bs',135:'ca',0:'lr',90:'ud'}
frame = 0
cv.namedWindow('lasers', flags=cv.WINDOW_GUI_NORMAL | cv.WINDOW_AUTOSIZE)
def draw(linger=16):
global canvas, frame
for (y, x), angle in np.ndenumerate(mirrors): # just put them on top
if angle == 69:
continue
line(y, x, mirror_rections[angle], (0x7f, 0x9a, 0xa5)[::-1])
zewm = 840 // canvas.shape[0]
cv.imshow('lasers', np.kron(canvas, np.ones((zewm, zewm, 1), dtype='uint8')))
#cv.imwrite('lasers%04d.png' % frame, np.kron(canvas, np.ones((zewm, zewm, 1), dtype='uint8')))
frame += 1
cv.waitKey(linger)
def line(y, x, rection, color):
global canvas, scale
off1 = initials[rection[0]]
off2 = initials[rection[1]]
cv.line(canvas,
(x * scale + int(off1[1] * (scale - 1)),
y * scale + int(off1[0] * (scale - 1))),
(x * scale + int(off2[1] * (scale - 1)),
y * scale + int(off2[0] * (scale - 1))),
color,
1)
scale = 7
canvas = np.kron(np.ones((size * scale, size * scale, 1)),
np.asarray((0x43, 0x3c, 0x34))[::-1].reshape((1, 1, 3))).astype('uint8')
draw(1000)
def nextvel(y, x, vel):
here = mirrors[y,x]
if here == 45: # 0->90 avv, 180->270 avv: (init % 180)
if here == 69:
return [vel, ]
elif here == 45: # 0->90 avv, 180->270 avv: (init % 180)
return [(vel // 180) * 180 + (90 - vel % 180), ]
elif here == 135: # 0->270 avv, 180->90 avv
return [270 - vel, ]
@ -33,8 +74,6 @@ def nextvel(y, x, vel):
return [90, 270]
else:
return [vel, ]
elif here == 69:
return [vel, ]
else:
raise ValueError('omg')
@ -49,14 +88,41 @@ def set_done(y, x, vel, beam):
done[beam,vel // 90,y,x] = True
def test(y, x, vel, beam):
if len(sys.argv) > 1 and sys.argv[1] == '-v' and beam == 0:
ic(y, x, vel)
global totest
if is_done(y, x, vel, beam):
return
set_done(y, x, vel, beam)
totest += nexts(y, x, vel, beam)
if verbose and beam % draw_every == 0: # meh
here = mirrors[y,x]
if here == 69:
line(y, x, {0:'lr',90:'ud'}[vel%180], (0, 0, 255))
elif here == 45: # 0->90 avv, 180->270 avv: (init % 180)
if vel in (0, 270):
line(y, x, 'lm', (0, 0, 255))
line(y, x, 'mu', (0, 0, 255))
else:
line(y, x, 'rm', (0, 0, 255))
line(y, x, 'md', (0, 0, 255))
elif here == 135:
if vel in (0, 90):
line(y, x, 'lm', (0, 0, 255))
line(y, x, 'md', (0, 0, 255))
else:
line(y, x, 'rm', (0, 0, 255))
line(y, x, 'mu', (0, 0, 255))
elif here == 0:
if vel == 90:
line(y, x, 'dm', (0, 0, 255))
elif vel == 270:
line(y, x, 'um', (0, 0, 255))
elif here == 90:
if vel == 0:
line(y, x, 'lm', (0, 0, 255))
elif vel == 180:
line(y, x, 'rm', (0, 0, 255))
totest=deque()
for step in range(size):
totest += [(step, 0, 0, step), ]
totest += [(step, size - 1, 180, step + size), ]
@ -64,10 +130,13 @@ for step in range(size):
totest += [(size - 1, step, 90, step + size * 3), ]
while totest:
if len(sys.argv) > 1 and sys.argv[1] == '-v':
draw(done[0].sum(axis=0), mirrors)
if verbose:
draw()
for _ in range(len(totest)):
test(*totest.popleft())
print(np.count_nonzero(done[0].sum(axis=0).astype(bool)))
print(max(np.count_nonzero(done.sum(axis=1).astype(bool), axis=(1, 2))))
if verbose:
draw(0)