It looks like you're trying to implement the Sieve of Eratosthenes, modified to return a certain number of primes rather than check a certain number of candidates, but there's several problems with your approach.
You start with 2 as prime, but start your search at 1. You're going to get 1 and 2 again. Your search should start at 3.
You're correct that you can gain efficiencies by iterating two at a time, but you've left 2 out of your sieve so even numbers remain. Your candidates and your divisors both need to be odds only.
Your check to see if you've matched enough primes is in the outermost loop, so it's never going to stop the inner loop.
@num
should be passed in as an argument.
Cleaning that all up, and extracting the inner loop as a function to simplify things...
# Pass in the number of primes to make the function more useful. Default to @num.
def find_prime_array(num_primes = @num)
# Start with 2 so we only have to check odd numbers.
array_prime = [2]
# Step through only the odd numbers.
(3..2001).step(2) do |i|
# Extract the prime check into a function.
array_prime << i if prime?(i)
# Stop when we have enough primes.
break if array_prime.size >= num_primes
end
array_prime
end
def prime?(i)
# Also only divide by only the odd numbers.
(3..(i-1)).step(2) do |j|
return false if i % j == 0
end
return true
end
But we can do this more efficiently. The power of the sieve is you don't have to divide every candidate by every odd number. You only need to divide by the primes you've found so far.
def find_prime_array(num_primes = @num)
array_prime = [2]
(3..2001).step(2) do |i|
array_prime << i if prime?(i, array_prime)
break if array_prime.size >= num_primes
end
array_prime
end
def prime?(i, array_prime)
array_prime.each do |j|
return false if i % j == 0
end
return true
end
Finally, we can do the same thing more idiomatically with no artificial limit.
def find_prime_array(num_primes)
primes = [2]
(3..).step(2) do |candidate|
if primes.none? { |prime| candidate % prime == 0 }
primes << candidate
end
break if primes.size >= num_primes
end
return primes
end