function decodeOrder(xs) { var rem = [...xs].sort(), code = 0n; xs.forEach((x, i) => { var j = rem.indexOf(x); code = code * BigInt(xs.length - i) + BigInt(j); rem.splice(j, 1); }); return code; } function decodeOrderStr(xs) { for (var chars = [], n = decodeOrder(xs); n; n >>= 8n) chars.push(String.fromCharCode(Number(n & 255n))); return chars.reverse().join(""); } /// All-in-one version. function decodeOrderStrCombined(xs) { var rem = [...xs].sort(), n = 0n; xs.forEach((x, i) => { var j = rem.indexOf(x); n = n * BigInt(xs.length - i) + BigInt(j); rem.splice(j, 1); }); for (var chars = []; n; n >>= 8n) chars.push(String.fromCharCode(Number(n & 255n))); return chars.reverse().join(""); } /// Only needed for encoding. function facts(n) { const f = [1n]; for (var i = 1; i <= n; i++) f[i] = f[i - 1] * BigInt(i); return f; } function encodeOrder(xs, code) { const rem = [...xs].sort(), out = [], f = facts(xs.length); code = BigInt(code); for (var 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; } function encodeOrderStr(xs, s) { var n = [...s].reduce((n, c) => (n << 8n) | BigInt(c.charCodeAt(0)), 0n); return encodeOrder(xs, strToBignum(s)); }