|
|
@@ -1,55 +1,40 @@ |
|
|
|
import random |
|
|
|
import heapq |
|
|
|
|
|
|
|
|
|
|
|
def solve(ns): |
|
|
|
heap = [(0, None, 0, d) for d in [1, 1j]] |
|
|
|
exhausted = set() |
|
|
|
while True: |
|
|
|
old_cost, _, old_pos, old_dir = heapq.heappop(heap) |
|
|
|
|
|
|
|
if old_pos == end: |
|
|
|
break |
|
|
|
|
|
|
|
key = old_pos, old_dir |
|
|
|
if key in exhausted: |
|
|
|
continue |
|
|
|
exhausted.add(key) |
|
|
|
|
|
|
|
for n in ns: |
|
|
|
new_pos = old_pos + old_dir * n |
|
|
|
if new_pos not in graph: |
|
|
|
break |
|
|
|
new_cost = old_cost + sum(graph[old_pos + i * old_dir] for i in range(1, n + 1)) |
|
|
|
|
|
|
|
heapq.heappush(heap, (new_cost, random.random(), new_pos, old_dir * 1j)) |
|
|
|
heapq.heappush(heap, (new_cost, random.random(), new_pos, old_dir / 1j)) |
|
|
|
return old_cost |
|
|
|
|
|
|
|
|
|
|
|
text = open(0).read() |
|
|
|
graph = { |
|
|
|
complex(x, y): int({'.': 1, '#': 10000}.get(val, val)) |
|
|
|
complex(x, y): int(val) |
|
|
|
for y, row in enumerate(text.splitlines()) |
|
|
|
for x, val in enumerate(row) |
|
|
|
} |
|
|
|
xmax = max(int(p.real) for p in graph) |
|
|
|
ymax = max(int(p.imag) for p in graph) |
|
|
|
end = complex(xmax, ymax) |
|
|
|
mapping = {1: '>', -1: '<', 1j: 'v', -1j: '^'} |
|
|
|
|
|
|
|
# a position mapped to the lowest effort taken to reach it |
|
|
|
edge = {(0, ''): (0, '')} |
|
|
|
exhausted = {} |
|
|
|
while end not in exhausted: |
|
|
|
pos = min(edge, key=edge.get) |
|
|
|
parent = edge.pop(pos) |
|
|
|
if pos[0] == end: |
|
|
|
break |
|
|
|
exhausted[pos] = parent |
|
|
|
for step in [1, -1, 1j, -1j]: |
|
|
|
# no reverse |
|
|
|
if pos[1] and pos[1][-1] == mapping[-step]: continue |
|
|
|
|
|
|
|
# turn condition |
|
|
|
bop = pos[1] + mapping[step] |
|
|
|
if len(bop) == 4 and len(set(bop)) == 1: continue |
|
|
|
|
|
|
|
adj = pos[0] + step, bop[-3:] |
|
|
|
|
|
|
|
# out of bounds check |
|
|
|
if adj[0] not in graph: continue |
|
|
|
|
|
|
|
# some positions are truly dead |
|
|
|
if adj in exhausted: continue |
|
|
|
|
|
|
|
score = parent[0] + graph[adj[0]], parent[1] + mapping[step] |
|
|
|
if adj not in edge: |
|
|
|
edge[adj] = score |
|
|
|
else: |
|
|
|
edge[adj] = min(edge[adj], score) |
|
|
|
|
|
|
|
|
|
|
|
def scorer(seq): |
|
|
|
pos = 0 |
|
|
|
out = 0 |
|
|
|
for char in seq: |
|
|
|
pos += {'>': 1, '<': -1, '^': -1j, 'v': 1j}[char] |
|
|
|
out += graph[pos] |
|
|
|
return out |
|
|
|
|
|
|
|
|
|
|
|
print(parent[1], scorer(parent[1])) |
|
|
|
test = '>>>v>>>^>>>vv>vv>vvv>vvv<vv>' |
|
|
|
print(test, scorer(test)) |
|
|
|
print(solve([1, 2, 3])) |
|
|
|
print(solve(list(range(4, 11)))) |