day 22 python cleanup

also make part 1 work again
main
magical 2022-12-22 20:56:46 -08:00
parent 77f02a8217
commit a299c90401
1 changed files with 68 additions and 69 deletions

View File

@ -7,6 +7,10 @@ with open("input") as f:
map.append(line.rstrip("\n")) map.append(line.rstrip("\n"))
moves = f.readline().strip() moves = f.readline().strip()
# 0 - E
# 1 - S
# 2 - W
# 3 - N
F = { F = {
0: (+1, 0), 0: (+1, 0),
1: (0, +1), 1: (0, +1),
@ -17,17 +21,15 @@ F = {
#assert len(set(len(l) for l in map)) == 1 #assert len(set(len(l) for l in map)) == 1
class Map: class Map:
def __init__(self, map): def __init__(self, map, region_size=50):
self.map = map self.map = map
self.starts = {}
for row in range(len(self.map)):
i = 0
while self.map[row][i] == ' ':
i += 1
self.starts[row] = i
self.row = 0 self.row = 0
self.col = self.starts[0] self.col = 0
self.face = 0 self.face = 0
self.region_size = region_size
while self.map[self.row][self.col] == ' ':
self.col += 1
# 9' # 9'
# 1 2 # 1 2
@ -56,90 +58,91 @@ class Map:
if (r,f) != orig: if (r,f) != orig:
print("!!", s) print("!!", s)
ok = False ok = False
assert ok, "region topography failure" assert ok, "topology failure"
def set_simple_region_map(self):
R = self.region_size
def exists(x,y):
return 0 <= y < len(self.map) and 0 <= x < len(self.map[y]) and self.map[y][x] != ' '
for y in range(0,len(self.map), R):
for x in range(0, len(self.map[y]), R):
if exists(x,y):
warps = []
for f in range(4):
dx, dy = F[f]
dx, dy = dx*R, dy*R
x1, y1 = x+dx, y+dy
if exists(x1, y1):
dest = self.region(x1,y1)
else:
if dy:
y1 %= len(self.map)
while not exists(x1, y1):
y1 = (y1+dy)%len(self.map)
if dx:
x1 %= len(self.map[y1])
while not exists(x1, y1):
x1 = (x1+dx)%len(self.map[y1])
dest = self.region(x1, y1)
warps.append((dest, 0))
r = self.region(x,y)
self.region_map[r] = warps
print(self.region_map)
def nextTile(self, x, y, face): def nextTile(self, x, y, face):
# 0 - E R = self.region_size
# 1 - S
# 2 - W
# 3 - N
dx, dy = F[face] dx, dy = F[face]
r = self.region(x,y) if 0 <= (x%R + dx) < R and 0 <= (y%R + dy) < R:
if 0 <= (x%50 + dx) < 50 and 0 <= (y%50 + dy) < 50:
x, y = x+dx, y+dy x, y = x+dx, y+dy
else: else:
r = self.region(x,y)
u = (x+dx) % R
v = (y+dy) % R
new_r, rotate = self.region_map[r][face] new_r, rotate = self.region_map[r][face]
x = (x+dx) % 50
y = (y+dy) % 50
if rotate == 0: if rotate == 0:
pass pass
elif rotate == -1: elif rotate == -1:
x, y = y, 50-x-1 u, v = v, R-u-1
elif rotate == 1: elif rotate == 1:
x, y = 50-y-1, x u, v = R-v-1, u
elif rotate == 2: elif rotate == 2:
x, y = 50-x-1, 50-y-1 u, v = R-u-1, R-v-1
x, y = self.in_region(x, y, new_r) x, y = self.to_abs(u, v, new_r)
face = (face + rotate) % 4 face = (face + rotate) % 4
c = self.map[y][x] c = self.map[y][x]
assert c != ' ' assert c != ' '
return x, y, face, c return x, y, face, c
@staticmethod def to_abs(self, u, v, r):
def in_region(x, y, r): """returns the absolute coords of the local point (u,v) in region r"""
"""returns the absolute coords if the local (x,y) in region r""" R = self.region_size
x %= 50 u %= R
y %= 50 v %= R
rx = r % 3 rx = r % 3
ry = r // 3 ry = r // 3
return (rx*50 + x), (ry*50 + y) return (rx*R + u), (ry*R + v)
@staticmethod def region(self, x, y):
def region(x, y): R = self.region_size
return y//50 * 3 + x//50 return y//R * 3 + x//R
def warp(x,y,face):
r = self.region(x,y)
s = 0
if dx:
x += dx
if x < self.starts[y]:
x = len(self.map[y])-1
elif x >= len(self.map[y]):
x = self.starts[y]
if dy:
for _ in range(999):
y += dy
if y < 0:
y = len(self.map)-1
elif y >= len(self.map):
y = 0
if x > len(self.map[y]) or self.map[y][x] == ' ':
continue
break
assert self.map[y][x] != ' '
return x, y, self.map[y][x]
def turnLeft(self): def turnLeft(self):
self.face = (self.face - 1) % 4 self.face = (self.face - 1) % 4
def turnRight(self): def turnRight(self):
self.face = (self.face + 1) % 4 self.face = (self.face + 1) % 4
def walk(self, n): def walk(self, n, noclip=True):
x, y, face = self.col, self.row, self.face
while n > 0: while n > 0:
x,y,f,c = self.nextTile(self.col, self.row, self.face) x,y,face,c = self.nextTile(x, y, face)
if c == '#': if c == '#' and noclip:
break break
pass#break n -= 1
self.row = y self.row = y
self.col = x self.col = x
self.face = f self.face = face
#self.map[y][x] = '>v<^'[self.face] #print(self.pos())
n -= 1
print(self.row+1, self.col+1)
def pos(self): def pos(self):
return self.row+1, self.col+1 return self.row+1, self.col+1
@ -148,15 +151,11 @@ class Map:
r, c = self.pos() r, c = self.pos()
return r*1000 + c*4 + self.face return r*1000 + c*4 + self.face
print(moves) #print(moves)
m = Map(map) m = Map(map)
#m.set_simple_region_map()
for _ in range(4):
#m.walk(50)
print("---")
#blah
i = 0 i = 0
while i < len(moves): while i < len(moves):
if moves[i].isdigit(): if moves[i].isdigit():