views:

140

answers:

2

Hey, I am trying to solve problem 41, but i don't know why my code stops at 987654319:

def IsPandigital(No):
 a = sorted(str(No))
 for i in range(1,10):
  if a[i - 1] != str(i):
   return False
 return True
def IsPrime(No):
 i = 2
 while i < No:
  if No % i == 0:
   return False
  i += 1
 return True
i = 987654321
while i > 0:
 print i
 raw_input()
 if IsPrime(i) == True and IsPandigital(i) == True:
  print i
  break
 i -= 1
print i
print "EOP"
raw_input()

P.S: I know that i should start from 799999999 because:

GergS: Every 9 digit and 8 digit pandigital number is divisible by 3.

+1  A: 

The routine to find primes takes much longer than the pandigital, so switch the order that they are run. So it should be:

if IsPandigital(i) == True and IsPrime(i) == True:
EddieC
+3  A: 

Your IsPrime function is very slow. It quickly calculated that 987654321 is dividable by 3 and 987654320 is dividable by 2. However, 987654319 is prime and it takes very very long to check it against all divisors so it seems as if it stopped.

The problem requires more than just simple calculation, as you did. Calculating prime numbers is a slow process, so you should optimize it, for example:

  • Test IsPandigital before IsPrime,
  • Even better, create a list of only pandigital numbers and make the prime test. Hint: the pandigital numbers are: [987654321,987654312,987654231,987654213,...]
  • You dont have to make loop while i < No - it is enough to go up to sqrt(No).
  • Numbers ending with digit 0, 2, 4, 5, 6 or 8 are never prime
  • Another option might be to calculate all n-digit prime numbers and then pick the largest pandigital number.

Your other problems:

  • You are calculating the largest 9-digit pandigital prime. The problem says "the largest n-digit pandigital prime", so you should be able to calculate any length depending on a parameter
  • You should not start from 799999999, as you wrote. You should simply skip calculations for n=3, n=5, n=6, n=8 and n=9 because none of those is prime.
zvonimir
Don't test any value larger than the `sqrt(No)` for being prime. If you didn't value, `x <= sqrt(No)` that divides `No`, then stop checking, it can't be larger than the square root.
S.Lott
@S.Lott Of course, you are right. I updated my answer.
zvonimir
But how to create a list of only pandigital numbers ? i am stuck in this point !
Goblin
- make a list from 1 to 9- make a list of string representations thereof- make a list of all sublists thereof beginning with '1'- make all permutations of all those sublists- chain those permutations togehether- join each permutataion into a single string- turn each string into an intTake a look at the itertools module, and make it lazy as much as you can.
pillmuncher
@Goblin I don't want to give you a complete solution ;) but here's a list of **all** pandigital numbers: `[int(''.join(map(str,x))) for x in sum([list(permutations(range(1,length+1),length)) for length in range(1,9+1)],[])]`. This can be further optimized with my hints above, but even this is enough to solve the problem in seconds...
zvonimir