Skip to content
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

Rebase Tommy McGuire's each_permutation patch #6523

Closed
wants to merge 5 commits 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
147 changes: 127 additions & 20 deletions src/libcore/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,46 @@ pub fn reverse<T>(v: &mut [T]) {
}
}

/**
* Reverse part of a vector in place.
*
* Reverse the elements in the vector between `start` and `end - 1`.
*
* If either start or end do not represent valid positions in the vector, the
* vector is returned unchanged.
*
* # Arguments
*
* * `v` - The mutable vector to be modified
*
* * `start` - Index of the first element of the slice
*
* * `end` - Index one past the final element to be reversed.
*
* # Example
*
* Assume a mutable vector `v` contains `[1,2,3,4,5]`. After the call:
*
* ~~~
*
* reverse_part(v, 1, 4);
*
* ~~~
*
* `v` now contains `[1,4,3,2,5]`.
*/
pub fn reverse_part<T>(v: &mut [T], start: uint, end : uint) {
let sz = v.len();
if start >= sz || end > sz { return; }
let mut i = start;
let mut j = end - 1;
while i < j {
vec::swap(v, i, j);
i += 1;
j -= 1;
}
}

/// Returns a vector with the order of elements reversed
pub fn reversed<T:Copy>(v: &const [T]) -> ~[T] {
let mut rs: ~[T] = ~[];
Expand Down Expand Up @@ -1739,29 +1779,49 @@ pub fn each2_mut<U, T>(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T)
*
* The total number of permutations produced is `len(v)!`. If `v` contains
* repeated elements, then some permutations are repeated.
*
* See [Algorithms to generate
* permutations](http://en.wikipedia.org/wiki/Permutation).
*
* # Arguments
*
* * `values` - A vector of values from which the permutations are
* chosen
*
* * `fun` - The function to iterate over the combinations
*/
#[cfg(not(stage0))]
pub fn each_permutation<T:Copy>(v: &[T], put: &fn(ts: &[T]) -> bool) -> bool {
let ln = len(v);
if ln <= 1 {
put(v);
} else {
// This does not seem like the most efficient implementation. You
// could make far fewer copies if you put your mind to it.
let mut i = 0u;
while i < ln {
let elt = v[i];
let mut rest = slice(v, 0u, i).to_vec();
rest.push_all(const_slice(v, i+1u, ln));
for each_permutation(rest) |permutation| {
if !put(append(~[elt], permutation)) {
return false;
}
}
i += 1u;
pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> bool {
let length = values.len();
let mut permutation = vec::from_fn(length, |i| values[i]);
if length <= 1 {
fun(permutation);
return true;
}
let mut indices = vec::from_fn(length, |i| i);
loop {
if !fun(permutation) { return true; }
// find largest k such that indices[k] < indices[k+1]
// if no such k exists, all permutations have been generated
let mut k = length - 2;
while k > 0 && indices[k] >= indices[k+1] {
k -= 1;
}
if k == 0 && indices[0] > indices[1] { return true; }
// find largest l such that indices[k] < indices[l]
// k+1 is guaranteed to be such
let mut l = length - 1;
while indices[k] >= indices[l] {
l -= 1;
}
// swap indices[k] and indices[l]; sort indices[k+1..]
// (they're just reversed)
vec::swap(indices, k, l);
reverse_part(indices, k+1, length);
// fixup permutation based on indices
for uint::range(k, length) |i| {
permutation[i] = values[indices[i]];
}
}
return true;
}

/**
Expand Down Expand Up @@ -4730,6 +4790,53 @@ mod tests {
}
}

#[test]
fn test_reverse_part() {
let mut values = [1,2,3,4,5];
reverse_part(values,1,4);
assert_eq!(values, [1,4,3,2,5]);
}

#[test]
fn test_permutations0() {
let values = [];
let mut v : ~[~[int]] = ~[];
for each_permutation(values) |p| {
v.push(p.to_owned());
}
assert_eq!(v, ~[~[]]);
}

#[test]
fn test_permutations1() {
let values = [1];
let mut v : ~[~[int]] = ~[];
for each_permutation(values) |p| {
v.push(p.to_owned());
}
assert_eq!(v, ~[~[1]]);
}

#[test]
fn test_permutations2() {
let values = [1,2];
let mut v : ~[~[int]] = ~[];
for each_permutation(values) |p| {
v.push(p.to_owned());
}
assert_eq!(v, ~[~[1,2],~[2,1]]);
}

#[test]
fn test_permutations3() {
let values = [1,2,3];
let mut v : ~[~[int]] = ~[];
for each_permutation(values) |p| {
v.push(p.to_owned());
}
assert_eq!(v, ~[~[1,2,3],~[1,3,2],~[2,1,3],~[2,3,1],~[3,1,2],~[3,2,1]]);
}

#[test]
fn test_each_val() {
use old_iter::CopyableNonstrictIter;
Expand Down