Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the quickest way to get a number with unique digits in python?

Lemme clarify:

What would be the fastest way to get every number with all unique digits between two numbers. For example, 10,000 and 100,000.

Some obvious ones would be 12,345 or 23,456. I'm trying to find a way to gather all of them.

for i in xrange(LOW, HIGH):
  str_i = str(i)
  ...?
like image 747
SetSlapShot Avatar asked Sep 11 '13 03:09

SetSlapShot


1 Answers

Use itertools.permutations:

from itertools import permutations

result = [
    a * 10000 + b * 1000 + c * 100 + d * 10 + e
    for a, b, c, d, e in permutations(range(10), 5)
    if a != 0
]

I used the fact, that:

  • numbers between 10000 and 100000 have either 5 or 6 digits, but only 6-digit number here does not have unique digits,
  • itertools.permutations creates all combinations, with all orderings (so both 12345 and 54321 will appear in the result), with given length,
  • you can do permutations directly on sequence of integers (so no overhead for converting the types),

EDIT:

Thanks for accepting my answer, but here is the data for the others, comparing mentioned results:

>>> from timeit import timeit
>>> stmt1 = '''
a = []
for i in xrange(10000, 100000):
    s = str(i)
    if len(set(s)) == len(s):
        a.append(s)
'''
>>> stmt2 = '''
result = [
    int(''.join(digits))
    for digits in permutations('0123456789', 5)
    if digits[0] != '0'
]
'''
>>> setup2 = 'from itertools import permutations'
>>> stmt3 = '''
result = [
    x for x in xrange(10000, 100000)
    if len(set(str(x))) == len(str(x))
]
'''
>>> stmt4 = '''
result = [
    a * 10000 + b * 1000 + c * 100 + d * 10 + e
    for a, b, c, d, e in permutations(range(10), 5)
    if a != 0
]
'''
>>> setup4 = setup2
>>> timeit(stmt1, number=100)
7.955858945846558
>>> timeit(stmt2, setup2, number=100)
1.879319190979004
>>> timeit(stmt3, number=100)
8.599710941314697
>>> timeit(stmt4, setup4, number=100)
0.7493319511413574

So, to sum up:

  • solution no. 1 took 7.96 s,
  • solution no. 2 (my original solution) took 1.88 s,
  • solution no. 3 took 8.6 s,
  • solution no. 4 (my updated solution) took 0.75 s,

Last solution looks around 10x faster than solutions proposed by others.

Note: My solution has some imports that I did not measure. I assumed your imports will happen once, and code will be executed multiple times. If it is not the case, please adapt the tests to your needs.

EDIT #2: I have added another solution, as operating on strings is not even necessary - it can be achieved by having permutations of real integers. I bet this can be speed up even more.

like image 160
Tadeck Avatar answered Nov 06 '22 03:11

Tadeck