In Python, I can do:
from itertools import product
k = 3
for kmer in product("AGTC", repeat=k):
print(kmer)
In Rust, I can force the behavior of k=3
by:
#[macro_use] extern crate itertools;
for kmer in iproduct!("AGTC".chars(), "AGTC".chars(), "AGTC".chars()){
println!("{:?}", kmer);
}
But what if I wanted k=4
or k=5
?
Writing a proper generalisation for any type for any k would be hard because the return type could be tuples of any size. As you want to work only on String
, it's quite easier: playground
fn kproduct(seq: String, k: u32) -> Vec<String> {
match k {
0 => vec![],
1 => seq.chars().map(|c| c.to_string()).collect(),
2 => iproduct!(seq.chars(), seq.chars()).map(|(a, b)| format!("{}{}", a, b)).collect(),
_ => iproduct!(kproduct(seq.clone(), k - 1), seq.chars()).map(|(a, b)| format!("{}{}", a, b)).collect(),
}
}