Веселин обнови решението на 18.12.2011 09:55 (преди около 13 години)
+require 'set'
+
+module GameOfLife
+
+ NeighbourDeltas = [[-1, 1], [-1, 0], [1, -1], [1, 0], [0, -1], [0, 1], [-1, -1], [1, 1]]
+
+ class Board
+ include Enumerable
+
+ def initialize(*aliveCells)
+ @aliveCells = Set.new(aliveCells)
+ end
+
+ def [](x, y)
+ @aliveCells.include?([x, y])
+ end
+
+ def each
+ @aliveCells.each { |cell| yield cell[0], cell[1] }
+ end
+
+ def count
+ @aliveCells.count
+ end
+
+ def next_generation
+ new_cells = get_all_potential_cells.select { |cell| neighbours_count(cell) == 3 }
+ new_cells |= @aliveCells.select { |x, y| cell_lives?([x, y]) }
+ Board.new(*new_cells)
+ end
+
+ private
+
+ def cell_lives?(cell)
+ [2, 3].include?(neighbours_count(cell))
+ end
+
+ def get_all_potential_cells
+ @aliveCells.inject(Set.new) { |set, cell| set | get_neighbours(cell) } .to_a
+ end
+
+ def get_neighbours(cell)
+ NeighbourDeltas.map { |delta| [delta[0] + cell[0], delta[1] + cell[1]] }
+ end
+
+ def neighbours_count(cell)
+ get_neighbours(cell).select { |cell| @aliveCells.include?(cell) } .length
+ end
+
+ end
+end
Решението изглежда прилично на пръв поглед, но имам малко забележки относно спазването на Ruby coding style-конвенциите:
- Имена на константи, които не са модули и класове, се записват като
NEIGHBOUR_DELTAS
, а неNeighbourDeltas
- Имена на методи, локални, инстанционни променливи и прочее се записват в
underscore_lower_case
, а не така:@aliveCells
. - Пробвай да си кръщаваш методите без
get_*
отпред. Може би ще стане една идея по-четимо. Напримерneighbours_of(cell)
, вместоget_neighbours(cell)
.