> pick | shuffle | pair <

// Pega una lista, elige ganadores, baraja el orden o forma grupos con personas - todo en tu navegador

[PICK_N]

Elegir N elementos al azar

Extrae cualquier número de ganadores de tu lista. Sin reemplazo para ganadores únicos, o con reemplazo para sorteos de estilo ponderado.

[SHUFFLE]

Barajado Fisher-Yates sin sesgo

Reordena toda la lista con el clásico barajado de Knuth. Cada permutación es igual de probable - sin trucos de ordenación ingenuos aquí.

[PAIRS]

Formar grupos

Divide una lista en parejas, tríos o cualquier tamaño de grupo. Perfecto para trabajo en pareja, rotaciones de revisión de código o amigos invisibles.

[SEEDED]

Reproducibilidad con semilla

Proporciona una cadena de semilla para obtener un sorteo determinista. La misma semilla más la misma lista siempre produce el mismo resultado - compartible y verificable.

// ACERCA DEL SELECTOR ALEATORIO

Cómo funciona:

Esta herramienta usa el barajado de Fisher-Yates (también conocido como Knuth): recorre el arreglo desde el último índice hasta el primero y, en cada paso, intercambia el elemento actual con uno en un índice anterior elegido de forma uniformemente aleatoria. Esto produce una permutación uniforme sin sesgo en tiempo O(n). El truco ingenuo array.sort(() => Math.random() - 0.5) tiene sesgo porque los comparadores de ordenación de JavaScript deben ser transitivos - los comparadores aleatorios lo violan y distorsionan la distribución. Para sorteos sin semilla obtenemos entropía de window.crypto.getRandomValues. Cuando proporcionas una cadena de semilla, la convertimos con cyrb53 en un entero de 53 bits y luego alimentamos un PRNG mulberry32 para que semillas idénticas produzcan resultados idénticos y reproducibles.

Algoritmo:

for i = n-1 down to 1: j = randInt(0, i); swap(a[i], a[j]) - unbiased Fisher-Yates

Estándares y referencias:

  • >Web Crypto API (W3C) - crypto.getRandomValues para aleatoriedad criptográficamente fuerte
  • >Barajado de Fisher-Yates (1938), popularizado por Donald Knuth en The Art of Computer Programming Vol. 2
  • >mulberry32 - PRNG con semilla pequeño, rápido y bien distribuido de Tommy Ettinger
  • >cyrb53 - hash de cadena de 53 bits de bryc, usado para convertir una cadena de semilla en un estado numérico de PRNG

Casos de uso comunes:

  • >Sorteos, rifas y elección de un ganador al azar entre las participaciones
  • >Sorteos de nombres en el aula y selección de alumnos para preguntas espontáneas
  • >Emparejamiento de equipos deportivos, entrenamientos en pareja y cuadros de torneo
  • >Asignación de revisores de código en un equipo de ingeniería
  • >Selección de muestras para pruebas A/B y cohortes de encuesta aleatorizadas
  • >Parejas de amigo invisible, intercambios de regalos y compañeros de almuerzo del equipo
  • >Entradas de prueba aleatorias y semillas de fuzzing para QA
  • >Toma de decisiones en grupo y desempates
  • >Selección de jurado simulado y paneles de entrevista aleatorizados
  • >Sorteos de tipo lotería para eventos comunitarios y premios

Herramientas relacionadas:

  • >Generador de números aleatorios — el complemento basado en texto: elige números en un rango con las mismas primitivas de reproducibilidad con semilla
  • >Generador de UUID — identificadores v4 aleatorios cuando necesitas un ID opaco único en lugar de un ganador de una lista
  • >Generador de contraseñas — cadenas criptográficamente aleatorias con control del conjunto de caracteres para tokens y credenciales
  • >randompickerwheel.app — interfaz de ruleta complementaria a este selector de texto, perfecta para sorteos ante público en vivo, llamadas en el aula y revelaciones en pantalla

// EJEMPLOS DE SELECCIÓN

Sorteo — elegir 3 ganadores de 50 participaciones

> input:

alice@x.com
bob@x.com
carlos@x.com
…(50 líneas en total)

> config:

Modo=Pick N, Cantidad=3, Permitir duplicados=off, Semilla=(vacía)

> output:

1. carlos@x.com
2. priya@x.com
3. wei@x.com

