Решение на Шеста задача от Евгения Манолова

Обратно към всички решения

Към профила на Евгения Манолова

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 16 успешни тест(а)
  • 2 неуспешни тест(а)

Код

module GameOfLife
class Cell
def initialize(x, y, live = false)
@x = x
@y = y
@live = live
end
def coordinates
[@x, @y]
end
def live_area
# return the 9 squares containing the given cell in the middle
(@x - 1).upto(@x + 1).to_a.product (@y - 1).upto(@y + 1).to_a
end
def live?
@live # maybe the same as: alias :live? :live
end
end
class Board
include Enumerable
def initialize(*initial_cells)
@live_cells = []
initial_cells.each do |cell|
@live_cells << Cell.new(cell[0], cell[1], true)
end
# or just: @live_cells = initial_cells.map { |cell| Cell.new(cell[0], cell[1], true) }
end
def [](x, y)
@live_cells.find { |cell| [x, y] == cell.coordinates } != nil
end
def each
return @live_cells unless block_given?
@live_cells.each do |cell|
yield cell.coordinates
end
end
def next_generation
Generation.new(self).next # how to remove this dependency ?
end
def live_area
# returns all live cells on the board + treir surroundings
@live_cells.map { |cell| cell.live_area }.inject(:|) # merge returned sets
end
end
class Population
def initialize(cell, board)
@cell = cell
@board = board
end
def survive?
@cell.live? and count.between? 2, 3
end
def reproduct?
not @cell.live? and count == 3
end
private
def count
neighbours.find_all { |cell| cell.live? }.count
end
def neighbours
( @cell.live_area - [@cell.coordinates] ).map do |x, y|
Cell.new(x, y, @board[x, y])
end
end
end
class Generation
def initialize(board)
@board = board
end
def next
Board.new *next_generation
end
private
def next_generation
@board.live_area.find_all do |x, y|
population = Population.new Cell.new(x, y, @board[x, y]), @board
population.survive? or population.reproduct?
end
end
end
end

Лог от изпълнението

......F...F.......

Failures:

  1) GameOfLife::Board GameOfLife::Board enumeration live cells count returns the number of live cells on a board
     Failure/Error: new_board([0, 0], [1, 1], [0, 0]).count.should eq 2
       
       expected: 2
            got: 3
       
       (compared using ==)
     # /tmp/d20111221-3114-gej7xo/spec.rb:46:in `block (4 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) GameOfLife::Board evolution returns a new board
     Failure/Error: next_gen = board.next_generation
     NoMethodError:
       undefined method `find_all' for nil:NilClass
     # /tmp/d20111221-3114-gej7xo/solution.rb:101:in `next_generation'
     # /tmp/d20111221-3114-gej7xo/solution.rb:95:in `next'
     # /tmp/d20111221-3114-gej7xo/solution.rb:50:in `next_generation'
     # /tmp/d20111221-3114-gej7xo/spec.rb:74:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.48813 seconds
18 examples, 2 failures

Failed examples:

rspec /tmp/d20111221-3114-gej7xo/spec.rb:43 # GameOfLife::Board GameOfLife::Board enumeration live cells count returns the number of live cells on a board
rspec /tmp/d20111221-3114-gej7xo/spec.rb:72 # GameOfLife::Board evolution returns a new board

История (1 версия и 1 коментар)

Евгения обнови решението на 19.12.2011 03:30 (преди над 12 години)

+module GameOfLife
+
+ class Cell
+ def initialize(x, y, live = false)
+ @x = x
+ @y = y
+ @live = live
+ end
+
+ def coordinates
+ [@x, @y]
+ end
+
+ def live_area
+ # return the 9 squares containing the given cell in the middle
+ (@x - 1).upto(@x + 1).to_a.product (@y - 1).upto(@y + 1).to_a
+ end
+
+ def live?
+ @live # maybe the same as: alias :live? :live
+ end
+ end
+
+ class Board
+ include Enumerable
+
+ def initialize(*initial_cells)
+ @live_cells = []
+
+ initial_cells.each do |cell|
+ @live_cells << Cell.new(cell[0], cell[1], true)
+ end
+
+ # or just: @live_cells = initial_cells.map { |cell| Cell.new(cell[0], cell[1], true) }
+ end
+
+ def [](x, y)
+ @live_cells.find { |cell| [x, y] == cell.coordinates } != nil
+ end
+
+ def each
+ return @live_cells unless block_given?
+
+ @live_cells.each do |cell|
+ yield cell.coordinates
+ end
+ end
+
+ def next_generation
+ Generation.new(self).next # how to remove this dependency ?
+ end
+
+ def live_area
+ # returns all live cells on the board + treir surroundings
+ @live_cells.map { |cell| cell.live_area }.inject(:|) # merge returned sets
+ end
+ end
+
+ class Population
+
+ def initialize(cell, board)
+ @cell = cell
+ @board = board
+ end
+
+ def survive?
+ @cell.live? and count.between? 2, 3
+ end
+
+ def reproduct?
+ not @cell.live? and count == 3
+ end
+
+ private
+
+ def count
+ neighbours.find_all { |cell| cell.live? }.count
+ end
+
+ def neighbours
+ ( @cell.live_area - [@cell.coordinates] ).map do |x, y|
+ Cell.new(x, y, @board[x, y])
+ end
+ end
+
+ end
+
+ class Generation
+
+ def initialize(board)
+ @board = board
+ end
+
+ def next
+ Board.new *next_generation
+ end
+
+ private
+
+ def next_generation
+ @board.live_area.find_all do |x, y|
+ population = Population.new Cell.new(x, y, @board[x, y]), @board
+ population.survive? or population.reproduct?
+ end
+ end
+
+ end
+
+end
  • В #count може да подадеш блока направо на Enumerable#count и да си спестиш find_all
  • Имаш нужда от малки корекции в спазването на конвенциите за whitespace/скоби. Виж този Ruby style guide. (Подкрепям 90% от нещата, казани там.)
  • Класът Cell може би можеше да се спести :) Може би като цяло решението е леко over-engineered. Разгледай решенията на другите, има някои интересни.