| 1 | #include "slalib.h" | 
|---|
| 2 | #include "slamac.h" | 
|---|
| 3 | void slaCombn  ( int nsel, int ncand, int list[], int* j ) | 
|---|
| 4 | /* | 
|---|
| 5 | **  - - - - - - - - - | 
|---|
| 6 | **   s l a C o m b n | 
|---|
| 7 | **  - - - - - - - - - | 
|---|
| 8 | ** | 
|---|
| 9 | **  Generate the next combination, a subset of a specified size chosen | 
|---|
| 10 | **  from a specified number of items. | 
|---|
| 11 | ** | 
|---|
| 12 | **  Given: | 
|---|
| 13 | **     nsel    int        number of items (subset size) | 
|---|
| 14 | **     ncand   int        number of candidates (set size) | 
|---|
| 15 | ** | 
|---|
| 16 | **  Given and Returned: | 
|---|
| 17 | **     list    int[nsel]  latest combination, list[0]=0 to initialize | 
|---|
| 18 | ** | 
|---|
| 19 | **  Returned: | 
|---|
| 20 | **     *j      int        status: -1 = illegal nsel or ncand | 
|---|
| 21 | **                                 0 = OK | 
|---|
| 22 | **                                +1 = no more combinations available | 
|---|
| 23 | ** | 
|---|
| 24 | **  Notes: | 
|---|
| 25 | ** | 
|---|
| 26 | **  1) nsel and ncand must both be at least 1, and nsel must be less | 
|---|
| 27 | **     than or equal to ncand. | 
|---|
| 28 | ** | 
|---|
| 29 | **  2) This routine returns, in the list array, a subset of nsel integers | 
|---|
| 30 | **     chosen from the range 1 to ncand inclusive, in ascending order. | 
|---|
| 31 | **     Before calling the routine for the first time, the caller must set | 
|---|
| 32 | **     the first element of the list array to zero (any value less than 1 | 
|---|
| 33 | **     will do) to cause initialization. | 
|---|
| 34 | ** | 
|---|
| 35 | **  2) The first combination to be generated is: | 
|---|
| 36 | ** | 
|---|
| 37 | **        list[0]=1, list[1]=2, ..., list[nsel-1]=nsel | 
|---|
| 38 | ** | 
|---|
| 39 | **     This is also the combination returned for the "finished" (j=1) | 
|---|
| 40 | **     case. | 
|---|
| 41 | ** | 
|---|
| 42 | **     The final permutation to be generated is: | 
|---|
| 43 | ** | 
|---|
| 44 | **        list[0]=ncand, list[1]=ncand-1, ..., list[nsel-1]=ncand-nsel+1 | 
|---|
| 45 | ** | 
|---|
| 46 | **  3) If the "finished" (j=1) status is ignored, the routine | 
|---|
| 47 | **     continues to deliver combinations, the pattern repeating | 
|---|
| 48 | **     every ncand!/(nsel!*(ncand-nsel)!) calls. | 
|---|
| 49 | ** | 
|---|
| 50 | **  4) The algorithm is by R.F.Warren-Smith (private communication). | 
|---|
| 51 | ** | 
|---|
| 52 | **  Last revision:   25 August 1999 | 
|---|
| 53 | ** | 
|---|
| 54 | **  Copyright P.T.Wallace.  All rights reserved. | 
|---|
| 55 | */ | 
|---|
| 56 | { | 
|---|
| 57 | int i, more, nmax, m; | 
|---|
| 58 |  | 
|---|
| 59 |  | 
|---|
| 60 | /* Validate, and set status. */ | 
|---|
| 61 | if ( nsel < 1 || ncand < 1 || nsel > ncand ) { | 
|---|
| 62 | *j = -1; | 
|---|
| 63 | return; | 
|---|
| 64 | } else { | 
|---|
| 65 | *j = 0; | 
|---|
| 66 | } | 
|---|
| 67 |  | 
|---|
| 68 | /* Just starting? */ | 
|---|
| 69 | if ( list[0] < 1 ) { | 
|---|
| 70 |  | 
|---|
| 71 | /* Yes: return 1,2,3... */ | 
|---|
| 72 | for ( i = 0; i < nsel; i++ ) { | 
|---|
| 73 | list[i] = i+1; | 
|---|
| 74 | } | 
|---|
| 75 |  | 
|---|
| 76 | } else { | 
|---|
| 77 |  | 
|---|
| 78 | /* No: find the first selection that we can increment. */ | 
|---|
| 79 |  | 
|---|
| 80 | /* Start with the first list item. */ | 
|---|
| 81 | i = 0; | 
|---|
| 82 |  | 
|---|
| 83 | /* Loop. */ | 
|---|
| 84 | more = 1; | 
|---|
| 85 | while ( more ) { | 
|---|
| 86 |  | 
|---|
| 87 | /* Is this the final list item? */ | 
|---|
| 88 | if ( i == nsel-1 ) { | 
|---|
| 89 |  | 
|---|
| 90 | /* Yes:  comparison value is number of candidates plus one. */ | 
|---|
| 91 | nmax = ncand+1; | 
|---|
| 92 |  | 
|---|
| 93 | } else { | 
|---|
| 94 |  | 
|---|
| 95 | /* No:  comparison value is next list item. */ | 
|---|
| 96 | nmax = list[i+1]; | 
|---|
| 97 | } | 
|---|
| 98 |  | 
|---|
| 99 | /* Can the current item be incremented? */ | 
|---|
| 100 | if ( nmax - list[i] > 1 ) { | 
|---|
| 101 |  | 
|---|
| 102 | /* Yes:  increment it. */ | 
|---|
| 103 | list[i]++; | 
|---|
| 104 |  | 
|---|
| 105 | /* Reinitialize the preceding items. */ | 
|---|
| 106 | for ( m = 0; m < i; m++ ) { | 
|---|
| 107 | list[m] = m+1; | 
|---|
| 108 | } | 
|---|
| 109 |  | 
|---|
| 110 | /* Quit the loop. */ | 
|---|
| 111 | more = 0; | 
|---|
| 112 |  | 
|---|
| 113 | } else { | 
|---|
| 114 |  | 
|---|
| 115 | /* Can't increment the current item:  is it the final one? */ | 
|---|
| 116 | if ( i == nsel-1 ) { | 
|---|
| 117 |  | 
|---|
| 118 | /* Yes:  set the status. */ | 
|---|
| 119 | *j = 1; | 
|---|
| 120 |  | 
|---|
| 121 | /* Restart the sequence. */ | 
|---|
| 122 | for ( i = 0; i < nsel; i++ ) { | 
|---|
| 123 | list[i] = i+1; | 
|---|
| 124 | } | 
|---|
| 125 |  | 
|---|
| 126 | /* Quit the loop. */ | 
|---|
| 127 | more = 0; | 
|---|
| 128 |  | 
|---|
| 129 | } else { | 
|---|
| 130 |  | 
|---|
| 131 | /* No:  next list item. */ | 
|---|
| 132 | i++; | 
|---|
| 133 | } | 
|---|
| 134 | } | 
|---|
| 135 | } | 
|---|
| 136 | } | 
|---|
| 137 | } | 
|---|