pub struct Choose<T: Copy> {
vec: Vec<T>,
k: usize,
indices: Vec<usize>,
first: bool,
}
impl<T: Copy> Choose<T> {
fn new(vec: Vec<T>, k: usize) -> Choose<T> {
Choose { vec: vec,
k: k,
indices: range(0, k).collect(),
first: true,
}
}
fn n(&self) -> usize {
self.vec.len()
}
}
impl<T: Copy> Iterator for Choose<T> {
type Item = Vec<T>;
fn next(&mut self) -> Option<Vec<T>> {
match self.first {
true => {
match self.n() < self.k {
true => None,
false => {
self.first = false;
Some(self.indices.iter().map(|&i| *self.vec.get(i).unwrap()).collect())
}
}
},
false => {
let first_thing = range(0, self.k).rev().filter(|&_i| *self.indices.get(_i).unwrap() != _i + self.n() - self.k).take(1).collect::<Vec<usize>>();
match first_thing.len() {
0 => None,
_ => {
let i = first_thing[0];
self.indices[i] += 1;
for j in range(i+1, self.k) {
self.indices[j] = self.indices[j-1] + 1;
}
Some(self.indices.iter().map(|&i| *self.vec.get(i).unwrap()).collect())
}
}
}
}
}
}
pub trait Chooseable<T> {
fn choose(self, k: usize) -> Choose<T>;
}
impl<T: Copy> Chooseable<T> for Vec<T> {
fn choose(self, k: usize) -> Choose<T> {
Choose::new(self, k)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test] fn it_returns_none_when_choosing_one_from_an_empty_list() {
let vector: Vec<()> = vec![];
let mut it = vector.choose(1);
assert!(it.next().is_none());
}
#[test] fn it_returns_the_empty_vector_when_choosing_zero_from_an_empty_list() {
let vector: Vec<()> = vec![];
let mut it = vector.choose(0);
assert_eq!(it.next().unwrap(), vec![]);
assert!(it.next().is_none());
}
#[test] fn it_returns_the_empty_vector_when_choosing_zero_from_a_list_with_elements() {
let vector = vec![0, 1, 2];
let mut it = vector.choose(0);
assert_eq!(it.next().unwrap().len(), 0);
assert!(it.next().is_none());
}
#[test] fn it_returns_each_item_when_choosing_one_from_a_list_with_items() {
let vector = vec![0, 1, 2];
let mut it = vector.choose(1);
assert_eq!(it.next().unwrap(), vec![0]);
assert_eq!(it.next().unwrap(), vec![1]);
assert_eq!(it.next().unwrap(), vec![2]);
assert!(it.next().is_none());
}
#[test] fn it_returns_each_item_combination_when_choosing_two_from_a_list_with_items() {
let vector = vec![0, 1, 2];
let mut it = vector.choose(2);
assert_eq!(it.next().unwrap(), vec![0, 1]);
assert_eq!(it.next().unwrap(), vec![0, 2]);
assert_eq!(it.next().unwrap(), vec![1, 2]);
assert!(it.next().is_none());
}
#[test] fn it_returns_each_item_combination_when_choosing_three_from_a_list_with_four_items() {
let vector = vec![0, 1, 2, 3, 4];
let mut it = vector.choose(2);
assert_eq!(it.next().unwrap(), vec![0, 1]);
assert_eq!(it.next().unwrap(), vec![0, 2]);
assert_eq!(it.next().unwrap(), vec![0, 3]);
assert_eq!(it.next().unwrap(), vec![0, 4]);
assert_eq!(it.next().unwrap(), vec![1, 2]);
assert_eq!(it.next().unwrap(), vec![1, 3]);
assert_eq!(it.next().unwrap(), vec![1, 4]);
assert_eq!(it.next().unwrap(), vec![2, 3]);
assert_eq!(it.next().unwrap(), vec![2, 4]);
assert_eq!(it.next().unwrap(), vec![3, 4]);
assert!(it.next().is_none());
}
}