1#![doc(html_root_url = "https://docs.rs/gen-combinations/0.1.0")]
2#[derive(Debug)]
30pub struct CombinationIterator<'a, T> {
31 items: &'a [T],
32 indices: Vec<usize>,
33}
34
35impl<T> CombinationIterator<'_, T> {
36 pub fn new(items: &[T], n: usize) -> CombinationIterator<T> {
40 let indices = (0..n).collect();
41 CombinationIterator { items, indices }
42 }
43}
44
45impl<'a, T> Iterator for CombinationIterator<'a, T> {
46 type Item = Vec<&'a T>;
47
48 fn next(&mut self) -> Option<Vec<&'a T>> {
49 if self.indices.is_empty() || self.indices.len() > self.items.len() {
50 None
51 } else {
52 let ret = self.indices.iter().map(|i| &(self.items[*i])).collect();
53 for i in (0..self.indices.len()).rev() {
54 if self.indices[i] < self.items.len() - (self.indices.len() - i) {
55 self.indices[i] += 1;
56 for j in i..self.indices.len() {
57 self.indices[j] = self.indices[i] + (j - i);
58 }
59 return Some(ret);
60 }
61 }
62 self.indices.clear(); Some(ret)
64 }
65 }
66}
67
68#[test]
69fn generate_combinations() {
70 let items = [1, 2, 3];
71 let mut c = CombinationIterator::new(&items, 2);
72 assert_eq!(c.next(), Some(vec![&1, &2]));
73 assert_eq!(c.next(), Some(vec![&1, &3]));
74 assert_eq!(c.next(), Some(vec![&2, &3]));
75 assert_eq!(c.next(), None);
76}
77
78#[test]
79fn generate_more_combinations() {
80 let items = [1, 2, 3, 4, 5];
81 let mut c = CombinationIterator::new(&items, 3);
82 assert_eq!(c.next(), Some(vec![&1, &2, &3]));
83 assert_eq!(c.next(), Some(vec![&1, &2, &4]));
84 assert_eq!(c.next(), Some(vec![&1, &2, &5]));
85 assert_eq!(c.next(), Some(vec![&1, &3, &4]));
86 assert_eq!(c.next(), Some(vec![&1, &3, &5]));
87 assert_eq!(c.next(), Some(vec![&1, &4, &5]));
88 assert_eq!(c.next(), Some(vec![&2, &3, &4]));
89 assert_eq!(c.next(), Some(vec![&2, &3, &5]));
90 assert_eq!(c.next(), Some(vec![&2, &4, &5]));
91 assert_eq!(c.next(), Some(vec![&3, &4, &5]));
92 assert_eq!(c.next(), None);
93}
94
95#[test]
96fn generate_combinations_of_things_that_arent_copy_just_to_be_sure() {
97 let items = [String::from("one"), String::from("two"), String::from("yeet")];
98 let mut c = CombinationIterator::new(&items, 2);
99 assert_eq!(c.next(), Some(vec![&String::from("one"), &String::from("two")]));
100 assert_eq!(c.next(), Some(vec![&String::from("one"), &String::from("yeet")]));
101 assert_eq!(c.next(), Some(vec![&String::from("two"), &String::from("yeet")]));
102 assert_eq!(c.next(), None);
103}
104
105#[test]
106fn misuse_arguments() {
107 let items = [1, 2, 3];
108 let mut c = CombinationIterator::new(&items, 500);
109 assert_eq!(c.next(), None);
110
111 let mut c = CombinationIterator::new(&items, 0);
112 assert_eq!(c.next(), None);
113}