Sanırım dört cevabım var, ikisi @Adam Rosenfield gibi kesin çözümler veriyor, ancak sonsuz döngü problemi olmadan ve diğer ikisi neredeyse mükemmel bir çözüm ama ilkinden daha hızlı uygulama.
En iyi çözüm 7 çağrı gerektirir rand5
, ancak anlayabilmek için devam edelim.
Yöntem 1 - Kesin
Adem'in cevabının gücü, mükemmel bir düzgün dağılım sağlaması ve sadece iki rand5 () çağrısına ihtiyaç duyulması olasılığı çok yüksek (21/25). Ancak, en kötü durum sonsuz döngüdür.
Aşağıdaki ilk çözüm de mükemmel bir düzgün dağılım sağlar, ancak toplam 42 çağrı gerektirir rand5
. Sonsuz döngü yok.
İşte bir R uygulaması:
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
R'ye aşina olmayan insanlar için, basitleştirilmiş bir sürüm:
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
}
Dağıtımı rand5
korunacaktır. Matematiği yaparsak, döngünün 7 yinelemesinin her birinin 5 ^ 6 olası kombinasyonu vardır, bu nedenle toplam olası kombinasyon sayısı vardır (7 * 5^6) %% 7 = 0
. Böylece, rastgele sayıları 7 eşit grupta bölebiliriz. Bununla ilgili daha fazla tartışma için ikinci yönteme bakınız.
İşte tüm olası kombinasyonlar:
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
Bence Adam'ın yönteminin çok daha hızlı çalışacağını göstermek doğru. rand5
Adam'ın çözümünde 42 veya daha fazla çağrı yapılması olasılığı çok azdır ( (4/25)^21 ~ 10^(-17)
).
Yöntem 2 - Tam Değil
Şimdi neredeyse tek tip olan ancak 6 çağrı gerektiren ikinci yöntem rand5
:
rand7 <- function() (sum(sapply(1:6,function(i) i*rand5())) %% 7) + 1
İşte basitleştirilmiş bir sürüm:
rand7 = function(){
r = 0
for(i in 1:6){
r = r + i*rand5()
}
return r %% 7 + 1
}
Bu, esasen yöntem 1'in bir tekrarıdır. Tüm olası kombinasyonları üretersek, sonuç olarak şunlar sayılır:
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
5^6 = 15625
Denemelerde bir sayı bir kez daha görünecektir .
Şimdi, Yöntem 1'de, 1 ila 6 ekleyerek, birbirini izleyen noktaların her birine 2233 sayısını taşırız. Böylece toplam kombinasyon sayısı eşleşecektir. Bu, 5 ^ 6 %% 7 = 1 olduğu için çalışır ve sonra 7 uygun varyasyon yaparız, bu nedenle (7 * 5 ^ 6 %% 7 = 0).
Yöntem 3 - Kesin
Yöntem 1 ve 2'nin argümanı anlaşılırsa, yöntem 3 izler ve yalnızca 7 çağrı gerektirir rand5
. Bu noktada, bunun kesin bir çözüm için gereken minimum çağrı sayısı olduğunu hissediyorum.
İşte bir R uygulaması:
rand5 <- function() sample(1:5,1)
rand7 <- function() (sum(sapply(1:7, function(i) i * rand5())) %% 7) + 1
R'ye aşina olmayan insanlar için, basitleştirilmiş bir sürüm:
rand7 = function(){
r = 0
for(i in 1:7){
r = r + i * rand5()
}
return r %% 7 + 1
}
Dağıtımı rand5
korunacaktır. Matematiği yaparsak, döngünün 7 yinelemesinin her birinin 5 olası sonucu vardır, bu nedenle toplam olası kombinasyon sayısıdır (7 * 5) %% 7 = 0
. Böylece üretilen rastgele sayıları 7 eşit grupta bölebiliriz. Bununla ilgili daha fazla tartışma için birinci ve ikinci yöntemlere bakınız.
İşte tüm olası kombinasyonlar:
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
Bence Adam'ın yönteminin hala daha hızlı çalışacağını göstermek doğru. rand5
Adam'ın çözümünde 7 veya daha fazla çağrı yapılması olasılığı hala küçük ( (4/25)^3 ~ 0.004
).
Yöntem 4 - Tam Değil
Bu, ikinci yöntemin küçük bir varyasyonudur. Neredeyse aynıdır, ancak 7 çağrıyı gerektirir rand5
, bu yöntem 2'ye bir ektir:
rand7 <- function() (rand5() + sum(sapply(1:6,function(i) i*rand5())) %% 7) + 1
İşte basitleştirilmiş bir sürüm:
rand7 = function(){
r = 0
for(i in 1:6){
r = r + i*rand5()
}
return (r+rand5()) %% 7 + 1
}
Mümkün olan tüm kombinasyonları üretersek, sonuç olarak şunlar sayılır:
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
5^7 = 78125
Denemelerde iki sayı daha az görünecektir . Çoğu amaç için, bununla yaşayabilirim.