Problem 018

git-svn-id: file:///srv/svn/euler@44 e5f4c3ec-3c0c-11df-b522-21efaa4426b5
This commit is contained in:
Correl Roush 2010-04-12 21:06:47 +00:00
parent 3a59429f26
commit 63982f51a0
3 changed files with 115 additions and 0 deletions

96
e018.py Normal file
View file

@ -0,0 +1,96 @@
from e012 import triangle
class Vertex:
"""Holds information on each vertex in the triangle
The weight represents the weight of any edge between an adjacent vertex and
this one
"""
def __init__(self, value):
self.value = value
self.weight = 100 - self.value
self.min_distance = float('+inf')
self.previous_vertex = None
self.adjacent = []
def add_adjacent(self, vertex):
self.adjacent.append(vertex)
def __cmp__(self, other):
return cmp(self.min_distance, other.min_distance)
def __repr__(self):
return '{0} ({1})'.format(self.value, [a.value for a in self.adjacent])
class Triangle:
def __init__(self, vertex_data):
self.vertices = []
i = 0
row = 1
for v in vertex_data:
if (i >= triangle(row)):
row = row + 1
vertex = Vertex(v)
if row > 1:
# Find upwards adjacent vertices
above_row = self.vertices[triangle(row - 2):triangle(row - 1)]
total_this_row = triangle(row) - triangle(row - 1)
pos = i - triangle(row - 1) + 1
start = int((pos / float(total_this_row)) * len(above_row)) - 1
end = int(((pos + 1) / float(total_this_row)) * len(above_row))
adjacent = above_row[start if start >= 0 else 0:end]
for a in adjacent:
vertex.add_adjacent(a)
self.vertices.append(vertex)
i = i + 1
self.rows = row
if len(self.vertices) != triangle(self.rows):
raise Exception('Invalid vertex set')
def find_path(self):
"""Implementation of Dijkstra's algorithm"""
# Reset vertice info
for v in self.vertices:
v.min_distance = float('+inf')
v.previous_vertex = None
orig = Vertex(100)
orig.min_distance = 0
adjacent = self.vertices[triangle(self.rows - 1):]
for a in adjacent:
orig.add_adjacent(a)
Q = [orig] + [v for v in self.vertices]
while len(Q) > 0:
u = min(Q)
if u.min_distance == float('+inf'):
return False
Q.remove(u)
for v in u.adjacent:
distance = u.min_distance + v.weight
if distance < v.min_distance:
v.min_distance = distance
v.previous_vertex = u
return True
def get_path(self):
"""Returns the found path as a list of vertices, from the top of the
triangle to the bottom
"""
v = self.vertices[0]
path = [v]
for i in range(self.rows - 1):
v = v.previous_vertex
if not v:
raise Exception('Missing or incomplete path!')
path.append(v)
return path
if __name__ == '__main__':
vertex_data = []
with open('p018/triangle.txt', 'r') as f:
while True:
line = f.readline()
if not line:
break
vertex_data = vertex_data + [int(v) for v in line.split(' ')]
t = Triangle(vertex_data)
t.find_path()
path = t.get_path()
print 'Path', [v.value for v in path]
print 'Sum', sum([v.value for v in path])

4
p018/test.txt Normal file
View file

@ -0,0 +1,4 @@
3
7 4
2 4 6
8 5 9 3

15
p018/triangle.txt Normal file
View file

@ -0,0 +1,15 @@
75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23