Created
June 21, 2014 21:14
-
-
Save timuruski/dcdc2c50077735bcf08a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class World | |
def initialize(cells) | |
@cells = cells | |
@row_count = cells.length | |
@col_count = cells[0].length | |
end | |
def living_neighbours(col, row) | |
[ | |
cell(col, row - 1), # NORTH | |
cell(col + 1, row - 1), # NORTH-EAST | |
cell(col + 1, row), # EAST | |
cell(col + 1, row + 1), # SOUTH-EAST | |
cell(col, row + 1), # SOUTH | |
cell(col - 1, row + 1), # SOUTH-WEST | |
cell(col - 1, row), # WEST | |
cell(col - 1, row - 1) # NORTH-WEST | |
].select(&:living?) | |
end | |
def cell(col,row) | |
@cells[row % @row_count][col % @col_count] | |
end | |
def next | |
new_cells = cell_map { |c| | |
c.next(living_neighbours(c)) | |
} | |
self.class.new(@cells) | |
end | |
def cell_map | |
@cells.map { |row| | |
row.map { |cell| | |
yield cell | |
} | |
} | |
end | |
end | |
class Cell | |
def self.next(target, neighbours) | |
living_neighbours = neighbours.count { |c| c.living? } | |
if target.living? | |
next_living = living_neighbours > 1 && living_neighbours < 4 | |
else | |
next_living = living_neighbours == 3 | |
end | |
new(living: next_living) | |
end | |
def initialize(living: false) | |
@living = living | |
end | |
def living? | |
@living | |
end | |
end | |
describe "Conway's Game of Life" do | |
def alive | |
Cell.new(living: true) | |
end | |
def dead | |
Cell.new(living: false) | |
end | |
describe "Cell.new" do | |
it "is not living by default" do | |
expect(Cell.new.living?).to be false | |
end | |
it "can be living" do | |
expect(Cell.new(living: true).living?).to be true | |
end | |
it "can be not living" do | |
expect(Cell.new(living: false).living?).to be false | |
end | |
end | |
describe "Cell.next" do | |
context "with a living target cell" do | |
let(:target) { Cell.new(living: true) } | |
context "and 1 living neighbour" do | |
it "produces an dead cell" do | |
neighbours = [ | |
dead, | |
alive, | |
dead | |
] | |
expect(Cell.next(target, neighbours).living?).to be false | |
end | |
end | |
context "and 2 living neighbours" do | |
it "produces a living cell" do | |
neighbours = [ | |
alive, | |
alive, | |
dead | |
] | |
expect(Cell.next(target, neighbours).living?).to be true | |
end | |
end | |
context "and 3 living neighbours" do | |
it "produces a living cell" do | |
neighbours = [ | |
alive, | |
alive, | |
alive | |
] | |
expect(Cell.next(target, neighbours).living?).to be true | |
end | |
end | |
context "and 4 living neighbours" do | |
it "produces an dead cell" do | |
neighbours = [ | |
alive, | |
alive, | |
alive, | |
alive | |
] | |
expect(Cell.next(target, neighbours).living?).to be false | |
end | |
end | |
end | |
context "with an dead target cell" do | |
let(:target) { Cell.new(living: false) } | |
context "and 2 living neighbours" do | |
it "produces an dead cell" do | |
neighbours = [ | |
alive, | |
alive, | |
dead | |
] | |
expect(Cell.next(target, neighbours).living?).to be false | |
end | |
end | |
context "and 3 living neighbours" do | |
it "produces an living cell" do | |
neighbours = [ | |
alive, | |
alive, | |
alive | |
] | |
expect(Cell.next(target, neighbours).living?).to be true | |
end | |
end | |
context "and 4 living neighbours" do | |
it "produces an dead cell" do | |
neighbours = [ | |
alive, | |
alive, | |
alive, | |
alive | |
] | |
expect(Cell.next(target, neighbours).living?).to be false | |
end | |
end | |
end | |
end | |
describe World do | |
describe "#neighbours" do | |
it "returns an empty array if no living neighbours" do | |
a,b,c = dead, dead, dead | |
d,e,f = dead, dead, dead | |
g,h,i = dead, dead, dead | |
subject = World.new([[a,b,c], | |
[d,e,f], | |
[g,h,i]]) | |
expect(subject.living_neighbours(1,1)).to eq([]) | |
end | |
it "returns an array of only the living neighbours" do | |
a,b,c = alive, alive, alive | |
d,e,f = alive, dead, alive | |
g,h,i = alive, alive, alive | |
subject = World.new([[a,b,c], | |
[d,e,f], | |
[g,h,i]]) | |
expect(subject.living_neighbours(1,1)).to match_array([a,b,c,d,f,g,h,i]) | |
end | |
it "returns an array without the dead neighbours" do | |
a,b,c = dead, alive, dead | |
d,e,f = alive, dead, alive | |
g,h,i = dead, alive, dead | |
subject = World.new([[a,b,c], | |
[d,e,f], | |
[g,h,i]]) | |
expect(subject.living_neighbours(1,1)).to match_array([b,d,f,h]) | |
end | |
it "returns an array without the dead neighbours" do | |
a,b,c,d,e = alive, alive, alive, alive, alive | |
f,g,h,i,j = alive, alive, alive, alive, alive | |
k,l,m,n,o = alive, alive, alive, alive, alive | |
p,q,r,s,t = alive, alive, alive, alive, alive | |
u,v,w,x,y = alive, alive, alive, alive, alive | |
subject = World.new([[a,b,c,d,e], | |
[f,g,h,i,j], | |
[k,l,m,n,o], | |
[p,q,r,s,t], | |
[u,v,w,x,y]]) | |
expect(subject.living_neighbours(2,2)).to match_array([g,h,i,l,n,q,r,s]) | |
end | |
it "returns neighbours wrapping around the world" do | |
a,b,c = alive, alive, alive | |
d,e,f = alive, alive, alive | |
g,h,i = alive, alive, alive | |
subject = World.new([[a,b,c], | |
[d,e,f], | |
[g,h,i]]) | |
expect(subject.living_neighbours(2,2)).to match_array([a,b,c,d,e,f,g,h]) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment