> pick | shuffle | pair <

// Incolla un elenco, estrai i vincitori, mescola l'ordine o dividi le persone in gruppi - tutto nel tuo browser

[PICK_N]

Estrai N elementi a caso

Estrai un numero qualsiasi di vincitori dal tuo elenco. Senza reinserimento per vincitori unici, oppure con reinserimento per estrazioni in stile ponderato.

[SHUFFLE]

Mescolamento Fisher-Yates senza distorsioni

Riordina l'intero elenco con il classico mescolamento di Knuth. Ogni permutazione è equiprobabile - nessun trucco di ordinamento ingenuo qui.

[PAIRS]

Dividi in gruppi

Suddividi un elenco in coppie, trii o qualsiasi dimensione di gruppo. Perfetto per il lavoro in coppia, le rotazioni di revisione del codice o gli abbinamenti del Babbo Natale segreto.

[SEEDED]

Riproducibilità con seme

Fornisci una stringa di seme per ottenere un'estrazione deterministica. Lo stesso seme con lo stesso elenco produce sempre lo stesso risultato - condivisibile e verificabile.

// INFORMAZIONI SUL SELETTORE CASUALE

Come funziona:

Questo strumento usa il mescolamento di Fisher-Yates (detto anche Knuth): percorri l'array dall'ultimo indice al primo e, a ogni passo, scambia l'elemento corrente con uno a un indice precedente scelto in modo uniformemente casuale. Ciò produce una permutazione uniforme e priva di distorsioni in tempo O(n). Il trucco ingenuo array.sort(() => Math.random() - 0.5) è distorto perché i comparatori di ordinamento di JavaScript devono essere transitivi - i comparatori casuali violano questa regola e falsano la distribuzione. Per le estrazioni senza seme attingiamo entropia da window.crypto.getRandomValues. Quando fornisci una stringa di seme, la convertiamo con cyrb53 in un intero a 53 bit e poi alimentiamo un PRNG mulberry32 in modo che semi identici producano risultati identici e riproducibili.

Algoritmo:

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

Standard e riferimenti:

  • >Web Crypto API (W3C) - crypto.getRandomValues per casualità crittograficamente forte
  • >Mescolamento di Fisher-Yates (1938), reso popolare da Donald Knuth in The Art of Computer Programming Vol. 2
  • >mulberry32 - PRNG con seme piccolo, veloce e ben distribuito di Tommy Ettinger
  • >cyrb53 - hash di stringa a 53 bit di bryc, usato per trasformare una stringa di seme in uno stato numerico del PRNG

Casi d'uso comuni:

  • >Concorsi, lotterie e scelta di un vincitore casuale tra le partecipazioni
  • >Estrazione di nomi in classe e selezione di studenti per domande a sorpresa
  • >Abbinamento di squadre sportive, allenamenti in coppia e tabelloni di torneo
  • >Assegnazione dei revisori del codice in un team di ingegneria
  • >Selezione del campione per test A/B e coorti di sondaggio randomizzate
  • >Coppie del Babbo Natale segreto, scambi di regali e compagni di pranzo del team
  • >Input di test casuali e semi di fuzzing per il QA
  • >Decisioni di gruppo e spareggi
  • >Selezione di giurie simulate e panel di colloqui randomizzati
  • >Estrazioni in stile lotteria per eventi della comunità e premi

Strumenti correlati:

  • >Generatore di numeri casuali — il complemento basato sul testo: scegli numeri in un intervallo con le stesse primitive di riproducibilità con seme
  • >Generatore di UUID — identificatori v4 casuali quando serve un ID opaco univoco anziché un vincitore estratto da un elenco
  • >Generatore di password — stringhe crittograficamente casuali con controllo del set di caratteri per token e credenziali
  • >randompickerwheel.app — interfaccia a ruota della fortuna complementare a questo selettore testuale, perfetta per estrazioni davanti al pubblico dal vivo, domande in classe e rivelazioni a schermo

// ESEMPI DI ESTRAZIONE

Concorso — estrai 3 vincitori da 50 partecipazioni

> input:

alice@x.com
bob@x.com
carlos@x.com
…(50 righe in totale)

> config:

Modalità=Pick N, Quantità=3, Consenti duplicati=off, Seme=(vuoto)

> output:

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

Mescola un elenco di 10 nomi per un ordine di presentazione

> input:

Alice
Bob
Charlie
Dana
Evelyn
Farouk
Gabriela
Hiroshi
Isabella
Jamal

> config:

Modalità=Shuffle, Seme=(vuoto)

> output:

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

Dividi una classe di 12 studenti in gruppi da 2

> input:

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

> config:

Modalità=Pair Up, Dimensione gruppo=2, Seme=class-2026-05-02

> output:

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

Estrazione riproducibile con seme — eseguila due volte con lo stesso seme, ottieni gli stessi vincitori

> input:

alpha
bravo
charlie
delta
echo
foxtrot
golf
hotel

> config:

Modalità=Pick N, Quantità=2, Seme=launch-day, Consenti duplicati=off

> output:

Esecuzione 1: 1. echo
              2. bravo
Esecuzione 2: 1. echo
              2. bravo  (identico — con seme)

// PERCHÉ .SORT() INGENUO È DISTORTO

