Skip to content

Commit 77c98f0

Browse files
committed
auto merge of #6523 : cmr/rust/faster_each_permutation, r=luqmana
Closes #5127
2 parents 09bf401 + af54d58 commit 77c98f0

File tree

1 file changed

+127
-20
lines changed

1 file changed

+127
-20
lines changed

src/libcore/vec.rs

+127-20
Original file line numberDiff line numberDiff line change
@@ -1445,6 +1445,46 @@ pub fn reverse<T>(v: &mut [T]) {
14451445
}
14461446
}
14471447

1448+
/**
1449+
* Reverse part of a vector in place.
1450+
*
1451+
* Reverse the elements in the vector between `start` and `end - 1`.
1452+
*
1453+
* If either start or end do not represent valid positions in the vector, the
1454+
* vector is returned unchanged.
1455+
*
1456+
* # Arguments
1457+
*
1458+
* * `v` - The mutable vector to be modified
1459+
*
1460+
* * `start` - Index of the first element of the slice
1461+
*
1462+
* * `end` - Index one past the final element to be reversed.
1463+
*
1464+
* # Example
1465+
*
1466+
* Assume a mutable vector `v` contains `[1,2,3,4,5]`. After the call:
1467+
*
1468+
* ~~~
1469+
*
1470+
* reverse_part(v, 1, 4);
1471+
*
1472+
* ~~~
1473+
*
1474+
* `v` now contains `[1,4,3,2,5]`.
1475+
*/
1476+
pub fn reverse_part<T>(v: &mut [T], start: uint, end : uint) {
1477+
let sz = v.len();
1478+
if start >= sz || end > sz { return; }
1479+
let mut i = start;
1480+
let mut j = end - 1;
1481+
while i < j {
1482+
vec::swap(v, i, j);
1483+
i += 1;
1484+
j -= 1;
1485+
}
1486+
}
1487+
14481488
/// Returns a vector with the order of elements reversed
14491489
pub fn reversed<T:Copy>(v: &const [T]) -> ~[T] {
14501490
let mut rs: ~[T] = ~[];
@@ -1739,29 +1779,49 @@ pub fn each2_mut<U, T>(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T)
17391779
*
17401780
* The total number of permutations produced is `len(v)!`. If `v` contains
17411781
* repeated elements, then some permutations are repeated.
1782+
*
1783+
* See [Algorithms to generate
1784+
* permutations](http://en.wikipedia.org/wiki/Permutation).
1785+
*
1786+
* # Arguments
1787+
*
1788+
* * `values` - A vector of values from which the permutations are
1789+
* chosen
1790+
*
1791+
* * `fun` - The function to iterate over the combinations
17421792
*/
1743-
#[cfg(not(stage0))]
1744-
pub fn each_permutation<T:Copy>(v: &[T], put: &fn(ts: &[T]) -> bool) -> bool {
1745-
let ln = len(v);
1746-
if ln <= 1 {
1747-
put(v);
1748-
} else {
1749-
// This does not seem like the most efficient implementation. You
1750-
// could make far fewer copies if you put your mind to it.
1751-
let mut i = 0u;
1752-
while i < ln {
1753-
let elt = v[i];
1754-
let mut rest = slice(v, 0u, i).to_vec();
1755-
rest.push_all(const_slice(v, i+1u, ln));
1756-
for each_permutation(rest) |permutation| {
1757-
if !put(append(~[elt], permutation)) {
1758-
return false;
1759-
}
1760-
}
1761-
i += 1u;
1793+
pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> bool {
1794+
let length = values.len();
1795+
let mut permutation = vec::from_fn(length, |i| values[i]);
1796+
if length <= 1 {
1797+
fun(permutation);
1798+
return true;
1799+
}
1800+
let mut indices = vec::from_fn(length, |i| i);
1801+
loop {
1802+
if !fun(permutation) { return true; }
1803+
// find largest k such that indices[k] < indices[k+1]
1804+
// if no such k exists, all permutations have been generated
1805+
let mut k = length - 2;
1806+
while k > 0 && indices[k] >= indices[k+1] {
1807+
k -= 1;
1808+
}
1809+
if k == 0 && indices[0] > indices[1] { return true; }
1810+
// find largest l such that indices[k] < indices[l]
1811+
// k+1 is guaranteed to be such
1812+
let mut l = length - 1;
1813+
while indices[k] >= indices[l] {
1814+
l -= 1;
1815+
}
1816+
// swap indices[k] and indices[l]; sort indices[k+1..]
1817+
// (they're just reversed)
1818+
vec::swap(indices, k, l);
1819+
reverse_part(indices, k+1, length);
1820+
// fixup permutation based on indices
1821+
for uint::range(k, length) |i| {
1822+
permutation[i] = values[indices[i]];
17621823
}
17631824
}
1764-
return true;
17651825
}
17661826

17671827
/**
@@ -4730,6 +4790,53 @@ mod tests {
47304790
}
47314791
}
47324792

4793+
#[test]
4794+
fn test_reverse_part() {
4795+
let mut values = [1,2,3,4,5];
4796+
reverse_part(values,1,4);
4797+
assert_eq!(values, [1,4,3,2,5]);
4798+
}
4799+
4800+
#[test]
4801+
fn test_permutations0() {
4802+
let values = [];
4803+
let mut v : ~[~[int]] = ~[];
4804+
for each_permutation(values) |p| {
4805+
v.push(p.to_owned());
4806+
}
4807+
assert_eq!(v, ~[~[]]);
4808+
}
4809+
4810+
#[test]
4811+
fn test_permutations1() {
4812+
let values = [1];
4813+
let mut v : ~[~[int]] = ~[];
4814+
for each_permutation(values) |p| {
4815+
v.push(p.to_owned());
4816+
}
4817+
assert_eq!(v, ~[~[1]]);
4818+
}
4819+
4820+
#[test]
4821+
fn test_permutations2() {
4822+
let values = [1,2];
4823+
let mut v : ~[~[int]] = ~[];
4824+
for each_permutation(values) |p| {
4825+
v.push(p.to_owned());
4826+
}
4827+
assert_eq!(v, ~[~[1,2],~[2,1]]);
4828+
}
4829+
4830+
#[test]
4831+
fn test_permutations3() {
4832+
let values = [1,2,3];
4833+
let mut v : ~[~[int]] = ~[];
4834+
for each_permutation(values) |p| {
4835+
v.push(p.to_owned());
4836+
}
4837+
assert_eq!(v, ~[~[1,2,3],~[1,3,2],~[2,1,3],~[2,3,1],~[3,1,2],~[3,2,1]]);
4838+
}
4839+
47334840
#[test]
47344841
fn test_each_val() {
47354842
use old_iter::CopyableNonstrictIter;

0 commit comments

Comments
 (0)