|
|
@@ -0,0 +1,48 @@ |
|
|
|
def parse_grid(text): |
|
|
|
grid = {} |
|
|
|
for y, row in enumerate(text): |
|
|
|
for x, v in enumerate(row): |
|
|
|
grid[complex(x, y)] = v if v in 'SE' else ord(v) |
|
|
|
return grid |
|
|
|
|
|
|
|
|
|
|
|
def print_grid(mapping): |
|
|
|
xmin, *_, xmax = {int(p.real) for p in mapping} |
|
|
|
ymin, *_, ymax = {int(p.imag) for p in mapping} |
|
|
|
for y in range(ymin, ymax + 1): |
|
|
|
for x in range(xmin, xmax + 1): |
|
|
|
print(mapping.get(complex(x, y), ' '), end=' ') |
|
|
|
print() |
|
|
|
|
|
|
|
|
|
|
|
def shortest_path(starts, ends, evolve): |
|
|
|
starts = {k: [k] for k in starts} |
|
|
|
known = starts.copy() |
|
|
|
while starts: |
|
|
|
old = list(starts)[0] |
|
|
|
path = starts.pop(old) |
|
|
|
starts |= {new: path + [new] for new in evolve(old) if new not in known} |
|
|
|
known |= starts |
|
|
|
for final in set(starts) & set(ends): |
|
|
|
# print_grid({k: '.' for k in known[final]}) |
|
|
|
return known[final] |
|
|
|
|
|
|
|
|
|
|
|
def main(): |
|
|
|
text = open(0).read().splitlines() |
|
|
|
grid = parse_grid(text) |
|
|
|
|
|
|
|
rev = {v: k for k, v in grid.items()} |
|
|
|
start, end = rev['S'], rev['E'] |
|
|
|
grid[start], grid[end] = ord('a'), ord('z') |
|
|
|
|
|
|
|
dof = [1, -1, 1j, -1j] |
|
|
|
evolve = lambda old: {old + step for step in dof if is_valid(old, step)} |
|
|
|
is_valid = lambda old, step: old + step in grid and grid[old + step] - grid[old] <= 1 |
|
|
|
|
|
|
|
print(len(shortest_path({start}, {end}, evolve)) - 1) |
|
|
|
starts = {k for k, v in grid.items() if v == ord('a')} |
|
|
|
print(len(shortest_path(starts, {end}, evolve)) - 1) |
|
|
|
|
|
|
|
|
|
|
|
main() |