1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/// Computes lexicographically next smallest permutation.
///
/// This is done by finding a the longest decreasing suffix of the given slice, and replacing the preceding element by
/// the next smallest element of the suffix.
///
/// # Examples
/// All permutations of a list can be iterated as follows:
/// ```
/// # use comlib_math::next_permutation;
/// let mut list = [1, 3, 2, 4, 2];
/// list.sort();
/// # let mut permutation_count = 0;
/// loop {
///     // Do something with list
/// #   permutation_count += 1;
///
///     if !next_permutation(&mut list) {
///         break;
///     }
/// }
/// # assert_eq!(permutation_count, 60);
/// ```
pub fn next_permutation<T>(data: &mut [T]) -> bool
where
    T: Ord,
{
    // Empty one one-element lists have already visited all of their permutations
    if data.len() <= 1 {
        return false;
    }

    // Iterate from the back until we find two consecutive elements which are not in decreasing order
    let mut i = data.len() - 1;
    while i > 0 && data[i - 1] >= data[i] {
        i -= 1;
    }

    if i == 0 {
        // All permutations done
        data.reverse();
        return false;
    }

    // We have found a decreasing suffix of data. To turn that into the lexicographically next smallest slice, we need
    // to increase the element preceding by as little as possible. This can be done by finding the smallest element in
    // the suffix that is larger than the preceding element, swapping those elements, and finally reversing the suffix.
    for j in (0..data.len()).rev() {
        if data[i - 1] < data[j] {
            data.swap(i - 1, j);
            data[i..].reverse();
            return true;
        }
    }

    unreachable!("The comparison operator must be wrong. At least j == i-1 should have matched.");
}

// TODO: prev_permutation