2
\$\begingroup\$

This code loads the data for Project Euler problem 18, but I feel that there must be a better way of writing it. Maybe with a double list comprehension, but I couldn't figure out how I might do that. It is a lot more difficult since the rows to split up are not uniform in length.

def organizeVar():
    triangle = "\
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"
    triangle = [row for row in list(triangle.split(","))]
    adjTriangle = []
    for row in range(len(triangle)):
        adjTriangle.append([int(pos) for pos in triangle[row].split(" ")])
    return adjTriangle

The code converts this string into a list of lists of ints where the first list contains 75, the second list 95, 64, the third list 17, 47, 82, the fourth list 18, 35, 87, 10 and so on to the bottom row.

\$\endgroup\$
1
  • \$\begingroup\$ Also there's no need to list() the trianle.split(","), split will always return a list. \$\endgroup\$ – Attila O. Feb 21 '13 at 13:28
4
\$\begingroup\$
  1. Avoid the need to escape the newlines by using Python's triple-quoted strings that can extend over multiple lines:

    triangle = """
    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
    """
    
  2. Use the strip method to remove the whitespace at the beginning and end.

  3. Use the splitlines method to split the string into lines.

  4. Use the split method to split each line into words.

  5. Use the built-in map function to call int on each word.

Putting that all together in a list comprehension:

>>> [map(int, line.split()) for line in triangle.strip().splitlines()]
[[75],
 [95, 64],
 [17, 47, 82],
 [18, 35, 87, 10],
 [20, 4, 82, 47, 65],
 [19, 1, 23, 75, 3, 34],
 [88, 2, 77, 73, 7, 63, 67],
 [99, 65, 4, 28, 6, 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, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31],
 [4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23]]

In Python 3 map doesn't return a list, so you have to write

[list(map(int, line.split())) for line in triangle.strip().splitlines()]

instead. If you prefer a double list comprehension you can write it like this:

[[int(word) for word in line.split()] for line in triangle.strip().splitlines()]

but the version with map is shorter, and, I think, clearer.

\$\endgroup\$
5
  • \$\begingroup\$ Wow, that is awesome. :) \$\endgroup\$ – Jack J Feb 21 '13 at 12:51
  • \$\begingroup\$ Using Python 3.3 I haven't quite gotten this to work. The closest I get while trying to use the map form is:[line.strip().split(' ') for line in triangle.strip().splitlines()]. This returns everything correctly except ints. When I try to use map, as in map(int, line.strip().split(' ') or even just map(int, line.split()) I get a bunch of these: <map object at 0x0000000002F469E8>. \$\endgroup\$ – Jack J Feb 21 '13 at 22:46
  • \$\begingroup\$ See revised answer. (Also, it's usually better to write .split() instead of .split(" ") unless you really want 'a  b' to split into ['a', '', 'b'].) \$\endgroup\$ – Gareth Rees Feb 21 '13 at 22:52
  • \$\begingroup\$ I think also, if you try to put this into a function, you have to strip it twice; once for the two outside lines, and once for the indentation. If you don't, map will try to turn the extra space into ints, but will give an error when that happens... I didn't read your above comment in time. Alternatively I could just do that .split() to make it work. Thanks. \$\endgroup\$ – Jack J Feb 21 '13 at 23:03
  • \$\begingroup\$ No, that's not necessary: ' a b '.split()['a', 'b'] \$\endgroup\$ – Gareth Rees Feb 21 '13 at 23:07

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.