You mentioned in the comments that the size of the triangle is hard-coded into the code. The very first thing you should do is make this a variable which you declare at the start of your code. (In many other languages, this would be a constant). You also use the number 100 in line 5. If this is supposed to be one more than the number of lines, it should be defined in terms of the same constant, so that the two can be changed in the same place. (Edit: I see from the problem that 99 and 100 are not related. If you had had two variables, NUM_ROWS and MAX_VALUE defined at the top, the meaning of each of the numbers would have been clear to me immediately.)
A level of sophistication above, but still very easy, would be to give some reasonable error to a user like @JanneKarila who has used the wrong number of lines. This might be overkill for code that you and only you are ever going to run, but a one-line check with an error message might help you if you debug using the wrong file (it's easy to spend hours taking your program to pieces and forget to check which input you are using), and it makes life much easier for anyone else who wants to try it.
Another stylistic thing which can be very important - for me the hardest part of your code to read is the lines that start pq.append
. For each expression on these lines, I have to glance several times back to the definition of priorityQueue
and the comment with it to find out exactly what each element of your tuple represents. If you defined a very simple class, then rather than m[3] + m[1]
I would see m.totalScore + m.currentValue
. Just doing this by itself would make the code easier to read (these two lines are going to be among the most important to debug). It might be the case that your class could also have methods or 'smart' constructors which could do some of the trickier work and make your inner loop more readable.
Ultimately, I don't think it is realistic to 'optimize' this program to be able to solve a problem of the same size as Euler problem 67. If you try and store the lists inside your tuples more efficiently you might get to 18, 19 or 20 levels before crashing. However, the fundamental flaw of the algorithm is that you are going to store almost every path in your list in priorityQueue
, with probably up to half of them present at any one time. This is unworkable from a memory perspective (the number of paths grows very rapidly as you increase the size of the triangle) and also from a run time perspective (if you try and measure the time taken for levels up to 17 you should be able to see this). Using the a* algo has made it a little bit less obvious to see that you are doing exactly what the Project Euler page recommends against - trying all paths. (EDIT: I didn't run the code. Turns out a stack overflow and not running out of memory is the reason for your crash. If you get rid of the recursion as suggested in @JanneKarila's answer, you will probably make it to quite a few more levels before running out of memory, but still nowhere near 100. The comments below still apply.)
You need to go back to the drawing board and think of another way to solve the problem. A good starting point is to try and solve a few small triangles by hand, and see what methods you come across. Don't worry though - writing this program has given you a chance to learn both about an interesting algo and some things about programming, which I'm sure have made it worthwhile.
if len(m[2]) is 99:
If you want to try it with 4 lines, you have to change the number to 3 from 99. Sorry for that bit that I left out. \$\endgroup\$