Terinspirasi secara acak dengan tangan terikat :
Target
Tujuan dari tantangan ini adalah untuk menulis sebuah program yang menghasilkan bit stream pseudorandom, yang merupakan string 1s dan 0s yang tampaknya murni acak, tetapi sebenarnya dihasilkan dengan cara deterministik. Program Anda harus menampilkan string 1 dan 0s (dengan spasi kosong opsional) dan harus melewati persyaratan berikut:
- Dengan waktu dan memori yang tidak terbatas, program Anda harus terus menghasilkan string 1s dan 0s selamanya
- Program Anda harus mengeluarkan lebih dari 1000 bit acak dalam waktu sekitar satu menit, pada mesin yang masuk akal. Jika persyaratan ini tidak mungkin, maka saya akan menguranginya.
- String bit dapat diulang, tetapi panjang bagian berulang harus lebih dari 1000 bit.
- String bit harus lulus sebanyak mungkin tes keacakan (dijelaskan di bawah) sebanyak mungkin.
- Program tidak boleh mengambil input dari sumber eksternal apa pun atau menggunakan fungsi bawaan () - seperti apa pun.
- Karena persyaratan di atas, program harus menampilkan string bit yang persis sama setiap kali dijalankan.
Uji Keacakan # 1
String bit pseudorandom tidak boleh menyertakan pola yang jelas pada inspeksi visual.
Uji Keacakan # 2 (dapat berubah berdasarkan komentar)
String bit harus mengandung distribusi yang sama antara 1s dan 0s. Untuk menguji ini (dan hal lainnya juga), aliran bit dipecah menjadi segmen yang panjangnya 3 bit, seperti 101|111|001
.
Dari semua segmen ini, 1/8 dari mereka harus memiliki tiga 1s dan tidak ada 0s, 3/8 dari mereka harus memiliki dua 1s dan satu 0, 3/8 dari mereka harus memiliki satu 1 dan dua 0s, dan 1/8 dari mereka seharusnya tidak memiliki 1 dan tiga 0.
Uji Keacakan # 3
"Jalankan" didefinisikan sebagai serangkaian bit berurutan yang semuanya memiliki nilai yang sama. String 1001001110
memiliki tiga kali run ukuran 1 ( 1..1.....0
), dua kali run ukuran 2 ( .00.00....
) dan satu kali run dari ukuran 3 ( ......111.
). Perhatikan bahwa menjalankan tidak tumpang tindih.
Dari string 1000 bit acak, harus ada sekitar 250 run ukuran 1, 125 run ukuran 2, 62 run ukuran 3, dll. Secara umum, untuk run size R, harus ada sekitar 1000/(2**(R+1))
run dari ukuran itu.
Uji Keacakan # 4
840 bit pertama dibagi menjadi dua bagian masing-masing 420 bit. Setiap bit di babak pertama dibandingkan dengan bit yang sesuai di babak kedua. Dua bit harus cocok dengan sekitar lima puluh persen dari waktu.
Berikut ini adalah kode sumber dari program Perl yang melakukan tes 2 hingga 4. Sampai sekarang, itu memerlukan string bit tidak mengandung spasi.
Waktu Kriteria Kemenangan yang Objektif!
Pemenangnya adalah program yang lulus semua 6 persyaratan dan semua tes keacakan sejauh tidak bisa dibedakan dari keacakan. Jika beberapa program mencapai ini, maka program yang membutuhkan waktu paling lama untuk mengulang akan menang. Jika beberapa program mencapai ini, maka saya mungkin harus menemukan lebih banyak tes keacakan untuk bertindak sebagai tie-breaker.
sumber
Jawaban:
C, 61
Ya, saya tahu ini bukan kode golf. Ini jelas merupakan anti-solusi ... tetapi cukup memenuhi kriteria Anda.
Panjang periode adalah 2²⁹.
sumber
Mathematica
7853 karakterAngka-angka dari representasi biner dari Pi tampaknya berperilaku seolah-olah mereka diproduksi secara kacau meskipun ini tidak terbukti.
Rutin sederhana berikut secara deterministik mengembalikan sebagai string digit biner pi, yang sesuai dengan
d
digit desimal:Pemakaian
Jika kami meminta rekanan dari 301 digit desimal Pi, kami menerima 1000 digit biner.
Karena Pi adalah bilangan irasional, tidak ada periode. Namun, akan ada kendala praktis karena perangkat keras berjalan.
Tes 1 Terlihat bagus untuk saya.
Tes 2
Pemeriksaan lebih teliti:
Tes 3: Berlari
Saya menjalankan sejumlah besar kasus untuk memeriksa distribusi proses secara sistematis. Dalam kira-kira 3 juta digit biner, ada 830k berjalan dari 1, 416k berjalan dari 2, 208k berjalan dari 3, 104k berjalan dari 4, dll.
Tes 4: Pencocokan data bagian pertama dan kedua
Pertandingan adalah 212 kasus 0 dan 2; ketidakcocokan adalah 208 kasus di mana jumlah dari masing-masing digit adalah 1.
Pengaturan waktu
Dibutuhkan di bawah dua detik untuk menghitung 3321928 digit biner (sesuai dengan 10 ^ 6 angka desimal).
sumber
e
alih-alihpi
menyimpan satu byte?e
didistribusikan secara kacau?Python, 90
g
adalah nilai benih. Pengambilan sampel secara acak menunjukkan distribusi yang luar biasa normal, pengulangan sampel secara acak dari sampel berarti menghasilkan rata-rata0.506
dan standar deviasi.0473
(ukuran sampel 1000). Sayangnya, keacakan sangat sensitif terhadap benih awal. Benih dalam kode di atas memberi saya keacakan yang terbaik: pMEMPERBARUI
Mari kita lihat bagaimana kode ini bertahan pada pengujian OP:
Tes # 1
Yang ini agak subyektif ... tapi kelihatannya tidak biasa bagi saya.
Tes # 2
Tes # 3
Dijalankan berdasarkan ukuran:
Tes # 4
sumber
Haskell
7458Berkat shiona untuk penyederhanaannya. Hasil:
Ini juga merupakan generator pseudo-acak yang mengerikan (mirip dengan yang digunakan oleh von-Neuman). Bagi mereka yang tidak sadar
concatMap == (=<<) == flip . (>>=)
(untuk daftar)sumber
\x->if odd x then"1"else"0"
denganshow.(`mod`2)
.Pertanyaannya pada dasarnya setara dengan "mengimplementasikan stream cipher". Jadi saya mengimplementasikan RC4, karena ini relatif sederhana.
Saya tidak menggunakan kunci, dan menjatuhkan 100000 bit pertama, karena awal RC4 agak bias, terutama karena saya melewatkan jadwal kunci. Tapi saya berharap untuk lulus ujian Anda bahkan tanpa itu (menghemat 20 karakter kode).
Biasanya satu akan menghasilkan byte penuh per siklus, tetapi mengkonversi ke biner agak jelek di C #, jadi saya hanya membuang semuanya kecuali yang paling tidak signifikan.
Atau tanpa spasi:
C #, 156 karakter, bekerja dalam mode pernyataan LinqPad. Untuk program C # lengkap tambahkan boilerplate biasa.
Kita juga dapat menggunakan primitif kripto bawaan (solusi Penipu):
(C #, 99 karakter, berfungsi dalam mode pernyataan LinqPad. Untuk compiler C # yang normal, Anda perlu menambahkan sedikit boilerplate)
Output dari fungsi hash kriptografis dirancang agar tidak dapat dibedakan dari data acak, jadi saya berharap ini untuk lulus semua tes keacakan (mati lebih keras, ...) Anda melemparkannya, tapi saya terlalu malas untuk menguji.
sumber
C, 52 karakter
Ini adalah LFSR 10 bit, hasil pengujian:
sumber
a
harus dimulai sebagai 1, (dengan asumsi itu disebut tanpa argumen). Anda juga bisa tetapa=
di tengah, sesuatu sepertia=a/2^-!putchar(49-a%2)%576
(mengambil beberapa kebebasan dengan algoritma)a
, saya mengubahnya karena "The program must not take any input from any external sources
"Sage / Python
Program ini mencetak digit biner paling kanan yang umum untuk setiap menara eksponensial yang cukup tinggi dari bentuk 3 3 3 3 . . . Untuk semua yang bisa dihasilkan secara layak, ini adalah angka biner paling kanan dari nomor Graham . Urutan digit tidak terbatas, dan tidak periodik.
Untuk 1000 digit, ini membutuhkan waktu kurang dari 2 detik; Namun, waktu akan meningkat lebih cepat daripada linear dalam jumlah digit.
Hasil pengujian menggunakan program OP adalah
(Lihat Apakah digit paling kanan dari G acak? Untuk lebih dari 32.000 digit dan tes statistik tambahan.)
sumber
Jawa,
371317Berdasarkan LFSR 128 bit (ketukan bit berasal dari xilinx app note 52 )
EDIT: Saya tidak puas menggunakan BigInteger sehingga versi ini tidak. Menyimpan beberapa karakter. Output mungkin sedikit kurang acak karena saya tidak bisa memikirkan metode 'seeding' yang baik.
Kode Baru: Argumen: BITS_TO_PRINT
Versi Lama: Argumen: SEED, BITS_TO_PRINT
Versi Baru: Contoh output, bit = 100:
sumber
JavaScript - 1ms to 2ms untuk 1000 pseudo-random bits (139ms to 153ms untuk 100000 bits)
Solusi ini menggunakan fakta bahwa akar kuadrat itu tidak rasional, dan dengan demikian cukup acak. Pada dasarnya, dibutuhkan akar kuadrat dari 2 untuk memulai, mengubahnya menjadi biner, membuang bagian terkemuka yang cocok dengan root sebelumnya, menambahkannya ke string acak, mengulangi dengan angka yang lebih tinggi berikutnya (atau kembali ke 2 jika angka tersebut diulang dan setidaknya 30 bit panjang), dan mengembalikan string acak setelah cukup lama.
Saya belum menjalankan tes, tetapi saya membayangkan itu akan berhasil pada mereka. Ini biola sehingga Anda bisa melihatnya beraksi. Untuk waktu saya, saya hanya menjalankan program beberapa kali dan mengambil nilai tercepat dan paling lambat sebagai rentang.
sumber
Python
Seharusnya memiliki periode sekitar 2 ^ 512.
sumber
perl, 44 byte
Saya tahu ini bukan kode golf, tapi saya selalu suka mengambil bit orde rendah dari fungsi kuadratik sederhana, misalnya:
Periode lebih dari 3 miliar, tetapi saya sudah kehabisan ruang disk untuk menghitung lebih banyak.
sumber
$x=1/7;print substr($x*=4-4*$x,9,1)%2while 1