Ich glaube, ich habe vier Antworten, von denen zwei exakte Lösungen wie die von @Adam Rosenfield liefern, aber ohne das Endlosschleifenproblem, und die anderen zwei mit nahezu perfekter Lösung, aber schnellerer Implementierung als die erste.
Die beste exakte Lösung erfordert 7 Anrufe rand5
, aber lassen Sie uns fortfahren, um zu verstehen.
Methode 1 - Genau
Die Stärke von Adams Antwort ist, dass es eine perfekte gleichmäßige Verteilung gibt und es eine sehr hohe Wahrscheinlichkeit (21/25) gibt, dass nur zwei Aufrufe von rand5 () benötigt werden. Der schlimmste Fall ist jedoch die Endlosschleife.
Die erste Lösung unten bietet ebenfalls eine perfekte gleichmäßige Verteilung, erfordert jedoch insgesamt 42 Anrufe an rand5
. Keine Endlosschleifen.
Hier ist eine R-Implementierung:
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
Für Leute, die nicht mit R vertraut sind, gibt es hier eine vereinfachte Version:
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
}
Die Verteilung von rand5
bleibt erhalten. Wenn wir rechnen, hat jede der 7 Iterationen der Schleife 5 ^ 6 mögliche Kombinationen, also die Gesamtzahl der möglichen Kombinationen (7 * 5^6) %% 7 = 0
. Somit können wir die erzeugten Zufallszahlen in gleiche Gruppen von 7 teilen. Weitere Informationen hierzu finden Sie in Methode 2.
Hier sind alle möglichen Kombinationen:
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
Ich denke, es ist einfach zu zeigen, dass Adams Methode viel schneller laufen wird. Die Wahrscheinlichkeit, dass rand5
in Adams Lösung 42 oder mehr Aufrufe enthalten sind, ist sehr gering ( (4/25)^21 ~ 10^(-17)
).
Methode 2 - Nicht genau
Nun die zweite Methode, die fast einheitlich ist, aber 6 Aufrufe erfordert rand5
:
rand7 <- function() (sum(sapply(1:6,function(i) i*rand5())) %% 7) + 1
Hier ist eine vereinfachte Version:
rand7 = function(){
r = 0
for(i in 1:6){
r = r + i*rand5()
}
return r %% 7 + 1
}
Dies ist im Wesentlichen eine Iteration von Methode 1. Wenn wir alle möglichen Kombinationen generieren, ergeben sich hier folgende Zählungen:
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
Eine Zahl wird in 5^6 = 15625
Versuchen noch einmal erscheinen .
In Methode 1 verschieben wir nun durch Addition von 1 zu 6 die Zahl 2233 zu jedem der aufeinanderfolgenden Punkte. Somit stimmt die Gesamtzahl der Kombinationen überein. Dies funktioniert, weil 5 ^ 6 %% 7 = 1 ist und wir dann 7 geeignete Variationen durchführen, also (7 * 5 ^ 6 %% 7 = 0).
Methode 3 - Genau
Wenn das Argument von Methode 1 und 2 verstanden wird, folgt Methode 3 und erfordert nur 7 Aufrufe von rand5
. An diesem Punkt denke ich, dass dies die Mindestanzahl von Anrufen ist, die für eine genaue Lösung erforderlich sind.
Hier ist eine R-Implementierung:
rand5 <- function() sample(1:5,1)
rand7 <- function() (sum(sapply(1:7, function(i) i * rand5())) %% 7) + 1
Für Leute, die nicht mit R vertraut sind, gibt es hier eine vereinfachte Version:
rand7 = function(){
r = 0
for(i in 1:7){
r = r + i * rand5()
}
return r %% 7 + 1
}
Die Verteilung von rand5
bleibt erhalten. Wenn wir rechnen, hat jede der 7 Iterationen der Schleife 5 mögliche Ergebnisse, also die Gesamtzahl der möglichen Kombinationen(7 * 5) %% 7 = 0
. Somit können wir die erzeugten Zufallszahlen in gleiche Gruppen von 7 teilen. Weitere Informationen hierzu finden Sie in Methode eins und zwei.
Hier sind alle möglichen Kombinationen:
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
Ich denke, es ist einfach zu zeigen, dass Adams Methode immer noch schneller läuft. Die Wahrscheinlichkeit, dass rand5
in Adams Lösung 7 oder mehr Aufrufe enthalten sind, ist immer noch gering ( (4/25)^3 ~ 0.004
).
Methode 4 - Nicht genau
Dies ist eine geringfügige Variation der zweiten Methode. Es ist fast einheitlich, erfordert jedoch 7 Aufrufe von rand5
, das ist eine zusätzliche zu Methode 2:
rand7 <- function() (rand5() + sum(sapply(1:6,function(i) i*rand5())) %% 7) + 1
Hier ist eine vereinfachte Version:
rand7 = function(){
r = 0
for(i in 1:6){
r = r + i*rand5()
}
return (r+rand5()) %% 7 + 1
}
Wenn wir alle möglichen Kombinationen generieren, ergeben sich folgende Zählungen:
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
In 5^7 = 78125
Versuchen werden zwei Zahlen einmal weniger angezeigt. Für die meisten Zwecke kann ich damit leben.