各サイドが3回出現するまでダイスを振る必要があると予想される回数はいくつですか?
この質問はニュージーランドの小学校で尋ねられ、シミュレーションを使用して解決されました。この問題の分析ソリューションは何ですか?
各サイドが3回出現するまでダイスを振る必要があると予想される回数はいくつですか?
この質問はニュージーランドの小学校で尋ねられ、シミュレーションを使用して解決されました。この問題の分析ソリューションは何ですか?
回答:
すべての辺に等しいチャンスがあると仮定します。サイドが回現れ、サイドが回現れ、...サイドが回現れるまで、必要なロールの予想数を一般化して見つけましょう。側面のアイデンティティーは重要ではないので(それらはすべて等しいチャンスを持っています)、この目的の説明は凝縮することができます:側面はまったく現れる必要がなく、側面のが現れる必要があると仮定しましょう一度だけ、...、そして辺の出現する必要があります =回。してみましょう
簡単な繰り返しが利用可能です。 次のロールのいずれかに対応して表示された側のいずれか、である私たちはそれを参照してくださいする必要はありませんでした、または我々は、一度それを見るために必要な、...、または我々はそれを見るために必要な:以上回。は、それを見るのに必要な回数です。
とき、我々はそれと何も変更を確認する必要はありませんでした。これは、確率発生します。
ときその後、我々はこの辺を参照してくださいする必要がありました。これで、回見る必要がある側が1つ少なくなり、回見る必要がある側がもう1つあります。したがって、はなり、はます。この操作は、構成要素にしてみましょうに指定されように、
これは、確率発生します。
このサイコロを数えるだけで、再帰を使用してさらに多くのロールが予想されることを知ることができます。 期待と総確率の法則により、
(i j = 0のときはいつでも理解しましょう場合、合計の対応する項はゼロである。)
場合、処理は完了し、e (i)= 0です。それ以外の場合、e (i)を解いて、望ましい再帰式を与えることができます
そのお知らせは、表示したいイベントの総数です。操作⋅ jは任意のための1つによりその量を低減J > 0設けI 、J > 0常にそうです。したがって、この再帰は正確に|の深さで終了します。私| (3 (6 )に等しい=
私は計算
それは私にはひどく小さいように思えたので、シミュレーションを実行しました(を使用R
)。300万回以上のサイコロを振った後、このゲームは平均長さで100,000回以上プレイされていました。その推定値の標準誤差は0.027です。この平均値と理論値の差はわずかであり、理論値の精度が確認されています。
長さの分布が興味深い場合があります。(明らかに、6面すべてを3回収集するために必要なロールの最小数であるから開始する必要があります。)
# Specify the problem
d <- 6 # Number of faces
k <- 3 # Number of times to see each
N <- 3.26772e6 # Number of rolls
# Simulate many rolls
set.seed(17)
x <- sample(1:d, N, replace=TRUE)
# Use these rolls to play the game repeatedly.
totals <- sapply(1:d, function(i) cumsum(x==i))
n <- 0
base <- rep(0, d)
i.last <- 0
n.list <- list()
for (i in 1:N) {
if (min(totals[i, ] - base) >= k) {
base <- totals[i, ]
n <- n+1
n.list[[n]] <- i - i.last
i.last <- i
}
}
# Summarize the results
sim <- unlist(n.list)
mean(sim)
sd(sim) / sqrt(length(sim))
length(sim)
hist(sim, main="Simulation results", xlab="Number of rolls", freq=FALSE, breaks=0:max(sim))
の再帰的な計算は簡単ですが、一部のコンピューティング環境ではいくつかの課題があります。これらの中で最も重要なのは、e (i)の値を計算時に保存することです。これは不可欠です。それ以外の場合、各値は非常に多くの回数(冗長に)計算されます。ただし、iによってインデックス付けされた配列に必要なストレージは膨大な量になる可能性があります。理想的には、計算中に実際に遭遇するiの値のみを保存する必要があります。これには、一種の連想配列が必要です。
説明のために、ここに作業R
コードを示します。コメントは、中間結果を保存するための単純な「AA」(連想配列)クラスの作成を説明しています。ベクトルは文字列に変換され、すべての値を保持するリストにインデックスを付けるために使用されます。私 ⋅ j個の操作は、次のように実装されています。E
%.%
これらの予備により、数学的な表記法に対応する方法で、再帰関数をかなり簡単に定義できます。特に、ライン
x <- (d + sum(sapply(1:n, function(i) j[i+1]*e.(j %.% i))))/(d - j[1])
上記の式と直接比較できます。すべてのインデックスが増加されていることに注意してください1ので開始はでその配列のインデックスを作成する1ではなく0。R
タイミングは、計算に秒かかることを示しています。その値はe(c(0,0,0,6))
32.6771634160506
蓄積された浮動小数点丸めエラーが(あるべきで下二桁破壊した68
というよりは06
)。
e <- function(i) {
#
# Create a data structure to "memoize" the values.
#
`[[<-.AA` <- function(x, i, value) {
class(x) <- NULL
x[[paste(i, collapse=",")]] <- value
class(x) <- "AA"
x
}
`[[.AA` <- function(x, i) {
class(x) <- NULL
x[[paste(i, collapse=",")]]
}
E <- list()
class(E) <- "AA"
#
# Define the "." operation.
#
`%.%` <- function(i, j) {
i[j+1] <- i[j+1]-1
i[j] <- i[j] + 1
return(i)
}
#
# Define a recursive version of this function.
#
e. <- function(j) {
#
# Detect initial conditions and return initial values.
#
if (min(j) < 0 || sum(j[-1])==0) return(0)
#
# Look up the value (if it has already been computed).
#
x <- E[[j]]
if (!is.null(x)) return(x)
#
# Compute the value (for the first and only time).
#
d <- sum(j)
n <- length(j) - 1
x <- (d + sum(sapply(1:n, function(i) j[i+1]*e.(j %.% i))))/(d - j[1])
#
# Store the value for later re-use.
#
E[[j]] <<- x
return(x)
}
#
# Do the calculation.
#
e.(i)
}
e(c(0,0,0,6))
最後に、正確な答えを生成した元のMathematica実装を示します。メモ化は慣用表現を介して行われ、e[i_] := e[i] = ...
ほとんどすべてのR
予備作業が排除されます。ただし、内部的には、2つのプログラムは同じことを同じ方法で実行しています。
shift[j_, x_List] /; Length[x] >= j >= 2 := Module[{i = x},
i[[j - 1]] = i[[j - 1]] + 1;
i[[j]] = i[[j]] - 1;
i];
e[i_] := e[i] = With[{i0 = First@i, d = Plus @@ i},
(d + Sum[If[i[[k]] > 0, i[[k]] e[shift[k, i]], 0], {k, 2, Length[i]}])/(d - i0)];
e[{x_, y__}] /; Plus[y] == 0 := e[{x, y}] = 0
e[{0, 0, 0, 6}]
この質問の元のバージョンは、次の質問から始まりました。
各面が3回現れるまでに必要なロール数
Of course, that is a question that does not have an answer as @JuhoKokkala commented above: the answer is a random variable with a distribution that needs to be found. The question was then modified to ask: "What is the expected number of rolls." The answer below seeks to answer the original question posed: how to find the distribution of the number of rolls, without using simulation, and just using conceptually simple techniques any New Zealand student with a computer could implement Why not? The problem reduces to a 1-liner.
Distribution of the number of rolls required ... such that each side appears 3 times
We roll a die times. Let denote the number of times side of the die appears, where . Then, the joint pmf of is i.e.:
Let: Then the cdf of is:
i.e. To find the cdf , simply calculate for each value of :
Here, for example, is Mathematica code that does this, as increases from 18 to say 60. It is basically a one-liner:
cdf = ParallelTable[
Probability[x1 >= 3 && x2 >= 3 && x3 >= 3 && x4 >= 3 && x5 >= 3 && x6 >= 3,
{x1, x2, x3, x4, x5, x6} \[Distributed] MultinomialDistribution[n, Table[1/6, 6]]],
{n, 18, 60}]
... which yields the exact cdf as increases:
Here is a plot of the cdf , as a function of :
To derive the pmf , simply first difference the cdf:
Of course, the distribution has no upper bound, but we can readily solve here for as many values as practically required. The approach is general and should work just as well for any desired combination of sides required.