Алгоритм рандомизации порядка вывода короткого массива в Go

Ключевое отличие этого вопроса от множества повторяющихся ответов заключается в том, что входной массив короткий, всего 3 элемента. --

Скажем, у меня есть заказанный набор int. Размер массива всего 3 (или чуть больше). Мне нужно рандомизировать их порядок и вернуть новый массив. Хотя это чисто алгоритмический вопрос, но предпочтительным языком ответов является Go.

Однако это мой код:

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] })
}

И это один из результатов моего тестового прогона:

[2 1 3]
[1 3 2]
[2 1 3]
[2 1 3]
[1 3 2]
[1 2 3]
[2 3 1]

который, кажется, не очень рандомизирован.

Любая хорошая идея, чтобы иметь лучшую рандомизацию для короткого массива из 3 элементов?

КСТАТИ,

это не будет "выглядеть" случайным, потому что есть только три элемента. rand.Shuffle использует алгоритм Фишера-Йейтса под капотом. если вы реализуете это самостоятельно, вы увидите аналогичные результаты.

skeeter 30.03.2023 16:16

Вот реализация math.rand.Shuffle, в которой говорится, что она использует Fisher-Yates: github.com/golang/go/blob/master/src/math/rand/…

Solomon Ucko 30.03.2023 16:19

«что не кажется очень рандомизированным» - как вы это определяете? случайный не означает равномерно распределенный, это означает случайный, который отлично подходит для вывода. Если вы хотите измерить его, запустите его миллион раз и постройте гистограмму.

JimB 30.03.2023 16:29

Попробуйте запустить его много раз и посчитайте, сколько раз встречается каждая перестановка.

Solomon Ucko 30.03.2023 16:29

Спросите себя: сколько существует различных перестановок 1, 2, 3? Запишите их все. Выберите одну из этих перестановок случайным образом (не нужно перемешивать).

Volker 30.03.2023 17:09
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
5
104
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]

БИНГО! Спасибо, что заметили крошечную деталь, которую другие не смогли определить!

xpt 03.04.2023 16:56

Другие вопросы по теме