Perbaiki fungsi acak yang rusak

18

Seorang teman memiliki kartu tambahan di komputer mereka yang menghasilkan angka acak sempurna dari 1 hingga 5 inklusif. Sayangnya, mereka menumpahkan cola di atasnya, dan sekarang hanya menghasilkan 2 untuk semua angka dari 1 hingga 4. Untungnya keacakan dipertahankan, tetapi 2 memiliki probabilitas 80% dan 5 memiliki probabilitas 20%, dan tidak ada 1, 3 atau 4 dihasilkan. Dengan menggunakan sumber acak ini (sebut saja BrokenRand()atau sejenisnya), tulis generator angka acak yang berfungsi yang menghasilkan angka dari 1 hingga 5 masing-masing dengan probabilitas 20% sama dengan keacakan sempurna yang sama dengan sumber aslinya.

Kemenangan program terpendek. Poin bonus diberikan untuk jumlah panggilan minimum yang tidak BrokenRandmemihak oleh konsultan fokus layanan pelanggan yang dipilih secara demografis, yang dirinci menurut usia dan jenis kelamin - yaitu saya.

Thomas O
sumber

Jawaban:

10

JavaScript - 69 karakter

Ini menggunakan ekstraktor von Neumann untuk menghasilkan bit yang tidak bias; algoritma umum juga dijelaskan di situs web HotBits . Tiga bit digunakan untuk membentuk angka dari 0 hingga 7. Semua angka 5 dan di atas dibuang, dan 1 ditambahkan ke masing-masing sisanya sebelum dicetak. Saya membuat simulasi untuk menunjukkan bahwa ini tidak berat sebelah .

Anda perlu menyediakan fungsi Anda sendiri r()untuk mengakses RNG.

 for(;;v<5&&alert(v+1))for(v=i=0;i<3;a-b&&(v*=2,v+=a<b,i++))b=r(a=r())
Tolong berdiri
sumber
Ini dilakukan dengan sangat baik! Saya suka bagaimana Anda melakukan hubungan pendek nilai kenaikan.
snmcdonald
Anda dapat menghasilkan 7 bit dan mengekstrak 3 angka acak untuk mengurangi panggilan ke BrokenRand, tetapi itu mungkin akan membutuhkan beberapa pukulan lagi
gnibbler
5

scala 79 chars:

// preparation: 
val r = util.Random 
def defektRNG = if (r.nextInt (5) == 0) 5 else 2 

(1 to 20).foreach (_ => print (" " + defektRNG))
// first impression:
// 2 2 2 2 2 2 2 5 2 2 5 2 2 2 5 2 2 2 2 2

def rnd : Int = { val k = (1 to 5).map (_ => defektRNG)
  if (k.sum == 13) k.findIndexOf (_ == 5) + 1 else rnd } 

// first impression:
(1 to 20).foreach (_ => print (" " + rnd))             
// 3 3 2 3 5 2 2 5 1 1 3 4 3 2 5 3 3 1 5 4
// control:
(1 to 50000).map (_ => rnd).groupBy (identity) .map (_._2.length) 
// scala.collection.immutable.Iterable[Int] = List(10151, 9997, 9971, 9955, 9926)

Sekarang untuk golf asli, defektRNG alias brokenRand diubah namanya menjadi b.

def r:Int={val k=(1 to 5).map(_=>b)
if(k.sum==13)k.findIndexOf(_==5)+1 else r} 

Cara kerjanya: Paling sering, b mengembalikan urutan 2s. Tetapi jika Anda melakukan 5 panggilan ke b, Anda akan sering berakhir dengan hasil 4x2 dan 1x5, ini adalah acara yang paling mungkin kedua, dan bisa 5-2-2-2-2, 2-5-2-2 -2, 2-2-5-2-2, 2-2-2-5-2 dan 2-2-2-2-5.

Ini memiliki kesamaan, bahwa jumlahnya adalah 4 * 2 + 5 = 13. Indeks lima pertama dapat digunakan untuk menentukan angka acak yang valid. Jika ada lebih atau kurang dari satu 5, jumlah yang lebih besar atau lebih rendah 13, ulangi.

Penghitung di 'rnd' alias 'r' dapat menunjukkan berapa banyak panggilan yang diperlukan secara rata-rata untuk menghasilkan nomor. Ada 121 200 panggilan ke r untuk 50.000 nomor acak, yang tidak mengesankan. :)

Pengguna tidak diketahui
sumber
3

> <> (Ikan) - 55 byte

Diperbarui untuk menggunakan algoritma yang sama dengan @user yang tidak dikenal dalam jawaban skala-nya

<v? = d + &: i & + &: i & + &: i & + &: i &: i
 0
 > 1 + $ 5 (? Vnao;
 ^ <

Diharapkan generator yang rusak terhubung ke stdin; inilah skrip python yang saya gunakan . Kode cocok dengan spesifikasi Ikan saat ini, tetapi saya menggunakan versi penerjemah lama yang sudah dimodifikasi .

bash:$ for i in $(seq 1000); do ./bad_rand.py | ./myfish.py rand.fish; done >res.txt
bash:$ for i in $(seq 5); do echo -n "$i : "; grep -c $i res.txt; done
1 : 193
2 : 204
3 : 198
4 : 206
5 : 199

Saya akan melakukan sampel yang lebih besar tetapi lambat.

cthom06
sumber
2

GolfScript, 23 byte

Jawaban terlambat, tetapi karena ini kebetulan muncul di halaman depan ...

0{;[{r}5*].5?)\5-,4-}do

Menggunakan algoritma yang sama dengan solusi Scala yang tidak diketahui pengguna . Diasumsikan bahwa generator nomor acak yang bias diberikan sebagai subrutin GolfScript bernama r; Anda dapat menentukan sendiri RNG yang bias misalnya:

{5rand!3*2+}:r;

Berikut ini adalah tes cepat yang menunjukkan kurangnya bias. Sayangnya, server GolfScript online agak lambat, jadi saya harus memotong demonstrasi menjadi hanya 100 sampel agar selesai tepat waktu. Jika menjalankan tes secara lokal dengan interpreter GolfScript , coba tingkatkan 100*ke 1000*atau bahkan 10000*.

(Server GolfScript juga kadang-kadang membeku secara acak dan waktu habis. Jika ini terjadi untuk Anda, mencoba lagi biasanya menyelesaikannya. Ini terjadi dengan kode lain juga, dan hanya terjadi di server, bukan di komputer saya sendiri, jadi saya yakin bahwa itu masalah dengan server dan bukan dengan kode saya.)

Ilmari Karonen
sumber
-1

javascript, 160 karakter tanpa mengurangi pembacaan alias optimasi

function giveRandom(){
    var result = Math.floor(5 * Math.random()) + 1;
    while(BrockenRand() != 5){
        result = Math.floor(5 * Math.random()) + 1;
    }
    return result;
}
www0z0k
sumber
@ snmcdonald -beberapa dari itu bukan kesalahan ketik, ini adalah cara untuk meningkatkan js acak dengan generator acak yang sempurna hanya menyetujui (benar-benar acak!) 20% hasilnya
www0z0k
Mau jelaskan apa BrockenBand()itu?
Mateen Ulhaq
6
Saya pikir Anda melewatkan intinya
cthom06
@muntoo - artinyaBrockenRand
www0z0k
Simpan beberapa byte dengan cara ini:function giveRandom(){return Math.ceil(Math.random()*5)}
user300375