Problem 10
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
I've been doing a lot of exploring through the crate.io website. I've found much like the old apple istore catch phrase, there's a crate for that.
I utilized a library called prime_tools. The library has a function that literally finds all prime numbers less than a given number. It returns a vector as 32bit unsigned integers. From there we could loop through using vector.init().sum() however, sum() isn't a function of u64 and the answer here exceeds the max of a u32. So I went with a for loop. Someday I hope to learn a better way
Tmol file -
[dependencies]
prime_tools = "0.3.4"
main.rs
fn main(){
let my_vec = prime_tools::get_primes_less_than_x(2000000);
let mut my_sum: u64 = 0;
for i in my_vec{
my_sum = my_sum + i as u64;
}
println!("{}", my_sum);
}
Now, this is kind of a cop out in someways but it gets the job done. The alternative is to go through and brute force it. Alternatively, you could use a sieve until you got to or exceeded 2000000. This was my go to.
There was another user that used rust and went with the sieve method. I won't go into that here as I've already covered it with a previous problem that addressed prime numbers.
User Hegemon8 used an interesting brute force method.
Slick. 0.64s fn main() { let mut vector:Vec<bool> = vec![false; 2_000_000]; for i in 2..1415 { if vector[i] == false { let mut j = i * i; while j < vector.len() { vector[j] = true; j = j + i; } } } let mut sum = 0; for (index, i) in vector.iter().enumerate() { if i == &false { sum = sum + index; } } println!("{}", sum - 1); }
He created a vector of 2000000 values of bools all set to false. They he looped through all the values from 2 to 1415. Then if the value of the loop in the vector was false, he multiplied it by itself and set it to true if that index existed. The significance of 1415 is that squared it exceeds 20000000 and 1414 falls a little short. If you square a number the resulting number can't be prime. This is a clever sieve method that's more compact than other's I've seen. He then sums up all the false indexes and returns the sum.
I was curious if we could clean this up.
Maybe?
Here's my rewrite for the for loop at the bottom
let sum: u64 = vector.into_iter().enumerate().fold(0, |s, (i, j)| s + eval(i as u64, j));
println!("{}", sum);
Then I had to add a function.
fn eval(x: u64, y: bool) -> u64{
match y { true => 0, false => x as u64}
}
Now. It seems that the reason I had to use u64 is cause the answer is soooo big.
I learned a lot about the fold method doing this (4 hours of head to desk before it worked). I also learned that in a fold, you can't (or I couldn't find how) to use a filter/match/ifelse statement. I tried but match wouldn't work....
As I write this, I had a facepalm moment. Yup learning in real time now. :(
I went back and tried something. It worked.
let sum: u64 = vector.into_iter()
.enumerate()
.fold(0, |s, (i, j)| s + match j { true => 0, false => i as u64});
Yup, so the match did work. I realized when I tried earlier I didn't add to the s value which is the total sum.
Correct me if I'm wrong (please).
fold (starting value, |return value, value_i'm evaluating in the iter| formula evaluated and added to the return value)
That's my understanding anyways.
No comments:
Post a Comment