Skip to content

Instantly share code, notes, and snippets.

@conradludgate
Created May 22, 2021 09:57
Show Gist options
  • Save conradludgate/2d84b6c7cae88003c87b519777c6fd51 to your computer and use it in GitHub Desktop.
Save conradludgate/2d84b6c7cae88003c87b519777c6fd51 to your computer and use it in GitHub Desktop.
Works for r = 3, almost works for other r
use std::{fmt::Debug, ops::Range};
fn main() {
let mut v = vec![1, 2, 3, 4, 5, 6];
let r = 3;
for x in CombiIterator::new(&mut v, r) {
println!("{:?}", x);
}
}
struct CombiIterator<'a, T> {
slice: &'a mut [T],
range: Range<usize>,
r: usize,
step: usize,
end: usize,
}
impl<'a, T> CombiIterator<'a, T> {
fn new(slice: &'a mut [T], r: usize) -> Self {
let n = slice.len();
Self {
slice,
range: r - 1..n,
r,
step: 0,
end: n,
}
}
}
impl<'a, T: Clone + Debug> Iterator for CombiIterator<'a, T> {
type Item = Vec<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.end < self.r {
return None;
}
let output = self.slice[..self.r].to_vec();
self.slice[self.range.clone()].rotate_left(1);
self.step += 1;
if self.step == self.range.len() {
if self.range.len() == 1 {
self.slice[1..self.end].rotate_left(self.r - 1);
self.slice[..].rotate_left(1);
self.end -= 1;
self.range.end = self.end;
} else {
self.slice[(self.range.start - 1)..self.end].rotate_left(1);
self.range.end -= 1;
}
self.step = 0;
}
Some(output)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment