Reputation: 252
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
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
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
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
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
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 string
s) 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