Diharapkan berapa kali untuk menggulung dadu sampai masing-masing sisi muncul 3 kali

15

Berapa yang diharapkan berapa kali Anda harus melempar dadu sampai masing-masing sisi muncul 3 kali?

Pertanyaan ini ditanyakan di sekolah dasar di Selandia Baru dan diselesaikan dengan simulasi. Apa solusi analitis untuk masalah ini?

Edgar Santos
sumber
6
Karena hasil dari gulungan adalah acak, tidak mungkin untuk mengetahui sebelumnya berapa banyak gulungan yang dibutuhkan. Jika pertanyaan mencari, misalnya, jumlah gulungan yang diharapkan sebelum masing-masing sisi muncul 3 kali, itu harus dinyatakan secara eksplisit. Dalam hal ini, stats.stackexchange.com/tags/self-study/info berlaku.
Juho Kokkala
3
Beri tahu anak-anak Selandia Baru untuk membaca Norman L. Johnson, Samuel Kotz, N. Balakrishnan "Discrete Multivariate Distribution" wiley.com/WileyCDA/WileyTitle/productCd-0471128449.html .
Mark L. Stone

Jawaban:

28

Misalkan semua sisi memiliki peluang yang sama. Menggeneralisasikan dan mari kita menemukan jumlah yang diharapkan dari gulungan diperlukan sampai sisi 1 telah muncul n 1 kali, sisi 2 telah muncul n 2 kali, ..., dan sisi d telah muncul n d kali. Karena identitas para pihak tidak penting (mereka semua memiliki kesempatan yang sama), deskripsi tujuan ini dapat terkondensasi: mari kita anggap bahwa saya 0 belah pihak tidak perlu muncul sama sekali, saya 1 dari sisi perlu muncul hanya sekali, ..., dan i nd=61n12n2dndi0i1insisi harus muncul kali. Biarkan i = ( i 0 , i 1 , ... , i n ) tentukan situasi ini dan tulis e ( i ) untuk jumlah gulungan yang diharapkan. Pertanyaannya menanyakan e ( 0 , 0 , 0 , 6 ) : i 3 =n=max(n1,n2,,nd)

i=(i0,i1,,in)
e(i)
e(0,0,0,6) menunjukkan keenam sisi harus dilihat masing-masing tiga kali.i3=6

Perulangan mudah tersedia. Pada gulungan berikutnya, sisi yang muncul bersesuaian dengan salah satu : yaitu, baik kita tidak perlu melihatnya, atau kita perlu melihat sekali, ..., atau kami harus melihatnya n lebih waktu. j adalah berapa kali kita perlu melihatnya.ijnj

  • Ketika , kami tidak perlu melihatnya dan tidak ada yang berubah. Ini terjadi dengan probabilitas i 0 / d .j=0i0/d

  • Ketika maka kita memang perlu melihat sisi ini. Sekarang ada satu sisi lebih sedikit yang perlu dilihat j kali dan satu sisi lagi yang perlu dilihat j - 1 kali. Jadi, i j menjadi i j - 1 dan i j - 1 menjadi i j + 1 . Biarkan operasi ini pada komponen i ditunjuk ij , sehinggaj>0jj1ijij1ij1ij+1iij

    ij=(i0,,ij2,ij1+1,ij1,ij+1,,in).

    Ini terjadi dengan probabilitas .ij/d

Kita hanya perlu menghitung gulungan ini dan menggunakan rekursi untuk memberi tahu kami berapa banyak gulungan yang diharapkan. Dengan hukum harapan dan probabilitas total,

e(i)=1+i0de(i)+j=1nijde(ij)

(Mari kita pahami bahwa setiap kali , istilah terkait dalam penjumlahan adalah nol.)ij=0

Jika , kita selesai dan e ( i ) = 0 . Kalau tidak, kita dapat memecahkan untuk e ( i ) , memberikan formula rekursif yang diinginkani0=de(i)=0e(i)

