map = [] moves = "" with open("input") as f: for line in f: if line == "\n": break map.append(line.rstrip("\n")) moves = f.readline().strip() F = { 0: (+1, 0), 1: (0, +1), 2: (-1, 0), 3: (0, -1), } #assert len(set(len(l) for l in map)) == 1 class Map: def __init__(self, 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.col = self.starts[0] self.face = 0 # 9' # 1 2 # \ 4 \ # 6 7 # 9 \ self.region_map = { # R D L U 1: [(2,0), (4, 0), (6,2), (9, 1)], 4: [(2,-1), (7,0), (6,-1), (1, 0)], 7: [(2,2), (9,+1), (6,0), (4,0)], 6: [(7,0), (9,0), (1,2), (4,+1)], 9: [(7,-1), (2,0), (1,-1), (6,0)], 2: [(7,2), (4,+1), (1, 0), (9,0)], } ok = True for f in range(4): for r in self.region_map: orig = (r,f) s = repr(orig) for _ in range(4): r, h = self.region_map[r][f] f = (f+h)%4 s += "-> {} {}".format(r, f) if (r,f) != orig: print("!!", s) ok = False assert ok, "region topography failure" def nextTile(self, x, y, face): # 0 - E # 1 - S # 2 - W # 3 - N dx, dy = F[face] r = self.region(x,y) if 0 <= (x%50 + dx) < 50 and 0 <= (y%50 + dy) < 50: x, y = x+dx, y+dy else: new_r, rotate = self.region_map[r][face] x = (x+dx) % 50 y = (y+dy) % 50 if rotate == 0: pass elif rotate == -1: x, y = y, 50-x-1 elif rotate == 1: x, y = 50-y-1, x elif rotate == 2: x, y = 50-x-1, 50-y-1 x, y = self.in_region(x, y, new_r) face = (face + rotate) % 4 c = self.map[y][x] assert c != ' ' return x, y, face, c @staticmethod def in_region(x, y, r): """returns the absolute coords if the local (x,y) in region r""" x %= 50 y %= 50 rx = r % 3 ry = r // 3 return (rx*50 + x), (ry*50 + y) @staticmethod def region(x, y): return y//50 * 3 + x//50 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): self.face = (self.face - 1) % 4 def turnRight(self): self.face = (self.face + 1) % 4 def walk(self, n): while n > 0: x,y,f,c = self.nextTile(self.col, self.row, self.face) if c == '#': break pass#break self.row = y self.col = x self.face = f #self.map[y][x] = '>v<^'[self.face] n -= 1 print(self.row+1, self.col+1) def pos(self): return self.row+1, self.col+1 def score(self): r, c = self.pos() return r*1000 + c*4 + self.face print(moves) m = Map(map) for _ in range(4): #m.walk(50) print("---") #blah i = 0 while i < len(moves): if moves[i].isdigit(): j = i+1 while j < len(moves) and moves[j].isdigit(): j += 1 n = int(moves[i:j]) m.walk(n) i = j elif moves[i] == 'L': m.turnLeft() i += 1 elif moves[i] == 'R': m.turnRight() i += 1 else: print("invalid move", moves[i], "at", i) i += 1 print(m.row, m.col) print(m.score())