function facts(n) { const f = [1n]; for (let i = 1; i <= n; i++) f[i] = f[i - 1] * BigInt(i); return f; } function decodeOrder(xs) { const rem = [...xs].sort(), f = facts(xs.length); let code = 0n; for (let i = 0; i < xs.length; i++) { const j = rem.indexOf(xs[i]); if (j < 0) throw Error("duplicate item"); code += BigInt(j) * f[xs.length - 1 - i]; rem.splice(j, 1); } return code; } function encodeOrder(xs, code) { const rem = [...xs].sort(), out = [], f = facts(xs.length); code = BigInt(code); for (let i = xs.length; i > 0; i--) { const q = code / f[i - 1]; code %= f[i - 1]; out.push(rem.splice(Number(q), 1)[0]); } return out; } /// Extras function strToBignum(s) { return [...s].reduce((n, c) => (n << 8n) | BigInt(c.charCodeAt(0)), 0n); } function bignumToStr(n) { let s = ""; for (n = BigInt(n); n; n >>= 8n) { s = String.fromCharCode(Number(n & 255n)) + s; } return s; }; function encodeOrderStr(xs, s) { return encodeOrder(xs, strToBignum(s)); } function decodeOrderStr(xs) { return bignumToStr(decodeOrder(xs)); }