#!/usr/bin/python3 import glob import os import sys TRANSFER_TIME = 2 class Line (dict): def __init__(self, name): self.name = name self.stations = [] def get_next_freq(L, p, tm, rev=False) : off = L.stations[p][1] o = "offset" if rev : off = L.stations[-1][1] - L.stations[p][1] o = "roffset" k = (L[o] + off) % L["frequency"] while k < tm : k += L["frequency"] return k class Station (dict) : def __init__(self, code, line, pos): self.code = code self.lines = [(line,pos)] def getlines(self): return [i[0] for i in self.lines] def nexttrains(self, tm): # find next trains departing at stn around tm trains = [] for l,p in self.lines : L = lines[l] if p < L.nstations-1 : trains.append((get_next_freq(L,p,tm), l,False)) if L["rev"] and p > 0: trains.append((get_next_freq(L,p,tm,True), l,True)) trains.sort(key=lambda x: x[1]) return trains def reachablestations(self, tm, exclude=[]) : stns = [] for l,p in self.lines : if l in exclude: continue L = lines[l] if p < L.nstations-1 : dep = get_next_freq(L,p,tm) ors = L.stations[p] for k in range(p+1,L.nstations) : stn = L.stations[k] arr = stn[1] - ors[1] + dep stns.append((stn[0],dep,arr,L.name,False)) if L["rev"] and p > 0: dep = get_next_freq(L,p,tm,True) ors = L.stations[p] for k in range(0,p) : stn = L.stations[k] arr = ors[1] - stn[1] + dep stns.append((stn[0],dep,arr,L.name,True)) stns.sort(key=lambda x: x[2]) return stns lines = {} stations = {} for k in glob.glob("lines/*") : if k.endswith("~") : continue f = open(k,"r") l = Line(os.path.basename(k)) for j in f : o = j.split() if j.startswith(" ") : l[o[0].lower()] = int(o[1]) else : l.stations.append((o[0],int(o[1]))) if not o[0] in stations : stations[o[0]] = Station(o[0], l.name, len(l.stations)-1) else : stations[o[0]].lines.append((l.name, len(l.stations)-1)) l.nstations = len(l.stations) lines[l.name] = l time = 10 start = sys.argv[1] end = sys.argv[2] end = sys.argv[2] if len(sys.argv) > 3 : TRANSFER_TIME = int(sys.argv[3]) #print(stations["Mar"].reachablestations(49)) #print(stations["MoC"].reachablestations(49)) Q = stations[start].reachablestations(time) klines = stations[start].getlines() prev = {} d = {} for k in Q : prev[k[0]] = (start, k[1], k[2],k[3],k[4]) d[k[0]] = k[2] while Q : u = Q.pop(0) if u[0] == end : break stu = stations[u[0]] if len(stu.lines)>1 : R = stu.reachablestations(u[2]+TRANSFER_TIME,klines) for k in R : if k[0] not in d or k[2] < d[k[0]] : prev[k[0]] = (u[0], u[1],u[2],u[3],u[4]) d[k[0]] = k[2] Q.append(k) klines += stu.getlines() Q.sort(key=lambda i: i[2]) translist = [] while True : translist.insert(0,u) u = prev[u[0]] if u[0] == start : break print("Number of Changes: %d, Time needed: %d minutes" % (len(translist)-1, translist[-1][2]-translist[0][1])) for j in translist : print("Take line %s to %s at :%02d, arrival :%02d" % (j[3],j[0],j[1] %60,j[2] %60))