RPCFN: The Game of Life (#11)

by on June 28, 2010

Ruby Programming Challenge For Newbies

RPCFN: The Game of Life (#11)

By Elise Huard

About Elise Huard

Elise HuardElise Huard is based in Brussels, Belgium and is the owner of Jabberwocky, a solutions company mostly focused on Rails. She has worked with a few other technologies before falling in love with Rails and Ruby about 3 years ago and going freelance to work with Ruby full time. She contributes to open source projects as much as she can, and has given talks at a few Ruby and Rails conferences. She’s a jack of all trades, loves reading, tinkering, food, travel, learning, and people out of the ordinary.

Elise has this to say about the challenge:

This challenge consists in implementing the game of life. This is a problem that is simple to understand, but requires some thought to implement correctly. Tests will help you spot your own reasoning fallacies. And of course, every hacker has to have implemented the game of life at least once :)

Our Awesome Sponsor

This monthly programming challenge is sponsored by Backup My App.

Backup My App

Backup My App is an automatic backup service for Ruby on Rails applications. You simply install the plugin to your Rails application and they handle the rest of the process. They store backup history for several weeks and you can restore any of them automatically. Try out their 1 GB plan for free. Backup My App has sponsored this challenge and is proud to make this contribution to the Ruby community.

Prizes

  • The participant with the best Ruby solution (if there is a tie between answers, then the one who posted first will be the winner) will be awarded any one of PeepCode’s Ruby on Rails screencasts and a free 10 GB account for a year from Backup My App.
  • From the remaining working Ruby solutions, three participants would be selected randomly and each one would be awarded any one of Pragmatic’s The Ruby Object Model and Metaprogramming screencasts.
  • All the participants in this challenge (except the participant with the best Ruby solution) will get a free 5 GB account for 6 months from Backup My App.

The four persons who win, can’t win again in the next immediate challenge but can still participate.

The Ruby Challenge

RPCFN

The Challenge

The entire challenge details are available at: http://github.com/elisehuard/game_of_life

How to Enter the Challenge

Read the Challenge Rules. By participating in this challenge, you agree to be bound by these Challenge Rules. It’s free and registration is optional. You can enter the challenge just by posting the following as a comment to this blog post:

  1. Your name:
  2. Country of Residence:
  3. GIST URL of your Solution (i.e. Ruby code) with explanation and / or test cases:
  4. Code works with Ruby 1.8 / 1.9 / Both:
  5. Email address (will not be published):
  6. Brief description of what you do (will not be published):

Note:

  • As soon as we receive your GIST URL, we will fork your submission. This means that your solution is frozen and accepted. Please be sure that is the solution you want, as it is now recorded in time and is the version that will be evaluated.
  • All solutions posted would be hidden to allow participants to come up with their own solutions.
  • You should post your entries before midnight of 2nd Aug. 2010 (Indian Standard Time). No new solutions will be accepted from 3rd Aug. onwards.
  • On 3rd Aug. 2010 all the solutions will be thrown open for everyone to see and comment upon.
  • The winning entries will be announced on this blog before 10th Aug. 2010. The winners will be sent their prizes by email.

More details on the RPCFN?

Please refer to the RPCFN FAQ for answers to the following questions:

Donations

RPCFN is entirely financed by RubyLearning and sometimes sponsors, so if you enjoy solving Ruby problems and would like to give something back by helping with the running costs then any donations are gratefully received.

Click here to lend your support to: Support RubyLearning With Some Love and make a donation at www.pledgie.com !

Acknowledgements

Special thanks to:

  • Elise Huard.
  • Sponsors Backup My App.
  • GitHub, for giving us access to a private repository on GitHub to store all the submitted solutions.
  • The RubyLearning team.

Questions?

Contact Satish Talim at satish [dot] talim [at] gmail.com OR if you have any doubts / questions about the challenge (the current problem statement), please post them as comments to this post and the author will reply asap.

The Participants

There are two categories of participants. Some are vying for the prizes and some are participating for the fun of it.

In the competition

  1. Dominik Masur, Germany
  2. Sergey Kruk, Russian Federation
  3. Mark Mba Wright, USA
  4. Andrew Cox, U.K.
  5. Julio C. Villasante, Cuba
  6. Nils Riedemann, USA
  7. Valério Farias, Brazil
  8. Christopher Fortenberry, USA
  9. Falk Pauser, Germany
  10. Sam Johnson, Australia
  11. Brad O’Connor, Australia
  12. Michael Klaus, Germany
  13. Dmytrii Nagirniak, Australia
  14. Milan Dobrota, USA
  15. Steve Hindmarch, UK
  16. Nithin Bekal, India
  17. Zachary Becker, USA
  18. Benoit Daloze, Belgium
  19. Tanzeeb Khalili, Canada
  20. Cary Swoveland, Canada

Just for Fun

  1. Trevor Fountain, U.K.
  2. William Crawford, USA

The Winners

Winners

Congratulations to the winners of this Ruby Challenge. They are:

Previous Challenge

RPCFN: Business Hours (#10) by Ryan Bates.

Note: All the previous challenges, sponsors and winners can be seen on the Ruby Programming Challenge for Newbies page.

Update

  • This challenge is now closed.
  • The (#12) challenge by David Griffiths, USA is scheduled for Aug. 2010.

Technorati Tags: , , , , ,

Posted by Satish Talim

Follow me on Twitter to communicate and stay connected

{ 78 comments… read them below or add one }

Dominik Masur June 28, 2010 at 7:01 pm

Solution (#1):

Dominik Masur, Germany
https://gist.github.com/d881c26151874021d4cf
Code works with Ruby 1.8
I changed the init line and gist new after elises comments (thx for that)

Reply

Elise Huard August 3, 2010 at 7:31 am

- lack of ambition in parameters (only one: size)
- could use some refactoring, and a little more cleverness in neighbor calculation

Reply

Trevor Fountain June 28, 2010 at 9:15 pm

Solution (#2):

Trevor Fountain, U.K.
http://gist.github.com/456010
Tested with Ruby 1.8
I’m not in this for real, just for fun — I don’t think I can get away with claiming the “Ruby Newbie” title anymore. I’m a Cognitive Science graduate student in Scotland; I started using Ruby for casual projects a few years ago, but only seriously learned the language when I began using it to conduct my research.
In case the “brief description of what you do” was meant to be a “brief description of what your code does”, well, the code is somewhat documented — and the #evolve method is more-or-less readable, thanks to the ugly, ugly monkeypatch that precedes it.

Reply

Elise Huard August 3, 2010 at 7:32 am

- (as you know) the reopening of Array is clever, although overloading something as essential as [] can be dangerous in any larger projects (unintended side effects)
- the neighbour calculation is also pretty nicely done
- code is clear, names are sensible
- I don’t think the probability calculation is correct, a comparison between the result of rand and the probability would have made more sense. Creating a game of life with a low probability actually yields more cells than creating a game of life with high probability, unless that’s the purpose ?

Reply

Sergey Kruk June 29, 2010 at 2:44 am

Solution (#3):

Sergey Kruk
https://gist.github.com/451cfcbac82ba53059ef
GameOfLife is inherited from Array and replaces iteslf on evolve. Thus GameOfLife#inspect method shows current state. The field is folded onto itself.
You can initialize the field with parameters:
size
width, height
width, height, seeds
Or with options hash. Default is 5×5 with 10 seeds
If number of seeds exceeds field size, all field is filled.

Reply

Elise Huard August 3, 2010 at 7:32 am

- correct implementation.
- I think it’s better to have a well-defined set of parameters, like a hash in your case, this sends a clearer message to people using your class.
You say: I expect this and that, and then you test on that limited set whether you get the expected inputs.
- your initialization is interesting, you’re the only one who does the randomizing on the width and height. Your implementation is a bit complex (especially the bit with the while loop). Striving for simplicity will help you if you need to get back into your own code 6 months later :)
- also, I suspect the initialization is OK, but doesn’t produce too many viable configs: trying with a small matrix yields a matrix full of 1, trying with a larger number yields a very sparse matrix. But it allows to play with seeds, which is good.
- dup is not strictly necessary, you can just clone your state

Reply

James Edward Gray II June 29, 2010 at 5:31 am

I build this life simulator when I was very new to Ruby, so it’s probably pretty awful code:

https://gist.github.com/dee55426374e780a9870

It can generate PPM images though, in numerical sequence. Graphic Converter can then convert those into fun Quicktime movies. I have a good one of the “Puffer Train.”

Reply

elise June 29, 2010 at 10:34 pm

Nice one ! As you are as far from newbie as one can get, I guess this is not an official entry :)

Reply

James Edward Gray II June 30, 2010 at 5:36 am

I still feel like a newbie most days at work and I was definitely a Ruby newbie when I wrote that code.

Reply

ippa June 29, 2010 at 7:54 pm

The Ruby 2D-gamelib Chingu [ http://github.com/ippa/chingu ] has a game of life example [ http://github.com/ippa/chingu/blob/master/examples/game_of_life.rb ] with OpenGL accelerated gfx, oh yeah ;). Developed by R.Kawowski [ http://www.toastymofo.blogspot.com/ ]

I added some modifications and various common patterns (like the Gospel Glider Gun, Lightweight Spaceship and the Pulsar) which can be scrolled through with the mouse-wheel and put out on the screen with a click. Easy to add your own patterns in ascii-format too…

Reply

Elise August 4, 2010 at 1:59 am

nice, one of the entries used your implementation I think :)

Reply

Mark Mba Wright June 30, 2010 at 6:51 am

Solution (#4):

Mark Mba Wright, USA
I’m pretty new to Ruby so the code may not look too rubyish.
Proposed solution: https://gist.github.com/f6914344c2d1c5ae34ce
Test Case: https://gist.github.com/ad89eae9051c5a2c2c17
Visualization (ruby-processing): https://gist.github.com/4d52b08104468955fc6f

Reply

Elise Huard August 3, 2010 at 7:33 am

- error in initialization: is systematically initialized with 0 everywhere …
- evolve shouldn’t need to reinitialize the state, since it is defined when initializing the object.
- readability: clear variable names always help, refactoring in smaller, clearly named methods would help too

Reply

Andrew Cox June 30, 2010 at 1:36 pm

Solution (#5):

Andrew Cox, U.K.
https://gist.github.com/8dcb8d3365b5228fb7d6

Reply

Elise Huard August 3, 2010 at 7:33 am

- extra points for adding tests to the solution
- nicely OO approach with Cell, with neighbors of a cell being part of its properties
- naming for clarity, short methods
- maybe a bit heavy for the problem simplicity, but nicely done.

Reply

Julio C. Villasante July 1, 2010 at 7:25 pm

Solution (#6):

Julio C. Villasante, Cuba
https://gist.github.com/967c2235c85169f9673d
Tested in Ruby 1.9.1
With the solution I’m posting a README file that broadly explains how I do it.
Posted a modified test case for when the board is not folded with the same tests that were provided.
Anyway, enjoy a lot doing this, keep up the good work…
jvillasantegomez@gmail.com

Reply

Elise Huard August 3, 2010 at 7:34 am

- good point for adding a readme to explain reasoning
- bonus points for dialog, and number of variables used
- fold_board is not strictly necessary since it’s possible to calculate with ruby using negative indexes
- the implementation itself doesn’t seem to work that well
- no state accessors to get or set the state, which was asked

Reply

Julio C. Villasante August 3, 2010 at 5:40 pm

Please, being new to ruby I would like you to elaborate on “the implementation itself doesn’t seem to work that well”, actually I got into this to get some feedback.
About the fold_board method you are right, but I always strive for clear/readable code (using negative indexes and the like is like an abomination to me :))
Didn’t add any state accessors ’cause didn’t had the time to write tests, thought that they were needed for testing only.
Anyway, good challenge, enjoyed it a lot, thanks for sharing…

Reply

Elise August 6, 2010 at 12:11 pm

Jose: I mean by that that I tried to run a visualization of it, and it didn’t work.
about the negative indexes: I see what you mean. I think that within bounds, a little cleverness is allowed :) But you’re right that going overboard with that is dangerous.
The accessors were for my tests as well.

Reply

nils_r July 2, 2010 at 2:21 am

Solution (#7):

Nils Riedemann, USA
Hey I am relatively new to ruby so there might be some things that could have been done better. And it was the first time i did tdd/bdd.
Did it in less than 40 lines (excluding comments) but tried to maintain readability.
https://gist.github.com/8709224425dd99034dda

Reply

Elise Huard August 3, 2010 at 7:35 am

- congratulations for your first specs :) bonus points for adding them.
- a slight lack of ambition in features
- a correct, short implementation.
- adding the neighbours themselves to calculate the neighbours would have been possible, since they are 1 or 0

Reply

Valério Farias July 2, 2010 at 3:50 am

Solution (#8):

Valério Farias, Brazil
http://gist.github.com/460651
I ran the code using ruby 1.8.7
I used Shoes to see the graph

Reply

Elise Huard August 3, 2010 at 7:36 am

- bonus points for adding tests
- lack of ambition in features
- adding neighbours to each other would have worked, since we’re talking about 0 and 1 (no if required)
- cloning of the result of evolve is not necessary, assignment is enough – one state is enough for this problem
- correct implementation

Reply

CPFB July 2, 2010 at 7:11 am

Solution (#9):

Christopher Fortenberry, USA
https://gist.github.com/bff42e44d35ca554ac67
Works with 1.8 and 1.9

Reply

Elise Huard August 3, 2010 at 7:36 am

- bonus points for adding tests !
- initialization seems a bit heavy – assigning a rand(2) to every cell, or playing with a probability (rand > probability) could have worked too.
- creating an array with the correct size, and assigning live cells to it afterwards, may be a bit safer than constructing arrays from scratch. (although this works too)
- nice to implement access to the ‘matrix’ by making new getters. However, pushing this might have been more interesting, and more ‘OO’ (having a class for the state)
- correct implementation

Reply

Falk Pauser July 2, 2010 at 2:53 pm

Solution (#10):

Falk Pauser, Germany
I am a Webdeveloper from Germany (Koblenz/Rhein) and here is my solution: http://gist.github.com/461159

Reply

Elise Huard August 3, 2010 at 7:36 am

- bonus point for adding specs !
- the seeding is not going to be evenly spread over the cells – there’s always going to be a higher probability of upper left than lower right
- bonus for checking on inputs in state= and initialize
- clear naming for neighbors
- living_nb calculation is not as elegant as it could have been

Reply

Falk Pauser August 3, 2010 at 11:54 am

What about the bonus point for the sinatra visualization? ;)

Reply

Elise August 4, 2010 at 1:57 am

hah, very cool :)

Reply

Dmytrii Nagirniak July 3, 2010 at 4:41 pm

Hi,

How can we submit the solution if it would include the set of tests (Cucumber and RSpec), couple of files for the solution itself and possibly some other additions to the game.
It doesn’t seem it could be easily done using a Gist.

So maybe I could just submit the solution files only (no tests or other stuff) with gist and then add comment to link to the whole github project?
Or maybe the project itself from the github can be submitted?

Cheers.

Reply

elise July 4, 2010 at 12:48 pm

Dmytriee, it is actually possible to add several files in one gist (‘add another file’ option).
however, if you prefer you could fork the project, do your thing and then submit that link.
Hope that helps ?

Reply

William July 5, 2010 at 4:06 am

Solution (#11):

William Crawford, USA
git@gist.github.com:d643626f26d16c54591f.git
I only tested it on 1.8.
As I’m a professional developer in another language, I’m doing this just for fun. I’ve been meaning to learn more about Ruby for a while, and these challenges seemed like a good way. Any feedback on how my code can be more ‘Ruby-like’ is much appreciated.

Reply

Elise Huard August 3, 2010 at 7:37 am

- for flexibility, width and height could be made inputs – to have the defaults set to 5, you’d use initialize(widht=5, height=5)
- width and height are not really necessary as instance variables since they can be deduced from state
- bonus points for raising exceptions on wrong input on state. The usual ruby error would be ArgumentError (or a custom subclass of RuntimeException).
- in Ruby, you can go negative with Array indexes. So you could add arr[-1], and it would just take the last element of the array
- seems to be a correct implementation !

Reply

William August 3, 2010 at 3:57 pm

Thanks for the comments! They’ll definitely help me be more ruby-like in the future.

Can I ask how what you said about width and height being made inputs is different from what I did?

My Code:

def initialize width=5, height=5
@width = width
@height = height
@state = Array.new(@height).map! { Array.new(@width).map! { rand(2) } }
end

Reply

Elise August 3, 2010 at 4:18 pm

ehm, then I wonder if I have the correct URL
https://gist.github.com/d643626f26d16c54591f
In this version the initialize method takes no argument … but your code is correct, you can ignore the comment

Reply

William August 3, 2010 at 4:21 pm

Oh! My mistake! I added that after I submitted! I forgot I had made some more changes afterwards because I was playing around with it.

Thanks again for looking over it!

Dmytrii Nagirniak July 5, 2010 at 4:28 am

Elise,

The Gist allows adding many files but as far as I know it is not possible to organise them with folders. So if submitting a fork can work in this case I would take that option which sounds to be ok.

Thanks and cheers.

Reply

Sam Johnson July 7, 2010 at 9:36 pm

Solution (#12):

Sam Johnson, Australia
http://gist.github.com/466917
Code tested with 1.8.7

Reply

Elise Huard August 3, 2010 at 7:37 am

- bonus for adding tests !
- initialization is 0 …, evolve is correct
- apart from that, elegant and readable

Reply

Edd M July 9, 2010 at 12:11 pm

Since the ncurses demo doesn’t run on Windows, I’ve made a visualisation of the game of life in WPF for those on the Microsoft platform that want to see stuff happening instead of shifting array elements :)

If you follow the outline of the challenge, it should work great with your solution (just put a callback to update() when your game evolves).

http://trquadrant.com/2010/7/8/48-ruby-game-of-life-in-wpf

It’s in IronRuby, so it’s still cool right? ;)

Reply

elise July 14, 2010 at 10:55 am

wow, nice one :)
there is a working solution for Windows with Shoes in the github project, but yours looks pretty nice !

Reply

Brad O'Connor July 13, 2010 at 12:31 pm

Solution (#13):

Brad O’Connor, Australia
http://gist.github.com/473578
Should work with Ruby 1.8 or 1.9. I’ve only tested it with 1.9.1
Thanks for this challenge. It was a nice bite-sized piece of coding to do. As always, I learnt many things doing it, including things I wasn’t expecting to learn.

Reply

Elise Huard August 3, 2010 at 7:38 am

- bonus for adding tests !
- concise and clear, and correct
- shorter way to create matrix: Array.new(n) { Array.new(n) { rand(2) }}
- another tip would be to make the internal methods private

Reply

Michael Klaus July 21, 2010 at 9:23 pm

Solution (#14):

Michael Klaus, Germany
I tried to roughly optimize the task for code complexity in terms of token count. This results in the #neighbours method just adding the numbers in the patch and subtracting the current cell’s value. The #evolve method was stripped down to the minimum necessary cases using minimal input data. Hope you like it.
https://gist.github.com/2fefaf84664908c32f41
Works with: Ruby 1.8 and 1.9

Reply

Elise Huard August 3, 2010 at 7:38 am

- bonus for adding specs !
- unfortunately, initialization is incorrect, the state is filled with Nil
- evolve is correct, the use of modulo is clever

Reply

Dmytrii Nagirniak July 22, 2010 at 6:50 pm

Solution (#15):

Dmytrii Nagirniak, Australia
http://github.com/jameskayn/game_of_life
Code works with Ruby 1.8.7>:

Reply

Elise Huard August 3, 2010 at 7:38 am

- bonus for the specs !
- nicely OO structure, maybe a bit much for the simplicity of the problem
- initizialization parameter name leads to confusion – I guess it should be size – could have been nice to have width and height, since both are obviously planned for.
- implementation is correct

Reply

Dmytrii Nagirniak August 3, 2010 at 10:54 am

Hi Elise,

I agree about “a bit much for the simlicity”, but it really saved a lot of my time and brought to correct implementation :)

As for the initialization parameters, there are both initialization options available: size and width-heigh.

You can see that on this spec:
http://github.com/jameskayn/game_of_life/blob/master/spec/models/game_spec.rb

Probably one place of confusion may be in the fact the ‘size’ initialization does not require a ‘board’ to exist, where ‘width-height’ requires a board or array to be passed into Game.

Cheers,
Dmytrii.

Reply

Elise August 3, 2010 at 11:07 am

You’re absolutely right, I should have looked at the specs more closely. Thanks for clearing this up !

Reply

Milan Dobrota July 25, 2010 at 1:51 pm

Solution (#16):

Milan Dobrota, USA
https://gist.github.com/203b4d71e32794fd7a70
Code tested with Ruby 1.8.6

Reply

Elise Huard August 3, 2010 at 7:39 am

- could have worked with width and height as input parameters
- nice implementation with CircularRange
- just summing the neighbours could also have worked, since you use 0 and 1

Reply

Steve Hindmarch July 29, 2010 at 2:51 pm

Solution (#17):

Steve Hindmarch, UK
https://gist.github.com/0fdaaf7ea5340a22786c
Code works with Ruby 1.8

Reply

Elise Huard August 3, 2010 at 7:39 am

- bonus for added tests !
- nice to have more parameters
- also nice touch to have a form of persistence
- quite readable
- correct implementation

Reply

Nithin Bekal July 29, 2010 at 9:25 pm

Solution (#18):

Nithin Bekal, India
https://gist.github.com/840815ba8f3579370853
The code works with ruby 1.8, but I haven’t checked it version 1.9.

Reply

Elise Huard August 3, 2010 at 7:39 am

- correct implementation
- avoid variable names like x and y (i and j as counters are acceptable)
- good neighbour calculation, with modulo and using the negative array index
- get_new_state is correct, but could be slightly more readable

Reply

Zachary Becker July 31, 2010 at 11:00 am

Solution (#19):

Zachary Becker, USA
http://gist.github.com/501813
1.8 tested, should work in 1.9

Reply

Elise Huard August 3, 2010 at 7:40 am

- correct implementation
- the Marshal.load(Marshal.dump(@state)) is slightly weird – clone would have achieved the same result
- everything is named clearly, so readable
- for neighbour calculation, summing up the elements themselves achieves the same result, since we have 1 and 0

Reply

Zachary Becker August 3, 2010 at 12:19 pm

Clone was only copying the array one level deep, so if I changed the copy it was still changing the original.

Here is an example.
$ irb
irb(main):001:0> a = [[1,2,3],[4,5,6],[7,8,9]]
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
irb(main):002:0> b = a.clone
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
irb(main):003:0> b[1][1] = 0
=> 0
irb(main):004:0> a
=> [[1, 2, 3], [4, 0, 6], [7, 8, 9]]
irb(main):005:0> b
=> [[1, 2, 3], [4, 0, 6], [7, 8, 9]]
irb(main):006:0> a[1][1] = 5
=> 5
irb(main):007:0> b
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
irb(main):008:0> b = Marshal.load(Marshal.dump(a))
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
irb(main):009:0> b[1][1] = 0
=> 0
irb(main):010:0> a
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
irb(main):011:0> b
=> [[1, 2, 3], [4, 0, 6], [7, 8, 9]]

Reply

Elise August 3, 2010 at 4:32 pm

Strange, when I try in irb (ruby enterprise 1.8.7)
a = [[1,2],[3,5,6]]
=> [[1, 2], [3, 5, 6]]
ree-1.8.7-2010.02 > b = a.clone
=> [[1, 2], [3, 5, 6]]
ree-1.8.7-2010.02 > b[0][1]
=> 2
ree-1.8.7-2010.02 > b[1][1]
=> 5
And same result in ruby 1.9.2
Marshal is still fairly unusual in this context … it’s certainly not incorrect.

Reply

Benoit Daloze August 3, 2010 at 4:39 pm

The “rows/sub” Arrays need to be cloned/duped too:
new = old.map(&:dup)

Reply

Leonardo Bessa July 31, 2010 at 6:20 pm

Solution (#20):

Leonardo Bessa, Brazil
https://gist.github.com/36ea89b66956fdf3c6cb
Code works with Ruby 1.8.
My code iterates in each cell of an array of arrays a verifies if the cell should be alive or dead. I also made a sintra application where each cell is a radio button in a form, to visualize the game of life.

Reply

Elise Huard August 3, 2010 at 7:40 am

- cool visualization with sinatra :)
- bonus for adding tests
- clear and correct implementation

Reply

Benoit Daloze August 2, 2010 at 4:15 am

Solution (#21):

Benoit Daloze, Belgium
http://github.com/eregon/game_of_life
Code works with 1.9, some with 1.8 (and a little of JRuby 1.8)
This is a fairly big solution with 9 implementations and a few visualizations. I wanted to try a lot of different way of coding for the implementations, and try to make a visualization beautiful and fast.
More on the README ;)

Reply

Elise August 4, 2010 at 1:41 am

- very nice, full exploration of many variations on the game, and a good knowledge of ruby
- would have been even more impressive if every different (ruby) implementation could have been slotted in to one game class (although this is already great)
- pretty awesome visualizations

Reply

Benoit Daloze August 4, 2010 at 4:59 pm

Thanks !

About the classes, it would have been much harder to compare and use them in visualizations, or I should have then alias GameOfLife to the implementation used.

I thought to that possible name collision, and it was a bit harder for the specs and benchmarks, but safer too.

In fact, I did not want to have more than one implementation loaded at runtime, as some use monkey-patching which would cause name clashes and method redefined.

Great challenge and many interesting solutions !

Reply

Tanzeeb Khalili August 2, 2010 at 3:36 pm

Solution (#22):

Tanzeeb Khalili, Canada
git://gist.github.com/504449.git
Should work with 1.8.7 and 1.9.2

Reply

Tanzeeb Khalili August 3, 2010 at 10:20 am

Sorry, here’s a clickable URL: http://gist.github.com/504449

Reply

Elise August 4, 2010 at 1:42 am

- correct implementation
- elegant and clever
- extensible, thanks to the use of rules, and seed can be input
- summing the neighbors would have worked instead of counting ’1′

Reply

Tanzeeb Khalili August 4, 2010 at 7:42 pm

Hi Elise,

Thanks for your comments :-)

Quick question — I’m not sure how to do a sum with an array? Do you mean using inject?

Reply

Elise August 6, 2010 at 12:17 pm

Tanzeeb: yes, that’s what I meant.
I agree with WC below that your implementation was the most beautiful in terms of code.

Benoit Daloze August 6, 2010 at 4:59 pm

Indeed, your implementation has many good/cool ideas.

I did add it in my repo (http://github.com/eregon/game_of_life/blob/master/lib/game_of_life_tanzeeb.rb)

I had to modify quite much #initialize to respect my API, so do not pay attention to the ugly “case”.

Please say if this is a problem to you (I mean including your code)

WC August 4, 2010 at 4:47 am

I find your entry to be really impressive. I keep looking at the code and finding things that just amaze me. Thank you for entering it.

Reply

Tanzeeb Khalili August 4, 2010 at 7:45 pm

Thanks WC :-)

Reply

Brad O'Connor August 6, 2010 at 10:50 am

I agree. A look through the code has revealed just how much less Ruby I know than I thought I did. I really need to learn how to use blocks as method parameters.

Reply

Tanzeeb Khalili August 10, 2010 at 3:39 am

Thanks Brad! I learned the trick from PragProg — http://ruby-doc.org/docs/ProgrammingRuby/html/tut_containers.html#UG.

Cary Swoveland August 2, 2010 at 10:32 pm

Solution (#23):

Cary Swoveland, Canada
I’m crossing my fingers, as I didn’t have much time for testing.
https://gist.github.com/5f784cd6c9c5a4329d6b

Reply

Elise August 4, 2010 at 1:53 am

- well researched, only implementation that explores possible topologies, nice
- passes tests for the torus topology
- unusual in that dimensions are not parameters but constants, only topology is variable

Reply

Cary Swoveland August 4, 2010 at 5:20 am

Thanks, Elise–great challenge! I assume you noticed I did chose the grid sizes randomly, though I hard-wired the ranges for those dimensions. Frankly, I wasn’t very interested in that part of the challenge, so didn’t spend much time on it. I instead focused on allowing for different topologies. I am new to OOP generally–not just Ruby–and thought allowing a choice of topology would improve my understanding of subclasses, inheritance and overriding methods. It did!

Reply

Leave a Comment

{ 36 trackbacks }

Previous post:

Next post: