Commit 3d2a6da

mo khan <mo@mokhan.ca>
2014-06-21 21:06:47
finish pairing session with Ben.
1 parent 9704607
spec/cell_spec.rb
@@ -0,0 +1,159 @@
+class Cell
+  attr_accessor :x, :y
+  def initialize(populated: false)
+    @populated = populated
+  end
+
+  def spawn(neighbors)
+    populated_neighbors = neighbors.find_all { |x| x.populated? }
+    if populated?
+      Cell.new(populated: (2...4).include?(populated_neighbors.count))
+    else
+      Cell.new(populated: populated_neighbors.count == 3)
+    end
+  end
+
+  def neighbor?(other_cell)
+    if matches_x?(other_cell) && one_cell_away(other_cell.y - self.y)
+      return true
+    elsif matches_y?(other_cell) && one_cell_away(other_cell.x - self.x)
+      return true
+    end
+    false
+  end
+
+  def populated?
+    @populated
+  end
+
+  private
+
+  def matches_x?(other_cell)
+    other_cell.x == x
+  end
+
+  def matches_y?(other_cell)
+    other_cell.y == y
+  end
+
+  def one_cell_away(difference)
+    difference.abs == 1
+  end
+end
+
+describe Cell do
+  let(:populated_neighbor) { Cell.new(populated: true) }
+  let(:unpopulated_neighbor) { Cell.new(populated: false) }
+
+  context "when populated" do
+    subject { Cell.new(populated: true) }
+
+    it "is populated at creation" do
+      expect(subject.populated?).to be_truthy
+    end
+
+    context "when it has a single populated neighbor" do
+      let(:neighbors) { [populated_neighbor, unpopulated_neighbor] }
+
+      it "dies of isolation" do
+        expect(subject.spawn(neighbors)).to_not be_populated
+      end
+    end
+
+    context 'when it has two populated neighbors' do
+      let(:neighbors) { [populated_neighbor] * 2 }
+
+      it "remains populated" do
+        expect(subject.spawn(neighbors)).to be_populated
+      end
+    end
+
+    context 'when it has three populated neighbors' do
+      let(:neighbors) { [populated_neighbor] * 3 }
+
+      it "remains populated" do
+        expect(subject.spawn(neighbors)).to be_populated
+      end
+    end
+
+    context 'when it has more than three neighbors' do
+      let(:neighbors) { [populated_neighbor] * 4 }
+
+      it "becomes unpopulated" do
+        expect(subject.spawn(neighbors)).to_not be_populated
+      end
+    end
+  end
+
+  context "when unpopulated" do
+    subject { Cell.new(populated: false) }
+    let(:populated_neighbors) { [populated_neighbor] * 2 }
+    let(:neighbors) { populated_neighbors + [unpopulated_neighbor] }
+
+    context "when it has two populated neighbors" do
+      it "remains unpopulated" do
+        expect(subject.spawn(neighbors)).to_not be_populated
+      end
+    end
+  end
+
+  describe "neighbor?" do
+    subject { create_cell(3, 3) }
+
+    context "when other cell is one cell north" do
+      it "returns true" do
+        expect(subject.neighbor?(create_cell(3, 4))).to be_truthy
+      end
+    end
+
+    context "when the other cell is two cells north" do
+      it "returns false" do
+        expect(subject.neighbor?(create_cell(3, 5))).to be_falsey
+      end
+    end
+
+    context "when other cell is one cell east" do
+      it "returns true" do
+        expect(subject.neighbor?(create_cell(4, 3))).to be_truthy
+      end
+    end
+
+    context "when other cell is two cells to the east" do
+      it "returns true" do
+        expect(subject.neighbor?(create_cell(5, 3))).to be_falsey
+      end
+    end
+
+    context "when the other cell is one cell to the south" do
+      it "return true" do
+        expect(subject.neighbor?(create_cell(3, 2))).to be_truthy
+      end
+    end
+
+    context "when the other cell is two cells to the south" do
+      it "returns false" do
+        expect(subject.neighbor?(create_cell(3, 1))).to be_falsey
+      end
+    end
+
+    context "when the other cell is one cell to the west" do
+      it "returns true" do
+        expect(subject.neighbor?(create_cell(2, 3))).to be_truthy
+      end
+    end
+
+    context "when the other cell is two cells to the west" do
+      it "returns true" do
+        expect(subject.neighbor?(create_cell(1, 3))).to be_falsey
+      end
+    end
+
+    def create_cell(x, y)
+      Cell.new.tap do |cell|
+        cell.x = x
+        cell.y = y
+      end
+    end
+  end
+end
+
spec/spec_helper.rb
@@ -0,0 +1,78 @@
+# This file was generated by the `rspec --init` command. Conventionally, all
+# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
+# The generated `.rspec` file contains `--require spec_helper` which will cause this
+# file to always be loaded, without a need to explicitly require it in any files.
+#
+# Given that it is always loaded, you are encouraged to keep this file as
+# light-weight as possible. Requiring heavyweight dependencies from this file
+# will add to the boot time of your test suite on EVERY test run, even for an
+# individual file that may not need all of that loaded. Instead, make a
+# separate helper file that requires this one and then use it only in the specs
+# that actually need it.
+#
+# The `.rspec` file also contains a few flags that are not defaults but that
+# users commonly want.
+#
+# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+# The settings below are suggested to provide a good initial experience
+# with RSpec, but feel free to customize to your heart's content.
+=begin
+  # These two settings work together to allow you to limit a spec run
+  # to individual examples or groups you care about by tagging them with
+  # `:focus` metadata. When nothing is tagged with `:focus`, all examples
+  # get run.
+  config.filter_run :focus
+  config.run_all_when_everything_filtered = true
+
+  # Many RSpec users commonly either run the entire suite or an individual
+  # file, and it's useful to allow more verbose output when running an
+  # individual spec file.
+  if config.files_to_run.one?
+    # Use the documentation formatter for detailed output,
+    # unless a formatter has already been configured
+    # (e.g. via a command-line flag).
+    config.default_formatter = 'doc'
+  end
+
+  # Print the 10 slowest examples and example groups at the
+  # end of the spec run, to help surface which specs are running
+  # particularly slow.
+  config.profile_examples = 10
+
+  # Run specs in random order to surface order dependencies. If you find an
+  # order dependency and want to debug it, you can fix the order by providing
+  # the seed, which is printed after each run.
+  #     --seed 1234
+  config.order = :random
+
+  # Seed global randomization in this process using the `--seed` CLI option.
+  # Setting this allows you to use `--seed` to deterministically reproduce
+  # test failures related to randomization by passing the same `--seed` value
+  # as the one that triggered the failure.
+  Kernel.srand config.seed
+
+  # rspec-expectations config goes here. You can use an alternate
+  # assertion/expectation library such as wrong or the stdlib/minitest
+  # assertions if you prefer.
+  config.expect_with :rspec do |expectations|
+    # Enable only the newer, non-monkey-patching expect syntax.
+    # For more details, see:
+    #   - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
+    expectations.syntax = :expect
+  end
+
+  # rspec-mocks config goes here. You can use an alternate test double
+  # library (such as bogus or mocha) by changing the `mock_with` option here.
+  config.mock_with :rspec do |mocks|
+    # Enable only the newer, non-monkey-patching expect syntax.
+    # For more details, see:
+    #   - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
+    mocks.syntax = :expect
+
+    # Prevents you from mocking or stubbing a method that does not exist on
+    # a real object. This is generally recommended.
+    mocks.verify_partial_doubles = true
+  end
+=end
+end
spec/world_spec.rb
@@ -0,0 +1,33 @@
+class World
+  def initialize(cells)
+    @cells = cells
+  end
+
+  def neighbors_for(cell)
+    @cells.find_all { |x| cell.neighbor?(x) }
+  end
+end
+
+describe World do
+  subject { World.new(cells) }
+  let(:cells) { [neighbor, other_cell] }
+  let(:neighbor) { Object.new }
+  let(:other_cell) { Object.new }
+
+  context "#neighbors_for" do
+    let(:cell) { Object.new }
+
+    before :each do
+      cell.stub(:neighbor?).with(neighbor).and_return(true)
+      cell.stub(:neighbor?).with(other_cell).and_return(false)
+    end
+
+    it "returns the neighboring cells" do
+      expect(subject.neighbors_for(cell)).to include(neighbor)
+    end
+
+    it "does not return cells that are not neighbors" do
+      expect(subject.neighbors_for(cell)).to_not include(other_cell)
+    end
+  end
+end
.rspec
@@ -0,0 +1,3 @@
+--color
+--warnings
+--require spec_helper