bijection 0.0.1 → 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.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Rakefile CHANGED
@@ -1 +1,7 @@
1
1
  require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
- require "bijection/version"
3
+ require "bijection"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "bijection"
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.authors = ["Ryan Berckmans"]
9
9
  s.email = ["ryan.berckmans@gmail.com"]
10
10
  s.homepage = "https://github.com/ryanberckmans/bijection"
11
- s.summary = "bijection container in ruby; pre-alpha wip"
12
- s.description = s.summary
11
+ s.summary = "bijection container in ruby"
12
+ s.description = s.summary + ". See example in Class Bijection."
13
13
 
14
14
  s.rubyforge_project = "bijection"
15
15
 
@@ -1,12 +1,143 @@
1
- require "bijection/version"
2
- require "bijection/base"
3
-
4
- # @example b = Bijection.new
5
- module Bijection
6
- class << self
7
- # @return [Base]
8
- def new
9
- Bijection::Base.new
10
- end
1
+
2
+ # Bijection is a container similar to a Hash with unique values.
3
+ # {http://en.wikipedia.org/wiki/Bijection}
4
+ #
5
+ # Bijection associates each non-nil unique x in a set X, with a non-nil unique y in a set Y.
6
+ #
7
+ # Please send (welcome) feedback and bug reports to my {https://github.com/ryanberckmans github}.
8
+ #
9
+ # @example
10
+ # b = Bijection.new
11
+ # b.add 5, 7 # associates 5 in X with 7 in Y
12
+ # b.size
13
+ # => 1
14
+ # b.add 5, 2 # raises, 5 already in X
15
+ # b.add "foo", 7 # raises, 7 already in Y
16
+ # b.add "bar", 5 # OK; 5 was not yet in Y
17
+ # b.size
18
+ # => 2
19
+ # d = b.domain # d == [5, "bar"]
20
+ # r = b.range # r == [7, 5] # i.e., not the "same" 5 in domain
21
+ # b.each_x { |x| puts x }
22
+ # => 5
23
+ # => "bar"
24
+ # b.each_y { |y| puts y }
25
+ # => 7
26
+ # => 5 # i.e., not the "same" 5 that's in X
27
+ # b.each_pair { |x,y| .. }
28
+ # x = b.get_x 7 # x == 5
29
+ # y = b.get_y 5 # y == 7
30
+ # is_nil = b.get_x "returns nil if not found" # is_nil == nil
31
+ # b.inverse! # X and Y are now swapped; all as above with x and y swapped
32
+ class Bijection
33
+ VERSION = "0.1.0"
34
+
35
+ def initialize
36
+ @X = {} # @X[x] -> y
37
+ @Y = {} # @Y[y] -> x
38
+ end
39
+
40
+ # returns the number of pairs in the bijection
41
+ # @return [Fixnum]
42
+ def size
43
+ @X.size
44
+ end
45
+
46
+ # add (x,y) to the bijection set (X,Y)
47
+ # @param x the non-nil object associated with y
48
+ # @param y the non-nil object associated with x
49
+ # @note x must be unique in X; y must be unique in Y
50
+ # @return [self]
51
+ def add( x, y )
52
+ raise "Bijection: x may not be nil" if x == nil
53
+ raise "Bijection: y may not be nil" if y == nil
54
+ raise "Bijection: #{x.to_s} already present in domain set X" if @X.key? x
55
+ raise "Bijection: #{y.to_s} already present in range set Y" if @Y.key? y
56
+ @X[x] = y
57
+ @Y[y] = x
58
+ self
59
+ end
60
+
61
+ # get the domain set X as an Array
62
+ # @return [Array]
63
+ def domain
64
+ @X.keys
65
+ end
66
+
67
+ # get the range set Y as an Array
68
+ # @return [Array]
69
+ def range
70
+ @Y.keys
71
+ end
72
+
73
+ # swap domain X and range Y of this
74
+ # @return [nil]
75
+ def inverse!
76
+ temp = @X
77
+ @X = @Y
78
+ @Y = temp
79
+ nil
80
+ end
81
+
82
+ # get the x associated with y
83
+ # @param y in domain set Y
84
+ # @return the x associated with y, or nil if y not in range Y
85
+ def get_x( y )
86
+ @Y[y]
87
+ end
88
+
89
+ # get the y associated with x
90
+ # @param x in domain set X
91
+ # @return the y associated with x, or nil if x not in domain X
92
+ def get_y( x )
93
+ @X[x]
94
+ end
95
+
96
+ # @yield [x] each x in domain set X
97
+ # @return [nil]
98
+ def each_x
99
+ @X.each_key { |x| yield x } if block_given?
100
+ nil
101
+ end
102
+
103
+ # @yield [y] each y in range set Y
104
+ # @return [nil]
105
+ def each_y
106
+ @Y.each_key { |y| yield y } if block_given?
107
+ nil
108
+ end
109
+
110
+ # @yield [x,y] each (x,y) in sets X and Y
111
+ # @return [nil]
112
+ def each_pair
113
+ @X.each_pair { |x,y| yield x,y } if block_given?
114
+ nil
115
+ end
116
+
117
+ # given x, delete (x,y) and return y
118
+ # @param (see #get_x)
119
+ # @example
120
+ # b = Bijection.new
121
+ # x = 2 ; y = 3
122
+ # b.add x, y
123
+ # y = nil
124
+ # while true do y = b.delete_by_x x ; b.add x, y end
125
+ # @return (see #get_x)
126
+ def delete_by_x( x )
127
+ y = @X[x]
128
+ @X.delete x
129
+ @Y.delete y
130
+ y
131
+ end
132
+
133
+ # given y, delete (x,y) and return x
134
+ # @param (see #get_y)
135
+ # @return (see #get_y)
136
+ # see example #delete_by_x
137
+ def delete_by_y( y )
138
+ x = @Y[y]
139
+ @Y.delete y
140
+ @X.delete x
141
+ x
11
142
  end
