Esiste una risposta esatta (sotto forma di un prodotto a matrice, presentato al successivo punto 4). Esiste un algoritmo ragionevolmente efficiente per calcolarlo, derivante da queste osservazioni:
Una mescolanza casuale di carte può essere generata mescolando casualmente carte e quindi alternando casualmente le rimanenti carte al loro interno.N kN+kNk
Mischiando solo gli assi e quindi (applicando la prima osservazione) intervallando i due, poi i tre e così via, questo problema può essere visto come una catena di tredici passi.
Dobbiamo tenere traccia di più del valore della carta che stiamo cercando. Nel fare ciò, tuttavia, non è necessario tenere conto della posizione del segno rispetto a tutte le carte, ma solo della sua posizione rispetto a carte di valore uguale o inferiore.
Immagina di mettere un segno sul primo asso, quindi di segnare i primi due trovati dopo di esso, e così via. (Se in qualsiasi momento il mazzo si esaurisce senza visualizzare la carta che stiamo attualmente cercando, lasceremo tutte le carte non segnate.) Lascia che il "posto" di ogni segno (quando esiste) sia il numero di carte di valore uguale o inferiore che sono stati distribuiti al momento del marchio (inclusa la carta contrassegnata stessa). I luoghi contengono tutte le informazioni essenziali.
Il posto dopo il segno è un numero casuale. Per un determinato mazzo, la sequenza di questi luoghi forma un processo stocastico. In realtà è un processo di Markov (con matrice di transizione variabile). Una risposta esatta può quindi essere calcolata da dodici moltiplicazioni di matrice.ith
Utilizzando queste idee, questa macchina ottiene un valore di (calcolo in virgola mobile a precisione doppia) in secondo. Questa approssimazione del valore esatto è precisa per tutte le cifre visualizzate.5.83258855290199651/9
1982600579265894785026945331968939023522542569339917784579447928182134345929899510000000000
Il resto di questo post fornisce dettagli, presenta un'implementazione funzionante (in R
) e conclude con alcuni commenti sulla domanda e sull'efficienza della soluzione.
Generazione di mescolanze casuali di un mazzo
In realtà è concettualmente più chiaro e matematicamente non è più complicato considerare un "mazzo" (aka multiset ) di carte di cui ci sono della denominazione più bassa, della successiva più bassa, e così via . (La domanda posta riguarda il mazzo determinato dal vettore .)N=k1+k2+⋯+kmk1k213(4,4,…,4)
Uno "shuffle casuale" di carte è una permutazione presa in modo uniforme e casuale dalla permutazioni delle carteQuesti shuffle si dividono in gruppi di configurazioni equivalenti perché permutare i "assi" tra loro non cambia nulla, permettendo ai "due" tra loro anche cambiare nulla, e così via. Pertanto ogni gruppo di permutazioni che sembrano identiche quando i semi delle carte vengono ignorate contienepermutazioni. Questi gruppi, il cui numero è quindi dato dal coefficiente multinomialeNN!=N×(N−1)×⋯×2×1Nk1k2k1!×k2!×⋯×km!
(Nk1,k2,…,km)=N!k1!k2!⋯km!,
sono chiamate "combinazioni" del mazzo.
C'è un altro modo per contare le combinazioni. Le prime carte possono formare solo combinazione. Lasciano "slot" tra e intorno a loro in cui possono essere posizionate le successive carte. Potremmo indicare questo con un diagramma dove " " designa una delle carte e " " indica uno slot che può contenere tra e carte supplementari:k1k1!/k1!=1k1+1k2∗k1_0k2
_∗_∗_⋯_∗_k1 stars
Quando si carte aggiuntive, il modello di stelle e nuove carte suddivide le carte in due sottoinsiemi. Il numero di tali sottoinsiemi distinti è .k2k1+k2(k1+k2k1,k2)=(k1+k2)!k1!k2!
Ripetendo questa procedura con "tre", troviamo che ci sono modi di separarli tra le prime carte. Pertanto, il numero totale di modi distinti per disporre le prime in questo modo è ugualek3((k1+k2)+k3k1+k2,k3)=(k1+k2+k3)!(k1+k2)!k3!k1+k2k1+k2+k3
1×(k1+k2)!k1!k2!×(k1+k2+k3)!(k1+k2)!k3!=(k1+k2+k3)!k1!k2!k3!.
Dopo aver finito le ultime carte e aver continuato a moltiplicare queste frazioni telescopiche, troviamo che il numero di combinazioni distinte ottenute è uguale al numero totale di combinazioni come precedentemente contate, . Pertanto non abbiamo trascurato nessuna combinazione. Ciò significa che questo processo sequenziale di mescolare le carte cattura correttamente le probabilità di ciascuna combinazione, supponendo che in ogni fase ogni possibile modo distinto di intercalare le nuove carte tra le vecchie sia preso con uniformemente uguale probabilità.kn(Nk1,k2,…,km)
Il processo del luogo
Inizialmente, ci sono assi e ovviamente il primo è contrassegnato. Nelle fasi successive ci sono carte, il posto (se esiste una carta segnata) è uguale a (un valore compreso tra e ) e stiamo per intercalare carte attorno a loro. Possiamo visualizzarlo con un diagramma similek1n=k1+k2+⋯+kj−1p1nk=kj
_∗_∗_⋯_∗_p−1 stars⊙_∗_⋯_∗_n−p stars
dove " " indica il simbolo attualmente contrassegnato. In base a questo valore del posto , desideriamo trovare la probabilità che il posto successivo sia uguale a (un valore compreso tra e ; in base alle regole del gioco, il posto successivo deve venire dopo , da cui ). Se riusciamo a trovare quanti modi ci sono per separare le nuove carte negli spazi vuoti in modo che il posto successivo sia uguale a , allora possiamo dividere per il numero totale di modi per separare queste carte (uguale a , come abbiamo visto) per ottenere il file⊙pq1n+kpq≥p+1kq(n+kk)probabilità di transizione che il luogo cambi da a . (Ci sarà anche una probabilità di transizione per far scomparire del tutto il luogo quando nessuna delle nuove carte segue la carta segnata, ma non è necessario calcolarla esplicitamente.)pq
Aggiorniamo il diagramma per riflettere questa situazione:
_∗_∗_⋯_∗_p−1 stars⊙∗∗⋯∗s stars | _∗_⋯_∗_n−p−s stars
La barra verticale " " mostra dove la prima nuova carta avviene dopo la carta contrassegnata: no nuove carte può quindi apparire tra il e (e pertanto nessun slot sono mostrati in quell'intervallo). Non sappiamo quante stelle ci sono in questo intervallo, quindi ho appena chiamato (che può essere zero) l'ignoto spariranno una volta che troviamo il rapporto tra essa e .|⊙|ssq
Supponiamo, quindi, di separare nuove carte attorno alle stelle prima del e quindi - indipendentemente da ciò - separiamo le rimanenti nuove carte attorno alle stelle dopo il . Ci sonoj⊙k−j−1|
τn,k(s,p)=((p−1)+jj)((n−p−s)+(k−j)−1k−j−1)
modi per farlo. Si noti, tuttavia - questa è la parte più difficile dell'analisi - che il posto di uguale a perché|p+s+j+1
- Ci sono "vecchie" carte in corrispondenza o prima del segno.p
- Ci sono vecchie carte dopo il marchio, ma prima di .s|
- Ci sono nuove carte prima del segno.j
- C'è la nuova carta rappresentata da stesso.|
Pertanto, ci fornisce informazioni sulla transizione da luogo a luogo . Quando seguiamo attentamente queste informazioni per tutti i possibili valori di e sommiamo tutte queste possibilità (disgiunte), otteniamo la probabilità condizionale del posto dopo il posto ,τn,k(s,p)pq=p+s+j+1sqp
Prn,k(q|p)=(∑j(p−1+jj)(n+k−qk−j−1))/(n+kk)
dove la somma inizia da e termina in . (La lunghezza variabile di questa somma suggerisce che c'è è improbabile che sia una formula chiusa per esso in funzione di e , tranne in casi speciali.)j=max(0,q−(n+1))j=min(k−1,q−(p+1)n,k,q,p
L'algoritmo
Inizialmente c'è la probabilità che il posto sia e la probabilità avrà qualsiasi altro valore possibile in . Questo può essere rappresentato da un vettore .1102,3,…,k1p1=(1,0,…,0)
Dopo aver sparpagliato le successive carte , il vettore viene aggiornato a moltiplicandolo (a sinistra) per la matrice di transizione . Questo si ripete fino a quando tutte le carte sono state piazzate. Ad ogni stadio , la somma delle voci nel vettore di probabilità è la possibilità che una carta sia stata segnata. Qualunque cosa rimanga per rendere il valore uguale a quindi, è la possibilità che nessuna carta rimanga segnata dopo il passaggiok2p1p2(Prk1,k2(q|p),1≤p≤k1,1≤q≤k2)k1+k2+⋯+kmjpj1j. Le successive differenze di questi valori ci danno quindi la probabilità che non siamo riusciti a trovare una carta di tipo da marcare: questa è la distribuzione di probabilità del valore della carta che stavamo cercando quando il mazzo si esaurisce alla fine del gioco .j
Implementazione
Il R
codice seguente implementa l'algoritmo. Parallela alla discussione precedente. Innanzitutto, il calcolo delle probabilità di transizione viene eseguito da t.matrix
(senza normalizzazione con la divisione per , facilitando il tracciamento dei calcoli durante il test del codice):(n+kk)
t.matrix <- function(q, p, n, k) {
j <- max(0, q-(n+1)):min(k-1, q-(p+1))
return (sum(choose(p-1+j,j) * choose(n+k-q, k-1-j))
}
Questo è usato da transition
aggiornare a . Calcola la matrice di transizione ed esegue la moltiplicazione. Si occupa anche di calcolare il vettore iniziale se l'argomento è un vettore vuoto:pj−1pjp1p
#
# `p` is the place distribution: p[i] is the chance the place is `i`.
#
transition <- function(p, k) {
n <- length(p)
if (n==0) {
q <- c(1, rep(0, k-1))
} else {
#
# Construct the transition matrix.
#
t.mat <- matrix(0, nrow=n, ncol=(n+k))
#dimnames(t.mat) <- list(p=1:n, q=1:(n+k))
for (i in 1:n) {
t.mat[i, ] <- c(rep(0, i), sapply((i+1):(n+k),
function(q) t.matrix(q, i, n, k)))
}
#
# Normalize and apply the transition matrix.
#
q <- as.vector(p %*% t.mat / choose(n+k, k))
}
names(q) <- 1:(n+k)
return (q)
}
Ora possiamo facilmente calcolare le probabilità non-mark in ogni fase per qualsiasi mazzo:
#
# `k` is an array giving the numbers of each card in order;
# e.g., k = rep(4, 13) for a standard deck.
#
# NB: the *complements* of the p-vectors are output.
#
game <- function(k) {
p <- numeric(0)
q <- sapply(k, function(i) 1 - sum(p <<- transition(p, i)))
names(q) <- names(k)
return (q)
}
Eccoli per il mazzo standard:
k <- rep(4, 13)
names(k) <- c("A", 2:9, "T", "J", "Q", "K")
(g <- game(k))
L'output è
A 2 3 4 5 6 7 8 9 T J Q K
0.00000000 0.01428571 0.09232323 0.25595013 0.46786622 0.66819134 0.81821790 0.91160622 0.96146102 0.98479430 0.99452614 0.99818922 0.99944610
Secondo le regole, se un re fosse segnato, non cercheremmo altre carte: questo significa che il valore di deve essere aumentato a . Nel fare ciò, le differenze danno la distribuzione del "numero in cui ti troverai quando il mazzo si esaurisce":0.99944611
> g[13] <- 1; diff(g)
2 3 4 5 6 7 8 9 T J Q K
0.014285714 0.078037518 0.163626897 0.211916093 0.200325120 0.150026562 0.093388313 0.049854807 0.023333275 0.009731843 0.003663077 0.001810781
(Confronta questo con l'output che riporto in una risposta separata che descrive una simulazione Monte-Carlo: sembrano essere gli stessi, fino alle quantità previste di variazione casuale.)
Il valore atteso è immediato:
> sum(diff(g) * 2:13)
[1] 5.832589
Tutto sommato, ciò richiedeva solo una dozzina di righe di codice eseguibile. L'ho verificato rispetto ai calcoli manuali per piccoli valori di (fino a ). Pertanto, se si riscontra una discrepanza tra il codice e la precedente analisi del problema, affidarsi al codice (poiché l'analisi potrebbe contenere errori tipografici).k3
Osservazioni
Rapporti con altre sequenze
Quando ce n'è una per ogni carta, la distribuzione è una sequenza di reciproci di numeri interi:
> 1/diff(game(rep(1,10)))
[1] 2 3 8 30 144 840 5760 45360 403200
Il valore al posto sono(a partire dal posto ). Questa è la sequenza A001048 nell'Enciclopedia online delle sequenze di numeri interi. Di conseguenza, potremmo sperare in una formula chiusa per i mazzi con costante (i mazzi "adatti") che generalizzi questa sequenza, che a sua volta ha alcuni significati profondi. (Ad esempio, conta le dimensioni delle classi di coniugazione più grandi nei gruppi di permutazione ed è anche correlata ai coefficienti trinomiali .) (Sfortunatamente, i reciproci nella generalizzazione per non sono generalmente numeri interi).ii!+(i−1)!i=1kik>1
Il gioco come processo stocastico
La nostra analisi chiarisce che coefficienti iniziali dei vettori , , sono costanti. Ad esempio, seguiamo l'output di come elabora ogni gruppo di carte:ipjj≥igame
> sapply(1:13, function(i) game(rep(4,i)))
[[1]]
[1] 0
[[2]]
[1] 0.00000000 0.01428571
[[3]]
[1] 0.00000000 0.01428571 0.09232323
[[4]]
[1] 0.00000000 0.01428571 0.09232323 0.25595013
...
[[13]]
[1] 0.00000000 0.01428571 0.09232323 0.25595013 0.46786622 0.66819134 0.81821790 0.91160622 0.96146102 0.98479430 0.99452614 0.99818922 0.99944610
Ad esempio, il secondo valore del vettore finale (che descrive i risultati con un mazzo completo di 52 carte) è già apparso dopo l'elaborazione del secondo gruppo (ed è uguale a ). Pertanto, se si desidera solo informazioni sul markup attraverso il valore della carta , è necessario eseguire il calcolo solo per un mazzo di card.1/(84)=1/70jthk1+k2+⋯+kj
Perché la possibilità di non segna una carta di valore di si sta rapidamente vicino al come aumenta, dopo tipi di carte in quattro semi abbiamo quasi raggiunto il valore limite per l'attesa. In effetti, il valore limite è di circa (calcolato per un mazzo di carte, a quel punto un errore di arrotondamento a doppia precisione impedisce di andare oltre).j1j135.8333554×32
sincronizzazione
Osservando l'algoritmo applicato a -vector , vediamo che il suo tempismo dovrebbe essere proporzionale a e - usando un limite superiore grezzo - non peggio che proporzionale a . Sincronizzando tutti i calcoli per a e a e analizzando solo quelli che richiedono tempi relativamente lunghi ( secondo o più), stimo che il tempo di calcolo sia approssimativamente , a sostegno di questa valutazione del limite superiore.( k , k , ... , k ) k 2 m 3 k = 1 7 n = 10 30 1 / 2 O ( k 2 n 2.9 )m(k,k,…,k)k2m3k=17n=10301/2O(k2n2.9)
Un uso di questi asintotici è di proiettare i tempi di calcolo per problemi più grandi. Ad esempio, visto che il caso richiede circa secondi, stimeremmo che il caso (molto interessante) richiederebbe circa secondi. (In realtà ci vogliono secondi.)1,31 k = 1 , n = 100 1.31 ( 1 / 4 ) 2 ( 100 / 30 ) 2,9 ≈ 2,7 2,87k=4,n=301.31k=1,n=1001.31(1/4)2(100/30)2.9≈2.72.87