I wrote the following little piece of Python code to take in some integer, and return a permutation that has that rank in the lexicographical ordering of permutations. While this works, I'm worried that the number of calls to pop() and append() might be slowing this down. This function is part of a larger program, which will call FromRank() millions of times, and any small efficiency may make a large impact down the road.
Note: The same topic for Java is here!
Input:
There are four arguments: rank, level, ordered, and perm. rank is the rank given. level is the number of uncertain digits of the permutation minus one. Hence, if the size of a permutation is 8 digits, then level is initially 7. ordered is initially list(range(size)) and is always sorted. perm keeps track of the permutation, and is initially an empty list.
Code:
def FromRank(rank,level,ordered,perm):
fact = math.factorial(level)
section = rank // fact
if len(ordered) == 1:
perm.extend(ordered)
return perm
elif rank % fact == 0:
ordered.sort()
nxt = ordered.pop(section - 1)
perm.append(nxt)
ordered.sort(reverse = True)
perm.extend(ordered)
return perm
elif rank < fact:
ordered.sort()
first = ordered.pop(0)
perm.append(first)
return FromRank(rank,level - 1,ordered,perm)
else:
ordered.sort()
nxt = ordered.pop(section)
perm.append(nxt)
rank = rank - (rank // fact) * fact
return FromRank(rank,level - 1,ordered,perm)
Example:
I ran the following code:
for j in range(1,11):
start_time = timeit.default_timer()
for i in range(1,math.factorial(j)+1):
x = FromRank(i,j-1,list(range(j)),[])))
elapsed_time = timeit.default_timer() - start_time
print("Permutations of size {} took {} seconds."\
.format(j,elapsed_time))
and got the following times:
Permutations of size 1 took 4.83249833749e-05 seconds.
Permutations of size 2 took 0.000249750356557 seconds.
Permutations of size 3 took 0.00016293644837 seconds.
Permutations of size 4 took 0.000660726542604 seconds.
Permutations of size 5 took 0.00366414564209 seconds.
Permutations of size 6 took 0.0185743274595 seconds.
Permutations of size 7 took 0.160154982071 seconds.
Permutations of size 8 took 1.48163329891 seconds.
Permutations of size 9 took 15.2436537109 seconds.
Permutations of size 10 took 177.243403105 seconds.