auto merge of #14623 : exscape/rust-fork/master, r=alexcrichton
Unlike ImmutableClonableVector::permutations() which returns an iterator, cloning the entire array each iteration, these methods mutate the vector in-place. For that reason, these methods are much faster; between 35-55 times faster, depending on the benchmark. They also generate permutations in lexicographical order.
This commit is contained in:
commit
7645982efc
|
@ -712,6 +712,36 @@ pub trait MutableOrdVector<T> {
|
||||||
/// assert!(v == [-5, -3, 1, 2, 4]);
|
/// assert!(v == [-5, -3, 1, 2, 4]);
|
||||||
/// ```
|
/// ```
|
||||||
fn sort(self);
|
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] {
|
impl<'a, T: Ord> MutableOrdVector<T> for &'a mut [T] {
|
||||||
|
@ -719,6 +749,66 @@ impl<'a, T: Ord> MutableOrdVector<T> for &'a mut [T] {
|
||||||
fn sort(self) {
|
fn sort(self) {
|
||||||
self.sort_by(|a,b| a.cmp(b))
|
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
|
/// Unsafe operations
|
||||||
|
@ -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]
|
#[test]
|
||||||
fn test_position_elem() {
|
fn test_position_elem() {
|
||||||
assert!([].position_elem(&1).is_none());
|
assert!([].position_elem(&1).is_none());
|
||||||
|
|
Loading…
Reference in New Issue