euler/crystal/prime.cr

69 lines
1.4 KiB
Crystal

require "./euler"
module Euler
class Prime
include Iterator(NumType | BigInt)
def initialize()
@sieve_size = 16
@sieved_up_to = 0
@primes = Array(Bool).new(@sieve_size, true)
@primes[0] = false
@primes[1] = false
@index = 0
iterative_eratosthenes_sieve
end
private def check_and_increase_sieve
if @index > @primes.size - 1
@sieve_size *= 2
until @primes.size == @sieve_size
@primes << true
end
end
iterative_eratosthenes_sieve
end
private def iterative_eratosthenes_sieve
2.step(to: Math.sqrt(@sieve_size)) do |i|
if @primes[i]
(i * i >= @sieved_up_to ? i * i : @sieved_up_to + i - (@sieved_up_to % i)).step(to: @sieve_size-1, by: i) do |j|
@primes[j] = false
end
end
end
@sieved_up_to = @sieve_size-1
end
def next
@index += 1
check_and_increase_sieve
until @primes[@index]
@index += 1
check_and_increase_sieve
end
@index
end
def self.eratosthenes_sieve(n)
sieve = Array.new(n + 1, true)
sieve[0] = false
sieve[1] = false
2.step(to: Math.sqrt(n)) do |i|
if sieve[i]
(i * i).step(to: n, by: i) do |j|
sieve[j] = false
end
end
end
result = sieve.map_with_index { |b, i| b ? i : nil }.compact
end
end
end