Barajar una lista de 10 nombres para un orden de presentación

> input:

Alice
Bob
Charlie
Dana
Evelyn
Farouk
Gabriela
Hiroshi
Isabella
Jamal

> config:

Modo=Shuffle, Semilla=(vacía)

> output:

1. Hiroshi
2. Alice
3. Farouk
4. Jamal
5. Dana
6. Evelyn
7. Bob
8. Isabella
9. Gabriela
10. Charlie

Formar grupos de 2 con una clase de 12 estudiantes

> input:

S01
S02
S03
S04
S05
S06
S07
S08
S09
S10
S11
S12

> config:

Modo=Pair Up, Tamaño de grupo=2, Semilla=class-2026-05-02

> output:

Grupo 1: S07, S02
Grupo 2: S11, S04
Grupo 3: S09, S12
Grupo 4: S01, S06
Grupo 5: S03, S10
Grupo 6: S08, S05

Sorteo reproducible con semilla — ejecuta dos veces con la misma semilla, obtén los mismos ganadores

> input:

alpha
bravo
charlie
delta
echo
foxtrot
golf
hotel

> config:

Modo=Pick N, Cantidad=2, Semilla=launch-day, Permitir duplicados=off

> output:

Ejecución 1: 1. echo
             2. bravo
Ejecución 2: 1. echo
             2. bravo  (idéntico — con semilla)

// POR QUÉ EL .SORT() INGENUO TIENE SESGO

Un barajado de una línea común es arr.sort(() => Math.random() - 0.5). Parece elegante, cabe en una línea y se siente aleatorio — pero la distribución de permutaciones resultante dista mucho de ser uniforme. La especificación ECMAScript exige que las funciones comparadoras sean deterministas y transitivas: si a < b y b < c, entonces a < c. Un comparador de cara o cruz viola ese contrato, y la implementación de ordenación del motor visita los pares de comparación en un patrón no uniforme.

V8 (Chrome, Node) usa Timsort; los motores más antiguos usaban quicksort o mergesort. Cada implementación visita un subconjunto distinto de pares de comparación y reutiliza las comparaciones en caché de distintas maneras. Como demostró empíricamente Mike Bostock (bost.ocks.org/mike/shuffle/compare.html), la ordenación ingenua produce salidas fuertemente sesgadas donde algunas permutaciones aparecen varias veces más a menudo que otras — inaceptable para un sorteo, un bucket A/B o cualquier extracción que deba ser justa.

El algoritmo correcto es Fisher-Yates (barajado de Knuth): recorre el arreglo desde el último índice hasta el primero y, en cada paso, intercambia el elemento actual con uno elegido uniformemente al azar entre los índices 0..i. Se ejecuta en O(n), usa O(1) de espacio adicional y produce demostrablemente cada permutación con igual probabilidad.

// BAD: NOT uniformly random
const shuffled = arr.sort(() => Math.random() - 0.5);

