You are on page 1of 6

A Tutorial on Generating Permutations using Factoradic Number Representation

Prof. Joel G. Silva Filho Instituto de Educação Superior de Brasília - 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, = ((0),(1), … , ( n -

1)), where ( 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, 2 = {0,2,1,3} - we will explain the subscript '2' later, where 2 (0) = 0, 2 (1) = 2, 2 (2) = 1 and 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), 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,

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) .

digit being in the range [0

, ( n -1) - for a n digit number - are the digits of the number representation, each

( b -1)]. For a base 10 representation the digits are in the range [0

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 = 1 2 + 2 1 + 3 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 = 1 6 + 1 5 + 1 4 + 1 3 + 0 2 + 1 1 + 1 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:

( n -1), is a base-( i +1) digit, such that we shall have

the i-th digit from right to left, i = 0

d i 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.

n 1

By induction, it can be proved that n ! = ii ! + 1 . For example, the largest factoradic

i = 0

number of 5 digits ( n = 5) is 43210 ! , which has as next value (43210 ! +1) = 100000 ! . In other words, 44!+3!+2!+1!+! = 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

= 1 + 5

5

= 2 + 1

1

= 1 + 0

0

= 0 + 0

Inversions Consider a set of n = 5 elements, represented by Z 5 = {0,1,2,3,4} and let us label the

which represents the identity permutation, as the order of the original set has not changed. Another permutation could be 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 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() = [ l 0 (), l 1 (), … , l n-1 ()], where

l i () = |{ j > i: ( i) > ( 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

!

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 = 0 = {0,1,2,3,4}. Let us assume now that we want to identify 51 . Considering that N = 51 =

20110 ! , then we can write L(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 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 0 , or else, 51 (0) = 0 ( l 0 ) = 0 (2) = 2. Now, we remove this element from the original set (it has already been used in 51 ), getting 0 ' = {0,1,3,4}, and consider the next element of L, l 1 = 0. The same process applies now to 0 ', giving 51 (1) = 0 '( l 1 ) = 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 51 :

Table 2: Constructing permutation 51 (n =5) from its Lehmer Code.

i

l

i

Lehmer Code

Set S (0 )

Perm 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 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)!,

1!, 0!]. We have limited 'n' to 12, as this is just a demo program and 12! fits into a 32-bit CPU word. *)

,2!,

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('

writeln('

writeln('

writeln('

writeln;

halt(1);

end;

> nextperm <N> <n>'); where'); - N is a decimal index to a lexicographically permuted set'); - n is the order of the set to be permuted');

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)

ShowFac('Factoradic('+inttostr(D)+') = ',n,Factoradic);

= ',n,S);

// 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)+')

writeln;

= ',n,Perm);

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]

= [2,0,3,4,1]

Perm(51)

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.