2023-12-23 06:04:49 +00:00
|
|
|
import sys
|
|
|
|
input = sys.stdin
|
|
|
|
map = []
|
|
|
|
for line in input:
|
|
|
|
map.append(list(line.strip()))
|
|
|
|
|
2023-12-23 08:35:10 +00:00
|
|
|
# find points where the path forks
|
2023-12-23 06:04:49 +00:00
|
|
|
|
|
|
|
def neighbors(x,y):
|
|
|
|
n = []
|
|
|
|
c = map[y][x]
|
|
|
|
for i,j in [(y-1,x),(y+1,x),(y,x-1),(y,x+1)]:
|
|
|
|
if c == '<' and not j < x: continue
|
|
|
|
if c == '>' and not j > x: continue
|
|
|
|
if c == '^' and not i < y: continue
|
|
|
|
if c == 'v' and not i > y: continue
|
|
|
|
if 0 <= i < len(map) and 0 <= j < len(map[i]):
|
|
|
|
if map[i][j] != '#':
|
|
|
|
n.append((j,i))
|
|
|
|
return n
|
|
|
|
|
|
|
|
spots = []
|
|
|
|
for i in range(len(map)):
|
|
|
|
for j in range(len(map[i])):
|
|
|
|
if map[i][j] == '.':
|
|
|
|
n = neighbors(j,i)
|
|
|
|
if len(n) not in (0,2):
|
|
|
|
spots.append((j,i))
|
|
|
|
|
2023-12-23 08:35:10 +00:00
|
|
|
# construct a graph of paths between fork points
|
|
|
|
|
|
|
|
def find_paths(start,spots):
|
2023-12-23 06:04:49 +00:00
|
|
|
q = [(0,start)]
|
|
|
|
dist = {}
|
|
|
|
r = []
|
|
|
|
while q:
|
|
|
|
q.sort()
|
|
|
|
n,(x,y) = q.pop(0)
|
|
|
|
if (x,y) in dist:
|
|
|
|
continue
|
|
|
|
dist[x,y] = n
|
|
|
|
#print(x,y,neighbors(x,y))
|
|
|
|
if (x,y) in spots and (x,y) != start:
|
|
|
|
r.append((n,(x,y)))
|
|
|
|
else:
|
|
|
|
for j,i in neighbors(x,y):
|
|
|
|
if (j,i) not in dist:
|
|
|
|
q.append((n+1,(j,i)))
|
|
|
|
|
|
|
|
return r
|
|
|
|
|
|
|
|
G = {}
|
|
|
|
for p in spots:
|
2023-12-23 08:35:10 +00:00
|
|
|
G[p] = find_paths(p,spots)
|
|
|
|
|
2023-12-23 06:04:49 +00:00
|
|
|
print(G)
|
|
|
|
|
|
|
|
|
2023-12-23 08:35:10 +00:00
|
|
|
# find start position
|
|
|
|
|
|
|
|
for i,c in enumerate(map[0]):
|
|
|
|
if c == '.':
|
|
|
|
start = (i,0)
|
|
|
|
break
|
|
|
|
|
|
|
|
# algorithm for finding the shortest path between points in a
|
|
|
|
# a weighted directed acyclic graph
|
|
|
|
#
|
|
|
|
# from wikipedia:
|
|
|
|
# https://en.wikipedia.org/w/index.php?title=Topological_sorting&oldid=1188428695#Application_to_shortest_path_finding
|
|
|
|
#
|
|
|
|
# this is a variant of the bellman-ford and shortest path faster algorithms
|
|
|
|
# except we can take some shortcuts because the graph is acyclic
|
|
|
|
#
|
|
|
|
# we implicitly invert the weights of the graph so that, in effect,
|
|
|
|
# it finds the longest path instead
|
|
|
|
|
2023-12-23 06:04:49 +00:00
|
|
|
def topo(G, start):
|
|
|
|
t = []
|
|
|
|
seen = set()
|
|
|
|
tmp = set()
|
|
|
|
def visit(n):
|
|
|
|
if n in seen:
|
|
|
|
return
|
|
|
|
if n in tmp:
|
2023-12-23 08:35:10 +00:00
|
|
|
raise Exception("cycle with %s %s" % (n,tmp))
|
2023-12-23 06:04:49 +00:00
|
|
|
tmp.add(n)
|
|
|
|
for _, p in G[n]:
|
|
|
|
visit(p)
|
|
|
|
tmp.remove(n)
|
|
|
|
seen.add(n)
|
|
|
|
t.append(n)
|
|
|
|
visit(start)
|
|
|
|
t.reverse()
|
|
|
|
return t
|
|
|
|
|
|
|
|
print("topo=",topo(G,start))
|
|
|
|
|
|
|
|
|
2023-12-23 08:35:10 +00:00
|
|
|
dist = {n: float('-inf') for n in G}
|
2023-12-23 06:04:49 +00:00
|
|
|
dist[start] = 0
|
|
|
|
T = topo(G, start)
|
|
|
|
for u in T:
|
|
|
|
for n,v in G[u]:
|
2023-12-23 08:35:10 +00:00
|
|
|
if dist[v] < dist[u] + n:
|
|
|
|
dist[v] = dist[u] + n
|
2023-12-23 06:04:49 +00:00
|
|
|
|
2023-12-23 08:35:10 +00:00
|
|
|
print(dist)
|
|
|
|
print(max(dist.values()))
|