Rompicapo: come generare 7 numeri interi con uguale probabilità usando una moneta distorta che ha un pr (testa) = p?


58

Questa è una domanda che ho trovato su Glassdoor : come si possono generare 7 numeri interi con uguale probabilità usando una moneta che ha un ?Pr(Head)=p(0,1)

Fondamentalmente, hai una moneta che può essere o non essere giusta, e questo è l'unico processo di generazione di numeri casuali che hai, quindi crea un generatore di numeri casuali che genera numeri interi da 1 a 7 in cui la probabilità di ottenere ciascuno di questi numeri interi è 1/7.

L'efficienza del processo genera dati.


Correlati, non duplici
Ripristina Monica il

12
Ci sono una miriade di modi per ottenere questo risultato. Una versione più interessante della domanda richiede il metodo migliore in un senso ben definito. Un senso naturale del meglio sarebbe il numero meno atteso di lanci per numero intero generato. Un'altra versione interessante è descrivere tutte le possibili soluzioni (che si basano su lanci indipendenti della moneta e niente di più).
whuber

1
@whuber buon suggerimento, ho modificato la domanda per riflettere il tuo commento.
Amazzonia,

<<< Fondamentalmente, hai una moneta che può essere o non essere giusta, e questo è l'unico processo di generazione di numeri casuali che hai >>> Significa che, usando la moneta in un metodo diverso dal lanciarla e controllare la testa vs. tail è "proibito", dal momento che sarebbe un altro processo di generazione di numeri casuali?
TinglTanglBob,

9
Mod 7 dell'anno sulla moneta.
Nat

Risposte:


56

Lancia la moneta due volte. Se atterra HHo TT, ignoralo e capovolgilo di nuovo due volte.

Ora, la moneta ha la stessa probabilità di salire HTo TH. Se si presenta HT, chiama questo H1. Se si presenta TH, chiama questo T1.

Continua a ottenere H1o T1fino a quando non ne hai tre di seguito. Questi tre risultati forniscono un numero basato sulla tabella seguente:

H1 H1 H1 -> 1
H1 H1 T1 -> 2
H1 T1 H1 -> 3
H1 T1 T1 -> 4
T1 H1 H1 -> 5
T1 H1 T1 -> 6
T1 T1 H1 -> 7
T1 T1 T1 -> [Throw out all results so far and repeat]

Sostengo che questo funzionerebbe perfettamente, anche se nel processo si avrebbe un sacco di sprechi!


4
L'unico vincolo è che la probabilità di testa è "p". Si noti che p potrebbe essere o . Quindi non è garantito che funzioni, ma Sycorax (o Sephan) funzionerebbe, anche in quei casi. 101
gung - Ripristina Monica

8
@gung: Non sono sicuro che lavorerei per una moneta con due teste o due code.
S. Kolassa - Ripristina Monica il

6
Con probabilità finirà a tempo finito. 1
Clark,

18
Questo si chiama sbiancamento Von-Neuman.
DonFusili,

4
Puoi iterare l'estrattore von Neumann per estrarre più completamente l'entropia dalla sequenza. Raccogli tutte le coppie HH e TT, considera una sequenza, applica l'estrattore von Neumann, ecc.
A Simmons,

47

Supponiamo che .p(0,1)

Fase 1: . Lancia la moneta 5 volte.

Se il risultato è

, ritorno 1 e stop.(H,H,H,T,T)1

, ritorno 2 e stop.(H,H,T,T,H)2

, ritorno 3 e stop.(H,T,T,H,H)3

, ritorno 4 e stop.(T,T,H,H,H)4

, ritorno 5 e stop.(T,H,H,H,T)5

, ritorno 6 e stop.(H,H,T,H,T)6

, ritorno 7 e stop.(H,T,H,T,H)7

Fase 2: . Se il risultato non è uno dei precedenti, ripetere il passaggio 1.

Si noti che indipendentemente dal valore di , ciascuno dei sette risultati sopra elencati ha probabilità q = p 3 ( 1 - p ) 2 e il numero previsto di gettoni è 5p(0,1)q=p3(1p)2 . Il lanciatore non ha bisogno di conoscere il valore dip(tranne chep0ep1); è garantito che i sette numeri interi abbiano la stessa probabilità di essere restituiti dall'esperimento quando termina (ed è garantito che termina con probabilità1).57qpp0p11


6
Possiamo ridurre il numero previsto di lanci per questo consentendo o la sequenza qui specificata O quella sequenza con ogni inversione invertita. ad es .: per 1, (H, H, H, T, T) o (T, T, T, H, H)?
altro il

5
Puoi aggiungere anche il complemento. Se il risultato è (H, H, H, T, T) o (T, T, T, H, H), restituire 1 e arrestare, ecc. In tal caso la probabilità per ciascun risultato è . q=p3(1p)2+p2(1p)3
Sisto Empirico

