From 6c64d1b62e15cf2c788f005a88fdf7429f911d5c Mon Sep 17 00:00:00 2001 From: Sebastian Mark Date: Fri, 6 Dec 2024 13:05:45 +0100 Subject: [PATCH] add 2024/day6 --- 2024/06/main.py | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 2024/06/main.py diff --git a/2024/06/main.py b/2024/06/main.py new file mode 100644 index 0000000..2f1a807 --- /dev/null +++ b/2024/06/main.py @@ -0,0 +1,109 @@ +#!/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]: + 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 + + # mark spot as visited and move guard + visited.add(guard) + guard = nxt + + return len(visited), False + + +def print_maze(maze: list): + for row in maze: + print("".join(row)) + print("-") + + +def main(): + # part 1 + maze = readinput() + guard = find_guard(maze) + count, _ = move_guard(maze, guard) + print("Guard positions: %d" % count) + + # part 2 + count = 0 + maze = readinput() + guard = find_guard(maze) + + # brute force: + # place an obstacle everywhere (except the guards position) + for row, _ in enumerate(maze): + for col, _ in enumerate(maze[0]): + if (col, row) == guard: + continue + new_maze = deepcopy(maze) + new_maze[row][col] = "#" + _, loop = move_guard(new_maze, guard) + if loop: + count += 1 + + print("Loop options: %d" % count) + + +if __name__ == "__main__": + main()