Last active
April 30, 2018 19:40
-
-
Save ericyd/101ce779a6550a28a5c3e3109f0b84cb to your computer and use it in GitHub Desktop.
Rust script to get all possible combinations of sets of vectors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// some experiments with combinations and deduping | |
// I think clippy has some good recommendations - I wrote this while learning Rust so it's rough | |
fn main() { | |
let arr = vec![vec![1, 1, 1], vec![2, 2, 2], vec![3, 3, 3], vec![4, 4, 4]]; | |
let mut indices = arr.iter().map(|ref _x| 0).collect(); | |
let mut paths: Vec<Vec<usize>> = vec![]; | |
let paths = find_combinations(&arr, &mut indices, 0, &mut paths); | |
let paths_dedupe1 = dedupe(&paths, &mut vec![]); | |
let paths_dedupe2 = dedupe2(&paths); | |
assert_eq!(paths.len(), paths_dedupe1.len(), "dedupe 1 has different length than original"); | |
assert_eq!(paths.len(), paths_dedupe2.len(), "dedupe 2 has different length than original"); | |
// this is only true if they are all the same size | |
// e.g. {elements per array}^{number of arrays} | |
// else, would have to just multiply lengths of all elements in arr | |
assert_eq!( | |
paths.len(), | |
arr[0].len().pow(arr.len() as u32), | |
"paths contains wrong number of elements" | |
); | |
} | |
fn find_combinations<'a>( | |
arr: &Vec<Vec<i32>>, | |
indices: &mut Vec<usize>, | |
index: usize, | |
paths: &'a mut Vec<Vec<usize>>, | |
) -> &'a Vec<Vec<usize>> { | |
for (i, _) in arr[index].iter().enumerate() { | |
let i = i as usize; | |
indices[index] = i; | |
if index == arr.len() - 1 { | |
paths.push(indices.clone()); | |
} | |
if index < arr.len() - 1 { | |
find_combinations(arr, indices, index + 1, paths); | |
} | |
} | |
paths | |
} | |
fn dedupe(arr: &Vec<Vec<usize>>, result: &mut Vec<Vec<usize>>) -> Vec<Vec<usize>> { | |
for (i, val) in arr.iter().enumerate() { | |
// if first item that matches this value is the value itself, | |
// it is not a duplicate. Otherwise, it is. | |
match arr.iter().position(|ref x| x == &val) { | |
Some(x) => { | |
if x == i { | |
result.push(val.clone()); | |
} | |
} | |
None => (), | |
} | |
} | |
result.clone() | |
} | |
fn dedupe2(arr: &Vec<Vec<usize>>) -> Vec<Vec<usize>> { | |
arr.iter() | |
.enumerate() | |
.filter(|&(index, value)| match arr.iter().position( | |
|ref y| y == &value, | |
) { | |
Some(x) => { | |
if index == x { | |
return true; | |
} | |
return false; | |
} | |
None => return false, | |
}) | |
.map(|(_index, value)| value.clone()) | |
.collect() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment