121 lines
3.6 KiB
Python
121 lines
3.6 KiB
Python
|
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()
|