Skip to content

Instantly share code, notes, and snippets.

@RangerDane
Last active November 2, 2016 04:33
Show Gist options
  • Save RangerDane/11f2a9a6563f79e8b138e7fd6292d1c8 to your computer and use it in GitHub Desktop.
Save RangerDane/11f2a9a6563f79e8b138e7fd6292d1c8 to your computer and use it in GitHub Desktop.
Sieve of Eratosthenes in Ruby
# Sieve of Eratosthenes. Use it for all of your prime number shenanigans.
# Built this for solving Project Euler problems.
# Hash map chosen over array after careful arbitrary consideration.
### O(1) amortized lookup of any prime with dynamic resizing.
### O(n) memory where n = size of cache, but RAM is cheap these days.
class Sieve
def initialize()
@size = 64
@next = 1
# assume all numbers are innocent (prime) until proven not guilty (divisible)
@cache = Hash.new { true }
build!
end
def is_prime?( x )
if x < 2
return false
elsif x > @size
# puts "[SIEVE] Size " + @size.to_s + " too small to test " + x.to_s
# resize to next power of 2
@size = 2 ** ( Math.log( x, 2 ).ceil + 1 )
build!
end
@cache[x]
end
# vomit out an array of primes less than max
def vomit(max)
(2..max).to_a.select { |x| self.is_prime? n }
end
def next
loop do
@next += 1
break if is_prime?( @next )
end
@next
end
def self.instance
@sieve_instance ||= self.new
end
def self.is_prime?( n )
self.instance.is_prime? n
end
def self.vomit( max )
self.instance.vomit max
end
def self.next
self.instance.next
end
private
def build!
# puts "[SIEVE] Building cache of size " + @size.to_s
# microoptimization - no number has divisors higher than its square root
max = Math.sqrt(@size).to_i
(2..max).each do |x|
if @cache[x]
multi = x * x
while multi <= @size
@cache[multi] = false
multi += x
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment