Can you create a python generator to provide values over a range in a random order without repetition?
Question:
I am unsure if this is one of those problems that is impossible or not, in my mind it seems like it should be possible. Edit – We more or less agree it is impossible
Given a range specified by two integers (i.e. n1 ... n2
), is it possible to create a python generator that yields a random integer from the range WITHOUT repetitions and WITHOUT loading the list of options into memory (i.e. list(range(n1, n2))
).
Expected usage would be something like this:
def random_range_generator(n1, n2):
...
gen = random_range_generator(1, 6)
for n in gen:
print(n)
Output:
4
1
5
3
2
Answers:
How can we shuffle something?
The Idea:
- generate pairs (random integer, the stuff you want shuffled)
- sort those pairs by the random integer part
- output the list of second parts
unsorted = [(random(), x) for x in range(n1,n2) ]
sorted = sort(unsorted, key = lambda x : x[0])
result = [p[1] for p in sorted]
Note: I haven’t tested this but you get the idea. This is a useful method that can be applied/adapted also to similar problems of reordering one thing, based on the ordering of another list.
This is simple enough to do, keeping it in memory. Seems to me impossible otherwise:
import random
def random_range_generator(n1, n2):
r = list(range(n1, n2))
random.shuffle(r)
yield from r
gen = random_range_generator(1, 6)
for n in gen:
print(n)
I am unsure if this is one of those problems that is impossible or not, in my mind it seems like it should be possible. Edit – We more or less agree it is impossible
Given a range specified by two integers (i.e. n1 ... n2
), is it possible to create a python generator that yields a random integer from the range WITHOUT repetitions and WITHOUT loading the list of options into memory (i.e. list(range(n1, n2))
).
Expected usage would be something like this:
def random_range_generator(n1, n2):
...
gen = random_range_generator(1, 6)
for n in gen:
print(n)
Output:
4
1
5
3
2
How can we shuffle something?
The Idea:
- generate pairs (random integer, the stuff you want shuffled)
- sort those pairs by the random integer part
- output the list of second parts
unsorted = [(random(), x) for x in range(n1,n2) ]
sorted = sort(unsorted, key = lambda x : x[0])
result = [p[1] for p in sorted]
Note: I haven’t tested this but you get the idea. This is a useful method that can be applied/adapted also to similar problems of reordering one thing, based on the ordering of another list.
This is simple enough to do, keeping it in memory. Seems to me impossible otherwise:
import random
def random_range_generator(n1, n2):
r = list(range(n1, n2))
random.shuffle(r)
yield from r
gen = random_range_generator(1, 6)
for n in gen:
print(n)