// GOOD: Fisher-Yates (Knuth) shuffle
function shuffle(arr) {
  const a = arr.slice();
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

// IMPLEMÉNTALO TÚ MISMO

¿Quieres crear tu propio selector o auditar el nuestro? Estas son las primitivas exactas que usa esta página — pequeñas, sin dependencias e idénticas a lo que se ejecuta en tu navegador cuando haces clic en PICK. Cópialas directamente en un script de Node u otra app web.

// Fisher-Yates shuffle (uniform, O(n))

function shuffle(arr, rng = Math.random) {
  const a = arr.slice();
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(rng() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

// Pick N without replacement (shuffle then slice)

function pickN(arr, n, rng = Math.random) {
  if (n > arr.length) {
    throw new Error('n exceeds list size');
  }
  return shuffle(arr, rng).slice(0, n);
}

// mulberry32 seeded PRNG + cyrb53 string hash

// cyrb53: turn a seed string into a 53-bit integer
function cyrb53(str, seed = 0) {
  let h1 = 0xdeadbeef ^ seed;
  let h2 = 0x41c6ce57 ^ seed;
  for (let i = 0, ch; i < str.length; i++) {
    ch = str.charCodeAt(i);
    h1 = Math.imul(h1 ^ ch, 2654435761);
    h2 = Math.imul(h2 ^ ch, 1597334677);
  }
  h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^
       Math.imul(h2 ^ (h2 >>> 13), 3266489909);
  h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^
       Math.imul(h1 ^ (h1 >>> 13), 3266489909);
  return 4294967296 * (2097151 & h2) + (h1 >>> 0);
}

// mulberry32: tiny seeded PRNG -> [0, 1)
function mulberry32(a) {
  return function () {
    a |= 0; a = (a + 0x6D2B79F5) | 0;
    let t = a;
    t = Math.imul(t ^ (t >>> 15), t | 1);
    t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

// Build a seeded picker:
const h = cyrb53('my-seed', 1);
const state = (h ^ Math.floor(h / 4294967296)) >>> 0;
const rng = mulberry32(state);
const winners = pickN(['alice', 'bob', 'carlos'], 2, rng);

>> preguntas frecuentes

P: ¿Cómo se genera la aleatoriedad?

R: Cuando no se proporciona semilla, usamos window.crypto.getRandomValues, el generador de números aleatorios criptográficamente seguro del navegador respaldado por la Web Crypto API. Es la misma fuente de entropía que se usa para claves y tokens criptográficos, así que es más que robusta para rifas y barajados. Cuando proporcionas una semilla, derivamos de forma determinista un estado de 53 bits mediante el hash de cadena cyrb53 y lo introducimos en un PRNG mulberry32 para que el sorteo sea reproducible.

P: ¿Puedo obtener el mismo resultado dos veces usando una semilla?

R: Sí. Escribe cualquier cadena en el campo SEMILLA - una fecha, el nombre de un concurso, un hash, lo que sea. La misma semilla combinada con la misma lista de entrada y el mismo modo siempre producirá exactamente la misma salida. Esto es invaluable para sorteos transparentes en los que quieres publicar la semilla por adelantado y dejar que los participantes verifiquen el sorteo, o para rotaciones de ingeniería que deban ser reproducibles entre máquinas.

P: ¿Cuál es la diferencia entre Pick N y Shuffle?

R: Pick N selecciona un subconjunto de tamaño N de tu lista, opcionalmente con reemplazo (se permiten duplicados). Shuffle devuelve toda la lista reordenada - no se descarta ni se repite ningún elemento, solo se reorganiza. Usa Pick N cuando solo quieres unos pocos ganadores de muchas participaciones; usa Shuffle cuando cada elemento debe seguir participando pero en un nuevo orden aleatorio, como una cola de presentación o una lista de reproducción.

P: ¿array.sort(() => Math.random() - 0.5) es realmente aleatorio?

R: No, tiene sesgo. La especificación ECMAScript exige que los comparadores de ordenación sean deterministas y transitivos (si a < b y b < c entonces a < c). Un comparador aleatorio viola ese contrato, y distintos motores de JavaScript ejecutan diferentes algoritmos de ordenación subyacentes (TimSort, mergesort, quicksort) que interactúan con el comparador aleatorio de maneras distintas. El resultado es una distribución no uniforme donde algunas permutaciones aparecen mucho más a menudo que otras. Fisher-Yates es el algoritmo correcto.

P: ¿Puedo emparejar una lista con un número impar de elementos?

R: Sí. El modo Pair Up baraja tu lista con Fisher-Yates y luego la divide según el tamaño de grupo que elijas. Si el total no se divide de manera exacta, el último grupo será más pequeño y se etiqueta claramente como grupo sobrante en la salida. Para una lista impar puedes aceptar una entrada en solitario, aumentar el tamaño del grupo o añadir un nombre de relleno como "bye" antes de sortear.

P: ¿Se sube mi lista a algún sitio?

R: No. Esta herramienta es 100 % del lado del cliente - tu lista, tu semilla y la salida nunca salen de tu navegador. No hay llamadas al servidor, ni registros, ni analítica sobre la entrada. Puedes desconectarte de internet después de cargar la página y cada botón sigue funcionando. Recarga la página y los datos desaparecen para siempre.

P: ¿Existe una versión visual con ruleta de esta herramienta?

R: Para una experiencia interactiva de ruleta de nombres con animación, efectos de sonido y una gran revelación visual, consulta randompickerwheel.app. Es un producto complementario centrado en sorteos ante público en vivo y compartir pantalla. Esta página es un selector centrado en el texto, enfocado en listas masivas, sorteos reproducibles con semilla, exportación CSV y emparejamiento - útil cuando necesitas una respuesta determinista rápida en lugar de una presentación.

// OTHER LANGUAGES