Choosing random integers except for a particular number for python?

Question:

I am just wondering how do I make python generate random numbers other than a particular number? For instance, I want it to generate any number from 1 to 5 except 3, so the output would be 1, 2, 4, 5 and 3 will not be counted in the list. What can I do to achieve that?

An example would be like this:
There are five computerized players (Player 0 to 4) in a game.
Player 1 randomly selects one other player (except itself) and Player 2 to 4 will do the same thing.

So the output will be something like:

Player 1, who do you want to play with?
Player 1 chooses Player 2
Asked By: bugbytes

||

Answers:

Use random.choice on a list, but first remove that particular number from the list:

>>> import random
>>> n = 3
>>> end  = 5
>>> r = list(range(1,n)) + list(range(n+1, end))
>>> r
[1, 2, 4]
>>> random.choice(r)
2
>>> random.choice(r)
4

Or define a function:

def func(n, end, start = 1):
    return list(range(start, n)) + list(range(n+1, end))
... 
>>> r = func(3, 5)
>>> r
[1, 2, 4]
>>> random.choice(r)
2

Update:

This returns all numbers other than a particular number from the list:

>>> r = range(5)
for player in r:
    others = list(range(0, player)) + list(range(player+1, 5))
    print player,'-->', others
...     
0 --> [1, 2, 3, 4]
1 --> [0, 2, 3, 4]
2 --> [0, 1, 3, 4]
3 --> [0, 1, 2, 4]
4 --> [0, 1, 2, 3]
Answered By: Ashwini Chaudhary

It sounds as if you want to produce a random set of numbers, then pick from those one-by-one. A random sequence without repetition, in other words.

Generate all those numbers, shuffle, then use .pop() to pick one at a time and remove it from the set of possibilities:

import random

numbers = range(5)  # list(range(5)) in Python 3
random.shuffle(numbers)

a_random_number = numbers.pop()
another_random_number = numbers.pop()

list.pop() removes the last value from the list of randomly shuffled numbers.

It may be enough even to just shuffle and then loop over the list:

players = range(5)
random.shuffle(players)

for player in players:
    # random ordering of players

You can bundle the random-number-sequence production up as an iterator in a function:

import random

def random_number_sequence(n):
    numbers = range(n)  # list(range(n)) in Python 3
    random.shuffle(numbers)
    return iter(numbers)

random_sequence = random_number_sequence(5)
a_random_number = next(numbers)
another_random_number = next(numbers)

You can call next() on the iterator and it’ll produce another random number from the sequence, until the sequence is exhausted (at which point StopIteration is returned).

Answered By: Martijn Pieters

In this case, random.choice will work fine, but there’s also an obvious simple mathematical transform you could use. If players are numbered 0 through 5 inclusive, and you are player X, then:

number = random.randint(0, 4) # first, pick a number: 0, 1, 2, 3, or 4
if number >= X:               # then, if it's me or higher...
    number += 1               # move forward one player

Note that this works no matter which player number you are. If you are #5, this picks a number between 0 and 4, which is not you (because you are #5). If you are #0, this picks a number between 0 and 4, which is >= you (because you are #0) so you add 1 giving a number between 1 and 5. If you are #3, this picks a number between 0 and 4, and if it’s 3 or 4 you bump it up one to 4 or 5 respectively.

Edit to add: this won’t allow you to do "fair" alternation (where everyone gets a turn before someone gets to go again). If you want that, generating a list, using random.shuffle to put it in random order, and then picking from the list (with .pop() or similar) until it is empty is the way to go. You can then refill and re-shuffle the list for a new (but different) "fair" order.

(Note that this kind of thing is why it is important to figure out what you want before going about "how to get there".)

Answered By: torek

The idea is. To pick random number from LIST(A) And each time it picks random number from LIST(A) the LIST(A) gets smaller. So you cant repeat. If Python pics ‘2’ first time. It can’t do it second time because ‘2’ is not in LIST(A) …

import random 
random_numbers =  [1,2,3,4,5] 
X = []
while True:
    one = random.choice(random_numbers))
    # print(one)
    if str(one) not in X:
        X.append(str(one))
        break

    if '2' in X:
        print("Last number was 2 with out repeating!")
        print("You did it u pick random numbers one by one with out repeating")
    random_numbers.remove(one)

print(X)
Answered By: wr3stl3r

While other answers are correct. The use of intermediate lists is inefficient.


Alternate Solution:
Another way you could do this is by choosing randomly from a range of numbers that is n-1 in size. Then adding +1 to any results that are greater than or equal to >= the number you want to skip.

The following function random_choice_except implements the same API as np.random.choice, and so adjusting size allows efficient generation of multiple random values:


import numpy as np

def random_choice_except(a: int, excluding: int, size=None, replace=True):
    # generate random values in the range [0, a-1)
    choices = np.random.choice(a-1, size, replace=replace)
    # shift values to avoid the excluded number
    return choices + (choices >= excluding)

random_choice_except(3, 1)
# >>> 0  <or>  2  
random_choice_except(3, 1, size=10)
# >>> eg. [0 2 0 0 0 2 2 0 0 2]

The behaviour of np.random.choice changes depending on if an integer, list or array is passed as an argument. To prevent unwanted behavior we may want to add the following assertion at the top of the function: assert isinstance(a, int)

Answered By: Nathan

I suggest use a recursion function.

import random

def randint_exc(start, end, exception):
    res = random.randint(start, end)
    if res != exception:
        return res
    else:
        return randint_exc(start, end, exception)

test = randint_exc(1, 4, 1)
print(test)
# results will be 2 or 3 or 4

For variable number of exception, you can use *args argument.

def randint_exc(start, end, *exception):
    res = random.randint(start, end)
    if res not in exception:
        return res
    else:
        return randint_exc(start, end, *exception)

test1 = randint_exc(1, 4, 1)
print(test1)
# results will be 2 or 3 or 4
test2 = randint_exc(1, 4, 1, 2)
print(test2)
# results will be 3 or 4

Or you can use list for more easy-reading.

def randint_exc(start, end, exception_list):
    res = random.randint(start, end)
    if res not in exception_list:
        return res
    else:
        return randint_exc(start, end, exception_list)

test1 = randint_exc(1, 4, [1])
print(test1)
# results will be 2 or 3 or 4
test2 = randint_exc(1, 4, [1, 2])
print(test2)
# results will be 3 or 4
Answered By: j3rry
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.