2024-12-17 14:36:40 +00:00
|
|
|
DIRECTIONS = {
|
|
|
|
"^": 0 - 1j, # up
|
|
|
|
">": 1 + 0j, # right
|
|
|
|
"v": 0 + 1j, # down
|
|
|
|
"<": -1 + 0j, # left
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def find_start_pos(grid):
|
|
|
|
for y, row in enumerate(grid):
|
|
|
|
for x, _ in enumerate(row):
|
|
|
|
if grid[y][x] == "@":
|
|
|
|
return complex(x, y)
|
|
|
|
|
|
|
|
|
|
|
|
def get_pos(grid, pos):
|
|
|
|
x, y = int(pos.real), int(pos.imag)
|
|
|
|
if 0 <= x < len(grid[0]) and 0 <= y < len(grid):
|
|
|
|
return grid[y][x]
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def set_pos(grid, pos, val):
|
|
|
|
x, y = int(pos.real), int(pos.imag)
|
|
|
|
grid[y][x] = val
|
|
|
|
|
|
|
|
|
|
|
|
def debug_print(grid, move):
|
|
|
|
print("Move ", move)
|
|
|
|
for row in grid:
|
|
|
|
print("".join(row))
|
|
|
|
|
|
|
|
|
|
|
|
def push(grid, pos, movement):
|
|
|
|
direction = DIRECTIONS[movement]
|
|
|
|
start_pos = pos + direction
|
|
|
|
# Find the end pos of a consecutive "O" chain
|
|
|
|
end_pos = start_pos
|
|
|
|
while get_pos(grid, end_pos + direction) == "O":
|
|
|
|
end_pos += direction
|
|
|
|
if get_pos(grid, end_pos + direction) == ".":
|
|
|
|
if movement == ">":
|
|
|
|
start_x, end_x = int(start_pos.real), int(end_pos.real)
|
|
|
|
y = int(start_pos.imag)
|
|
|
|
for i in range(end_x, start_x - 1, -1):
|
|
|
|
grid[y][i+1] = "O" # shift "O" to the right
|
|
|
|
grid[y][start_x] = "."
|
|
|
|
elif movement == "<":
|
|
|
|
start_x, end_x = int(start_pos.real), int(end_pos.real)
|
|
|
|
y = int(start_pos.imag)
|
2024-12-17 15:58:25 +00:00
|
|
|
for i in range(start_x, end_x - 1, -1):
|
|
|
|
grid[y][i-1] = "O" # shift "O" to the left
|
2024-12-17 14:36:40 +00:00
|
|
|
grid[y][start_x] = "."
|
|
|
|
elif movement == "v":
|
|
|
|
start_y, end_y = int(start_pos.imag), int(end_pos.imag)
|
|
|
|
x = int(start_pos.real)
|
|
|
|
for i in range(start_y, end_y + 1):
|
|
|
|
grid[i+1][x] = "O" # shift "O" down
|
|
|
|
grid[start_y][x] = "."
|
|
|
|
elif movement == "^":
|
|
|
|
start_y, end_y = int(start_pos.imag), int(end_pos.imag)
|
|
|
|
x = int(start_pos.real)
|
2024-12-17 15:58:25 +00:00
|
|
|
for i in range(start_y, end_y - 1, -1):
|
|
|
|
grid[i-1][x] = "O" # shift "O" up
|
2024-12-17 14:36:40 +00:00
|
|
|
grid[start_y][x] = "."
|
|
|
|
|
|
|
|
|
2024-12-17 15:58:25 +00:00
|
|
|
def calculate_gps_coords(grid):
|
|
|
|
total = 0
|
|
|
|
for y, row in enumerate(grid):
|
|
|
|
for x, _ in enumerate(row):
|
|
|
|
if grid[y][x] == "O":
|
|
|
|
total += 100*y + x
|
|
|
|
return total
|
|
|
|
|
|
|
|
|
2024-12-17 14:36:40 +00:00
|
|
|
def main(content):
|
|
|
|
grid, movements = content.split("\n\n")
|
|
|
|
grid = [list(x) for x in grid.split("\n")]
|
|
|
|
movements = movements.replace("\n", "")
|
|
|
|
pos = find_start_pos(grid)
|
|
|
|
|
|
|
|
for movement in movements:
|
|
|
|
new_pos = pos + DIRECTIONS[movement]
|
|
|
|
v = get_pos(grid, new_pos)
|
|
|
|
match v:
|
|
|
|
case ".":
|
|
|
|
set_pos(grid, pos, ".")
|
|
|
|
set_pos(grid, new_pos, "@")
|
|
|
|
pos = new_pos
|
|
|
|
case "O":
|
|
|
|
push(grid, pos, movement)
|
|
|
|
if get_pos(grid, new_pos) == ".":
|
|
|
|
set_pos(grid, new_pos, "@")
|
|
|
|
set_pos(grid, pos, ".")
|
|
|
|
pos = new_pos
|
|
|
|
case "#": pass
|
|
|
|
case c: raise RuntimeError("This should never happen", c)
|
2024-12-17 15:58:25 +00:00
|
|
|
#debug_print(grid, movement)
|
|
|
|
part1 = calculate_gps_coords(grid)
|
|
|
|
print("Part 1: ", part1)
|
2024-12-17 14:36:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
import sys
|
|
|
|
infile = sys.argv[1] if len(sys.argv) > 1 else "example.txt"
|
|
|
|
with open(infile) as f:
|
|
|
|
content = f.read()
|
|
|
|
main(content)
|
|
|
|
|