borel 0.1.1 → 0.2.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/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  pkg
2
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://www.rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rspec', '~> 2.8.0'
7
+ gem 'guard', '~> 1.0.0'
8
+ end
@@ -0,0 +1,6 @@
1
+ guard 'rspec', :version => 2 do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/borel/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
6
+
@@ -1,3 +1,5 @@
1
+ (The MIT License)
2
+
1
3
  Copyright (c) 2012 Amadeus Folego
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
data/README.md CHANGED
@@ -12,8 +12,8 @@ Borelian sets are formed by enumerable union, intersection or
12
12
 
13
13
  [1]: http://intervals.rubyforge.org
14
14
 
15
- Installation
16
- ------------
15
+ Install
16
+ -------
17
17
 
18
18
  You may install it traditionally, for interactive sessions:
19
19
 
@@ -111,7 +111,46 @@ Interval['a','c'] ^ Interval['b','d'] # -> Interval['b','c']
111
111
  Interval['a','c'] | Interval['b','d'] # -> Interval['a','d']
112
112
  ```
113
113
 
114
- ### Remarks
114
+ Math Extensions
115
+ ---------------
115
116
 
116
- * There is no distinction between **open** and **closed** intervals
117
- * Complement and Minus operations are not supported on any class
117
+ By requiring `borel/math_extensions` you are provided with some natural
118
+ math-related interval methods:
119
+
120
+ ```ruby
121
+ Interval[1,5].rand # -> Random.new.rand 1..5
122
+ Interval[1,5].width # -> 5-1 or 4
123
+ ```
124
+
125
+ It's supported only for Numeric Comparable and arithmetic supported classes
126
+
127
+ Remarks
128
+ -------
129
+
130
+ * There is no distinction between **open** and **closed**intervals
131
+ * Complement and Minus operations have limited support for
132
+ non numeric-comparable classes
133
+
134
+ License
135
+ -------
136
+
137
+ (The MIT License)
138
+
139
+ Copyright (c) 2012 Amadeus Folego
140
+
141
+ Permission is hereby granted, free of charge, to any person obtaining a copy
142
+ of this software and associated documentation files (the "Software"), to
143
+ deal in the Software without restriction, including without limitation the
144
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
145
+ sell copies of the Software, and to permit persons to whom the Software is
146
+ furnished to do so, subject to the following conditions:
147
+
148
+ The above copyright notice and this permission notice shall be included in
149
+ all copies or substantial portions of the Software.
150
+
151
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
152
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
153
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
154
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
155
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
156
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -8,7 +8,9 @@ Gem::Specification.new do |s|
8
8
  s.email = ["amadeusfolego@gmail.com"]
9
9
  s.homepage = "http://github.com/amadeusfolego/borel"
10
10
  s.summary = "Generic ordered set's operations"
11
- s.description = "Borel sets are made of enumerable union and intersection of intervals. Borel performs regular set operations on any interval of a Comparable class."
11
+ s.description = "Borel sets are made of enumerable union and intersection of
12
+ intervals. Borel performs regular operations on any interval of any
13
+ Comparable class."
12
14
  s.rubyforge_project = s.name
13
15
  s.required_ruby_version = ">= 1.9.3"
14
16
  s.required_rubygems_version = ">= 1.3.6"
@@ -0,0 +1,36 @@
1
+ module Borel
2
+ class Construction < ArgumentError
3
+ def initialize(array)
4
+ super(
5
+ "An interval can only be constructed either from at most two " \
6
+ "numbers or from a sequence of arrays of at most two numbers: " +
7
+ array.inspect)
8
+ end
9
+ end
10
+
11
+ class NonDegenerate < ArgumentError
12
+ def initialize(i)
13
+ super("#{i.inspect} is not degenerate.")
14
+ end
15
+ end
16
+
17
+ class NonSimple < ArgumentError
18
+ def initialize(i)
19
+ super("#{i.inspect} is not simple.")
20
+ end
21
+ end
22
+
23
+ class EmptyInterval < ArgumentError
24
+ def initialize
25
+ super("The interval is empty.")
26
+ end
27
+ end
28
+
29
+ class OpenRight < ArgumentError
30
+ def initialize(range)
31
+ super(
32
+ "Cannot construct an interval from a three-dot range " \
33
+ "with end-value #{range.last.inspect}.")
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,5 @@
1
+ require 'borel/errors'
2
+
1
3
  Infinity = 1/0.0
2
4
 
3
5
  class Interval
@@ -200,34 +202,3 @@ class Interval::Multiple < Interval
200
202
  self
201
203
  end
202
204
  end
203
-
204
- module Borel
205
- class Construction < ArgumentError
206
- def initialize(array)
207
- super(
208
- "An interval can only be constructed either from at most two " \
209
- "numbers or from a sequence of arrays of at most two numbers: " +
210
- array.inspect)
211
- end
212
- end
213
-
214
- class NonDegenerate < ArgumentError
215
- def initialize(i)
216
- super("#{i.inspect} is not degenerate.")
217
- end
218
- end
219
-
220
- class NonSimple < ArgumentError
221
- def initialize(i)
222
- super("#{i.inspect} is not simple.")
223
- end
224
- end
225
-
226
- class OpenRight < ArgumentError
227
- def initialize(range)
228
- super(
229
- "Cannot construct an interval from a three-dot range " \
230
- "with end-value #{range.last.inspect}.")
231
- end
232
- end
233
- end
@@ -0,0 +1,2 @@
1
+ require 'borel/math_extensions/randomizable'
2
+ require 'borel/math_extensions/interval_arithmetic'
@@ -0,0 +1,13 @@
1
+ require 'borel'
2
+
3
+ module Borel
4
+ module IntervalArithmetic
5
+ def width
6
+ raise NonSimple, self unless self.respond_to?(:simple?) and self.simple?
7
+ self.extrema.last - self.extrema.first
8
+ end
9
+
10
+ Interval.send(:include, self)
11
+ end
12
+ end
13
+
@@ -0,0 +1,20 @@
1
+ require 'borel/math_extensions/interval_arithmetic'
2
+
3
+ module Borel
4
+ module Randomizable
5
+ def rand
6
+ raise EmptyInterval if self.respond_to?(:empty?) and self.empty?
7
+
8
+ if self.simple?
9
+ Random.new.rand Range.new *self.extrema
10
+ else
11
+ total_weight = self.map(&:width).reduce(:+)
12
+ selected_weight = Random.new.rand 0..total_weight
13
+ rand_interval = self.find{|c| (selected_weight -= c.width) <= 0}
14
+ Random.new.rand Range.new *rand_interval.extrema
15
+ end
16
+ end
17
+
18
+ Interval.send(:include, self)
19
+ end
20
+ end
@@ -1,7 +1,7 @@
1
1
  module Borel
2
2
  MAJOR = 0
3
- MINOR = 1
4
- TINY = 1
3
+ MINOR = 2
4
+ TINY = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, TINY].join('.')
7
7
 
@@ -0,0 +1,33 @@
1
+ require 'borel/math_extensions/interval_arithmetic'
2
+
3
+ describe Borel::IntervalArithmetic do
4
+ it "should include #width" do
5
+ class Foo
6
+ include Borel::IntervalArithmetic
7
+ end
8
+
9
+ Foo.instance_methods.should include :width
10
+ end
11
+
12
+ context "#width" do
13
+ specify "Interval[1,2] -> 1" do
14
+ Interval[1,2].width.should be 1
15
+ end
16
+
17
+ specify "Interval[-1,2] -> 3" do
18
+ Interval[-1,2].width.should be 3
19
+ end
20
+
21
+ specify "Interval[1] -> 0" do
22
+ Interval[1].width.should be 0
23
+ end
24
+
25
+ it "should raise error if not simple" do
26
+ expect{Interval[].width}.
27
+ to raise_error Borel::NonSimple
28
+
29
+ expect{Interval[[1,2],[3,4]].width}.
30
+ to raise_error Borel::NonSimple
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ require 'borel/math_extensions/randomizable'
2
+
3
+ describe Borel::Randomizable do
4
+ it 'should include #rand' do
5
+ class Foo
6
+ include Borel::Randomizable
7
+ end
8
+
9
+ Foo.instance_methods.should include :rand
10
+ end
11
+
12
+ context '#random' do
13
+ let(:interval){ Interval[1,10] }
14
+ let(:rand_mock) { mock }
15
+
16
+ it 'should be a point inside the interval' do
17
+ interval.should include interval.rand
18
+ end
19
+
20
+ it 'should be itself if degenerate' do
21
+ Interval[5].rand.should be 5
22
+ end
23
+
24
+ it 'should be a random number on simple intervals' do
25
+ random_number = 3
26
+ Random.should_receive(:new).and_return(rand_mock)
27
+ rand_mock.should_receive(:rand).with(1..10).and_return(random_number)
28
+
29
+ interval.rand.should be random_number
30
+ end
31
+
32
+ it 'should run on multiple intervals by weight' do
33
+ interval = Interval[[1,5],[6,8]]
34
+
35
+ Random.should_receive(:new).exactly(2).times.and_return(rand_mock)
36
+ rand_mock.should_receive(:rand).with(0..6).and_return(4)
37
+ rand_mock.should_receive(:rand).with(1..5).and_return(3)
38
+
39
+ interval.rand.should be 3
40
+
41
+ Random.should_receive(:new).exactly(2).times.and_return(rand_mock)
42
+ rand_mock.should_receive(:rand).with(0..6).and_return(6)
43
+ rand_mock.should_receive(:rand).with(6..8).and_return(7)
44
+
45
+ interval.rand.should be 7
46
+ end
47
+
48
+ it 'should raise error if empty' do
49
+ expect{Interval[].rand}.
50
+ to raise_error Borel::EmptyInterval
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,11 @@
1
+ require 'borel/math_extensions'
2
+
3
+ describe "Intervals Math Extensions" do
4
+ specify do
5
+ Interval.should include Borel::Randomizable
6
+ end
7
+
8
+ specify do
9
+ Interval.should include Borel::IntervalArithmetic
10
+ end
11
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: borel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,13 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-18 00:00:00.000000000 Z
12
+ date: 2012-02-24 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: Borel sets are made of enumerable union and intersection of intervals.
15
- Borel performs regular set operations on any interval of a Comparable class.
14
+ description: ! 'Borel sets are made of enumerable union and intersection of
15
+
16
+ intervals. Borel performs regular operations on any interval of any
17
+
18
+ Comparable class.'
16
19
  email:
17
20
  - amadeusfolego@gmail.com
18
21
  executables: []
@@ -21,17 +24,26 @@ extra_rdoc_files: []
21
24
  files:
22
25
  - .gitignore
23
26
  - .rspec
24
- - MIT-LICENSE
27
+ - Gemfile
28
+ - Guardfile
29
+ - LICENSE
25
30
  - README.md
26
31
  - Rakefile
27
32
  - borel.gemspec
28
33
  - lib/borel.rb
34
+ - lib/borel/errors.rb
29
35
  - lib/borel/interval.rb
36
+ - lib/borel/math_extensions.rb
37
+ - lib/borel/math_extensions/interval_arithmetic.rb
38
+ - lib/borel/math_extensions/randomizable.rb
30
39
  - lib/borel/nil_class.rb
31
40
  - lib/borel/numeric.rb
32
41
  - lib/borel/range.rb
33
42
  - lib/borel/version.rb
34
43
  - spec/interval_spec.rb
44
+ - spec/math_extensions/interval_arithmetic_spec.rb
45
+ - spec/math_extensions/randomizable_spec.rb
46
+ - spec/math_extensions_spec.rb
35
47
  - spec/nil_class_spec.rb
36
48
  - spec/numeric_spec.rb
37
49
  - spec/range_spec.rb
@@ -57,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
69
  version: 1.3.6
58
70
  requirements: []
59
71
  rubyforge_project: borel
60
- rubygems_version: 1.8.11
72
+ rubygems_version: 1.8.10
61
73
  signing_key:
62
74
  specification_version: 3
63
75
  summary: Generic ordered set's operations