// Unbiased randomness from crypto.getRandomValues (available on http too). const buf = new Uint32Array(1); /** Uniform integer in [0, n). Rejection sampling avoids modulo bias. */ export function randomInt(n) { if (n <= 1) return 0; const limit = Math.floor(0x100000000 / n) * n; let x; do { crypto.getRandomValues(buf); x = buf[0]; } while (x >= limit); return x % n; } /** Fisher–Yates shuffle, returns a new array. */ export function shuffle(arr) { const a = arr.slice(); for (let i = a.length - 1; i > 0; i--) { const j = randomInt(i + 1); [a[i], a[j]] = [a[j], a[i]]; } return a; } export function pick(arr) { return arr[randomInt(arr.length)]; }