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