Files
advent-of-code-go/2024/day10/day10.py
T
2024-12-27 16:10:36 -05:00

100 lines
3.1 KiB
Python

def part1(input: str) -> int:
grid: list[list[int, int]] = []
for line in input.splitlines():
grid.append([int(x) for x in list(line)])
# alternative pythonic way...
# grid = [[int(char) for char in line] for line in input.splitlines()]
ans: int = 0
for r in range(len(grid)):
for c in range(len(grid[0])):
if grid[r][c] == 0:
ans += len(dfs_backtrack_unique_end_coords(grid, r, c, {(r, c)}))
return ans
# I misread the instructions slightly and went for a "unique paths" algo at first.
# It would be simpler to pass the "reachable 9s coords" set in as an arg and update
# it in the termination case, then take the length of that set in the part1() function.
# This would remove the need to combine the sets which is potentially expensive (and ugly)
def dfs_backtrack_unique_end_coords(
grid: list[list[int, int]], row: int, col: int, visited: set[tuple[int, int]]
) -> set[tuple[int, int]]:
if grid[row][col] == 9:
return {(row, col)}
all_coords: set[tuple[int, int]] = set()
for diff in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nextRow = row + diff[0]
nextCol = col + diff[1]
if not (0 <= nextRow < len(grid) and 0 <= nextCol < len(grid[0])):
continue
if (nextRow, nextCol) in visited:
continue
if grid[nextRow][nextCol] == grid[row][col] + 1:
visited.add((nextRow, nextCol))
new_coords = dfs_backtrack_unique_end_coords(
grid, nextRow, nextCol, visited
)
# combines the two sets, see comment above function def
all_coords.update(new_coords)
visited.remove((nextRow, nextCol))
return all_coords
def part2(input: str) -> int:
grid = [[int(char) for char in line] for line in input.splitlines()]
ans: int = 0
for r in range(len(grid)):
for c in range(len(grid[0])):
if grid[r][c] == 0:
ans += dfs_backtrack_unique_paths(grid, r, c, {(r, c)})
return ans
def dfs_backtrack_unique_paths(
grid: list[list[int, int]], row: int, col: int, visited: set[tuple[int, int]]
) -> int:
if grid[row][col] == 9:
# unique path found
return 1
total: int = 0
for diff in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
nextRow = row + diff[0]
nextCol = col + diff[1]
if not (0 <= nextRow < len(grid) and 0 <= nextCol < len(grid[0])):
continue
if (nextRow, nextCol) in visited:
continue
if grid[nextRow][nextCol] == grid[row][col] + 1:
visited.add((nextRow, nextCol))
total += dfs_backtrack_unique_paths(grid, nextRow, nextCol, visited)
visited.remove((nextRow, nextCol))
return total
example = """89010123
78121874
87430965
96549874
45678903
32019012
01329801
10456732"""
input = open("input.txt").read().strip()
print(f"part1 example: {part1(example)} want 36")
print(f"part1: {part1(input)} want 782")
print(f"part2 example: {part2(example)} want 81")
print(f"part2 example: {part2(input)} want 1694")