function shuffle(subject: A[]): A[] { let res = Array.from(subject); for (let i = 0; i < res.length - 1; ++i) { const j = i + Math.floor(Math.random() * (res.length - i)); if (i != j) { const k = res[i]!; res[i] = res[j]!; res[j] = k; } } return res; } function group(subject: A[], keepTogether: A[][]): A[][] { type Value = {array: A[], added: boolean}; let groups: Map = new Map; for (const xs of keepTogether) { let value = {array: xs, added: false}; for (const x of xs) { groups.set(x, value); } } let res = []; for (const x of subject) { let group = groups.get(x); if (group?.added) { continue; } else if (group) { group.added = true; res.push(shuffle(group.array)); } else { res.push([x]); } } return res; } function groupedShuffle(subject: A[], keepTogether: A[][]): A[] { return shuffle(group(subject, keepTogether)).flat(); } function shuffleAll() { let groups = [group('myno', 'abyss'), group('clip', 'cervine')]; for (const elem of Array.from(document.getElementsByClassName('shuffle'))) { let shuffled = groupedShuffle(Array.from(elem.children), groups); elem.innerHTML = ''; for (const child of shuffled) { elem.appendChild(child); } } function group(...xs: string[]) { let elements = xs.map(x => document.getElementById(x)); return elements.every(x => x) ? elements as HTMLElement[] : []; } } document.addEventListener('DOMContentLoaded', shuffleAll); export {};