[英]A random generator with non-repeating elements and changing range
我想實現一個隨機生成器,以便它能夠生成從 0 到 n 的隨機數,但除非范圍用盡,否則它不應該返回已返回的元素。 例如,如果范圍是從0到7,並且上一代是4,那么在返回0-7中的所有整數之前,4不會出現在隨機生成中。 這是我到目前為止所擁有的 - 我將生成的元素交換到數組的前面並縮小范圍。
現在我必須實現一個 function 以在生成時更改隨機生成的范圍,並且在更改范圍后非重復條件仍然成立。 function 采用下限和上限,表示新范圍,可以小於或大於舊范圍。 比如返回4后,我把范圍改成2到7,那么列表2-7用完后,4就不會出現在生成中了。
我不知道這樣做最有效的方法是什么。 我試圖創建一個黑名單並在該范圍內重新生成一個數組,其中的數字不在黑名單中,但是在列表用完后重置數組時遇到了一些問題。
class RandomGenerator:
def __init__(self, n):
self.n = n
self.start = 0
self.arr = list(range(n+1))
def generate(self):
if self.start > self.n:
self.arr = list(range(n+1))
r = random.randint(self.start, self.n)
out = self.arr[r]
temp = self.arr[self.start]
self.arr[self.start] = self.arr[r]
self.arr[r] = temp
self.start += 1
return out
對於小的n
,您可以生成一個數字列表, shuffle
它,然后pop
元素; 當它用盡時,生成一個新的source
,然后重復。
import random
def get_random_without_repeats(n=8):
source = []
while True:
if not source:
source = list(range(n))
random.shuffle(source)
yield source.pop()
for elt in get_random_without_repeats():
print(elt)
您可以添加更復雜的邏輯以在耗盡后重新生成源,以滿足您的需求。 例如,以下示例在每次源耗盡時從底部縮小值的范圍
import random
def get_random_without_repeats(n=8):
source = []
turn = 0
while True:
if not source:
source = list(range(turn, n))
if not source:
return StopIteration
turn += 1
random.shuffle(source)
yield source.pop()
for elt in get_random_without_repeats():
print(elt)
除非我遺漏了一些明顯的東西,否則你可以在生成器中無休止地從random.sample
中提取數字——它們保證永遠不會重復,如果你迭代像itertools.cycle
這樣的無限迭代器,你就可以擁有可能的數字池用盡給定范圍內的所有數字后“重置”:
from itertools import islice
def get_numbers(minimum, maximum):
# minimum and maximum are inclusive
from itertools import cycle
from random import sample
for generator in cycle([sample]):
yield from generator(range(minimum, maximum+1), k=maximum+1)
print(list(islice(get_numbers(0, 7), 16)))
Output:
[0, 1, 4, 3, 7, 2, 6, 5, 1, 6, 0, 3, 7, 4, 5, 2]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.