Skip to content

Add next_permutation and prev_permutation onto MutableOrdVector<T>. #14623

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 4, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions src/libstd/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,13 +712,103 @@ pub trait MutableOrdVector<T> {
/// assert!(v == [-5, -3, 1, 2, 4]);
/// ```
fn sort(self);

/// Mutates the slice to the next lexicographic permutation.
///
/// Returns `true` if successful, `false` if the slice is at the last-ordered permutation.
///
/// # Example
///
/// ```rust
/// let v = &mut [0, 1, 2];
/// v.next_permutation();
/// assert_eq!(v, &mut [0, 2, 1]);
/// v.next_permutation();
/// assert_eq!(v, &mut [1, 0, 2]);
/// ```
fn next_permutation(self) -> bool;

/// Mutates the slice to the previous lexicographic permutation.
///
/// Returns `true` if successful, `false` if the slice is at the first-ordered permutation.
///
/// # Example
///
/// ```rust
/// let v = &mut [1, 0, 2];
/// v.prev_permutation();
/// assert_eq!(v, &mut [0, 2, 1]);
/// v.prev_permutation();
/// assert_eq!(v, &mut [0, 1, 2]);
/// ```
fn prev_permutation(self) -> bool;
}

impl<'a, T: Ord> MutableOrdVector<T> for &'a mut [T] {
#[inline]
fn sort(self) {
self.sort_by(|a,b| a.cmp(b))
}

fn next_permutation(self) -> bool {
// These cases only have 1 permutation each, so we can't do anything.
if self.len() < 2 { return false; }

// Step 1: Identify the longest, rightmost weakly decreasing part of the vector
let mut i = self.len() - 1;
while i > 0 && self[i-1] >= self[i] {
i -= 1;
}

// If that is the entire vector, this is the last-ordered permutation.
if i == 0 {
return false;
}

// Step 2: Find the rightmost element larger than the pivot (i-1)
let mut j = self.len() - 1;
while j >= i && self[j] <= self[i-1] {
j -= 1;
}

// Step 3: Swap that element with the pivot
self.swap(j, i-1);

// Step 4: Reverse the (previously) weakly decreasing part
self.mut_slice_from(i).reverse();

true
}

fn prev_permutation(self) -> bool {
// These cases only have 1 permutation each, so we can't do anything.
if self.len() < 2 { return false; }

// Step 1: Identify the longest, rightmost weakly increasing part of the vector
let mut i = self.len() - 1;
while i > 0 && self[i-1] <= self[i] {
i -= 1;
}

// If that is the entire vector, this is the first-ordered permutation.
if i == 0 {
return false;
}

// Step 2: Reverse the weakly increasing part
self.mut_slice_from(i).reverse();

// Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
let mut j = self.len() - 1;
while j >= i && self[j-1] < self[i-1] {
j -= 1;
}

// Step 4: Swap that element with the pivot
self.swap(i-1, j);

true
}
}

/// Unsafe operations
Expand Down Expand Up @@ -1229,6 +1319,58 @@ mod tests {
}
}

#[test]
fn test_lexicographic_permutations() {
let v : &mut[int] = &mut[1, 2, 3, 4, 5];
assert!(v.prev_permutation() == false);
assert!(v.next_permutation());
assert_eq!(v, &mut[1, 2, 3, 5, 4]);
assert!(v.prev_permutation());
assert_eq!(v, &mut[1, 2, 3, 4, 5]);
assert!(v.next_permutation());
assert!(v.next_permutation());
assert_eq!(v, &mut[1, 2, 4, 3, 5]);
assert!(v.next_permutation());
assert_eq!(v, &mut[1, 2, 4, 5, 3]);

let v : &mut[int] = &mut[1, 0, 0, 0];
assert!(v.next_permutation() == false);
assert!(v.prev_permutation());
assert_eq!(v, &mut[0, 1, 0, 0]);
assert!(v.prev_permutation());
assert_eq!(v, &mut[0, 0, 1, 0]);
assert!(v.prev_permutation());
assert_eq!(v, &mut[0, 0, 0, 1]);
assert!(v.prev_permutation() == false);
}

#[test]
fn test_lexicographic_permutations_empty_and_short() {
let empty : &mut[int] = &mut[];
assert!(empty.next_permutation() == false);
assert_eq!(empty, &mut[]);
assert!(empty.prev_permutation() == false);
assert_eq!(empty, &mut[]);

let one_elem : &mut[int] = &mut[4];
assert!(one_elem.prev_permutation() == false);
assert_eq!(one_elem, &mut[4]);
assert!(one_elem.next_permutation() == false);
assert_eq!(one_elem, &mut[4]);

let two_elem : &mut[int] = &mut[1, 2];
assert!(two_elem.prev_permutation() == false);
assert_eq!(two_elem, &mut[1, 2]);
assert!(two_elem.next_permutation());
assert_eq!(two_elem, &mut[2, 1]);
assert!(two_elem.next_permutation() == false);
assert_eq!(two_elem, &mut[2, 1]);
assert!(two_elem.prev_permutation());
assert_eq!(two_elem, &mut[1, 2]);
assert!(two_elem.prev_permutation() == false);
assert_eq!(two_elem, &mut[1, 2]);
}

#[test]
fn test_position_elem() {
assert!([].position_elem(&1).is_none());
Expand Down