В то время как здесь есть много вопросов о кодовом гольфе, связанных со случайностью, я еще не видел ни одного, который бы на самом деле требовал создания алгоритмического генератора псевдослучайных чисел. Есть один, который просит вас генерировать поток битов, но тесты случайности, предоставленные на этом, были не очень строгими, и это не код-гольф.
В написанной вами программе будет одна вызываемая функция, которая будет возвращать случайное целое число от 0 до 4294967295. Эта функция не должна вызывать какие-либо библиотеки или другие функции, которые также не были написаны как часть программы, особенно вызовы / dev / random или встроенная в язык библиотека rand (). Более конкретно, вы ограничены базовыми операторами языка, на котором вы работаете, такими как арифметика, доступ к массиву и операторы условного управления потоком.
Оценка вашей программы рассчитывается следующим образом:
Score = C / R
Где C - длина кода в символах, а R - количество тестов Diehard, которые ваш генератор прошел (если ваш генератор случайных чисел не прошел хотя бы один тест Diehard, его оценка равна бесконечности, и он дисквалифицирован). Ваш генератор проходит тест Diehard, если генерируемый им файл предоставляет диапазон значений P, которые, по-видимому, распределены равномерно по интервалу [0, 1).
Чтобы вычислить R, используйте генератор случайных чисел с его начальным значением по умолчанию для создания файла двоичных данных размером 16 МБ. Каждый вызов функции возвращает четыре байта; если ваша функция слишком медленная, чтобы возвращать байты, это приведет к компромиссу в достижении низкой оценки из-за сложности тестирования. Затем проведите его через тесты Diehard и проверьте предоставленные значения P. (Не пытайтесь реализовать их самостоятельно; используйте представленные здесь )
Самая низкая оценка выигрывает, конечно.
источник
Ответы:
Mathematica, 32/15 = 2,133
Простая реализация BBS .
Двоичный файл, созданный с помощью:
Сводка результатов:
Полный
random.bin
здесь.Полный файл журнала здесь.
источник
28!-67
несколько запредельно. Есть ли меньшее значение, которое поместится в 64-разрядное целое число?Perl 28/13 ≈ 2,15
файл журнала здесь
Perl 29/13 ≈ 2,23
файл журнала здесь
Это что-то вроде вариации Xorshift , использующего деление с плавающей точкой вместо правого смещения. Они оба проходят 13 из 15 тестов, не пройдя только тесты 6 и 7.
Я точно не знаю , как долго этот цикл, а потому , что следующий код не прекращается в любой короткий промежуток времени, то, скорее всего , полный 2 32 :
Perl 39/10 = 3,9
Примечание: если вы ищете PRNG от Blum-Blum-Shub-esque, решение Кейта Рэндалла намного лучше, чем любой из них.
Как и в моем исходном решении ниже, это также реализация Blum Blum Shub, с одним существенным отличием. Я использую модуль, немного больший чем 2 32 ( M = 50971 • 84263 ), и всякий раз, когда встречается значение, которое не является действительным 32-битным целым числом (то есть больше 2 32 ), оно возвращает следующее значение в вращение вместо. По сути, эти значения сокращаются, оставляя остальную часть вращения без помех, что приводит к почти равномерному распределению.
Кажется, это помогло. Помимо прохождения тех же 9 тестов, что и раньше, теперь он также убедительно проходит тест на минимальное расстояние. Пример файла журнала можно найти здесь .
Perl 33/9 ≈ 3,67 (неверно?)
Примечание: это решение может считаться недействительным, поскольку самый верхний 0,00037% диапазона никогда не будет наблюдаться.
Быстрая и грязная реализация Blum Blum Shub . Я требую следующие результаты:
Пример файла журнала можно найти здесь , не стесняйтесь оспаривать любой из результатов. Файл для diehard может быть сгенерирован следующим образом:
и затем скопировать вывод в файл. Минимальное расстояние выглядит так, как будто оно прошло, но если вы запускаете его несколько раз, оно всегда очень близко к 1,0 , что указывает на сбой.
подробности
В общем, Blum Blum Shub - ужасный PRNG, но его производительность можно улучшить, выбрав хороший модуль. M Я выбрал это 7027 • 611207 . Оба из этих простых факторов, p и q , имеют модульный остаток 3 (mod 4) , и gcd (φ (p-1), φ (q-1)) = 2 , что является настолько низким, насколько это возможно.
Хотя это единственные критерии, перечисленные на вики-странице, этого недостаточно. Почти все по модулю, которые я попробовал, провалились в каждом тесте. Но есть горстка, которая пройдет некоторые тесты, и тот, который я выбрал, кажется исключительно хорошим по любой причине.
В заключение отметим, что тест 5 сам по себе является довольно хорошим показателем того, насколько хорош PRNG. Если он почти не пройдет 5-й тест, он остальным провалится.
БОНУС: Perl 62/14 ≈ 4.43
Просто для гиков: это 32-битная версия PRNG, использованная в оригинальном Tetris для NES. Удивительно, но он проходит 14 из 15 тестов!
Пример файла журнала можно раньше здесь .
По общему признанию,
1..37
бит не является точной транскрипцией. В оригинальной версии процедура энтропии обновляется 60 раз в секунду, а затем запрашивается через случайные интервалы, в значительной степени зависящие от пользовательского ввода. Для тех, кто хочет разобрать ROM, процедура энтропии начинается с0xAB47
.Псевдокод в стиле Python:
источник
Python, 46/15 = 3,0666
Использует модульное возведение в степень для генерации случайности. 2 ** 32-5 - наибольшее простое число меньше 2 ^ 32. (То же самое касается невозможности запустить тест № 2.)
источник
\r
и\n
в\r\n
, что явно искажает результаты. Исправление - написать файл напрямую, используяf = open('file.bin', 'wb')
иf.write
.Рубин, 32/15 = 2,1333
Это решение Кейта Рэндалла, реализованное в Ruby.
источник
C # 144/15 = 9,6
Это прошло все испытания.
С не слишком большим количеством символов он проходит TestU01.
Результат: http://codepad.org/iny6usjV
источник
C # - 103/14 = 7,36
Результаты
Пройдено все, кроме теста №6.
См. Результаты на http://codepad.org/k1NSoyQW
объяснение
C # просто не может конкурировать с Ruby и Python за краткость, как обычно, но мне понравилось пробовать. Конечно, есть и другие значения, которые будут работать так же хорошо (т. Е. Начальное значение для j = 999 и делитель = 277). Я выбрал их после коротких экспериментов.
С оберткой для создания файлов
источник
Python, 41/15 = 2,73333
Любопытное обмана , используя встроенный в хэш - функции, но это не встроенная, так больше обмана , чем при использовании других встроенных команд, как
len
. С другой стороны, мне больно платить заglobal v;
заявление ...Проходит все тесты Diehard (у меня была проблема с тестом № 2, это SEGV на моей машине с OSX. На мой взгляд, я предполагаю, что это пройдет).
Вот драйвер для создания файла 16 МБ:
источник
+
ли встроенная функция и, следовательно, дисквалифицирована?+
и__add__
в python, или перегрузку операторов в c ++. Я знаю, что я немного расщепляю волосы, поэтому рассмотрим этот пример. В Python я могу создать карту , как это:{'a':5}
? Вы, вероятно, скажете «да», но затем подумайте, что под прикрытием вамhash('a')
звонят, когда вы это делаете.С, 38/15 = 2,533
Я не смог заставить тесты Diehard работать на моей машине, но он проходит набор PractRand для вывода до 8 ГБ, поэтому я предполагаю, что он пройдет их все.
источник
Brain-Flak , 344 / (ожидается)
Попробуйте онлайн!
Это работает нормально, но ссылки на несгибаемые тесты не работают :( так что пока мы не получим новые, у меня нет окончательного результата
При этом используется PRNG Blum Blum Shub, поэтому он должен пройти большинство случаев. Используемые числа достаточно велики, в 16 МБ тестовых случаев шаблоны не появятся
источник
Objective-C, 40/1 = 40
Довольно умный подход, использующий,
.hash
чтобы немного обмануть здесь, но мне это нравитсяисточник