我有一个洗牌的问题。有很多页面和讨论关于完全洗牌一系列值,比如一摞牌。
我需要的是一个随机播放,它将在远离其起始位置的最多 N 个位置均匀地置换数组元素。
也就是说,如果 N 为 2,则元素 I 最多将被洗牌到从 I-2 到 I+2 的位置(在数组的范围内)。
事实证明,使用一些简单的解决方案会导致元件运动的方向偏差或不均匀的量,这很棘手。
我有一个洗牌的问题。有很多页面和讨论关于完全洗牌一系列值,比如一摞牌。
我需要的是一个随机播放,它将在远离其起始位置的最多 N 个位置均匀地置换数组元素。
也就是说,如果 N 为 2,则元素 I 最多将被洗牌到从 I-2 到 I+2 的位置(在数组的范围内)。
事实证明,使用一些简单的解决方案会导致元件运动的方向偏差或不均匀的量,这很棘手。
你是对的,这很棘手!首先,我们需要建立更多规则,以确保我们不会人为地创建非随机结果:
现在我们可以真正解决问题了。
i + [-N, N]
内生成一个随机值数组。i
规范化数组边界之外的值(例如-1
应该成为length-1
并且length
应该成为0
)。[3, 1, 1, 0]
index2
可用),从该集合中选择一个随机值,并将数组值之一设置为选定的结果。这避免了在解决冲突之前需要循环,但代码更复杂,并且有可能遇到集合为空的情况。我不确定如何最好地实施#2,我建议您对其进行基准测试。如果您不想花时间进行基准测试,我会选择第一个选项。其他的优化可能会更快,但实际上最终可能会更慢。
该解决方案在理论上具有无限的运行时间,但在实践中应该相当快地终止。再次,在任何关键的地方使用它之前对其进行基准测试和测试。
尽管我不确定它有多“幼稚”,但我想出了一种可能的解决方案。尤其是在边缘,尤其是远边缘。
创建一个标志数组(布尔值)N long(表示已交换的元素)
对于在每个索引处检查它是否已经被交换(根据标志数组中的第一个元素),如果是,则继续下一个(见下文)
旋转标志数组,删除第一个元素(表示此元素),并添加一个新的“未交换”元素到结尾。旁白:这可以使用模数数组查找来完成,以避免必须实际移动数组内容,尤其是对于大 N
环形...
用选定的未交换元素交换当前元素,在标志数组中将选定元素标记为交换。循环到下一个元素