Is there an efficient algorithm to generate a permutation from one index provided? The permutations do not need to have any specific ordering and it just needs to return every permutation once per every possible index. The set I wish to permute is all integers from 0~255.
-
1If I understand this correctly, in your case, the permutations coincide with the indices themselves. Why not return the index?user1984– user19842022-03-14 15:20:08 +00:00Commented Mar 14, 2022 at 15:20
-
Note that log2(256!) = 1684 bits (around) = 210.5 bytes. So, the index would be about as long as the permutation array itsel (256 bytes).Damien– Damien2022-03-14 15:45:18 +00:00Commented Mar 14, 2022 at 15:45
-
1Could you provide an example of what you are looking for with sample input and output? Currently, it is very unclear.RBarryYoung– RBarryYoung2022-03-14 16:17:45 +00:00Commented Mar 14, 2022 at 16:17
-
1Related: Finding n-th permutation without computing others; Given a list of elements in lexicographical order (i.e. ('a', 'b', 'c', 'd')), find the nth permutationStef– Stef2022-03-14 18:07:50 +00:00Commented Mar 14, 2022 at 18:07
2 Answers
If I understand the question correctly, the problem is as follows: You are given two integers n and k, and you want to find the kth permutation of n integers. You don't care about it being the kth lexicographical permutation, but it's just easier to be lexicographical so let's stick with that.
This is not too bad to compute. The base permutation is 1,2,3,4...n. This is the k=0 case. Consider what happens if you were to swap the 1 and 2: by moving the 1, you are passing up every single permutation where 1 goes first, and there are (n-1)! of those (since you could have permuted 2,3,4..n if you fixed the 1 in place). Thus, the algorithm is as follows:
for i from 1 to n:
j = k / (n-i)! // integer division, so rounded down
k -= j * (n-i)!
place down the jth unplaced number
This will iteratively produce the kth lexicographical permutation, since it repeatedly solves a sub-problem with a smaller set of numbers to place, and decrementing k along the way.
Comments
There is an implementation in python in module more-itertools: nth_permutation.
Here is an implementation, adapted from the code of more_itertools.nth_permutation:
from sympy import factorial
def nth_permutation(iterable, index):
pool = list(iterable)
n = len(pool)
c = factorial(n)
index = index % c
result = [0] * n
q = index
for d in range(1, n + 1):
q, i = divmod(q, d)
if 0 <= n - d < n:
result[n - d] = i
if q == 0:
break
return tuple(map(pool.pop, result))
print( nth_permutation(range(6), 360) )
# (3, 0, 1, 2, 4, 5)
3 Comments
uniques = set(l); return list(chain(uniques, (Counter(l) - Counter(uniques)).elements()) but I'm not sure how helpful that would be to the OP.set adds overhead?