|
@@ -17,21 +17,13 @@ board = [line for line in lines[:-2]]
|
|
|
max_width = max(len(line) for line in board)
|
|
|
board = [line + " " * max(0, max_width - len(line)) for line in board]
|
|
|
|
|
|
-pw = deque(lines[-1])
|
|
|
-
|
|
|
def show(grid):
|
|
|
for line in grid:
|
|
|
for c in line:
|
|
|
print(c, end='')
|
|
|
print("")
|
|
|
|
|
|
-pos = ([x for x, c in enumerate(board[0]) if c == '.'][0], 0)
|
|
|
-facing = 0
|
|
|
-
|
|
|
-num = ""
|
|
|
-
|
|
|
-def walk(steps):
|
|
|
- global pos
|
|
|
+def walk(steps, board, pos):
|
|
|
for _ in range(steps):
|
|
|
x, y = pos
|
|
|
new_x = pos[0] + 1
|
|
@@ -41,9 +33,9 @@ def walk(steps):
|
|
|
break
|
|
|
else:
|
|
|
pos = (new_x, y)
|
|
|
+ return (board, pos)
|
|
|
|
|
|
-def rotate(rot):
|
|
|
- global board, pos, facing
|
|
|
+def rotate(rot, board, pos, facing):
|
|
|
if rot == "R":
|
|
|
board = rot_left(board)
|
|
|
|
|
@@ -56,28 +48,240 @@ def rotate(rot):
|
|
|
board = rot_right(board)
|
|
|
pos = (new_x, x)
|
|
|
facing = (facing - 1) % 4
|
|
|
+ return (board, pos, facing)
|
|
|
+
|
|
|
+def part1(board, pw):
|
|
|
+
|
|
|
+ pw = deque(pw)
|
|
|
+
|
|
|
+ pos = ([x for x, c in enumerate(board[0]) if c == '.'][0], 0)
|
|
|
+ facing = 0
|
|
|
+
|
|
|
+ num = ""
|
|
|
+
|
|
|
+ while pw:
|
|
|
+ char = pw.popleft()
|
|
|
+ if char == 'R' or char == 'L':
|
|
|
+ steps = int(num)
|
|
|
+
|
|
|
+ board, pos = walk(steps, board, pos)
|
|
|
+
|
|
|
+ board, pos, facing = rotate(char, board, pos, facing)
|
|
|
+
|
|
|
+ num = ""
|
|
|
+ else:
|
|
|
+ num += char
|
|
|
+
|
|
|
+
|
|
|
+ board, pos = walk(int(num), board, pos)
|
|
|
+
|
|
|
+ final_facing = facing
|
|
|
+
|
|
|
+ while facing != 0:
|
|
|
+ board, pos, facing = rotate("R", board, pos, facing)
|
|
|
+
|
|
|
+ pos = (pos[0] + 1, pos[1] + 1)
|
|
|
+
|
|
|
+ print(pos[1] * 1000 + pos[0] * 4 + final_facing)
|
|
|
+
|
|
|
+part1(board, lines[-1])
|
|
|
+
|
|
|
+grid_sz = 50
|
|
|
+
|
|
|
+def empty_side():
|
|
|
+ return [" " * grid_sz] * grid_sz
|
|
|
+
|
|
|
+def extract_side(board, pos):
|
|
|
+ return [line[pos[0] * grid_sz : (pos[0] + 1) * grid_sz] for line in board[pos[1] * grid_sz : (pos[1] + 1) * grid_sz]]
|
|
|
|
|
|
-while pw:
|
|
|
- char = pw.popleft()
|
|
|
- if char == 'R' or char == 'L':
|
|
|
- steps = int(num)
|
|
|
|
|
|
- walk(steps)
|
|
|
|
|
|
- rotate(char)
|
|
|
+dir_to_sym = [">", "v", "<", "^"]
|
|
|
|
|
|
- num = ""
|
|
|
- else:
|
|
|
- num += char
|
|
|
+def build_cube(board):
|
|
|
+ neighbours = {}
|
|
|
+ sides = set()
|
|
|
|
|
|
+ side = ([x for x, c in enumerate(board[0]) if c == '.'][0] // grid_sz, 0)
|
|
|
+ q = deque()
|
|
|
+ q.append(side)
|
|
|
+
|
|
|
+ while q:
|
|
|
+ side = q.popleft()
|
|
|
+ x, y = side
|
|
|
+ if side not in neighbours:
|
|
|
+ neighbours[side] = [None, None, None, None]
|
|
|
+ for i, (dx, dy) in enumerate([(1, 0), (0, 1), (-1, 0), (0, -1)]):
|
|
|
+ new_x, new_y = x + dx, y + dy
|
|
|
+ new = (new_x, new_y)
|
|
|
+ if new_x < 0:
|
|
|
+ continue
|
|
|
+ if new_y < 0:
|
|
|
+ continue
|
|
|
+ try:
|
|
|
+ if board[new_y * grid_sz][new_x * grid_sz] != " ":
|
|
|
+ if new not in neighbours:
|
|
|
+ neighbours[new] = [None, None, None, None]
|
|
|
+ neighbours[side][i] = (new, (i + 2) % 4)
|
|
|
+ neighbours[new][(i+2) % 4] = (side, i % 4)
|
|
|
+ if (new_x, new_y) not in sides:
|
|
|
+ sides.add((new_x, new_y))
|
|
|
+ q.append((new_x, new_y))
|
|
|
+ except IndexError:
|
|
|
+ continue
|
|
|
+
|
|
|
+ for _ in range(4):
|
|
|
+ for pos, nbrs in neighbours.items():
|
|
|
+ # Fold corners
|
|
|
+ for i in range(4):
|
|
|
+ left = nbrs[i]
|
|
|
+ right = nbrs[(i+1) % 4]
|
|
|
+ if left is not None and right is not None:
|
|
|
+ if neighbours[left[0]][(i+1)%4] is not None:
|
|
|
+ continue
|
|
|
+ if left[0] in [a[0] for a in neighbours[right[0]] if a is not None]:
|
|
|
+ continue
|
|
|
+ rel_left = (i - left[1]) % 4
|
|
|
+ rel_right = ((i + 1) - right[1]) % 4
|
|
|
+ rel = (rel_left - rel_right) % 4
|
|
|
+ print("Looking at", pos)
|
|
|
+ print("Relative direction:", rel_left, rel_right, rel)
|
|
|
+ if rel == 0:
|
|
|
+ print(left[0], "has", right[0], "to the", dir_to_sym[(i + 1)%4])
|
|
|
+ print(right[0], "has", left[0], "to the", dir_to_sym[(i + 0)%4])
|
|
|
+ print("-" * 20)
|
|
|
+ neighbours[left[0]][(i+1)%4] = (right[0], (i+0)%4)
|
|
|
+ neighbours[right[0]][(i+0)%4] = (left[0], (i+1)%4)
|
|
|
+ elif rel == 1:
|
|
|
+ print(left[0], "has", right[0], "to the", dir_to_sym[(i + 1)%4])
|
|
|
+ print(right[0], "has", left[0], "to the", dir_to_sym[(i + 1)%4])
|
|
|
+ print("-" * 20)
|
|
|
+ neighbours[left[0]][(i+1)%4] = (right[0], (i+1)%4)
|
|
|
+ neighbours[right[0]][(i+1)%4] = (left[0], (i+1)%4)
|
|
|
+ else:
|
|
|
+ raise ValueError("Weird grid?")
|
|
|
+
|
|
|
+ for pair in neighbours.items():
|
|
|
+ print(pair)
|
|
|
+ # Finish the fold :DDD
|
|
|
+ for i in range(2):
|
|
|
+ for start in [(pos, nbrs) for (pos, nbrs) in neighbours.items() if None in nbrs]:
|
|
|
+ print("Start:", start)
|
|
|
+ pos, nbrs = start
|
|
|
+ for direction in [(2 + i) % 4 for i, n in enumerate(nbrs) if n is None]:
|
|
|
+ start_dir = direction
|
|
|
+ print("Direction:", direction)
|
|
|
+ for i in range(3):
|
|
|
+ if neighbours[pos][direction] is None:
|
|
|
+ break
|
|
|
+ pos, new_dir = neighbours[pos][direction]
|
|
|
+ direction = (2 + new_dir) % 4
|
|
|
+ print("pos:", pos, "Direction:", direction)
|
|
|
+ else:
|
|
|
+ neighbours[start[0]][(2 + start_dir) % 4] = (pos, direction)
|
|
|
+ neighbours[pos][direction] = (start[0], (2 + start_dir) % 4)
|
|
|
+ for pair in neighbours.items():
|
|
|
+ print(pair)
|
|
|
+
|
|
|
+ return neighbours
|
|
|
+
|
|
|
+
|
|
|
+def part2(board, pw):
|
|
|
+ #neighbours = build_cube(board)
|
|
|
+ #print(neighbours)
|
|
|
+ neighbours = {
|
|
|
+ (1, 0): [((2, 0), 2), ((1, 1), 3), ((0, 2), 2), ((0, 3), 2)],
|
|
|
+ (2, 0): [((1, 2), 0), ((1, 1), 0), ((1, 0), 0), ((0, 3), 1)],
|
|
|
+ (1, 1): [((2, 0), 1), ((1, 2), 3), ((0, 2), 3), ((1, 0), 1)],
|
|
|
+ (1, 2): [((2, 0), 0), ((0, 3), 0), ((0, 2), 0), ((1, 1), 1)],
|
|
|
+ (0, 2): [((1, 2), 2), ((0, 3), 3), ((1, 0), 2), ((1, 1), 2)],
|
|
|
+ (0, 3): [((1, 2), 1), ((2, 0), 3), ((1, 0), 3), ((0, 2), 1)]}
|
|
|
+ if False:
|
|
|
+ edges = set()
|
|
|
+ for pos, nbrs in neighbours.items():
|
|
|
+ for i, (n, d) in enumerate(nbrs):
|
|
|
+ if (n, d) in edges:
|
|
|
+ print("Duplicate:", (n, d))
|
|
|
+ break
|
|
|
+ edges.add((n, d))
|
|
|
+ print(pos, "has", n, "to the", dir_to_sym[i])
|
|
|
+
|
|
|
+ for side in neighbours.keys():
|
|
|
+ for direction in range(4):
|
|
|
+ current = side
|
|
|
+ #print("Start:", current, "Direction:", direction)
|
|
|
+ for i in range(4):
|
|
|
+ side, new_dir = neighbours[side][direction]
|
|
|
+ direction = (2 + new_dir) % 4
|
|
|
+ #print("side:", side, "Direction:", direction)
|
|
|
+ print(side, current)
|
|
|
+ assert current == side
|
|
|
+
|
|
|
+
|
|
|
+ side = ([x for x, c in enumerate(board[0]) if c == '.'][0] // grid_sz, 0)
|
|
|
+ grid = extract_side(board, side)
|
|
|
+ pos = ([x for x, c in enumerate(grid[0]) if c == '.'][0], 0)
|
|
|
+ facing = 0
|
|
|
+
|
|
|
+
|
|
|
+ num = ""
|
|
|
+
|
|
|
+ path = set()
|
|
|
+
|
|
|
+ pw = deque(pw)
|
|
|
+ pw.append('S')
|
|
|
+
|
|
|
+ while pw:
|
|
|
+ char = pw.popleft()
|
|
|
+ if char == 'R' or char == 'L' or char == 'S':
|
|
|
+ rot = char
|
|
|
+ steps = int(num)
|
|
|
+
|
|
|
+ #print("grid:", side, "pos:", pos, "face:", dir_to_sym[facing])
|
|
|
+ #show(grid)
|
|
|
+
|
|
|
+ for _ in range(steps):
|
|
|
+ x, y = pos
|
|
|
+ new_x = pos[0] + 1
|
|
|
+ new_pos = (new_x, pos[1])
|
|
|
+ new_grid = grid
|
|
|
+ new_side = side
|
|
|
+ new_facing = facing
|
|
|
+ if new_x >= grid_sz:
|
|
|
+ # Find next side
|
|
|
+ new_side, entry_dir = neighbours[side][facing]
|
|
|
+ rel_dir = entry_dir - facing
|
|
|
+ new_facing = (entry_dir + 2) % 4
|
|
|
+ new_grid = extract_side(board, new_side)
|
|
|
+ for _ in range(new_facing):
|
|
|
+ new_grid = rot_left(new_grid)
|
|
|
+ new_x = 0
|
|
|
+ new_pos = (0, y)
|
|
|
+
|
|
|
+ if new_grid[y][new_x] == '#':
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ side = new_side
|
|
|
+ pos = new_pos
|
|
|
+ grid = new_grid
|
|
|
+ facing = new_facing
|
|
|
+
|
|
|
+ #print("grid:", side, "pos:", pos, "face:", dir_to_sym[facing])
|
|
|
+ #show(grid)
|
|
|
+
|
|
|
+ grid, pos, facing = rotate(rot, grid, pos, facing)
|
|
|
+
|
|
|
+ num = ""
|
|
|
+ else:
|
|
|
+ num += char
|
|
|
|
|
|
-walk(int(num))
|
|
|
+ final_facing = facing
|
|
|
|
|
|
-final_facing = facing
|
|
|
+ while facing != 0:
|
|
|
+ grid, pos, facing = rotate("R", grid, pos, facing)
|
|
|
|
|
|
-while facing != 0:
|
|
|
- rotate("R")
|
|
|
+ pos = (side[0] * grid_sz + pos[0] + 1, side[1] * grid_sz + pos[1] + 1)
|
|
|
|
|
|
-pos = (pos[0] + 1, pos[1] + 1)
|
|
|
+ print(pos[1] * 1000 + pos[0] * 4 + final_facing)
|
|
|
|
|
|
-print(pos[1] * 1000 + pos[0] * 4 + final_facing)
|
|
|
+part2(board, lines[-1])
|