Adventures with Ruby

Conway’s Game of Life; or: Writing Perl in Ruby

View Comments

We had a programming exercise this week at work. We were set out to write Conway’s Game of Life, using pair programming and TDD. It was a fun and educational evening. I even did some Scala.

Programmers humor dictates me that from time to time I say things like “In Ruby, that’s only one line!” or “In Ruby, that would cost me just one minute!”. Putting money where my mouth is, I wrote the entire application in just one line of Ruby.

So here it is. It looks more like Perl than Ruby. But it works!

String.class_eval{define_method(:to_grid){(self =~ /\A(\d+)x(\d+)\z/ ? 
(0...split('x').last.to_i).map{|_| (0...split('x').first.to_i).map{|_| rand > 0.5 } } : 
split("\n").map{|row| row.split(//).map{|cell_string| cell_string == "o" } }
).tap{|grid| grid.class.class_eval{define_method(:next){each{|row| 
row.each{|cell| cell.class.class_eval{define_method(:next?){|neighbours| 
(self && (2..3).include?(neighbours.select{|me| me }.size)) || 
(!self && neighbours.select{|me| me }.size == 3)}}}} && 
enum_for(:each_with_index).map{|row, row_num| row.enum_for(:each_with_index).map{|cell, col_num| 
cell.next?([ at(row_num - 1).at(col_num - 1), at(row_num - 1).at(col_num), 
at(row_num - 1).at((col_num + 1) % row.size), row.at((col_num + 1) % row.size), 
row.at(col_num - 1), at((row_num + 1) % size).at(col_num - 1), 
at((row_num + 1) % size).at(col_num), at((row_num + 1) % size).at((col_num + 1) % row.size) ]) 
} }} && define_method(:to_s){map{|row| row.map{|cell| cell ? "o" : "." }.join }.join("\n")}}}}}

I didn’t cheat! No semicolons where harmed during the making of the spaghetti code. I did enter some newlines in the code shown above to prevent wild scrollbars from appearing.

You can use it like this:

# generate a random grid
grid = "100x30".to_grid
# show the grid:
puts grid.to_s
# get the next generation of the grid
new_grid = grid.next
# convert a drawn out grid to a grid
new_grid.to_s.to_grid == new_grid # returns true

If you want to know how it works, or make an animation of it, it’s all here.

This is what it looks like:

Conway's Game of Life

It was a fun exercise, but I don’t think I’ll be writing all my code like this in the future :)

Written by Iain Hecker

April 30th, 2010 at 3:49 pm

Posted in iain.nl

  • Nathaniel Revetria

    You’re a monster freak :D

  • http://mayerdan.com Dan Mayer

    You must have gone to a code retreat recently?

  • http://iain.nl Iain Hecker

    yes, forgot to mention that. Can’t make this in sessions of 45 minutes though. Took about 4 hours…

  • http://thinkinginrails.com/2010/05/links-of-the-week-05012010/ Thinking In Rails » Blog Archive » Links of the Week [05/01/2010]

    [...] The Game Of Life in one line of Ruby [...]

blog comments powered by Disqus
Fork me on GitHub