Reputation: 1234
What is the pythonic (can use numpy) way to generate a random range of length [range_length_min, range_length_max]
in the range [range_start, range_end]
?
Example:
Allowed Solutions:
[53, 59]
[934, 941]
Invalid Solutions:
[92, 94]
because length of range is less than range_length_min
[92, 104]
because length of the range is more than range_length_max
[-4, 3]
because start of range is less than range_start
[1998, 2004]
because end of range is less than range_end
Current Solution:
start = np.random.randint(range_start, range_end - (range_max_length - range_min_length))
end = start + np.random.randint(range_min_length, range_max_length)
This gives the correct result but does not sample uniformly. The range_end - (range_max_length - range_min_length)
is a hack.
Upvotes: 0
Views: 292
Reputation: 51988
Here is one approach, based on weighting the choice of the length:
import random
def rand_interval(lmin,lmax,a,b):
"""picks random subinterval in [a,b] with length between lmin and lmax inclusive"""
weights = [b-a - x + 1 for x in range(lmin,lmax+1)]
length = random.choices(range(lmin,lmax+1),weights)[0]
start = random.randint(a,b-length)
return start, start + length
A test:
import collections
print(collections.Counter(rand_interval(1,2,1,3) for _ in range(10000)))
typical output:
Counter({(1, 2): 3389, (1, 3): 3386, (2, 3): 3225})
Upvotes: 1
Reputation: 3988
Just try making a function for specific needs:
>>> def foo(range_start, range_end, range_length_min, range_length_max):
... v = random.randint(range_start, range_end)
... v1 = random.randint(v + range_length_min, v + range_length_max if range_length_max <= range_end else range_end)
... return [v, v1]
...
>>> foo(range_start, range_end, range_length_min, range_length_max)
[1384, 1390]
Upvotes: 0
Reputation: 146
How about?
from random import randint
a = randint(range_start, range_end - range_length_max)
b = randint(range_length_min, range_length_max)
r = [a, a+b]
Upvotes: 0