Васил обнови решението на 17.12.2011 17:46 (преди около 13 години)
+# От една страна има доста повторения на методи, използващи
+# cell като аргумент, което би могло да се направи в отделен
+# клас за клетка. От друга страна, не знам дали има смисъл
+# да го усложнявам толкова...
+
+module GameOfLife
+
+ class Board
+ include Enumerable
+
+ def initialize(*cells)
+ @cells = cells.uniq
+ end
+
+ def each &block
+ @cells.each do |cell|
+ if block_given?
+ block.call cell
+ else
+ yield cell
+ end
+ end
+ end
+
+ def neighbours(cell)
+ x, y = cell.first, cell.last
+ [x].product([y+1, y-1]) +
+ [x-1].product([y-1, y, y+1]) +
+ [x+1].product([y-1, y, y+1])
+ end
+
+ def count_neighbours(cell)
+ neighbours(cell).select { |cell| @cells.include? cell }.length
+ end
+
+ def next_status(cell)
+ case count_neighbours(cell)
+ when 2 then (self[cell.first, cell.last] ? cell : nil)
+ when 3 then cell
+ else nil
+ end
+ end
+
+ def [] (x, y)
+ @cells.include? [x, y]
+ end
+
+ def generation
+ return nil if @cells.empty?
+ @cells.map { |cell| neighbours(cell) }.inject(:+).uniq
+ .select { |neighbour| next_status(neighbour) }
+ end
+
+ def next_generation
+ GameOfLife::Board.new *generation
+ end
+ end
+end