I just solved Project Euler 38 and was wondering if you guys could provide some suggestions on how to speed it up. I've tried adding extra conditions but they increase the time. Any ideas on how to optimize the numbers I'm checking would be appreciated.
from timeit import default_timer as timer
def create_pandigital_multiple(original_number):
num = str(original_number)
digits = range(1, 10)
if len(num) >= 5:
return 0
else:
temp = 2
while len(num) < 9:
num += str(original_number * temp)
temp += 1
if sorted([int(x) for x in num]) == digits:
return int(num)
else:
return 0
start = timer()
ans = 0
for k in range(9, 10**5):
if create_pandigital_multiple(k) > greatest:
ans = create_pandigital_multiple(k)
elapsed_time = (timer() - start) * 1000 # s --> ms
print "Found %d in %r ms." % (ans, elapsed_time)
3 Answers 3
- Checking
if len(num) >= 5
is redundant because you only call the function withk < 10**5
- Instead of
sorted([int(x) for x in num])
you could compute justsorted(num)
and compare that to aDIGITS = [str(i) for i in range(1, 10)]
constant that you can compute outside the function. - Most of the multiples end up longer than 9 digits. Testing
len(num) == 9
before sorting the digits should be faster. - You could take advantage of the example 918273645 provided in the problem statement. The number you are looking for must be greater or equal to that. For one thing, the first two digits must be in range 91 to 98, which is a small fraction of all the two-digit numbers you try.
Ok first off we can narrow the range by making the following observations coupled with the obvious fact the number must begin with a 9.
- \$x\$ is not 9
- if \90ドル \leq x <100\,ドル then \$n1+n2+n3 \approx 90180360\$ an 8 digit number, so we can exclude this range as well
if \900ドル \leq x <1000\,ドル then \$\approx 90018003600\$; too many so they can be eliminated.
Finally if \9000ドル \leq x < 10000\,ドル we have \$n1 + n2 \approx 900018000\$; a 9 digit
So we can narrow the range to 9000 to 9999. That brings your run time down to about 9.7 ms from 100 ms
Here is a more efficient way to find 1-9 pandigitals by observing from above that n has a max value of 2 which eliminates the need for a nested loop by directly creating the number to check like this:
def problem38():
largest=int()
for i in xrange(9000,10000):
temp=str(i)+str(i*2)
if "0" not in temp:
if len(set(temp))==9:
if int(temp)>largest:
largest=int(temp)
return largest
By testing if the number contains 0 then testing the set length we know the number is pandigital.
This algorithm runs in 1.3 ms
-
\$\begingroup\$ Why does the answer have to begin with a 9? \$\endgroup\$Johnny Apple– Johnny Apple2017年11月10日 17:03:18 +00:00Commented Nov 10, 2017 at 17:03
Instead of
if create_pandigital_multiple(k) > greatest:
ans = create_pandigital_multiple(k)
you can use
ans = max(ans, create_pandigital_multiple(k))
-
2\$\begingroup\$ Why? how does it make the Code better? please explain these things in your answer/Review, thank you \$\endgroup\$Malachi– Malachi2015年06月17日 14:11:06 +00:00Commented Jun 17, 2015 at 14:11
-
1\$\begingroup\$ It makes the code easier to read. \$\endgroup\$Theta Sigma– Theta Sigma2015年06月17日 14:42:30 +00:00Commented Jun 17, 2015 at 14:42
-
\$\begingroup\$ Not quite sure why this is getting downvoted... Also not quite sure where the
greatest
variable comes from in the original code... \$\endgroup\$SylvainD– SylvainD2015年06月17日 14:50:17 +00:00Commented Jun 17, 2015 at 14:50 -
\$\begingroup\$ @ThetaSigma Actualy, using
max
is calculatecreate_pandigital_multiple
only once, in original code it is recalculated every time condition is accepted. \$\endgroup\$outoftime– outoftime2015年06月17日 14:55:19 +00:00Commented Jun 17, 2015 at 14:55 -
\$\begingroup\$ I don't think that using the
max
function is optimal here. every time this line is hit it will assign theans
variable, whereas the OP only assigns when thecreate_pandigital_multiple(k)
is bigger, so the OP would be assigning the variable less times than your code. \$\endgroup\$Malachi– Malachi2015年06月29日 18:27:45 +00:00Commented Jun 29, 2015 at 18:27
Explore related questions
See similar questions with these tags.