HiveBrain v1.2.0
Get Started
← Back to all entries
snippetpythonMinor

Generate a random integer of length N with unique digits

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
randomuniquewithlengthdigitsgenerateinteger

Problem

The task is simple: given N, generate a random integer with no repeating digits.

'''
Generate a random number of length, N and all digits
are unique
'''
from __future__ import print_function
import random
from collections import OrderedDict

# keep generating till all are unique
# This is a brute force approach where I store the digits generated
# so far in a OrderedDict and if the next random number is already
# there, i ignore it.
def randN(n):
    digits = OrderedDict()
    while len(digits) < n:
        d = random.randint(0, 9)
        if d == 0 and not digits.keys():
            continue
        else:
            if not digits.get(str(d), None):
                digits[str(d)] = 1
    return int(''.join(digits.keys()))

def _assert(randi, n):
    assert len(str(randi)) == n
    assert len(set(str(randi))) == n

for _ in range(100000):
    _assert(randN(10), 10)
    _assert(randN(1), 1)
    _assert(randN(5), 5)


I have a feeling there is a better approach to solve this, which is why I am posting it here.

Solution

Not quite one line, but here's a much simpler solution:

import random

def randN(n):
    assert n <= 10
    l = list(range(10)) # compat py2 & py3
    while l[0] == 0:
        random.shuffle(l)
    return int(''.join(str(d) for d in l[:n]))


Explanation:

The problem wants N unique digits. To get those, first make a list of all the digits, then shuffle them and cut off the unwanted digits (it should be noted that if you have many more than 10 digits, shuffling the whole lot would be expensive if you only want a handful).

To turn the list of digits into an integer, the shortest way is to stringify each digit and then join them into one string, and parse that back into an integer.

But wait! If the first digit is 0, the parsed string will be one digit shorter sometimes. So, earlier in the code, simply repeat the shuffle until some other digit comes first.

Since the initial order of the list has the 0 at the beginning, we don't need to do an extra shuffle before the loop.

Code Snippets

import random

def randN(n):
    assert n <= 10
    l = list(range(10)) # compat py2 & py3
    while l[0] == 0:
        random.shuffle(l)
    return int(''.join(str(d) for d in l[:n]))

Context

StackExchange Code Review Q#69797, answer score: 4

Revisions (0)

No revisions yet.