Oczekiwano, ile razy rzucisz kością, aż każda strona pojawi się 3 razy

15

Jakiej oczekiwanej liczby razy musisz rzucić kostką, aż każda ze stron pojawi się 3 razy?

To pytanie zostało zadane w szkole podstawowej w Nowej Zelandii i zostało rozwiązane za pomocą symulacji. Jakie jest analityczne rozwiązanie tego problemu?

Edgar Santos
źródło
6
Ponieważ wyniki rzutów są losowe, nie można z góry wiedzieć, ile rzutów jest potrzebnych. Jeśli pytanie dotyczy na przykład oczekiwanej liczby rzutów, zanim każda strona pojawi się 3 razy, należy to wyraźnie zaznaczyć. W takim przypadku obowiązuje stats.stackexchange.com/tags/self-study/info .
Juho Kokkala,
3
Powiedz tym nowozelandzkim dzieciom, aby przeczytały Normana L. Johnsona, Samuela Kotza, N. Balakrishnana „Dyskretne dystrybucje wielowymiarowe” wiley.com/WileyCDA/WileyTitle/productCd-0471128449.html .
Mark L. Stone,

Odpowiedzi:

28

Załóżmy, że wszystkie stron mają równe szanse. oczekiwaną liczbę potrzebnych rzutów, aż strona się razy, strona się razy, ..., a strona się razy. Ponieważ tożsamość stron nie ma znaczenia (wszystkie mają równe szanse), opis tego celu można : załóżmy, że strony wcale nie muszą się pojawiać, strony muszą pojawić się tylko raz , ... i boków muszą pojawić się razy. Pozwolićd=61n12n2dndi0i1inn=max(n1,n2,,nd)e ( i ) e ( 0 , 0 , 0 , 6 )

i=(i0,i1,,in)
tę sytuację i napisz dla oczekiwanej liczby rzutów. Pytanie wymaga : oznacza, że ​​wszystkie sześć stron trzeba zobaczyć trzy razy.
e(i)
e(0,0,0,6)i3=6

Dostępna jest łatwa rekurencja. Na następnej stronie rolki, które się pojawi, odpowiada jeden z : To znaczy, że albo nie trzeba go zobaczyć, czy potrzebujemy go zobaczyć raz, ..., lub co potrzebne, aby go zobaczyć razy więcej . to ile razy potrzebowaliśmy to zobaczyć. n jijotnjot

  • Gdy , nie musieliśmy tego widzieć i nic się nie zmienia. Dzieje się tak z prawdopodobieństwem .i 0 / djot=0ja0/re

  • Kiedy musieliśmy zobaczyć tę stronę. Teraz jest o jedną stronę mniejszą niż raz i jeszcze jedną stronę, którą trzeba zobaczyć razy. Zatem staje się a staje się . Niech ta operacja na komponentach zostanie oznaczona , tak abyj j - 1 i j i j - 1 i j - 1 i j + 1 i ijjot>0jotjot-1jajotjajot-1jajot-1jajot+1jajajot

    jajot=(ja0,,jajot-2),jajot-1+1,jajot-1,jajot+1,,jan).

    Dzieje się tak z prawdopodobieństwem .jajot/re

Musimy tylko policzyć ten rzut kości i użyć rekurencji, aby powiedzieć nam, ile oczekiwanych jest rzutów. Według praw oczekiwania i całkowitego prawdopodobieństwa,

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

(Rozumiemy, że ilekroć , odpowiedni warunek w sumie wynosi zero).ij=0

Jeśli , to skończymy, a . W przeciwnym razie możemy rozwiązać dla , podając żądaną formułę rekurencyjnąe ( i ) = 0 e ( i )i0=de(i)=0e(i)

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

Zauważ, że to łączna liczba zdarzeń, które chcemy zobaczyć. Operacja zmniejsza tę liczbę o jeden dla dowolnego pod warunkiem, że , co zawsze ma miejsce. Dlatego ta rekurencja kończy się na głębokości dokładnie(równa w pytaniu). Ponadto (co nie jest trudne do sprawdzenia) liczba możliwości na każdej głębokości rekurencji w tym pytaniu jest niewielka (nigdy nie przekracza ). W związku z tym jest to skuteczna metoda, przynajmniej wtedy, gdy możliwości kombinatoryczne nie są zbyt liczne, a my zapamiętujemy wyniki pośrednie (tak aby żadna wartośćj j > 0 i j > 0 | i | 3 ( 6 ) = 18 8 e

|i|=0(i0)+1(i1)++n(in)
jj>0ij>0|i|3(6)=188e jest obliczany więcej niż jeden raz).

Obliczam, że

e(0,0,0,6)=22868786045088836998400000000032,677.

Wydawało mi się to okropnie małe, więc przeprowadziłem symulację (używając R). Po ponad trzech milionach rzutów kostką gra została ukończona ponad 100 000 razy, przy średniej długości . Standardowy błąd tego oszacowania wynosi : różnica między tą średnią a wartością teoretyczną jest nieznaczna, co potwierdza dokładność wartości teoretycznej.0,02732,6690,027

Interesujący może być rozkład długości. (Oczywiście musi zaczynać się od , minimalna liczba rzutów potrzebna do zebrania wszystkich sześciu stron trzy razy każda).18

