Sea una lista que contenga las 26 letras del alfabeto de la A a la Z. Mezclamos la lista con el algoritmo de Fisher-Yates (ver https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle ). Nos interesa la primera letra de la tabla:
Aquí está el código que usé:
"use strict"; // mix const mix = array => { const { length: n } = array; for (let i = 0; i < n; i++) { const x = Math.floor(Math.random() * n); [array[i], array[x]] = [array[x], array[i]]; } return array; }; const A = 'A'.charCodeAt(0); const NB_LETTERS = 26; const TABLE = {}; for (let i = 0; i < NB_LETTERS; i++) TABLE[String.fromCharCode(A + i)] = 0; for (let N = 1; ; N++) { // init const array = []; for (let i = 0; i < NB_LETTERS; i++) array[i] = String.fromCharCode(A + i); mix(array); TABLE[array[0]]++; if (N % 1000000 === 0) { console.log(''); console.log("N =", N); console.log( Object.entries(TABLE) .map(([letter, n]) => { const freq = n / N; return letter + '\t' + freq.toString().replace('.', ','); }) .join('\n') ); } }Preguntas:
Math.random() ? Yo creo que sí... ¿conoces alguna alternativa que daría una distribución uniforme?Gracias por adelantado !
El algoritmo de reproducción aleatoria en la mix de funciones no está implementado correctamente.
El algoritmo en el artículo de Wikipedia al que se hace referencia estipula que el rango para tomar un número aleatorio debe ser diferente en cada iteración, lo que no es el caso en su implementación, por lo tanto, la distribución no homogénea.
Haz esta corrección:
const x = i + Math.floor(Math.random() * (n - i));Se pueden encontrar otras implementaciones (con algunas optimizaciones) en How to randomize (shuffle) a JavaScript array?