Skip to content

Add next_permutation and prev_permutation onto MutableTotalOrdVector<T>. #13761

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

Closed
wants to merge 1 commit into from
Closed
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
160 changes: 160 additions & 0 deletions src/libstd/slice.rs
Original file line number Diff line number Diff line change
@@ -1838,12 +1838,103 @@ pub trait MutableTotalOrdVector<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 mut 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 mut 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: TotalOrd> MutableTotalOrdVector<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
}
}

/**
@@ -3690,6 +3781,75 @@ mod tests {
let y: &mut [int] = [];
assert!(y.mut_last().is_none());
}

#[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_lexicographic_permutations_owned() {
let mut empty : ~[int] = ~[];
assert!(empty.prev_permutation() == false);
assert!(empty.next_permutation() == false);
assert_eq!(empty, ~[]);

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

#[cfg(test)]