Kami diberi generator bilangan acak RandNum50
yang menghasilkan bilangan bulat acak seragam di kisaran 1-50. Kami hanya dapat menggunakan generator angka acak ini untuk menghasilkan dan mencetak semua bilangan bulat dari 1 hingga 100 dalam urutan acak. Setiap angka harus tepat satu kali, dan probabilitas setiap angka yang terjadi di tempat mana pun harus sama.
Apa algoritma yang paling efisien untuk ini?
algorithms
integers
randomness
random-number-generator
Raj Wadhwa
sumber
sumber
RandNum100 = (RandNum50() * 2) - (RandNum50 > 25) ? 0 : 1)
.Jawaban:
Saya pikir (jadi bisa salah :-) dari solusi yang menggunakan shuffle Fisher-Yates . Untuk menjaga distribusi yang seragam dengan pendekatan yang baik (lihat bagian EDIT di bawah) di setiap iterasi Anda dapat menggunakan trik ini untuk menghasilkan nilai antara 0 dan k - 1 :O ( N2) 0 k - 1
krand
Algoritma Fisher-Yates menjadi:
EDIT:
krand
sumber
Karena orang lain telah memberikan solusi perkiraan dan solusi yang melibatkan pengambilan jumlah penyimpangan yang tidak pasti, bagaimana dengan bukti bahwa tidak ada algoritma yang dijamin hanya membutuhkan jumlah
RandNum50()
panggilan yang terbatas ?RandNum50
RandNum50
RandNum50
sumber
Jika Anda tidak tahu cara membuat seragam, seperti yang disarankan dalam posting itu, dari bit acak, Anda juga bisa menghasilkan perkiraan seragam secara langsung, dengan cara ini (yang setara dengan "reallyrand" Vor, tetapi lebih cepat):
sumber
Saya belum melakukan analisis untuk mengkonfirmasi seberapa seragam (atau tidak) ini akan, dan itu bisa disesuaikan menjadi shuffle yang benar, tetapi bisakah Anda memilih, dari susunan awal dari
i
indeks th =i + 1
,(k + RandNum50() + RandNum50() - 1) mod (100 - k)
indeks, dengan penghapusan, untukk
= 0,99?Ini "mendorong" puncak
RandNum50() + RandNum50()
distribusi ke depan secara seragam.Saya cukup yakin ini tidak tepat seperti yang saya nyatakan karena 0 index (1) tidak dapat diperoleh dari pilihan pertama dan saya tidak dapat dengan cepat melihat alternatif 1..50 + 1..50 penyesuaian yang menghasilkan 0 ..99.
Memperbarui
Untuk memperbaiki masalah yang saya catat, saya secara efektif digunakan
RandNum100
seperti yang disebutkan dalam komentar pertanyaan untuk menginisialisasik
offset pertama secara acak .Ini menghasilkan distribusi dengan gelombang yang signifikan di bagian depan.
Alih-alih maju dengan 1 saya menggunakan yang lain
RandNum50
untuk meningkatkan itu terlebih dahuluk
. Ini menghasilkan hasil yang cukup acak bagi saya, tetapi masih tidak "benar-benar" acak, seperti yang dapat dengan mudah dilihat jika Anda mengubah K menjadi 2.Menguji kode VB.NET di mana saya melayani bahkan K. Catatan itu adalah O (K), 6K + 2 sebenarnya.
sumber