15
\$\begingroup\$

I programmed Problem #22 from Project Euler in Python. It works but I want to know if it really is pythonic enough.

Using names.txt (right click and 'Save Link/Target As...'), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.

For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 × 53 = 49714.

What is the total of all the name scores in the file?

from itertools import count 

FILE = "e022.txt"
CHAR_OFFSET = ord('A') - 1

def parse(file):
    """Return the read in list"""
    with open(file) as fid:
        return fid.read().replace('"',"").split(',')

def score_name(name):
    """Returns the score of a single name"""
    return sum(ord(char) - CHAR_OFFSET for char in list(name))

def score_names(names):
    """Returns the score of the list"""
    return sum(ind*score_name(name) for (ind, name) in zip(count(1),sorted(names)))

if __name__ == "__main__":
    print(score_names(parse(FILE)))

Please feel free to critic me on it. One thing I wasn't sure about: In the file parser, did I need to make the with guard or is this not needed when encapsulated in a function?

Furthermore, the global variable FILE is in a place where it is easy accessible, but let's say we would import it as a module and wouldn't need it. Should I move it down to the main guard and loose a bit of overview?

\$\endgroup\$
12
\$\begingroup\$

Your code is split into small functions and looks nice.

A few things could be done in a better way.

zip(count(1),sorted(names) can be rewritten with the enumerate builtin : enumerate(sorted(names), start=1).

You can iterate directly over strings so you don't need to use a list in list(name).

You don't need parenthesis in for (ind, name) in.

To answer your question :

  • FILE could easily be moved behind the main guard so I'd put it there. Had it been the smallest of the issues, I would have left it where it currently is.

  • for the with, I consider it to be a good habit to put it. Also, this should answer your solution.

\$\endgroup\$
  • \$\begingroup\$ Thank you for this input. I didn't know about enumerate, what a nice tool and of course you're also right with list. I'm not sure if I got exactly the point with with, it is good to do it but not necessary? Since it leaves the file identifier leaves the scope anyway and calls the destructor? \$\endgroup\$ – magu_ Dec 16 '14 at 16:05
  • \$\begingroup\$ @magu_ Did you notice that the word "this" links to a SO question that discusses the with matter? \$\endgroup\$ – Janne Karila Dec 17 '14 at 9:31
6
\$\begingroup\$

A few minor things on top of @Josay's review.

PEP8 violations

PEP8 is the official coding style guide of Python.

  • Put a space after commas in parameter lists, for example .replace('"', "") instead of .replace('"',"")
  • Put spaces around operators, for example ind * score_name(name) instead of ind*score_name(name)
  • Put 2 blank lines in front of method definitions

Naming

fid is a bit unusual name for a file object. I'd recommend fh ("file handle") or fd ("file descriptor")

The methods score_name and score_names have too similar names. It's good to avoid names differ only by one letter. It would be slightly less confusing and more readable to rename score_names to score_name_list. This may be a matter of taste though, and not a big problem.

\$\endgroup\$
  • \$\begingroup\$ I don't see how fd is an improvement over fid. Surely such short, abbreviated variable names aren't encouraged. \$\endgroup\$ – RubberDuck Dec 17 '14 at 2:39
  • 2
    \$\begingroup\$ Thank you for your comment's. I completly agree with all of them. fid commes more from matlab but since it is actually a handle and not an identifier an other name should be better. Maybe file fits the bill. \$\endgroup\$ – magu_ Dec 17 '14 at 7:48
  • \$\begingroup\$ @RubberDuck having seen fd and fh hundreds of times, when I see it again my brain recognizes without thinking. When I see fid, it's new, so I pause for a mental cycle, then for another to figure out why it's called that way. "file id" was my guess, but since I've never seen anybody calling it like that, I'm not sure if the guess is right. Only after the OP's comment I see it's the right guess, but it's an odd name. Short variable names are perfectly acceptable in some cases, I believe this is one of those. \$\endgroup\$ – Stop ongoing harm to Monica Dec 17 '14 at 7:54
  • \$\begingroup\$ Hey @magu_, file wouldn't fit the bill in Python 2, where it was the name of a builtin. Not sure about Python 3. \$\endgroup\$ – Stop ongoing harm to Monica Dec 17 '14 at 8:00
  • 1
    \$\begingroup\$ Okay @janos fair enough. Every language has their idioms (I can't seem to stop using rst for recordset no matter how hard I try.) It was just odd for an outsider to see. \$\endgroup\$ – RubberDuck Dec 17 '14 at 9:55

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.