Reputation: 24895
The following two functions, which check if a number is prime:
def prime1?(prime_candidate)
return true if [1, 2].include? prime_candidate
range = 2.upto(Math.sqrt(prime_candidate).ceil).to_a
i = 0
while i < range.count
return false if prime_candidate % range[i] == 0
range = range.reject { |j| j % range[i] == 0 }
end
true
end
def prime2?(prime_candidate)
return true if [1, 2].include? prime_candidate
range = 2.upto(Math.sqrt(prime_candidate).ceil).to_a
range.each do |i|
return false if prime_candidate % i == 0
range = range.reject { |j| j % i == 0 }
end
true
end
yield the following benchamrking result when testing with a very large prime (5915587277):
user system total real
prime1: 2.500000 0.010000 2.510000 ( 2.499585)
prime2: 20.700000 0.030000 20.730000 ( 20.717267)
Why is that? Is it because in the second function range
does not get modified by the reject
, so the each
is iterating over the original long range
?
Upvotes: 0
Views: 628
Reputation: 60068
When you do range=range.reject {..}
, you don't modify the parent range (which you shouldn't do, because it would mess up the iteration--you need reject!
to do that) but rather construct a temporary array which only gets assigned to the parent range variable at the end of the iteration.
The each
iteration in prime2
runs over the whole original range, not the shortened which, before the loop ends, only exist in the block.
The while version modifies the original array and is therefore quicker (BTW, you realize that i remains zero and it's the range.count
that changes (decreases) in that while condition and that reject iterates over the WHOLE array again--even the beginning where there couldn't possibly be any more nonprimes to reject).
You'll get a much faster result if you improve the logic of your code. That array manipulation is costly and for this, you don't even need an array:
def prime3?(prime_candidate)
return false if prime_candidate==1
return true if prime_candidate==2
range = 2..(Math.sqrt(prime_candidate).ceil)
range.all? {|x| prime_candidate % x !=0 }
end #about 300× times as fast for your example as prime1? on my PC
Upvotes: 2