aoc2022/d12.py

121 lines
3.6 KiB
Python
Raw Normal View History

2023-12-08 05:57:09 +01:00
import lib
EXAMPLE = """
Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi
"""
def neighbors_4(row, col, rows, cols):
n = []
for r, c in [(1, 0), (-1, 0), (0, 1), (0, -1)]:
new_row, new_col = row + r, col + c
if new_row >= 0 and new_row < rows and new_col >= 0 and new_col < cols:
n.append((new_row, new_col))
return n
def solve(lines: list[str]):
start = (0, 0)
end = (0, 0)
rows = len(lines)
cols = len(lines[0])
heights = []
dists = []
for (row, line) in enumerate(lines):
heights.append([])
dists.append([])
for (col, c) in enumerate(line):
if c == 'S':
start = (row, col)
heights[row].append(0)
dists[row].append(0)
elif c == 'E':
end = (row, col)
heights[row].append(26)
dists[row].append(2**16)
else:
heights[row].append(ord(lines[row][col]) - ord('a'))
dists[row].append(2**16)
active_fields = [start]
while active_fields:
row, col = active_fields.pop()
current_dist = dists[row][col]
current_height = heights[row][col]
for row, col in neighbors_4(row, col, rows, cols):
pot_height = heights[row][col]
if current_height < pot_height - 1:
continue
if current_dist + 1 < dists[row][col]:
dists[row][col] = current_dist + 1
active_fields.append((row, col))
# for row in dists:
# print(row)
# 34:00
return dists[end[0]][end[1]]
def solve2(lines: list[str]):
starts = []
all_dists =[]
for (row, line) in enumerate(lines):
for (col, c) in enumerate(line):
if c == 'S' or c == 'a':
starts.append((row, col))
for start in starts:
end = (0, 0)
rows = len(lines)
cols = len(lines[0])
heights = []
dists = []
for (row, line) in enumerate(lines):
heights.append([])
dists.append([])
for (col, c) in enumerate(line):
if row == start[0] and col == start[1]:
heights[row].append(0)
dists[row].append(0)
elif c == 'E':
end = (row, col)
heights[row].append(26)
dists[row].append(2**16)
else:
heights[row].append(ord(lines[row][col]) - ord('a'))
dists[row].append(2**16)
active_fields = [start]
while active_fields:
row, col = active_fields.pop()
current_dist = dists[row][col]
current_height = heights[row][col]
for row, col in neighbors_4(row, col, rows, cols):
pot_height = heights[row][col]
if current_height < pot_height - 1:
continue
if current_dist + 1 < dists[row][col]:
dists[row][col] = current_dist + 1
active_fields.append((row, col))
all_dists.append(dists[end[0]][end[1]])
# 39:45
return min(all_dists)
def main():
lines = lib.str_to_lines_no_empty(EXAMPLE)
print("Example 1:", solve(lines))
lines = lib.str_to_lines_no_empty(open("i12.txt").read())
print("Solution 1:", solve(lines))
lines = lib.str_to_lines_no_empty(EXAMPLE)
print("Example 2:", solve2(lines))
lines = lib.str_to_lines_no_empty(open("i12.txt").read())
print("Solution 2:", solve2(lines))
if __name__ == "__main__":
main()