Problem 24 : Lexicographic permutations
A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:
012 021 102 120 201 210
What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?
C++ source code
#include <iostream>
#include <string>
#include <cassert> // assert()
#include <algorithm> // next_permutation()
using namespace std;
class PE0024
{
public:
string findNextPermutation(const string& digitsString, int SeqNo);
};
string PE0024::findNextPermutation(const string& digitsString, int SeqNo)
{
int num = 0;
string digits;
digits.assign(digitsString.begin(), digitsString.end());
while(true == next_permutation(digits.begin(), digits.end()))
{
num++;
if (num == SeqNo-1)
{
break;
}
}
return digits;
}
int main()
{
PE0024 pe0024;
string digitsString = "012";
assert(pe0024.findNextPermutation(digitsString, 3) == "102");
digitsString = "0123456789";
int sequenceNo = 1000000; // millionth
cout << "The millionth lexicographic permutation of the digits " ;
cout << "0,1,2,3,4,5,6,7,8 and 9 is " ;
cout << pe0024.findNextPermutation(digitsString,sequenceNo) << endl;
return 0;
}
Python source code
import math
#--- generate permutations-------------------------------------------------
def next_permutation(s, n):
"""
Find the nth permutation of the string s, but n starts from 0
Example:
>>>next_permutation('abcde', 30)
bcade
"""
if len(s)==1:
return s
q, r = divmod(n, math.factorial(len(s)-1))
return s[q] + next_permutation(s[:q] + s[q+1:], r)
def next_permutation2(s, n, fn):
"""
Find the nth permutation of the string s, but n starts from 0
Example:
>>>next_permutation('abcde', 30)
bcade
"""
if len(s)==1:
return s
q, r = divmod(n, fn) # fn = factorial(len(s)-1)
return s[q] + next_permutation(s[:q] + s[q+1:], r)
def findNextPermutation(digitsString, SeqNo):
""" SeqNo starts from 1 """
return next_permutation(digitsString, SeqNo-1)
def findNextPermutation2(digitsString, SeqNo):
""" SeqNo starts from 1 """
return next_permutation2(digitsString,
SeqNo-1,
math.factorial(len(digitsString)-1))
def main():
assert findNextPermutation('012', 3) == '102'
print("The millionth lexicographic permutation of the digits")
print("0,1,2,3,4,5,6,7,8 and 9 is", findNextPermutation2('0123456789',1000000))
if __name__ == '__main__':
main()