with open('input.text', 'r') as file: data: list[str] = file.readlines() y_bound = len(data) x_bound = len(data[0]) class Vector: x: int y: int def __init__(self, x: int, y: int): self.x = x self.y = y def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) def __str__(self): return f'{self.x}, {self.y}' def __eq__(self, value): return self.x == value.x and self.y == value.y class Guard: pos: Vector dir: Vector def __init__(self, p: Vector, d: Vector): self.pos = p self.dir = d def move(self, ob) -> bool: new_pos = self.pos + self.dir # Check if need to turn if new_pos in ob: self.turn() return self.move(ob) # Check if move out of bounds if new_pos.y < 0 or new_pos.y >= y_bound or new_pos.x < 0 or new_pos.x >= x_bound: return False self.pos = new_pos return True def turn(self): temp_x = self.dir.x self.dir.x = -self.dir.y self.dir.y = temp_x # Parse Data obstacles = [] guard = None for y, line in enumerate(data): for x, char in enumerate(line): match char: case '#': obstacles.append(Vector(x, y)) case '^': guard = Guard(Vector(x, y), Vector(0, -1)) starting_pos = guard.pos # Part 1 been = [starting_pos] while guard.move(obstacles): if guard.pos not in been: been.append(guard.pos) print(f'Part 1: {len(been)}') # Part 2 total = 0 been.remove(starting_pos) for place in been: temp_obstacles = obstacles.copy() temp_obstacles.append(place) guard.pos = starting_pos guard.dir = Vector(0, -1) steps = 0 while guard.move(temp_obstacles): steps += 1 # Yup, this is what I count as in a loop... if steps >= 10 ** 5: total += 1 break print(f'Part 2: {total}')