Христо обнови решението на 20.12.2011 22:55 (преди около 13 години)
+module GameOfLife
+ class Board
+ include Enumerable
+
+ attr_writer :cells
+
+ def initialize *cells
+ @cells = Hash.new false
+ cells.each { |x| @cells[x] = true }
+ @mutator = CellMutator.new(@cells)
+ end
+
+ def each
+ @cells.keys.each { |key| yield key }
+ end
+
+ def [] x, y
+ @cells[[x,y]] == true
+ end
+
+ def count
+ @cells.select { |k, v| v == true }.size
+ end
+
+ def next_generation
+ next_generation = Board.new
+ next_generation.cells = @mutator.mutate
+ next_generation
+ end
+ end
+
+ class AliveNeighbourCounter
+ def initialize cells
+ @cells = cells
+ end
+
+ def count cell
+ neighbour_coordinates(cell).inject(0) { |sum, neighbour| @cells[neighbour] ? sum + 1 : sum }
+ end
+
+ def dead_neighbours cell
+ neighbour_coordinates(cell).select { |neighbour| @cells[neighbour] == false }
+ end
+
+ private
+
+ def neighbour_coordinates cell
+ x, y = cell
+ [[x-1, y-1], [x, y-1], [x+1, y-1], [x-1, y], [x+1, y], [x-1, y+1], [x, y+1], [x+1, y+1]]
+ end
+ end
+
+ class CellMutator
+ def initialize cells
+ @old_generation = cells.dup
+ @new_generation = cells.dup
+ @alive_counter = AliveNeighbourCounter.new(@old_generation)
+ end
+
+ def mutate
+ kill_loners_and_stars
+ breed_new_cells
+ @new_generation
+ end
+
+ private
+
+ def kill_loners_and_stars
+ should_die = @old_generation.keys.select do |cell|
+ neighbours = @alive_counter.count(cell)
+ neighbours < 2 or neighbours > 3
+ end
+ should_die.each { |cell| @new_generation.delete cell }
+ end
+
+ def breed_new_cells
+ keys = @old_generation.keys
+ for_testing = keys.inject([]) { |all, cell| all | @alive_counter.dead_neighbours(cell) }
+ should_breed = for_testing.select { |cell| @alive_counter.count(cell) == 3 }
+ should_breed.each { |cell| @new_generation[cell] = true }
+ end
+ end
+end
Здравейте, много бих се радвал ако счетете една малка промяна в кода, получена от ненавременна оптимизация:
Ако в първоначално публикувания код в метода Board#new_generation се замени редът next_generation.cells = @mutator.generate с next_generation.cells = @mutator.mutate ще работи нормално.
Явно оптимизациите в последния момент могат да счупят цялата програма... :)
Поздрави! Христо
Жест с пръст тип "много внимавай, това не е окей" :) Няма да се повтори ;)