Мартин обнови решението на 17.12.2011 21:57 (преди над 12 години)
+module GameOfLife
+
+ class BoardUtil
+ def self.generate_all_cells(*live_cells)
+ x_coords = BoardUtil.get_x_coords(*live_cells)
+ y_coords = BoardUtil.get_y_coords(*live_cells)
+ if x_coords.count == 0
+ return {}
+ end
+ init_cells(x_coords.min, y_coords.min, x_coords.max, y_coords.max, *live_cells)
+ end
+
+ def self.get_x_coords(*live_cells)
+ all = *live_cells.flatten.inject([]) { |res, current| res.push(current)}
+ all.values_at(* all.each_index.select { |i| i.even? })
+ end
+
+ def self.get_y_coords(*live_cells)
+ all = *live_cells.flatten.inject([]) { |res, current| res.push(current) }
+ all.values_at(*all.each_index.select { |i| i.odd? })
+ end
+
+ def self.generate_live_cells(*args)
+ live_cells = {}
+ args.each do |x,y|
+ live_cells[[x,y]] = Cell.new x, y, args, true
+ end
+ live_cells
+ end
+
+ def self.init_cells(min_x, min_y, max_x, max_y, *live_cells)
+ all_cells = {}
+ for i in (min_x -1)..(max_x+1)
+ for j in (min_y - 1)..(max_y+1)
+ all_cells[[i,j]] = Cell.new i, j, live_cells, live_cells.include?([i,j])
+ end
+ end
+ all_cells
+ end
+
+ end
+
+ class Board
+ def initialize(*live_cells)
+ @cells = BoardUtil.generate_all_cells(*live_cells)
+ @live_cells = BoardUtil.generate_live_cells(*live_cells)
+ @next_generation = {}
+ end
+
+ def [](x,y)
+ if @live_cells[[x,y]]
+ true
+ else
+ false
+ end
+ end
+
+ def each(&block)
+ if block
+ @live_cells.keys.each do |value|
+ block.call(value)
+ end
+ else
+ @live_cells.each
+ end
+ end
+
+ def drop(from)
+ @live_cells.keys.drop(from)
+ end
+
+ def first
+ @live_cells.keys.first
+ end
+
+ def reverse_each(&block)
+ if block
+ @live_cells.keys.reverse_each do |value|
+ block.call value
+ end
+ else
+ @live_cells.keys.reverse_each
+ end
+ end
+
+ def to_a
+ @live_cells.keys
+ end
+
+ def count
+ @live_cells.count
+ end
+
+ def next_generation
+ @cells.each do |key, value|
+ if value.is_living_in_next_iteration? or value.is_spawning_in_next_iteration?
+ @next_generation[key] = :alive
+ end
+ end
+ Board.new *@next_generation.keys
+ end
+
+ end
+
+ class Cell
+ attr_reader :x,:y
+ def initialize(x, y, possible_live_neighbours, is_alive)
+ @x, @y, @neighbours,@is_alive = x, y, [], is_alive
+ possible_live_neighbours.each do |cell_x, cell_y|
+ if is_neighbour?(cell_x,cell_y)
+ @neighbours += [[cell_x,cell_y]]
+ end
+ end
+ end
+
+ def is_neighbour?(x,y)
+ (@x-x).abs <= 1 && (@y - y).abs <= 1 && !(@x == x && @y == y)
+ end
+
+ def is_living_in_next_iteration?
+ @is_alive && (@neighbours.size == 2 || @neighbours.size == 3)
+ end
+
+ def is_spawning_in_next_iteration?
+ @neighbours.size == 3
+ end
+ end
+
+end
+
Изглежда ми леко over-engineered :) Малко дългичко за поставения проблем :)
include Enumerable
- Разгледай решенията на колегите си. Има интересни неща там.