Skip to content

Commit de9546a

Browse files
author
blake2-ppc
committed
std::vec: Replace each_permutation with a new Permutations iterator
Introduce ElementSwaps and Permutations. ElementSwaps is an iterator that for a given sequence length yields the element swaps needed to visit each possible permutation of the sequence in turn. We use an algorithm that generates a sequence such that each permutation is only one swap apart. let mut v = [1, 2, 3]; for perm in v.permutations_iter() { // yields 1 2 3 | 1 3 2 | 3 1 2 | 3 2 1 | 2 3 1 | 2 1 3 } The `.permutations_iter()` yields clones of the input vector for each permutation. If a copyless traversal is needed, it can be constructed with `ElementSwaps`: for (a, b) in ElementSwaps::new(3) { // yields (2, 1), (1, 0), (2, 1) ... v.swap(a, b); // .. }
1 parent 6212729 commit de9546a

File tree

1 file changed

+165
-119
lines changed

1 file changed

+165
-119
lines changed

src/libstd/vec.rs

Lines changed: 165 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -408,56 +408,106 @@ pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (~[T], ~[U]) {
408408
(ts, us)
409409
}
410410

411-
/**
412-
* Iterate over all permutations of vector `v`.
413-
*
414-
* Permutations are produced in lexicographic order with respect to the order
415-
* of elements in `v` (so if `v` is sorted then the permutations are
416-
* lexicographically sorted).
417-
*
418-
* The total number of permutations produced is `v.len()!`. If `v` contains
419-
* repeated elements, then some permutations are repeated.
420-
*
421-
* See [Algorithms to generate
422-
* permutations](http://en.wikipedia.org/wiki/Permutation).
423-
*
424-
* # Arguments
425-
*
426-
* * `values` - A vector of values from which the permutations are
427-
* chosen
428-
*
429-
* * `fun` - The function to iterate over the combinations
430-
*/
431-
pub fn each_permutation<T:Clone>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> bool {
432-
let length = values.len();
433-
let mut permutation = vec::from_fn(length, |i| values[i].clone());
434-
if length <= 1 {
435-
fun(permutation);
436-
return true;
437-
}
438-
let mut indices = vec::from_fn(length, |i| i);
439-
loop {
440-
if !fun(permutation) { return true; }
441-
// find largest k such that indices[k] < indices[k+1]
442-
// if no such k exists, all permutations have been generated
443-
let mut k = length - 2;
444-
while k > 0 && indices[k] >= indices[k+1] {
445-
k -= 1;
446-
}
447-
if k == 0 && indices[0] > indices[1] { return true; }
448-
// find largest l such that indices[k] < indices[l]
449-
// k+1 is guaranteed to be such
450-
let mut l = length - 1;
451-
while indices[k] >= indices[l] {
452-
l -= 1;
453-
}
454-
// swap indices[k] and indices[l]; sort indices[k+1..]
455-
// (they're just reversed)
456-
indices.swap(k, l);
457-
indices.mut_slice(k+1, length).reverse();
458-
// fixup permutation based on indices
459-
for i in range(k, length) {
460-
permutation[i] = values[indices[i]].clone();
411+
/// An Iterator that yields the element swaps needed to produce
412+
/// a sequence of all possible permutations for an indexed sequence of
413+
/// elements. Each permutation is only a single swap apart.
414+
///
415+
/// The Steinhaus–Johnson–Trotter algorithm is used.
416+
///
417+
/// Generates even and odd permutations alternatingly.
418+
///
419+
/// The last generated swap is always (0, 1), and it returns the
420+
/// sequence to its initial order.
421+
pub struct ElementSwaps {
422+
priv sdir: ~[SizeDirection],
423+
/// If true, emit the last swap that returns the sequence to initial state
424+
priv emit_reset: bool,
425+
}
426+
427+
impl ElementSwaps {
428+
/// Create an `ElementSwaps` iterator for a sequence of `length` elements
429+
pub fn new(length: uint) -> ElementSwaps {
430+
// Initialize `sdir` with a direction that position should move in
431+
// (all negative at the beginning) and the `size` of the
432+
// element (equal to the original index).
433+
ElementSwaps{
434+
emit_reset: true,
435+
sdir: range(0, length)
436+
.map(|i| SizeDirection{ size: i, dir: Neg })
437+
.to_owned_vec()
438+
}
439+
}
440+
}
441+
442+
enum Direction { Pos, Neg }
443+
444+
/// An Index and Direction together
445+
struct SizeDirection {
446+
size: uint,
447+
dir: Direction,
448+
}
449+
450+
impl Iterator<(uint, uint)> for ElementSwaps {
451+
#[inline]
452+
fn next(&mut self) -> Option<(uint, uint)> {
453+
fn new_pos(i: uint, s: Direction) -> uint {
454+
i + match s { Pos => 1, Neg => -1 }
455+
}
456+
457+
// Find the index of the largest mobile element:
458+
// The direction should point into the vector, and the
459+
// swap should be with a smaller `size` element.
460+
let max = self.sdir.iter().map(|&x| x).enumerate()
461+
.filter(|&(i, sd)|
462+
new_pos(i, sd.dir) < self.sdir.len() &&
463+
self.sdir[new_pos(i, sd.dir)].size < sd.size)
464+
.max_by(|&(_, sd)| sd.size);
465+
match max {
466+
Some((i, sd)) => {
467+
let j = new_pos(i, sd.dir);
468+
self.sdir.swap(i, j);
469+
470+
// Swap the direction of each larger SizeDirection
471+
for x in self.sdir.mut_iter() {
472+
if x.size > sd.size {
473+
x.dir = match x.dir { Pos => Neg, Neg => Pos };
474+
}
475+
}
476+
Some((i, j))
477+
},
478+
None => if self.emit_reset && self.sdir.len() > 1 {
479+
self.emit_reset = false;
480+
Some((0, 1))
481+
} else {
482+
None
483+
}
484+
}
485+
}
486+
}
487+
488+
/// An Iterator that uses `ElementSwaps` to iterate through
489+
/// all possible permutations of a vector.
490+
///
491+
/// The first iteration yields a clone of the vector as it is,
492+
/// then each successive element is the vector with one
493+
/// swap applied.
494+
///
495+
/// Generates even and odd permutations alternatingly.
496+
pub struct Permutations<T> {
497+
priv swaps: ElementSwaps,
498+
priv v: ~[T],
499+
}
500+
501+
impl<T: Clone> Iterator<~[T]> for Permutations<T> {
502+
#[inline]
503+
fn next(&mut self) -> Option<~[T]> {
504+
match self.swaps.next() {
505+
None => None,
506+
Some((a, b)) => {
507+
let elt = self.v.clone();
508+
self.v.swap(a, b);
509+
Some(elt)
510+
}
461511
}
462512
}
463513
}
@@ -1141,6 +1191,7 @@ impl<'self, T: TotalOrd> ImmutableTotalOrdVector<T> for &'self [T] {
11411191
pub trait ImmutableCopyableVector<T> {
11421192
fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]);
11431193
unsafe fn unsafe_get(&self, elem: uint) -> T;
1194+
fn permutations_iter(self) -> Permutations<T>;
11441195
}
11451196

11461197
/// Extension methods for vectors
@@ -1170,6 +1221,16 @@ impl<'self,T:Clone> ImmutableCopyableVector<T> for &'self [T] {
11701221
unsafe fn unsafe_get(&self, index: uint) -> T {
11711222
(*self.unsafe_ref(index)).clone()
11721223
}
1224+
1225+
/// Create an iterator that yields every possible permutation of the
1226+
/// vector in succession.
1227+
fn permutations_iter(self) -> Permutations<T> {
1228+
Permutations{
1229+
swaps: ElementSwaps::new(self.len()),
1230+
v: self.to_owned(),
1231+
}
1232+
}
1233+
11731234
}
11741235

11751236
#[allow(missing_doc)]
@@ -2847,28 +2908,6 @@ mod tests {
28472908
assert_eq!(v, ~[1, 3, 5]);
28482909
}
28492910

2850-
#[test]
2851-
fn test_each_permutation() {
2852-
let mut results: ~[~[int]];
2853-
2854-
results = ~[];
2855-
do each_permutation([]) |v| { results.push(v.to_owned()); true };
2856-
assert_eq!(results, ~[~[]]);
2857-
2858-
results = ~[];
2859-
do each_permutation([7]) |v| { results.push(v.to_owned()); true };
2860-
assert_eq!(results, ~[~[7]]);
2861-
2862-
results = ~[];
2863-
do each_permutation([1,1]) |v| { results.push(v.to_owned()); true };
2864-
assert_eq!(results, ~[~[1,1],~[1,1]]);
2865-
2866-
results = ~[];
2867-
do each_permutation([5,2,0]) |v| { results.push(v.to_owned()); true };
2868-
assert!(results ==
2869-
~[~[5,2,0],~[5,0,2],~[2,5,0],~[2,0,5],~[0,5,2],~[0,2,5]]);
2870-
}
2871-
28722911
#[test]
28732912
fn test_zip_unzip() {
28742913
let z1 = ~[(1, 4), (2, 5), (3, 6)];
@@ -2880,6 +2919,58 @@ mod tests {
28802919
assert_eq!((3, 6), (left[2], right[2]));
28812920
}
28822921

2922+
#[test]
2923+
fn test_element_swaps() {
2924+
let mut v = [1, 2, 3];
2925+
for (i, (a, b)) in ElementSwaps::new(v.len()).enumerate() {
2926+
v.swap(a, b);
2927+
match i {
2928+
0 => assert_eq!(v, [1, 3, 2]),
2929+
1 => assert_eq!(v, [3, 1, 2]),
2930+
2 => assert_eq!(v, [3, 2, 1]),
2931+
3 => assert_eq!(v, [2, 3, 1]),
2932+
4 => assert_eq!(v, [2, 1, 3]),
2933+
5 => assert_eq!(v, [1, 2, 3]),
2934+
_ => fail!(),
2935+
}
2936+
}
2937+
}
2938+
2939+
#[test]
2940+
fn test_permutations() {
2941+
use hashmap;
2942+
{
2943+
let v: [int, ..0] = [];
2944+
let mut it = v.permutations_iter();
2945+
assert_eq!(it.next(), None);
2946+
}
2947+
{
2948+
let v = [~"Hello"];
2949+
let mut it = v.permutations_iter();
2950+
assert_eq!(it.next(), None);
2951+
}
2952+
{
2953+
let v = [1, 2, 3];
2954+
let mut it = v.permutations_iter();
2955+
assert_eq!(it.next(), Some(~[1,2,3]));
2956+
assert_eq!(it.next(), Some(~[1,3,2]));
2957+
assert_eq!(it.next(), Some(~[3,1,2]));
2958+
assert_eq!(it.next(), Some(~[3,2,1]));
2959+
assert_eq!(it.next(), Some(~[2,3,1]));
2960+
assert_eq!(it.next(), Some(~[2,1,3]));
2961+
assert_eq!(it.next(), None);
2962+
}
2963+
{
2964+
// check that we have N! unique permutations
2965+
let mut set = hashmap::HashSet::new();
2966+
let v = ['A', 'B', 'C', 'D', 'E', 'F'];
2967+
for perm in v.permutations_iter() {
2968+
set.insert(perm);
2969+
}
2970+
assert_eq!(set.len(), 2 * 3 * 4 * 5 * 6);
2971+
}
2972+
}
2973+
28832974
#[test]
28842975
fn test_position_elem() {
28852976
assert!([].position_elem(&1).is_none());
@@ -3175,13 +3266,12 @@ mod tests {
31753266
fn test_permute_fail() {
31763267
let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
31773268
let mut i = 0;
3178-
do each_permutation(v) |_elt| {
3269+
for _ in v.permutations_iter() {
31793270
if i == 2 {
31803271
fail!()
31813272
}
31823273
i += 1;
3183-
true
3184-
};
3274+
}
31853275
}
31863276

31873277
#[test]
@@ -3493,50 +3583,6 @@ mod tests {
34933583
assert_eq!(values, [1,4,3,2,5]);
34943584
}
34953585

3496-
#[test]
3497-
fn test_permutations0() {
3498-
let values = [];
3499-
let mut v : ~[~[int]] = ~[];
3500-
do each_permutation(values) |p| {
3501-
v.push(p.to_owned());
3502-
true
3503-
};
3504-
assert_eq!(v, ~[~[]]);
3505-
}
3506-
3507-
#[test]
3508-
fn test_permutations1() {
3509-
let values = [1];
3510-
let mut v : ~[~[int]] = ~[];
3511-
do each_permutation(values) |p| {
3512-
v.push(p.to_owned());
3513-
true
3514-
};
3515-
assert_eq!(v, ~[~[1]]);
3516-
}
3517-
3518-
#[test]
3519-
fn test_permutations2() {
3520-
let values = [1,2];
3521-
let mut v : ~[~[int]] = ~[];
3522-
do each_permutation(values) |p| {
3523-
v.push(p.to_owned());
3524-
true
3525-
};
3526-
assert_eq!(v, ~[~[1,2],~[2,1]]);
3527-
}
3528-
3529-
#[test]
3530-
fn test_permutations3() {
3531-
let values = [1,2,3];
3532-
let mut v : ~[~[int]] = ~[];
3533-
do each_permutation(values) |p| {
3534-
v.push(p.to_owned());
3535-
true
3536-
};
3537-
assert_eq!(v, ~[~[1,2,3],~[1,3,2],~[2,1,3],~[2,3,1],~[3,1,2],~[3,2,1]]);
3538-
}
3539-
35403586
#[test]
35413587
fn test_vec_zero() {
35423588
use num::Zero;

0 commit comments

Comments
 (0)