โข Option
โข Result
โข The ? operator propagates errors up the call stack concisely
โข Combinators like .map(), .and_then(), .unwrap_or() chain fallible operations
โข The compiler forces you to handle every error case โ no silent failures
โข Option
โข Result
โข The ? operator propagates errors up the call stack concisely
โข Combinators like .map(), .and_then(), .unwrap_or() chain fallible operations
โข The compiler forces you to handle every error case โ no silent failures
from itertools import combinations
list(combinations(['a','b','c','d'], 2))
Rust doesn't have a built-in combinations iterator (though the `itertools` crate does). Understanding the recursive structure makes you independent of any library and clarifies why there are exactly C(n, k) = n! / (k! * (n-k)!) results.
fn combinations<T: Clone>(k: usize, lst: &[T]) -> Vec<Vec<T>> {
if k == 0 {
return vec![vec![]]; // one empty combination (base case)
}
if k > lst.len() {
return vec![]; // impossible: can't choose more than we have
}
let head = &lst[0];
let tail = &lst[1..];
// Branch 1: combinations that include `head`
let with_head: Vec<Vec<T>> = combinations(k - 1, tail)
.into_iter()
.map(|mut combo| {
combo.insert(0, head.clone()); // prepend head to each sub-combo
combo
})
.collect();
// Branch 2: combinations that exclude `head`
let without_head = combinations(k, tail);
// Merge both branches
let mut result = with_head;
result.extend(without_head);
result
}
Trace for `combinations(2, ['a','b','c'])`:
| Concept | OCaml | Rust |
|---|---|---|
| Recursive structure | Pattern match on `hd::tl` | `lst[0]` (head) + `lst[1..]` (tail) |
| Base case k=0 | Returns `[[]]` | Returns `vec![vec![]]` (one empty Vec) |
| Prepend element | `hd :: combo` | `combo.insert(0, head.clone())` |
| Merge branches | `@` (list concat) | `result.extend(without_head)` |
| Bitmask variant | Unusual in OCaml style | Natural with `u64` bit operations |
// Combinations โ 99 Problems #26
// Generate all combinations of k distinct objects from a list.
// combinations 3 ['a','b','c','d'] โ [['a','b','c'],['a','b','d'],['a','c','d'],['b','c','d']]
fn combinations<T: Clone>(k: usize, lst: &[T]) -> Vec<Vec<T>> {
if k == 0 {
return vec![vec![]];
}
if k > lst.len() {
return vec![];
}
let head = &lst[0];
let tail = &lst[1..];
// Combinations including head
let with_head: Vec<Vec<T>> = combinations(k - 1, tail)
.into_iter()
.map(|mut combo| {
combo.insert(0, head.clone());
combo
})
.collect();
// Combinations excluding head
let without_head = combinations(k, tail);
let mut result = with_head;
result.extend(without_head);
result
}
/// Iterative version using bitmask enumeration (works for small lists).
fn combinations_bitmask<T: Clone>(k: usize, lst: &[T]) -> Vec<Vec<T>> {
let n = lst.len();
if k > n {
return vec![];
}
let mut result = Vec::new();
// Enumerate all subsets of size k
for mask in 0u64..(1u64 << n) {
if mask.count_ones() as usize == k {
let combo: Vec<T> = (0..n)
.filter(|&i| (mask >> i) & 1 == 1)
.map(|i| lst[i].clone())
.collect();
result.push(combo);
}
}
result
}
fn main() {
let input = vec!['a', 'b', 'c', 'd'];
println!("combinations(2, {:?}):", input);
for c in combinations(2, &input) {
print!(" {:?}", c);
}
println!();
println!("combinations(3, {:?}):", input);
for c in combinations(3, &input) {
print!(" {:?}", c);
}
println!();
let count = combinations(3, &['a', 'b', 'c', 'd', 'e', 'f']).len();
println!("C(6,3) = {}", count); // should be 20
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_combinations_0() {
// C(n, 0) = 1 (the empty combination)
assert_eq!(combinations(0, &[1, 2, 3]), vec![vec![]]);
}
#[test]
fn test_combinations_all() {
// C(n, n) = 1
assert_eq!(combinations(3, &['a', 'b', 'c']), vec![vec!['a', 'b', 'c']]);
}
#[test]
fn test_combinations_count() {
// C(6, 3) = 20
assert_eq!(combinations(3, &[1, 2, 3, 4, 5, 6]).len(), 20);
// C(4, 2) = 6
assert_eq!(combinations(2, &['a', 'b', 'c', 'd']).len(), 6);
}
#[test]
fn test_combinations_k_exceeds_n() {
assert_eq!(combinations(5, &[1, 2, 3]), vec![] as Vec<Vec<i32>>);
}
}
(* Combinations *)
(* OCaml 99 Problems #26 *)
(* Implementation for example 26 *)
(* Tests *)
let () =
(* Add tests *)
print_endline "โ OCaml tests passed"