Skip to content

Commit 7645982

Browse files
committed
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.
2 parents a6401b5 + 3b5d6fd commit 7645982

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

src/libstd/slice.rs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,13 +712,103 @@ pub trait MutableOrdVector<T> {
712712
/// assert!(v == [-5, -3, 1, 2, 4]);
713713
/// ```
714714
fn sort(self);
715+
716+
/// Mutates the slice to the next lexicographic permutation.
717+
///
718+
/// Returns `true` if successful, `false` if the slice is at the last-ordered permutation.
719+
///
720+
/// # Example
721+
///
722+
/// ```rust
723+
/// let v = &mut [0, 1, 2];
724+
/// v.next_permutation();
725+
/// assert_eq!(v, &mut [0, 2, 1]);
726+
/// v.next_permutation();
727+
/// assert_eq!(v, &mut [1, 0, 2]);
728+
/// ```
729+
fn next_permutation(self) -> bool;
730+
731+
/// Mutates the slice to the previous lexicographic permutation.
732+
///
733+
/// Returns `true` if successful, `false` if the slice is at the first-ordered permutation.
734+
///
735+
/// # Example
736+
///
737+
/// ```rust
738+
/// let v = &mut [1, 0, 2];
739+
/// v.prev_permutation();
740+
/// assert_eq!(v, &mut [0, 2, 1]);
741+
/// v.prev_permutation();
742+
/// assert_eq!(v, &mut [0, 1, 2]);
743+
/// ```
744+
fn prev_permutation(self) -> bool;
715745
}
716746

717747
impl<'a, T: Ord> MutableOrdVector<T> for &'a mut [T] {
718748
#[inline]
719749
fn sort(self) {
720750
self.sort_by(|a,b| a.cmp(b))
721751
}
752+
753+
fn next_permutation(self) -> bool {
754+
// These cases only have 1 permutation each, so we can't do anything.
755+
if self.len() < 2 { return false; }
756+
757+
// Step 1: Identify the longest, rightmost weakly decreasing part of the vector
758+
let mut i = self.len() - 1;
759+
while i > 0 && self[i-1] >= self[i] {
760+
i -= 1;
761+
}
762+
763+
// If that is the entire vector, this is the last-ordered permutation.
764+
if i == 0 {
765+
return false;
766+
}
767+
768+
// Step 2: Find the rightmost element larger than the pivot (i-1)
769+
let mut j = self.len() - 1;
770+
while j >= i && self[j] <= self[i-1] {
771+
j -= 1;
772+
}
773+
774+
// Step 3: Swap that element with the pivot
775+
self.swap(j, i-1);
776+
777+
// Step 4: Reverse the (previously) weakly decreasing part
778+
self.mut_slice_from(i).reverse();
779+
780+
true
781+
}
782+
783+
fn prev_permutation(self) -> bool {
784+
// These cases only have 1 permutation each, so we can't do anything.
785+
if self.len() < 2 { return false; }
786+
787+
// Step 1: Identify the longest, rightmost weakly increasing part of the vector
788+
let mut i = self.len() - 1;
789+
while i > 0 && self[i-1] <= self[i] {
790+
i -= 1;
791+
}
792+
793+
// If that is the entire vector, this is the first-ordered permutation.
794+
if i == 0 {
795+
return false;
796+
}
797+
798+
// Step 2: Reverse the weakly increasing part
799+
self.mut_slice_from(i).reverse();
800+
801+
// Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
802+
let mut j = self.len() - 1;
803+
while j >= i && self[j-1] < self[i-1] {
804+
j -= 1;
805+
}
806+
807+
// Step 4: Swap that element with the pivot
808+
self.swap(i-1, j);
809+
810+
true
811+
}
722812
}
723813

724814
/// Unsafe operations
@@ -1229,6 +1319,58 @@ mod tests {
12291319
}
12301320
}
12311321

1322+
#[test]
1323+
fn test_lexicographic_permutations() {
1324+
let v : &mut[int] = &mut[1, 2, 3, 4, 5];
1325+
assert!(v.prev_permutation() == false);
1326+
assert!(v.next_permutation());
1327+
assert_eq!(v, &mut[1, 2, 3, 5, 4]);
1328+
assert!(v.prev_permutation());
1329+
assert_eq!(v, &mut[1, 2, 3, 4, 5]);
1330+
assert!(v.next_permutation());
1331+
assert!(v.next_permutation());
1332+
assert_eq!(v, &mut[1, 2, 4, 3, 5]);
1333+
assert!(v.next_permutation());
1334+
assert_eq!(v, &mut[1, 2, 4, 5, 3]);
1335+
1336+
let v : &mut[int] = &mut[1, 0, 0, 0];
1337+
assert!(v.next_permutation() == false);
1338+
assert!(v.prev_permutation());
1339+
assert_eq!(v, &mut[0, 1, 0, 0]);
1340+
assert!(v.prev_permutation());
1341+
assert_eq!(v, &mut[0, 0, 1, 0]);
1342+
assert!(v.prev_permutation());
1343+
assert_eq!(v, &mut[0, 0, 0, 1]);
1344+
assert!(v.prev_permutation() == false);
1345+
}
1346+
1347+
#[test]
1348+
fn test_lexicographic_permutations_empty_and_short() {
1349+
let empty : &mut[int] = &mut[];
1350+
assert!(empty.next_permutation() == false);
1351+
assert_eq!(empty, &mut[]);
1352+
assert!(empty.prev_permutation() == false);
1353+
assert_eq!(empty, &mut[]);
1354+
1355+
let one_elem : &mut[int] = &mut[4];
1356+
assert!(one_elem.prev_permutation() == false);
1357+
assert_eq!(one_elem, &mut[4]);
1358+
assert!(one_elem.next_permutation() == false);
1359+
assert_eq!(one_elem, &mut[4]);
1360+
1361+
let two_elem : &mut[int] = &mut[1, 2];
1362+
assert!(two_elem.prev_permutation() == false);
1363+
assert_eq!(two_elem, &mut[1, 2]);
1364+
assert!(two_elem.next_permutation());
1365+
assert_eq!(two_elem, &mut[2, 1]);
1366+
assert!(two_elem.next_permutation() == false);
1367+
assert_eq!(two_elem, &mut[2, 1]);
1368+
assert!(two_elem.prev_permutation());
1369+
assert_eq!(two_elem, &mut[1, 2]);
1370+
assert!(two_elem.prev_permutation() == false);
1371+
assert_eq!(two_elem, &mut[1, 2]);
1372+
}
1373+
12321374
#[test]
12331375
fn test_position_elem() {
12341376
assert!([].position_elem(&1).is_none());

0 commit comments

Comments
 (0)