Inspirado por Random con las manos atadas :
La meta
El objetivo de este desafío es escribir un programa que genere una secuencia de bits pseudoaleatoria, que es una cadena de 1s y 0s que parece ser puramente aleatoria, pero que en realidad se genera de manera determinista. Su programa debe generar una cadena de 1 y 0 (con espacios en blanco opcionales) y debe cumplir los siguientes requisitos:
- Con tiempo y memoria ilimitados, su programa debe continuar produciendo una cadena de 1s y 0s para siempre
- Su programa debe generar más de 1000 bits aleatorios en aproximadamente un minuto, en una máquina razonable. Si este requisito es imposible, lo disminuiré.
- La cadena de bits puede repetirse, pero la longitud de la sección de repetición debe ser superior a 1000 bits.
- La cadena de bits debe pasar tantas pruebas de aleatoriedad (descritas a continuación) como sea posible.
- El programa no debe tomar ninguna entrada de ninguna fuente externa ni utilizar ninguna función incorporada de tipo rand ().
- Debido al requisito anterior, el programa debe generar la misma cadena de bits exacta cada vez que se ejecuta.
Prueba de aleatoriedad # 1
La cadena de bits pseudoaleatorios no debe incluir ningún patrón obvio en la inspección visual.
Prueba de aleatoriedad n. ° 2 (sujeta a cambios según los comentarios)
La cadena de bits debe contener una distribución igual de 1s y 0s. Para probar esto (y otras cosas también), el flujo de bits se divide en segmentos de 3 bits de longitud, como 101|111|001
.
De todos estos segmentos, 1/8 de ellos deben tener tres 1s y no 0s, 3/8 de ellos deben tener dos 1s y uno 0, 3/8 de ellos deben tener un 1 y dos 0s, y 1/8 de ellos no deberían tener 1s y tres 0s.
Prueba de aleatoriedad # 3
Una "ejecución" se define como una serie consecutiva de bits que tienen el mismo valor. La cadena 1001001110
tiene tres ejecuciones de tamaño 1 ( 1..1.....0
), dos ejecuciones de tamaño 2 ( .00.00....
) y una ejecución de tamaño 3 ( ......111.
). Tenga en cuenta que las ejecuciones no se superponen.
De una cadena de 1000 bits aleatorios, debe haber aproximadamente 250 ejecuciones de tamaño 1, 125 ejecuciones de tamaño 2, 62 ejecuciones de tamaño 3, etc. En general, para 1000/(2**(R+1))
ejecuciones de tamaño R, debería haber aproximadamente ejecuciones de ese tamaño.
Prueba de aleatoriedad # 4
Los primeros 840 bits se dividen en dos mitades de 420 bits cada una. Cada bit en la primera mitad se compara con el bit correspondiente en la segunda mitad. Los dos bits deben coincidir aproximadamente el cincuenta por ciento del tiempo.
Aquí está el código fuente de un programa Perl que realiza las pruebas 2 a 4. A partir de ahora, requiere que la cadena de bits no contenga ningún espacio en blanco.
Objetivo Criterio ganador ¡Tiempo!
El ganador es el programa que pasa los 6 requisitos y todas las pruebas de aleatoriedad en la medida en que no se puede distinguir de la aleatoriedad. Si varios programas logran esto, entonces ganará el que demore más tiempo en repetirse. Si varios programas logran esto, entonces podría tener que encontrar más pruebas de aleatoriedad para actuar como desempate.
fuente
Respuestas:
C, 61
Sí, sé que no es código golf. Obviamente, esto es más bien una anti-solución ... pero cumple con sus criterios.
La duración del período es de 2²⁹.
fuente
Mathematica
7853 caracteresLos dígitos de la representación binaria de Pi parecen comportarse como si fueran producidos caóticamente, aunque esto no está probado.
La siguiente rutina simple devuelve determinísticamente como una cadena los dígitos binarios de pi, correspondientes a
d
dígitos decimales:Uso
Si solicitamos la contrapartida de 301 dígitos decimales de Pi, recibimos 1000 dígitos binarios.
Como Pi es un número irracional, no hay punto. Sin embargo, habrá restricciones prácticas debido al hardware que se está ejecutando.
Prueba 1 Me parece bien.
Prueba 2
Verificación más exhaustiva:
Prueba 3: carreras
Ejecuté una gran cantidad de casos para verificar sistemáticamente la distribución de las corridas. En aproximadamente 3 millones de dígitos binarios, hubo 830k corridas de 1, 416k corridas de 2, 208k corridas de 3, 104k corridas de 4, etc.
Prueba 4: coincidencia de la primera y segunda mitad de los datos
Los partidos son los 212 casos de 0 y 2; los desajustes son los 208 casos donde la suma de los dígitos respectivos es 1.
Sincronización
Se tarda menos de dos segundos en calcular 3321928 dígitos binarios (correspondientes a 10 ^ 6 dígitos decimales).
fuente
e
lugar depi
guardar un byte?e
distribuye caóticamente?Python, 90
g
es el valor de la semilla El muestreo aleatorio exhibe una distribución notablemente normal. El muestreo aleatorio repetido de las medias muestrales arrojó una media0.506
y una desviación estándar de.0473
(tamaño de muestra de 1000). Desafortunadamente, la aleatoriedad es altamente sensible a la semilla inicial. La semilla en el código anterior me dio la mejor aleatoriedad: pACTUALIZAR
Veamos cómo este código resiste las pruebas del OP:
Prueba n. ° 1
Este es un poco subjetivo ... pero me parece bastante irregular.
Prueba n. ° 2
Prueba n. ° 3
Se ejecuta por tamaño:
Prueba n. ° 4
fuente
Haskell
7458Gracias a shiona por la simplificación. Resultados:
Este también es un terrible generador pseudoaleatorio (similar al utilizado por von-Neuman). Para aquellos que no estaban al tanto
concatMap == (=<<) == flip . (>>=)
(para listas)fuente
\x->if odd x then"1"else"0"
conshow.(`mod`2)
.La pregunta es esencialmente equivalente a "implementar un cifrado de flujo". Así que implemento RC4, ya que es relativamente simple.
No uso ninguna clave y dejo caer los primeros 100000 bits, porque el comienzo de RC4 está un poco sesgado, especialmente porque omití la programación de claves. Pero espero que pase tu prueba incluso sin eso (ahorrando 20 caracteres de código).
Normalmente, se generaría un byte completo por ciclo, pero la conversión a binario es bastante fea en C #, por lo que simplemente descarto todo excepto el bit menos significativo.
O sin espacios:
C #, 156 caracteres, funciona en el modo de declaración de LinqPad. Para un programa completo de C #, agregue la repetitiva habitual.
También podríamos usar cripto primitivas integradas (solución Cheater):
(C #, 99 caracteres, funciona en el modo de declaración de LinqPad. Para el compilador normal de C # necesitará agregar un poco de repetitivo)
La salida de las funciones criptográficas de hash está diseñada para ser indistinguible de los datos aleatorios, por lo que espero que pase todas las pruebas de aleatoriedad (morir más duro ...), pero soy demasiado vago para probar.
fuente
C, 52 caracteres
Este es un LFSR de 10 bits, resultados de la prueba:
fuente
a
debería comenzar como 1, (suponiendo que se llame sin argumentos). También podría pegara=
en el medio, algo así comoa=a/2^-!putchar(49-a%2)%576
(tomarse algunas libertades con el algoritmo)a
, la cambié por "The program must not take any input from any external sources
"Sabio / Python
Este programa imprime los dígitos binarios más a la derecha que son comunes a todas las torres de exponenciación suficientemente altas de forma 3 3 3 3 . . . Por todo lo que podría generarse de manera factible, estos son los dígitos binarios más a la derecha del número de Graham . La secuencia de dígitos es infinita y no es periódica.
Para 1000 dígitos, esto tomó menos de 2 segundos; sin embargo, el tiempo aumentará mucho más rápido que linealmente en el número de dígitos.
Los resultados de la prueba usando el programa OP son
(Consulte ¿Son aleatorios los dígitos más a la derecha de G? Para más de 32000 dígitos y pruebas estadísticas adicionales).
fuente
Java,
371317Basado en un LFSR de 128 bits (las derivaciones de bits provienen de la nota 52 de la aplicación xilinx )
EDITAR: no estaba satisfecho con el uso de BigInteger, por lo que esta versión no. Guardado algunos personajes. La producción puede ser un poco menos aleatoria ya que no podría pensar en un buen método de 'siembra'.
Nuevo Código: Argumentos: BITS_TO_PRINT
Versión antigua: Argumentos: SEED, BITS_TO_PRINT
Nueva versión: Ejemplo de salida, bits = 100:
fuente
JavaScript: 1ms a 2ms para 1000 bits pseudoaleatorios (139ms a 153ms para 100000 bits)
Esta solución utiliza el hecho de que las raíces cuadradas son irracionales y, por lo tanto, bastante aleatorias. Básicamente, toma la raíz cuadrada de 2 para comenzar, la convierte en binaria, tira la parte principal que coincide con la raíz anterior, la agrega a la cadena aleatoria, se repite con el siguiente número más alto (o vuelve a 2 si el número se repite) y tenía al menos 30 bits de longitud), y devuelve la cadena aleatoria una vez que es lo suficientemente larga.
Todavía no lo he pasado por las pruebas, pero imagino que les irá bien. Aquí hay un violín para que puedas verlo en acción. Para mis tiempos, simplemente ejecuté el programa varias veces y tomé los valores más rápidos y más lentos como rangos.
fuente
Pitón
Debería tener un período de aproximadamente 2 ^ 512.
fuente
perl, 44 bytes
Sé que esto no es golf de código, pero siempre he sido fanático de tomar los bits de orden inferior de una función cuadrática simple, por ejemplo:
El período es más largo que 3 mil millones, pero me he quedado sin espacio en disco para calcular más.
fuente
$x=1/7;print substr($x*=4-4*$x,9,1)%2while 1