From: bors Date: Sun, 27 Apr 2014 06:41:31 +0000 (-0700) Subject: auto merge of #13783 : wackywendell/rust/permfix, r=kballard X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=b2a8fae84c290f6dbbff769de7f59f76a9400103;hp=3ffe56ce38d8680fa3c1a7cfd6f8bde609e4bc7a;p=rust.git 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. --- diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index 929c47b05b9..f5e064942e6 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -307,6 +307,7 @@ pub struct ElementSwaps { sdir: ~[SizeDirection], /// If true, emit the last swap that returns the sequence to initial state emit_reset: bool, + swaps_made : uint, } impl ElementSwaps { @@ -319,7 +320,8 @@ pub fn new(length: uint) -> ElementSwaps { emit_reset: true, sdir: range(0, length) .map(|i| SizeDirection{ size: i, dir: Neg }) - .collect::<~[_]>() + .collect::<~[_]>(), + swaps_made: 0 } } } @@ -358,16 +360,30 @@ fn new_pos(i: uint, s: Direction) -> uint { x.dir = match x.dir { Pos => Neg, Neg => Pos }; } } + self.swaps_made += 1; Some((i, j)) }, - None => if self.emit_reset && self.sdir.len() > 1 { + None => if self.emit_reset { self.emit_reset = false; - Some((0, 1)) - } else { - None - } + if self.sdir.len() > 1 { + // The last swap + 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) { + // 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 @@ -388,6 +404,7 @@ impl Iterator<~[T]> for Permutations { fn next(&mut self) -> Option<~[T]> { match self.swaps.next() { None => None, + Some((0,0)) => Some(self.v.clone()), Some((a, b)) => { let elt = self.v.clone(); self.v.swap(a, b); @@ -395,6 +412,11 @@ fn next(&mut self) -> Option<~[T]> { } } } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.swaps.size_hint() + } } /// An iterator over the (overlapping) slices of length `size` within @@ -2767,19 +2789,33 @@ fn test_permutations() { { let v: [int, ..0] = []; 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); } { let v = ["Hello".to_owned()]; 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); } { let v = [1, 2, 3]; 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,3,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(~[2,3,1])); assert_eq!(it.next(), Some(~[2,1,3])); @@ -2789,10 +2825,15 @@ fn test_permutations() { // check that we have N! permutations let v = ['A', 'B', 'C', 'D', 'E', 'F']; 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; } + assert_eq!(amt, it.swaps.swaps_made); + assert_eq!(amt, min_size); assert_eq!(amt, 2 * 3 * 4 * 5 * 6); + assert_eq!(amt, max_opt.unwrap()); } }