import math
def num_smaller(m, p, i):
count = 0
for j in range(i):
count += int(m > p[j])
return count
def num_preceding_permutations(n, k, m, p, i):
num_unused_preceding = m - 1 - num_smaller(m, p, i)
return (
math.factorial(n - i - 1)
/ math.factorial(n - k)
) * num_unused_preceding
def rank(p, n):
k = len(p)
return int(sum(
num_preceding_permutations(n, k, m, p, i)
for i, m in enumerate(p)))
def unrank(index, n, k):
p = []
j = index
for i in range(k):
m = 0
while (num_preceding_permutations(n, k, m + 1, p, i)
<= j):
m += 1
p.append(m)
j -= num_preceding_permutations(n, k, m, p, i)
return p
ps = [
([3, 4], 4),
([3, 2, 4], 4),
([34, 2, 18, 27, 10], 38)
]
for p, n in ps:
rank_p = rank(p, n)
print((p, rank_p, unrank(rank_p, n, len(p)) == p))
aW1wb3J0IG1hdGgKCgpkZWYgbnVtX3NtYWxsZXIobSwgcCwgaSk6CiAgY291bnQgPSAwCiAgZm9yIGogaW4gcmFuZ2UoaSk6CiAgICBjb3VudCArPSBpbnQobSA+IHBbal0pCiAgcmV0dXJuIGNvdW50CgoKZGVmIG51bV9wcmVjZWRpbmdfcGVybXV0YXRpb25zKG4sIGssIG0sIHAsIGkpOgogIG51bV91bnVzZWRfcHJlY2VkaW5nID0gbSAtIDEgLSBudW1fc21hbGxlcihtLCBwLCBpKQogIHJldHVybiAoCiAgICAgIG1hdGguZmFjdG9yaWFsKG4gLSBpIC0gMSkKICAgICAgLyBtYXRoLmZhY3RvcmlhbChuIC0gaykKICApICogbnVtX3VudXNlZF9wcmVjZWRpbmcKCgpkZWYgcmFuayhwLCBuKToKICBrID0gbGVuKHApCiAgcmV0dXJuIGludChzdW0oCiAgICBudW1fcHJlY2VkaW5nX3Blcm11dGF0aW9ucyhuLCBrLCBtLCBwLCBpKQogICAgZm9yIGksIG0gaW4gZW51bWVyYXRlKHApKSkKCgpkZWYgdW5yYW5rKGluZGV4LCBuLCBrKToKICBwID0gW10KICBqID0gaW5kZXgKICBmb3IgaSBpbiByYW5nZShrKToKICAgIG0gPSAwCiAgICB3aGlsZSAobnVtX3ByZWNlZGluZ19wZXJtdXRhdGlvbnMobiwgaywgbSArIDEsIHAsIGkpCiAgICAgICAgICAgPD0gaik6CiAgICAgIG0gKz0gMQogICAgcC5hcHBlbmQobSkKICAgIGogLT0gbnVtX3ByZWNlZGluZ19wZXJtdXRhdGlvbnMobiwgaywgbSwgcCwgaSkKICByZXR1cm4gcAoKCnBzID0gWwogIChbMywgNF0sIDQpLAogIChbMywgMiwgNF0sIDQpLAogIChbMzQsIDIsIDE4LCAyNywgMTBdLCAzOCkKXQoKZm9yIHAsIG4gaW4gcHM6CiAgcmFua19wID0gcmFuayhwLCBuKQogIHByaW50KChwLCByYW5rX3AsIHVucmFuayhyYW5rX3AsIG4sIGxlbihwKSkgPT0gcCkp