auto merge of #13783 : wackywendell/rust/permfix, r=kballard
I filed bugs #13734 and #13759 recently, and then realized I could probably fix them myself. This does exactly that, with a couple additional modifications and additions to the test-suite to pick up on that. I've never done this before, so please feel free to tell me all the things I'm doing wrong or could be doing better.
This commit is contained in:
commit
b2a8fae84c
1 changed files with 48 additions and 7 deletions
|
@ -307,6 +307,7 @@ pub struct ElementSwaps {
|
||||||
sdir: ~[SizeDirection],
|
sdir: ~[SizeDirection],
|
||||||
/// If true, emit the last swap that returns the sequence to initial state
|
/// If true, emit the last swap that returns the sequence to initial state
|
||||||
emit_reset: bool,
|
emit_reset: bool,
|
||||||
|
swaps_made : uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ElementSwaps {
|
impl ElementSwaps {
|
||||||
|
@ -319,7 +320,8 @@ impl ElementSwaps {
|
||||||
emit_reset: true,
|
emit_reset: true,
|
||||||
sdir: range(0, length)
|
sdir: range(0, length)
|
||||||
.map(|i| SizeDirection{ size: i, dir: Neg })
|
.map(|i| SizeDirection{ size: i, dir: Neg })
|
||||||
.collect::<~[_]>()
|
.collect::<~[_]>(),
|
||||||
|
swaps_made: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,16 +360,30 @@ impl Iterator<(uint, uint)> for ElementSwaps {
|
||||||
x.dir = match x.dir { Pos => Neg, Neg => Pos };
|
x.dir = match x.dir { Pos => Neg, Neg => Pos };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.swaps_made += 1;
|
||||||
Some((i, j))
|
Some((i, j))
|
||||||
},
|
},
|
||||||
None => if self.emit_reset && self.sdir.len() > 1 {
|
None => if self.emit_reset {
|
||||||
self.emit_reset = false;
|
self.emit_reset = false;
|
||||||
Some((0, 1))
|
if self.sdir.len() > 1 {
|
||||||
} else {
|
// The last swap
|
||||||
None
|
self.swaps_made += 1;
|
||||||
}
|
Some((0, 1))
|
||||||
|
} else {
|
||||||
|
// Vector is of the form [] or [x], and the only permutation is itself
|
||||||
|
self.swaps_made += 1;
|
||||||
|
Some((0,0))
|
||||||
|
}
|
||||||
|
} else { None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||||
|
// For a vector of size n, there are exactly n! permutations.
|
||||||
|
let n = range(2, self.sdir.len() + 1).product();
|
||||||
|
(n - self.swaps_made, Some(n - self.swaps_made))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An Iterator that uses `ElementSwaps` to iterate through
|
/// An Iterator that uses `ElementSwaps` to iterate through
|
||||||
|
@ -388,6 +404,7 @@ impl<T: Clone> Iterator<~[T]> for Permutations<T> {
|
||||||
fn next(&mut self) -> Option<~[T]> {
|
fn next(&mut self) -> Option<~[T]> {
|
||||||
match self.swaps.next() {
|
match self.swaps.next() {
|
||||||
None => None,
|
None => None,
|
||||||
|
Some((0,0)) => Some(self.v.clone()),
|
||||||
Some((a, b)) => {
|
Some((a, b)) => {
|
||||||
let elt = self.v.clone();
|
let elt = self.v.clone();
|
||||||
self.v.swap(a, b);
|
self.v.swap(a, b);
|
||||||
|
@ -395,6 +412,11 @@ impl<T: Clone> Iterator<~[T]> for Permutations<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||||
|
self.swaps.size_hint()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over the (overlapping) slices of length `size` within
|
/// An iterator over the (overlapping) slices of length `size` within
|
||||||
|
@ -2767,19 +2789,33 @@ mod tests {
|
||||||
{
|
{
|
||||||
let v: [int, ..0] = [];
|
let v: [int, ..0] = [];
|
||||||
let mut it = v.permutations();
|
let mut it = v.permutations();
|
||||||
|
let (min_size, max_opt) = it.size_hint();
|
||||||
|
assert_eq!(min_size, 1);
|
||||||
|
assert_eq!(max_opt.unwrap(), 1);
|
||||||
|
assert_eq!(it.next(), Some(v.as_slice().to_owned()));
|
||||||
assert_eq!(it.next(), None);
|
assert_eq!(it.next(), None);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let v = ["Hello".to_owned()];
|
let v = ["Hello".to_owned()];
|
||||||
let mut it = v.permutations();
|
let mut it = v.permutations();
|
||||||
|
let (min_size, max_opt) = it.size_hint();
|
||||||
|
assert_eq!(min_size, 1);
|
||||||
|
assert_eq!(max_opt.unwrap(), 1);
|
||||||
|
assert_eq!(it.next(), Some(v.as_slice().to_owned()));
|
||||||
assert_eq!(it.next(), None);
|
assert_eq!(it.next(), None);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let v = [1, 2, 3];
|
let v = [1, 2, 3];
|
||||||
let mut it = v.permutations();
|
let mut it = v.permutations();
|
||||||
|
let (min_size, max_opt) = it.size_hint();
|
||||||
|
assert_eq!(min_size, 3*2);
|
||||||
|
assert_eq!(max_opt.unwrap(), 3*2);
|
||||||
assert_eq!(it.next(), Some(~[1,2,3]));
|
assert_eq!(it.next(), Some(~[1,2,3]));
|
||||||
assert_eq!(it.next(), Some(~[1,3,2]));
|
assert_eq!(it.next(), Some(~[1,3,2]));
|
||||||
assert_eq!(it.next(), Some(~[3,1,2]));
|
assert_eq!(it.next(), Some(~[3,1,2]));
|
||||||
|
let (min_size, max_opt) = it.size_hint();
|
||||||
|
assert_eq!(min_size, 3);
|
||||||
|
assert_eq!(max_opt.unwrap(), 3);
|
||||||
assert_eq!(it.next(), Some(~[3,2,1]));
|
assert_eq!(it.next(), Some(~[3,2,1]));
|
||||||
assert_eq!(it.next(), Some(~[2,3,1]));
|
assert_eq!(it.next(), Some(~[2,3,1]));
|
||||||
assert_eq!(it.next(), Some(~[2,1,3]));
|
assert_eq!(it.next(), Some(~[2,1,3]));
|
||||||
|
@ -2789,10 +2825,15 @@ mod tests {
|
||||||
// check that we have N! permutations
|
// check that we have N! permutations
|
||||||
let v = ['A', 'B', 'C', 'D', 'E', 'F'];
|
let v = ['A', 'B', 'C', 'D', 'E', 'F'];
|
||||||
let mut amt = 0;
|
let mut amt = 0;
|
||||||
for _perm in v.permutations() {
|
let mut it = v.permutations();
|
||||||
|
let (min_size, max_opt) = it.size_hint();
|
||||||
|
for _perm in it {
|
||||||
amt += 1;
|
amt += 1;
|
||||||
}
|
}
|
||||||
|
assert_eq!(amt, it.swaps.swaps_made);
|
||||||
|
assert_eq!(amt, min_size);
|
||||||
assert_eq!(amt, 2 * 3 * 4 * 5 * 6);
|
assert_eq!(amt, 2 * 3 * 4 * 5 * 6);
|
||||||
|
assert_eq!(amt, max_opt.unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue