## JavaScript (ES6), 163 bytes <!-- begin snippet: js hide: false console: true babel: false --> <!-- language: lang-js --> g=(a,n,l)=>l?g(a,a.reduce((r,_,i)=>r+=i<=l&a.indexOf(l)<a.indexOf(i),n*l--),l):n f=(n,i=0,a=[],j=i-n%++i)=>n?f(n/i|0,i,[...a.map(e=>e+=e>=j),j]):g(a,0,i-1) <!-- language: lang-html --> <input type=number min=0 oninput=o.textContent=f(+this.value)><pre id=o> <!-- end snippet --> 0-indexed. Works by converting the index to a permutation, inverting it, then converting back to an index. `g` inverts the permutation as it converts it back to an index. Ungolfed: function index(n) { var a = [0]; for (var i = 1; n = Math.floor(n / i); i++) { var j = i - n % (i + 1); for (var k = 0; k < i; k++) { if (a[k] > j) a[k]++; } a.push(j); } a = [...a.keys()].map(k => a.indexOf(k)); while (i) { n *= i--; j = a.pop(); for (k = 0; k < i; k++) { if (a[k] > j) n++; } } return n; }