From d3d175a038c66cedc11316ea7c7d62504d392ce7 Mon Sep 17 00:00:00 2001 From: Andrew Ekstedt Date: Sat, 23 Dec 2023 08:35:10 +0000 Subject: [PATCH] day 23 cleanup part 1 --- day23/sol.py | 68 ++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/day23/sol.py b/day23/sol.py index d830d2d..babca62 100644 --- a/day23/sol.py +++ b/day23/sol.py @@ -4,11 +4,7 @@ map = [] for line in input: map.append(list(line.strip())) -# construct a graph -for i,c in enumerate(map[0]): - if c == '.': - start = (i,0) - break +# find points where the path forks def neighbors(x,y): n = [] @@ -31,7 +27,9 @@ for i in range(len(map)): if len(n) not in (0,2): spots.append((j,i)) -def reachable(start,spots): +# construct a graph of paths between fork points + +def find_paths(start,spots): q = [(0,start)] dist = {} r = [] @@ -53,11 +51,30 @@ def reachable(start,spots): G = {} for p in spots: - G[p] = reachable(p,spots) - + G[p] = find_paths(p,spots) + 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): t = [] seen = set() @@ -66,7 +83,7 @@ def topo(G, start): if n in seen: return if n in tmp: - raise Exception("cycle with %s %s" % (repr(n),tmp)) + raise Exception("cycle with %s %s" % (n,tmp)) tmp.add(n) for _, p in G[n]: visit(p) @@ -80,36 +97,13 @@ def topo(G, start): print("topo=",topo(G,start)) -dist = {n:float('inf') for n in G} -pred = {} +dist = {n: float('-inf') for n in G} dist[start] = 0 T = topo(G, start) for u in T: for n,v in G[u]: - w = -n - if dist[v] > dist[u] + w: - dist[v] = dist[u] + w - pred[v] = u - -print(dist) -print(-min(dist.values())) + if dist[v] < dist[u] + n: + dist[v] = dist[u] + n -#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) +print(dist) +print(max(dist.values()))