1

I'm trying to write a code that randomly chooses numbers and adds them to the list random_numbers, but if a random number was already generated, the code detects that and replaces the number with another, until every number is different.

import random
random_numbers = []
for x in range(11):

This part generates a random integer and appends it to the list random_numbers:

    random_numbers.append('[q' + str(random.randint(1, 11)) + ']')

This part is supposed to iterate over the list and check if the random number generated was already generated, and replace it:

    for item in range(len(random_numbers)):
        if random_numbers[x] == random_numbers[item]:
            random_numbers[x] = '[q' + str(random.randint(1, num_of_qs_in_file)) + ']'

print(random_numbers)

The output varies, but almost always the list has the same integer more than once. Can anybody help?

pault
  • 41,343
  • 15
  • 107
  • 149
E. Epstein
  • 739
  • 2
  • 11
  • 26
  • 2
    Try `random.sample(range(100), 10)`. Or `random.sample(['aa', 'bbb', 'vccc'], 2)`. This topic is definitely a duplicate. – Elmex80s Feb 05 '18 at 19:06
  • 1
    what's the purpose of filling your list with strings? – jpp Feb 05 '18 at 19:06
  • Hint: what if the second `randint` generates another number already in the list? – Matteo Italia Feb 05 '18 at 19:06
  • 1
    If the greatest number is not too big, you can construct a list 1, 2, 3, ... n and then permute it randomly, and then output the elements of the permutation one at a time. I think there is a function named 'shuffle' to do that. – Robert Dodier Feb 05 '18 at 19:07
  • How about using `random.shuffle`? I.e. `random_numbers = random.shuffle([i for i in range(11)])`. – Thomas Kühn Feb 05 '18 at 19:10
  • 1
    https://stackoverflow.com/questions/196017/unique-non-repeating-random-numbers-in-o1#196065 – BHawk Feb 05 '18 at 19:13
  • 1
    It looks like you want a permutation of the numbers in `range(1, 12)`, so you should use the `random.shuffle` function to do that. Matteo has hinted at the problem with your current approach. You _could_ fix that, but your code will still be slow due to the nested loops. If you want to learn how `random.shuffle` works, do a search for "Fisher–Yates shuffle". – PM 2Ring Feb 05 '18 at 19:18
  • Does this answer your question? [Generate 'n' unique random numbers within a range](https://stackoverflow.com/questions/22842289/generate-n-unique-random-numbers-within-a-range) – Tomerikoo Jan 21 '22 at 11:45

3 Answers3

6

One straightforward way to do non-repeating 'random' (psudeorandom) whole numbers in a modest range is to create a list using range(1, n), then random.shuffle() the list, and then take as many numbers as you want from the list using pop() or a slice.

import random

max = 11
l = list(range(1, max))  # the cast to list is optional in Python 2
random.shuffle(l)

Now every time you want a random number, just l.pop().

Another is to use random.sample() -- see https://docs.python.org/3/library/random.html

Andrew Gorcester
  • 19,595
  • 7
  • 57
  • 73
0

This is one forceful way

import random as rd
random = rd.randint(1,20)
rdlist = []
for _ in range(10):
    while random not in rdlist:
        rdlist.append(random)
    while random in rdlist:
        random = rd.randint(1,20)
Tien Dinh
  • 351
  • 1
  • 12
-1

Randomness is a concept that most people assume means "different every time" or some understanding like that.

In reality, randomness is pretty hard to define and generally, it's safe to assume anyway that you will see repetition. If something is truly random, it (the algorithm) does not care if it repeats or not. It pays no attention to previous values when it creates new ones. This is the gist of what 'random' means in the programming world.

If you roll a die and you get a 4 (1/6 chance), what are the chances you will get a 4 again? It's still 1/6. Getting a 4 once does not change the likelihood of getting it again.

So you don't actually want randomness. You want to somewhat control the behavior of your output.

What I would suggest is keeping another list of integers you have already inserted into the array and if the newest one generated is something you already have, produce another random number in order to hopefully get a different one this time.

Dylan Moore
  • 443
  • 4
  • 14
  • 7
    There is such a thing as random draws without repetition. Imagine drawing differently coloured balls from a bag and not putting them back. – Thomas Kühn Feb 05 '18 at 19:12
  • 2
    Keeping a list and redrawing if you get an item already on the list is a reasonable place to start, but it becomes increasingly inefficient as the set of possibilities is exhausted. To get the last item in the set, the probability that you have to draw again is (n - 1)/n and the expected number of times you have to draw is n^2 - n (if I've done my arithmetic correctly). But when n is large and the number of samples needed is much less than n (so the probability of collision is low) then the approach you suggest is more attractive. – Robert Dodier Feb 05 '18 at 19:24