12
143
  end
@@ -0,0 +1,160 @@
1
+ require "spec_helper"
2
+
3
+ describe Bijection do
4
+ before(:each) { @b = Bijection.new }
5
+
6
+ it "initializes with empty domain" do
7
+ @b.domain.should be_empty
8
+ end
9
+
10
+ it "initializes with empty range" do
11
+ @b.range.should be_empty
12
+ end
13
+
14
+ it "initializes with empty size" do
15
+ @b.size.should == 0
16
+ end
17
+
18
+ it "returns self when add is called" do
19
+ @b.add(5, 3).should == @b
20
+ end
21
+
22
+ it "returns nil when inverse! is called" do
23
+ @b.inverse!.should be_nil
24
+ end
25
+
26
+ it "add raises when x is nil" do
27
+ expect { @b.add nil, "fooz" }.to raise_error
28
+ end
29
+
30
+ it "add raises when y is nil" do
31
+ expect { @b.add 57, nil }.to raise_error
32
+ end
33
+
34
+ it "delete_by_x returns nil for x not in X" do
35
+ @b.delete_by_x(5).should be_nil
36
+ end
37
+
38
+ it "delete_by_y returns nil for y not in Y" do
39
+ @b.delete_by_y(5).should be_nil
40
+ end
41
+
42
+ it "each_x returns nil" do
43
+ @b.each_x.should be_nil
44
+ end
45
+
46
+ it "each_y returns nil" do
47
+ @b.each_y.should be_nil
48
+ end
49
+
50
+ it "each_pair returns nil" do
51
+ @b.each_pair.should be_nil
52
+ end
53
+
54
+ context "with one pair added" do
55
+ before :each do
56
+ @x = 3
57
+ @y = []
58
+ @b.add @x, @y
59
+ end
60
+
61
+ it "has domain with exactly x" do
62
+ @b.domain.should == [@x]
63
+ end
64
+
65
+ it "has range with exactly y" do
66
+ @b.range.should == [@y]
67
+ end
68
+
69
+ it "finds x in each_x" do
70
+ @b.each_x { |x| x.should == @x }
71
+ end
72
+
73
+ it "finds y in the each_y" do
74
+ @b.each_y { |y| y.should == @y }
75
+ end
76
+
77
+ it "finds x,y in each_pair" do
78
+ x1 = nil
79
+ y1 = nil
80
+ @b.each_pair do |x,y|
81
+ x1 = x
82
+ y1 = y
83
+ end
84
+ x1.should == @x
85
+ y1.should == @y
86
+ end
87
+
88
+ it "raises when x is re-added" do
89
+ expect { @b.add @x, "fooz" }.to raise_error
90
+ end
91
+
92
+ it "raises when y is re-added" do
93
+ expect { @b.add "sdfdsfs", @y }.to raise_error
94
+ end
95
+
96
+ it "returns x when given y" do
97
+ @b.get_x(@y).should == @x
98
+ end
99
+
100
+ it "returns y when given x" do
101
+ @b.get_y(@x).should == @y
102
+ end
103
+
104
+ it "returns nil when given x not in X" do
105
+ @b.get_y(7).should be_nil
106
+ end
107
+
108
+ it "returns nil when given y not in Y" do
109
+ @b.get_x("foo").should be_nil
110
+ end
111
+
112
+ it "returns x for delete_by_y y and then the bijection is empty" do
113
+ @b.delete_by_y(@y).should == @x
114
+ @b.size == 0
115
+ end
116
+
117
+ it "returns y for delete_by_x x and then the bijection is empty" do
118
+ @b.delete_by_x(@x).should == @y
119
+ @b.size == 0
120
+ end
121
+
122
+ context "after deleting (x,y)" do
123
+ before :each do
124
+ @b.delete_by_x @x
125
+ end
126
+
127
+ it "bijection is empty" do
128
+ @b.size.should == 0
129
+ end
130
+
131
+ it "allows re-adding of (x,y)" do
132
+ @b.add @x, @y
133
+ end
134
+
135
+ context "when re-adding (x,y)" do
136
+ before :each do
137
+ @b.add @x, @y
138
+ end
139
+
140
+ it "should have size 1" do
141
+ @b.size.should == 1
142
+ end
143
+ end
144
+ end
145
+
146
+ context "the inverse" do
147
+ before(:each) do
148
+ @b.inverse!
149
+ end
150
+
151
+ it "returns y for get_x" do
152
+ @b.get_x(@x).should == @y
153
+ end
154
+
155
+ it "returns x for get_y" do
156
+ @b.get_y(@y).should == @x
157
+ end
158
+ end # context inverse
159
+ end # context one pair added
160
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bijection
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,9 +9,9 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-06-20 00:00:00.000000000Z
12
+ date: 2011-06-21 00:00:00.000000000Z
13
13
  dependencies: []
