Para hacer aleatorio, imparcial , debes aplicar Fisher-Yates algoritmo . Si desea barajar una matriz x de n elementos (numerados de 0 a n -1), haga esto:
for all i from 0 to n-1
let j = rnd(n - i) + i
swap x[i] with x[j]
donde rnd (k) significa: generar un valor aleatorio uniforme en el rango de 0 a k -1. Tenga en cuenta que puede suceder que i = j en el bucle anterior, lo que significa que puede intercambiar un elemento de matriz consigo mismo. Esto es normal y es necesario para la selección uniforme adecuada de una permutación.
Su problema, entonces, es cómo convertir un flujo de palabras aleatorias en selecciones aleatorias en un rango más pequeño. sjcl.prng.randomWords()
devuelve una matriz de palabras de 32 bits, es decir, valores en el rango de 0 a 2 32 -1. Si simplemente divide un valor de palabra por k y mantiene el resto, entonces su selección está sesgada. El truco es rechazar parte del rango, para que la función rnd () tenga este aspecto:
rnd(k):
while true
let z = next-random-word
let r = z mod k
if z - r + k <= 2^32
return r
Por ejemplo, si k = 37 (desea un entero imparcial aleatorio en el rango de 0 a 36), genera un z aleatorio. Si ese valor z cae en el rango de 0 a 4294967288, entonces solo reduce el valor módulo 37, y tiene su número entero aleatorio; esto es imparcial porque 4294967289 es un múltiplo de 37. Sin embargo, si z cae en el rango 4294967289 a 4294967295, debe intentarlo de nuevo con otro z .
(Hablando matemáticamente, algún tipo de bucle es inevitable cuando k no divide 2 32 . Sin embargo, los riesgos de realizar un bucle muchas veces son insignificantes.)
No sé exactamente para qué necesitas tu shuffle; si eso es para generar una "contraseña", entonces hacer una combinación de caracteres imprimibles de 33 a 126 (los caracteres imprimibles ASCII, excluyendo el espacio, por lo tanto, los valores de 94) es extraño, porque no hay ninguna ley en contra de usar el mismo carácter dos veces en una contraseña . De hecho, evitar a la fuerza que el mismo carácter aparezca dos veces en una contraseña reduce el espacio de las posibles contraseñas y, por lo tanto, reduce la seguridad. Para generar una contraseña aleatoria, es más simple y mejor producir cada carácter de forma aleatoria e independiente de los demás; juguetear con permutaciones y barajar es simplemente una complejidad innecesaria (y se sabe que la complejidad es, en general, perjudicial para la seguridad en sí misma).