1
0
Fork 0
adventofcode/2024/06/main.py

109 lines
2.5 KiB
Python
Raw Normal View History

2024-12-06 12:05:45 +00:00
#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# Author: Sebastian Mark
# CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de)
# pylint: disable=missing-module-docstring,missing-function-docstring,consider-using-f-string
from copy import deepcopy
def readinput() -> str:
with open("input", "r", encoding="utf-8") as file:
lines = [list(line.strip()) for line in file]
return lines
def find_guard(maze: list) -> tuple:
for idx, row in enumerate(maze):
try:
x = row.index("^")
y = idx
except ValueError:
pass
else:
return (x, y)
return tuple(-1, -1)
def move_guard(maze: list, guard: tuple) -> tuple[int, bool, dict]:
2024-12-06 12:05:45 +00:00
width = len(maze[0])
height = len(maze)
path_history = {}
# remember the start position as visited
visited = set()
visited.add(guard)
# start upwards
direction = (0, -1)
while True:
# get next position
nxt = (
guard[0] + direction[0],
guard[1] + direction[1],
)
# check borders
if not (0 <= nxt[0] < width and 0 <= nxt[1] < height):
visited.add(guard)
break
# check for obstacle and rotate clockwise
if maze[nxt[1]][nxt[0]] == "#":
direction = (-direction[1], direction[0])
continue
# loop detection
# (has the guard been here and walking in the same direction?)
if nxt not in path_history:
path_history[nxt] = (guard, direction)
elif path_history[nxt] == (guard, direction):
return 0, True, {}
2024-12-06 12:05:45 +00:00
# mark spot as visited and move guard
visited.add(guard)
guard = nxt
return len(visited), False, path_history
2024-12-06 12:05:45 +00:00
def print_maze(maze: list):
for row in maze:
print("".join(row))
print("-")
def main():
# part 1
maze = readinput()
guard = find_guard(maze)
count, _, guard_path = move_guard(maze, guard)
2024-12-06 12:05:45 +00:00
print("Guard positions: %d" % count)
# part 2
count = 0
maze = readinput()
guard = find_guard(maze)
# place an obstacle at every position in the guards path
# then check new maze for loop
for col, row in guard_path:
if (col, row) == guard:
continue
new_maze = deepcopy(maze)
new_maze[row][col] = "#"
_, loop, _ = move_guard(new_maze, guard)
if loop:
count += 1
2024-12-06 12:05:45 +00:00
print("Loop options: %d" % count)
if __name__ == "__main__":
main()