> pick | shuffle | pair <
// Wklej listę, wylosuj zwycięzców, przetasuj kolejność lub podziel osoby na grupy - wszystko w przeglądarce
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.
Nieobciążone tasowanie Fishera-Yatesa
Przestawia całą listę za pomocą klasycznego tasowania Knutha. Każda permutacja jest jednakowo prawdopodobna - bez naiwnych sztuczek z sortowaniem.
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.
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.