diff options
author | Dave Beckett <dave@dajobe.org> | 2011-11-27 09:30:25 -0800 |
---|---|---|
committer | Dave Beckett <dave@dajobe.org> | 2011-11-27 09:30:25 -0800 |
commit | 8bc6b7fc14c08a918588bd03eaf427e455aaacf8 (patch) | |
tree | 01325c3c0f700f60906b035f72489156bf022e2d /src | |
parent | 02805ce5e6221314bad9fb997a57cca9183cc6f1 (diff) | |
download | raptor-8bc6b7fc14c08a918588bd03eaf427e455aaacf8.tar.gz |
(raptor_sequence_next_permutation): Added based on int permute code
(raptor_sequence_next_permutation# with '#' will be ignored, and an empty message aborts the commit.
Diffstat (limited to 'src')
-rw-r--r-- | src/raptor2.h.in | 4 | ||||
-rw-r--r-- | src/raptor_sequence.c | 72 |
2 files changed, 75 insertions, 1 deletions
diff --git a/src/raptor2.h.in b/src/raptor2.h.in index c87796f6..c10250b6 100644 --- a/src/raptor2.h.in +++ b/src/raptor2.h.in @@ -1522,7 +1522,9 @@ RAPTOR_API int raptor_sequence_swap(raptor_sequence* seq, int i, int j); RAPTOR_API int raptor_sequence_reverse(raptor_sequence* seq, int start_index, int length); - +RAPTOR_API +int raptor_sequence_next_permutation(raptor_sequence *seq, raptor_data_compare_handler compare); + /* helper for printing sequences of strings */ RAPTOR_API int raptor_sequence_print(raptor_sequence* seq, FILE* fh); diff --git a/src/raptor_sequence.c b/src/raptor_sequence.c index a1921256..4fd6678a 100644 --- a/src/raptor_sequence.c +++ b/src/raptor_sequence.c @@ -663,6 +663,78 @@ raptor_sequence_reverse(raptor_sequence* seq, int start_index, int length) return 0; } + +/** + * raptor_sequence_next_permutation: + * @seq: int seq + * @compare: comparison function + * + * Get the next permutation of a sequence in lexicographic order + * + * Assumes the initial order of the items is lexicographically + * increasing. This function alters the order of the items until the + * last permuatation is done at which point the contents is reset to + * the intial order. + * + * Algorithm used is described in + * <http://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order> + * + * The comparison function @compare is compatible with that used for + * qsort() and provides the addresses of pointers to the data that + * must be dereferenced to get to the stored sequence data. + * + * Return value: non-0 at the last permutation + */ +RAPTOR_EXTERN_C +int +raptor_sequence_next_permutation(raptor_sequence *seq, + raptor_data_compare_handler compare) +{ + int k; + int l; + void* temp; + + if(seq->size < 2) + return 1; + + /* 1. Find the largest index k such that a[k] < a[k + 1]. If no such + * index exists, the permutation is the last permutation. + */ + k = seq->size - 2; + while(k >= 0 && compare(seq->sequence[k], seq->sequence[k + 1]) >= 0) + k--; + + if(k == -1) { + /* done - reset to starting order */ + raptor_sequence_reverse(seq, 0, seq->size); + return 1; + } + + /* 2. Find the largest index l such that a[k] < a[l]. Since k + 1 + * is such an index, l is well defined and satisfies k < l. + */ + l = seq->size - 1; + while( compare(seq->sequence[k], seq->sequence[l]) >= 0) + l--; + + /* 3. Swap a[k] with a[l]. */ +#if 1 + temp = seq->sequence[k]; + seq->sequence[k] = seq->sequence[l]; + seq->sequence[l] = temp; +#else + raptor_sequence_swap(seq, k, l); +#endif + + /* 4. Reverse the sequence from a[k + 1] up to and including the + * final element a[n]. + */ + raptor_sequence_reverse(seq, k + 1, seq->size - (k + 1)); + + return 0; +} + + #endif |