Константин обнови решението на 19.12.2011 14:02 (преди около 13 години)
+module BoardEnumerable
+
+ include Enumerable
+
+ def each &block
+ @field.each_with_index { |elem, ind| each_yield elem, ind, &block }
+ end
+
+ def count
+ @field.flatten.count { |elem| elem == true }
+ end
+
+ private
+
+ def each_yield array, index
+ array.each_index do |pos|
+ yield index, pos if array[pos] == true
+ end
+ end
+
+end
+
+
+
+module GameOfLife
+
+class NeighbourGenerator
+
+ def initialize field
+ @field = field
+ end
+
+ def get_neighbours x, y
+ neigh = []
+ neigh << [left(x,y), right(x,y)]
+ neigh << [top(x,y), top_left(x,y), top_right(x,y)]
+ (neigh + [bottom(x,y), bottom_left(x,y), bottom_right(x,y)]).flatten
+ end
+
+ private
+
+ def left x, y
+ y < 1 ? false : @field[x][y-1]
+ end
+
+ def right x, y
+ @field[x][y+1] == nil ? false : @field[x][y+1]
+ end
+
+ def top x, y
+ x < 1 ? false : @field[x-1][y]
+ end
+
+ def top_left x, y
+ (x < 1 or y < 1) ? false : @field[x-1][y-1]
+ end
+
+ def top_right x, y
+ return false if x < 1
+ @field[x-1][y+1] == nil ? false : @field[x-1][y+1]
+ end
+
+ def bottom x, y
+ @field[x+1] == nil ? false : @field[x+1][y]
+ end
+
+ def bottom_left x, y
+ return false if @field[x+1] == nil
+ y < 1 ? false : @field[x+1][y-1]
+ end
+
+ def bottom_right x, y
+ return false if @field[x+1] == nil
+ @field[x+1][y+1] == nil ? false : @field[x+1][y+1]
+ end
+
+end
+
+
+class GenerationGenerator
+
+ def initialize past_gen_field
+ @current_field = past_gen_field
+ @neigh_gen = NeighbourGenerator.new @current_field
+ end
+
+ def produce_generation
+ Board.new produce_living
+ end
+
+ private
+
+ def count_alive array
+ array.count { |cell| cell == true }
+ end
+
+ def produce_living
+ living_arr = []
+ @current_field.each_with_index do |row, row_index|
+ living_arr += living_from_row(row, row_index)
+ end
+ living_arr
+ end
+
+ def living_from_row row, row_index
+ living_in_row = []
+ row.each_with_index do |elem, pos|
+ living_in_row << [row_index, pos] if should_live?(row_index, pos)
+ end
+ living_in_row
+ end
+
+ def should_live? x, y
+ alive_n = @neigh_gen.get_neighbours(x, y).count { |elem| elem == true }
+ return alive_cond?(alive_n) if @current_field[x][y] == true
+ dead_cond?(alive_n)
+ end
+
+ def alive_cond? count_alive
+ return false if count_alive < 2 or count_alive > 3
+ true
+ end
+
+ def dead_cond? count_alive
+ return true if count_alive == 3
+ false
+ end
+
+end
+
+
+class Board
+
+ include BoardEnumerable
+
+ def initialize *cells
+ cells_leg = produce_legitimate cells
+ @field = construct_field cells_leg
+ cells_leg.each do |x, y|
+ @field[x][y] = true
+ end
+ end
+
+ def [] x, y
+ @field[x][y] or false
+ end
+
+ def next_generation
+ gen = GenerationGenerator.new @field
+ gen.produce_generation
+ end
+
+ private
+
+ def construct_field cells
+ dim1 = cells.empty? ? 0 : cells.map(&:first).max
+ dim2 = cells.empty? ? 0 : cells.map(&:last).max
+ Array.new(dim1 + 2) { Array.new(dim2 + 2) { false } }
+ end
+
+ def produce_legitimate cells
+ return [] if cells == [[]] or cells == []
+ cells = (cells.first.first.kind_of? Array) ? cells.first : cells
+ end
+
+end
+
+end