Project Euler 18/67: Maximum Path Sum The complete problem definition can be summarized as "find the largest sum of for paths from the top to the bottom of a triangle of integers".  I decided to read the triangle in from a file which can be found here.

My solution

#!/usr/bin/python
"""chicks' answer to Euler Project problem #18"""

import sys
import string
import re
import pprint

# read command line
argcount = len(sys.argv)
if argcount &lt;= 1:
    raise ValueError("missing filename on command line")
triangle_filename = sys.argv[1]
print str(argcount) + " arguments: " + triangle_filename

# read file
with open(triangle_filename, "r") as triangle_file:
    lines = triangle_file.readlines()
    print str(len(lines)) + " lines read"

triangle = []
for y in lines:
    y = string.strip(y)
    fields = re.split(r'\s+', y)
    int_fields = []
    for f in fields:
        int_fields.append(int(f))
    triangle.insert(0, int_fields)
    c = len(fields)

pretty = pprint.PrettyPrinter(indent=4)
#pretty.pprint(triangle)

rows = len(triangle) - 1
for z in range(0, rows):
    row = triangle[z]
    pretty.pprint(row)

    entries = len(row) - 1
    for y in range(0, entries):
        a = row[y]
        b = row[y + 1]
        #print "comparing " + str(a) + " and " + str(b)
        adder = 0
        if a &gt;= b:
            adder = a
        else:
            adder = b

        triangle[z + 1][y] += adder


answer = str(triangle[rows][0])
print "ANSWER:" + answer


Desired Focus

I left performance out because I'm more interested in having pythonicly correct and maintainable code than squeezing out a few ms.  I have run this through pylint and fixed everything it suggested.  I am still a beginner at python so I'm presuming there are more pythonic ways to do some of this.
High-level comments:


There are several print statements left in this file which look like they were in for debugging purposes. Maybe useful to you, but means nothing to me when I’m running the file. These should be commented out, or (since you’re using source control) removed entirely.
There are no comments in this file. That makes it quite hard to follow what’s going on – even if this is a simple problem that you understand well, that won’t be the case when you come to re-read this in six months.

Explain why the code is written this way, and how the program structures relate back to the original problem. It makes it much easier to review and improve.
Everything runs at the top-level. You should break some of this down into functions – it will make the code easier to reuse and follow.


A few smaller suggestions:


On line 24, you’re using regexes to split a line on whitespace, but Python already has a string method split() that does this for you.

You can rewrite these few lines as:

for line in lines:
    fields = line.strip().split()




Notice that I’m also calling the strip() method directly on line, and I’ve renamed the loop variable to make it clearer what I’m doing.
On lines 25–7, a common antipattern:

int_fields = []
for f in fields:
    int_fields.append(int(f))




It’s cleaner and more Pythonic to do this with a list comprehension:

int_fields = [int(f) for f in fields]




Note also that you store the value of len(fields) in a variable here – but then never actually use it.
In lines 35-6, you have a common Python antipattern:

for z in range(0, rows):
    row = triangle[z]




It’s always better to iterate over the items directly, i.e. for row in triangle. In this case you’re actually using z further down, so you should use enumerate():

for idx, row in enumerate(triangle):
    # do stuff with idx and row



On lines 40–50, there are several problems:


You don’t need to initialise the variable adder to 0.
You can get its value in a single line:

adder = max(a, b)

The names a and b are not very meaningful, and are only used once. It would be cleaner to write this as:

triangle[z+1][y] += max(row[y], row[y+1])


You should also rename y and z to be more meaningful.

You’re calling range(0, x) in several places. Since it defaults to a start of 0, you can drop the first argument to reduce visual noise: range(x).