7
\$\begingroup\$

I use Project Euler to teach me programming and not to submit any results. As such I look up the expected return values to double check my solutions.

To organise my files I use the following folder structure:

main.py
\euler # The problem files
     __init__.py # empty
     e001.py
     e002.py
     ...
\input # Additional input files
     8.dat
     11.dat
     ...

My main.py file is the common entry point. It can either run all the solved examples so far or a specific one. This second option is added that I don't need to add an if __name__ == '__main__' guard in every file. The file looks as follows:

TOP_LEVEL = "euler"

def run_module(num):
    """Run specific Problem"""
    mod = importlib.import_module('%s.e%0.3i' % (TOP_LEVEL, num))

    start = time.time()
    ist = mod.run()
    print("  %5i | %6.3f |  %s  | %i" % \
(num, time.time() - start, "ox"[ist == mod.SOLL], ist))

if __name__ == '__main__':
    N_MAX = 67

    # Pre Header
    print('Problem |  Time  | x/o | Solution')
    print("--------+--------+-----+---------")

    global_time = time.time()

    # Run over all problems
    if len(sys.argv) == 2:
        run_module(int(sys.argv[1]))
    else:
        for num in range(1, N_MAX + 1):
            run_module(num)

    # End Header
    print("--------+--------+-----+---------")
    print("Total: %.3f s" % (time.time() - global_time))

I'll show now two example files to show the source files and how old code can be reused. e018.py:

"""By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.

3
7 4
2 4 6
8 5 9 3
That is, 3 + 7 + 4 + 9 = 23.

Find the maximum total from top to bottom of the triangle below"""

SOLL = 1074

def run(file = "input/18.dat"):
    # Parse File
    with open(file) as fid:
        tri = [[int(num) for num in line.split(' ')] for line in fid.read().split('\n')]

    # From bottom's up find the maximal value   
    for row in range(len(tri) - 2, -1, -1):
        for col in range(row + 1):
            tri[row][col] += max(tri[row + 1][col], tri[row + 1][col + 1])

    return tri[0][0]

and e067.py

"""By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.

3
7 4
2 4 6
8 5 9 3
That is, 3 + 7 + 4 + 9 = 23.

Find the maximum total from top to bottom of the triangle below"""

import e018

SOLL = 7273

def run(file = "input/67.dat"):
    # problem has been solved in set 18
    return e018.run(file = file)

Since this is the first time I tried to structure such a project, I'm quite sure there is plenty of room for optimization. I'm happy for any feedback I can get.

\$\endgroup\$
3
\$\begingroup\$

Use .format

Using % is considered old style, so:

print("  %5i | %6.3f |  %s  | %i".format(
    (num, time.time() - start, "ox"[ist == mod.SOLL], ist)))

Be generous with long variables names

For example ist is impossible to understand for me, solution is more natural

Don't abuse Code-Golf techniques

The line:

"ox"[ist == mod.SOLL]

is a well known Code-Golf trick that relies on implicit boolean to integer conversion that is equivalent to:

"x" if ist == mod.SOLL else "o"

please use the latter.

Use argparse

C-Style arguments such as sys.argv[1] should be avoided, I suggest argparse (help to get started here: https://stackoverflow.com/questions/7427101/dead-simple-argparse-example-wanted-1-argument-3-results)

Don't shadow built-ins

def run(file = "input/18.dat"):
    # Parse File
    with open(file) as fid:

file is a built-in, you should use file_ in your code.

Explode long lines

Divide the following lines in two please.

 tri = [[int(num) for num in line.split(' ')] for line in fid.read().split('\n')]
\$\endgroup\$
  • \$\begingroup\$ Thank you for this input. I definitely have to look into the .format since I still stick to c formatting all the time. I also started using argparse meanwhile and learned to like it. Once thing I'm myself not really certain about is the shadowing of the file variable. A better name might have been path anyway but is it really so bad to shadow a builtin for which nearly nobody is ever gonna call its constructor directly? Conserning the data structure I was also wondering if you had any input about that. \$\endgroup\$ – magu_ Jun 15 '15 at 16:18
  • \$\begingroup\$ @magu_ it is better not to, because, for example in an IDE file will change colour, and seeing an ordinary variable of another colour is distracting \$\endgroup\$ – Caridorc Jun 15 '15 at 16:19
  • \$\begingroup\$ Yes, I guess your right. \$\endgroup\$ – magu_ Jun 15 '15 at 18:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.