life 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --order random
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in life.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Joel Quenneville
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ # Life
2
+
3
+ A ruby implementation of Conway's [game of life](http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life).
4
+
5
+ ## Installation
6
+
7
+ $ gem install life
8
+
9
+ ## Usage
10
+
11
+ TODO: Write usage instructions here
12
+
13
+ ## Contributing
14
+
15
+ 1. Fork it
16
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
17
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
18
+ 4. Push to the branch (`git push origin my-new-feature`)
19
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,8 @@
1
+ require "life/version"
2
+ require 'life/cell'
3
+ require 'life/world'
4
+ require 'life/grid'
5
+
6
+ module Life
7
+ # Your code goes here...
8
+ end
@@ -0,0 +1,22 @@
1
+ class Cell
2
+
3
+ def initialize(live)
4
+ @live = live
5
+ end
6
+
7
+ def live?
8
+ @live
9
+ end
10
+
11
+ def dead?
12
+ !@live
13
+ end
14
+
15
+ def live
16
+ @live = true
17
+ end
18
+
19
+ def kill
20
+ @live = false
21
+ end
22
+ end
@@ -0,0 +1,44 @@
1
+ class Grid < Array
2
+
3
+ def initialize(x, y, seed=[])
4
+ @width = x
5
+ @height = y
6
+ super(x) { Array.new(y) { Cell.new(false) } }
7
+ seed(seed)
8
+ end
9
+
10
+ def deep_copy
11
+ Marshal.load(Marshal.dump(self))
12
+ end
13
+
14
+ def live_neighbor_count_for(x, y)
15
+ count = 0
16
+ x_range(x).each do |curr_x|
17
+ y_range(y).each do |curr_y|
18
+ unless (curr_x == x && curr_y == y)
19
+ count += 1 if self[curr_x][curr_y].live?
20
+ end
21
+ end
22
+ end
23
+ count
24
+ end
25
+
26
+ private
27
+ def x_range(x)
28
+ west = x - 1 < 0 ? 0 : x - 1
29
+ east = x + 1 > @width - 1 ? @width - 1 : x + 1
30
+ west..east
31
+ end
32
+
33
+ def y_range(y)
34
+ north = y - 1 < 0 ? 0 : y - 1
35
+ south = y + 1 > @height - 1 ? @height - 1 : y + 1
36
+ north..south
37
+ end
38
+
39
+ def seed(pattern)
40
+ pattern.each do |x, y|
41
+ self[x][y].live
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module Life
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,28 @@
1
+ class World
2
+
3
+ attr_reader :current
4
+
5
+ def initialize(x, y, seed = [])
6
+ @current = Grid.new(x, y, seed)
7
+ @next = @current.deep_copy
8
+ end
9
+
10
+ def tick
11
+ current.each do |row|
12
+ x = current.index(row)
13
+ row.each do |cell|
14
+ y = row.index(cell)
15
+ if cell.live?
16
+ case @current.live_neighbor_count_for(x,y)
17
+ when 0..1 then @next[x][y].kill
18
+ when 2..3 then @next[x][y].live
19
+ when 4..8 then @next[x][y].kill
20
+ end
21
+ elsif cell.dead? && @current.live_neighbor_count_for(x,y) == 3
22
+ @next[x][y].live
23
+ end
24
+ end
25
+ end
26
+ @current = @next.deep_copy
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/life/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Joel Quenneville"]
6
+ gem.email = ["joel.quenneville@collegeplus.org"]
7
+ gem.description = %q{Conway's Game of life in ruby}
8
+ gem.summary = %q{Conway's Game of life in ruby}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "life"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Life::VERSION
17
+
18
+ gem.add_development_dependency 'rspec'
19
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cell do
4
+ describe "#live?" do
5
+ subject { cell }
6
+ context "when live" do
7
+ let(:cell) { Cell.new(true) }
8
+ it { should be_live }
9
+ end
10
+ context "when dead" do
11
+ let(:cell) { Cell.new(false) }
12
+ it { should_not be_live }
13
+ end
14
+ end
15
+
16
+ describe "#dead?" do
17
+ subject { cell }
18
+ context "when live" do
19
+ let(:cell) { Cell.new(true) }
20
+ it { should_not be_dead }
21
+ end
22
+ context "when dead" do
23
+ let(:cell) { Cell.new(false) }
24
+ it { should be_dead }
25
+ end
26
+ end
27
+
28
+ describe "#live" do
29
+ subject { cell }
30
+ before { subject.live }
31
+ context "when live" do
32
+ let(:cell) { Cell.new(true) }
33
+ it { should be_live }
34
+ end
35
+ context "when dead" do
36
+ let(:cell) { Cell.new(false) }
37
+ it { should be_live }
38
+ end
39
+ end
40
+
41
+ describe "#kill" do
42
+ subject { cell }
43
+ before { subject.kill }
44
+ context "when live" do
45
+ let(:cell) { Cell.new(true) }
46
+ it { should_not be_live }
47
+ end
48
+ context "when dead" do
49
+ let(:cell) { Cell.new(false) }
50
+ it { should_not be_live }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grid do
4
+
5
+ describe ".new" do
6
+ let(:grid) { Grid.new(10, 8) }
7
+ it "should be a 2d array that is 10 wide" do
8
+ grid.length.should eq 10
9
+ end
10
+ it "should be a 2d array that is 8 high" do
11
+ grid.first.length.should eq 8
12
+ end
13
+ it "should be populated with dead cells" do
14
+ grid[0][1].live?.should be_false
15
+ end
16
+ end
17
+
18
+ describe "#deep_copy" do
19
+ let(:grid) { Grid.new(3,4) }
20
+ it "should create a distinct copy" do
21
+ grid.deep_copy.should_not eq grid
22
+ end
23
+ end
24
+
25
+ describe "seed pattern" do
26
+ let(:grid) { Grid.new(4,5, [[0,0], [1,2], [3,1]])}
27
+ it "should be initialized correctly" do
28
+ grid[0][0].should be_live
29
+ grid[1][2].should be_live
30
+ grid[3][1].should be_live
31
+ end
32
+ end
33
+
34
+ describe "#live_neighbor_count_for" do
35
+ let(:grid) { Grid.new(3,3, [[1,0], [0,1], [2,1], [1,2]])}
36
+ context "when NW corner" do
37
+ it "should return the right amount" do
38
+ grid.live_neighbor_count_for(0,0).should eq 2
39
+ end
40
+ end
41
+ context "when SE corner" do
42
+ it "should return the right amount" do
43
+ grid.live_neighbor_count_for(2,2).should eq 2
44
+ end
45
+ end
46
+ context "when center" do
47
+ it "should return the right amount" do
48
+ grid.live_neighbor_count_for(1,1).should eq 4
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,80 @@
1
+ require "spec_helper"
2
+
3
+ describe World do
4
+ describe "blank world" do
5
+ let(:world) { World.new(10, 8) }
6
+ it "should be populated by separate cells" do
7
+ world.current[0][1].should_not eq world.current[1][1]
8
+ end
9
+ end
10
+
11
+ describe "seed pattern" do
12
+ let(:world) { World.new(4,5, [[0,0], [1,2], [3,1]])}
13
+ it "should be initialized correctly" do
14
+ world.current[0][0].should be_live
15
+ world.current[1][2].should be_live
16
+ world.current[3][1].should be_live
17
+ end
18
+ end
19
+
20
+ describe "Rules" do
21
+ before { world.tick }
22
+ subject { world.current[1][1] }
23
+
24
+ describe "Any live cell with fewer than two live neighbours dies, as if caused by under-population" do
25
+ context "when 0 neighbours" do
26
+ let(:world) { World.new(3,3, [[1,1]]) }
27
+ it { should be_dead }
28
+ end
29
+ context "when 1 neighbours" do
30
+ let(:world) { World.new(3,3, [[1,1], [0,0]]) }
31
+ it { should be_dead }
32
+ end
33
+ end
34
+
35
+ describe "Any live cell with two or three live neighbours lives on to the next generation." do
36
+ context "when 2 neighbours" do
37
+ let(:world) { World.new(3,3, [[1,1], [0,0], [0,1]]) }
38
+ it { should be_live }
39
+ end
40
+
41
+ context "when 3 neighbours" do
42
+ let(:world) { World.new(3,3, [[1,1], [0,0], [0,1], [0,2]]) }
43
+ it { should be_live }
44
+ end
45
+ end
46
+
47
+ describe "Any live cell with more than three live neighbours dies, as if by overcrowding." do
48
+ context "when 4 neighbours" do
49
+ let(:world) { World.new(3,3, [[1,1], [0,0], [0,1], [0,2], [1,0]]) }
50
+ it { should be_dead }
51
+ end
52
+
53
+ context "when 5 neighbours" do
54
+ let(:world) { World.new(3,3, [[1,1], [0,0], [0,1], [0,2], [1,0], [1,2]]) }
55
+ it { should be_dead }
56
+ end
57
+
58
+ context "when 6 neighbours" do
59
+ let(:world) { World.new(3,3, [[1,1], [0,0], [0,1], [0,2], [1,0], [1,2], [2,0]]) }
60
+ it { should be_dead }
61
+ end
62
+
63
+ context "when 7 neighbours" do
64
+ let(:world) { World.new(3,3, [[1,1], [0,0], [0,1], [0,2], [1,0], [1,2], [2,0], [2,1]]) }
65
+ it { should be_dead }
66
+ end
67
+
68
+ context "when 8 neighbours" do
69
+ let(:world) { World.new(3,3, [[1,1], [0,0], [0,1], [0,2], [1,0], [1,2], [2,0], [2,1], [2,2]]) }
70
+ it { should be_dead }
71
+ end
72
+ end
73
+
74
+ describe "Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction." do
75
+ let(:world) { World.new(3,3, [[0,0], [0,1], [0,2]]) }
76
+ it { should be_live }
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,3 @@
1
+ $:.unshift File.expand_path("../../lib", __FILE__)
2
+
3
+ require 'life'
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: life
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joel Quenneville
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Conway's Game of life in ruby
31
+ email:
32
+ - joel.quenneville@collegeplus.org
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - .rspec
39
+ - Gemfile
40
+ - LICENSE
41
+ - README.md
42
+ - Rakefile
43
+ - lib/life.rb
44
+ - lib/life/cell.rb
45
+ - lib/life/grid.rb
46
+ - lib/life/version.rb
47
+ - lib/life/world.rb
48
+ - life.gemspec
49
+ - spec/life/cell_spec.rb
50
+ - spec/life/grid_spec.rb
51
+ - spec/life/world_spec.rb
52
+ - spec/spec_helper.rb
53
+ homepage: ''
54
+ licenses: []
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 1.8.21
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Conway's Game of life in ruby
77
+ test_files:
78
+ - spec/life/cell_spec.rb
79
+ - spec/life/grid_spec.rb
80
+ - spec/life/world_spec.rb
81
+ - spec/spec_helper.rb