Un mescolamento in una riga molto diffuso è arr.sort(() => Math.random() - 0.5). Sembra elegante, sta in una riga e dà l'impressione di essere casuale — ma la distribuzione delle permutazioni risultanti è tutt'altro che uniforme. La specifica ECMAScript richiede che le funzioni di confronto siano deterministiche e transitive: se a < b e b < c, allora a < c. Un comparatore a testa o croce viola questo contratto e l'implementazione di ordinamento del motore visita le coppie di confronto secondo uno schema non uniforme.

V8 (Chrome, Node) usa Timsort; i motori più vecchi usavano quicksort o mergesort. Ogni implementazione visita un sottoinsieme diverso di coppie di confronto e riutilizza i confronti memorizzati in cache in modi diversi. Come dimostrato empiricamente da Mike Bostock (bost.ocks.org/mike/shuffle/compare.html), l'ordinamento ingenuo produce output fortemente distorti in cui alcune permutazioni compaiono molte più volte di altre — inaccettabile per un concorso, un bucket A/B o qualsiasi estrazione che debba essere equa.

L'algoritmo corretto è Fisher-Yates (mescolamento di Knuth): percorri l'array dall'ultimo indice al primo e, a ogni passo, scambia l'elemento corrente con uno scelto in modo uniformemente casuale tra gli indici 0..i. Viene eseguito in O(n), usa O(1) di spazio aggiuntivo e produce in modo dimostrabile ogni permutazione con uguale probabilità.

// 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;
}

// IMPLEMENTALO TU STESSO

Vuoi creare il tuo selettore o verificare il nostro? Queste sono le primitive esatte usate da questa pagina — piccole, senza dipendenze e identiche a ciò che gira nel tuo browser quando fai clic su PICK. Copiale direttamente in uno script Node o in un'altra 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);

>> domande frequenti

D: Come viene generata la casualità?

R: Quando non viene fornito alcun seme, usiamo window.crypto.getRandomValues, il generatore di numeri casuali crittograficamente sicuro del browser basato sulla Web Crypto API. È la stessa fonte di entropia usata per chiavi e token crittografici, quindi più che robusta per lotterie e mescolamenti. Quando fornisci un seme, deriviamo in modo deterministico uno stato a 53 bit tramite l'hash di stringa cyrb53 e lo immettiamo in un PRNG mulberry32 affinché l'estrazione sia riproducibile.

D: Posso ottenere lo stesso risultato due volte usando un seme?

R: Sì. Digita una stringa qualsiasi nel campo SEME - una data, il nome di un concorso, un hash, qualsiasi cosa. Lo stesso seme combinato con lo stesso elenco di ingresso e la stessa modalità produrrà sempre esattamente lo stesso output. È preziosissimo per concorsi trasparenti in cui vuoi pubblicare il seme in anticipo e lasciare che i partecipanti verifichino l'estrazione, o per rotazioni di ingegneria che devono essere riproducibili tra le macchine.

D: Qual è la differenza tra Pick N e Shuffle?

R: Pick N seleziona un sottoinsieme di dimensione N dal tuo elenco, facoltativamente con reinserimento (duplicati consentiti). Shuffle restituisce l'intero elenco riordinato - nessun elemento viene eliminato o ripetuto, solo riorganizzato. Usa Pick N quando vuoi solo pochi vincitori tra molte partecipazioni; usa Shuffle quando ogni elemento deve ancora partecipare ma in un nuovo ordine casuale, come una coda di presentazione o una playlist.

D: array.sort(() => Math.random() - 0.5) è davvero casuale?

R: No, è distorto. La specifica ECMAScript richiede che i comparatori di ordinamento siano deterministici e transitivi (se a < b e b < c allora a < c). Un comparatore casuale viola questo contratto e diversi motori JavaScript eseguono diversi algoritmi di ordinamento sottostanti (TimSort, mergesort, quicksort) che interagiscono con il comparatore casuale in modi diversi. Il risultato è una distribuzione non uniforme in cui alcune permutazioni compaiono molto più spesso di altre. Fisher-Yates è l'algoritmo corretto.

D: Posso abbinare un elenco con un numero dispari di elementi?

R: Sì. La modalità Pair Up mescola il tuo elenco con Fisher-Yates e poi lo suddivide in base alla dimensione del gruppo scelta. Se il totale non si divide in modo esatto, l'ultimo gruppo sarà più piccolo e viene chiaramente etichettato come gruppo residuo nell'output. Per un elenco dispari puoi accettare una voce singola, aumentare la dimensione del gruppo o aggiungere un nome segnaposto come "bye" prima dell'estrazione.

D: Il mio elenco viene caricato da qualche parte?

R: No. Questo strumento è al 100% lato client - il tuo elenco, il tuo seme e l'output non lasciano mai il tuo browser. Non c'è alcuna chiamata al server, nessuna registrazione e nessuna analisi sull'input. Puoi disconnetterti da internet dopo il caricamento della pagina e ogni pulsante continua a funzionare. Ricarica la pagina e i dati spariscono per sempre.

D: Esiste una versione visiva con ruota della fortuna di questo strumento?

R: Per un'esperienza interattiva con ruota dei nomi, animazione, effetti sonori e una grande rivelazione visiva, consulta randompickerwheel.app. È un prodotto complementare incentrato su estrazioni davanti al pubblico dal vivo e condivisione dello schermo. Questa pagina è un selettore orientato al testo, focalizzato su elenchi di massa, estrazioni riproducibili con seme, esportazione CSV e abbinamento - utile quando serve una risposta deterministica rapida anziché una presentazione.

// OTHER LANGUAGES