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()