Postać

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

Realizacja

Chociaż rekurencyjne obliczanie jest proste, stanowi pewne wyzwanie w niektórych środowiskach obliczeniowych. Najważniejszym z nich jest przechowywanie wartości podczas ich obliczania. Jest to niezbędne, ponieważ w przeciwnym razie każda wartość zostanie (nadmiarowo) obliczona bardzo wiele razy. Jednak pamięć potencjalnie potrzebna dla tablicy indeksowanej przez może być ogromna. Idealnie powinny być przechowywane tylko wartości , które faktycznie występują podczas obliczeń. Wymaga to pewnego rodzaju tablicy asocjacyjnej.mimi(ja)jaja

Aby to zilustrować, oto działający Rkod. Komentarze opisują utworzenie prostej klasy „AA” (tablica asocjacyjna) do przechowywania wyników pośrednich. Wektory są konwertowane na ciągi, które służą do indeksowania do listy, która będzie zawierać wszystkie wartości. Operacja jest zaimplementowana jako .jaEjajot%.%

Te czynności wstępne umożliwiają raczej zdefiniowanie funkcji rekurencyjnej w sposób podobny do zapisu matematycznego. W szczególności liniami

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

jest bezpośrednio porównywalny z powyższym wzorem . Zauważ, że wszystkie indeksy zostały zwiększone o ponieważ zaczyna indeksować swoje tablice od zamiast .(1)1R10

Czas pokazuje, że obliczenie zajmuje sekundy ; jego wartość to0,01e(c(0,0,0,6))

32,6771634160506

Skumulowany błąd zaokrąglenia zmiennoprzecinkowego zniszczył dwie ostatnie cyfry (które powinny być 68raczej niż 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))

Wreszcie, oto oryginalna implementacja Mathematica, która dała dokładną odpowiedź. Zapamiętywanie odbywa się za pomocą e[i_] := e[i] = ...wyrażenia idiomatycznego , eliminując prawie wszystkie czynności Rwstępne. Jednak wewnętrznie oba programy robią te same rzeczy w ten sam sposób.

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
źródło
5
+1 Wyobrażam sobie, że niektóre zapisy byłyby trudne do naśladowania dla studentów, którym zadano to pytanie (nie żebym miał teraz konkretną alternatywę do zasugerowania). Z drugiej strony zastanawiam się, co mieli zrobić z takim pytaniem.
Glen_b
1
@Glen_b Mogliby się wiele nauczyć, rzucając kostką (i licząc wyniki). To brzmi jak dobry sposób na zajęcie klasy przez pół godziny, podczas gdy nauczyciel odpoczywa :-).
whuber
12

Oryginalna wersja tego pytania rozpoczęła życie od zadania:

ile rzutów potrzeba, aż każda strona pojawi się 3 razy

Oczywiście jest to pytanie, na które nie ma odpowiedzi, jak to skomentował @JuhoKokkala: odpowiedź jest zmienną losową z rozkładem, który należy znaleźć. Pytanie zostało następnie zmodyfikowane, aby zapytać: „Jaka jest oczekiwana liczba rzutów”. Poniższa odpowiedź ma na celu odpowiedzieć na postawione pierwotne pytanie: jak znaleźć rozkład liczby rolek bez korzystania z symulacji i po prostu przy użyciu prostych koncepcyjnie technik, które każdy student z Nowej Zelandii za pomocą komputera mógłby wdrożyć prawo Dlaczego nie? Problem sprowadza się do 1-liniowej.

Rozkład liczby wymaganych rolek ... tak, że każda strona pojawia się 3 razy

Rzucamy kostką razy. Niech oznacza, ile razy pojawia się strona matrycy, gdzie . Zatem wspólnym pmf dla jest tj . :nXjajaja{1,,6}(X1,X2),,X6)Wielomian(n,16)

P.(X1=x1,,X6=x6)=n!x1!x6!16n z zastrzeżeniem: ja=16xja=n

Niech:Zatem cdf z to:N.=min{n:Xja3)ja}.N.P.(N.n)=P.(Xja3)|n)

tzn. Aby znaleźć cdf , po prostu oblicz dla każdej wartości :P.(N.n)n={18,19,20,}

P.(X13),,X63)) gdzie (X1,,X6)Wielomian(n,16)

Oto na przykład kod Mathematica , który to robi, gdy wzrasta z 18 do 60. Jest to w zasadzie jednowierszowy:n

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

... co daje dokładny plik cdf w miarę wzrostu :n

1814889875110199605761928290762544079842304203111983875176319369216211168408491253173748645888223283142988125507799783342082361483465418375609359740010496

Oto wykres cdf , w funkcji :P.(N.n)n

wprowadź opis zdjęcia tutaj

Aby uzyskać pmf , po prostu najpierw rozróżnij plik cdf:P.(N.=n)

wprowadź opis zdjęcia tutaj

Oczywiście rozkład nie ma górnej granicy, ale możemy tutaj łatwo rozwiązać tyle wartości, ile jest praktycznie wymagane. Podejście to jest ogólne i powinno działać równie dobrze dla każdej wymaganej kombinacji wymaganych stron.

wilki
źródło