用于短序列的更好的随机“感觉”整数生成器

时间:2010-06-23 05:33:53

标签: algorithm random arc4random

我正在试图找出一种方法来创建随机数字,这些随机数字在短序列中“感觉”随机。这是一个测验游戏,有四种可能的选择,软件需要选择四个位置中的一个来放置正确的答案,然后再填充其他三个与干扰者。

显然,arc4random % 4会在一个长序列中创建超过足够随机的结果,但在短序列中,完全可能(并经常发生!)有五个或六个相同的数字返回到行。这就是我要避免的。

我也不想简单地说“永远不要选择同一个方格两次”,因为除了第一个问题,每个问题只能得到三个可能的答案。目前我正在做这样的事情:

bool acceptable = NO;
do {
  currentAnswer = arc4random() % 4;
  if (currentAnswer == lastAnswer) {
    if (arc4random() % 4 == 0) {
      acceptable = YES;
    }
  } else {
    acceptable = YES;
  }
} while (!acceptable);

我有什么更好的解决办法吗?

4 个答案:

答案 0 :(得分:3)

您填充一系列结果,然后 shuffle ,然后按顺序分配。

所以只有8个问题:

answer_slots = [0,0,1,1,2,2,3,3]

shuffle(answer_slots)

print answer_slots
 [1,3,2,1,0,2,3,0]

答案 1 :(得分:3)

如果您的问题是如何非迭代地使用示例的概率计算currentAnswer,那么Guffa就有了答案。

如果问题是如何在不违反等概率的情况下避免随机聚类并且您知道列表长度的上限,那么请考虑以下算法,这类似于取消排序:

from random import randrange
# randrange(a, b) yields a <= N < b

def decluster():
    for i in range(seq_len):
        j = (i + 1) % seq_len
        if seq[i] == seq[j]:
            i_swap = randrange(i, seq_len) # is best lower bound 0, i, j?
            if seq[j] != seq[i_swap]:
                print 'swap', j, i_swap, (seq[j], seq[i_swap])
                seq[j], seq[i_swap] = seq[i_swap], seq[j]

seq_len = 20
seq = [randrange(1, 5) for _ in range(seq_len)]; print seq
decluster(); print seq
decluster(); print seq

与实际工作的Python代码的任何关系纯属巧合。我很确定先前的概率是保持不变的,它看起来似乎是破碎的集群(偶尔会增加一些)。但我很困,所以这只是为了娱乐目的。

答案 2 :(得分:0)

要将重复次数的概率降低25%,您可以选择介于0和3.75之间的随机数,然后旋转它以使0.75在前一个答案处结束。

要避免使用浮点值,可以将因子乘以4:

伪代码(其中/是整数除法):

currentAnswer = ((random(0..14) + lastAnswer * 4) % 16) / 4

答案 3 :(得分:0)

设置加权数组。让我们说最后一个值是2.创建一个这样的数组:

array = [0,0,0,0,1,1,1,1,2,3,3,3,3];

然后在数组中选择一个数字。

newValue = array[arc4random() % 13];

现在切换到使用math而不是数组。

newValue = ( ( ( arc4random() % 13 ) / 4 ) + 1 + oldValue ) % 4;

对于P可能性和权重0<W<=1使用:

newValue = ( ( ( arc4random() % (P/W-P(1-W)) ) * W ) + 1 + oldValue ) % P;

对于P = 4且W = 1/4,(P / W-P(1-W))= 13.这表示最后一个值将是其他值的1/4。

如果你完全消除了最新的答案,那么就会像最近出现的答案一样明显。我不知道你觉得什么样的体重,但1/4是一个很好的起点。