Skip to content

Instantly share code, notes, and snippets.

@conradludgate
Last active May 23, 2021 09:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save conradludgate/434d02bcd59f0c2f6db6aaeb00727fff to your computer and use it in GitHub Desktop.
Save conradludgate/434d02bcd59f0c2f6db6aaeb00727fff to your computer and use it in GitHub Desktop.
Seems to work for any r and any n
fn main() {
let v = vec![1, 2, 3, 4, 5, 6];
let r = 3;
for x in CombiIterator::new(v, r) {
println!("{:?}", x);
}
}
#[derive(Debug, Clone)]
struct CombiIterator<T> {
slice: Vec<T>,
r: usize,
ends: Vec<usize>,
}
impl<T> CombiIterator<T> {
fn new(slice: Vec<T>, r: usize) -> Self {
let n = slice.len();
let mut ends = Vec::with_capacity(r);
ends.resize(r, n);
Self {
slice,
r,
ends,
}
}
}
impl<T: Clone> Iterator for CombiIterator<T> {
type Item = Vec<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.ends[0] < self.r {
return None;
}
let output = self.slice[..self.r].to_vec();
self.slice[self.r-1..self.ends[0]].rotate_left(1);
self.ends[0] -= 1;
let mut x = 0;
for i in 0..self.r-1 {
if self.ends[i] < self.r {
self.ends[i+1] -= 1;
x = i + 1;
} else {
break;
}
}
for i in 0..x {
self.ends[i] = self.ends[x];
}
if x > 0 {
let e = self.ends[0] + 1;
self.slice[self.r-x..self.r].reverse();
self.slice[self.r-x..e].reverse();
self.slice[self.r-x-1..e].rotate_left(1);
}
Some(output)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment