lowdash/
combination.rs

1/// Finds all combinations of k elements from a collection.
2///
3/// # Arguments
4/// * `items` - A slice of items to combine
5/// * `k` - The number of elements to select in each combination
6///
7/// # Returns
8/// * `Vec<Vec<T>>` - A vector containing all combinations of k elements from the input
9///
10/// # Examples
11/// ```rust
12/// use lowdash::combination;
13///
14/// let items = vec![1, 2, 3, 4];
15/// let result = combination(&items, 2);
16/// assert_eq!(result.len(), 6);
17/// // One possible combination: [2, 3]
18/// assert!(result.contains(&vec![2, 3]));
19/// ```
20pub fn combination<T: Clone>(items: &[T], k: usize) -> Vec<Vec<T>> {
21    if k == 0 {
22        return vec![vec![]];
23    }
24    if k > items.len() {
25        return vec![];
26    }
27    let mut result = Vec::new();
28    for i in 0..=items.len() - k {
29        let current = items[i].clone();
30        let rest_combinations = combination(&items[i + 1..], k - 1);
31        for mut comb in rest_combinations {
32            let mut entry = vec![current.clone()];
33            entry.append(&mut comb);
34            result.push(entry);
35        }
36    }
37    result
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn test_combination_k_zero() {
46        let items = vec![1, 2, 3];
47        let result = combination(&items, 0);
48        assert_eq!(result, vec![vec![]]);
49    }
50
51    #[test]
52    fn test_combination_k_greater_than_len() {
53        let items = vec![1, 2];
54        let result = combination(&items, 3);
55        assert!(result.is_empty());
56    }
57
58    #[test]
59    fn test_combination_single_element() {
60        let items = vec![42];
61        let result = combination(&items, 1);
62        assert_eq!(result, vec![vec![42]]);
63    }
64
65    #[test]
66    fn test_combination_multiple() {
67        let items = vec![1, 2, 3, 4];
68        let result = combination(&items, 2);
69        // combinations: [1,2], [1,3], [1,4], [2,3], [2,4], [3,4]
70        assert_eq!(result.len(), 6);
71        assert!(result.contains(&vec![1, 2]));
72        assert!(result.contains(&vec![2, 4]));
73    }
74
75    #[test]
76    fn test_combination_all_elements() {
77        let items = vec![1, 2, 3];
78        let result = combination(&items, 3);
79        assert_eq!(result, vec![vec![1, 2, 3]]);
80    }
81}