寻找可用的"斑点"在一组

时间:2017-07-17 08:33:01

标签: python random sequence

我正在寻找一种以编程方式查找列表中可用(未使用)点的方法,通常是一组标准。我可以给你一个电话簿的例子:我将生成具有特定规则的电话号码(例如,在这种情况下,7位数字,非常简单)。 "发电机"会随机选择一个可用的号码。这个数字不会出现在下一次尝试的生成器中。

generator = PhoneNumberGenerator()
generator.generate()
"559-608-XXXX"
# This number won't be available next time the generator.generate is called

一种可能性是存储"使用"排序列表中的电话号码,并寻找第一个可能的可能性。但这不是随机的。第一个生成的数字是000-0000,第二个是000-0001,依此类推。另一种可能性是创建所有可用电话号码的完整列表并删除已经使用过的电话号码,但这将是一个巨大的列表。假设经常使用发电机,性能可能会受到影响。

当然,我在这里使用电话号码生成器的示例,但这可能是一个不同的生成器,用于车牌或验证码或其他任何其他的,仅由一组规则定义。我试图用Python做到这一点,所以欢迎使用这种语言的例子,但如果你用不同的语言有理论的文章,​​也不要犹豫,我只是编辑这个问题如果可以,请包括答案。

提前致谢,

1 个答案:

答案 0 :(得分:2)

取两个素数,pq,并为p * i % q生成数字0 <= i < q。结果数字覆盖了从0q(不包括)的所有数字,看似伪随机*顺序,没有重复或错过的数字。

>>> p, q = 7, 11
>>> [p*i % q for i in range(q)]
[0, 7, 3, 10, 6, 2, 9, 5, 1, 8, 4]
>>> sorted(_)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

>>> p, q = 101, 131
>>> [p*i % q for i in range(q)]
[0, 101, 71, ..., 60, 30]
>>> Counter(_).most_common(5)
[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1)]

证明(不是非常严格):假设列表中有重复的数字,即ikp*i % q == p*k % q。这意味着差异p*(k-i)必须是q的倍数(因为它们等于模q}),也是p的倍数。但由于pq是素数,因此它们的最小公倍数为p*q,永远不会与i < q达成。因此,列表中的所有数字必须是唯一的,并且由于列表中包含q个元素,因此必须包含0q的所有数字(不包括)。

显然,对于电话号码等,素数会大得多,但(假设没有溢出等)同样应该没有显着的计算或内存开销。如果您想在特定时间间隔内生成数字,例如从100000999999,您可以选择素数,以便q略大于数字,添加最小值作为每个数字的偏移量,并删除大于上限的所有数字。此外,填充前导零的数字。

*)当然,这不是随机的,甚至不是伪随机的,只是没有数字可以出现两次的标准,并且可能很容易找出下一个数字。但对于&#34;休闲&#34;观察者他们应该足够随机,不能确定首先生成两个数字中的哪一个,或者在某个给定数字之前生成了多少个数字。