## Wednesday, December 3, 2008

### Project Euler p83 and Dijkstra's algorithm

Problem definition:
-----------------------------------------------------------
In the 5 by 5 matrix below, the minimal path sum from the top left to the bottom right, by moving left, right, up, and down, is indicated in bold and is equal to 2297.

131 673 234 103 18
201 96  342 965 150
630 803 746 422 111
537 699 497 121 956
805 732 524 37  331

Find the minimal path sum, in matrix.txt , a 31K text file containing a 80 by 80 matrix, from the top left to the bottom right by moving left, right, up, and down.

-----------------------------------------------------------
Problem is solved with the help of Dijkstra's algorithm
Answer is calculated in a 2.5 seconds. Also it is not optimized,- computes distances to all nodes in network. To speed up - when we find target node - we can only check these nodes which distance is less than target node distance. Also this code suits equally well for solving project euler problem no 81 - only change shortestpath() function parameter "directions". And finally - this solution shows shortest path visually,- prints it to screen. Program code:

`import time as tdef readmatrix(filename):    f=open(filename, 'r')    m=[map(lambda x: int(x),r.strip().split(",")) for r in f.readlines()]    return mdef nextcell(dctresults):    minw = 10000000    mink = None    for k in dctresults:        if not dctresults[k]:            if dctresults[k] < minw:                minw = dctresults[k]                mink = k    return minkdef analyzecell(lstmat, tupcell, lstdirec, dctresults):    i,j = tupcell    for dr in lstdirec:        di,dj = dr        if (i+di) in range(len(lstmat)) and (j+dj) in range(len(lstmat)):            if not dctresults.has_key((i+di,j+dj)):                dctresults[(i+di,j+dj)] = [(i,j),dctresults[(i,j)]+lstmat[i+di][j+dj],False]            else:                oldw = dctresults[(i+di,j+dj)]                neww = dctresults[(i,j)]+lstmat[i+di][j+dj]                if neww < oldw:                    dctresults[(i+di,j+dj)] = (i,j)                    dctresults[(i+di,j+dj)] = neww    dctresults[(i,j)] = Truedef shortestpath(filename, directions):    mat = readmatrix(filename)    results = {}    results[(0,0)] = [None,mat,False]    cell = nextcell(results)    while cell:        analyzecell(mat,cell,directions,results)        cell = nextcell(results)    return results, results[(len(mat)-1,len(mat)-1)], matdef showpath(res, inpmat):    print ' '+'-'*len(inpmat)+' '    pathcells = []    curc = (len(inpmat)-1,len(inpmat)-1)    while curc:        pathcells += [curc]        curc = res[curc]    for i in range(len(inpmat)):        s='|'        for j in range(len(inpmat)):            s+= '#' if (i,j) in pathcells else '.'        print s+'|'    print ' '+'-'*len(inpmat)+' 't1 = t.time()*1000resd, pathsum, mat = shortestpath('matrix.txt',[(-1,0),(+1,0),(0,-1),(0,+1)])t2 = t.time()*1000print 'Shortest path sum', pathsum, '; Calculation time is ', int(t2-t1), 'ms'showpath(resd, mat)`

Have fun with shortest path algorithms !!!