14
- description: bijection container in ruby; pre-alpha wip
14
+ description: bijection container in ruby. See example in Class Bijection.
15
15
  email:
16
16
  - ryan.berckmans@gmail.com
17
17
  executables: []
@@ -19,14 +19,14 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - .gitignore
22
+ - .rspec
22
23
  - .rvmrc
23
24
  - .yardopts
24
25
  - Gemfile
25
26
  - Rakefile
26
27
  - bijection.gemspec
27
28
  - lib/bijection.rb
28
- - lib/bijection/base.rb
29
- - lib/bijection/version.rb
29
+ - spec/lib/bijection_spec.rb
30
30
  - spec/spec_helper.rb
31
31
  homepage: https://github.com/ryanberckmans/bijection
32
32
  licenses: []
@@ -51,5 +51,5 @@ rubyforge_project: bijection
51
51
  rubygems_version: 1.8.5
52
52
  signing_key:
53
53
  specification_version: 3
54
- summary: bijection container in ruby; pre-alpha wip
54
+ summary: bijection container in ruby
55
55
  test_files: []
@@ -1,68 +0,0 @@
1
- module Bijection
2
-
3
- # @example
4
- # b = Bijection.new
5
- # => Bijection::Base
6
- class Base
7
- def initialize
8
- @x = {}
9
- @y = {}
10
- end
11
-
12
- # add (x,y) to the bijection set (X,Y)
13
- # @param x the object associated with y
14
- # @param y the object associated with x
15
- # @note x must be unique in X; y must be unique in Y
16
- # @return self
17
- def map( x, y )
18
- self
19
- end
20
-
21
- # @return [Enumerator] the domain set X
22
- def domain
23
- @x.each_key
24
- end
25
-
26
- # @return [Enumerator] the range set Y
27
- def range
28
- @y.each_key
29
- end
30
-
31
- # swap domain X and range Y of this
32
- # @return nil
33
- def inverse!
34
- end
35
-
36
- # @param y in domain set Y
37
- # @return the x associated with y
38
- def get_x( y )
39
- end
40
-
41
- # @param x in domain set X
42
- # @return the y associated with x
43
- def get_y( x )
44
- end
45
-
46
- # @return [Enumerator] an enumerator all (x,y)
47
- def each_pair
48
- end
49
-
50
- # given x, delete (x,y) and return y
51
- # @param (see #get_x)
52
- # @example
53
- # b = Bijection.new
54
- # x = 2 ; y = 3
55
- # b.map x, y
56
- # y = nil
57
- # while 1 { y = b.delete_x x ; b.map x, y }
58
- # @return the y associated with x
59
- def delete_x( x )
60
- end
61
-
62
- # given y, delete (x,y) and return x
63
- # @param (see #get_y)
64
- # @return x associated with y
65
- def delete_y( y )
66
- end
67
- end
68
- end
@@ -1,3 +0,0 @@
1
- module Bijection
2
- VERSION = "0.0.1"
3
- end