Let's write β

プログラミング中にできたことか、思ったこととか

Rubyで一次元オートマトン part 2 (画像生成)

Cairoライブラリを利用して画像を出力できるようにしてみました。
もうすこし抽象化したいですが..

require 'cairo'

class World 
        def initialize(size)
                @map = Array.new(size, 0)
                @rule = Hash.new
        end

        def show
                @map.each do |cell|
                        if cell == 0
                                print " "
                        else
                                print "X"
                        end
                end
                puts
        end

        def cellNeighbors(idx)
                [
                        @map[idx-1],
                        @map[idx],
                        @map[(idx+1) % (@map.size)]
                ]
        end

        def getNextState(idx)
                neighbors = cellNeighbors(idx)
                nextState = @rule.fetch(neighbors,0)
                return nextState
        end

        def update
                newMap = []
                (0..@map.size-1).each do |idx|
                        newMap << (getNextState(idx))
                end
                @map = newMap
        end

        def genRandom()
                (0..@map.size-1).each do |idx|
                        @map[idx] = rand(2)
                end
        end

        def setCell(idx, n)
                @map[idx] = n
        end

        def setRule(rule, n)
                @rule[rule] = n
        end

        def genPng(size, n, cellSize = 5, filePath)
                format = Cairo::FORMAT_ARGB32
                surface = Cairo::ImageSurface.new(format,
                                                  size*cellSize,
                                                  n*cellSize)
                context = Cairo::Context.new(surface)
                context.set_source_rgb(1, 1, 1) # 白
                context.rectangle(0, 0,
                                  size*cellSize,
                                  n*cellSize)
                context.fill
                context.stroke
                context.set_source_rgb(0, 0, 0)
                (0..n-1).each do |col|
                        self.update
                        @map.each_with_index do |cell, idx|
                                if cell == 0
                                        context.rectangle(idx*cellSize, col*cellSize, cellSize, cellSize)
                                        context.fill
                                        context.stroke
                                end
                        end
                end
                surface.write_to_png(filePath)
        end

        private :cellNeighbors
        private :getNextState
        #Accessor
        attr_reader :map, :rule
end

def rule30(size,n)
        world = World.new(size)
        world.setCell(size/2,1)
        world.setRule([0,0,0],0)
        world.setRule([0,0,1],1)
        world.setRule([0,1,0],1)
        world.setRule([0,1,1],1)
        world.setRule([1,0,0],1)
        world.setRule([1,0,1],0)
        world.setRule([1,1,0],0)
        world.setRule([1,1,1],0)
        world.show
        (1..n).each do |x|
                world.update
                world.show
        end
end

def rule90(size,n)
        world = World.new(size)
        world.setCell(size/2,1)
        world.setRule([0,0,0],0)
        world.setRule([0,0,1],1)
        world.setRule([0,1,0],0)
        world.setRule([0,1,1],1)
        world.setRule([1,0,0],1)
        world.setRule([1,0,1],0)
        world.setRule([1,1,0],1)
        world.setRule([1,1,1],0)
        world.show
        (1..n).each do |x|
                world.update
                world.show
        end
end

def rule137(size,n)
        world = World.new(size)
        world.setCell(size/2,1)
        world.setRule([0,0,0],1)
        world.setRule([0,0,1],0)
        world.setRule([0,1,0],0)
        world.setRule([0,1,1],1)
        world.setRule([1,0,0],0)
        world.setRule([1,0,1],0)
        world.setRule([1,1,0],0)
        world.setRule([1,1,1],1)
        world.show
        (1..n).each do |x|
                world.update
                world.show
        end
end

def rule150(size,n)
        world = World.new(size)
        world.setCell(size/2,1)
        world.setRule([0,0,0],0)
        world.setRule([0,0,1],1)
        world.setRule([0,1,0],1)
        world.setRule([0,1,1],0)
        world.setRule([1,0,0],1)
        world.setRule([1,0,1],0)
        world.setRule([1,1,0],0)
        world.setRule([1,1,1],1)
        world.show
        (1..n).each do |x|
                world.update
                world.show
        end
end

def rule62(size,n)
        world = World.new(size)
        world.setCell(size/2,1)
        world.setRule([0,0,0],0)
        world.setRule([0,0,1],1)
        world.setRule([0,1,0],1)
        world.setRule([0,1,1],1)
        world.setRule([1,0,0],1)
        world.setRule([1,0,1],1)
        world.setRule([1,1,0],0)
        world.setRule([1,1,1],0)
        world.show
        (1..n).each do |x|
                world.update
                world.show
        end
end

def rule73(size,n)
        world = World.new(size)
        world.setCell(size/2,1)
        world.setRule([0,0,0],1)
        world.setRule([0,0,1],0)
        world.setRule([0,1,0],0)
        world.setRule([0,1,1],1)
        world.setRule([1,0,0],0)
        world.setRule([1,0,1],0)
        world.setRule([1,1,0],1)
        world.setRule([1,1,1],0)
        world.show
        (1..n).each do |x|
                world.update
                world.show
        end
end


def samplePng(fileName)
        world = World.new(100)
        world.setCell(100/2,1)
        world.setRule([0,0,0],1)
        world.setRule([0,0,1],0)
        world.setRule([0,1,0],0)
        world.setRule([0,1,1],1)
        world.setRule([1,0,0],0)
        world.setRule([1,0,1],0)
        world.setRule([1,1,0],1)
        world.setRule([1,1,1],0)

        world.genPng(100, 100, 3, fileName)
end

samplePng("hoge.png")

生成される画像は、こんな感じ。Rule73ですね。
f:id:Pocket7878_dev:20120928170033p:plain