[Python-es] ¿Cómo generar una distribución aleatoria?
Chema Cortes
pych3m4 en gmail.com
Mie Jul 3 07:58:05 EDT 2019
El mié., 3 jul. 2019 a las 4:09, lasizoillo (<lasizoillo en gmail.com>)
escribió:
> Buenas,
>
> Lo primero sería acotar cual es realmente el problema. En una entrevista
> de trabajo alguien tiene que desentrañar si eres apto o no para un puesto y
> esa aptitud puede tener varias facetas:
> - Eres capaz de poner en duda los requisitos y plantear alternativas
> mejores para la empresa
> - Eres capaz de resolver problemas lógicos
> - Ante un problema que muy posiblemente no sabes por dónde cogerlo...
> ¿cómo vas a reaccionar? te enfadarás, tratarás de colar una solución
> erronea, asumirás que no sabes hacer eso pero plantearás estrategias para
> atacar el problema, ...
>
> Así que lo primero negociaría si realmente no se puede simplificar el
> enunciado porque lo que realmente se quiere evaluar el conocimiento técnico
> o recursos para atacar este problema. Si les vale ser capaz de poner en
> duda requisitos peregrinos eso que me ahorraría. Si quiere una solución
> técnica pasaría a atacar el problema, reconociendo que no sé la solución a
> priori, y pensaría en voz alta algunas cosas evidentes:
> - Una sola llamada a la función randint(1,5) no tiene información
> suficiente para hacer el equivalente a randint(1,7)
> - No puedo sumar 7 "tiradas" de randint(1,5) y dividir entre 5 porque la
> distribución no sería plana.
> - Al no ser una potencia de dos no puedo convertir a binario la función
> randint(1,5) y codificar los bits del número. Ejemplo 1 y 3 es un 0, 2 y 4
> es un 1 y 5 vuelvo a calcular. 2^3=8, por lo que tres bits de tiradas
> binarias me darían números del 0 al 7, no del 1 al 7.
>
Te dejas el caso de que no sea resoluble, a pesar de tener un enunciado tan
sencillo.
Lo primero que podemos pensar es que necesitamos 7 tiradas de [1,5] para
tener 5 tiradas de [1,7].
Representamos este cambio de dominios por una matriz 7 x 5. Todos los
elementos están a cero, excepto un elemento de cada fila que asignamos
aleatoriamente a 1. Por ejemplo:
[[0, 0, 0, 0, 1],
[0, 0, 0, 0, 1],
[0, 0, 0, 0, 1],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 1],
[1, 0, 0, 0, 0],
[0, 0, 1, 0, 0]]
Es imposible asegurar que en cada columna haya un único elemento a 1.
Alguna columna puede tener todos sus elementos a cero y, al menos, habrá
alguna columna que tendrá más de un 1 seguro.
Por tener una imagen del problema: es como tirar un dado y que algunas
veces no sale nada, y en otras salen dos números o más.
>
> Ahora diría en alto lo que me parece una solución válida que me ha venido
> a la cabeza: lo mismo que con la función randint(1,5) desechaba cuando
> salía 5 para simular tiradas de cara o cruz, puedo eliminar cuando el
> resultado de calcular 3 bits me da un número que equivale a 0. Pensaría si
> cumple con las restricciones del enunciado (creo que si) y pasaría a una
> implementación rápida.
>
> def rand_0_1() -> int:
> while True:
> num = randint(1, 5)
> if num==5:
> continue
> return num % 2
>
> def randint_1_7() -> int:
> while True:
> num = rand_0_1() * 4 + rand_0_1() * 2 + rand_0_1()
> if num:
> return num
>
El truco está en que quitar un elemento de una distribución uniforme deja
una distribución uniforme de los elementos que quedan.
En tu caso, a randint(1,5) le quitas el 5, lo que equivale a randint(1,4),
y lo usas para construir un randint(0,1) . Por otro lado, implementas un
randint(0,7) al que le quitas el cero, lo que equivale a randint(1,7), que
es lo que se buscaba.
Un efecto añadido es que no se sabe cuántas llamadas son necesarias hacer a
randint(1,5) para obtener un elemento de randint(1,7). Cómo poco haces 3
llamadas. El ideal sería hacer 1.4 llamadas por resultado obtenido (1.4 ==
7/5). El nuevo reto podría ser ahora minimizar el número de llamadas
necesarias.
>
> Le comentaría que lo suyo sería hacer una función de test para quedarme
> tranquilo con que el resultado es correcto y poder refactorizar en el
> futuro si se me ocurre una solución mejor. Escucharía si quiere dejarlo
> aquí o si quiere ver la función que haga el test (que no es trivial, pero
> tampoco demasiado complicada). Pero la función de test ya se escapa a tu
> propuesta ;-)
>
> Un saludo,
>
> Javi
>
>
> El mié., 3 jul. 2019 a las 1:50, Jose Caballero (<jcaballero.hep en gmail.com>)
> escribió:
>
>> Hola,
>>
>> a un colega le han preguntado durante una entrevista de trabajo lo
>> siguiente:
>> ¿cómo generar una distribución plana de enteros aleatorios, del 1 al 7,
>> usando únicamente random.randint(1,5)?
>> O sea, sin usar ninguna otra función que genere números aleatorios.
>>
>> Y he pensado en proponer el reto aquí, a ver lo que los miembros de la
>> lista sugieren.
>>
>> Un saludo,
>> Jose
>> _______________________________________________
>> Python-es mailing list
>> Python-es en python.org
>> https://mail.python.org/mailman/listinfo/python-es
>>
> _______________________________________________
> Python-es mailing list
> Python-es en python.org
> https://mail.python.org/mailman/listinfo/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/>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20190703/7b8eb0b7/attachment.html>
Más información sobre la lista de distribución Python-es