day 23 cleanup part 1
parent
7c2e376938
commit
d3d175a038
64
day23/sol.py
64
day23/sol.py
|
@ -4,11 +4,7 @@ map = []
|
||||||
for line in input:
|
for line in input:
|
||||||
map.append(list(line.strip()))
|
map.append(list(line.strip()))
|
||||||
|
|
||||||
# construct a graph
|
# find points where the path forks
|
||||||
for i,c in enumerate(map[0]):
|
|
||||||
if c == '.':
|
|
||||||
start = (i,0)
|
|
||||||
break
|
|
||||||
|
|
||||||
def neighbors(x,y):
|
def neighbors(x,y):
|
||||||
n = []
|
n = []
|
||||||
|
@ -31,7 +27,9 @@ for i in range(len(map)):
|
||||||
if len(n) not in (0,2):
|
if len(n) not in (0,2):
|
||||||
spots.append((j,i))
|
spots.append((j,i))
|
||||||
|
|
||||||
def reachable(start,spots):
|
# construct a graph of paths between fork points
|
||||||
|
|
||||||
|
def find_paths(start,spots):
|
||||||
q = [(0,start)]
|
q = [(0,start)]
|
||||||
dist = {}
|
dist = {}
|
||||||
r = []
|
r = []
|
||||||
|
@ -53,11 +51,30 @@ def reachable(start,spots):
|
||||||
|
|
||||||
G = {}
|
G = {}
|
||||||
for p in spots:
|
for p in spots:
|
||||||
G[p] = reachable(p,spots)
|
G[p] = find_paths(p,spots)
|
||||||
|
|
||||||
print(G)
|
print(G)
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
def topo(G, start):
|
def topo(G, start):
|
||||||
t = []
|
t = []
|
||||||
seen = set()
|
seen = set()
|
||||||
|
@ -66,7 +83,7 @@ def topo(G, start):
|
||||||
if n in seen:
|
if n in seen:
|
||||||
return
|
return
|
||||||
if n in tmp:
|
if n in tmp:
|
||||||
raise Exception("cycle with %s %s" % (repr(n),tmp))
|
raise Exception("cycle with %s %s" % (n,tmp))
|
||||||
tmp.add(n)
|
tmp.add(n)
|
||||||
for _, p in G[n]:
|
for _, p in G[n]:
|
||||||
visit(p)
|
visit(p)
|
||||||
|
@ -80,36 +97,13 @@ def topo(G, start):
|
||||||
print("topo=",topo(G,start))
|
print("topo=",topo(G,start))
|
||||||
|
|
||||||
|
|
||||||
dist = {n:float('inf') for n in G}
|
dist = {n: float('-inf') for n in G}
|
||||||
pred = {}
|
|
||||||
dist[start] = 0
|
dist[start] = 0
|
||||||
T = topo(G, start)
|
T = topo(G, start)
|
||||||
for u in T:
|
for u in T:
|
||||||
for n,v in G[u]:
|
for n,v in G[u]:
|
||||||
w = -n
|
if dist[v] < dist[u] + n:
|
||||||
if dist[v] > dist[u] + w:
|
dist[v] = dist[u] + n
|
||||||
dist[v] = dist[u] + w
|
|
||||||
pred[v] = u
|
|
||||||
|
|
||||||
print(dist)
|
print(dist)
|
||||||
print(-min(dist.values()))
|
print(max(dist.values()))
|
||||||
|
|
||||||
#import astar
|
|
||||||
#def goal(state):
|
|
||||||
# x,y = state
|
|
||||||
# return y == len(map)-1
|
|
||||||
#
|
|
||||||
#M = max(n for p in G for n,_ in G[p])
|
|
||||||
#
|
|
||||||
#def nb(state):
|
|
||||||
# p = state
|
|
||||||
# for n,q in G[p]:
|
|
||||||
# yield 1+M-n, q
|
|
||||||
#
|
|
||||||
#n, g, path = astar.search(start, goal, nb)
|
|
||||||
#print(g,path)
|
|
||||||
#t = 0
|
|
||||||
#for p, q in zip(path, path[1:]):
|
|
||||||
# t += sum(n for n,r in G[p] if r == q)
|
|
||||||
#
|
|
||||||
#print(t)
|
|
||||||
|
|
Loading…
Reference in New Issue