La siguiente declaración de impresión imprimiría "hola mundo". ¿Alguien podría explicar esto?
System.out.println(randomString(-229985452) + " " + randomString(-147909649));
Y se randomString()
ve así:
public static String randomString(int i)
{
Random ran = new Random(i);
StringBuilder sb = new StringBuilder();
while (true)
{
int k = ran.nextInt(27);
if (k == 0)
break;
sb.append((char)('`' + k));
}
return sb.toString();
}
n
enfor (int n = 0; ; n++)
. Podrían usarfor(;;)
o en suwhile(true)
lugar!Respuestas:
Cuando
java.util.Random
se construye una instancia de con un parámetro semilla específico (en este caso-229985452
o-147909649
), sigue el algoritmo de generación de números aleatorios que comienza con ese valor semilla.Cada
Random
construido con la misma semilla generará el mismo patrón de números cada vez.fuente
"hello\0"
y"world\0"
. Si asumió un generador verdaderamente aleatorio, las probabilidades serían de 1 en 27 ^ 6 (387,420,489) de obtener la secuencia que estaba buscando, por lo que es bastante impresionante, ¡pero no alucinante!"Hello"
"World"
), o usar en122-k
lugar de96+k
, o ...Las otras respuestas explican por qué, pero aquí es cómo.
Dada una instancia de
Random
:Los primeros 6 números que
r.nextInt(27)
genera son:y los primeros 6 números que
r.nextInt(27)
genera dadoRandom r = new Random(-147909649)
son:Luego solo agregue esos números a la representación entera del carácter
`
(que es 96):fuente
new Random(-229985452).nextInt(27)
siempre devuelve 8.new Random()
no devuelve ningún número en absoluto.Random
no es criptográficamente seguro (estoy bastante seguro de que es un Mersenne Twister, pero no me cite al respecto), probablemente sea posible retroceder desde "Quiero estos números" hasta "este es el semilla que usaría ". He hecho algo similar con el generador congruencial lineal C estándar.Lo dejaré aquí. Quien tenga mucho tiempo (CPU) de sobra, siéntase libre de experimentar :) Además, si ha dominado algo de fork-join-fu para hacer que esto queme todos los núcleos de CPU (solo los hilos son aburridos, ¿verdad?), Comparta tu codigo. Me sería de gran aprecio.
Salida:
fuente
nextInt(27)
significa dentro del rango[0, 26]
.Todos aquí hicieron un gran trabajo al explicar cómo funciona el código y al mostrar cómo puedes construir tus propios ejemplos, pero aquí hay una respuesta teórica de información que muestra por qué podemos esperar razonablemente que exista una solución que la búsqueda de fuerza bruta eventualmente encontrará.
Las 26 letras minúsculas diferentes forman nuestro alfabeto
Σ
. Para permitir generar palabras de diferentes longitudes, agregamos un símbolo terminador⊥
para obtener un alfabeto extendidoΣ' := Σ ∪ {⊥}
.Sea
α
un símbolo y X una variable aleatoria distribuida uniformementeΣ'
. La probabilidad de obtener ese símbolo,P(X = α)
y su contenido de informaciónI(α)
, están dados por:Para una palabra
ω ∈ Σ*
y su⊥-
contraparte terminadaω' := ω · ⊥ ∈ (Σ')*
, tenemosDado que el generador de números pseudoaleatorios (PRNG) se inicializa con una semilla de 32 bits, podemos esperar la mayoría de las palabras de longitud hasta
ser generado por al menos una semilla. Incluso si buscáramos una palabra de 6 caracteres, tendríamos éxito aproximadamente el 41.06% del tiempo. No está nada mal.
Para 7 letras, estamos mirando más cerca del 1,52%, pero no me había dado cuenta antes de intentarlo:
Ver la salida: http://ideone.com/JRGb3l
fuente
I(⍵)
ecuación reordenada.I(⍵)
es 32 (bits) y|⍵|
resulta ser 5 (símbolos).Escribí un programa rápido para encontrar estas semillas:
Lo tengo ejecutándose en segundo plano ahora, pero ya ha encontrado suficientes palabras para un pangrama clásico:
( Demo en ideone. )
PD.
-727295876, -128911, -1611659, -235516779
.fuente
Estaba intrigado por esto, ejecuté este generador de palabras al azar en una lista de palabras del diccionario. Rango: Integer.MIN_VALUE a Integer.MAX_VALUE
Tengo 15131 visitas.
Huellas dactilares
fuente
La mayoría de los generadores de números aleatorios son, de hecho, "pseudoaleatorios". Son generadores congruenciales lineales o LCG ( http://en.wikipedia.org/wiki/Linear_congruential_generator )
Los LCG son bastante predecibles dada una semilla fija. Básicamente, use una semilla que le dé su primera letra, luego escriba una aplicación que continúe generando el siguiente int (char) hasta que toque la siguiente letra en su cadena de destino y escriba cuántas veces tuvo que invocar el LCG. Continúa hasta que hayas generado todas y cada una de las letras.
fuente
/dev/urandom
dispositivo para leer datos aleatorios. Sin embargo, este es un recurso escaso. Por lo tanto, estos datos aleatorios se utilizan normalmente para sembrar PRNG.urandom
que todavía es pseudoaleatorio en.wikipedia.org/wiki//dev/random/dev/random
. El artículo que cité anteriormente dice que el kernel de Linux genera entropía a partir de los tiempos del teclado, los movimientos del mouse y los tiempos IDE y hace que los datos de caracteres aleatorios estén disponibles para otros procesos del sistema operativo a través de los archivos especiales / dev / random y / dev / urandom. Eso me deja creer que es realmente al azar. Puede ser que eso no sea completamente correcto. Pero/dev/random
al menos contiene algo de entropía.Como el subprocesamiento múltiple es muy fácil con Java, aquí hay una variante que busca una semilla utilizando todos los núcleos disponibles: http://ideone.com/ROhmTA
fuente
L
y cambiar el tipo de argumento along
, es decirrandomString(long i)
, para jugar. :)Aleatorio siempre devuelve la misma secuencia. Se utiliza para barajar matrices y otras operaciones como permutaciones.
Para obtener diferentes secuencias, es necesario inicializar la secuencia en alguna posición, llamada "semilla".
RandomSting obtiene el número aleatorio en la posición i (seed = -229985452) de la secuencia "aleatoria". Luego usa el código ASCII para los siguientes 27 caracteres en la secuencia después de la posición inicial hasta que este valor sea igual a 0. Esto devuelve el "hola". La misma operación se realiza para "mundo".
Creo que el código no funcionó para otras palabras. El tipo que programó que conoce muy bien la secuencia aleatoria.
¡Es un código geek muy bueno!
fuente
El principal es la clase aleatoria construida con la misma semilla que generará el mismo patrón de números cada vez.
fuente
Derivado de la respuesta de Denis Tulskiy , este método genera la semilla.
fuente
Desde los documentos de Java, esta es una característica intencional cuando se especifica un valor de inicialización para la clase Random.
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Random.html
Aunque extraño, pensaría que hay problemas de seguridad implícitos al tener números 'aleatorios' predecibles.
fuente
Random
"establece la semilla del generador de números aleatorios en un valor muy probable que sea distinto de cualquier otra invocación de este constructor" ( javadoc ). En la implementación actual, esta es una combinación de la hora actual y un contador.Se trata de "semilla". Las mismas semillas dan el mismo resultado.
fuente
Aquí hay una pequeña mejora para la respuesta de Denis Tulskiy . Reduce el tiempo a la mitad
fuente
Salida
fuente