Sementara ada banyak pertanyaan kode golf di sini yang melibatkan keacakan, saya belum melihat satu yang benar-benar meminta untuk membangun generator nomor pseudorandom algoritmik. Ada satu ini yang meminta Anda untuk menghasilkan aliran bit, tetapi tes keacakan yang disediakan di salah satu yang tidak sangat ketat, dan itu bukan kode-golf.
Program yang Anda tulis akan memiliki fungsi yang dapat dipanggil tunggal yang akan mengembalikan integer acak dari 0 hingga 4294967295. Fungsi ini tidak boleh memanggil perpustakaan atau fungsi lain yang tidak juga ditulis sebagai bagian dari program, terutama panggilan ke / dev / random atau pustaka rand () bawaan bahasa. Lebih khusus, Anda terbatas pada operator dasar bahasa tempat Anda bekerja, seperti aritmatika, akses larik, dan pernyataan kontrol aliran bersyarat.
Skor program Anda dihitung sebagai berikut:
Score = C / R
Di mana C adalah panjang kode dalam karakter, dan R adalah jumlah tes Diehard yang dilewati generator Anda (Jika generator angka acak Anda tidak lulus setidaknya satu tes Diehard, nilainya tak terhingga dan didiskualifikasi). Generator Anda lulus uji Diehard jika file yang dihasilkannya memberikan kisaran nilai-P yang tampaknya didistribusikan secara merata di sepanjang interval [0, 1).
Untuk menghitung R, gunakan pembangkit angka acak Anda dengan seed default untuk menghasilkan file data biner 16 MB. Setiap panggilan fungsi mengembalikan empat byte; jika fungsi Anda terlalu lambat untuk mengembalikan byte, ini akan menjadi faktor trade-off untuk mencapai skor rendah dengan seberapa sulitnya untuk menguji. Kemudian, jalankan melalui tes Diehard dan periksa nilai-P yang disediakan. (Jangan mencoba dan menerapkannya sendiri; gunakan yang disediakan di sini )
Skor terendah menang, tentu saja.
sumber
Jawaban:
Mathematica, 32/15 = 2.133
Implementasi BBS yang mudah .
File biner dihasilkan dengan:
Ringkasan hasil:
Penuh
random.bin
disini.File log lengkap di sini.
sumber
28!-67
agak penghalang. Apakah ada nilai yang lebih kecil yang cocok dengan integer 64-bit?Perl 28/13 ≈ 2.15
file log di sini
Perl 29/13 ≈ 2.23
file log di sini
Ini adalah sesuatu variasi pada Xorshift , menggunakan pembagian floating point alih-alih shift yang tepat. Keduanya lulus 13 dari 15 tes, hanya gagal tes 6 dan 7.
Saya tidak yakin berapa lama siklusnya, tetapi karena kode berikut ini tidak berakhir dalam waktu singkat, kemungkinan penuh 2 32 :
Perl 39/10 = 3,9
Catatan: jika Anda mencari PRNG Blum-Blum-Shub-esque, solusi Keith Randall jauh lebih baik daripada keduanya.
Seperti dengan solusi asli saya di bawah ini, ini juga merupakan implementasi dari Blum Blum Shub, dengan satu perbedaan utama. Saya menggunakan modulus sedikit lebih besar dari 2 32 ( M = 50971 • 84263 ), dan setiap kali nilai ditemukan bahwa itu bukan bilangan bulat 32-bit yang valid (yaitu, lebih besar dari 2 32 ), ia mengembalikan nilai berikutnya dalam rotasi sebagai gantinya. Pada dasarnya, nilai-nilai ini dipangkas, meninggalkan sisa rotasi tidak terganggu, menghasilkan distribusi yang hampir seragam.
Tampaknya telah membantu. Selain lulus 9 tes yang sama seperti sebelumnya, sekarang dengan meyakinkan melewati tes Jarak Minimum. File log sampel dapat ditemukan di sini .
Perl 33/9 ≈ 3.67 (Tidak valid?)
Catatan: solusi ini mungkin dianggap tidak valid, karena 0,00037% teratas dari rentang tidak akan pernah diamati.
Implementasi Blum Blum Shub yang cepat dan kotor . Saya mengklaim hasil berikut:
File log sampel dapat ditemukan di sini , jangan ragu untuk menyengketakan hasil apa pun. File untuk diehard dapat dibuat dengan cara berikut:
dan kemudian menyalurkan output ke file. Jarak Minimum sepertinya sudah terlewati, tetapi jika Anda menjalankannya berkali-kali selalu sangat dekat dengan 1,0 , yang mengindikasikan kegagalan.
Detail
Secara umum, Blum Blum Shub adalah PRNG yang mengerikan, tetapi kinerjanya dapat ditingkatkan dengan memilih modulus yang baik. The M Aku telah memilih adalah 7027 • 611.207 . Kedua faktor utama ini, p dan q , memiliki residu modular 3 (mod 4) , dan gcd (φ (p-1), φ (q-1)) = 2 , yang serendah mungkin.
Meskipun ini adalah satu-satunya kriteria yang tercantum pada halaman wiki, sepertinya tidak cukup. Hampir semua modulo yang saya coba gagal setiap tes. Tetapi ada beberapa yang akan lulus beberapa tes, dan yang saya pilih tampaknya sangat bagus, untuk alasan apa pun.
Sebagai catatan terakhir, Tes 5 sendiri tampaknya menjadi indikator yang cukup baik tentang seberapa baik PRNG. Jika hampir tidak lulus Tes 5, itu akan gagal sisanya secara spektakuler.
BONUS: Perl 62/14 ≈ 4.43
Hanya untuk geekery, ini adalah versi 32-bit dari PRNG yang digunakan dalam Tetris asli untuk NES. Hebatnya, ini lulus 14 dari 15 tes!
Sampel file log bisa sebelum di sini .
Memang,
1..37
bit itu bukan transkripsi yang tepat. Dalam versi asli, rutin entropi diperbarui 60 kali per detik, dan kemudian ditanyai secara acak, sebagian besar tergantung pada input pengguna. Bagi siapa pun yang ingin membongkar ROM, rutinitas entropi dimulai pada0xAB47
.Kode semu gaya-python:
sumber
Python, 46/15 = 3.0666
Menggunakan eksponensial modular untuk menghasilkan keacakan. 2 ** 32-5 adalah prime terbesar kurang dari 2 ^ 32. (Kesepakatan yang sama dengan tidak bisa menjalankan tes # 2.)
sumber
\r
dan\n
ke\r\n
, yang jelas mengacaukan hasilnya. Cara mengatasinya adalah menulis file secara langsung menggunakanf = open('file.bin', 'wb')
danf.write
.Ruby, 32/15 = 2.1333
Ini adalah solusi Keith Randall, diimplementasikan di Ruby.
sumber
C # 144/15 = 9,6
Ini melewati semua tes.
Dengan tidak terlalu banyak karakter, ia melewati TestU01.
Hasil: http://codepad.org/iny6usjV
sumber
C # - 103/14 = 7.36
Hasil
Lewati semua kecuali tes # 6
Lihat hasil di http://codepad.org/k1NSoyQW
Penjelasan
C # tidak bisa bersaing dengan Ruby dan Python untuk mendapatkan kesederhanaan, seperti biasa, tetapi saya senang mencoba. Tentu saja ada nilai-nilai lain yang akan berfungsi dengan baik (yaitu, nilai awal untuk j = 999, dan pembagi = 277). Saya memilih ini setelah eksperimen singkat.
Dengan pembungkus pembuatan file
sumber
Python, 41/15 = 2.73333
Agak curang menggunakan built-in fungsi hash, tetapi adalah built-in, sehingga tidak ada lagi kecurangan daripada menggunakan builtin lainnya, seperti
len
. Di sisi lain, saya harus membayar untukglobal v;
pernyataan ...Lulus semua tes Diehard (saya punya masalah dengan tes # 2, itu SEGV pada mesin OSX saya. Untuk skor saya, saya menganggap itu akan lulus).
Inilah driver untuk menghasilkan file 16MB:
sumber
+
fungsi bawaan, dan karenanya didiskualifikasi?+
dan__add__
dalam python, atau operator kelebihan dalam c ++. Saya tahu saya agak suka membelah rambut, jadi pertimbangkan contoh ini. Dengan python, bisakah saya membuat peta seperti ini{'a':5}
:? Anda mungkin akan mengatakan ya, tetapi kemudian mempertimbangkan bahwa di balik selimut,hash('a')
dipanggil ketika Anda melakukan itu.C, 38/15 = 2.533
Saya tidak bisa mendapatkan tes Diehard bekerja pada mesin saya, tetapi melewati suite PractRand hingga 8GB output jadi saya berasumsi itu akan melewati semuanya.
sumber
Brain-Flak , 344 / (tertunda)
Cobalah online!
Ini berfungsi dengan baik tetapi tautan tes diehard semuanya rusak :( jadi sampai kami mendapatkan yang baru saya tidak memiliki skor akhir
Ini menggunakan Blum Blum Shub PRNG sehingga harus melewati sebagian besar kasus. Jumlah yang digunakan cukup besar, tidak ada pola yang akan muncul dalam 16 MB kasus uji
sumber
Objective-C, 40/1 = 40
Pendekatan yang cukup pintar, mengeksploitasi
.hash
agak curang di sini, tapi saya sukasumber