70 lines
1.7 KiB
Python
70 lines
1.7 KiB
Python
import sys
|
|
sys.path.append('../aoclib')
|
|
|
|
from aoclib import Input
|
|
|
|
def find_starting_points(field) -> list[tuple[int, int]]:
|
|
points = []
|
|
for y in range(len(field)):
|
|
for x in range(len(field[0])):
|
|
if field[y][x] == 0:
|
|
points.append((x, y))
|
|
return points
|
|
|
|
|
|
def num_trails(point: tuple[int, int], curr: int, field: list[list[int]]) -> list[tuple[int, int]]:
|
|
if out_of_bounds(point, field):
|
|
return [None]
|
|
|
|
x, y = point
|
|
if field[y][x] != curr:
|
|
# impossible path
|
|
return [None]
|
|
|
|
if curr == 9 and field[y][x] == curr:
|
|
# goal
|
|
return [point]
|
|
|
|
curr += 1
|
|
|
|
opts = list()
|
|
|
|
opts.extend(num_trails((x+1, y), curr, field))
|
|
opts.extend(num_trails((x-1, y), curr, field))
|
|
opts.extend(num_trails((x, y+1), curr, field))
|
|
opts.extend(num_trails((x, y-1), curr, field))
|
|
|
|
return opts
|
|
|
|
|
|
def out_of_bounds(point: tuple[int, int], field: list[list[int]]) -> bool:
|
|
x, y = point
|
|
return y < 0 or y >= len(field) or x < 0 or x >= len(field[0])
|
|
|
|
|
|
def solve1(field: list[list[int]]) -> int:
|
|
starts = find_starting_points(field)
|
|
count = 0
|
|
for p in starts:
|
|
trails = num_trails(p, 0, field)
|
|
count += sum([1 if n else 0 for n in set(trails)])
|
|
return count
|
|
|
|
def solve2(field: list[list[int]]) -> int:
|
|
starts = find_starting_points(field)
|
|
count = 0
|
|
for p in starts:
|
|
trails = num_trails(p, 0, field)
|
|
count += sum([1 if n else 0 for n in trails])
|
|
return count
|
|
|
|
if __name__ == '__main__':
|
|
#field = Input('input_test.txt').lines_split_as_ints()
|
|
field = Input('input.txt').lines_split_as_ints()
|
|
|
|
#part 1
|
|
print('part 1:', solve1(field)) # 733
|
|
|
|
#part 2
|
|
print('part 2:', solve2(field)) # 1514
|