Reputation: 732
I continue to struggle with the concept of recursion. I have a function that takes a u64
and returns a Vec<u64>
of factors of that integer. I would like to recursively call this function on each item in the Vec
, returning a flattened Vec
until the function returns Vec<self>
for each item, i.e., each item is prime.
fn prime_factors(x: u64) -> Vec<u64> {
let factors = factoring_method(x);
factors.iter().flat_map(|&i| factoring_method(i)).collect()
}
This returns only the Vec
of factors of the final iteration and also has no conditional that allows it to keep going until items are all prime.
The factoring_method
is a congruence of squares that I'm pretty happy with. I'm certain there's lots of room for optimization, but I'm hoping to get a working version complete before refactoring. I think the recursion should in the congruence_of_squares
— calling itself upon each member of the Vec
it returns, but I'm not sure how to frame the conditional to keep it from doing so infinitely.
Upvotes: 1
Views: 916
Reputation: 431809
Useful recursion requires two things:
One definition of the prime factorization of a number is:
From that, we can identify a termination condition ("if it's prime") and the recursive call ("prime factors of factors").
Note that we haven't written any code yet — everything to this point is conceptual.
We can then transcribe the idea to Rust:
fn prime_factors(x: u64) -> Vec<u64> {
if is_prime(x) {
vec![x]
} else {
factors(x).into_iter().flat_map(prime_factors).collect()
}
}
Interesting pieces here:
into_iter
to avoid the need to dereference the iterated value.Some (inefficient) helper functions round out the implementation:
fn is_prime(x: u64) -> bool {
!(2..x).any(|i| x % i == 0)
}
fn factors(x: u64) -> Vec<u64> {
match (2..x).filter(|i| x % i == 0).next() {
Some(v) => vec![v, x / v],
None => vec![],
}
}
Upvotes: 2