> pick | shuffle | pair <

// Wklej listę, wylosuj zwycięzców, przetasuj kolejność lub podziel osoby na grupy - wszystko w przeglądarce

[PICK_N]

Wybierz N losowych elementów

Wylosuj dowolną liczbę zwycięzców z listy. Bez zwracania dla unikalnych zwycięzców lub ze zwracaniem dla losowań w stylu ważonym.

[SHUFFLE]

Nieobciążone tasowanie Fishera-Yatesa

Przestawia całą listę za pomocą klasycznego tasowania Knutha. Każda permutacja jest jednakowo prawdopodobna - bez naiwnych sztuczek z sortowaniem.

[PAIRS]

Podziel na grupy

Podziel listę na pary, trójki lub dowolny rozmiar grupy. Idealne do pracy w parach, rotacji recenzentów kodu lub losowania mikołajek.

[SEEDED]

Powtarzalność z ziarnem

Podaj ciąg ziarna, aby uzyskać deterministyczne losowanie. To samo ziarno plus ta sama lista zawsze daje ten sam wynik - można go udostępniać i weryfikować.

// O NARZĘDZIU LOSOWEGO WYBORU

Jak to działa:

To narzędzie używa tasowania Fishera-Yatesa (zwanego też tasowaniem Knutha): przejdź przez tablicę od ostatniego indeksu do pierwszego i na każdym kroku zamień bieżący element z elementem o jednostajnie losowym wcześniejszym indeksie. Daje to nieobciążoną, jednostajną permutację w czasie O(n). Naiwna sztuczka array.sort(() => Math.random() - 0.5) jest obciążona, ponieważ komparatory sortowania w JavaScript muszą być przechodnie - losowe komparatory naruszają tę zasadę i wypaczają rozkład. W losowaniach bez ziarna pobieramy entropię z window.crypto.getRandomValues. Gdy podasz ciąg ziarna, haszujemy go za pomocą cyrb53 do 53-bitowej liczby całkowitej, a następnie zasilamy PRNG mulberry32, dzięki czemu identyczne ziarna dają identyczne, powtarzalne wyniki.

Algorytm:

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

Standardy i odniesienia:

  • >Web Crypto API (W3C) - crypto.getRandomValues dla kryptograficznie silnej losowości
  • >Tasowanie Fishera-Yatesa (1938), spopularyzowane przez Donalda Knutha w The Art of Computer Programming tom 2
  • >mulberry32 - mały, szybki, dobrze rozłożony PRNG z ziarnem autorstwa Tommy'ego Ettingera
  • >cyrb53 - 53-bitowy hash ciągu autorstwa bryc, używany do zamiany ciągu ziarna w numeryczny stan PRNG

Typowe zastosowania:

  • >Konkursy, loterie i wyłanianie losowego zwycięzcy spośród zgłoszeń
  • >Losowanie nazwisk w klasie i wybór uczniów do niespodziewanych pytań
  • >Dobieranie drużyn sportowych, treningi w parach i drabinki turniejowe
  • >Przydzielanie recenzentów kodu w zespole inżynierskim
  • >Wybór próby do testów A/B i randomizowane kohorty ankietowe
  • >Pary mikołajkowe, wymiana prezentów i partnerzy do lunchu w zespole
  • >Losowe dane testowe i ziarna fuzzingu dla QA
  • >Podejmowanie decyzji grupowych i rozstrzyganie remisów
  • >Wybór symulowanej ławy przysięgłych i randomizowane panele rekrutacyjne
  • >Losowania w stylu loterii na wydarzenia społecznościowe i nagrody

Powiązane narzędzia:

  • >Generator liczb losowych — tekstowy odpowiednik: wybieraj liczby z zakresu przy użyciu tych samych prymitywów powtarzalności z ziarnem
  • >Generator UUID — losowe identyfikatory v4, gdy potrzebujesz unikalnego nieprzejrzystego ID, a nie zwycięzcy z listy
  • >Generator haseł — kryptograficznie losowe ciągi z kontrolą puli znaków dla tokenów i poświadczeń
  • >randompickerwheel.app — interfejs koła fortuny uzupełniający ten tekstowy losownik, idealny do losowań na żywo przed publicznością, pytań w klasie i ujawnień na ekranie

