Skip to content

Instantly share code, notes, and snippets.

@kylewlacy
Created November 17, 2015 07:28
Show Gist options
  • Save kylewlacy/115965b40e02a3325558 to your computer and use it in GitHub Desktop.
Save kylewlacy/115965b40e02a3325558 to your computer and use it in GitHub Desktop.
Cartesian product function in Rust
/// Given a vector containing a partial Cartesian product, and a list of items,
/// return a vector adding the list of items to the partial Cartesian product.
///
/// # Example
///
/// ```
/// let partial_product = vec![vec![1, 4], vec![1, 5], vec![2, 4], vec![2, 5]];
/// let items = &[6, 7];
/// let next_product = partial_cartesian(partial_product, items);
/// assert_eq!(next_product, vec![vec![1, 4, 6],
/// vec![1, 4, 7],
/// vec![1, 5, 6],
/// vec![1, 5, 7],
/// vec![2, 4, 6],
/// vec![2, 4, 7],
/// vec![2, 5, 6],
/// vec![2, 5, 7]]);
/// ```
pub fn partial_cartesian<T: Clone>(a: Vec<Vec<T>>, b: &[T]) -> Vec<Vec<T>> {
a.into_iter().flat_map(|xs| {
b.iter().cloned().map(|y| {
let mut vec = xs.clone();
vec.push(y);
vec
}).collect::<Vec<_>>()
}).collect()
}
/// Computes the Cartesian product of lists[0] * lists[1] * ... * lists[n].
///
/// # Example
///
/// ```
/// let lists: &[&[_]] = &[&[1, 2], &[4, 5], &[6, 7]];
/// let product = cartesian_product(lists);
/// assert_eq!(product, vec![vec![1, 4, 6],
/// vec![1, 4, 7],
/// vec![1, 5, 6],
/// vec![1, 5, 7],
/// vec![2, 4, 6],
/// vec![2, 4, 7],
/// vec![2, 5, 6],
/// vec![2, 5, 7]]);
/// ```
pub fn cartesian_product<T: Clone>(lists: &[&[T]]) -> Vec<Vec<T>> {
match lists.split_first() {
Some((first, rest)) => {
let init: Vec<Vec<T>> = first.iter().cloned().map(|n| vec![n]).collect();
rest.iter().cloned().fold(init, |vec, list| {
partial_cartesian(vec, list)
})
},
None => {
vec![]
}
}
}
/// Print the Cartesian product of a set of lists to stdout, in
/// the following form:
///
/// ```text
/// 1 4 6
/// 1 4 7
/// 1 5 6
/// 1 5 7
/// 2 4 6
/// 2 4 7
/// ...
/// ```
pub fn print_cartesian_product(lists: &[&[i32]]) {
let products = cartesian_product(lists);
for product in products.iter() {
let product_str: Vec<_> = product.iter().map(|n| format!("{}", n)).collect();
let line = product_str.join(" ");
println!("{}", line);
}
}
fn main() {
let a = &[1, 2, 3];
let b = &[4, 5];
let c = &[6, 7, 8];
print_cartesian_product(&[a, b, c]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment