mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-05-18 19:13:27 +02:00
hacky and not dry but it works... slowly
This commit is contained in:
@@ -0,0 +1,165 @@
|
|||||||
|
# guard walks forward, turns right if blocked, turn or step = 1 move
|
||||||
|
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def part1(input: str) -> int:
|
||||||
|
return len(get_full_path(input))
|
||||||
|
|
||||||
|
|
||||||
|
# changed this to return the set of all coords on the path to (slightly) speed up part 2
|
||||||
|
# so part 2 can just modify things already on the guard's path instead of brute forcing
|
||||||
|
# the entire grid
|
||||||
|
def get_full_path(input: str) -> set[tuple[int, int]]:
|
||||||
|
lines = input.splitlines()
|
||||||
|
|
||||||
|
row: int = 0
|
||||||
|
col: int = 0
|
||||||
|
|
||||||
|
# find starting row and col
|
||||||
|
for r in range(len(lines)):
|
||||||
|
for c in range(len(lines[0])):
|
||||||
|
if lines[r][c] == "^":
|
||||||
|
row = r
|
||||||
|
col = c
|
||||||
|
break
|
||||||
|
|
||||||
|
# example and my input both have the guard just starting pointing north
|
||||||
|
dir_index: int = 0
|
||||||
|
dirs: list[list[int]] = [
|
||||||
|
[-1, 0],
|
||||||
|
[0, 1],
|
||||||
|
[1, 0],
|
||||||
|
[0, -1],
|
||||||
|
]
|
||||||
|
|
||||||
|
seen: set[tuple[int, int]] = set()
|
||||||
|
|
||||||
|
# assume that we just have to run off the grid?..
|
||||||
|
while row >= 0 and row < len(lines) and col >= 0 and col < len(lines[0]):
|
||||||
|
coord = (row, col)
|
||||||
|
|
||||||
|
seen.add(coord)
|
||||||
|
dir = dirs[dir_index]
|
||||||
|
nextRow: int = row + dir[0]
|
||||||
|
nextCol: int = col + dir[1]
|
||||||
|
if not (
|
||||||
|
nextRow >= 0
|
||||||
|
and nextRow < len(lines)
|
||||||
|
and nextCol >= 0
|
||||||
|
and nextCol < len(lines[0])
|
||||||
|
):
|
||||||
|
break
|
||||||
|
if lines[nextRow][nextCol] == "#":
|
||||||
|
# rotate
|
||||||
|
dir_index += 1
|
||||||
|
dir_index %= 4
|
||||||
|
else:
|
||||||
|
row = nextRow
|
||||||
|
col = nextCol
|
||||||
|
|
||||||
|
# return len(seen)
|
||||||
|
return seen
|
||||||
|
|
||||||
|
|
||||||
|
def part2(input: str) -> int:
|
||||||
|
|
||||||
|
path = get_full_path(input)
|
||||||
|
|
||||||
|
# list(str) divides the str into individual characters?
|
||||||
|
# can't just use str.split("")
|
||||||
|
# need an actual 2D array so we can modify the grid and add obstacles
|
||||||
|
grid = [list(line) for line in input.splitlines()]
|
||||||
|
|
||||||
|
# for every coord on the guard's path, just make it an obstacle and see if it loops
|
||||||
|
ans: int = 0
|
||||||
|
for coord in path:
|
||||||
|
if grid[coord[0]][coord[1]] == ".":
|
||||||
|
grid[coord[0]][coord[1]] = "#"
|
||||||
|
if does_guard_loop(grid):
|
||||||
|
ans += 1
|
||||||
|
grid[coord[0]][coord[1]] = "."
|
||||||
|
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
# slight modification to getting the entire path by tracking the direction
|
||||||
|
# these two could be combined...
|
||||||
|
def does_guard_loop(grid: list[list[str]]) -> bool:
|
||||||
|
row: int = 0
|
||||||
|
col: int = 0
|
||||||
|
|
||||||
|
# find starting row and col
|
||||||
|
for r in range(len(grid)):
|
||||||
|
for c in range(len(grid[0])):
|
||||||
|
if grid[r][c] == "^":
|
||||||
|
row = r
|
||||||
|
col = c
|
||||||
|
break
|
||||||
|
|
||||||
|
# example and my input both have the guard just starting pointing north
|
||||||
|
dir_index: int = 0
|
||||||
|
dirs: list[list[int]] = [
|
||||||
|
[-1, 0],
|
||||||
|
[0, 1],
|
||||||
|
[1, 0],
|
||||||
|
[0, -1],
|
||||||
|
]
|
||||||
|
|
||||||
|
# keys: row, col, dir_index
|
||||||
|
seen: set[tuple[int, int, int]] = set()
|
||||||
|
|
||||||
|
# assume that we just have to run off the grid?..
|
||||||
|
while row >= 0 and row < len(grid) and col >= 0 and col < len(grid[0]):
|
||||||
|
key = (row, col, dir_index)
|
||||||
|
|
||||||
|
if key in seen:
|
||||||
|
return True
|
||||||
|
|
||||||
|
seen.add(key)
|
||||||
|
dir = dirs[dir_index]
|
||||||
|
nextRow: int = row + dir[0]
|
||||||
|
nextCol: int = col + dir[1]
|
||||||
|
if not (
|
||||||
|
nextRow >= 0
|
||||||
|
and nextRow < len(grid)
|
||||||
|
and nextCol >= 0
|
||||||
|
and nextCol < len(grid[0])
|
||||||
|
):
|
||||||
|
break
|
||||||
|
if grid[nextRow][nextCol] == "#":
|
||||||
|
# rotate
|
||||||
|
dir_index += 1
|
||||||
|
dir_index %= 4
|
||||||
|
else:
|
||||||
|
row = nextRow
|
||||||
|
col = nextCol
|
||||||
|
|
||||||
|
# no loop found
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
example = """....#.....
|
||||||
|
.........#
|
||||||
|
..........
|
||||||
|
..#.......
|
||||||
|
.......#..
|
||||||
|
..........
|
||||||
|
.#..^.....
|
||||||
|
........#.
|
||||||
|
#.........
|
||||||
|
......#..."""
|
||||||
|
|
||||||
|
input = open("input.txt").read()
|
||||||
|
|
||||||
|
|
||||||
|
print(f"part1 example: {part1(example)} want 41")
|
||||||
|
print(f"part1: {part1(input)} want 4939")
|
||||||
|
|
||||||
|
print(f"part2 example: {part2(example)} want 6")
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
print(f"part2: {part2(input)} want 1434") # slow as heck... ~30s on my laptop
|
||||||
|
end_time = time.time()
|
||||||
|
print(f"runtime = {end_time - start_time} seconds")
|
||||||
Reference in New Issue
Block a user