Algorithm 寻找一个有限的洗牌算法
我洗牌有问题。有很多页面和讨论关于完全洗牌一系列值,比如一堆卡片 我需要的是一个洗牌,它将均匀地将数组元素从其起始位置移开最多N个位置 也就是说,如果N是2,那么元素I最多将被洗牌到从I-2到I+2的位置(在数组的边界内)Algorithm 寻找一个有限的洗牌算法,algorithm,random,shuffle,array-algorithms,Algorithm,Random,Shuffle,Array Algorithms,我洗牌有问题。有很多页面和讨论关于完全洗牌一系列值,比如一堆卡片 我需要的是一个洗牌,它将均匀地将数组元素从其起始位置移开最多N个位置 也就是说,如果N是2,那么元素I最多将被洗牌到从I-2到I+2的位置(在数组的边界内) 事实证明,对于一些简单的解决方案来说,这是一个棘手的问题,这些解决方案会导致元素移动的方向性偏差,或者导致偏移量不均匀。你说得对,这是一个棘手的问题!首先,我们需要建立更多的规则,以确保我们不会产生人为的非随机结果: 元素可以保留在它们开始的位置。这是任何公平洗牌的必要部分
事实证明,对于一些简单的解决方案来说,这是一个棘手的问题,这些解决方案会导致元素移动的方向性偏差,或者导致偏移量不均匀。你说得对,这是一个棘手的问题!首先,我们需要建立更多的规则,以确保我们不会产生人为的非随机结果:
- 元素可以保留在它们开始的位置。这是任何公平洗牌的必要部分,也确保了我们的洗牌在N=0时有效
- 当N大于元素到数组起点或终点的距离时,允许将其移动到另一侧。我们可以调整算法来禁止这样做,但这将违反“统一”要求——靠近两端的元素比靠近中间的元素更可能保持不变
i+[-N,N]
范围内生成一个随机值数组,其中i
是数组中的当前索引。规范化数组边界以外的值(例如,-1
应变为length-1
,length
应变为0
)- 重新计算这两个值,直到它们彼此不冲突,否则它们仍可能与其他值冲突
- 只重新计算一个值,直到它与另一个值不冲突为止,第一个值仍然可能冲突,但第二个值现在应该是唯一的,这可能意味着对RNG的调用更少
- 确定每次碰撞的可用索引集(例如,在
索引[3,1,1,0]
中可用),从该集中选择一个随机值,并将其中一个数组值设置为选定结果。这避免了在冲突解决之前需要循环,但编码更复杂,并且有可能遇到集合为空的情况2
该解决方案在理论上有一个无限的运行时,但在实践中应该很快终止。同样,在任何关键的地方使用它之前,先对它进行基准测试和测试。我提出了一个可能的解决方案,尽管我不确定它有多“幼稚”。尤其是在边缘,尤其是远边缘
- 从0到N(或小于N,如果N加上当前值 索引大于正在洗牌的数组
- 如果为0,则元素与自身交换,移动到下一个
- 否则,如果该元素标记为已交换,请循环并重试。 请注意,flags数组中始终有2个元素可以自己拾取 和最后一个元素(除非接近被洗牌的数组末尾)
总之:在当前索引的+/-N范围内创建一个单独的随机索引数组。然后查找解决重复索引。从该位置开始,解决过程可能很困难,如果不是不可能的话。第三个选项(计算可用索引集)将在有限的时间内运行,但我不认为它实际上比一般情况下的无限选项更好。正如我所说,您需要对其进行基准测试。如果解决方案被证明不可能,可能是您的问题没有一个通用的解决方案。我很好奇您是从哪里想到这个的,或者是什么原因使您认为您需要这个行为。这让我和我的同事感到困惑,所以谢谢你提出这个问题!这实际上是一个图形问题。请看命令“ppmspread”,或ImageMagick转换选项“-spread”。在这两种情况下,源都意味着它交换像素,从而保留原始图像中的所有像素,只是被替换。然而……事实并非如此,两个图像操作符实际上都会丢失像素复制和丢失的信息。我想修复这种“幼稚”的方法,但只是简单地在处理过程中交换像素图像导致某些像素“双交换”。搜索解决方案的结果无效。请注意,如果N的大小相同(或大于)在实际数组中,洗牌基本上应该转化为数组的完全洗牌。虽然在正常使用中,N相对于数组长度应该很小。通常在1到5之间。您认为这是
ppmspread
/spread
中的一个错误吗?您看过这些操作的源代码了吗?指向文档的链接你看到的是一个很有帮助的地方,所以我们确信我们看到的是相同的东西