jabba_lib/
jpermutation.rs

1//! # permutation
2//!
3//! Generate the lexicographically next permutation of a sequence
4//! of elements.
5//!
6//! Pseudo-code:
7//!
8//! 1. Find the largest index `k` such that `a[k] < a[k + 1]`.
9//!    If no such index exists, the permutation is the last permutation.
10//! 2. Find the largest index `l` such that `a[k] < a[l]`.
11//!    Since `k + 1` is such an index, `l` is well-defined and satisfies `k < l`.
12//! 3. Swap `a[k]` with `a[l]`.
13//! 4. Reverse the sequence from `a[k + 1]` up to end including the final element.
14
15/// Generates the lexicographically next permutation of an array / vector.
16///
17/// Returns `false` if the permutation is the last permutation.
18///
19/// The sequence is modified in place.
20///
21/// # Examples
22///
23/// ```
24/// let mut v = ['a', 'b', 'c'];
25///
26/// jabba_lib::jpermutation::lexicographically_next_permutation(&mut v);
27/// assert_eq!(v, ['a', 'c', 'b']);
28/// jabba_lib::jpermutation::lexicographically_next_permutation(&mut v);
29/// assert_eq!(v, ['b', 'a', 'c']);
30/// jabba_lib::jpermutation::lexicographically_next_permutation(&mut v);
31/// assert_eq!(v, ['b', 'c', 'a']);
32pub fn lexicographically_next_permutation<T: PartialOrd + Copy>(a: &mut [T]) -> bool {
33    let mut i = a.len() - 2;
34    loop {
35        if a[i] < a[i + 1] {
36            break;
37        }
38        if i == 0 {
39            return false;
40        }
41        i -= 1;
42    }
43    // else, if a[i] < a[i + 1]
44    let mut j = a.len() - 1;
45    while !(a[j] > a[i]) {
46        j -= 1;
47    }
48    (a[i], a[j]) = (a[j], a[i]); // swap
49    reverse(a, i + 1, a.len() - 1); // reverse the elements from position i+1 until the end
50    true
51}
52
53/**********
54  private
55***********/
56
57fn reverse<T: Copy>(a: &mut [T], i: usize, j: usize) {
58    let mut i = i;
59    let mut j = j;
60    while i < j {
61        (a[i], a[j]) = (a[j], a[i]); // swap
62                                     //
63        i += 1;
64        j -= 1;
65    }
66}
67
68// ==========================================================================
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    use lexicographically_next_permutation as next_perm;
75
76    #[test]
77    fn lexicographically_next_permutation_test1() {
78        let mut v = ['a', 'b', 'c'];
79        next_perm(&mut v);
80        assert_eq!(v, ['a', 'c', 'b']);
81        next_perm(&mut v);
82        assert_eq!(v, ['b', 'a', 'c']);
83        next_perm(&mut v);
84        assert_eq!(v, ['b', 'c', 'a']);
85        next_perm(&mut v);
86        assert_eq!(v, ['c', 'a', 'b']);
87        next_perm(&mut v);
88        assert_eq!(v, ['c', 'b', 'a']);
89        let status = next_perm(&mut v);
90        assert_eq!(status, false);
91    }
92
93    #[test]
94    fn lexicographically_next_permutation_test2() {
95        let mut v = vec!['C', 'A', 'D', 'B'];
96        next_perm(&mut v);
97        assert_eq!(v, vec!['C', 'B', 'A', 'D']);
98        //
99        let mut v = [1, 2, 9, 6, 5];
100        next_perm(&mut v);
101        assert_eq!(v, [1, 5, 2, 6, 9]);
102    }
103}