Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@burtlo
Last active December 15, 2015 08:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save burtlo/5228393 to your computer and use it in GitHub Desktop.
Save burtlo/5228393 to your computer and use it in GitHub Desktop.
Kanye's Game of Life
class Point < Struct.new(:x,:y)
def self.at(x,y)
new x, y
end
def ==(other)
other.x == x and other.y == y
end
def around
-1.upto(1).map do |diff_x|
-1.upto(1).map do |diff_y|
next if diff_x == 0 and diff_y == 0
self.class.at(x + diff_x,y + diff_y)
end
end.flatten.compact
end
end
class Cell
def self.at(x,y)
AliveCell.new Point.at(x,y)
end
def initialize(position)
@position = position
@neighbors = 0
end
attr_reader :position, :neighbors
def neighbored
@neighbors += 1
end
def to_s
"#{self.class.name} @ #{position.x},#{position.y} - Neighbors: #{neighbors}"
end
end
class AliveCell < Cell
def transform
AliveCell.new(position) if neighbors == 2 || neighbors == 3
end
end
class DeadCell < Cell
def transform
AliveCell.new(position) if neighbors == 3
end
end
class Board
def initialize(cells=[])
cells.each {|cell| add cell }
end
def cells
@cells ||= Hash.new {|hash,position| hash[position] = DeadCell.new(position)}
end
def alive_cells
cells.values.find_all {|cell| cell.is_a? AliveCell }
end
def add(cell)
cell.position.around.each do |position|
found_cell = cells[position]
found_cell.neighbored
cell.neighbored if found_cell.is_a? AliveCell
end
cells[cell.position] = cell
end
def tick
surviving_cells = cells.values.map {|cell| cell.transform }.compact
self.class.new surviving_cells
end
end
describe Board do
describe '#tick' do
context "when the board has one lonely cell" do
#
# X => 0
#
it "generates a board with no alive cells" do
cell1 = Cell.at 0, 0
board = Board.new
board.add cell1
board = board.tick
expect(board.alive_cells).to have(0).cells
end
end
context "when the board has two lonely cells" do
#
# XX => 00
#
it "generates a board with no alive cells" do
cell1 = Cell.at 0, 0
cell2 = Cell.at 1, 0
board = Board.new
board.add cell1
board.add cell2
board = board.tick
expect(board.alive_cells).to have(0).cells
end
end
context "when the board has three neighboring cells" do
#
# X => XX => XX
# XX => XX => XX
#
it "generates the correct board" do
cell1 = Cell.at 0, 0
cell2 = Cell.at 1, 0
cell3 = Cell.at 1, 1
board = Board.new
board.add cell1
board.add cell2
board.add cell3
board = board.tick
expect(board.alive_cells).to have(4).cells
board = board.tick
# Four cells next to each other are in perfect harmony
expect(board.alive_cells).to have(4).cells
end
end
context "when a board has five live cells" do
#
# X => XXX => XXX => XXX
# XXX => X0X => X0X => X0X
# X => XXX => XXX => XXX
#
it "generates the correct board" do
cell1 = Cell.at 0, 0
cell2 = Cell.at 1, 0
cell3 = Cell.at 0, 1
cell4 = Cell.at -1,0
cell5 = Cell.at 0,-1
board = Board.new
board.add cell1
board.add cell2
board.add cell3
board.add cell4
board.add cell5
board = board.tick
expect(board.alive_cells).to have(8).cells
board = board.tick
expect(board.alive_cells).to have(8).cells
end
end
end
end
@burtlo
Copy link
Author

burtlo commented Mar 23, 2013

A Conway's Game of Life solution with the attempt at being approachable from a OOP perspective, while maintaining elegance in execution.

@zenspider
Copy link

cells.values.grep(AliveCell)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment