After generating the random number you've to put the "holes" back in the range. This can be achieved by incrementing the generated number as long as there are excluded numbers lower than or equal to the generated one. The lower exclude numbers are "holes" in the range before the generated number.
For "secure" random numbers, Python doesn't actually generate them: it gets them from the operating system, which has a special driver that gathers entropy from various real-world sources, such as variations in timing between keystrokes and disk seeks.
To generate random numbers without repeating in Python, you can use the random module function choices(). choices() takes a list and the number of random numbers you want to generate.
Generate one random number and map it onto your desired ranges of numbers.
If you wanted to generate an integer between 1-4
or 7-10
, excluding 5
and 6
, you might:
1-8
2
to the result.The mapping becomes:
Random number: 1 2 3 4 5 6 7 8
Result: 1 2 3 4 7 8 9 10
Doing it this way, you never need to "re-roll". The above example is for integers, but it can also be applied to floats.
Use random.choice(). In this example, a is your lower bound, the range between b and c is skipped and d is your upper bound.
import random
numbers = range(a,b) + range(c,d)
r = random.choice(numbers)
A possible solution would be to just shift the random numbers out of that range. E.g.
def NormalWORange(a, b, sigma):
r = random.normalvariate(a,sigma)
if r < a:
return r-b
else:
return r+b
That would generate a normal distribution with a hole in the range (a-b,a+b).
Edit: If you want integers then you will need a little bit more work. If you want integers that are in the range [c,a-b] or [a+b,d] then the following should do the trick.
def RangeWORange(a, b, c, d):
r = random.randrange(c,d-2*b) # 2*b because two intervals of length b to exclude
if r >= a-b:
return r+2*b
else:
return r
I may have misunderstood your problem, but you can implement this without recursion
def rand(exclude):
r = None
while r in exclude or r is None:
r = random.randrange(1,10)
return r
rand([1,3,9])
though, you're still looping over results until you find new ones.
The fastest solution would be this (with a and b defining the exclusion zone and c and d the set of good answers including the exclusion zone):
offset = b - a
maximum = d - offset
result = random.randrange(c, maximum)
if result >= a:
result += offset
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With