dyln
dyln

Reputation: 252

Writing shorter, readable, pythonic code

I'm trying to produce shorter, more pythonic, readable python. And I have this working solution for Project Euler's problem 8 (find the greatest product of 5 sequential digits in a 1000 digit number).

Suggestions for writing a more pythonic version of this script?

numstring = ''
for line in open('8.txt'):
    numstring += line.rstrip()

nums = [int(x) for x in numstring]

best=0
for i in range(len(nums)-4):
    subset = nums[i:i+5]
    product=1
    for x in subset:
        product *= x
    if product>best:
        best=product
        bestsubset=subset

print best
print bestsubset

For example: there's gotta be a one-liner for the below snippet. I'm sure there's a past topic on here but I'm not sure how to describe what I'm doing below.

numstring = ''
for line in open('8.txt'):
    numstring += line.rstrip()

Any suggestions? thanks guys!

Upvotes: 5

Views: 796

Answers (5)

Steven Rumbalski
Steven Rumbalski

Reputation: 45542

from operator import mul

def product(nums):
    return reduce(mul, nums)

nums = [int(c) for c in open('8.txt').read() if c.isdigit()]
result = max((product(nums[i:i+5]) for i in range(len(nums))))

Upvotes: 4

orlp
orlp

Reputation: 117691

Here's a full solution! First read out the number:

with open("8.txt") as infile:
    number = infile.replace("\n", "")

Then create a list of lists with 5 consecutive numbers:

cons_numbers = [list(map(int, number[i:i+5])) for i in range(len(number) - 4)]

Then find the largest and print it:

print(max(reduce(operator.mul, nums) for nums in cons_numbers))

If you're using Python 3.x you need to replace reduce with functools.reduce.

Upvotes: 0

steveha
steveha

Reputation: 76715

Here is my solution. I tried to write the most "Pythonic" code that I know how to write.

with open('8.txt') as f:
    numstring = f.read().replace('\n', '')

nums = [int(x) for x in numstring]

def sub_lists(lst, length):
    for i in range(len(lst) - (length - 1)):
        yield lst[i:i+length]

def prod(lst):
    p = 1
    for x in lst:
        p *= x
    return p

best = max(prod(lst) for lst in sub_lists(nums, 5))
print(best)

Arguably, this is one of the ideal cases to use reduce so maybe prod() should be:

# from functools import reduce   # uncomment this line for Python 3.x
from operator import mul
def prod(lst):
    return reduce(mul, lst, 1)

I don't like to try to write one-liners where there is a reason to have more than one line. I really like the with statement, and it's my habit to use that for all I/O. For this small problem, you could just do the one-liner, and if you are using PyPy or something the file will get closed when your small program finishes executing and exits. But I like the two-liner using with so I wrote that.

I love the one-liner by @Steven Rumbalski:

nums = [int(c) for c in open('8.txt').read() if c.isdigit()]

Here's how I would probably write that:

with open("8.txt") as f:
    nums = [int(ch) for ch in f.read() if ch.isdigit()]

Again, for this kind of short program, your file will be closed when the program exits so you don't really need to worry about making sure the file gets closed; but I like to make a habit of using with.

Upvotes: 1

Rob Volgman
Rob Volgman

Reputation: 2114

I'm working on a full answer, but for now here's the one liner

numstring = ''.join(x.rstrip() for x in open('8.txt'))

Edit: Here you go! One liner for the search. List comprehensions are wonderful.

from operator import mul
def prod(list):
    return reduce(mul, list)

numstring = ''.join(x.rstrip() for x in open('8.txt'))
nums = [int(x) for x in numstring]
print max(prod(nums[i:i+5]) for i in range(len(nums)-4))

Upvotes: 4

TankorSmash
TankorSmash

Reputation: 12747

As far as explaining what that last bit was, first you create an empty string called numstring:

numstring = ''

Then you loop over every line of text (or line of strings) in the txt file 8.txt:

for line in open('8.txt'):

And so for every line you find, you want to add the result of line.rstrip() to it. rstrip 'strips' the whitespace (newlines,spaces etc) from the string:

    numstring += line.rstrip()

Say you had a file, 8.txt that contains the text: LineOne \nLyneDeux\t\nLionTree you'd get a result that looked something like this in the end:

>>>'LineOne' #loop first time
>>>'LineOneLyneDeux' # second time around the bush
>>>'LineOneLyneDeuxLionTree' #final answer, reggie

Upvotes: 0

Related Questions