patternpythonMinor
Improve pandigital algorithm
Viewed 0 times
improvealgorithmpandigital
Problem
First of all, I am a beginner in Python trying to learn optimizations and proper coding standards.
Here is a snippet of code that checks if a number follows the rule: first AND last
When running this, the result is:
The code seems to work fine, but it doesn't appear to be very efficient. Would you have any tips to improve it? Any piece of code and/or idea would be highly appreciated.
PS: I chose this loop so that any improvements to the
Example of numbers I am looking for:
Here is a snippet of code that checks if a number follows the rule: first AND last
N digits contain all unique numbers from 1 to N, but in any order. This also means that in either first N or last N digits, each number appears exactly once.import time
start_time = time.time()
def is_pandigital(nr, n):
digits = ''.join(map(str, range(1, n + 1)))
nr = str(nr)
for i in digits:
if str(i) not in nr[0:9]:
return False
if str(i) not in nr[-9:]:
return False
return True
assert is_pandigital(1423, 4) is True
assert is_pandigital(1423, 5) is False
assert is_pandigital(14235554123, 4) is True
assert is_pandigital(14235552222, 4) is False # !important
assert is_pandigital(1444, 4) is False
assert is_pandigital(123564987, 9) is True
pandigitals = []
# this loop is strictly for benchmarking is_pandigital
for i in range(100000, 999999):
if is_pandigital(i, 6):
pandigitals.append(i)
print pandigitals
print time.time() - start_time, "seconds"When running this, the result is:
[123456, .......]
2.968 seconds
Process finished with exit code 0The code seems to work fine, but it doesn't appear to be very efficient. Would you have any tips to improve it? Any piece of code and/or idea would be highly appreciated.
PS: I chose this loop so that any improvements to the
is_pandigital function would be immediately obvious.Example of numbers I am looking for:
321XXXXXXXXXXXXXXX132 - good321XXXXXXXXXXXXXXX133 - not good, because the last 3 digits dont contain 1, 2 and 3231 - goodSolution
You can rewrite your asserts without comparing to
You can rewrite your benchmark with list comprehension:
Now for the algorithm itself, I must confess that I have troubles understanding what you want to do as you seem to be calling "pandigital" two different things. In any case, I have the feeling that something is wrong in your code, it seems like :
should be
and
should provide you some hints.
I'll go deeper in the code once you confirm that my understanding is correct.
Edit : I have to go, no time to run benchmarks but here are the improvements. I kept different versions to that you can take ideas out of it.
True and False:assert is_pandigital(1423, 4)
assert not is_pandigital(1423, 5)
assert is_pandigital(14235554123, 4)
assert not is_pandigital(14235552222, 4) # !important
assert not is_pandigital(1444, 4)
assert is_pandigital(123564987, 9)You can rewrite your benchmark with list comprehension:
# this loop is strictly for benchmarking is_pandigital
pandigitals = [i for i in range(100000, 999999) if is_pandigital(i, 6)]Now for the algorithm itself, I must confess that I have troubles understanding what you want to do as you seem to be calling "pandigital" two different things. In any case, I have the feeling that something is wrong in your code, it seems like :
if str(i) not in nr[0:9]:
return False
if str(i) not in nr[-9:]:
return Falseshould be
if str(i) not in nr[0:n]:
return False
if str(i) not in nr[-n:]:
return Falseand
assert not is_pandigital(9999912399999, 3)should provide you some hints.
I'll go deeper in the code once you confirm that my understanding is correct.
Edit : I have to go, no time to run benchmarks but here are the improvements. I kept different versions to that you can take ideas out of it.
def is_pandigital(nr, n):
nr = str(nr)
beg=nr[0:n]
end=nr[-n:]
for i in map(str, range(1, n + 1)):
if i not in beg or i not in end:
return False
return True
def is_pandigital(nr, n):
nr = str(nr)
beg=set(nr[0:n])
end=set(nr[-n:])
return beg==end and beg==set(map(str, range(1, n + 1)))Code Snippets
assert is_pandigital(1423, 4)
assert not is_pandigital(1423, 5)
assert is_pandigital(14235554123, 4)
assert not is_pandigital(14235552222, 4) # !important
assert not is_pandigital(1444, 4)
assert is_pandigital(123564987, 9)# this loop is strictly for benchmarking is_pandigital
pandigitals = [i for i in range(100000, 999999) if is_pandigital(i, 6)]if str(i) not in nr[0:9]:
return False
if str(i) not in nr[-9:]:
return Falseif str(i) not in nr[0:n]:
return False
if str(i) not in nr[-n:]:
return Falseassert not is_pandigital(9999912399999, 3)Context
StackExchange Code Review Q#31614, answer score: 4
Revisions (0)
No revisions yet.