Discrete Mathematics 240 (2001) 97–122
www.elsevier.com/locate/disc
Loopless generation of up–down permutations
James F. Korsh
Department of Computer and Information Science, Temple University, CC 300A, Broad and
Montgomery Streets, Philadelphia PA 19122, USA
Received 1 November 1999; revised 3 July 2000; accepted 5 September 2000
Abstract
An up–down permutation P = (p1 ; p2 ; : : : ; pn ) is a permutation of the integers 1 to n which
satis es constraints speci ed by a sequence C = (c1 ; c2 ; : : : ; cn−1 ) of U ’s and D’s of length n − 1.
If ci is U then pi ¡ pi+1 otherwise pi−1 ¿ pi . A loopless algorithm is developed for generating
all the up–down permutations satisfying any sequence C. Ranking and unranking algorithms are
c 2001 Elsevier Science B.V. All rights reserved.
discussed.
1. Introduction
An up–down permutation P = (p1 ; p2 ; : : : ; pn ) is a permutation of the integers
1–n satisfying constraints speci ed by a sequence C = (c1 ; c2 ; : : : ; cn−1 ) of U ’s (ups)
and D’s (downs) of length n − 1. Speci cally, if ci is U then pi ¡ pi+1 otherwise
pi−1 ¿ pi . When C has alternating U ’s and D’s the up–down permutations are called
alternating permutations.
There has been considerable work in counting and in generating up–down or alternating permutations for a given C. Determining how many up–down or alternating
permutations satisfy a given C began as early as 1881 by Andre [1], with the most
recent formulas derived by Szpiro [18]. Bauslaugh and Ruskey [3], Pruesse
and Ruskey [12], and Ruskey [17] developed constant average time generation
algorithms for alternating permutations. Kalvin and Varol [9,10] discussed algorithms
for up–down permutations but these are not constant average time. Roelants van Baronaigien and Ruskey [14] gave the rst constant average time algorithm for all up–down
permutations.
There has been interest in generating constant time (loopless) algorithms for many
combinatorial problems since the paper of Ehrlich [8] but none has been published
E-mail address: korsh@temple.edu (J.F. Korsh).
c 2001 Elsevier Science B.V. All rights reserved.
0012-365X/01/$ - see front matter
PII: S 0 0 1 2 - 3 6 5 X ( 0 0 ) 0 0 3 8 7 - 3
98
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
for up–down permutations. However, Kalvin and Varol [10] showed that the generation of up–down permutations is equivalent to generating all topological sorts (linear
orders) consistent with a partial order determined by the given C. Recently, Can eld
and Williamson [5] presented a loopless algorithm for the generation of all topological sorts. Hence, the application of their algorithm produces a loopless algorithm for
up–down permutations. This algorithm can be implemented so it generates the up–
down permutations directly rather than another representation for them. This is possible because their algorithm uses only transpositions (actually only adjacent transpositions). This algorithm requires n2 storage and generates each up–down permutation
twice.
The partial orders that arise from a given C have special properties and it seems
reasonable that an algorithm tailored to generating all their topological sorts would
be obtainable without using an algorithm that would apply to any partial order. This
leads to the algorithm for up–down permutations given in this paper. This loopless
algorithm requires storage only linear in n and generates each up–down permutation
only once.
2. The representation
Given C, de ne the partial order R on the integers 1 to n as follows:
If ci is U then i R i + 1 otherwise i + 1 R i for 16i6n − 1:
Let T = (t1 ; t2 ; : : : ; tn ) be a topological sort w.r.t. R and take P to be its inverse;
i.e. pi = k if tk = i for 16i6n. As in Kalvin and Varol [10], P is then an up–down
permutation of C and any up–down permutation of C is the inverse of some topological
sort w.r.t. R. For instance, if C = (UDDUUDD) then R can be speci ed by the implied
directed graph of Fig. 1. This may appear to be upside down but is consistent with
the literature.
Two topological sorts w.r.t. R are 14325876 and 45876312. The rst is its own
inverse and the second has 78612543 as its inverse. Both 14325876 and 78612543 are
up–down permutations of C.
The representation used in the loopless algorithm for up–down permutations will be
their inverses. However, their generation will also involve the multi-set permutations
described next.
Fig. 1. R for inverse permutations, C = (UDDUUDD).
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
99
Fig. 2. R′ for multi-set permutations, C = (UDDUUDD):
3. Background
A number of observations can be made directly from Fig. 1. The general form of
the graph corresponding to a given C will always have the same zig-zag structure
although it will start by going up if c1 is D. Moreover, it is always easy to write down
an initial topological sort: 14325876 here. This will always be its own inverse. The
general rule for obtaining this unique initial inverse permutation used in the paper is:
start with the inverse permutation consisting only of the integer 1 and insert integer i
as far to the right as allowed by R for i from 2 to n.
For reasons that will become clear later, the graph will also be labeled as in Fig. 2.
Fig. 2 is now interpreted as the graph for a partial order R′ on a speci c multi-set of
integers determined by C.
To obtain R′ for multi-set permutations from R for inverse permutations: traverse
through nodes 1–n of the zig-zag graph starting with 1, and label the next node with
the same number as the current node, increasing the label of the next node by one
only when its direction changes. This establishes a one–one mapping from the integers
1–n onto the integers of a multi-set determined by C. This mapping, in turn, induces
a one-to-one onto map from the set of inverses of C’s up–down permutations to the
set of multi-set permutations consistent with R′ .
The unique initial multi-set permutation used in the paper corresponds to the unique
initial inverse permutation. The initial inverse permutation is an up–down permutation
of C and is also consistent with R while the initial multi-set permutation is consistent
with R′ .
Thus, to go from Fig. 1 to Fig. 2, the 1’s continue until the direction goes up and
they become 2. The 2 changes to 3 when the direction goes down, etc. Each label of
Fig. 2 corresponds in this way, as already noted, to a unique number of Fig. 1 and
vice versa. Consequently, any of the multi-set permutations satisfying the constraints of
Fig. 2 corresponds to a unique inverse permutation satisfying the constraints of Fig. 1
and vice versa. Thus, 12213443 and 23443211 correspond, respectively, to 14325876
and 45876312. Both 12213443 and 23443211 are multi-set permutations of 11223344
and topological sorts of R′ .
Generating all the multi-set permutations of two 1’s, two 2’s two 3’s and two
4’s consistent with Fig. 2 and outputting the unique corresponding inverse permutation of the integers 1; 2; 3; 4; 5; 6; 7; and 8 is equivalent to generating all up–down
permutations consistent with Fig. 1. To be clear, for C = (UDDUUDD), the two
permutations mentioned are shown below along with their two other corresponding
100
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
Fig. 3. Partial order corresponding to multi-set permutations of 11223344.
permutations:
Two up–down permutations: 14325876, 78612543,
Their inverse permutations: 14325876, 45876312 (topological sorts of R),
Their multi-set permutations: 12213443, 23443211 (topological sorts of R′ ).
All the multi-set permutations of 11223344 can be generated as topological sorts
w.r.t. a partial order speci ed by Fig. 3 as noted in Pruesse and Ruskey [12]. Here a1
and a2 correspond to the rst and second 1’s. Similarly, the b’s, c’s and d’s correspond
to the rst and second 2’s, 3’s and 4’s.
Clearly the multi-set permutations satisfying Fig. 2 ‘almost’ correspond to those
satisfying Fig. 3 except the 2’s must appear before the second 1, the 3’s must appear
after the rst 2 and the 4’s must appear before the second 3.
The general problem dealt with in this paper is the following: Given C, begin with
the initial multi-set permutation and generate all multi-set permutations of R′ using no
more than a xed amount of time between permutations.
The algorithm developed in this paper is a modi cation of the loopless algorithm for
all multi-set permutations of Korsh and Lipschutz [11]. It requires that more information
be kept and must deal with more cases, but is conceptually the same. In Section 4,
the basic recursive algorithm for all multi-set permutations is given followed by a
discussion of its iterative, loopless version. Then the basic recursive algorithm for all
multi-set permutations of R′ is presented followed by a discussion of its iterative,
loopless version. Section 5 contains more implementation details.
The appendix contains a complete C ++ implementation that outputs not only the
multi-set, but also the inverse and up–down permutations.
4. Algorithms for all multi-set permutations and those consistent with R′
First consider the generation of all multi-set permutations. Later the generation of
those consistent with R′ will be dealt with. Let perm = (p1 ; p2 ; : : : ; pn ) be a multi-set
permutation consisting of n items. Each item has a number (i.e. an integer) and items
with the same number are said to be similar. Fig. 4 shows the rst 47 permutations of
1223444 generated by the loopless algorithm in Korsh and Lipschutz [11] that generates
all multi-set permutations.
The recursive algorithm begins with an initial permutation in which each integer is
to the right of all smaller integers. If all are similar only the initial permutation is
generated. Otherwise, the largest similar items, which start at the right, are placed in
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
101
Fig. 4. The rst 47 multi-set permutations of 1223444.
the sub-permutation of smaller items in all distinct ways, ending up at the left. The
next sub-permutation is then recursively generated and the largest similar items, now
at the left, are placed in it in all distinct ways, and end at the right. This shifting
from one end to the other continues until the largest similar items have appeared in
all distinct ways in the last sub-permutation.
As similar items move, they all move in the same direction and maintain their
positions relative to each other. The three 4’s, for instance, move from the right end
to the left end during the rst 35 permutations with the rst 4 always leftmost, the last
4 rightmost and the second 4 in between. If an item is moving left (right), then an
adjacent item on the left (right) is called its downward neighbor. Its other neighbor,
if there is one, is its upward neighbor. An item is mobile if its downward neighbor’s
number is smaller than its number. If a mobile item with a speci c number is moving
left (right), then the moving item is the mobile item similar to it that is farthest to the
right (left). Also note in Fig. 4, that when the moving 4 has upward similar neighbors
as in (4); (7); (10); (13), etc., that those similar items are moved to the left end if they
are not already there.
As the algorithm executes, similar items with the largest number rst sweep to the
left in this fashion. Once the sweep is done, the 3 begins its sweep but takes only one
step (permutation (36)). The 4’s then sweep from the left end to the right end (the rst
few permutations of this sweep are permutations (37) – (46)). The 3 will then take the
next step of its sweep and the 4’s will then sweep from right to left. At some point,
the 3’s will nish their sweep, the 4’s will nish theirs, and the 2’s will begin theirs,
taking one step. Then the 4’s will resume and so on, until all items have nished their
sweeps and the algorithm terminates.
102
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
A leftmost similar item nishes its sweep when it becomes the rst or last item
of the permutation or encounters an item whose value is greater than its own. Each
item similar to it then nishes its sweep when it encounters the item similar to it that
previously nished. Thus, all similar items accumulate after the sweep.
The multi-set permutation is represented as a doubly linked list. By using mobile and
nished lists, the algorithm can be implemented iteratively and looplessly. These lists
are threaded through the permutation and used with other data structures as described
in Korsh and Lipschutz [11] to generate the next permutation in constant time.
As each similar item nishes, its direction is changed, but only the last one to nish
is put on the nished list. When these similar items sweep back, it is the rightmost item
that nishes rst and the leftmost that nishes last. The mobile list initially contains
all mobile items ordered by their number, the largest rst. Whenever an item moves,
all items whose number is larger than its number are removed from the nished list
and placed at the front of the mobile list.
For Fig. 4, the mobile list initially contains the leftmost 4, the 3, and the leftmost 2.
When the 4’s complete their sweep, the rightmost 4 is put at the front of the nished
list. The 3 then moves and that 4 transferred from the nished list to the front of the
mobile list. It is important to note that all larger items have nished their sweeps and
are either at the left or right end of a permutation when the moving item moves.
Now it is time to consider the generation of multi-set permutations consistent with
R′ . The recursive algorithm begins with the initial multi-set permutation of Section 3.
Recall that each similar integer is as far to the right as possible in the sub-permutation
of smaller and similar integers. If all are similar only the initial permutation is generated. Otherwise, the largest similar items, which start ‘rightward’, are placed in
the sub-permutation of smaller items in all distinct ways, and end ‘leftward’. The
next sub-permutation is then recursively generated and the largest similar items, now
‘leftward’, are placed in it in all distinct ways, and end ‘rightward’. This shifting from
one end to the other continues until the largest similar items have appeared in all
distinct ways in the last sub-permutation.
The situation that must be dealt with here di ers from the generation of all multi-set
permutations just considered because a leftmost or rightmost item may be constrained
so that it nishes its sweep before reaching the left or right end of a permutation. This is
why the terms ‘leftward’ and ‘rightward’ were used earlier. Consequently, it ‘interferes’
with the moving item. Adapting the algorithm of Korsh and Lipschutz [11] to this new
problem requires recognizing special cases and dealing with them appropriately. Before
going into these, consider Fig. 5 which shows the graph and multi-set permutations
corresponding to C = (DUDUUD). Those permutations that correspond to special cases
are shown in bold (12; 17; 21; 31; 66; 77; 87; 96; 102; 110; 166; 177).
In the rst six permutations, 5 sweeps across from the right. In permutation (6), the
leftmost 4 must move left to generate the next permutation (7). The 5 then sweeps
back but can only go as far as the rightmost 4 in (12). This 4 must then go left which
it does by ‘pushing’ the 5 before it and interchanging with the downward 2, producing
(13). The 4’s cannot now go farther left because they have encountered the 3. Again,
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
103
Fig. 5. Graph (a) and multi-set permutations (b) when C = (DUDUUD).
the 5 sweeps to the left. In (17), since the 5 and 4 cannot move, the leftmost 3 goes
left ‘pulling’ the 4’s with it and interchanging with the downward 1. The 5 sweeps
back to the right till it encounters the rightmost 4 in (21). At this point the 4’s begin
their sweep back to the right. The rightmost 4 ‘pulls’ the 5 with it and interchanges
with the downward 1.
The next special case occurs in (31). If the 5 is ignored then the situation is similar
to the rightmost 4 moving in (46) of Fig. 4, although now there are only two 4’s.
104
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
However, the 5 is between those 4’s here. Before moving the 4 to the right, its left
neighbor, the other 4, must be sent back to its left ‘end ’; i.e. to the right of 3 where it
was when the 4’s nished their sweep left. This would produce 1341542. To complete
the generation of the next permutation, the mobile 4 must move right which it does
by ‘pulling’ the 5 with it and interchanging with its downward 2. In this case, when
the ‘adjacent multiple’ 4 went back to the 3, the larger 5 stayed with the mobile 4.
The next special case (66) involves the mobile 4 moving left and the adjacent
multiple 4 being sent to its right ‘end ’. This happens to be at the actual right end of
the permutation. Now, however, the larger 5 is sent with that 4, producing 3114254.
The mobile 4 goes left producing (67). These exemplify all special cases.
The algorithm for generating the next multi-set permutation is next perm:
Set p to the rst item on the mobile list.
If p’s item will be blocked after moving then
remove it from the mobile list.
If p’s item has an upward similar item then
insert that item at the front of the mobile list.
If the successor of p’s item is not null then
transfer items whose number is larger than
p’s from the nished list to the mobile list.
If p’s item will be nished after moving then
If p’s item is the last similar item then
insert p’s item at the front of the nished
list, update the successor of p, and set
the start of p to TRUE.
Change p’s direction.
Shift p’s item.
Shift is the step in which the mobile item is actually moved and it must recognize
all the cases.
The two normal cases involve a ‘simple adjacent multiple’ and a ‘move’. The rst
(simple adjacent multiple) occurs when no larger items are between the mobile item
and its adjacent multiples. The second (move left or move right), when the item to be
moved can be interchanged with its adjacent downward neighbor. When dealing with
all multi-set permutations as in Korsh and Lipschutz [11] these are the only cases. Any
adjacent multiples are sent back to the ‘end’ rst and then the mobile item is moved.
The same will be done here.
The special cases are resolved so that the correct next permutation is generated as
though any larger interfering items were not present and then positioning them so, as
they sweep left or right, all permutations are in fact generated. This means they must
start as far right (left) as possible if they are moving left (right). For instance consider
(31) and (66) of Fig. 5. The adjacent 4’s must be recognized and a decision made as
to whether any larger items between them are to go with the 4 being sent to its ‘end’
or to stay in place until the mobile item itself is dealt with. When a larger item is
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
105
an immediate neighbor of the mobile item, it, and others, may need to be ‘pulled left
(right)’ or ‘pushed left (right)’.
It is next perm that must take constant time. This is accomplished by representing
the permutation as a doubly linked list, keeping the items that can move on a linked
list (the mobile list) and keeping those items that have nished their sweep on another
linked list (the nished list). Both the mobile and nished lists are threaded through
the permutation list. Consequently, the shifting of adjacent items of the permutation
can be done in constant time when the rst and last of these items are known. The
same is true for the insertion or deletion of items from the front of the mobile or
nished lists.
The item to be moved is always the rst item on the mobile list, so p is set to
it. Items whose number is larger than p’s will always be adjacent on the nished list
and in order, with the largest numbered item at the front of the nished list. If the
successor of p’s item is not null, it will always point to the last of these items on
the nished list. Hence, transferring these from the nished list to the mobile list can
similarly be done in constant time.
Determining whether an item is blocked, has an upward similar item, is nished,
etc., can be done in constant time when the information needed can be accessed in
constant time. All this information is kept in the items themselves or in arrays and so
can be accessed in constant time. The updating of these items and the arrays is also
done in constant time. Section 5 outlines the implementation and additional details are
in Korsh and Lipschutz [11].
5. The implementation
The multi-set and inverse permutations are represented as a doubly linked list perm.
Each item of the list has number, value, and dir members to hold, respectively, the
integer of the multi-set to which it corresponds (Fig. 2), the integer of the inverse
permutation to which it corresponds (Fig. 1), and its direction. A member w is used
in determining whether or not a ‘pull’ is needed, meaning whether or not larger items
can bunch up behind the moving item. Members lt and rt make perm a two-way
list while next is used to link items on the mobile and nished lists, m and f. Additional members lim, adjr, and adjl are either null or contain pointers, respectively,
to the item that prevents a sweep from proceeding further in its direction, to the
next similar item to the right and to the left. Arrays succ, end, lt most, rt most and
start are used as in Korsh and Lipschutz [11]. The array C holds the U –D input
sequence.
The appendix contains a C + + implementation. Main is self-explanatory.
Initialize rst inputs the U –D sequence then calculates (based on Atkinson [2]) and
outputs the number of permutations. It then initializes perm to the rst permutation, m
to contain all initial mobile items, f to empty, sets the lim, adjr and adjl members,
and the arrays lt most, rt most, start, and succ.
106
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
Next perm implements the algorithm with the shift step being carried out by shift left
or shift right. Blocked, nished, dir done, and adjacent multiple are appropriate modi cations of those in Korsh and Lipschutz [11]. The program outputs three versions of
each permutation.
For C of Fig. 5, m initially consists of items 5; 4; 3; 2, whose corresponding values
are 7; 5; 4; 3, and f is initially null. The lim members of items with value 7; 5; 4 and
3 point, respectively to items 6; 4; 3 and 2. Only items with values 3 and 5 have w
members set to 1.
At completion m is null and f has items 5; 4; 3; 2, whose corresponding values
are 7; 6; 4; 3. The initial multi-set, inverse, and up–down permutations are 1132454,
2143576, and 2143576 — the last permutations are 5134421, 7245631, and 7263451.
6. Ranking
Given a listing of permutations, a permutation’s rank is the number preceding it in
the listing. In this section, an algorithm is developed for determining the rank of a
multi-set permutation, which is also the rank of the corresponding up–down permutation, for the listing generated by the algorithm of Section 4. A formula for the number
of such permutations is also presented.
Consider a permutation of a x’s and b y’s generated by the algorithm of Korsh and
Lipschutz [11]. Let NL (i) and NR (i) represent the number of permutations in which,
respectively, the leftmost y is in position i and the rightmost y is in position i. C(r; n)
is the number of ways to choose r things from n things.
Lemma 1. NL (i) = C(b − 1; a + b − i) for 16i6a + 1 and NR (i) = C(b − 1; i − 1) for
b6i6a + b.
Proof. Assume the b’s start at the right end. The leftmost y will be in position i in
just those permutations involving the rightmost b − 1 y’s moving from the right end to
i − 1. They correspond to the number of ways of choosing the b − 1 places from the
a + b − i places available. This determines NL (i). Since the reverse of each permutation
appears in the listing, NR (i) = NL (a + b − i) for b6i6a + b. This determines NR (i).
Now assume the b’s started at the left end. Since each permutation must still appear
in the list, NL (i) and NR (i) remain the same.
Given C, let CR (k; i) (CL (k; i)) be the number of multi-set permutations involving
only integers 1–k in which the rightmost (leftmost) k appears in position i. From
now on, case (D) obtains when C begins with a D and case (U ) otherwise. Let the
permutations consist of n1 1’s, n2 2’s, etc. From Lemma 1 CR (2; i) = C(n2 − 1; i − 2)
n2 +16i6n1 +n2 (D) and CL (2; i)=C(n2 −1; n1 +n2 −1−i) 16i6n1 (U ). Moreover,
n1 +n2 +···+nk−2
CR (k; i) =
CL (k − 1; j)C(nk − 1; i − j − 1)
j=1
nk + 16i6n1 + n2 + · · · + nk
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
107
and
n1 +n2 +···+nk−1
CL (k; i) =
CR (k − 1; j)C(nk − 1; j − 1 + nk − i)
j=nk−1 +1
16i6n1 + n2 + · · · + nk−1 :
These recurrence relations follow from the de nitions of CR (k; i) and CL (k; i). The use
of these formulas in determining the number of multi-set permutations (up–down permutations) corresponding to C is illustrated for C = (DUDUUD) and C = (UDUDDU ).
These represent the two cases (D) and (U ), respectively. The rst entry of C determines the case; the other entries are not relevant.
Let N (n) be the number of multi-set (up–down) permutations corresponding to ni
i’s, 16i6n. First determining N (n) is demonstrated.
Case (D): C = (DUDUUD)
Here n1 = 2, n2 = 1, n3 = 1, n4 = 2 and n5 = 1.
CR (2; i) = C(0; i − 2) = 1 for 26i63:
CL (3; i) =
3
CR (2; j)C(nk − 1; j − 1 + nk − i) = 1C(0; 2 − i) + 1C(0; 3 − i)
j=2
for 16i63:
So, CL (3; 1) = 2, CL (3; 2) = 2 and CL (3; 3) = 1.
CR (4; i) =
3
CL (3; j)C(nk − 1; i − j − 1) = 2C(1; i − 2) + 2C(1; i–3)
j=1
+1C(1; i − 4) for 36i66:
So, CR (4; 3) = 2, CR (4; 4) = 6, CR (4; 5) = 11 and CR (4; 6) = 16.
CL (5; i) =
6
CR (4; j)C(nk − 1; j − 1 + nk − i) = 2C(0; 3 − i) + 6C(0; 4 − i)
j=3
+ 11C(0; 5 − i) + 16C(0; 6 − i)
for 16i66:
So, CL (5; 1) = 35, CL (5; 2) = 35, CL (5; 3) = 35, CL (5; 4) = 33, CL (5; 5) = 27 and
CL (5; 6) = 16.
Then,
N (5) =
n1 +n
2 +n3 +n4
CL (5; j) = 181:
j=1
Case (U ): C = (UDUDDU )
Again, n1 = 2, n2 = 1, n3 = 1, n4 = 2 and n5 = 1.
CL (2; i) = C(0; 2 − i) = 1 for 16i62:
108
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
CR (3; i) =
2
CL (2; j)C(nk − 1; i − j − 1) = 1C(0; i − 2) + 1C(0; i − 3)
j=1
for 26i64:
So, CR (3; 2) = 1, CR (3; 3) = 2 and CR (3; 4) = 2.
CL (4; i) =
4
CR (3; j)C(nk − 1; j − 1 + nk − i) = 1C(1; 3 − i) + 2C(1; 4 − i)
j=2
+ 2C(1; 5 − i)
for 16i64:
So, CL (4; 1) = 16, CL (4; 2) = 11, CL (4; 3) = 6 and CL (4; 4) = 2.
CR (5; i) =
4
CL (4; j)C(nk − 1; i − j − 1) = 16C(0; i − 2) + 11C(0; i − 3)
j=1
+ 6C(0; i − 4) + 2C(0; i − 5) for 26i67:
So, CR (5; 2) = 16, CR (5; 3) = 27, CR (5; 4) = 33, CR (5; 5) = 35, CR (5; 6) = 35 and
CR (5; 7) = 35.
Then,
N (5) =
n1 +n2 +n
3 +n4 +n5
CR (5; j) = 181:
j=n4 +1
Now determining rank is demonstrated. Let p(n) denote the multi-set permutation
whose rank is to be found and let p(k), 26k6n, denote the multi-set permutation
obtained from p(n) by deleting all integers greater than k. Also, take k(r; t) to be the
position of the rth t in p(t), 16r6nt .
The following lemma will be needed to determine the rank of a permutation in
the listing generated by the algorithm next perm of Section 4. Suppose permutation
p(k) consists of b k’s and a non-k’s. NL; R (i; a; b; p(k)) (NR; R (i; a; b; p(k))) denotes the
number of multi-set permutations that precede p(k) in which the leftmost (rightmost)
k is in position i when the b k’s start at the right end and sweep left. NL; L (i; a; b; p(k))
(NR; L (i; a; b; p(k))) are similarly de ned except the b k’s start at the left end and sweep
right.
Lemma 2.
0 for 16i ¡ k(1; k);
b
C(b − j + 1; a + b − k(j; k)) for i = k(1; k)
NL; R (i; a; b; p(k)) =
j=2
C(b − 1; a + b − i) for k(1; k) + 16i6a + 1:
NR; R (i; a; b; p(k)) =
b
C(b − j; i − k(j; k) − 1)
j=1
for b + k(1; k)6i6a + b + k(1; k − 1):
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
NL; L (i; a; b; p(k)) =
b
C(b − j; k(b − j + 1; k) − i − 1)
109
for 16i6k(b; k) − b:
j=1
NR; L (i; a; b; p(k))
0
for k(b; k) ¡ i6a + b + k(1; k − 1);
b
C(b − j + 1; k(1; k − 1) − 1) for i = k(b; k);
=
j=2
C(b − 1; i − k(1; k − 1) − 1)
for b + k(1; k − 1)6i6k(b; k) − 1:
Proof. Consider NL; R (i; a; b; p(k)). The situation is as follows:
::: k :::
k :::
k :::;
k(1; k) k(2; k) k(b; k)
with the .’s representing the a non-k’s. Clearly NL; R (i; a; b; p(k)) is 0 for 16i ¡ k(1; k).
If i = k(1; k), the b − j + 1 k’s must be chosen from the a + b − k(j; k) positions for
each j between 2 and b. When k(1; k) + 16i6a + 1; the leftmost k is in position i
and the remaining b − 1 k’s can occupy any b − 1 positions chosen from the a + b − i
available positions. The remaining formulas follow by arguments similar to those in
the proof of Lemma 1.
Given C, let CR (r; i; p(k)) (CL (r; i; p(k))); r¿k¿2; be the number of permutations
involving integers 1–r in which the rightmost (leftmost) r appears in position i and
which precede p(k) in the listing generated by the loopless algorithm.
In case (D) and r = k ¿ 2:
k even; CR (k; i; p(k))
NR; L (i; n1 + n2 + · · · + nk−1
−k(1; k − 1); n ; p(k))
if rank p(k − 1) is odd;
k
=
N
(i;
n
+
n
+
·
·
·
+
n
1
2
k−1
R; R
−k(1; k − 1); nk ; p(k))
if rank p(k − 1) is even:
k odd; CR (k; i; p(k))
NL; R (i; k(nk−1 ; k − 1) − 1; nk ; p(k)) if rank p(k − 1) is even;
=
NL; L (i; k(nk−1 ; k − 1) − 1; nk ; p(k)) if rank p(k − 1) is odd:
In case (U) and r = k ¿ 2:
k odd; CR (k; i; p(k))
NR; L (i; n1 + n2 + · · · + nk−1 ;
−k(1; k − 1)nk ; p(k))
if rank p(k − 1) is odd;
=
NR; R (i; n1 + n2 + · · · + nk−1 ;
−k(1; k − 1); nk ; p(k))
if rank p(k − 1) is even:
110
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
k even; CR (k; i; p(k))
NL; R (i; k(nk−1 ; k − 1) − 1; nk ; p(k)) if rank p(k − 1) is even;
=
NL; L (i; k(nk−1 ; k − 1) − 1; nk ; p(k)) if rank p(k − 1) is odd:
If r ¡ k; recurrences like those for CR (k; i) (CL (k; i))
(CR (r; i; p(k))). Finally, the rank of p(n) is given by
govern
CR (r; i; p(k))
rank(p(n))
CR (n; i; p(3)) + · · ·
C
(n;
i;
p(2))
+
R
i
i
CR (n; i; p(n))
n even; case (D)
+
i
n odd; case (U )
=
CL (n; i; p(3)) + · · ·
CL (n; i; p(2)) +
i
i
+
CL (n; i; p(n))
n odd; case (D)
i
n even; case (U ):
These sums represent, respectively, the number of permutations whose sub-permutations
involving 1 and 2 precede p(2); the number of permutations whose sub-permutations
involving integers 1; 2 does not precede p(2) but whose sub-permutations involving 1; 2
and 3 precede p(3); : : : ; the number of permutations whose sub-permutations involving
1; 2; 3; : : : ; n − 1 do not precede p(n − 1) but whose sub-permutations involving integers
1; 2; : : : ; n precede p(n). Or, more loosely, those permutations ‘prior to p(2)’, those
‘not prior to p(2) but prior to p(3)’; : : : ; and those ‘not prior to p(n − 1) but prior to
p(n)’. Finding the rank of a permutation is now illustrated with two examples.
Case (D): C = (DUDUUD). Here n1 = 2; n2 = 1; n3 = 1; n4 = 2 and n5 = 1. For
this case, take the permutation p, whose rank is to be found, to be 1325414. Then
k(1; 1)=1; k(2; 1)=2; p(2)=121; k(1; 2)=2; p(3)=1321; k(1; 3)=2; p(4)=132414;
k(1; 4) = 4; k(2; 4) = 6; p(5) = 1325414 and k(1; 5) = 4.
CR (2; i; p(2)) = NR; R (i; n1 − 1; n2 ; p(2))
n2
=
C(n2 − j; i − k(j; 2) − 1)
j=1
n2 + k(1; 2)6i6n1 − 1 + n2 + k(1; 1)
=
1
C(1 − j; i − k(j; 2) − 1) = C(0; i − 3) = 1 for i = 3:
j=1
CL (3; i; p(2)) =
n
1 +n2
CR (2; j; p(2))C(n3 − 1; j − 1 + n3 − i)
16i6n1 + n2
j=n2 +1
=
3
CR (2; j; p(2))C(0; j − i) = 1C(0; 3 − i)
j=2
So CL (3; 1; p(2)) = 1; CL (3; 2; p(2)) = 1 and CL (3; 3; p(2)) = 1.
16i63:
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
CR (4; i; p(2)) =
n
1 +n2
111
CL (3; j; p(2))C(n4 − 1; i − j − 1)
j=1
n4 + 16i6n1 + n2 + n3 + n4
3
=
CL (3; j; p(2))C(1; i − j − 1) + 1C(1; i − 2) + 1C(1; i − 3)
j=1
+ 1C(1; i − 4) for 36i66:
So CR (4; 3; p(2)) = 1; CR (4; 4; p(2)) = 3; CR (4; 5; p(2)) = 6 and CR (4; 6; p(2)) = 9.
CL (5; i; p(2)) =
n1 +n
2 +n3 +n4
CR (4; j; p(2))C(n5 − 1; j − 1 + n5 − i)
j=n4 +1
16i6n1 + n2 + n3 + n4
6
=
CR (4; j; p(2))C(0; j − i)
j=3
= 1C(0; 3 − i) + 3C(0; 4 − i) + 6C(0; 5 − i) + 9C(0; 6 − i)
16i66:
So CL (5; 1; p(2)) = 19; CL (5; 2; p(2)) = 19; CL (5; 3; p(2)) = 19; CL (5; 4; p(2)) = 18;
CL (5; 5; p(2)) = 15 and CL (5; 6; p(2)) = 9:
Thus, i CL (5; i; p(2)) = 19 + 19 + 19 + 18 + 15 + 9 = 99. In Fig. 5, the rst time
sub-perm p(2) = 121 appears is in the 100th permutation. The rst 99 are ‘prior to
p(2)’.
Now, rank(p(2)) ( i CR (2; i; p(2)) = 1) is odd so the 3’s start at the left. Hence,
CL (3; i; p(3)) = NL; L (i; k(n2 ; 2) − 1; n3 ; p(3))
n3
=
C(n3 − j; k(n3 − j + 1; 3) − i − 1) 16i6k(n3 ; 3) − n3
j=1
= C(0; 1 − i) = 1 for i = 1:
n
1 +n2
CR (4; i; p(3)) =
CL (3; j; p(3))C(n4 − 1; i − j − 1)
j=1
n4 + 16i6n1 + n2 + n3 + n4
3
=
CL (3; j; p(3))C(1; i − j − 1) + 1C(1; i − 2) for 36i66:
j=1
So CR (4; 3; p(3)) = 1; CR (4; 4; p(3)) = 2; CR (4; 5; p(3)) = 3 and CR (4; 6; p(3)) = 4.
CL (5; i; p(3)) =
n1 +n
2 +n3 +n4
CR (4; j; p(3))C(n5 − 1; j − 1 + n5 − i)
j=n4 +1
=
6
j=3
CR (4; j; p(3))C(0; j − i)
112
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
= 1C(0; 3 − i) + 2C(0; 4 − i) + 3C(0; 5 − i) + 4C(0; 6 − i)
16i66:
So CL (5; 1; p(3)) = 10; CL (5; 2; p(3)) = 10; CL (5; 3; p(3)) = 10; CL (5; 4; p(3)) = 9;
CL (5; 5; p(3)) = 7 and CL (5; 6; p(3)) = 4.
Thus, i CL (5; i; p(3)) = 50. In Fig. 5, 50 permutations (100 –149) are ‘not prior to
p(2) but are prior to p(3)’. Since rank of p(3) ( i CL (3; i; p(2)) + i CL (3; i; p(3)) =
3 + 1 = 4) is even, the 4’s start at the right. Consequently,
CR (4; i; p(4)) = NR; R (i; n1 + n2 + n3 − k(1; 3); n4 ; p(4))
n4
=
C(n4 − j; i − k(j; 4) − 1)
j=1
n4 + k(1; 4)6i6n1 + n2 + n3 − k(1; 3) + n4 + k(1; 3)
= C(0; i − 3) 66i66:
So CR (4; 6; p(4)) = 1.
CL (5; i; p(4)) =
n1 +n
2 +n3 +n4
CR (4; j; p(4))C(n5 − 1; j − 1 + n5 − i)
j=n4 +1
=
6
CR (4; j; p(4))C(0; j − i)
j=3
= 1C(0; 6 − i) 16i66:
So CL (5; 1; p(4)) = 1; CL (5; 2; p(4)) = 1; CL (5; 3; p(4)) = 1; CL (5; 4; p(4)) = 1;
CL (5; 5; p(4)) = 1 and CL (5; 6; p(4)) = 1.
(150 –155) are ‘not prior to
Thus,
i CL (5; i; p(4)) = 6. In Fig. 5, 6 permutations
p(3) but prior to p(4)’. Since rank of p(4) ( i CR (4; i; p(2)) + i CR (4; i; p(3)) +
i CR (4; i; p(4)) = 19 + 10 + 1 = 30) is even, the 5 starts at the right.
CL (5; i; p(5)) = NL; R (i; k(n4 ; 4) − 1; n5 ; p(5))
0
16i ¡ k(1; 5);
n5
C(n5 − j + 1; k(n4 ; 4) − 1 + n5 − k(j; 5)) i = k(1; 5);
= j=2
for k(1; 5)
C(n5 − 1; k(n4 ; 4) − 1 + n5 − i)
+16i6k(n4 ; 4) − 1 + 1;
CL (5; i; p(5)) = NL; R (i; k(n4 ; 4) − 1; n5 ; p(5))
0
16i ¡ 4;
1
C(2 − j; 6 − k(j; 5)) i = 4;
=
j=2
C(0; 6 − i)
56i66:
So CL (5; i; p(5)) = 0; 16i64; CL (5; 5; p(5)) = 1 and CL (5; 6; p(5)) = 1. Thus,
i CL (5; i; p(5)) = 2. Permutations 156 and 157 are ‘not prior to p(4) but are prior to
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
113
p(5)’. Rank(p(5)) =
i CL (5; i; p(4)) +
i CL (5; i; p(3)) +
i CL (5; i; p(2)) +
C
(5;
i;
p(5))
=
99
+
50
+
6
+
2
=
157.
L
i
Case (U ): C = (UDUDDU ). Here n1 = 2; n2 = 1; n3 = 1; n4 = 2 and n5 = 1. Let
the permutation p whose rank is to found be 4521143. Then k(1; 1) = 1; k(2; 1) = 2;
p(2)=211; k(1; 2)=1; p(3)=2113; k(1; 3)=4; p(4)=421143; k(1; 4)=1; k(2; 4)=5;
p(5) = 4521143 and k(1; 5) = 2.
CL (2; i; p(2)) = NL; R (i; k(n1 ; 1) − 1; n2 ; p(2))
0
16i ¡ k(1; 2);
n2
C(n2 − j + 1; k(n1 ; 1) − 1
i = k(1; 2);
= j=2
+n2 − k(j; 2))
C(n2 − 1; k(n1 ; 1) − 1 + n2 − i) for k(1; 2) + 16i
6k(n1 ; 1) − 1 + 1;
CL (2; i; p(2)) = NL; R (i; k(n1 ; 1) − 1; n2 ; p(2))
0
16i ¡ 1;
1
C(2 − j; 2 − k(j; 2)) i = 1;
=
j=2
C(0; 2 − i)
26i62:
So CL (2; 2; p(2)) = 1.
CR (3; i; p(2)) =
n1
CL (2; j; p(2))C(n3 − 1; i − j − 1)
j=1
for n3 + 16i6n1 + n2 + n3
2
=
CL (2; j; p(2))C(0; i − j − 1) = 1C(0; i − 3) 26i64:
j=1
So CR (3; 3; p(2)) = 1 and CR (3; 4; p(2)) = 1.
CL (4; i; p(2)) =
n1 +n
2 +n3
CR (3; j; p(2))C(n4 − 1; j − 1 + n4 − i)
j=n3 +1
16i6n1 + n2 + n3
4
=
CR (2; j; p(2))C(1; j + 1 − i)
j=2
= 1C(1; 4 − i) + 1C(1; 5 − i)
16i64:
So CL (4; 1; p(2)) = 7; CL (4; 2; p(2)) = 5; CL (4; 3; p(2)) = 3 and CL (4; 4; p(2)) = 1.
CR (5; i; p(2)) =
n1 +n
2 +n3
CL (4; j; p(2))C(n5 − 1; i − j − 1)
j=1
for n5 + 16i6n1 + n2 + n3 + n4 + n5
114
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
=
4
CL (4; j; p(2))C(0; i − j − 1) 26i67
j=1
= 7C(0; i − 2) + 5C(0; i − 3) + 3C(0; i − 4) + 1C(0; i − 5)
26i67:
So CR (5; 2; p(2)) = 7; CR (5; 3; p(2)) = 12; CR (5; 4; p(2)) = 15; CR (5; 5; p(2)) = 16;
CR (5; 6; p(2)) = 16 and CR (5; 7; p(2)) = 16.
Thus, i CR (5; i; p(2))=7+12+15+16+16+16=82 and the rst 82 permutations
are ‘prior to p(2)’. Rank(p(2)) ( i CL (2; i; p(2)) = 1) is odd so the 3’s start at the
left and
CR (3; i; p(3)) = NR; L (i; n1 + n2 − k(1; 2); n3 ; p(3));
CR (3; i; p(3)) =
CR (3; i; p(3)) =
0;
n3
for k(n3 ; 3) ¡ i6n1 + n2
−k(1; 2) + n3 + k(1; 2)
C(n3 − j + 1; k(1; 2) − 1) for i = k(n3 ; 3);
j=2
for n3 + k(1; 2)6i
C(n3 − 1; i − k(1; 2) − 1)
6k(n3 ; 3) − 1;
0
1
for 4 ¡ i64;
C(2 − j; 0) for i = 4;
j=2
C(0; i)
for 26i63:
So CR (3; 2; p(3)) = 1 and CR (3; 3; p(3)) = 1.
CL (4; i; p(3)) =
n1 +n
2 +n3
CR (3; j; p(3))C(n4 − 1; j − 1 + n4 − i)
j=n3 +1
16i6n1 + n2 + n3
4
=
CR (2; j; p(3))C(1; j + 1 − i) = 1C(1; 3 − i) + 1C(1; 4 − i)
j=2
for 16i64:
So CL (4; 1; p(3)) = 5; CL (4; 2; p(3)) = 3 and CL (4; 3; p(3)) = 1.
CR (5; i; p(3)) =
n1 +n
2 +n3
CL (4; j; p(3))C(n5 − 1; i − j − 1)
j=1
for n5 + 16i6n1 + n2 + n3 + n4 + n5
4
=
CL (4; j; p(3))C(0; i − j − 1) 26i67
j=1
= 5C(0; i − 2) + 3C(0; i − 3) + 1C(0; i − 4) 26i67:
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
115
So CR (5; 2; p(3)) = 5; CR (5; 3; p(3)) = 8; CR (5; 4; p(3)) = 9; CR (5; 5; p(3)) = 9;
CR (5; 6; p(3)) = 9 and CR (5; 7; p(3)) = 9.
Thus, i CR (5; i; p(3)) = 49. There are 49 permutations ‘not prior to p(2) but prior
to p(3)’. Since rank of p(3) ( i CR (3; i; p(2)) + i C(3; i; p(3)) = 2 + 2 = 4) is even,
the 4’s start at the right. Consequently,
CL (4; i; p(4)) = NL; R (i; k(n3 ; 3) − 1; n4 ; p(4))
CL (4; i; p(4)) =
CL (4; i; p(4)) =
0
n4
C(n4 − j + 1; k(n3 ; 3) − 1
for 16i ¡ k(1; 4);
for i = k(1; 4);
j=2
+n4 − k(j; 4))
C(n4 − 1; k(n3 ; 3) − 1 + n4 − i) for k(1; 4) + 1
6i6k(n3 ; 3) − 1 + 1;
0
2
for 16i ¡ 1;
C(3 − j; 5 − k(j; 4)) for i = 1;
j=2
C(1; 5 − i)
for 26i64;
for 16i ¡ 1;
0
CL (4; i; p(4)) = C(1; 0)
for i = 1;
C(1; 5 − i) for 26i64:
So CL (4; 2; p(4)) = 3; CL (4; 3; p(4)) = 2 and CL (4; 3; p(4)) = 1.
CR (5; i; p(4)) =
n1 +n
2 +n3
CL (4; j; p(4))C(n5 − 1; i − j − 1)
j=1
for n5 + 16i6n1 + n2 + n3 + n4 + n5 ;
=
4
CL (4; j; p(4))C(0; i − j − 1) for 26i67;
j=1
= 3C(0; i − 3) + 2C(0; i − 4) + 1C(0; i − 5) for 26i67;
So CR (5; 3; p(4)) = 3; CR (5; 4; p(4)) = 5; CR (5; 5; p(4)) = 6; CR (5; 6; p(4)) = 6 and
CR (5; 7; p(4)) = 6.
Thus, i CR (5; i; p(4)) = 26. There are 26 permutations ‘not prior to p(3) but prior
to p(4)’. Since rank of p(4) ( i CL (4; i; p(2))+ i CL (4; i; p(3))+ i CL (4; i; p(4))=
16 + 9 + 6 = 31) is odd, the 5 starts at the left.
116
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
CR (5; i; p(5)) = NR; L (i; n1 + n2 + n3 + n4 − k(1; 4); n5 ; p(5))
0
for k(n5 ; 5)i6n1 + n2 + n3
+n4 − k(1; 4) + n5 + k(1; 4);
n5
C(n5 − j + 1; k(1; 4) − 1) for i = k(n5 ; 5);
CR (5; i; p(5)) =
j=2
for n5 + k(1; 4)6i
C(n5 − 1; i − k(1; 4) − 1)
6k(n5 ; 5) − 1;
CR (5; i; p(5)) =
0
1
for 2 ¡ i67;
C(2 − j; 0) for i = 1;
j=2
C(0; i)
for 26i60:
So CR (5; i; p(5))s are all 0.
0. No permutations are ‘not prior to p(4) but prior to
Thus,
i CR (5; i; p(5)) =
p(5)’. Finally, rank(p(5)) = i CR (5; i; p(2)) + i CR (5; i; p(3)) + i CR (5; i; p(4)) +
i CR (5; i; p(5)) = 82 + 49 + 26 + 0 = 157.
7. Unranking
Given the rank of a permutation, the unranking problem is to determine the per
mutation itself. To deal with this problem, consider
i CR (2; i; p(2)). The idea here
is to view it as made up of contributions from each k(t; 2); 16t6n2 , denoted by
i CR (2; i; k(t; 2)). As an example, consider case (D) from Section 6 and take the
given rank to be 157. Then
CR (2; i; k(1; 2)) = C(n2 − 1; i − k(1; 2) − 1)
n2 + k(1; 2)6i6n1 − 1 + n2 + k(1; 1)
= C(0; i − k(1; 2) − 1) 1 + k(1; 2)6i63:
So CR (2; 3; 3) = 0 and CR (2; 3; 2) = 1, since there are two possibilities for k(1; 2),
3 and 2.
In the same way, CL (3; i; p(2)); CR (4; i; p(2)) and CL (5; i; p(2)), can be viewed as
made up of contributions from CL (3; i; k(t; 2)); CR (4; i; k(t; 2)) and CL (5; i; k(t; 2)):
CL (3; i; k(1; 2)) =
n
1 +n2
CR (2; j; k(1; 2))C(n3 − 1; j − 1 + n3 − i)
j=n2 +1
=
3
CR (2; j; k(1; 2))C(n3 − 1; j − 1 + n3 − i)
j=2
=
3
j=2
CR (2; j; k(1; 2))C(0; j − i)
16i63;
16i6n1 + n2
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
117
So CL (3; i; 3) = 0 and CL (3; i; 2) = C(0; 3 − i)6i63,
CR (4; i; k(1; 2)) =
n
1 +n2
CL (3; j; k(1; 2))C(n4 − 1; i − j − 1)
j=1
n4 + 16i6n1 + n2 + n3 + n4
3
=
CL (3; j; k(1; 2))C(1; i − j − 1) 36i66:
j=1
So CR (4; i; 3) = 0 and CR (4; i; 2) = 1C(1; i − 2) + 1C(1; i − 3) + 1C(1; i − 4); 36i66
CL (5; i; k(1; 2)) =
n1 +n
2 +n3 +n4
CR (4; j; k(1; 2))C(n5 − 1; j − 1 + n5 − i)
j=n4 +1
16i6n1 + n2 + n3 + n4
6
=
CR (4; j; k(1; 2))C(0; j − i)
16i66:
j=3
So CL (5; i; 3) = 0 and CL (5; i; 2) = 1C(0; 3 − i) + 3C(0; 4 − i) + 6C(0; 5 − i) +
9C(0; 6 − i); 16i66.
Thus, i CL (5; i; k(1; 2)) = 0 when k(1; 2) = 3 and i CL (5; i; k(1; 2)) = 19 + 19 +
19 + 18 + 15 + 9 = 99 when k(1; 2) = 2. Since the 2’s are sweeping left, k(1; 2) will be
the smallest possible value whose i CL (5; i; k(1; 2)) ¡ 157. Because i CL (5; i; 2) =
99 ¡ 157; k(1; 2) has just been determined to be 2 and thus p(2) is known. Its rank,
( i CR (2; i; k(1; 2)) = 1) is odd. Hence the 3’s start at the left and sweep right. Had
there been more 2’s their corresponding k(t; 2) values would have been determined in
this way, for t = 2; : : : ; n2 and p(2)’s rank would be ( i t CR (2; i; k(t; 2)).
The value of k(1; 3) is next determined by the greatest value it can have such that
i CR (5; i; 3) ¡ 157 − 99 = 148. This produces p(3) and its rank. Since the 3’s sweep
right, had there been more 3’s, the k(t; 3)’s would have been determined by nding
k(n3 ; 3) rst and working down to k(1; 3). Similarly for p(4) and p(5).
8. Uncited references
[4,6,7,13,15,16]
Acknowledgements
The author would like to thank the referees for comments that improved the presentation of the material.
118
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
Appendix
# include ¡ iostream:h ¿
#include ¡ stdlib:h ¿
const int MAX = 50; LEFT = 1;
typedef struct listnode {struct listnode ∗ lt; ∗ next; ∗ rt; ∗ lim;∗ adjl;∗ adjr; int num, value, dir, w;
} list node, ∗ list pointer;
list pointer perm, p, q, f, m, t, lend, temp, succ[MAX], end[MAX], lt most[MAX], rt most[MAX];
int n, numperms, dir; char C[MAX]; bool result, start[MAX]; void initialize( ), print msperm(list pointer),
print udinvperm(list pointer), print udperm(list pointer), next perm( ), shift left( ), shift right( );
bool blocked( ), nished( ), adj multiple( ), dir done( );
void main( )
{
initialize( ); numperms = 1; cout ¡ ¡ “ \ t ′′ ¡ ¡ numperms; cout ¡ ¡ “ \ t ′′ ; print msperm(perm);
cout ¡ ¡ “ \ t′′ ; print udinvperm(perm); cout ¡ ¡ “ \ t ′′ ; print udperm(perm); cout ¡ ¡ endl;
while (m! = NULL)
{
next perm( ); numperms + +; cout ¡ ¡ “ \ t ′′ ¡ ¡ numperms; cout ¡ ¡ “ \ t ′′ ; print msperm(perm);
cout ¡ ¡ “ \ t′′ ; print udinvperm(perm); cout ¡ ¡ “ \ t ′′ ; print udperm(perm); cout ¡ ¡ endl;
}
}
void initialize( )
{
cout ¡ ¡ endl ¡ ¡
“Enter the up=down constraints as a sequence of U’s=D’s“ ¡ ¡
“ending with a period.” ¡ ¡ endl;
int i = 0; cin ¿ ¿ C[0]; while (C[i]! = ‘:’) {i + +; cin ¿ ¿ C[i]; }
== Calculate and output # of perms to be generated
n = i; int A[50]; A[0] = 1; int S, k, j;
for (j = 0; j ¡ n; j + +)
{
if (C[j] = =‘U’){S = 0; for (k = 0; k ¡ = j + 1; k + +){i = A[k]; A[k] = S; S = S + i; }}
else {A[j + 1] = 0; for (k = j; k ¿ = 0; k--) {A[k] = A[k] + A[k + 1]; }}
}
S = 0; for (k = 0; k ¡ = n; k + +) S = S + A[k]; cout ¡ ¡” The number generated will be ′′ ¡ ¡ S ¡ ¡ endl;
cout ¡ ¡“ Enter an integer to continue ¡ ¡ endl; cin ¿ ¿ i; perm = new list node; p = perm; p-¿ lt = NULL;
p-¿ num = 1; p-¿ value = 1; p-¿ dir = LEFT; j = 0; k = 1; m = NULL; p-¿ adjl = NULL; p-¿ adjr = NULL;
if (C[0] = =‘U’)
{
lend = p;
while (C[j] = =‘U’)
{
j + +; p-¿ rt = new list node; p-¿ rt-¿ lt = p; p-¿ adjr = p- ¿ rt;
p = p- ¿ rt; p-¿ adjl = p- ¿ lt; p-¿ num = k; p-¿ value = j + 1; p-¿ dir = LEFT;
}
lt most[k] = lend; rt most[k] = p; p-¿ adjr = NULL;
}
else
{
t = p;
while (C[j] = =‘D’)
{
j + +; p-¿ lt = new list node; p-¿ lt- ¿ rt = p; p-¿ adjl = p- ¿ lt; p = p- ¿ lt; p-¿ adjr = p- ¿ rt;
p-¿ rt- ¿ lt- ¿ adjl = p; p-¿ num = k; p-¿ value = j + 1; p-¿ dir = LEFT;
}
lt most[k] = p; rt most[k] = t; p-¿ adjl = NULL; perm = p; p-¿ lt = NULL; p = t;
}
k + +;
while (j ¡ n)
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
119
{
if (C[j] = =‘U’)
{
temp = p;
while (C[j] = =‘U’)
{
j + +; p-¿ rt = new list node; p-¿ rt- ¿ lt = p; p-¿ adjr = p- ¿ rt; p = p- ¿ rt;
p-¿ adjl = p- ¿ lt; p-¿ num = k; p-¿ value = j + 1; p-¿ dir = LEFT; p-¿ lim = NULL;
}
temp-¿ rt- ¿ lim = lt most[k − 1]; temp-¿ rt- ¿ w = 1; lt most[k] = temp- ¿ rt; rt most[k] = p;
temp-¿ rt- ¿ next = m; m = temp- ¿ rt; p-¿ adjr = NULL; temp-¿ adjr = NULL; temp-¿ rt- ¿ adjl = NULL;
}
else
{
temp = p- ¿ lt;
while (C[j] = =‘D’)
{
j + +; p-¿ lt = new list node; p-¿ lt- ¿ rt = p; p-¿ adjl = p- ¿ lt; p = p- ¿ lt; p-¿ adjr = p- ¿ rt;
p-¿ num = k; p-¿ value = j + 1; p-¿ dir = LEFT; p-¿ lim = NULL;
}
temp-¿ rt = p; p-¿ lt = temp; lt most[k] = p; p-¿ next = m; m = p; p-¿ adjl = NULL; p = rt most[k − 1];
rt most[k] = p- ¿ lt; p-¿ lt- ¿ lim = p; p-¿ lt- ¿ w = 0; p-¿ adjl = NULL; rt most[k]-¿ adjr = NULL;
rt most[k]-¿ rt- ¿ adjl = temp;
}
start[k] = true; k + +;
}
p-¿ rt = NULL; f = NULL; rt most[1]-¿ next = NULL; succ[k] = NULL;
}
void print msperm(list pointer perm)
{cout ¡ ¡ perm-¿ num ¡ ¡ “:′′ ; if (perm-¿ rt! = NULL) print msperm(perm-¿ rt); }
void print udinvperm(list pointer perm)
{cout ¡ ¡ perm-¿ value ¡ ¡ “ ′′ ; if (perm-¿ rt! = NULL) print udinvperm(perm-¿ rt); }
void print udperm(list pointer perm)
{
int S[MAX], i = 1;
q = perm; while (q! = NULL){S[q- ¿ value] = i; i + +; q = q- ¿ rt; }
for (i = 1; i ¡ = n + 1; i + +){cout ¡ ¡ S[i] ¡ ¡ “ ′′ ; }
}
void next perm( )
{
p = m; dir = p- ¿ dir; if (blocked( )) {m = p- ¿ next; }
if (adj multiple( ))
{
if(dir = =LEFT){p- ¿ adjr- ¿ next = m; m = p- ¿ adjr; } else {p- ¿ adjl- ¿ next = m; m = p- ¿ adjl; }
}
if (succ[p-¿ num]! = NULL){temp = m; m = f ; f = succ[p- ¿ num]- ¿ next; succ[p-¿ num]-¿ next = temp; }
if ( nished( ))
{
if (dir done( )) {p- ¿ next = f ; f = p; succ[p- ¿ num − 1] = p; start[p- ¿ num] = T; }p- ¿ dir=!dir;
}
if (dir = =LEFT) shift left( ); else shift right( );
}
bool blocked( )
{
if (dir = =LEFT)
{
if (p-¿ lt- ¿ num ¿ p- ¿ num)temp = lt most[p- ¿ num + 1]; else temp = p;
result = ((temp- ¿ lt- ¿ lt = =NULL)||(temp- ¿ lt- ¿ lt- ¿ num ¿ = p- ¿ num)||(temp- ¿ lt- ¿ lt = =p- ¿ lim));
}
120
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
else
{
if (p- ¿ rt-¿ num ¿ p- ¿ num)temp = rt most[p- ¿ num + 1]; else temp = p;
result = ((temp- ¿ rt- ¿ rt = =NULL)||(temp- ¿ rt- ¿ rt- ¿ num ¿ = p- ¿ num)||(temp-rt-rt = =p- ¿ lim));
}
return result;
}
bool nished( )
{
if (dir = =LEFT)
{
if (p-¿ lt- ¿ num ¿ p- ¿ num)temp = lt most[p- ¿ num + 1]; else temp = p;
result = ((temp- ¿ lt- ¿ lt = =NULL)||((temp- ¿ lt- ¿ lt- ¿ num ¿ p- ¿ num)&&((lt most[p-¿ num] = =p)||
(lt most[p-¿ num]- ¿ dir! = dir)))||(temp- ¿ lt- ¿ lt = =p- ¿ lim)||
((temp-¿ lt- ¿ lt- ¿ num = =p- ¿ num)&&(temp-¿ lt- ¿ lt- ¿ dir! = dir)));
}
else
{
if (p-¿ rt- ¿ num ¿ p- ¿ num)temp = rt most[p- ¿ num + 1]; else temp = p;
result = ((temp- ¿ rt- ¿ rt = =NULL)||((temp- ¿ rt- ¿ rt- ¿ num ¿ p- ¿ num)&&((rt most[p- ¿ num] = =p)||
(rt most[p-¿ num]- ¿ dir! = dir)))||(temp- ¿ rt- ¿ rt = =p- ¿ lim)||
((temp-¿ rt- ¿ rt- ¿ num = =p- ¿ num)&&(temp- ¿ rt- ¿ rt- ¿ dir! = dir)));
}
return result;
}
bool adj multiple()
{
return(dir = =LEFT)&&(p- ¿ rt! = NULL)&&((p- ¿ rt- ¿ num = =p- ¿ num)||(rt most[p- ¿ num]! = p))
||(dir! = LEFT)&&(p- ¿ lt! = NULL)&&((p- ¿ lt- ¿ num = =p- ¿ num)||(lt most[p- ¿ num]! = p));
}
bool dir done(){return(dir = =LEFT)&&(rt most[p- ¿ num] = =p)||(dir! = LEFT)&&(lt most[p- ¿ num] = =p); }
void shift left()
{
if (start[p- ¿ num]&&(p = =lt most[p- ¿ num])){end[p- ¿ num] = p- ¿ lt; start[p- ¿ num]=!true; }
if (p- ¿ lt- ¿ lt = =NULL)perm = p;
if ((p- ¿ rt! = NULL)&&(p- ¿ rt- ¿ num = =p- ¿ num)&&(end[p- ¿ num]! = p- ¿ lt))
{==Simple adjacent multiple
if (end[p- ¿ num]- ¿ rt! = NULL)end[p- ¿ num]- ¿ rt- ¿ lt = rt most[p- ¿ num];
temp = p- ¿ rt; p- ¿ rt = rt most[p- ¿ num]- ¿ rt; rt most[p- ¿ num]- ¿ rt = end[p- ¿ num]- ¿ rt;
end[p- ¿ num]- ¿ rt = temp; p- ¿ rt- ¿ lt = p; temp- ¿ lt = end[p- ¿ num];
}
else if ((p- ¿ rt! = NULL)&&(p- ¿ rt- ¿ num ¿ p- ¿ num)&&(rt most[p- ¿ num]! = p)
&&(end[p- ¿ num]! = p- ¿ lt)&&(lt most[p- ¿ num + 1]- ¿ lim! = NULL)&&(lt most[p- ¿ num + 1]- ¿ lim = =p))
{==Leave the larger items and move only adjacent multiples
if (end[p- ¿ num]- ¿ rt! = NULL)end[p- ¿ num]- ¿ rt- ¿ lt = rt most[p- ¿ num];
t = rt most[p- ¿ num + 1]; t- ¿ rt = rt most[p- ¿ num]- ¿ rt; t- ¿ rt- ¿ lt = t;
rt most[p- ¿ num]- ¿ rt = end[p- ¿ num]- ¿ rt; p- ¿ adjr- ¿ lt = end[p- ¿ num]; end[p- ¿ num]- ¿ rt = p- ¿ adjr;
}
else if ((p- ¿ rt! = NULL)&&(p- ¿ rt- ¿ num ¿ p- ¿ num)&&(rt most[p- ¿ num]! = p)
&&(end[p- ¿ num]! = p- ¿ lt)&&(rt most[p- ¿ rt- ¿ num]- ¿ lim = =rt most[p- ¿ num]))
{==Move the larger items with the adjacent multiples
if (end[p- ¿ num]- ¿ rt! = NULL)end[p- ¿ num]- ¿ rt- ¿ lt = rt most[p- ¿ num];
temp = p- ¿ rt; t = rt most[p- ¿ num]- ¿ rt; rt most[p- ¿ num]- ¿ rt = end[p- ¿ num]- ¿ rt; p- ¿ rt = t;
t- ¿ lt = p; end[p- ¿ num]- ¿ rt = temp; temp- ¿ lt = end[p- ¿ num];
}
if ((p- ¿ rt! = NULL)&&(p- ¿ rt- ¿ num ¿ p- ¿ num)&&(lt most[p- ¿ num + 1]- ¿ w))
{==Pull left
if (p- ¿ lt- ¿ lt! = NULL)p- ¿ lt- ¿ lt- ¿ rt = p; temp = p- ¿ lt; p- ¿ lt = temp- ¿ lt;
temp- ¿ rt = rt most[p- ¿ num + 1]- ¿ rt; temp- ¿ rt- ¿ lt = temp;
temp- ¿ lt = rt most[p- ¿ num + 1]; temp- ¿ lt- ¿ rt = temp;
}
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
121
else if (p- ¿ lt- ¿ num ¿ p- ¿ num)
{==Push left
temp = lt most[p- ¿ num + 1]; if (temp- ¿ lt- ¿ lt! = NULL)temp- ¿ lt- ¿ lt- ¿ rt = temp;
temp- ¿ lt- ¿ rt = p- ¿ rt; p- ¿ rt = temp- ¿ lt; if (p- ¿ rt- ¿ rt! = NULL)p- ¿ rt- ¿ rt- ¿ lt = p- ¿ rt;
temp- ¿ lt = p- ¿ rt- ¿ lt; p- ¿ rt- ¿ lt = p;
}
else
{==Move left
if (p- ¿ lt- ¿ lt! = NULL)p- ¿ lt- ¿ lt- ¿ rt = p; p- ¿ lt- ¿ rt = p- ¿ rt; p- ¿ rt = p- ¿ lt;
if (p- ¿ rt- ¿ rt! = NULL)p- ¿ rt- ¿ rt- ¿ lt = p- ¿ rt; p- ¿ lt = p- ¿ rt- ¿ lt; p- ¿ rt- ¿ lt = p;
}
}
void shift right()
{
if ((start[p- ¿ num])&&(p = =rt most[p- ¿ num])){end[p- ¿ num] = p- ¿ rt; start[p- ¿ num]=!true; }
if ((p- ¿ lt! = NULL)&&(p- ¿ lt- ¿ num = =p- ¿ num)&&(end[p- ¿ num]! = p- ¿ rt))
{==Simple adjacent multiple
if (end[p- ¿ num]- ¿ lt! = NULL)end[p- ¿ num]- ¿ lt- ¿ rt = lt most[p- ¿ num];
else perm = lt most[p- ¿ num]; temp = p- ¿ lt; p- ¿ lt = lt most[p- ¿ num]- ¿ lt;
lt most[p- ¿ num]- ¿ lt = end[p- ¿ num]- ¿ lt; end[p- ¿ num]- ¿ lt = temp;
p- ¿ lt- ¿ rt = p; temp- ¿ rt = end[p- ¿ num];
}
else if ((p- ¿ lt! = NULL)&&(p- ¿ lt- ¿ num ¿ p- ¿ num)&&(lt most[p- ¿ num]! = p)
&&(end[p- ¿ num]! = p- ¿ rt)&&(rt most[p- ¿ num + 1]- ¿ lim! = NULL)&&(rt most[p- ¿ num + 1]- ¿ lim = =p))
{==Leave the larger items and move only adjacent multiples
if (end[p- ¿ num]- ¿ lt! = NULL)end[p- ¿ num]- ¿ lt- ¿ rt = lt most[p- ¿ num]; else perm = lt most[p- ¿ num];
t = lt most[p- ¿ num + 1]; t- ¿ lt = lt most[p- ¿ num]- ¿ lt; t- ¿ lt- ¿ rt = t;
lt most[p- ¿ num]- ¿ lt = end[p- ¿ num]- ¿ lt; p- ¿ adjl- ¿ rt = end[p- ¿ num]; end[p- ¿ num]- ¿ lt = p- ¿ adjl;
}
else if ((p- ¿ lt! = NULL)&&(p- ¿ lt- ¿ num ¿ p- ¿ num)&&(lt most[p- ¿ num]! = p)
&&(end[p- ¿ num]! = p- ¿ rt)&&(lt most[p- ¿ lt- ¿ num]- ¿ lim = =lt most[p- ¿ num]))
{==Move the larger items with the adjacent multiples
if (end[p- ¿ num]- ¿ lt! = NULL)end[p- ¿ num]- ¿ lt- ¿ rt = lt most[p- ¿ num];
else perm = lt most[p- ¿ num]; temp = p- ¿ lt; t = lt most[p- ¿ num]- ¿ lt;
lt most[p- ¿ num]- ¿ lt = end[p- ¿ num]- ¿ lt; p- ¿ lt = t; t- ¿ rt = p;
end[p- ¿ num]- ¿ lt = temp; temp- ¿ rt = end[p- ¿ num];
}
if ((p- ¿ lt! = NULL)&&(p- ¿ lt- ¿ num ¿ p- ¿ num)&&(!(lt most[p- ¿ num + 1]- ¿ w)))
{==Pull right
if (p- ¿ rt- ¿ rt! = NULL)p- ¿ rt- ¿ rt- ¿ lt = p;
temp = p- ¿ rt; p- ¿ rt = temp- ¿ rt; temp- ¿ lt = lt most[p- ¿ num + 1]- ¿ lt;
temp- ¿ lt- ¿ rt = temp; temp- ¿ rt = lt most[p- ¿ num + 1]; temp- ¿ rt- ¿ lt = temp;
}
else if (p- ¿ rt- ¿ num ¿ p- ¿ num)
{==Push right
temp = rt most[p- ¿ num + 1]; if (temp- ¿ rt- ¿ rt! = NULL)temp- ¿ rt- ¿ rt- ¿ lt = temp;
temp-¿rt-¿lt = p-¿lt; p-¿lt = temp-¿rt; if (p-¿lt- ¿ lt! = NULL)p-¿lt-¿lt-¿rt = p-¿lt; else perm = p-¿lt;
temp- ¿ rt = p- ¿ lt- ¿ rt; p- ¿ lt- ¿ rt = p;
}
else
{==Move right
temp = p- ¿ rt; if (p- ¿ rt- ¿ rt! = NULL)p- ¿ rt- ¿ rt- ¿ lt = p; p- ¿ rt- ¿ lt = p- ¿ lt; p- ¿ lt = p- ¿ rt;
if (p- ¿ lt- ¿ lt! = NULL)p- ¿ lt- ¿ lt- ¿ rt = p- ¿ lt; else perm = temp; p- ¿ rt = p- ¿ lt- ¿ rt; p- ¿ lt- ¿ rt = p;
}
}
References
[1] D. Andre, Sur les permutations alternees, J. Math. Pures Appl. 7 (1881) 167–184.
122
J.F. Korsh / Discrete Mathematics 240 (2001) 97–122
[2] M.D. Atkinson, On zigzag permutations and comparisons of adjacent elements, Inform. Process. Lett.
21 (1985) 187–189.
[3] B. Bauslaugh, F. Ruskey, Generating alternating permutations lexicographically, BIT 30 (1990) 17–26.
[4] J.R. Bitner, G. Ehrlich, E.M. Reingold, Ecient generation of the binary re ected Gray code and its
applications, Commun. ACM 19 (1976) 517–521.
[5] E.R. Can eld, S.G. Williamson, A loop-free algorithm for generating the linear extensions of a poset,
Order 12 (1995) 57–75.
[6] N. Dershowitz, A simpli ed loop-free algorithm for generating permutations, BIT 15 (1975) 158–164.
[7] G. Ehrlich, Algorithm 466: four combinatorial algorithms, Commun. ACM 16 (1973) 690–691.
[8] G. Ehrlich, Loopless algorithms for generating permutations, combinations, and other combinatorial
objects, J. ACM 20 (1973) 500–513.
[9] D. Kalvin, Y.L. Varol, On the generation of all topological sortings, J. Algorithms 4 (1983) 150–162.
[10] D. Kalvin, Y.L. Varol, On two problems reducible to topological sorting, Comput. J. 27 (1984)
176–177.
[11] J.F. Korsh, S. Lipschutz, Generating multiset permutations in constant time, J. Algorithms 25 (1997)
321–335.
[12] G. Pruesse, F. Ruskey, Generating the linear extensions of certain posets by transpositions, SIAM
J. Discrete Math. 4 (1991) 413–422.
[13] D. Roelants van Baronaigien, A loopless algorithm for generating binary tree sequences, Inform. Process.
Lett. 39 (1991) 189–194.
[14] D. Roelants van Baronaigien, F. Ruskey, Generating permutations with given ups and downs, Discrete
Appl. Math. 36 (1992) 57–65.
[15] D. Roelants van Baronaigien, A multi-stack method for the fast generation of permutations with minimal
length increasing subsequences, Infom. Process. Lett. 69 (1999) 123–126.
[16] F. Ruskey, D. Roelants van Baronaigien, Fast recursive algorithms for generating combinatorial objects,
Congr. Numer. 41 (1984) 53–62.
[17] F. Ruskey, Transposition generation of alternating permutations, Order 6 (1989) 227–233.
[18] G.G. Szpiro, The number of permutations with a given signature, and the expectations of their elements,
Discrete Math. 226 (2001) 423–430.