I want to do a sieve that doesn't take advantage of the obvious math hacks. I want to brute force it. My algorithm is conceived with the notion that the sieve does a lot of checking for what are not prime numbers and just returning the result of the operations to check those rather than to figure out what are prime numbers. I think some Carmichael Numbers prove it to be invalid for something very large. I could be wrong on that. I went on to check numbers from a range, and followed the basic algorithm given from Wikipedia.
def primes(n)
nums = (2..n)
not_prime = []
primes = []
nums.to_a.each_with_index do |it, idx|
primes << it unless not_prime.include?(it)
p primes.last
p nums.step(primes.last).to_a
nums.step(primes.last).each_with_index do |num, idx|
next if idx == 0
not_prime << num
end
end
primes
end
When my range does the line:
nums.step(primes.last).each_with_index
for numbers other than the first one (2
), I get an off-by-x error (compounding on the list I believe). For example, all the non prime two multiples are found, but for the multiples of three, the step on the range returns 2
, 5
, 8
, 11
, etc., which are off by one.
I'm trying to figure out a solution using Range
objects or converting to an Array
, but I like the conciseness of my (wrong) solution. Anyone think they can help me solve this?
EDIT:
I fixed it! The solution was creating an entirely new range to iterate over rather than taking the original range. See below. Shout out to Jörg W Mittag for the inspiration to just create a new range instead of trying to fiddle with the original immutable object which is what I was trying to do. Square peg in round hole sounds so much better sometimes.
def primes(n)
nums = (2..n)
not_prime = []
primes = []
nums.to_a.each_with_index do |it, idx|
next if not_prime.include?(it)
primes << it
((primes.last)..n).step(primes.last).each_with_index do |num, idx|
next if idx == 0 || num == primes.last
not_prime << num
end
end
primes
end