Saya pikir saya punya empat jawaban, dua memberikan solusi tepat seperti yang dari @Adam Rosenfield tetapi tanpa masalah loop tak terbatas, dan dua lainnya dengan solusi yang hampir sempurna tetapi implementasi lebih cepat daripada yang pertama.
Solusi tepat terbaik membutuhkan 7 panggilan rand5
, tetapi mari kita lanjutkan untuk memahami.
Metode 1 - Tepat
Kekuatan jawaban Adam adalah bahwa ia memberikan distribusi seragam yang sempurna, dan ada probabilitas yang sangat tinggi (21/25) bahwa hanya dua panggilan ke rand5 () yang akan dibutuhkan. Namun, kasus terburuk adalah infinite loop.
Solusi pertama di bawah ini juga memberikan distribusi seragam yang sempurna, tetapi membutuhkan total 42 panggilan ke rand5
. Tidak ada loop tanpa batas.
Berikut ini adalah implementasi R:
rand5 <- function() sample(1:5,1)
rand7 <- function() (sum(sapply(0:6, function(i) i + rand5() + rand5()*2 + rand5()*3 + rand5()*4 + rand5()*5 + rand5()*6)) %% 7) + 1
Bagi orang yang tidak terbiasa dengan R, ini adalah versi yang disederhanakan:
rand7 = function(){
r = 0
for(i in 0:6){
r = r + i + rand5() + rand5()*2 + rand5()*3 + rand5()*4 + rand5()*5 + rand5()*6
}
return r %% 7 + 1
}
Distribusi rand5
akan dipertahankan. Jika kita menghitungnya, masing-masing dari 7 iterasi loop memiliki 5 ^ 6 kombinasi yang memungkinkan, sehingga jumlah total kombinasi yang mungkin adalah (7 * 5^6) %% 7 = 0
. Dengan demikian kita dapat membagi angka acak yang dihasilkan dalam kelompok yang sama dari 7. Lihat metode dua untuk diskusi lebih lanjut tentang ini.
Berikut ini semua kemungkinan kombinasi:
table(apply(expand.grid(c(outer(1:5,0:6,"+")),(1:5)*2,(1:5)*3,(1:5)*4,(1:5)*5,(1:5)*6),1,sum) %% 7 + 1)
1 2 3 4 5 6 7
15625 15625 15625 15625 15625 15625 15625
Saya pikir ini sangat jelas untuk menunjukkan bahwa metode Adam akan berjalan jauh lebih cepat. Probabilitas bahwa ada 42 atau lebih panggilan ke rand5
dalam solusi Adam sangat kecil ( (4/25)^21 ~ 10^(-17)
).
Metode 2 - Tidak Tepat
Sekarang metode kedua, yang hampir seragam, tetapi membutuhkan 6 panggilan ke rand5
:
rand7 <- function() (sum(sapply(1:6,function(i) i*rand5())) %% 7) + 1
Ini adalah versi yang disederhanakan:
rand7 = function(){
r = 0
for(i in 1:6){
r = r + i*rand5()
}
return r %% 7 + 1
}
Ini pada dasarnya adalah satu iterasi dari metode 1. Jika kami menghasilkan semua kombinasi yang mungkin, berikut adalah jumlah yang dihasilkan:
table(apply(expand.grid(1:5,(1:5)*2,(1:5)*3,(1:5)*4,(1:5)*5,(1:5)*6),1,sum) %% 7 + 1)
1 2 3 4 5 6 7
2233 2232 2232 2232 2232 2232 2232
Satu nomor akan muncul sekali lagi dalam 5^6 = 15625
uji coba.
Sekarang, dalam Metode 1, dengan menambahkan 1 hingga 6, kami memindahkan angka 2233 ke setiap titik berurutan. Dengan demikian jumlah total kombinasi akan cocok. Ini berhasil karena 5 ^ 6 %% 7 = 1, dan kemudian kita melakukan 7 variasi yang sesuai, jadi (7 * 5 ^ 6 %% 7 = 0).
Metode 3 - Tepat
Jika argumen metode 1 dan 2 dipahami, metode 3 mengikuti, dan hanya membutuhkan 7 panggilan ke rand5
. Pada titik ini, saya merasa ini adalah jumlah minimum panggilan yang diperlukan untuk solusi yang tepat.
Berikut ini adalah implementasi R:
rand5 <- function() sample(1:5,1)
rand7 <- function() (sum(sapply(1:7, function(i) i * rand5())) %% 7) + 1
Bagi orang yang tidak terbiasa dengan R, ini adalah versi yang disederhanakan:
rand7 = function(){
r = 0
for(i in 1:7){
r = r + i * rand5()
}
return r %% 7 + 1
}
Distribusi rand5
akan dipertahankan. Jika kita menghitungnya, masing-masing dari 7 iterasi loop memiliki 5 hasil yang mungkin, dengan demikian jumlah total kombinasi yang mungkin adalah (7 * 5) %% 7 = 0
. Dengan demikian kita dapat membagi angka acak yang dihasilkan dalam kelompok yang sama dari 7. Lihat metode satu dan dua untuk diskusi lebih lanjut tentang ini.
Berikut ini semua kemungkinan kombinasi:
table(apply(expand.grid(0:6,(1:5)),1,sum) %% 7 + 1)
1 2 3 4 5 6 7
5 5 5 5 5 5 5
Saya pikir ini sangat jelas untuk menunjukkan bahwa metode Adam masih akan berjalan lebih cepat. Probabilitas bahwa ada 7 panggilan atau lebih rand5
dalam solusi Adam masih kecil ( (4/25)^3 ~ 0.004
).
Metode 4 - Tidak Tepat
Ini adalah variasi kecil dari metode kedua. Hampir seragam, tetapi membutuhkan 7 panggilan ke rand5
, itu adalah satu tambahan untuk metode 2:
rand7 <- function() (rand5() + sum(sapply(1:6,function(i) i*rand5())) %% 7) + 1
Ini adalah versi yang disederhanakan:
rand7 = function(){
r = 0
for(i in 1:6){
r = r + i*rand5()
}
return (r+rand5()) %% 7 + 1
}
Jika kami menghasilkan semua kombinasi yang mungkin, berikut ini penghitungannya:
table(apply(expand.grid(1:5,(1:5)*2,(1:5)*3,(1:5)*4,(1:5)*5,(1:5)*6,1:5),1,sum) %% 7 + 1)
1 2 3 4 5 6 7
11160 11161 11161 11161 11161 11161 11160
Dua angka akan muncul sekali kurang dalam 5^7 = 78125
uji coba. Untuk sebagian besar tujuan, saya bisa hidup dengan itu.