#!/usr/bin/env python3 import sys, math import numpy as np def dijkstra(graph, v, a): Q = [n for n in graph.keys()] lq = len(Q) while len(Q) > 0: u = min([u for u in Q], key=lambda x: a[x]) Q.remove(u) for vo in graph[u]: if vo in Q: distance_update(graph, u,vo,a,v) return v, a def distance_update(g, u, vo, a, v): dist = 1 if vo[2] == u[2] else 1000 alt = a[u] + dist # joining the sets does not work because we never remove the older nodes! if alt <= a[vo]: if alt < a[vo]: v[vo] = set([]) a[vo] = alt v[vo].add(u) v[vo] = v[vo].union(set(v[u])) def count_set(edges, lab): edg = set([]) for e in edges: edg.add((e[0], e[1])) lab[e[1]][e[0]] = 'O' return edg if __name__ == '__main__': lab = [list(line.strip('\n')) for line in open(sys.argv[1])] rot90 = {(0,-1): [(-1,0),(1,0)], (1,0): [(0,-1),(0,1)], (0,1): [(1,0),(-1, 0)], (-1,0): [(0,1),(0,-1)]} start = (1, len(lab)-2, (1,0)) end = (len(lab[0])-2, 1, (0,-1)) graph = {} distance = {} pred = {} for y, l in enumerate(lab): for x, f in enumerate(lab[y]): if f == '#': continue for d in [(0,1), (0,-1), (1,0), (-1,0)]: distance[(x,y,d)] = math.inf pred[(x,y,d)] = set([]) graph[(x,y,d)] = [] for d1 in rot90[d]: if not lab[y+d1[1]][x+d1[0]] == '#': graph[(x,y,d)].append((x,y,d1)) if lab[y+d[1]][x+d[0]] != '#': graph[(x,y,d)].append((x+d[0], y+d[1], d)) distance[start] = 0 v1, a1 = dijkstra(graph, pred, distance) d1 = count_set(v1[end], lab) # challenge 1 res1 = a1[end] print(f"challenge 1:\n{res1}\n") # challenge 2, needed some reddit help again... d1.add((end[0],end[1])) d1.add((start[0], start[1])) res2 = len(d1) print(f"challenge 2:\n{res2}") for line in lab: print(''.join(line))