How to generate a random 4 digit number not starting with 0 and having unique digits?

后端 未结 12 1898
没有蜡笔的小新
没有蜡笔的小新 2020-12-28 12:48

This works almost fine but the number starts with 0 sometimes:

import random
numbers = random.sample(range(10), 4)
print(\'\'.join(map(str, numbers)))


        
相关标签:
12条回答
  • 2020-12-28 13:04

    We generate the first digit in the 1 - 9 range, then take the next 3 from the remaining digits:

    import random
    
    # We create a set of digits: {0, 1, .... 9}
    digits = set(range(10))
    # We generate a random integer, 1 <= first <= 9
    first = random.randint(1, 9)
    # We remove it from our set, then take a sample of
    # 3 distinct elements from the remaining values
    last_3 = random.sample(digits - {first}, 3)
    print(str(first) + ''.join(map(str, last_3)))
    

    The generated numbers are equiprobable, and we get a valid number in one step.

    0 讨论(0)
  • 2020-12-28 13:04

    rejection sampling method. Create a 4 digit random combination from 10 digits and resample if it doesn't match the criteria.

    r4=0    
    while r4 < 1000:
        r4=int(''.join(map(str,random.sample(range(10),4))))
    

    noticed that this is essentially the same as @Austin Haskings's answer

    0 讨论(0)
  • 2020-12-28 13:08

    This will allow zeros after the first digit -

    numbers = random.sample(range(1,10),1) + random.sample(range(10),3)
    
    0 讨论(0)
  • 2020-12-28 13:11

    [Fixed] Shift all four digits on one position is not right. Swap leading zero with fixed position is not right too. But random swap of the leading zero with any of nine positions is correct and gives equal probability:

    """ Solution: randomly shuffle all numbers. If 0 is on the 0th position,
                  randomly swap it with any of nine positions in the list.
    
      Proof
        Lets count probability for 0 to be in position 7. It is equal to probability 1/10 
      after shuffle, plus probability to be randomly swapped in the 7th position if
      0 come to be on the 0th position: (1/10 * 1/9). In total: (1/10 + 1/10 * 1/9).
        Lets count probability for 3 to be in position 7. It is equal to probability 1/10
      after shuffle, minus probability to be randomly swapped in the 0th position (1/9)
      if 0 come to be on the 0th position (1/10) and if 3 come to be on the 7th position
      when 0 is on the 0th position (1/9). In total: (1/10 - 1/9 * 1/10 * 1/9).
        Total probability of all numbers [0-9] in position 7 is:
      9 * (1/10 - 1/9 * 1/10 * 1/9) + (1/10 + 1/10 * 1/9) = 1
        Continue to prove in the same way that total probability is equal to
      1 for all other positions.
        End of proof. """
    
    import random
    l = [0,1,2,3,4,5,6,7,8,9]
    random.shuffle(l)
    if l[0] == 0:
        pos = random.choice(range(1, len(l)))
        l[0], l[pos] = l[pos], l[0]
    print(''.join(map(str, l[0:4])))
    
    0 讨论(0)
  • 2020-12-28 13:12

    Combine generators with next

    A Pythonic way to write would be to use 2 nested generators and next:

    from random import randint
    from itertools import count
    
    print(next(i for i in (randint(1023, 9876) for _ in count()) if len(set(str(i))) == 4))
    # 8756
    

    It's basically a one-liner variant of @MSeifert's answer

    Preprocess all the acceptable numbers

    If you need many random numbers, you could invest some time and memory for preprocessing all the acceptable numbers:

    import random    
    possible_numbers = [i for i in range(1023, 9877) if len(set(str(i))) == 4]
    

    1023 and 9877 are used as boundaries because no int lower than 1023 or greater than 9876 can have 4 unique, distince numbers.

    Then, you'd just need random.choice for a very fast generation:

    print(random.choice(possible_numbers))
    # 7234
    
    0 讨论(0)
  • 2020-12-28 13:17

    I do not know Python well, but something like

    digits=[1,2,3,4,5,6,7,8,9] <- no zero
    random.shuffle(digits)
    first=digits[0] <- first digit, obviously will not be zero
    digits[0]=0 <- used digit can not occur again, zero can
    random.shuffle(digits)
    lastthree=digits[0:3] <- last three digits, no repeats, can contain zero, thanks @Dubu
    

    A more useful iteration, actually creating a number:

    digits=[1,2,3,4,5,6,7,8,9]   # no zero
    random.shuffle(digits)
    val=digits[0]                # value so far, not zero for sure
    digits[0]=0                  # used digit can not occur again, zero becomes a valid pick
    random.shuffle(digits)
    for i in range(0,3):
      val=val*10+digits[i]       # update value with further digits
    print(val)
    

    After stealing pieces from other solutions, plus applying the tip from @DavidHammen:

    val=random.randint(1,9)
    digits=[1,2,3,4,5,6,7,8,9]
    digits[val-1]=0
    for i in random.sample(digits,3):
      val=val*10+i
    print(val)
    
    0 讨论(0)
提交回复
热议问题