Reputation: 761
First things first, here's my code:
row_1 = [3]
row_2 = [7, 4]
row_3 = [2, 4, 6]
row_4 = [8, 5, 9, 3]
for element in row_3:
key = row_3.index(element)
row_3[key] = element + max(row_4[key], row_4[key + 1])
for element in row_2:
key = row_2.index(element)
row_2[key] = element + max(row_3[key], row_3[key + 1])
for element in row_1:
key = row_1.index(element)
row_1[key] = element + max(row_2[key], row_2[key + 1])
print(row_1)
This code works, so far. As you may notice, there is quite a bit of repitition, and I was wondering how I could compress it. Ideally, I would like something like
for element in row_x:
key = row_x.index(element)
row_x[key] = element + max(row_(x+1)[key], row_(x+1)[key + 1])
I know that this is completely wrong, but it was just what I had in my head. I would greatly appreciate all insights.
Oh, by the way, this code maxizes the sum of the two adjacent numbers in a pyramid (see here: http://projecteuler.net/problem=18)
Upvotes: 1
Views: 90
Reputation: 27216
Here is exactly the translation of what you say(eliminating loop repetition):
l = [[3],
[7, 4],
[2, 4, 6],
[8, 5, 9, 3]]
for row in range(len(l)-2, -1, -1)
for key, element in enumerate(l[row]):
l[row][key] = element + max(l[row+1][key], l[row+1][key+1])
print(l[0][0])
Your mistake was storing the triangle on separate data structrures, just use a nested list and iterate over it.
Also, if you need both the element and the index when iterating over an iterable, use enumerate
function.
range(start, end, step)
iterates from start to end(without including end), and step is the increment, range(range(len(l)-2, -1, -1)
iterates like "len(l)-2
-> len(l)-3
-> ... -> 1
-> 0
". Note that we want 0
to be included, so we pass -1
as a parameter. A good mnemonic for both the range
function and slices is "you pass the first parameter you want, and the first parameter you don't want".Like:
In [1]: a, b, *c, d = range(5)
In [2]: a, b, d
Out[2]: (0, 1, 4)
In [3]: c
Out[3]: [2, 3]
And you can use the unpacking in loops too:
In [1]: l = ["enumerate", "is", "a", "nice", "builtin"]
In [2]: list(enumerate(l))
Out[2]: [(0, 'enumerate'), (1, 'is'), (2, 'a'), (3, 'nice'), (4, 'builtin')]
In [3]: for i, v in enumerate(l):
...: print(i, "->", v)
...:
0 -> enumerate
1 -> is
2 -> a
3 -> nice
4 -> builtin
Upvotes: 2
Reputation: 605
This answer is based on the problem in the link, not on your code, so it might not be of any use to you.
Sounds to me like a "reverse" Dijkstra's algorithm problem (Dijkstra's algorithm usually looks for the shortest path, not the maximum path, and is usually applied to a graph, but it can be adjusted for your pyramid.)
Dijkstra's looks like this:
Assign to every node a tentative distance value: set it to zero for our initial node and to infinity for all other nodes.
Mark all nodes unvisited. Set the initial node as current. Create a set of the unvisited nodes called the unvisited set consisting of all the nodes.
For the current node, consider all of its unvisited neighbors and calculate their tentative distances. Compare the newly calculated tentative distance to the current assigned value and assign the smaller one. For example, if the current node A is marked with a distance of 6, and the edge connecting it with a neighbor B has length 2, then the distance to B (through A) will be 6 + 2 = 8. If B was previously marked with a distance greater than 8 then change it to 8. Otherwise, keep the current value.
When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again.
If the destination node has been marked visited (when planning a route between two specific nodes) or if the smallest tentative distance among the nodes in the unvisited set is infinity (when planning a complete traversal; occurs when there is no connection between the initial node and remaining unvisited nodes), then stop. The algorithm has finished. Select the unvisited node that is marked with the smallest tentative distance, and set it as the new "current node" then go back to step 3.
These steps are from Wikipedia's page on Dijkstra's algorithm
Upvotes: 0
Reputation: 1075
Try putting all the rows into a list, then reverse iterate through them:
row_1 = [3]
row_2 = [7, 4]
row_3 = [2, 4, 6]
row_4 = [8, 5, 9, 3]
rows = [row_1, row_2, row_3, row_4]
for row_index, row in reversed(list(enumerate(rows[:-1]))):
for key, elem in enumerate(row):
lower_row = rows[row_index+1]
row[key] = elem + max(lower_row[key], lower_row[key+1])
print rows[0]
Upvotes: 1