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

发布于 2024-09-06 16:08:47 字数 546 浏览 3 评论 0 原文

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

显然,arc4random % 4 将在长序列中创建足够随机的结果,但在短序列中,完全有可能(并且经常发生!)有 5 或 6 个相同的数字返回连续。这就是我想要避免的。

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

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

是否有我忽略的更好的解决方案?

I'm trying to figure out a way to create random numbers that "feel" random over short sequences. This is for a quiz game, where there are four possible choices, and the software needs to pick one of the four spots in which to put the correct answer before filling in the other three with distractors.

Obviously, arc4random % 4 will create more than sufficiently random results over a long sequence, but in a short sequence its entirely possible (and a frequent occurrence!) to have five or six of the same number come back in a row. This is what I'm aiming to avoid.

I also don't want to simply say "never pick the same square twice," because that results in only three possible answers for every question but the first. Currently I'm doing something like this:

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

Is there a better solution to this that I'm overlooking?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

甲如呢乙后呢 2024-09-13 16:08:47

如果您的问题是如何使用示例的概率非迭代地计算 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 代码的任何关系纯粹是巧合。我很确定先验概率得到维持,并且它似乎确实打破了集群(并且偶尔会添加一些)。但我很困,所以这只是为了娱乐目的。

If your question was how to compute currentAnswer using your example's probabilities non-iteratively, Guffa has your answer.

If the question is how to avoid random-clustering without violating equiprobability and you know the upper bound of the length of the list, then consider the following algorithm which is kind of like un-sorting:

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

where any relation to actual working Python code is purely coincidental. I'm pretty sure the prior-probabilities are maintained, and it does seem break clusters (and occasionally adds some). But I'm pretty sleepy so this is for amusement purposes only.

海未深 2024-09-13 16:08:47

您填充一系列结果,然后随机播放 它,然后按该顺序分配它们。

所以只有 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]

You populate an array of outcomes, then shuffle it, then assign them in that order.

So for just 8 questions:

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

shuffle(answer_slots)

print answer_slots
 [1,3,2,1,0,2,3,0]
傲性难收 2024-09-13 16:08:47

要将重复数字的概率降低 25%,您可以选择 0 到 3.75 之间的随机数字,然后旋转它,使 0.75 最终成为上一个答案。

为了避免使用浮点值,您可以将因子乘以四:

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

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

To reduce the probability for a repeated number by 25%, you can pick a random number between 0 and 3.75, and then rotate it so that the 0.75 ends up at the previous answer.

To avoid using floating point values, you can multiply the factors by four:

Pseudo code (where / is an integer division):

currentAnswer = ((random(0..14) + lastAnswer * 4) % 16) / 4
紫轩蝶泪 2024-09-13 16:08:47

设置一个加权数组。假设最后一个值是 2。创建一个像这样的数组:

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

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

newValue = array[arc4random() % 13];

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

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

对于 P 个可能性和权重 0 使用:

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

对于 P=4 和 W=1/4,(P/WP(1-W)) = 13。这表示最后一个值的可能性是其他值的 1/4。

如果您完全消除最新的答案,它将与频繁出现的最新答案一样引人注目。我不知道什么重量适合您,但 1/4 是一个很好的起点。

Set up a weighted array. Lets say the last value was a 2. Make an array like this:

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

Then pick a number in the array.

newValue = array[arc4random() % 13];

Now switch to using math instead of an array.

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

For P possibilities and a weight 0<W<=1 use:

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

For P=4 and W=1/4, (P/W-P(1-W)) = 13. This says the last value will be 1/4 as likely as other values.

If you completely eliminate the most recent answer it will be just as noticeable as the most recent answer showing up too often. I do not know what weight will feel right to you, but 1/4 is a good starting point.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文