英文:
Algorithm to randomize output order of a short array in Go
问题
这个问题与许多重复答案的关键区别在于,输入数组很短,只有3个元素。
假设我有一个有序的整数集合。数组的大小只有3个(或稍多一些)。我需要随机化它们的顺序并返回一个新的数组。虽然这是一个纯粹的算法问题,但首选的答案语言是Go。
使用Python,答案是random.shuffle
。参考链接:https://stackoverflow.com/questions/71937148/how-can-i-output-a-list-in-random-order
使用Go,答案应该是rand.Shuffle
。参考链接:https://yourbasic.org/golang/shuffle-slice-array/
然而,这是我的代码:
func randShuffle(a []int) {
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
}
这是我的一个测试运行结果:
[2 1 3]
[1 3 2]
[2 1 3]
[2 1 3]
[1 3 2]
[1 2 3]
[2 3 1]
看起来并不是非常随机。
有没有好的方法来对一个只有3个元素的数组进行更好的随机化?
另外,
- https://stackoverflow.com/questions/19047989/how-to-output-array-elements-in-random-order-using-vhdl 提到使用线性反馈移位寄存器(linear feedback shift register),但我认为这对于这个问题不是一个好主意。
- https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array 给出了一种Durstenfeld shuffle算法,它是Fisher-Yates算法的优化版本。但我认为它的结果与Go的
rand.Shuffle
相似。是吗?
英文:
The key difference between this question and the lots of duplicated answers is that, the input array is short, only 3 elements. --
Say I have an ordered set of int
. The size of array is only 3 (or a bit more). I need to randomize their order and return a new array. Although it is a pure algorithm question, but the prefered answer language is in Go.
- With Python, https://stackoverflow.com/questions/71937148/how-can-i-output-a-list-in-random-order, the answer is
random.shuffle
. - With Go, https://yourbasic.org/golang/shuffle-slice-array/, the answer should be
rand.Shuffle
.
However, this is my code:
https://go.dev/play/p/CVu8_Q96-9F
func randShuffle(a []int) {
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
}
And this is one of my test run result:
[2 1 3]
[1 3 2]
[2 1 3]
[2 1 3]
[1 3 2]
[1 2 3]
[2 3 1]
which doesn't seems to be very randomized.
Any good idea to have a better randomization for a short 3-elements array?
BTW,
- https://stackoverflow.com/questions/19047989/how-to-output-array-elements-in-random-order-using-vhdl says to use a linear feedback shift register, but I don't think it'd be a good idea for this question.
- The https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array gives a Durstenfeld shuffle algorithm, an optimized version of Fisher-Yates. But I presume that its result will be quite similiar to Go's
rand.Shuffle
. Is it?
答案1
得分: 1
将random.Seed
从你的洗牌函数移动到主函数中。对 PRNG 的种子进行播种应该在程序中只执行一次,成功模拟随机性是通过生成器的状态转换而不是种子来实现的。除非你真正理解 PRNG 的工作原理并且试图明确控制过程以实现可重现性等原因,否则不要重新播种。
以下是你的代码的简单修改,可以满足你的需求:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
a := []int{1, 2, 3}
for i := 0; i < 10; i++ {
randShuffle(a)
fmt.Println(a)
}
}
func randShuffle(a []int) {
rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
}
这将产生如下结果:
[2 3 1]
[3 1 2]
[2 1 3]
[2 3 1]
[1 2 3]
[1 3 2]
[1 2 3]
[3 1 2]
[3 2 1]
[2 3 1]
英文:
Move random.Seed
from your shuffle function to the main. Seeding of a PRNG should only be done once per program, the successful mimicry of randomness is done by the state transitions of the generator rather than by the seed. Don't re-seed unless you really understand how PRNGs work and are trying to explicitly control the process for reasons such as reproducibility.
The following straightforward modification of your code should meet your needs:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
a := []int{1, 2, 3}
for i := 0; i < 10; i++ {
randShuffle(a)
fmt.Println(a)
}
}
func randShuffle(a []int) {
rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
}
This produces results such as:
[2 3 1]
[3 1 2]
[2 1 3]
[2 3 1]
[1 2 3]
[1 3 2]
[1 2 3]
[3 1 2]
[3 2 1]
[2 3 1]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论