Per creare un casuale, imparziale shuffle, si applica il Fisher-Yates algoritmo . Se vuoi mescolare un array x di elementi n (numerati da 0 a n -1), fai questo:
for all i from 0 to n-1
let j = rnd(n - i) + i
swap x[i] with x[j]
dove rnd (k) significa: genera un valore uniforme casuale nell'intervallo da 0 a k -1. Si noti che può succedere che i = j nel ciclo sopra, il che significa che è possibile scambiare un elemento di matrice con se stesso. Questo è normale e necessario per una corretta selezione uniforme di una permutazione.
Il tuo problema, quindi, è come convertire un flusso di parole casuali in selezioni casuali in un intervallo più piccolo. sjcl.prng.randomWords()
restituisce un array di parole a 32 bit, cioè valori nell'intervallo da 0 a 2 32 -1. Se dividi semplicemente un valore di una parola per k e mantieni il resto, la tua selezione sarà distorta. Il trucco è quello di rifiutare parte dell'intervallo, in modo che la funzione rnd () assomigli a questa:
rnd(k):
while true
let z = next-random-word
let r = z mod k
if z - r + k <= 2^32
return r
Ad esempio, se k = 37 (vuoi un intero imparziale casuale nell'intervallo da 0 a 36), generi un z casuale. Se quel valore z rientra nell'intervallo compreso tra 0 e 4294967288, allora riduci il valore modulo 37 e hai il numero intero casuale; questo è corretto perché 4294967289 è un multiplo di 37. Tuttavia, se z rientra nell'intervallo da 4294967289 a 4294967295, devi provare di nuovo con un altro z .
(Matematicamente parlando, una sorta di loop è inevitabile quando k non divide 2 32 . I rischi del looping molte volte sono trascurabili, però.)
Non so esattamente per cosa ti serve la tua mescolanza; se questo è per generare una "password", quindi fare uno shuffle di caratteri stampabili da 33 a 126 (i caratteri stampabili ASCII, escluso lo spazio, quindi 94 valori) è strano, perché non esiste una legge contro l'utilizzo dello stesso carattere due volte in una password . Infatti, impedire con la forza che lo stesso personaggio venga visualizzato due volte in una password riduce lo spazio delle possibili password, e quindi riduce la sicurezza . Per generare una password casuale, è più semplice e anche meglio produrre ogni personaggio in modo casuale e indipendentemente dagli altri; manipolare le permutazioni e mescolare è solo una complessità inutile (e la complessità è, in generale, dannosa per la sicurezza da sola).