什么是好的一次性伪随机洗牌? [关闭]

Posted

技术标签:

【中文标题】什么是好的一次性伪随机洗牌? [关闭]【英文标题】:What's a good one-pass pseudo-random shuffle? [closed] 【发布时间】:2011-10-09 22:00:25 【问题描述】:

Fisher-Yates shuffle 提供了一个很好的算法,可以一次性对长度为 n 的数组 A 进行洗牌:

For k = 1 to n
    Pick a random integer j from k to n
    Swap A[k] and A[j]

通过该算法单次后,A 的条目均匀随机出现。

破坏该算法的常见方法是执行以下操作:

For k = 1 to n
    Pick a random integer j from 1 to n
    Swap A[k] and A[j]

单次通过该算法得到的分布不是均匀随机的,在这篇文章中有很好的讨论:What distribution do you get from this broken random shuffle?

我最近阅读了 Diaconis、Fulman 和 Holmes 撰写的一篇令人愉快的文章,标题为 Analysis of Casino Shelf Shuffling Machines,其中作者描述了一台执行以下批处理 shuffle 的物理机器:

For k = 1 to n
    Pick a random integer j from 1 to 10
    Randomly choose to place card k on the top or bottom of stack j

作者提出的问题是,这是否会在单次通过后给出合理的随机排序。答案绝对不是。看到这种洗牌中的缺陷的一种方法是从一副牌开始,其中有n/2 红牌和n/2 黑牌。单次通过后产生的牌组最多有 10 张红牌!对于n = 52*6,这并不是非常随机的。作者还表明,对于一次洗牌的最佳“猜下一张牌”策略平均能正确猜出 9.5 张牌,而随机牌组的最佳策略平均只能正确猜出 4.5 张牌。

还有其他有趣的单次洗牌可以实现近乎随机和/或有趣的分布吗?我对类似于后者的混洗特别感兴趣,它适用于成批的条目。

【问题讨论】:

非常有趣的问题,但我认为它不适合 SO @Mitch C'mon ...让我们在这里保留一些有趣的问题! @PengOne:一些洗牌理论也出现在《Proofs from THE BOOK》中 Fisher-Yates 很简单,可能是正确的,一旦你理解了它,这几乎是最直观的洗牌方式。我们真的需要更多吗? :) 在物理世界中(因此对于 SO 来说是 OT),我确实想知道你可以实现的最快的 shuffle 是什么,它可以提供良好的分布。 @TimPost:我认为这不值得 CW,因为这不是购物清单问题。不幸的是,由于标题中的“好”,它看起来是主观的,但是“什么是好的算法”与“什么是好的监视器”有几个数量级的不同。在这种情况下,它可以用 Big-O 或 Theta 来量化。 【参考方案1】:

如果您有一张洗牌桌,您希望将一批新牌洗牌(并且您知道没有一张牌是重复的),那么我认为以下内容是有效的。

ForEach card in batch:
    gap = random(deck.size() + 1)  # choose a gap between cards, before first, or after last.
    deck.insertAt(gap,card)

分布

random 的分布是均匀的,deck 的顺序不变,所以还是均匀的。 我认为结果应该是统一的。 (我的统计数据太生疏了,无法确定)。

时间

假设 insertAt 是 O(1) 而不是 O(N) - 这取决于甲板的实施 - 整个例程是 O(batch size) - 这是你可以希望的最好的,因为你必须处理每张卡.

【讨论】:

以上是关于什么是好的一次性伪随机洗牌? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

什么是好的游戏随机数生成器?

什么是好的隐形验证码? [关闭]

什么是好的 GeoTiff 查看器? [关闭]

这种加密有多安全? [关闭]

什么是好的单元测试? [关闭]

什么是好的 JavaScript OOP 资源? [关闭]