Skip to content

Instantly share code, notes, and snippets.

@haru01
Created December 6, 2012 13:52
Show Gist options
  • Save haru01/4224595 to your computer and use it in GitHub Desktop.
Save haru01/4224595 to your computer and use it in GitHub Desktop.
lifegame
# encoding: utf-8
module LifeGame
describe "Spaceの中央セルの状態について" do
subject { Space.start(seeds).next_time.status(1, 1) }
context "誕生:死んでいるセルに隣接する生きたセルがちょうど3つあれば次世代が誕生する" do
let(:seeds) {[ [1,1,0],
[1,0,0],
[0,0,0]]}
it { should == Space::ALIVE }
end
context "生存:生きているセルに隣接する生きたセルが2つならば、次の世代でも生存する。" do
let(:seeds) {[ [1,1,0],
[0,1,0],
[0,0,0]]}
it { should == Space::ALIVE }
end
context "生存:生きているセルに隣接する生きたセルが3つならば、次の世代でも生存する。" do
let(:seeds) {[ [1,1,1],
[0,1,0],
[0,0,0]]}
it { should == Space::ALIVE }
end
context "過疎:生きているセルに隣接する生きたセルが1つ以下ならば、過疎により死滅する。" do
let(:seeds) {[ [0,0,0],
[0,1,1],
[0,0,0]]}
it { should == Space::DEAD }
end
context "過密:生きているセルに隣接する生きたセルが4つ以上ならば、過密により死滅する。" do
let(:seeds) {[ [1,1,1],
[1,1,0],
[0,0,0]]}
it { should == Space::DEAD }
end
end
describe "サンプル例題" do
let(:first) {[ [1,1,0],
[0,0,1],
[0,1,0]]}
let(:second) {[ [0,1,0],
[1,0,1],
[0,0,0]]}
let(:third) {[ [0,1,0],
[0,1,0],
[0,0,0]]}
let(:fourth) {[ [0,0,0],
[0,0,0],
[0,0,0]] }
context "2世代目" do
subject { Space.start(first).next_time }
it { should equals_cells_status(second) }
end
context "3世代目" do
subject { Space.start(first).next_time.next_time }
it { should equals_cells_status(third) }
end
context "4世代目" do
subject { Space.start(first).next_time.next_time.next_time }
it { should equals_cells_status(fourth) }
end
end
describe "cell#count_alive_around" do
let(:seeds) {[ [1,1,1,1],
[1,1,0,1],
[1,0,0,1],
[0,0,1,1]]}
subject(:space) { Space.start(seeds) }
it "8周辺がある場合の隣接する生きている要素が取得できること" do
space.cell(2, 2).count_alive_around.should == 5
end
it "左上隅の場合の隣接する生きている要素が取得できること" do
space.cell(0, 0).count_alive_around.should == 3
end
it "上辺の場合の隣接する生きている要素が取得できること" do
space.cell(0, 1).count_alive_around.should == 4
end
it "右上の場合の隣接する生きている要素が取得できること" do
space.cell(0, 3).count_alive_around.should == 2
end
it "左下の場合の隣接する生きている要素が取得できること" do
space.cell(3, 0).count_alive_around.should == 1
end
it "右下の場合の隣接する生きている要素が取得できること" do
space.cell(3, 3).count_alive_around .should == 2
end
end
RSpec::Matchers.define :equals_cells_status do |expected|
match do |actual|
actual.cells.group_by(&:row).values.map{|a| a.map(&:status) } == expected
end
failure_message_for_should do |actual|
"expected #{expected}\nbut actual #{actual.cells.group_by {|c| c.row }.values.map{|a| a.map {|c| c.status } }}"
end
end
end
module LifeGame
class Space
ALIVE = 1
DEAD = 0
attr_accessor :cells
def initialize(&block)
yield self if block_given?
end
def self.start(seeds=[])
Space.new {|s|
s.cells = []
seeds.each_with_index do |rows, row_i|
rows.each_with_index do |status, col_i|
s.cells << Cell.new(status, row_i, col_i, s.cells)
end
end
}
end
def next_time
Space.new {|s|
s.cells = cells.inject([]) {|next_cells, current_cell|
next_cells << current_cell.next_time(next_cells)
}
}
end
def cell(row, col)
@cells.find {|c| c.row == row && c.col == col }
end
def status(row, col)
cell(row, col).status
end
class Cell
attr_accessor :status, :cells, :row, :col
def initialize(status, row, col, cells)
@status, @row, @col, @cells = status, row, col, cells
end
def next_time(next_cells)
Cell.new(next_time_status, row, col, next_cells)
end
def next_time_status
# 誕生
if dead? and count_alive_around == 3
return ALIVE
# 生存(維持)
elsif alive? and (count_alive_around == 2 or count_alive_around == 3)
return ALIVE
end
# 過疎、過密
DEAD
end
def count_alive_around
cells.select {|cell|
around?(cell) and
cell.alive?
}.size
end
def around?(other_cell)
other_cell != self and
(row - 1 <= other_cell.row and other_cell.row <= row + 1 and
col - 1 <= other_cell.col and other_cell.col <= col + 1)
end
def dead?
status == Space::DEAD
end
def alive?
not dead?
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment