Skip to content

Commit dba7f6d

Browse files
committed
Add reverse_part, replace each_permutation, add tests
1 parent f529af0 commit dba7f6d

File tree

1 file changed

+194
-20
lines changed

1 file changed

+194
-20
lines changed

src/libcore/vec.rs

+194-20
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,46 @@ pub fn reverse<T>(v: &[mut T]) {
12911291
while i < ln / 2 { v[i] <-> v[ln - i - 1]; i += 1; }
12921292
}
12931293

1294+
/**
1295+
* Reverse part of a vector in place.
1296+
*
1297+
* Reverse the elements in the vector between `start` and `end - 1`.
1298+
*
1299+
* # Arguments
1300+
*
1301+
* * `v` - The mutable vector to be modified
1302+
*
1303+
* * `start` - Index of the first element of the slice
1304+
*
1305+
* * `end` - Index one past the final element to be reversed.
1306+
*
1307+
* # Example
1308+
*
1309+
* Assume a mutable vector `v` contains `[1,2,3,4,5]`. After the call:
1310+
*
1311+
* ~~~
1312+
*
1313+
* reverse_part(v, 1, 4);
1314+
*
1315+
* ~~~
1316+
*
1317+
* `v` now contains `[1,4,3,2,5]`.
1318+
*
1319+
* # Safety note
1320+
*
1321+
* Behavior is undefined if `start` or `end` do not represent valid
1322+
* positions in `v`.
1323+
*/
1324+
pub fn reverse_part<T>(v : &[mut T], start : uint, end : uint) {
1325+
let mut i = start;
1326+
let mut j = end - 1;
1327+
while i < j {
1328+
v[i] <-> v[j];
1329+
i += 1;
1330+
j -= 1;
1331+
}
1332+
}
1333+
12941334
/// Returns a vector with the order of elements reversed
12951335
pub pure fn reversed<T: Copy>(v: &[const T]) -> ~[T] {
12961336
let mut rs: ~[T] = ~[];
@@ -1457,31 +1497,74 @@ pub fn each2<U, T>(v1: &[U], v2: &[T], f: fn(u: &U, t: &T) -> bool) {
14571497
*
14581498
* The total number of permutations produced is `len(v)!`. If `v` contains
14591499
* repeated elements, then some permutations are repeated.
1500+
*
1501+
* See [Algorithms to generate
1502+
* permutations](http://en.wikipedia.org/wiki/Permutation).
1503+
*
1504+
* # Arguments
1505+
*
1506+
* * `values` - A vector of values from which the permutations are
1507+
* chosen
1508+
*
1509+
* * `fun` - The function to iterate over the combinations
14601510
*/
1461-
pure fn each_permutation<T: Copy>(v: &[T], put: fn(ts: &[T]) -> bool) {
1462-
let ln = len(v);
1463-
if ln <= 1 {
1464-
put(v);
1465-
} else {
1466-
// This does not seem like the most efficient implementation. You
1467-
// could make far fewer copies if you put your mind to it.
1468-
let mut i = 0u;
1469-
while i < ln {
1470-
let elt = v[i];
1471-
let mut rest = slice(v, 0u, i);
1472-
unsafe {
1473-
rest.push_all(const_view(v, i+1u, ln));
1474-
for each_permutation(rest) |permutation| {
1475-
if !put(append(~[elt], permutation)) {
1476-
return;
1477-
}
1478-
}
1479-
}
1480-
i += 1u;
1511+
pub pure fn each_permutation<T : Copy>(values : &[T],
1512+
fun : &fn(perm : &[T]) -> bool) {
1513+
let length = values.len();
1514+
let mut permutation = vec::from_fn(length, |i| values[i]);
1515+
if length <= 1 {
1516+
fun(permutation);
1517+
return;
1518+
}
1519+
let mut indices = vec::from_fn(length, |i| i);
1520+
loop {
1521+
if !fun(permutation) { return; }
1522+
// find largest k such that indices[k] < indices[k+1]
1523+
// if no such k exists, all permutations have been generated
1524+
let mut k = length - 2;
1525+
while k > 0 && indices[k] >= indices[k+1] {
1526+
k -= 1;
1527+
}
1528+
if k == 0 && indices[0] > indices[1] { return; }
1529+
// find largest l such that indices[k] < indices[l]
1530+
// k+1 is guaranteed to be such
1531+
let mut l = length - 1;
1532+
while indices[k] >= indices[l] {
1533+
l -= 1;
1534+
}
1535+
// swap indices[k] and indices[l]; sort indices[k+1..]
1536+
// (they're just reversed)
1537+
indices[k] <-> indices[l];
1538+
unsafe {
1539+
reverse_part(indices, k+1, length);
1540+
}
1541+
// fixup permutation based on indices
1542+
for uint::range(k, length) |i| {
1543+
permutation[i] = values[indices[i]];
14811544
}
14821545
}
14831546
}
14841547

1548+
/**
1549+
* Iterate over all permutations of vector `values`.
1550+
*
1551+
* This is an alternative to each_permutation that uses references to
1552+
* avoid copying the elements of the values vector.
1553+
*
1554+
* To avoid copying, the iterator will be passed a reference to a vector
1555+
* containing references to the elements in the original `values` vector.
1556+
*
1557+
* # Arguments
1558+
*
1559+
* * `values` - A vector of values from which the permutations are chosen
1560+
*
1561+
* * `fun` - The function to iterate over the permutations
1562+
*/
1563+
pub pure fn each_permutation_ref<T>(values : &v/[T],
1564+
fun : &fn(perm : &[&v/T]) -> bool) {
1565+
each_permutation(vec::from_fn(values.len(), |i| &values[i]), fun);
1566+
}
1567+
14851568
pub pure fn windowed<TT: Copy>(nn: uint, xx: &[TT]) -> ~[~[TT]] {
14861569
let mut ww = ~[];
14871570
assert 1u <= nn;
@@ -3995,6 +4078,97 @@ mod tests {
39954078
}
39964079
}
39974080

4081+
fn dup<T:Copy>(values : &[&T]) -> ~[T] {
4082+
from_fn(values.len(), |i| *values[i])
4083+
}
4084+
4085+
#[test]
4086+
fn test_reverse_part() {
4087+
let mut values = [1,2,3,4,5];
4088+
reverse_part(values,1,4);
4089+
assert values == [1,4,3,2,5];
4090+
}
4091+
4092+
#[test]
4093+
fn test_permutations0() {
4094+
let values = [];
4095+
let mut v : ~[~[int]] = ~[];
4096+
for each_permutation(values) |p| {
4097+
v.push(vec::from_slice(p));
4098+
}
4099+
assert v == ~[~[]];
4100+
}
4101+
4102+
#[test]
4103+
fn test_permutations0_ref() {
4104+
let values = [];
4105+
let mut v : ~[~[int]] = ~[];
4106+
for each_permutation_ref(values) |p| {
4107+
v.push(dup(p));
4108+
}
4109+
assert v == ~[~[]];
4110+
}
4111+
4112+
#[test]
4113+
fn test_permutations1() {
4114+
let values = [1];
4115+
let mut v : ~[~[int]] = ~[];
4116+
for each_permutation(values) |p| {
4117+
v.push(vec::from_slice(p));
4118+
}
4119+
assert v == ~[~[1]];
4120+
}
4121+
4122+
#[test]
4123+
fn test_permutations1_ref() {
4124+
let values = [1];
4125+
let mut v : ~[~[int]] = ~[];
4126+
for each_permutation_ref(values) |p| {
4127+
v.push(dup(p));
4128+
}
4129+
assert v == ~[~[1]];
4130+
}
4131+
4132+
#[test]
4133+
fn test_permutations2() {
4134+
let values = [1,2];
4135+
let mut v : ~[~[int]] = ~[];
4136+
for each_permutation(values) |p| {
4137+
v.push(vec::from_slice(p));
4138+
}
4139+
assert v == ~[~[1,2],~[2,1]];
4140+
}
4141+
4142+
#[test]
4143+
fn test_permutations2_ref() {
4144+
let values = [1,2];
4145+
let mut v : ~[~[int]] = ~[];
4146+
for each_permutation_ref(values) |p| {
4147+
v.push(dup(p));
4148+
}
4149+
assert v == ~[~[1,2],~[2,1]];
4150+
}
4151+
4152+
#[test]
4153+
fn test_permutations3() {
4154+
let values = [1,2,3];
4155+
let mut v : ~[~[int]] = ~[];
4156+
for each_permutation(values) |p| {
4157+
v.push(vec::from_slice(p));
4158+
}
4159+
assert v == ~[~[1,2,3],~[1,3,2],~[2,1,3],~[2,3,1],~[3,1,2],~[3,2,1]];
4160+
}
4161+
4162+
#[test]
4163+
fn test_permutations3_ref() {
4164+
let values = [1,2,3];
4165+
let mut v : ~[~[int]] = ~[];
4166+
for each_permutation_ref(values) |p| {
4167+
v.push(dup(p));
4168+
}
4169+
assert v == ~[~[1,2,3],~[1,3,2],~[2,1,3],~[2,3,1],~[3,1,2],~[3,2,1]];
4170+
}
4171+
39984172
}
39994173

40004174
// Local Variables:

0 commit comments

Comments
 (0)