Sha256: 56337e47d601ccd9282675ea5a6e1b445064cc5303c815133639295c3335d7d2

Contents?: true

Size: 997 Bytes

Versions: 1

Compression:

Stored size: 997 Bytes

Contents

require "prime_sieve"

class UlamSequence
  include Enumerable

  attr_reader :max, :size

  def initialize(size)
    @size = size.to_i
    @max = @size**2
    @sieve = PrimeSieve.new(@max)
  end

  def each
    return to_enum { size } unless block_given?

    points = Enumerator.new do |yielder|
      walk_cycle = [
        lambda { |x, y| [x + 1, y] }, # east
        lambda { |x, y| [x, y - 1] }, # north
        lambda { |x, y| [x - 1, y] }, # west
        lambda { |x, y| [x, y + 1] }, # south
      ].cycle

      x, y = origin
      i = 1
      advance_point = walk_cycle.next

      loop do
        ((i + 1) / 2).times do
          yielder << [x, y]
          x, y = advance_point.call(x, y)
        end

        advance_point = walk_cycle.next
        i += 1
      end
    end

    1.upto(max) do |n|
      x, y = points.next
      yield [x, y, n, sieve.prime?(n)]
    end
  end

  def origin
    [
      (size - 1) / 2,
      size / 2,
    ]
  end

  private

  attr_reader :sieve
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
ulaminate-0.1.0 lib/ulam_sequence.rb