// PRZYKŁADOWE LOSOWANIA

Konkurs — wylosuj 3 zwycięzców z 50 zgłoszeń

> input:

alice@x.com
bob@x.com
carlos@x.com
…(50 wierszy łącznie)

> config:

Tryb=Pick N, Liczba=3, Zezwól na duplikaty=off, Ziarno=(puste)

> output:

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

Przetasuj listę 10 nazwisk dla kolejności prezentacji

> input:

Alice
Bob
Charlie
Dana
Evelyn
Farouk
Gabriela
Hiroshi
Isabella
Jamal

> config:

Tryb=Shuffle, Ziarno=(puste)

> output:

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

Podziel klasę 12 uczniów na grupy po 2

> input:

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

> config:

Tryb=Pair Up, Rozmiar grupy=2, Ziarno=class-2026-05-02

> output:

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

Powtarzalne losowanie z ziarnem — uruchom dwa razy z tym samym ziarnem, uzyskaj tych samych zwycięzców

> input:

alpha
bravo
charlie
delta
echo
foxtrot
golf
hotel

> config:

Tryb=Pick N, Liczba=2, Ziarno=launch-day, Zezwól na duplikaty=off

> output:

Uruchomienie 1: 1. echo
                2. bravo
Uruchomienie 2: 1. echo
                2. bravo  (identyczne — z ziarnem)

// DLACZEGO NAIWNE .SORT() JEST OBCIĄŻONE

Popularne tasowanie w jednej linii to arr.sort(() => Math.random() - 0.5). Wygląda elegancko, mieści się w jednej linii i sprawia wrażenie losowego — ale wynikowy rozkład permutacji daleki jest od jednostajnego. Specyfikacja ECMAScript wymaga, aby funkcje komparatora były deterministyczne i przechodnie: jeśli a < b oraz b < c, to a < c. Komparator typu rzut monetą narusza ten kontrakt, a implementacja sortowania silnika odwiedza pary porównań w niejednostajny sposób.

V8 (Chrome, Node) używa Timsort; starsze silniki używały quicksort lub mergesort. Każda implementacja odwiedza inny podzbiór par porównań i na różne sposoby ponownie wykorzystuje zapamiętane porównania. Jak empirycznie wykazał Mike Bostock (bost.ocks.org/mike/shuffle/compare.html), naiwne sortowanie daje silnie obciążone wyniki, w których niektóre permutacje pojawiają się wielokrotnie częściej niż inne — co jest nie do przyjęcia w konkursie, koszyku A/B ani żadnym losowaniu, które musi być uczciwe.

Poprawnym algorytmem jest Fisher-Yates (tasowanie Knutha): przejdź przez tablicę od ostatniego indeksu do pierwszego i na każdym kroku zamień bieżący element z elementem wybranym jednostajnie losowo spośród indeksów 0..i. Działa w O(n), zużywa O(1) dodatkowej pamięci i dowodliwie daje każdą permutację z równym prawdopodobieństwem.

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

// ZAIMPLEMENTUJ TO SAM

Chcesz zbudować własny losownik lub sprawdzić nasz? To dokładnie te prymitywy, których używa ta strona — małe, bez zależności i identyczne z tym, co działa w Twojej przeglądarce po kliknięciu PICK. Skopiuj je bezpośrednio do skryptu Node lub innej aplikacji webowej.

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

>> najczęściej zadawane pytania

P: Jak generowana jest losowość?