2
Non sarebbe possibile aggiungere un altro lancio di una moneta se il risultato non dovesse riguardare alcuna disposizione (H, H, H, T, T)? Con il lancio della moneta aggiuntivo avresti bisogno di un'altra mappatura di (H, H, H, T, T, T) e (H, H, T, T, T, T) e ciascuna combinazione xT (7-x) H che può essere organizzato in 7 o più ordini diversi ai numeri da 1 a 7. Invece di riutilizzare tutte e 5 le monete questo aggiungerebbe solo 1 lancio aggiuntivo, ma non sono sicuro che funzioni: D
TinglTanglBob

5
Forse potrebbe essere la cosa migliore lanciare istantaneamente la moneta 7 volte, dal momento che è garantito, otterrai un numero casuale da esso (l'unica eccezione quindi è che la moneta atterra a testa alta o coda tutti i 7 tentativi) . Quindi con 7 lanci potresti finire con 1 fino a 6 teste (escludo qui l'opzione 0 e 7 poiché è inutile). Se una testa ci sono 7 diverse disposizioni di (H, T, T, T, T, T, T); Se 2 esce 21; se 3 è il suo 35; se 4 35 teste; se 5 21 teste; se 6 7 teste; Ciascuno può essere perfettamente mappato al numero 1-7 senza alcuna combinazione persa.
TinglTanglBob,

2
@TinglTanglBob Questa è essenzialmente la risposta di Martijn Weterings ;-)
M.Herzkamp,

22

Generalizzando il caso descritto da Dilip Sarwate

Alcuni dei metodi descritti nelle altre risposte utilizzano uno schema in cui si lancia una sequenza di n monete in un "turno" e, in base al risultato, si sceglie un numero compreso tra 1 o 7 oppure si scartano i turni e si lancia di nuovo.

Il trucco è trovare nell'espansione delle possibilità un multiplo di 7 risultati con la stessa probabilità pk(1p)nk e abbinarli tra loro.

Poiché il numero totale di risultati non è un multiplo di 7, abbiamo alcuni risultati che non possiamo assegnare a un numero e abbiamo alcune probabilità che dobbiamo scartarli e ricominciare da capo.


Il caso dell'utilizzo di 7 lanci di monete per turno

Intuitivamente potremmo dire che lanciare i dadi sette volte sarebbe molto interessante. Dal momento che abbiamo solo bisogno di buttare via 2 delle 27 possibilità. Vale a dire, il 7 volte teste e 0 volte teste.

Per tutte le altre 272 possibilità c'è sempre un multiplo di 7 casi con lo stesso numero di teste. Vale a dire 7 casi con 1 testa, 21 casi con 2 teste, 35 casi con 3 teste, 35 casi con 4 teste, 21 casi con 5 teste e 7 casi con 6 teste.

Quindi se calcoli il numero (scartando 0 teste e 7 teste)

X=k=17(k1)Ck

con Ck variabili variabili distribuite da Bernoulli (valore 0 o 1), quindi X modulo 7 è una variabile uniforme con sette possibili risultati.


Confronto tra un numero diverso di lanci di monete per turno

La domanda rimane quale sarebbe il numero ottimale di tiri per turno. Tirare più dadi per turno ti costa di più, ma riduci la probabilità di dover rotolare di nuovo.

L'immagine seguente mostra un calcolo manuale per i primi numeri di lanci di monete per turno. (forse potrebbe esserci una soluzione analitica, ma credo sia sicuro affermare che un sistema con 7 lanci di monete fornisce il metodo migliore per quanto riguarda il valore di aspettativa per il numero necessario di lanci di monete)

numero previsto di lanci di monete

# plot an empty canvas
plot(-100,-100,
     xlab="flips per turn",
     ylab="E(total flips)",
     ylim=c(7,400),xlim=c(0,20),log="y")
