Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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.