HHH, HHT y el comando "yield" de Python

Variable aleatoria X: tiramos una moneda al aire sucesivamente y contamos el número de veces que lo hacemos hasta obtener el patrón HHH (tres caras) en las tres últimas tiradas.

Variable aleatoria Y: lo mismo, pero hasta que salga el patrón HHT.

Entonces las medias de X e Y son iguales, ¿verdad? Pues no. (¿Alguien sabría decirme cuál de las combinaciones, HHH o HHT, tiende, en promedio, a aparecer antes? Pueden darse explicaciones muy complejas, pero existe una muy simple e intuitiva).

Este pequeño (¿y sorprendente?) ejercicio probabilístico me ha servido de excusa para practicar con el comando yield en Python, del que vine a tener noticia recientemente.

El código es:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from random import choice

def cadena():
        a, b, c = (None, None, None)
        while(True):
                a, b, c = b, c, choice("HT")
                yield a,b,c

niter = 100000
HHH = [0] * niter
HHT = [0] * niter

for i in range(niter):
        cont = 1
        gen = cadena()

        while( True ):
                seq = gen.next()
                if seq == ('H', 'H', 'H') and HHH[i] == 0:
                        HHH[i] = cont

                if seq == ('H', 'H', 'T') and HHT[i] == 0:
                        HHT[i] = cont

                cont += 1

                if( HHH[i] * HHT[i] > 0 ):
                        break

for x in HHH:
        print x;
for x in HHT:
        print x;

La magia está en el comando yield en la función cadena. Al hacer

1
gen = cadena()

se inicia el iterador. Cada vez que uno llama entonces a

1
seq = gen.next()

se ejecuta una iteración del bucle

1
2
3
while(True):
        a, b, c = b, c, choice("HT")
        yield a,b,c

en la función cadena, que recuerda entre llamada y llamada el estado de las variables (internas a ella) a, b y c (además de devolver, como haría return, el valor generado.

Si tengo un poco de tiempo, veré si puedo implementar esta misma solucíón (sospecho que podría ser posible) con el paquete iterators de R.