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 +1 -0
- data/Rakefile +6 -0
- data/bijection.gemspec +3 -3
- data/lib/bijection.rb +141 -10
- data/spec/lib/bijection_spec.rb +160 -0
- metadata +6 -6
- data/lib/bijection/base.rb +0 -68
- data/lib/bijection/version.rb +0 -3
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Rakefile
CHANGED
data/bijection.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "bijection
|
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
|
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
|
|
data/lib/bijection.rb
CHANGED
@@ -1,12 +1,143 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
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-
|
12
|
+
date: 2011-06-21 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
|
-
description: bijection container in ruby
|
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/
|
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
|
54
|
+
summary: bijection container in ruby
|
55
55
|
test_files: []
|
data/lib/bijection/base.rb
DELETED
@@ -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
|
data/lib/bijection/version.rb
DELETED