title("expectation value for total number of coin flips
(number of turns times flips per turn)")

# loop 1
# different values p from fair to very unfair 
# since this is symmetric only from 0 to 0.5 is necessary 

# loop 2
# different values for number of flips per turn
# we can only use a multiple of 7 to assign 
#   so the modulus will have to be discarded
#   from this we can calculate the probability that the turn succeeds
#   the expected number of flips is 
#       the flips per turn 
#             divided by 
#       the probability for the turn to succeed 

for (p in c(0.5,0.2,0.1,0.05)) {
  Ecoins <- rep(0,16)
  for (dr in (5:20)){
    Pdiscards = 0
    for (i in c(0:dr)) { 
      Pdiscards = Pdiscards + p^(i)*(1-p)^(dr-i) * (choose(dr,i) %% 7)
    }
    Ecoins[dr-4] = dr/(1-Pdiscards)
  }
  lines(5:20, Ecoins)
  points(5:20, Ecoins, pch=21, col="black", bg="white", cex=0.5)
  text(5, Ecoins[1], paste0("p = ",p), pos=2)
}

Utilizzando una regola di arresto anticipato

p=0.5p

X

  • Con 5 lanci di monete abbiamo per le sei possibili diverse serie non ordinate di teste e code:

    1 + 5 + 10 + 10 + 5 + 1 set ordinati

    E possiamo usare i gruppi con dieci casi (cioè il gruppo con 2 teste o il gruppo con 2 code) per scegliere (con uguale probabilità) un numero. Ciò si verifica in 14 casi su 2 ^ 5 = 32. Questo ci lascia con:

    1 + 5 + 3 + 3 + 5 + 1 set ordinati

  • Con un lancio di monete extra (6 °) abbiamo per le sette possibili diverse serie non ordinate di teste e code:

    1 + 6 + 8 + 6 + 8 + 6 + 1 set ordinati

    E possiamo usare i gruppi con otto casi (ovvero il gruppo con 3 teste o il gruppo con 3 code) per scegliere (con uguale probabilità) un numero. Ciò si verifica in 14 casi su 2 * (2 ^ 5-14) = 36 casi. Questo ci lascia con:

    1 + 6 + 1 + 6 + 1 + 6 + 1 set ordinati

  • Con un altro (7 °) lancio di monete extra abbiamo per le otto possibili diverse serie non ordinate di teste e code:

    1 + 7 + 7 + 7 + 7 + 7 + 7 + 1 set ordinati

    E possiamo usare i gruppi con sette casi (tutti tranne tutti i casi e tutti i capi) per scegliere (con uguale probabilità) un numero. Ciò si verifica in 42 casi su 44. Questo ci lascia con:

    1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 set ordinati

    (potremmo continuare questo, ma solo nel 49 ° passaggio questo ci dà un vantaggio)

Quindi la probabilità di selezionare un numero

  • 1432=716
  • 9161436=732
  • 11324244=231704
  • 1716732231704=227

Questo rende il valore di aspettativa per il numero di lanci in un turno, a condizione che ci sia successo e p = 0,5:

5716+6732+7231704=5.796875

Il valore di aspettativa per il numero totale di lanci (fino a quando non c'è un successo), a condizione che p = 0,5, diventi:

(5716+6732+7231704)27272=539=5.88889


La risposta di NcAdams utilizza una variante di questa strategia delle regole di arresto (ogni volta escono due nuovi lanci di monete) ma non sta selezionando in modo ottimale tutti i lanci.

Anche la risposta di Clid potrebbe essere simile anche se potrebbe esserci una regola di selezione irregolare secondo cui ogni due gettoni lancia un numero, ma non necessariamente con uguale probabilità (una discrepanza che viene riparata durante i gettoni successivi)


Confronto con altri metodi

Altri metodi che usano un principio simile sono quelli di NcAdams e AdamO.

xij

x

Ciò è dimostrato dall'immagine e dalla simulazione seguenti:

confronto

#### mathematical part #####
set.seed(1)


#plotting this method
p <- seq(0.001,0.999,0.001)
tot <- (5*7*(p^2*(1-p)^3+p^3*(1-p)^2)+
       6*7*(p^2*(1-p)^4+p^4*(1-p)^2)+
       7*7*(p^1*(1-p)^6+p^2*(1-p)^5+p^3*(1-p)^4+p^4*(1-p)^3+p^5*(1-p)^2+p^6*(1-p)^1)+
        7*1*(0+p^7+(1-p)^7) )/
             (1-p^7-(1-p)^7)
plot(p,tot,type="l",log="y",
     xlab="p",
     ylab="expactation value number of flips"
     )

#plotting method by AdamO
tot <- (7*(p^20-20*p^19+189*p^18-1121*p^17+4674*p^16-14536*p^15+34900*p^14-66014*p^13+99426*p^12-119573*p^11+114257*p^10-85514*p^9+48750*p^8-20100*p^7+5400*p^6-720*p^5)+6*
          (-7*p^21+140*p^20-1323*p^19+7847*p^18-32718*p^17+101752*p^16-244307*p^15+462196*p^14-696612*p^13+839468*p^12-806260*p^11+610617*p^10-357343*p^9+156100*p^8-47950*p^7+9240*p^6-840*p^5)+5*
          (21*p^22-420*p^21+3969*p^20-23541*p^19+98154*p^18-305277*p^17+733257*p^16-1389066*p^15+2100987*p^14-2552529*p^13+2493624*p^12-1952475*p^11+1215900*p^10-594216*p^9+222600*p^8-61068*p^7+11088*p^6-1008*p^5)+4*(-
          35*p^23+700*p^22-6615*p^21+39235*p^20-163625*p^19+509425*p^18-1227345*p^17+2341955*p^16-3595725*p^15+4493195*p^14-4609675*p^13+3907820*p^12-2745610*p^11+1592640*p^10-750855*p^9+278250*p^8-76335*p^7+13860*p^6-
          1260*p^5)+3*(35*p^24-700*p^23+6615*p^22-39270*p^21+164325*p^20-515935*p^19+1264725*p^18-2490320*p^17+4027555*p^16-5447470*p^15+6245645*p^14-6113275*p^13+5102720*p^12-3597370*p^11+2105880*p^10-999180*p^9+371000
           *p^8-101780*p^7+18480*p^6-1680*p^5)+2*(-21*p^25+420*p^24-3990*p^23+24024*p^22-103362*p^21+340221*p^20-896679*p^19+1954827*p^18-3604755*p^17+5695179*p^16-7742301*p^15+9038379*p^14-9009357*p^13+7608720*p^12-
           5390385*p^11+3158820*p^10-1498770*p^9+556500*p^8-152670*p^7+27720*p^6-2520*p^5))/(7*p^27-147*p^26+1505*p^25-10073*p^24+49777*p^23-193781*p^22+616532*p^21-1636082*p^20+3660762*p^19-6946380*p^18+11213888*p^17-
           15426950*p^16+18087244*p^15-18037012*p^14+15224160*p^13-10781610*p^12+6317640*p^11-2997540*p^10+1113000*p^9-305340*p^8+55440*p^7-5040*p^6)
lines(p,tot,col=2,lty=2)

#plotting method by NcAdam
lines(p,3*8/7/(p*(1-p)),col=3,lty=2)

legend(0.2,500,
       c("this method calculation","AdamO","NcAdams","this method simulation"),
       lty=c(1,2,2,0),pch=c(NA,NA,NA,1),col=c(1,2,3,1))


##### simulation part ######

#creating decision table
mat<-matrix(as.numeric(intToBits(c(0:(2^5-1)))),2^5,byrow=1)[,c(1:12)]
colnames(mat) <- c("b1","b2","b3","b4","b5","b6","b7","sum5","sum6","sum7","decision","exit")

# first 5 rolls
mat[,8] <- sapply(c(1:2^5), FUN = function(x) {sum(mat[x,1:5])})

mat[which((mat[,8]==2)&(mat[,11]==0))[1:7],12] = rep(5,7) # we can stop for 7 cases with 2 heads
mat[which((mat[,8]==2)&(mat[,11]==0))[1:7],11] = c(1:7)   
mat[which((mat[,8]==3)&(mat[,11]==0))[1:7],12] = rep(5,7) # we can stop for 7 cases with 3 heads
mat[which((mat[,8]==3)&(mat[,11]==0))[1:7],11] = c(1:7)    

# extra 6th roll
mat <- rbind(mat,mat)
mat[c(33:64),6] <- rep(1,32)
mat[,9] <- sapply(c(1:2^6), FUN = function(x) {sum(mat[x,1:6])})

mat[which((mat[,9]==2)&(mat[,11]==0))[1:7],12] = rep(6,7) # we can stop for 7 cases with 2 heads
mat[which((mat[,9]==2)&(mat[,11]==0))[1:7],11] = c(1:7)   
mat[which((mat[,9]==4)&(mat[,11]==0))[1:7],12] = rep(6,7) # we can stop for 7 cases with 4 heads
mat[which((mat[,9]==4)&(mat[,11]==0))[1:7],11] = c(1:7)    

# extra 7th roll
mat <- rbind(mat,mat)
mat[c(65:128),7] <- rep(1,64)
mat[,10] <- sapply(c(1:2^7), FUN = function(x) {sum(mat[x,1:7])})

for (i in 1:6) {
  mat[which((mat[,10]==i)&(mat[,11]==0))[1:7],12] = rep(7,7) # we can stop for 7 cases with i heads
  mat[which((mat[,10]==i)&(mat[,11]==0))[1:7],11] = c(1:7)   
}


mat[1,12] = 7           # when we did not have succes we still need to count the 7 coin tosses
mat[2^7,12] = 7


draws = rep(0,100)
num = rep(0,100)
# plotting simulation
for (p in seq(0.05,0.95,0.05)) {
  n <- rep(0,1000)
  for (i in 1:1000) {
    coinflips <- rbinom(7,1,p)  # draw seven numbers
    I <- mat[,1:7]-matrix(rep(coinflips,2^7),2^7,byrow=1) == rep(0,7)                      # compare with the table
    Imatch = I[,1]*I[,2]*I[,3]*I[,4]*I[,5]*I[,6]*I[,7]        # compare with the table 
      draws[i] <- mat[which(Imatch==1),11]                 # result which number
      num[i]   <- mat[which(Imatch==1),12]                 # result how long it took
  }
  Nturn <- mean(num)                   #how many flips we made
  Sturn <- (1000-sum(draws==0))/1000   #how many numbers we got (relatively)
  points(p,Nturn/Sturn)
}

p(1p)

confronto con valori di aspettativa ridimensionati

ingrandire i metodi di confronto descritti in questo post e commenti

metodi di confronto descritti qui

il "salto condizionato del 7 ° passaggio" è un leggero miglioramento che può essere apportato alla regola di arresto anticipato. In questo caso non si selezionano gruppi con pari probabilità dopo il 6 ° lancio. Hai 6 gruppi con pari probabilità e 1 gruppo con una probabilità leggermente diversa (per quest'ultimo gruppo devi capovolgere un altro tempo in più quando hai 6 teste o code e poiché scarti le 7 teste o 7 code, finirai dopo con la stessa probabilità dopo tutto)


Scritto da StackExchangeStrike


Stavo per iniziare a fare i calcoli per il caso n = 7, perché avevo la sensazione che potesse essere migliore di n = 1. Ho il mio voto, signore!
M.Herzkamp,

@ M.Herzkamp è ancora possibile un piccolo miglioramento. Un numero CkX

Quindi il miglioramento lo porta a poco più di 6 lanci di monete come valore di aspettativa per il numero di lanci di monete richiesti. Sarebbe diverso però per dimostrare che questa è la soluzione ottimale. Lo schema creato da Clid diverge un po 'permettendo di scegliere un numero in un determinato numero di lanci di monete ma non con uguale probabilità (almeno non per quel particolare passaggio, verrà corretto in seguito).
Sesto Empirico,

Ma se stai decidendo se lanciare la sesta moneta in base ai primi cinque risultati, le probabilità di ogni set, a condizione che tu abbia ottenuto sei lanci, sono le stesse degli altri set?
Accumulo

@ Accumulo potresti disegnarlo come un albero binario con 7 livelli. Selezioneremo tra i nodi solo se ce ne sono 7 con uguale probabilità. È come tagliare alcuni rami prima (al livello 5 o 6). Se lo desideri, puoi continuare fino a 7 passaggi, anziché in precedenza, ma in questi casi particolari il lancio della sesta e della settima moneta non fa differenza.
Sesto Empirico

20

Dividi un riquadro in sette regioni di uguale area, ciascuna etichettata con un numero intero. Getta la moneta nella scatola in modo tale che abbia pari probabilità di atterrare in ogni regione.

π

Questa è una delle uniche risposte valide per il caso di p=1p=0


2
Puoi suggerire un modo per dividere la scatola in sette regioni di uguale area, per ridurre al minimo la distorsione da ribaltamento, rimbalzo di muri ecc.? Sette settori dell'angolo 360/7?
smci

1
@smci Ecco perché stipulo che devi lanciare la moneta in modo che ci sia una probabilità uniforme che atterri in ogni quadrato. Se rimbalzare da un muro influenza quella probabilità, allora devi tenerne conto nel tuo tiro.
Ripristina Monica il

17
Sì, lo so che, e sto sottolineando a voi che semplicemente dicendo "buttarla in modo imparziale" senza definire esattamente come il raggiungimento di tale, non è in realtà una risposta completa ... nel qual caso il flipping-H / T i metodi basati sono superiori.
smci,

1
"Pari aree, con tiri che hanno pari probabilità di atterraggio in ciascuna regione" potrebbero essere difficili da stabilire in pratica. In pratica potrebbe essere più semplice tracciare un gran numero di "tiri di prova" e quindi suddividere l'area di atterraggio in spazi equipaggiabili empiricamente (ad es. Con 700 tiri, escludere una linea che taglia i 100 tiri più lontani, quindi un altro per il prossimo 100 e così via). Una semplificazione di questo per generare un singolo bit casuale sarebbe quella di lanciare la moneta due volte - se il primo lancio va oltre, il bit lo è 0e se il secondo lancio va oltre è un1
Pesce d'argento

4
C'è una bella risposta di @TheScienceBoy che purtroppo viene eliminata con un'alternativa interessante a questa - in effetti, usando la moneta come un filatore e segnando 7 sezioni lungo la sua circonferenza - che conserva gran parte dello spirito di questa risposta ma può essere fisicamente più semplice portare fuori!
Silverfish,

8

EDIT: basato sul feedback degli altri.

Ecco un pensiero interessante:

imposta l'elenco di {1,2,3,4,5,6,7}. Lancia la moneta per ciascun elemento nell'elenco in sequenza. Se arriva a testa in su per un particolare elemento, rimuovi il numero dall'elenco. Se tutti i numeri di una particolare iterazione dell'elenco vengono rimossi, ripetere il campionamento. Fallo finché non rimane un solo numero.

drop.one <- function(x, p) {
  drop <- runif(length(x)) < p
  if (all(drop))
    return(x)
  return(x[!drop])
}

sample.recur <- function(x, p) {
  if (length(x) > 1)
    return(sample.recur(drop.one(x, p), p))
  return(x)
}

# x <- c(1:7,7:1)
x <- 1:7
p <- 0.01

out <- replicate(1e5, sample.recur(x, p))

round(prop.table(table(out)), 2)

mi dà una distribuzione approssimativamente uniforme

> round(prop.table(table(out)), 2)
out
   1    2    3    4    5    6    7 
0.14 0.14 0.15 0.14 0.14 0.14 0.14 

N esiti binomiali come la somma di 13 lanci della moneta (contando 0 teste come risultato) e mappando {0,1 , 2, ..., 12,13} indice nell'elenco precedente di {1,2,3, ..., 3,2,1}. Non so proprio come provare che il mio metodo funzioni.


Valutazione del valore di aspettativa per il numero di lanci di monete

xy

M=[q700000117p1q6q600000021p2q56p1q5q50000035p3q415p2q45q4q4000035p4q320p3q310p2q34p1q3q300021p5q215p4q210p3q26p2q23p1q2q2007p6q16p5q15p4q14p3q13p2q12p1q100p7p6p5p4p3p200]

(MI)v=0

E(n)=247p(1p)

confronto del valore di aspettativa per i lanci di monete

p>2/3 . Ma anche le prestazioni non sono simmetriche. Una prestazione complessiva simmetrica e migliore potrebbe essere realizzata quando verrebbe fatta una regola di commutazione probabilistica che modifica la regola di decisione da code a teste quando le teste risultano improbabili.

Soluzione trovata con wxMaxima

M: matrix(
 [(1-p)^7,        0,          0,0,0,0,1,1], 
 [7* p*(1-p)^6,   (1-p)^6,        0,0,0,0,0,0], 
 [21*p^2*(1-p)^5, 6*p*(1-p)^5,    (1-p)^5,0,0,0,0,0], 
 [35*p^3*(1-p)^4, 15*p^2*(1-p)^4, 5*p*(1-p)^4,(1-p)^4,0,0,0,0], 
 [35*p^4*(1-p)^3, 20*p^3*(1-p)^3, 10*p^2*(1-p)^3,4*p*(1-p)^3,(1-p)^3,0,0,0], 
 [21*p^5*(1-p)^2, 15*p^4*(1-p)^2, 10*p^3*(1-p)^2,6*p^2*(1-p)^2,3*p*(1-p)^2,(1-p)^2,0,0], 
 [7* p^6*(1-p)^1, 6*p^5*(1-p),    5*p^4*(1-p),4*p^3*(1-p),3*p^2*(1-p),2*(1-p)*p,0,0], 
 [p^7,        p^6,        p^5,p^4,p^3,p^2,0,0]
);
z: nullspace(M-diagmatrix(8,1));
x : apply (addcol, args (z));
t : [7,6,5,4,3,2,0,0];
plot2d(t.x/x[7],[p,0,1],logy);

Calcoli in R

# plotting empty canvas
plot(-100,-100,
     xlab="p",
     ylab="E(total flips)",
     ylim=c(10,1000),xlim=c(0,1),log="y")

# plotting simulation
for (p in seq(0.1,0.9,0.05)) {

  n <- rep(0,10000)
  for (i in 1:10000) {
    success  = 0
    tests = c(1,1,1,1,1,1,1)     # start with seven numbers in the set
    count = 0
    while(success==0) {
      for (j in 1:7)  {
        if (tests[j]==1) {
          count = count + 1
          if  (rbinom(1,1,p) == 1) {
            tests[j] <- 0        # elliminate number when we draw heads
          }
        }
      }
      if (sum(tests)==1) {
        n[i] = count
        success = 1              # end     when 1 is left over
      }
      if (sum(tests)==0) {
        tests = c(1,1,1,1,1,1,1) # restart when 0 are left over
      }
    }
  }
  points(p,mean(n))
}

# plotting formula
p <- seq(0.001,0.999,0.001)

tot <- (7*(p^20-20*p^19+189*p^18-1121*p^17+4674*p^16-14536*p^15+34900*p^14-66014*p^13+99426*p^12-119573*p^11+114257*p^10-85514*p^9+48750*p^8-20100*p^7+5400*p^6-720*p^5)+6*
    (-7*p^21+140*p^20-1323*p^19+7847*p^18-32718*p^17+101752*p^16-244307*p^15+462196*p^14-696612*p^13+839468*p^12-806260*p^11+610617*p^10-357343*p^9+156100*p^8-47950*p^7+9240*p^6-840*p^5)+5*
    (21*p^22-420*p^21+3969*p^20-23541*p^19+98154*p^18-305277*p^17+733257*p^16-1389066*p^15+2100987*p^14-2552529*p^13+2493624*p^12-1952475*p^11+1215900*p^10-594216*p^9+222600*p^8-61068*p^7+11088*p^6-1008*p^5)+4*(-
    35*p^23+700*p^22-6615*p^21+39235*p^20-163625*p^19+509425*p^18-1227345*p^17+2341955*p^16-3595725*p^15+4493195*p^14-4609675*p^13+3907820*p^12-2745610*p^11+1592640*p^10-750855*p^9+278250*p^8-76335*p^7+13860*p^6-
    1260*p^5)+3*(35*p^24-700*p^23+6615*p^22-39270*p^21+164325*p^20-515935*p^19+1264725*p^18-2490320*p^17+4027555*p^16-5447470*p^15+6245645*p^14-6113275*p^13+5102720*p^12-3597370*p^11+2105880*p^10-999180*p^9+371000
   *p^8-101780*p^7+18480*p^6-1680*p^5)+2*(-21*p^25+420*p^24-3990*p^23+24024*p^22-103362*p^21+340221*p^20-896679*p^19+1954827*p^18-3604755*p^17+5695179*p^16-7742301*p^15+9038379*p^14-9009357*p^13+7608720*p^12-
 5390385*p^11+3158820*p^10-1498770*p^9+556500*p^8-152670*p^7+27720*p^6-2520*p^5))/(7*p^27-147*p^26+1505*p^25-10073*p^24+49777*p^23-193781*p^22+616532*p^21-1636082*p^20+3660762*p^19-6946380*p^18+11213888*p^17-
  15426950*p^16+18087244*p^15-18037012*p^14+15224160*p^13-10781610*p^12+6317640*p^11-2997540*p^10+1113000*p^9-305340*p^8+55440*p^7-5040*p^6)
lines(p,tot)

#plotting comparison with alternative method
lines(p,3*8/7/(p*(1-p)),lty=2)

legend(0.2,500,
       c("simulation","calculation","comparison"),
       lty=c(0,1,2),pch=c(1,NA,NA))

1
Idea intelligente (+1). Intuitivamente, dovrebbe funzionare, poiché la simmetria sembrerebbe annullare la distorsione verso qualsiasi numero particolare. Tuttavia, mi piacerebbe vedere una prova.
Ripristina Monica il

6
Questa idea è davvero carina, ma con un'alta probabilità di testa (buttare giù quel numero) penso che l'ultimo numero della fila abbia le migliori possibilità di "sopravvivere" dal momento che tutti gli altri infront vengono espulsi molto probabilmente prima della prima corsa? Forse potrebbe essere cambiato non lanciando la moneta in sequenza ma parallelamente per tutti i numeri in x? Il tempo di esecuzione dello script potrebbe aumentare immagino :)
TinglTanglBob il

2
Sono d'accordo con @TinglTanglBob - quando imposto p <- 0.99ottengo l'output0.89 0.02 0.02 0.02 0.02 0.02 0.02
Silverfish

6
L'esecuzione dell'eliminazione in "round" non risolverebbe il problema di distorsione? Inizia con 7 numeri. Lancia la moneta per ogni numero rimanente ed elimina quelli che lanciano la testa. Se tutti i numeri rimanenti vengono eliminati in un round, gratta i risultati di quel round e riprova. Non so come dimostrarlo, ma intuitivamente l'ordine dei numeri non importa più se sono i "vincitori"
Phil

1
p=0.01

5

La domanda è un po 'ambigua, sta chiedendo "genera un numero intero casuale uguale o inferiore a 7 con uguale probabilità" o sta chiedendo "genera 7 numeri interi casuali con uguale probabilità?" - ma qual è lo spazio degli interi?!?

Presumo sia il primo, ma la stessa logica che sto applicando può essere estesa anche al secondo caso, una volta chiarito il problema.

Con una moneta distorta, puoi produrre una moneta giusta seguendo la seguente procedura: https://en.wikipedia.org/wiki/Fair_coin#Fair_results_from_a_biased_coin

Un numero 7 o inferiore può essere scritto in binario come tre cifre {0,1}. Quindi tutto ciò che occorre fare è seguire la procedura sopra descritta tre volte e riconvertire il numero binario prodotto in decimale.


1
confrontando la mia risposta con @NcAdams, è chiaro che includo 0 come possibile risultato desiderabile!
Cam.Davidson.Pilon

Non capisco come la tua risposta sia diversa. Se includi {0,0,0} -> 1, a cosa corrisponde quindi {1,1,1}? Ci sono 8 possibilità.
AdamO,

1
000 sono mappati su 0, quindi il mio commento sull'inclusione di 0 come possibile valore. Questo è stato pubblicato prima della modifica dell'OP e quasi contemporaneamente come NcAdams.
Cam.Davidson.Pilon

La metà di questa risposta è un commento e il contenuto effettivo della risposta è solo link. Si prega di precisare la risposta effettiva piuttosto che semplicemente il collegamento ad essa.
Cubico

3

Una soluzione che non spreca mai lanci, che aiuta molto per le monete molto distorte.

Lo svantaggio di questo algoritmo (almeno come scritto) è l'utilizzo dell'aritmetica di precisione arbitraria. Praticamente, probabilmente vorrai usarlo fino al trabocco di numeri interi, e solo allora buttarlo via e ricominciare.

Inoltre, è necessario sapere che cosa il bias è ... che non si potrebbe, ad esempio, se è dipendente dalla temperatura come la maggior parte dei fenomeni fisici.


Supponendo che la probabilità di testa sia, diciamo, del 30%.

  • Inizia con l'intervallo [1, 8).
  • Lancia la tua moneta. Se esce testa, usa il 30% a sinistra, quindi la tua nuova gamma è [1, 3.1). Altrimenti, usa il giusto 70%, quindi la tua nuova gamma è [3.1, 8).
  • Ripetere fino a quando l'intero intervallo ha la stessa parte intera.

Codice completo:

#!/usr/bin/env python3
from fractions import Fraction
from collections import Counter
from random import randrange


BIAS = Fraction(3, 10)
STAT_COUNT = 100000


calls = 0
def biased_rand():
    global calls
    calls += 1
    return randrange(BIAS.denominator) < BIAS.numerator


def can_generate_multiple(start, stop):
    if stop.denominator == 1:
        # half-open range
        stop = stop.numerator - 1
    else:
        stop = int(stop)
    start = int(start)
    return start != stop


def unbiased_rand(start, stop):
    if start < 0:
        # negative numbers round wrong
        return start + unbiased_rand(0, stop - start)
    assert isinstance(start, int) and start >= 0
    assert isinstance(stop, int) and stop >= start
    start = Fraction(start)
    stop = Fraction(stop)
    while can_generate_multiple(start, stop):
        if biased_rand():
            old_diff = stop - start
            diff = old_diff * BIAS
            stop = start + diff
        else:
            old_diff = stop - start
            diff = old_diff * (1 - BIAS)
            start = stop - diff
    return int(start)


def stats(f, *args, **kwargs):
    c = Counter()
    for _ in range(STAT_COUNT):
        c[f(*args, **kwargs)] += 1

    print('stats for %s:' % f.__qualname__)
    for k, v in sorted(c.items()):
        percent = v * 100 / STAT_COUNT
        print('  %s: %f%%' % (k, percent))


def main():
    #stats(biased_rand)
    stats(unbiased_rand, 1, 7+1)
    print('used %f calls at bias %s' % (calls/STAT_COUNT, BIAS))


if __name__ == '__main__':
    main()

3
[0,1]00006666k

È lo stesso per un singolo output, giusto? Solo meglio per più? Lo scriverei come diff *= 7penso ... in effetti, non è necessario utilizzare la stessa base per ogni tentativo.
o11c,

Sì, è lo stesso se si desidera un singolo output; migliora l'efficienza solo se ne vuoi di più.
Federico Poloni,

pp

Questo fa assolutamente sprecare salti se si desidera un singolo output. Per una moneta giusta, la tecnica standard (lancia la moneta tre volte e ripeti se ottieni TTT) fornisce un numero previsto di 24/7 = 3 + 3/7 tiri. Se usi questa tecnica di codifica aritmetica, tiri almeno quattro volte a meno che tu non ottenga HHH o TTT, il che ti dà un numero previsto di più di 15/4 = 3 + 3/4 tiri.
Peter Shor,

3

Come accennato nei commenti precedenti, questo puzzle si riferisce al 1951 di John von Neumann carta "varie tecniche utilizzate in connessione con Random Digits", pubblicato sulla rivista di ricerca del National Bureau of Standards:

inserisci qui la descrizione dell'immagine

pf(p)f f(p)=min{1,2p}N di prove.


2

p1p0

Trasformiamo prima la moneta (forse) ingiusta in una moneta equa usando il processo della risposta di NcAdams :

Lancia la moneta due volte. Se atterra HHo TT, ignoralo e capovolgilo di nuovo due volte.

Ora, la moneta ha la stessa probabilità di salire HTo TH. Se si presenta HT, chiama questo H1. Se si presenta TH, chiama questo T1.

01H1=1T1 =00.H1 H1 T10.110

1/7

1/7=0.001001001...

2/7=0.010010010...

3/7=0.011011011...

4/7=0.100100100...

5/7=0.101101101...

6/7=0.110110110...

nn/7(n1)/717


1
1/7

1
1/7k=1(1/8)k=17

1
nT(n)=2n62nn3
3+n=31T(n)=4.5
8733.42

2

Ispirato dalla risposta di AdamO, ecco una soluzione Python che evita distorsioni:

def roll(p, n):
    remaining = range(1,n+1)
    flips = 0
    while len(remaining) > 1:
        round_winners = [c for c in remaining if random.choices(['H','T'], [p, 1.0-p]) == ['H']]
        flips += len(remaining)
        if len(round_winners) > 0:
            remaining = round_winners
        p = 1.0 - p
    return remaining[0], flips

Ci sono due principali cambiamenti qui: il principale è che se tutto il numero viene scartato in un round, ripetere il round. Inoltre capovolgo la scelta se testa o croce significa scartare ogni volta. Ciò riduce il numero di capovolgimenti necessari nei casi in cui p è vicino a 0 o 1 del ~ 70% quando p = 0,999


2
"Capovolgo la scelta se testa o croce significa scartare ogni volta. Questo riduce il numero di lanci necessari nei casi in cui p è vicino a 0 o 1 del ~ 70% quando p = 0,999" - pensiero intelligente!
Silverfish,

1
Alternare teste o code è sicuramente un miglioramento rispetto a scartare sempre le teste - ma forse sarebbe meglio se, dopo aver lanciato una moneta per ogni opzione rimanente, se sono tutte uguali ripetiamo di ripetere tutte, altrimenti se ci sono almeno tante teste quante code eliminiamo le rimanenti opzioni corrispondenti alle teste, altrimenti eliminiamo le rimanenti opzioni corrispondenti alle code.
David Cary,

2

Sembra che ci sia permesso di cambiare la mappatura del risultato di ogni lancio, ogni volta che giriamo . Quindi, usando per comodità i primi sette numeri interi positivi, forniamo i seguenti ordini:

H1
H2

H7
H1

eccetera

T


APT

PAP(no integers generated)=(1p)7

Nb

CountAP(useless flips)7Nb(1p)7

B(p,n=5)p3(1p)2

PDS(no integers generated)=17p3(1p)2

Il conteggio di lanci inutili tenderà qui a

CountDS(useless flips)5Nb[17p3(1p)2]

AP

CountAP(useless flips)<CountDS(useless flips)

7Nb(1p)7<5Nb[17p3(1p)2]

7(1p)7<5[17p3(1p)2]

p>0.0467AP

pAPDSp0.5967

CountAP(useless flips)CountDS(useless flips)

0.67p=0.10.3p=0.20.127p=0.4


p(0,1)

1
@Sycorax Ho aggiunto qualcosa, anche se non sono sicuro che sia sulla falsa riga che hai suggerito.
Alecos Papadopoulos,

H

1
12345679999999

1
p17p
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.