Repito el código por si no se ve bien la identación del anterior mensaje:

from random import randint
from functools import partial

# única función random que se permite usar
rand5 = partial(randint, 1, 5)

# yapf: disable
# matriz de conversión
conv = [
    [1, 2, 3, 4, 5],
    [6, 7, 1, 2, 3],
    [4, 5, 6, 7, 1],
    [2, 3, 4, 5, 6],
    [7, 0, 0, 0, 0]
]
# yapf: enable


def rand7() -> int:
    """
    Generador aleatorio de números en rango [1,7]
    a partir de randint(1,5)
    """

    res = 0
    while not res:

        # tomamos dos números aleatorios en el rango [1,5]
        (a, b) = (rand5(), rand5())

        # buscamos su correspondencia en el rango [1,7]
        res = conv[a - 1][b - 1]

    return res


El sáb., 6 jul. 2019 a las 18:19, Chema Cortes (<pych...@gmail.com>)
escribió:

> El jue., 4 jul. 2019 a las 0:47, lasizoillo (<lasizoi...@gmail.com>)
> escribió:
>
>> Buenas,
>>
>> Tras leer el correo de Chema me puse a pensar en cuantos bits de
>> información se podía obtener de randint(1,5) y cuantos necesitaba
>> randint(1,7) y me dio por pensar que era ln2(5) y ln2(7). Lo cual
>> seguramente es incorrecto (las mates no son lo mío), pero aun siendo una
>> estimación menor que el ideal propuesto por Chema de 1.4 llamadas es mayor
>> al usado en la solución de Mario (1). Así que había pensado en hacer unos
>> tests de aleatoriedad sobre esa solución demasiado bonita para ser cierta,
>> pero gracias por adelantarte.
>>
>> ¿Se deberían descartar todas las soluciones que hagan menos de 1.2 o 1.4
>> llamadas a randint(1,5) para calcular randint(1,7)?
>>
>>
> Yo muchas veces hablo más por intuición, por lo que considera ese límite
> como una estimación.
>
> Los estados definidos con randint(1,7) tienen más información que los
> definidos por randint(1,5), de ahí la estimación de 1.4 (=7/5) (puedes
> calcularlo en bits, pero sale lo mismo). Como 5 y 7 son primos entre sí, no
> es posible establecer una relación directa de estados. Dicho de otro modo:
> no existen n y m, números enteros, de modo que se cumpla la igualdad 5**n
> == 7**m. Siempre será necesario despreciar casos iniciales para que la
> distribución resultante sea más o menos uniforme.
>
> Analizando la solución propuesta anteriormente: para un valor de
> randint(1,7) es necesario llamar 3 veces a randint(1,5), con una
> probalidadad de repetir llamada de 3/5 + 1/8 = 29/40 ~= 0.72, probabilidad
> que es bastante alta.
>
> Una posible mejora sería hacer sólo dos llamadas, 25 casos posibles, y
> "mapearlos" con 21 estados de randint(1,7). Quedarían 4 casos sin mapear.
> La probabilidad de repetir tirada sería 4/25 ~= 0.16 que está bastante
> mejor.
>
> El código quedaría así:
> from random import randint
> from functools import partial
>
> # única función random que se permite usar
> rand5 = partial(randint, 1, 5)
>
> # yapf: disable
> # matriz de conversión
> conv = [
> [1, 2, 3, 4, 5],
> [6, 7, 1, 2, 3],
> [4, 5, 6, 7, 1],
> [2, 3, 4, 5, 6],
> [7, 0, 0, 0, 0]
> ]
> # yapf: enable
>
>
> def rand7() -> int:
> """
> Generador aleatorio de números en rango [1,7]
> a partir de randint(1,5)
> """
>
> res = 0
> while not res:
>
> # tomamos dos números aleatorios en el rango [1,5]
> (a, b) = (rand5(), rand5())
>
> # buscamos su correspondencia en el rango [1,7]
> res = conv[a - 1][b - 1]
>
> return res
> Pero aún se puede hacer mejor. Podemos mapear los 125 estados posibles de
> 3 llamadas de randint(1,5) con 98 (2*7**2) estados de randint(1,7). La
> probabilidad de tener que repetir la tirada sería de 0.216, algo peor que
> en el caso anterior. Pero que el número de llamadas necesarias se reduzca a
> 1.5 nos acercaría bastante al límite ideal.
>
> Como este caso es algo más largo, lo dejo disponible como gist, incluyendo
> un test de uniformidad por probar algo:
>
> https://gist.github.com/chemacortes/3d66daf14b2ebd2190cd50d969defaed
>
> Una prueba completa de aleatoriedad es bastante compleja. Hay un artículo
> sobre criptografía bastante bueno sobre el tema en:
>
> https://www.incibe-cert.es/blog/comprobando-aleatoriedad
>
>
>
> --
> Hyperreals *R  "Quarks, bits y otras criaturas infinitesimales":
> https://blog.ch3m4.org
> Buscador Python Hispano: http://busca.ch3m4.org
> <https://blog.ch3m4.org/pages/busqueda-python-es/>
>


-- 
Hyperreals *R  "Quarks, bits y otras criaturas infinitesimales":
https://blog.ch3m4.org
Buscador Python Hispano: http://busca.ch3m4.org
<https://blog.ch3m4.org/pages/busqueda-python-es/>
_______________________________________________
Python-es mailing list
Python-es@python.org
https://mail.python.org/mailman/listinfo/python-es

Responder a