【发布时间】:2021-05-15 11:09:19
【问题描述】:
维基百科上描述的Fisher yates算法是
该算法产生一个无偏的排列:每个排列都是等可能的。
我浏览了一些文章,这些文章解释了朴素和费希尔耶茨算法如何产生集合中项目的有偏和无偏组合。
文章链接
Fisher-Yates Shuffle – An Algorithm Every Developer Should Know
Randomness is hard: learning about the Fisher-Yates shuffle algorithm & random number generation
文章继续展示了这两种算法的几乎无偏见和非常有偏见的结果图表。我试图重现概率,但我似乎无法产生差异。
这是我的代码
import java.util.*
class Problem {
private val arr = intArrayOf(1, 2, 3)
private val occurrences = mutableMapOf<String, Int>()
private val rand = Random()
fun biased() {
for (i in 1..100000) {
for (i in arr.indices) {
val k = rand.nextInt(arr.size)
val temp = arr[k]
arr[k] = arr[i]
arr[i] = temp
}
val combination = arr.toList().joinToString("")
if (occurrences.containsKey(combination)) {
occurrences[combination] = occurrences[combination]!! + 1
} else {
occurrences[combination] = 1
}
}
print("Naive:\n")
occurrences.forEach { (t, u) ->
print("$t: $u\n")
}
}
/**
* Fisher yates algorithm - unbiased
*/
fun unbiased() {
for (i in 1..100000) {
for (i in arr.size-1 downTo 0) {
val j = rand.nextInt(i + 1)
val temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
val combination = arr.toList().joinToString("")
if (occurrences.containsKey(combination)) {
occurrences[combination] = occurrences[combination]!! + 1
} else {
occurrences[combination] = 1
}
}
print("Fisher Yates:\n")
occurrences.forEach { (t, u) ->
print("$t: $u\n")
}
}
}
fun main() {
Problem().biased()
Problem().unbiased()
}
这会产生以下结果
Naive:
312: 16719
213: 16654
231: 16807
123: 16474
132: 16636
321: 16710
Fisher Yates:
123: 16695
312: 16568
213: 16923
321: 16627
132: 16766
231: 16421
我的结果在这两种情况下并没有太大的不同。我的问题是,我的实现错了吗?还是我的理解有误?
【问题讨论】:
标签: algorithm kotlin fisher-yates-shuffle