|
#!/usr/bin/python |
|
|
|
import pprint |
|
import sys |
|
import re |
|
|
|
RECORD = re.compile('^(\w)\s+(\w)\s+(\d+)$') |
|
|
|
|
|
def readnodes(filename): |
|
for line in open(filename, 'rb'): |
|
for match in RECORD.finditer(line): |
|
start, end, cost = match.group(1, 2, 3) |
|
yield (start, end), int(cost) |
|
|
|
|
|
def findStartingVectors(vectors, startpoint): |
|
for edge, weight in vectors: |
|
if edge[0] == startpoint: |
|
yield edge, weight |
|
|
|
|
|
def findMatchingVectors(vectors, start, end): |
|
match = vectors.get((start, end), None) |
|
return ((start, end), match) if match is not None else (None, None) |
|
|
|
|
|
def sortVectorsByWeight(vectors): |
|
""" Assumes a list of similar model as `readnodes` yields; |
|
vectors = [ ((start, end), weight), ... ] |
|
""" |
|
return sorted(vectors, key = lambda x: x[1]) |
|
|
|
|
|
def iter_group(basedata, size = 2): |
|
_current = basedata[0:size] |
|
yield _current[:] |
|
for v in basedata[size:]: |
|
_current.pop(0) |
|
_current.append(v) |
|
yield _current[:] |
|
|
|
|
|
def calculatePathCost(vectors, path): |
|
cost = 0 |
|
for step in iter_group(path, 2): |
|
vector = findMatchingVectors(vectors, step[0], step[1]) |
|
cost = cost + vector[1] |
|
return cost |
|
|
|
|
|
|
|
|
|
def findpath(start, end, vectors, limit = 10): |
|
pathqueue = [] |
|
pathtemp = [ start ] |
|
|
|
pathqueue.append(pathtemp[:]) # enqueue the current path :) |
|
|
|
while len(pathqueue) and (limit > 0): |
|
pathtemp = pathqueue.pop(0) |
|
_last = pathtemp[-1] |
|
|
|
if _last == end: |
|
limit = limit - 1 |
|
yield pathtemp, calculatePathCost(vectors, pathtemp) |
|
|
|
else: |
|
_vectorlist = findStartingVectors(vectors.iteritems(), _last) |
|
for edge, weight in sortVectorsByWeight(_vectorlist): |
|
pathqueue.append(pathtemp + [ edge[1] ]) |
|
|
|
|
|
def main(args): |
|
vectors = dict(readnodes(args[0])) |
|
start = 'A' if len(args) < 2 else args[1] |
|
end = 'Z' if len(args) < 3 else args[2] |
|
paths = sorted(findpath(start, end, vectors), key = lambda x: x[1]) |
|
pprint.pprint(paths) |
|
|
|
if __name__ == '__main__': |
|
main(sys.argv[1:]) |