#!/usr/bin/ruby # ulam.rb - Generates an Ulam spiral # Copyright (C) 2007 Guillem Cantallops Ramis # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require "mathn" class BinaryPrimeSequence < Prime def initialize super @number = 0 @prime = self.next end def digit @number += 1 if @number == 1 then 1 elsif @number == @prime then @prime = self.next 1 else 0 end end end class SpiralWalker def initialize(dim) @dim = dim @x = @y = (@dim >> 1) + 1 @step = 1 end def path while (@step <= @dim) @step.times { break if @x > @dim or @y > @dim; yield @x, @y; @x += 1 } @step.times { break if @x > @dim or @y > @dim; yield @x, @y; @y -= 1 } @step += 1 @step.times { break if @x > @dim or @y > @dim; yield @x, @y; @x -= 1 } @step.times { break if @x > @dim or @y > @dim; yield @x, @y; @y += 1 } @step += 1 end end end exit unless (dim = Integer(ARGV[0])) > 0 dim |= 1 bps = BinaryPrimeSequence.new sw = SpiralWalker.new(dim) mtx = Array.new(dim) { Array.new(dim) { 0 } } sw.path { |x, y| mtx[x-1][y-1] = bps.digit } mtx.each { |row| row.each { |num| print num }; print "\n" }