Explorar E-books
Categorias
Explorar Audiolivros
Categorias
Explorar Revistas
Categorias
Explorar Documentos
Categorias
i=0
n1
ii ! + 1 . For example, the largest factoradic
number of 5 digits (n = 5) is 43210
!
, which has as next value (43210
!
+1) = 100000
!
. In other words,
44!+33!+22!+11!+0! = 119 and, 5! =120 = 119+1. This establishes that really any non-negative
integer has a unique representation as a factoradic number.
The conversion of a decimal number to its factoradic representation can be made by the
straightforward method of successive integer divisions by the place value for each position, starting
from i = n-1, and taking the quotients as the corresponding factoradic digits. The remainder of each
division is then divided by the next place value. For the previous example we could have computed
83 = 324 + 11
11 = 16 + 5
5 = 22 + 1
1 = 11 + 0
0 = 00 + 0
Inversions
Consider a set of n = 5 elements, represented by Z
5
= {0,1,2,3,4} and let us label the
elements of the set as p
i
, for i = 0 .. (n-1). A possible permutation on this set is r
0
= (0,1,2,3,4),
which represents the identity permutation, as the order of the original set has not changed. Another
permutation could be r
83
= (3,1,4,2,0) - as mentioned before, we will care about the subscripts later.
It is said that an inversion has occurred in position i, in a given permutation, when p
i
> p
j
, for some
j > i. In r
83
we find that for i = 0 we have 3 inversions, as 4 > 2, 3 and 1. In the same way, for i = 1
we have 1 inversion, for i = 2 we have 2 inversions, for i = 3 we have 1 inversion, and for i = 4 we
have 0 inversions. We will always have 0 inversions for i = (n-1) as there is no further elements
beyond that. If we put this inversion counts in the form of a vector we get what is called the
inversion vector, or inversion table, for the corresponding permutation, also called its Lehmer
Code
(4,5)
, L. For the general case we can write
L(r) = [l
0
(r), l
1
(r), , l
n-1
(r)], where
l
i
(r) = |{j > i: r(i) > r(j)}|.
It can be shown that every permutation has a unique Lehmer Code associated to it, thus
existing a one-to-one mapping between Lehmer Codes and permutations
(3)
.
Returning to our previous example then we have
L
83
= [3,1,2,1,0].
Now, the beauty of it: 83 = 31210
!
, which shows that we can associate each n-digit
factoradic number, one-to-one, with every permutation in S
n
. This finally justifies the use that we
have done for the subscripts added to the example permutations examined so far and gives us a very
easy way for enumerating all permutations in S
n
with a simple decimal index that counts from 0 to
(n! - 1). Another important result of this permutations ordering as factoradic numbers is that they
are obtained in a natural, lexicographical, order.
As a small example, let us take n = 3 and construct a table associating all 6 elements of S
3
to
its corresponding indexes, both in decimal and factoradic representation, as shown in table 1 below:
Table 1: Permutations and associated indexes for n = 3.
N N
!
r
N
0 (0,0,0) (0,1,2)
1 (0,1,0) (0,2,1)
2 (1,0,0) (1,0,2)
3 (1,1,0) (1,2,0)
4 (2,0,0) (2,0,1)
5 (2,1,0) (2,1,0)
From Permutations to Factoradic Numbers and Vice-versa
We have shown how to represent a given permutation as a factoradic number, simply by
constructing its inversion vector. Now it remains to show how we can determine the particular
permutation associated to a given factoradic number or decimal equivalent.
There are many and many ways of generating permutations, including sequential generation
and random generation. The point about generating a permutation from its associated factoradic
representation is that we can generate any permutation, without having to pass through intermediate
processing, or, from a given permutation, obtain a corresponding index for it, considered a
lexicographical ordering for the elements of S
n
.
To obtain the associated permutation of n elements from its corresponding Factoradic value,
or, equivalently, its Lehmer code, or inversion vector, is just a matter of going backwards with
respect to the previous construct. Let us consider n = 5, such that the original set may be regarded as
S = r
0
= {0,1,2,3,4}. Let us assume now that we want to identify r
51
. Considering that N = 51 =
20110
!
, then we can write L(r
51
) = [l
0
, l
1
, l
2
, l
3
, l
4
] = [2,0,1,1,0]. Starting with i = 0 we observe that
l
0
= 2 corresponds to the inversions count for that position. So, to find the corresponding element in
r
0
we just take the element in this set which is bigger than 2 other elements, which in turn is the
element of order 2 in r
0
, or else, r
51
(0) = r
0
(l
0
) = r
0
(2) = 2. Now, we remove this element from the
original set (it has already been used in r
51
), getting r
0
' = {0,1,3,4}, and consider the next element
of L, l
1
= 0. The same process applies now to r
0
', giving r
51
(1) = r
0
'(l
1
) = r
0
'(0) = 0, and so
successively, till we obtain all elements of the wanted permutation. In table 2 that follows it is better
illustrated this process of constructing r
51
:
Table 2: Constructing permutation r
51
(n=5) from its Lehmer Code.
i l
i
Lehmer Code Set S (r
0
) Perm r
51
0 2 [2,0,1,1,0] (0,1,2,3,4) (2,_,_,_,_)
1 0 [2,0,1,1,0] (0,1,3,4,_) (2,0,_,_,_)
2 1 [2,0,1,1,0] (1,3,4,_,_) (2,0,3,_,_)
3 1 [2,0,1,1,0] (1,4,_,_,_) (2,0,3,4,_)
4 0 [2,0,1,1,0] (1,_,_,_,_) (2,0,3,4,1)
Note that l
n-1
being always zero, it corresponds to whatever is the last element remaining in
r
0
' in the last step of the process.
Generating a Permutation
Given the order n and a decimal index N < (n-1)! we can generate the corresponding
permutation with this simple algorithm, in pseudo-language:
1. Define variables:
N,n: int; // Decimal integer and order of the set
i,j,r,v: int; // indexes to arrays
S: array[0..n-1]; // original set
Perm: array[0..n-1]; // permuted set
PlaceValue: array[0..n-1]; // fatoradic place values [0!,1!,2!,..,(n-1)!]
Factoradic:array[0..n-1]; // fatoradic digits corresponding to N
2. Initialize variables
2.1 read n,N
2.2 for i from 0 to (n-1) do
S[i] = I
PlaceValue[i] = i!
enddo
3. Convert N to factoradic
3.1 V = N
3.2 for i from (n-1) downto 0 do
Factoradic[i] = V div PlaceValue[i]
V = V mod PlaceValue[i]
enddo
4. Convert Factoradic to Permutation
for i from 0 to (n-1) do
j = (n-1)-i
r = Factoradic[j]
Perm[i] = S[r]
// delete S[r] by shifting left greater order elements
for j from r to (n-2) do S[j] = S[j+1]
enddo
END
A demo implementation in FreePascal of this algorithm is shown below, together with its
output for n = 5 and N = 51, as done in the previous example:
program Dec2Perm;
(* Program for generating a permutation of a set of n elements from a given
Decimal index, based on the representation of a permutation as a "factoradic
number", i.e. a number represented in the mixed base [(n-1)!,(n-2)!,...,2!,
1!, 0!].
We have limited 'n' to 12, as this is just a demo program and 12! fits into
a 32-bit CPU word. *)
uses SysUtils;
const
progname = 'Dec2Perm';
version = 'v0.9 - 12.01.03';
author = ' (Joel Guilherme)';
nmax = 12;
type
aset = array[0..(nmax-1)] of byte; // a set of integers mod-n
bset = array[0..(nmax-1)] of longword; // a set of integers
var
n: byte; // the order of the set
D,V: longword; // decimal to be converted to a permutation
Dmax: longword; // maximum value for D
i,j,r: byte; // indexes to arrays
Code: word; // indicates input conversion error
S: aset; // this will hold the original, ordered permutation (0,1,2,...,n-1)
Perm: aset; // the permutation associated to N
PlaceValue: bset; // array with fatoradic place values [0!,1!,2!,..,(n-1)!]
Factoradic: bset; // array with a fatoradic number digits corresponding to N
procedure ShowSet(msg: string; span: byte; var Arr: aset);
// writes a set to console
var
r,m: byte;
begin
m := span-1;
write(msg);
for r := 0 to m do
begin
if (r = 0) then
write('[',Arr[r])
else
write(',',Arr[r]);
end;
writeln(']');
end; { ShowSet }
procedure ShowFac(msg: string; span: byte; var Arr: bset);
// writes a factoradic array to console
var
r,m: byte;
begin
m := span-1;
write(msg);
for r := m downto 0 do
begin
if (r = m) then
write('[',Arr[r])
else
write(',',Arr[r]);
end;
writeln(']');
end; { ShowFac }
function factorial(x: longword): longword;
begin
if (x=0) or (x=1) then
factorial := 1
else
factorial := x*factorial(x-1);
end;
procedure Help;
// Shows a "help" message if wrong parameters passed
begin
writeln('usage:');
writeln(' > nextperm <N> <n>');
writeln(' where');
writeln(' - N is a decimal index to a lexicographically permuted set');
writeln(' - n is the order of the set to be permuted');
writeln;
halt(1);
end;
procedure Error(msg: string);
begin
writeln(msg,'! Aborting!');
halt(1);
end;
procedure Initialize;
// initialize arrays and variables
begin
Dmax := factorial(n);
for i := 0 to (n-1) do begin
S[i] := i;
PlaceValue[i] := factorial(i);
end;
end;
{ Main Program }
begin
writeln; writeln(Progname,' ',version);
writeln('Program for generating a lexicographically ordered ');
writeln('permutation from a given decimal index. - ',author); writeln;
if paramcount < 2 then Help;
val(paramstr(1),D,Code);
if Code > 0 then Error('Error reading input N');
val(paramstr(2),n,Code);
if Code > 0 then Error('Error reading input n');
if n > nmax then Error('Given order ''n'' is too big. Maximum is 12');
Initialize;
if D > Dmax then Error('Given decimal ''N'' is too big. Maximu is (n! - 1)');
// Convert N to Factoradic
V := D;
for i := (n-1) downto 0 do begin
Factoradic[i] := V div Placevalue[i];
V := V mod Placevalue[i];
end;
writeln('For n = ',n,':');
ShowSet('Perm(0) = ',n,S);
ShowFac('Factoradic('+inttostr(D)+') = ',n,Factoradic);
// Convert Factoradic to Permutation
for i := 0 to (n-1) do begin
j := (n-1) - i;
r := Factoradic[j];
Perm[i] := S[r];
// delete S[r] from S (by shifting left all greater order elements)
for j := r to (n-2) do S[j] := S[j+1];
end;
ShowSet('Perm('+inttostr(D)+') = ',n,Perm);
writeln;
end.
The program has been compiled with FreePascal 2.4.0 for Linux-Ubuntu 10.04. A sample
output from the program is:
$ ./Dec2Perm 51 5
Dec2Perm v0.9 - 12.01.03
Program for generating a lexicographically ordered
permutation from a given decimal index. - (Joel Guilherme)
For n = 5:
Perm(0) = [0,1,2,3,4]
Factoradic(51) = [2,0,1,1,0]
Perm(51) = [2,0,3,4,1]
Bibliography
(1) Symmetric group, http://en.wikipedia.org/wiki/Symmetric_group - accessed on 2011/12/11.
(2) Positional notation, http://en.wikipedia.org/wiki/Positional_notation - accessed on 2011/12/11.
(3) Factorial number system, http://en.wikipedia.org/wiki/Factorial_number_system - accessed on
2011/12/11.
(4) Permutation, http://en.wikipedia.org/wiki/Permutation - accessed on 2011/12/11.
(5) Enumerating permutations using inversion vectors and factoradic numbering, http://lin-ear-th-
inking.blogspot.com/2012/11/enumerating-permutations-using.html - . accessed on
2011/12/11.