O: Gdy nie podano ziarna, używamy window.crypto.getRandomValues, kryptograficznie bezpiecznego generatora liczb losowych przeglądarki opartego na Web Crypto API. To to samo źródło entropii, którego używa się do kluczy i tokenów kryptograficznych, więc jest aż nadto silne do loterii i tasowań. Gdy podasz ziarno, deterministycznie wyprowadzamy 53-bitowy stan za pomocą hasha ciągu cyrb53 i zasilamy nim PRNG mulberry32, dzięki czemu losowanie jest powtarzalne.

P: Czy mogę uzyskać ten sam wynik dwukrotnie, używając ziarna?

O: Tak. Wpisz dowolny ciąg w polu ZIARNO - datę, nazwę konkursu, hash, cokolwiek. To samo ziarno w połączeniu z tą samą listą wejściową i tym samym trybem zawsze da dokładnie ten sam wynik. Jest to nieocenione przy przejrzystych konkursach, w których chcesz opublikować ziarno z wyprzedzeniem i pozwolić uczestnikom zweryfikować losowanie, lub przy rotacjach inżynierskich, które muszą być powtarzalne między maszynami.

P: Jaka jest różnica między Pick N a Shuffle?

O: Pick N wybiera podzbiór o rozmiarze N z Twojej listy, opcjonalnie ze zwracaniem (dozwolone duplikaty). Shuffle zwraca całą listę w nowej kolejności - żadne elementy nie są usuwane ani powtarzane, jedynie przestawiane. Użyj Pick N, gdy chcesz tylko kilku zwycięzców spośród wielu zgłoszeń; użyj Shuffle, gdy każdy element nadal ma uczestniczyć, ale w nowej losowej kolejności, jak kolejka prezentacji lub playlista.

P: Czy array.sort(() => Math.random() - 0.5) jest naprawdę losowe?

O: Nie, jest obciążone. Specyfikacja ECMAScript wymaga, aby komparatory sortowania były deterministyczne i przechodnie (jeśli a < b oraz b < c, to a < c). Losowy komparator narusza ten kontrakt, a różne silniki JavaScript uruchamiają różne bazowe algorytmy sortowania (TimSort, mergesort, quicksort), które na różne sposoby współdziałają z losowym komparatorem. Rezultatem jest niejednostajny rozkład, w którym niektóre permutacje pojawiają się znacznie częściej niż inne. Fisher-Yates to poprawny algorytm.

P: Czy mogę dobrać w pary listę o nieparzystej liczbie elementów?

O: Tak. Tryb Pair Up tasuje Twoją listę za pomocą Fishera-Yatesa, a następnie dzieli ją według wybranego rozmiaru grupy. Jeśli suma nie dzieli się równo, ostatnia grupa będzie mniejsza i jest wyraźnie oznaczona w wyniku jako grupa resztkowa. Przy nieparzystej liście możesz zaakceptować pojedynczy wpis, zwiększyć rozmiar grupy lub przed losowaniem dodać nazwę zastępczą, np. "bye".

P: Czy moja lista jest gdziekolwiek przesyłana?

O: Nie. To narzędzie działa w 100% po stronie klienta - Twoja lista, ziarno i wynik nigdy nie opuszczają przeglądarki. Nie ma żadnych wywołań serwera, żadnego logowania ani analityki danych wejściowych. Możesz odłączyć się od internetu po załadowaniu strony, a każdy przycisk nadal działa. Odśwież stronę, a dane znikną na dobre.

P: Czy istnieje wizualna wersja tego narzędzia w postaci koła fortuny?

O: Aby uzyskać interaktywne doświadczenie koła nazwisk z animacją, efektami dźwiękowymi i dużym wizualnym ujawnieniem, zobacz randompickerwheel.app. To produkt uzupełniający, skupiony na losowaniach na żywo przed publicznością i udostępnianiu ekranu. Ta strona to losownik zorientowany na tekst, skupiony na masowych listach, powtarzalnych losowaniach z ziarnem, eksporcie CSV i dobieraniu w pary - przydatny, gdy potrzebujesz szybkiej deterministycznej odpowiedzi zamiast prezentacji.

// OTHER LANGUAGES