(1)e(i)=d+i1e(i1)++ine(in)di0.

Perhatikan bahwa adalah jumlah total acara yang ingin kita lihat. Operasi j mengurangi kuantitas itu menjadi satu untuk setiap j > 0 asalkan i j > 0 , yang selalu demikian. Oleh karena itu rekursi ini berakhir pada kedalaman yang tepat | saya | (sama dengan 3 ( 6 ) =

|i|=0(i0)+1(i1)++n(in)
jj>0ij>0|i| dalam pertanyaan). Selain itu (karena tidak sulit untuk memeriksa) jumlah kemungkinan pada setiap kedalaman rekursi dalam pertanyaan ini kecil (tidak pernah melebihi 8 ). Akibatnya, ini adalah metode yang efisien, setidaknya ketika kemungkinan kombinatorial tidak terlalu banyak dan kami memoize hasil antara (sehingga tidak ada nilai e dihitung lebih dari sekali).3(6)=188e

Saya menghitung bahwa

e(0,0,0,6)=22868786045088836998400000000032.677.

R32.6690.027

18

Figure

# 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))

Penerapan

Although the recursive calculation of e is simple, it presents some challenges in some computing environments. Chief among these is storing the values of e(i) as they are computed. This is essential, for otherwise each value will be (redundantly) computed a very large number of times. However, the storage potentially needed for an array indexed by i could be enormous. Ideally, only values of i that are actually encountered during the computation should be stored. This calls for a kind of associative array.

To illustrate, here is working R code. The comments describe the creation of a simple "AA" (associative array) class for storing intermediate results. Vectors i are converted to strings and those are used to index into a list E that will hold all the values. The ij operation is implemented as %.%.

These preliminaries enable the recursive function e to be defined rather simply in a way that parallels the mathematical notation. In particular, the line

x <- (d + sum(sapply(1:n, function(i) j[i+1]*e.(j %.% i))))/(d - j[1])

is directly comparable to the formula (1) above. Note that all indexes have been increased by 1 because R starts indexing its arrays at 1 rather than 0.

Timing shows it takes 0.01 seconds to compute e(c(0,0,0,6)); its value is

32.6771634160506

Accumulated floating point roundoff error has destroyed the last two digits (which should be 68 rather than 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))

Finally, here is the original Mathematica implementation that produced the exact answer. The memoization is accomplished via the idiomatic e[i_] := e[i] = ... expression, eliminating almost all the R preliminaries. Internally, though, the two programs are doing the same things in the same way.

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}]

228687860450888369984000000000

whuber
sumber
5
+1 I imagine some of the notation would be difficult to follow for the students who were asked this question (not that I have any concrete alternative to suggest right now). On the other hand I wonder what they were intended to do with such a question.
Glen_b -Reinstate Monica
1
@Glen_b They could learn a lot by actually rolling the dice (and tallying the results). It sounds like a good way to keep a class busy for a half hour while the teacher rests :-).
whuber
12

The original version of this question started life by asking:

how many rolls are needed until each side has appeared 3 times

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 n times. Let Xi denote the number of times side i of the die appears, where i{1,,6}. Then, the joint pmf of (X1,X2,,X6) is Multinomial(n,16) i.e.:

P(X1=x1,,X6=x6)=n!x1!x6!16n subject to: i=16xi=n

Let: N=min{n:Xi3i}. Then the cdf of N is: P(Nn)=P(Xi3|n)

i.e. To find the cdf P(Nn), simply calculate for each value of n={18,19,20,}:

P(X13,,X63) where (X1,,X6)Multinomial(n,16)

Here, for example, is Mathematica code that does this, as n 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 n increases:

1814889875110199605761928290762544079842304203111983875176319369216211168408491253173748645888223283142988125507799783342082361483465418375609359740010496

Here is a plot of the cdf P(Nn), as a function of n:

enter image description here

To derive the pmf P(N=n), simply first difference the cdf:

enter image description here

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.

wolfies
sumber