|
1234567891011121314151617181920212223242526272829303132333435363738 |
- import itertools
-
-
- # transform text into two helpful data structures
- valid = set()
- special_locations = {}
- for y, line in enumerate(data_file.read_text().splitlines()):
- for x, char in enumerate(line):
- if char != '#':
- valid.add((x, y))
- if char != '.':
- special_locations[(x, y)] = char
-
-
- # generate travel graph from every starting point to every other point via BFS
- graph = {}
- steps = [(0, 1), (0, -1), (1, 0), (-1, 0)]
- for A in special_locations:
- seen = {A}
- boundary = {A}
- locations_pending = set(special_locations) - seen
- for n_steps_taken in itertools.count(1):
- boundary = {(x + dx, y + dy) for x, y in boundary for dx, dy in steps}
- boundary &= valid - seen
- seen.update(boundary)
- for B in boundary & locations_pending:
- locations_pending -= {B}
- graph[special_locations[A], special_locations[B]] = n_steps_taken
- if not locations_pending:
- break
-
-
- # use map to determine routes
- z = '0'
- not_z = set(special_locations.values()) - {z}
- calc = lambda combo: sum(graph[a, b] for a, b in zip(combo, combo[1:]))
- ans1 = min(calc((z, *combo)) for combo in itertools.permutations(not_z))
- ans2 = min(calc((z, *combo, z)) for combo in itertools.permutations(not_z))
|