Pull to refresh

Comments 22

Да - под капотом всех шаффлов - перестановки Кнута.
Алгоритм работающий за линию и на выходе дающий честные* 1/n вероятности попадания для каждого элемента в любое место на выходе.
У Кнута в его "Искусстве программирования" есть доказателство.
*настолько честные - насколько ваш рандом "честен"

п.с. лет 10 на собесах давал эту задачу и следом "а как бы вы протестили что ваше решение дает честные 1/n"

Спорна сама уверенность в "лучшести" некого алгоритма генерации случайного числа. Бросая кости, вы же не мыслите логикой. что следующее число очков будет зависеть от результата предыдущего броска.

Почему? Если желаемое распределение выхлопа этой функции. Смотрим результат и сравниваем с желаемым распределением. Оцениваем хорошесть.

Кроме диапазона и процессорной логики разве не должен быть какой-то фактор из материального мира

/dev/urandom вам точно не подойдет?

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

Автор не умеет в лаконичность. Например, весь параграф про недостаток наивного алгоритма можно выразить одним предложением, что n^n не делится на n!, потому что n и (n-1) взаимно просты, и значит перестановки распределятся не поровну по исходам.

В древней Спарте такая подача материала не сошла бы автору с рук.

Ох уж эти математические дискурсы на кулаках, которыми известна древняя Спарта. Вы допускаете, что автор написал понятнее для тех, кто лучше понимает формулы + текстовые описания? Тем более это перевод.

var shuffledcards = cards.OrderBy(a => Guid.NewGuid());

Я представил, что было бы, если бы нынешние оптимизаторы сишных компиляторов добрались до дотнета. Они бы всем показали. Если Guid.NewGuid() не является полем a, значит программист сам не знает, чего хочет, а дальше было бы как в анекдоте про return 4; // Random enough.

Нам ещё везёт, что OrderBy кэширует значение NewGuid().

А если бы делегат вызывался при каждом сравнении внутри сортировки?

написано синхронизация по времени и далее предлагается очень нагрузный алгоритм KFY - я посмотрел на картинке его алгоритм первое о чем подумал что он еще проще предсказуем, перечитал еще раз участок текста с синхронизацией посмотрел граффик и пока ничего не понял(чтобы сделать ту синхронизацию наверняка надо всё понимать еще лучше чем с такой сортировкой)

low (50<) :30496
high (50>) :29504

наивный бросок монетки уложился в 50 процентов или должно быть иначе?

сортировать по некоторому Guid

Так Guid сам под капотом использует рандом, разве нет? Общей энтропии конечно больше ест, но при размере массива в 52 элемента уровень случайности перемешивания лучше едва ли станет.

Вспоминается университетская лабораторная по криптографии — всех подробностей уже не восстановить, но среди прочего тоже нужно было случайно перемешать массив.

Я придумал, как мне тогда казалось, ловкое и практичное решение: завёл второй массив той же длины, заполнил его случайными числами, а потом отсортировал, при этом зеркально повторяя все перестановки в основном массиве.

Кто-то нашёл в статье чёткий критерий "качества" перемешивания?

Там раза три написано. Перемешано качественно означает что вероятность любого расклада (порядка карт в колоде) одинакова.

Ещё один эквивалентный критерий, который иногда удобнее в доказательстве — это то, что каждый элемент на каждой позиции окажется равновероятно.

каждый элемент на каждой позиции окажется равновероятно

Не назвал бы эквивалентным. Пример таблицы вероятностей:

Скрытый текст
  • 123 - 33.(3)%

  • 132 - 0%

  • 231 - 33.(3)%

  • 213 - 0%

  • 312 - 33.(3)%

  • 321 - 0%

Каждый элемент на каждой позиции встречается равновероятно, но при этом вероятность у отдельных комбинаций совершенно разная.

К замечанию про рандом-из-миллисекунд хочу добавить, что давно пора форсировать, что все random-ы по умолчанию используют максимально честный криптографический недетерминированный рандом (если не аппаратный генератор, то хотя бы Yarrow или Fortuna), а детерминированные оставить для математиков с явно помеченными именами.

Ну а наивный переставлятор... изначально плохо пах. Но чтобы это из ощущения превратить в твёрдый вывод, тут и нужна математика.

К правильному решению можно прийти проще. Что нам надо сделать? Перемешивание. Точнее, модель реального перемешивания. Как выглядит реальное перемешивание? Берем несколько карт из случайной позиции, и помещаем в другое место среди других карт. Для лучшего перемешивания надо брать по одной. Что означает "берем"? Что мы физически убираем карту из колоды. Когда она перемещается в другую позицию, она находится в руке, а не в колоде.

Значит в коде, который моделирует процесс перемешивания, должно быть 2 списка карт. Второй изначально пустой. Берем случайный индекс от 0 до длины первого списка, убираем карту из первого списка, добавляем во второй. Суммарная длина двух списков всегда равна длине исходного, поэтому можно оптимизировать и использовать конец первого списка как второй список. А вместо сдвигов нескольких карт в первом списке на 1 элемент можно ставить на пустое место последнюю карту, все равно индексы случайные.

Sign up to leave a comment.

Articles