Skip to content

Instantly share code, notes, and snippets.

@bendyorke
Created April 4, 2014 21:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bendyorke/9983865 to your computer and use it in GitHub Desktop.
Save bendyorke/9983865 to your computer and use it in GitHub Desktop.
module GameOfLife
def self.play input, n
# return 42 if input == "the universe and everything"
@board = make_board_from input
n.times { age!; print_board; sleep(0.2) }
end
def self.age!
results = parse_cells
process results
end
def self.parse_cells
deep_map do |x,y,cell|
colony = get_block_at(y,x).select(&:alive?).count
colony -= 1 if cell.alive?
[:kill!,:kill!,nil,:grow!].fetch(colony, :kill!)
end
end
def self.process results
deep_map(results) { |x,y,action| @board[y][x].send(action) if action }
end
def self.deep_map grid = @board
grid.map.with_index do |row, y|
row.map.with_index do |val, x|
yield(x,y,val,row)
end
end
end
def self.get_block_at y, x
lower_y = y-1 < 0 ? y : y-1
lower_x = x-1 < 0 ? x : x-1
@board[lower_y..y+1].map { |row| row[lower_x..x+1] }.flatten
end
def self.make_board_from input
input.map do |row|
row.split('').map { |point| Cell.new point.to_i }
end
end
def self.print_board
print "\e[2J"
print "\e[H"
@board.each { |row| puts row.join }
end
Cell = Struct.new :status do
def alive?
self.status == 1
end
def grow!
self.status = 1
end
def kill!
self.status = 0
end
def to_s
self.alive? ? "*" : "-"
end
end
end
GameOfLife::play(ARGV[0..-2], ARGV[-1].to_i) if __FILE__ == $0
require_relative 'game_of_life'
describe GameOfLife do
describe '#make_board_from' do
it 'makes a properly sized array' do
GameOfLife::make_board_from(%w[10 10]).map(&:length).should eq [2,2]
end
it 'makes a Cell Struct for each input' do
GameOfLife::make_board_from(%w[10 10])[0][0].class.should eq GameOfLife::Cell
end
end
describe '#age!' do
it 'processes all the inputs before aging' do
GameOfLife.instance_variable_set :@board, Array.new(3) { Array.new(3) { GameOfLife::Cell.new(1) } }
GameOfLife::age!
GameOfLife.instance_variable_get(:@board).should eq GameOfLife::make_board_from %w[101 000 101]
end
it 'freezes "boat"' do
GameOfLife.instance_variable_set :@board, GameOfLife::make_board_from(%w[00000 01100 01010 00100 00000])
GameOfLife::age!
GameOfLife.instance_variable_get(:@board).should eq GameOfLife::make_board_from %w[00000 01100 01010 00100 00000]
end
it 'pulses "toad" (level 2)' do
GameOfLife.instance_variable_set :@board, GameOfLife::make_board_from(%w[000000 000000 001110 011100 000000 000000])
GameOfLife::age!
GameOfLife.instance_variable_get(:@board).should eq GameOfLife::make_board_from %w[000000 000100 010010 010010 001000 000000]
end
it 'pulses "pulsar" (level 3)' do
GameOfLife.instance_variable_set :@board, GameOfLife::make_board_from(%w[000000000000000 000111000111000 000000000000000
010000101000010 010000101000010 010000101000010
000111000111000 000000000000000 000111000111000
010000101000010 010000101000010 010000101000010
000000000000000 000111000111000 000000000000000])
2.times { GameOfLife::age! }
GameOfLife.instance_variable_get(:@board).should eq GameOfLife::make_board_from %w[000000000000000 000110000011000 000011000110000
010010101010010 011101101101110 001010101010100
000111000111000 000000000000000 000111000111000
001010101010100 011101101101110 010010101010010
000011000110000 000110000011000 000000000000000]
end
end
describe GameOfLife::Cell do
it 'tests that cell is alive' do
GameOfLife::Cell.new(1).alive?.should eq true
GameOfLife::Cell.new(0).alive?.should eq false
end
it 'can grow and kill cells' do
cell = GameOfLife::Cell.new(0)
cell.grow!
cell.alive?.should eq true
cell.kill!
cell.alive?.should eq false
end
it 'prints based on its status' do
GameOfLife::Cell.new(0).to_s.should eq '-'
GameOfLife::Cell.new(1).to_s.should eq '*'
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment