Skip to content

Instantly share code, notes, and snippets.

@shostakovich
Created October 19, 2012 14:51
Show Gist options
  • Save shostakovich/3918622 to your computer and use it in GitHub Desktop.
Save shostakovich/3918622 to your computer and use it in GitHub Desktop.
prime.rb
class EratosthenesGenerator < PseudoPrimeGenerator
def initialize
@last_prime = nil
super
end
def succ
@last_prime = @last_prime ? EratosthenesSieve.instance.next_to(@last_prime) : 2
end
def rewind
initialize
end
alias next succ
end
class Generator23 < PseudoPrimeGenerator
def initialize
@prime = 1
@step = nil
super
end
def succ
loop do
if (@step)
@prime += @step
@step = 6 - @step
else
case @prime
when 1; @prime = 2
when 2; @prime = 3
when 3; @prime = 5; @step = 2
end
end
return @prime
end
end
alias next succ
def rewind
initialize
end
end
class Integer
def Integer.from_prime_division(pd)
Prime.int_from_prime_division(pd)
end
def prime_division(generator = Prime::Generator23.new)
Prime.prime_division(self, generator)
end
def prime?
Prime.prime?(self)
end
def Integer.each_prime(ubound, &block) # :yields: prime
Prime.each(ubound, &block)
end
end
class Prime
include Enumerable
@the_instance = Prime.new
def initialize
@generator = EratosthenesGenerator.new
warn "Prime::new is obsolete. use Prime::instance or class methods of Prime."
end
class << self
extend Forwardable
include Enumerable
# Returns the default instance of Prime.
def instance; @the_instance end
def method_added(method) # :nodoc:
(class<< self;self;end).def_delegator :instance, method
end
end
def each(ubound = nil, generator = EratosthenesGenerator.new, &block)
generator.upper_bound = ubound
generator.each(&block)
end
def prime?(value, generator = Prime::Generator23.new)
value = -value if value < 0
return false if value < 2
for num in generator
q,r = value.divmod num
return true if q < num
return false if r == 0
end
end
def int_from_prime_division(pd)
pd.inject(1){|value, (prime, index)|
value *= prime**index
}
end
def prime_division(value, generator= Prime::Generator23.new)
raise ZeroDivisionError if value == 0
if value < 0
value = -value
pv = [[-1, 1]]
else
pv = []
end
for prime in generator
count = 0
while (value1, mod = value.divmod(prime)
mod) == 0
value = value1
count += 1
end
if count != 0
pv.push [prime, count]
end
break if value1 <= prime
end
if value > 1
pv.push [value, 1]
end
return pv
end
end
class PseudoPrimeGenerator
include Enumerable
def initialize(ubound = nil)
@ubound = ubound
end
def upper_bound=(ubound)
@ubound = ubound
end
def upper_bound
@ubound
end
def succ
raise NotImplementedError, "need to define `succ'"
end
def next
raise NotImplementedError, "need to define `next'"
end
.
def rewind
raise NotImplementedError, "need to define `rewind'"
end
def each(&block)
return self.dup unless block
if @ubound
last_value = nil
loop do
prime = succ
break last_value if prime > @ubound
last_value = block.call(prime)
end
else
loop do
block.call(succ)
end
end
end
alias with_index each_with_index
def with_object(obj)
return enum_for(:with_object) unless block_given?
each do |prime|
yield prime, obj
end
end
end
def [](index)
while index >= @primes.length
#calculate the number and push it to primes
end
return @primes[index]
end
class TrialDivisionGenerator<PseudoPrimeGenerator
def initialize
@index = -1
super
end
def succ
TrialDivision.instance[@index += 1]
end
def rewind
initialize
end
alias next succ
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment