Você está na página 1de 6

A Tutorial on

Generating Permutations using Factoradic Number Representation


Prof. Joel G. Silva Filho
Instituto de Educao Superior de Braslia - IESB
joel-iesb@joelguilherme.com
2012-01-03
Keywords: permutations, inversions, number systems, factoradic numbers, generation of permutations.
Introduction
A permutation on an ordered set of n elements is a well known concept. Whatever the
elements of the set may be, for simplicity and ease of manipulation, we can always represent it by
the set of the first n non-negative integers, or, in other words, the integers modulo-n: Z
n
= {0,1,2,
,n-1}. A permutation on this set is simply a rearrangement of its elements, r = (r(0),r(1), , r(n-
1)), where r(i) is the element that replaces i in the i-th position. For example, any set of 4 elements
can be represented by Z
4
= {0,1,2,3}. We can have then, for example, r
2
= {0,2,1,3} - we will
explain the subscript '2' later, where r
2
(0) = 0, r
2
(1) = 2, r
2
(2) = 1 and r
2
(3) = 3.
Ordered sets and its permutations find extensive application and interest in many areas such
as discrete mathematics, combinatorics, cryptography, computer science, and other areas.
One basic question when studying permutations is how many distinct permutations can we
find for a set of n elements. Considering that all elements in the set are distinct, the answer is easy
to find: we have n possible placements for each element, having n choices for the first, (n-1) for the
second, (n-2) for the third, and so on, such that for the last position we get only one choice, when all
others have already been chosen, getting N = n(n-1)(n-2) 321 , which is a number that
receives the special representation n! and is called the factorial of n (reading as n factorial). The
set of all permutations of n elements is usually denoted by S
n
and it forms the structure of a Group
under the operation of 'composition of permutations', i.e. the successive application of two (or
more) permutations on a given set, which consists the Symmetric Group of order n
(1)
.
Number Systems
We are used to single base number representations, such as base 10, which gives us the
ordinary decimal numbers, and base 2, which gives us the binary numbers, the latter being the basis
of all computer operations. Given a generic base b, we can represent any number in this base as
N = d
n-1
b
n-1
+d
n-2
b
n-2
+ +d
2
b
2
+d
1
b
1
+d
0
b
0

where d
i
, i = 0, .. , (n-1) - for a n digit number - are the digits of the number representation, each
digit being in the range [0 .. (b-1)]. For a base 10 representation the digits are in the range [0 .. 9],
and for a binary (base 2) representation the digits are in the range [0,1]. This representation is
known as a polynomial representation, as each digit can be viewed as the coefficient of a
polynomial in the base b. Also, the order, or position, of each digit assumes, in this way, a value
which is proportional to the corresponding power of the base, and thus this representation is also
known as a positional representation. Other base systems were developed through history, and even
non-positional systems, such as the Roman system
(2)
.
When several bases are considered, we better write a number followed by a subscript which
identifies the base. For example, the decimal number 123 can be written as 123
10
, which shall be
interpreted as
N = 123
10
= 110
2
+ 210
1
+ 310
0

giving rise to the familiar positional values of units, tens, hundreds, and so on. The same number
can also be represented in base 2, as the binary number
N = 123
10
= 1111011
2
= 12
6
+ 12
5
+ 12
4
+ 12
3
+ 02
2
+ 12
1
+ 12
0
.
Factoradic Numbers
Now, what is a factoradic number? A factoradic number is also a positional representation
for a number where a different base is used for each digit, but where the place value of the digits is
not proportional to a power of the base, but rather to its factorial value. So, it is a mixed base
system. The conjunction of the term factorial with mixed radix led to this term factoradic,
though other terms are and have been used in the literature
(3)
.
Any number N < n! can be represented by a unique n digit factoradic number, of the form
N
!
= d
n-1
.(n-1)!+d
n-2
.(n-2)!+ +d
2
.2!+d
1
.1!+d
0
.0!
which, in short, we write as
N
!
= (d
n-1
d
n-2
d
2
d
1
d
0
)
!
,
as we do for a number in any ordinary, fixed, base. Notice the use of the subscript '!' to indicate that
the number is in factoradic notation. It should be observed that:
the i-th digit from right to left, i = 0 .. (n-1), is a base-(i +1) digit, such that we shall have
d
i
s i;
the 1
st
digit, that for i = 0, will always be zero, such that it does not effectively contribute to
the total value of the number (and could even be omitted without loss of representation, as
some authors do);
the place value for the i-th digit is i!.
For example, a number that is less than 5! ( = 120
10
) may be expressed as a 5 digits
factoradic number
N
!
= (d
4
d
3
d
2
d
1
d
0
)
!
and, taking, for example, N = 83
10
, then we have
N
!
= 31210
!
= 34! + 13! + 22! +11! + 00!
= 324 + 16 + 22 +11 + 01
= 72 + 6 +4 + 1 + 0
= 83
10
From now on, where not indicated otherwise, we will use numbers without any subscript to
express decimal numbers, such that we will write 31210
!
= 83.
By induction, it can be proved that n! =

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.

Você também pode gostar