Se le proporciona una función Rand5 (). Esta función devuelve enteros perfectamente aleatorios (distribución igual) entre 1 y 5.
Proporcione la función Rand7 (), que usa Rand5 () para producir enteros perfectamente aleatorios entre 1 y 7.
code-challenge
math
random
Dan McGrath
fuente
fuente
Respuestas:
Java - 61 caracteres
Controlador de prueba para validación:
Resultados
fuente
rand5
. Los calculé en Maple usando álgebra matricial simple, pero puede hacerlo con lápiz y papel en unos minutos si lo desea. De todos modos, resulta que Omar ya publicó las mismas cifras (sin factor de normalización) en un comentario a otra respuesta un par de días antes. (También ps., Solo puede @ notificar a un usuario por comentario, aunque el autor de la publicación siempre se notifica en cualquier caso.)Perl - 47 (antes 52) caracteres
Además, puedo usar el operador ternario Y la recursividad. ¡El mejor día!
OK, 47 caracteres si usas mod en lugar de div:
fuente
&
signos para reducirlo a 46 caracteres (incluido el espacio, que pone su versión actual en 48).JavaScript, 42
Bono ES5 cosa:
fuente
Ruby - 54 caracteres (basado en la solución de Dan McGrath, usando el bucle)
Ruby - 45 caracteres (misma solución, usando recursividad)
fuente
(x=rand5+5*rand5-5)>7?
.En Python:
fuente
En Common Lisp 70 caracteres:
Los paréntesis ocupan más espacio del que quisiera.
fuente
(defun rand7()(setq n(-(+(rand5)(* 5(rand5)))5))(if(> n 7)(rand7)n))
(defun rand7()(if(>(setq n(-(+(rand5)(* 5(rand5)))5))7)(rand7)n))
En c / c ++ usando muestreo de rechazo
62 caracteres.
fuente
while(x>7)
, por lo que solo se cumpliría con números en el rango válido.Traducción a PHP, de la respuesta publicada ny Dan McGrath.
67 caracteres.
fuente
R, 34 caracteres
En R (un lenguaje creado para el cálculo estadístico), una solución deliberadamente engañosa:
Gracias a la evaluación perezosa de los argumentos, eliminé el punto y coma y las llaves.
Salida sobre 10 ^ 6 réplicas:
fuente
Rand7=function(){r=Rand5();sample(7)[r]}
Rand7=function(){sample(7)[Rand5()]}
scala,
47, 4059 caracteres:con 2 entradas de rand5:
Multiplico el primer 1 por 5 y agrego el segundo. La mayoría de los resultados se ignoran y conducen a un nuevo cálculo. El resultado debería ser una distribución equitativa de valores de 1 a 25, de los cuales solo selecciono los primeros 7. Podría aceptar los primeros 21 con la construcción de un módulo, pero esto conduciría a un código más largo.
código histórico que falló, pero no muy obviamente. Gracias a Ilmari Karonen por señalarlo:
Gracias a Yoshiteru Takeshita, por este enfoque scala-2.8.0 que hizo que la 'suma' fuera tan fácil. Mi solución antes:
rand5:
fuente
def rand7=(1 to 7).map(_=>rand5).sum%7+1
C ++
C ++ (109)
Golfed
fuente
Traducción a Javascript, de la respuesta publicada por Dan McGrath.
62 caracteres
fuente
function Rand7(){for(x=8;x>7;x=rand5()+5*rand5()-5);return x}
es un poco más corto: PJavaScript, 85
Sé que hay una respuesta más corta, pero quería mostrar la prueba de este rompecabezas. Resulta que solo la respuesta de Clyde Lobo usando el muestreo de rechazo de Dan McGrath es correcta (entre las respuestas de JS).
fuente
С ++
Distribución de números (1000000 enteros):
El número promedio de llamadas a Rand5 () por cada número entero generado es de aproximadamente 2.2 (2 a 10+).
fuente
En Java (o C / C ++, supongo)
usando la fórmula de generación de Alexandru, en 65 caracteres:
usando la fórmula de generación de Dan McGrath, en 60 caracteres
fuente
Clojure - 58 caracteres
fuente
Python,
5637 caracteresOtra solución que puede estar mal, en Python:
Esto parece ser demasiado simple, pero cuando lo intento:
Obtengo una distribución razonablemente uniforme (todo entre 14000 y 14500).
Bien, ahora que alguien votó por esta publicación: ¿Es esta solución realmente correcta? Más publiqué esto aquí para que la gente lo critique. Bueno, si es correcto, mi versión de golf sería:
que sale a 37 caracteres.
fuente
Java, 65 caracteres:
fuente
Python, 70 caracteres
pero completamente correcto basado en el razonamiento aquí .
fuente
Perl, 43 caracteres, muestreo de rechazo iterativo
Esto da una advertencia
Ambiguous use of -rand5 resolved as -&rand5()
, pero funciona correctamente. Anteponer un&
también a la segundarand5
llamada lo corrige a costa de un golpe. (Por el contrario, el otro&
también se puede eliminar sirand5
se ha definido con un()
prototipo).PD. La siguiente versión de 46 caracteres es aproximadamente tres veces más rápida:
fuente
Java - 66 caracteres
Más tiempo que la rutina anterior, pero creo que este devuelve números distribuidos uniformemente en menos tiempo.
fuente
PostScript (46)
Esto usa codificación de token binario, por lo tanto, aquí hay un hexdump:
Para probarlo, también puedes descargarlo .
Aquí está el código no comentado y comentado, junto con el código de prueba.
fuente
fuente
R (30 caracteres)
Definir rand7:
Debido a que R fue escrito con el análisis estadístico en mente, esta tarea es trivial, y uso la función incorporada
sample
con el reemplazo establecido en TRUE.Salida de muestra:
fuente
Maravilloso
distribución de ejemplo en más de 35,000 iteraciones:
¿Es malo que tenga estado?
fuente
Mathematica, 30
fuente
¿Qué tal esto?
fuente
/
operador matemática entera? ¿Qué sucede con sus resultados si hace matemática decimal, de coma flotante o de enteros?[2/25, 4/25, 5/25, 5/25, 5/25, 3/25, 1/25]
. No exactamente uniforme.Java - 54
Prueba de distribución:
[1000915, 999689, 999169, 998227, 1001653, 1000419, 999928]
Algoritmo:
> Los números ya no están mutuamente no correlacionados, sino individualmente perfectamente al azar.
fuente
Rubí (43 bytes)
La solución de cemper93 portada a Ruby es tres bytes más corta;) (34 bytes)
fuente
Código C / C ++ ¡el código central tiene una sola línea!
El srand7 () es la semilla de rand7, debe llamar a esta función antes que rand7, al igual que call srand antes de rand en C.
Esta es una muy buena, porque llama a rand () solo una vez, y no tiene bucle, no gasta recuerdos adicionales.
Permítame explicarlo: considere una matriz entera con un tamaño de 5:
Entonces obtuvimos la TABLA, cada uno de 1-7 aparece 5 veces en ella y tiene los 35 números, por lo que la probabilidad de cada número es 5/35 = 1/7. Y la próxima vez
Después de suficientes tiempos, podemos obtener la distribución uniforme de 1-7.
Entonces, podemos asignar una matriz para restaurar los cinco elementos de 1-7 por loop-left-shift, y obtener un número de la matriz cada vez por rand5. En cambio, podemos generar las siete matrices antes y usarlas circularmente. El código también es simple, tiene muchos códigos cortos que pueden hacer esto.
Pero podemos usar las propiedades de% operation, por lo que la tabla 1-7 filas es equivalente a (rand5 + i)% 7, es decir: a = rand ()% 5 + 1 es rand5 en lenguaje C, b = gi ++ % 7 genera todas las permutaciones en la tabla anterior, y 0 - 6 reemplaza 1 - 7 c = (a + b)% 7 + 1, genera 1 - 7 de manera uniforme. Finalmente, tenemos este código:
Pero, no podemos obtener 6 y 7 en la primera llamada, por lo que necesitamos una semilla, algunos como srand for rand en C / C ++, para desarmar la permutación para la primera llamada formal.
Aquí está el código completo para probar:
fuente
6
o7
llamándolo una vez ?int main(){if(rand7()==6) printf("Hello, world!");}
, la aproximación usando el bucle imprimirá '¡Hola, mundo!' 1 de cada 7 veces, pero su código no.