rational_number 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.
- checksums.yaml +7 -0
- data/.gitignore +45 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +67 -0
- data/LICENSE +20 -0
- data/README.md +76 -0
- data/Rakefile +47 -0
- data/lib/rational_number/version.rb +3 -0
- data/lib/rational_number.rb +264 -0
- data/rational_number.gemspec +44 -0
- data/spec/rational_number_spec.rb +165 -0
- data/spec/spec_helper.rb +24 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cc867843cd407372129d0e3090f47476e499295b
|
4
|
+
data.tar.gz: 54595ccb8d94685801bec59fd2412ba9b9e4f920
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7967627fae4440914f62fce3031c00fb6879642137f339a4c53e747c452f54edb6ad9f1729f8f6de36f63e82eda028185b2b06cf4b47cf2a7e3429baa621d319
|
7
|
+
data.tar.gz: d0de1d59035256db00f326c701f20d6af1fb30b4d44e7b08e1b426d46913f39cec54f28464fd0d154c4eab4218db1c038fa2a01f191483db1b6054b0f1d851ab
|
data/.gitignore
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# OSX
|
2
|
+
|
3
|
+
.DS_Store
|
4
|
+
.AppleDouble
|
5
|
+
.LSOverride
|
6
|
+
Icon
|
7
|
+
|
8
|
+
# Thumbnails
|
9
|
+
._*
|
10
|
+
|
11
|
+
# Files that might appear on external disk
|
12
|
+
.Spotlight-V100
|
13
|
+
.Trashes
|
14
|
+
|
15
|
+
# Windows
|
16
|
+
# Windows image file caches
|
17
|
+
Thumbs.db
|
18
|
+
ehthumbs.db
|
19
|
+
|
20
|
+
# Folder config file
|
21
|
+
Desktop.ini
|
22
|
+
|
23
|
+
# Recycle Bin used on file shares
|
24
|
+
$RECYCLE.BIN/
|
25
|
+
|
26
|
+
#Ruby standard
|
27
|
+
|
28
|
+
*.gem
|
29
|
+
*.rbc
|
30
|
+
.bundle
|
31
|
+
.config
|
32
|
+
coverage
|
33
|
+
InstalledFiles
|
34
|
+
lib/bundler/man
|
35
|
+
pkg
|
36
|
+
rdoc
|
37
|
+
spec/reports
|
38
|
+
test/tmp
|
39
|
+
test/version_tmp
|
40
|
+
tmp
|
41
|
+
|
42
|
+
# YARD artifacts
|
43
|
+
.yardoc
|
44
|
+
_yardoc
|
45
|
+
doc/
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rails_4_gem_devel
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.0.0-p195
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rational_number (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activesupport (4.0.0)
|
10
|
+
i18n (~> 0.6, >= 0.6.4)
|
11
|
+
minitest (~> 4.2)
|
12
|
+
multi_json (~> 1.3)
|
13
|
+
thread_safe (~> 0.1)
|
14
|
+
tzinfo (~> 0.3.37)
|
15
|
+
atomic (1.1.13)
|
16
|
+
colorize (0.5.8)
|
17
|
+
coveralls (0.6.7)
|
18
|
+
colorize
|
19
|
+
multi_json (~> 1.3)
|
20
|
+
rest-client
|
21
|
+
simplecov (>= 0.7)
|
22
|
+
thor
|
23
|
+
diff-lcs (1.2.4)
|
24
|
+
i18n (0.6.5)
|
25
|
+
mime-types (1.24)
|
26
|
+
minitest (4.7.5)
|
27
|
+
multi_json (1.7.9)
|
28
|
+
rake (10.1.0)
|
29
|
+
rest-client (1.6.7)
|
30
|
+
mime-types (>= 1.16)
|
31
|
+
rspec (2.14.1)
|
32
|
+
rspec-core (~> 2.14.0)
|
33
|
+
rspec-expectations (~> 2.14.0)
|
34
|
+
rspec-mocks (~> 2.14.0)
|
35
|
+
rspec-core (2.14.5)
|
36
|
+
rspec-expectations (2.14.2)
|
37
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
38
|
+
rspec-mocks (2.14.3)
|
39
|
+
shoulda (3.5.0)
|
40
|
+
shoulda-context (~> 1.0, >= 1.0.1)
|
41
|
+
shoulda-matchers (>= 1.4.1, < 3.0)
|
42
|
+
shoulda-context (1.1.5)
|
43
|
+
shoulda-matchers (2.3.0)
|
44
|
+
activesupport (>= 3.0.0)
|
45
|
+
simplecov (0.7.1)
|
46
|
+
multi_json (~> 1.0)
|
47
|
+
simplecov-html (~> 0.7.1)
|
48
|
+
simplecov-gem-adapter (1.0.1)
|
49
|
+
simplecov
|
50
|
+
simplecov-html (0.7.1)
|
51
|
+
thor (0.18.1)
|
52
|
+
thread_safe (0.1.2)
|
53
|
+
atomic
|
54
|
+
tzinfo (0.3.37)
|
55
|
+
|
56
|
+
PLATFORMS
|
57
|
+
ruby
|
58
|
+
|
59
|
+
DEPENDENCIES
|
60
|
+
bundler (>= 1.3.0)
|
61
|
+
coveralls
|
62
|
+
rake
|
63
|
+
rational_number!
|
64
|
+
rspec
|
65
|
+
shoulda (>= 3.5.0)
|
66
|
+
simplecov
|
67
|
+
simplecov-gem-adapter
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Leif Ringstad
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# rational_number
|
2
|
+
[](https://travis-ci.org/leifcr/rational_number) [](https://coveralls.io/r/leifcr/rational_number?branch=master)
|
3
|
+
|
4
|
+
This implements basic rational numbers in Ruby. It can be used in tree implementations and provides a really fast way of looking up a sorted tree.
|
5
|
+
|
6
|
+
Read about rational numbers in tree structures here: http://arxiv.org/pdf/0806.3115v1.pdf
|
7
|
+
|
8
|
+
Note: This is NOT a tree implementation, it is only a wrapper of rational numbers in ruby.
|
9
|
+
|
10
|
+
For a proper tree implementation see e.g. [mm-tree](https://github.com/leifcr/mm-tree)
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
### Using bundler
|
15
|
+
|
16
|
+
Latest stable release:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'rational_number'
|
20
|
+
```
|
21
|
+
|
22
|
+
For latest edge version:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
gem 'rational_number', :git => 'https://github.com/leifcr/rational_number.git'
|
26
|
+
```
|
27
|
+
|
28
|
+
This gem *only* supports the following versions:
|
29
|
+
|
30
|
+
* mongomapper >= 0.13
|
31
|
+
* ruby >= 2.0
|
32
|
+
* rails >= 3.2
|
33
|
+
|
34
|
+
_Note: If you are using mongo\_mapper < 0.13, ruby < 2.0 or rails < 3.2 you have to use version 0.1.4.
|
35
|
+
|
36
|
+
### Without bundler
|
37
|
+
|
38
|
+
gem install rational_number
|
39
|
+
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
a = RationalNumber.new # Root
|
44
|
+
b = a.child_from_position(1) # Get child of root in position 1
|
45
|
+
b.next_sibling # Get next sibling of b
|
46
|
+
b.sibling_from_position(5) #Get sibling in position 5 on the current "level"
|
47
|
+
|
48
|
+
# More advanced
|
49
|
+
b.rational_number_from_ancestor_and_position(b,5) # Get a specific rational number from a given ancestor and position
|
50
|
+
|
51
|
+
# check if rational numbers are related
|
52
|
+
a.has_child?(b) # true
|
53
|
+
b.is_child_of?(root) # true
|
54
|
+
|
55
|
+
b.has_ancestor?(a) # true
|
56
|
+
a.is_ancestor_of?(b) # true
|
57
|
+
```
|
58
|
+
|
59
|
+
For more examples see the spec in spec/rational\_number\_spec.rb
|
60
|
+
|
61
|
+
## Note on Patches/Pull Requests
|
62
|
+
|
63
|
+
* Fork the project.
|
64
|
+
* Make your feature addition or bug fix.
|
65
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
66
|
+
* Send me a pull request, if you have features you like to see implemented.
|
67
|
+
|
68
|
+
## Thanks
|
69
|
+
|
70
|
+
_Dan Hazel_: For his paper on rational numbers
|
71
|
+
|
72
|
+
## Copyright
|
73
|
+
|
74
|
+
Original ideas are Copyright Jakob Vidmar and Joel Junström. Please see their github repositories for details
|
75
|
+
Copyright (c) 2013 Leif Ringstad.
|
76
|
+
See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
|
6
|
+
begin
|
7
|
+
Bundler.setup(:default, :development)
|
8
|
+
rescue Bundler::BundlerError => e
|
9
|
+
$stderr.puts e.message
|
10
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
11
|
+
exit e.status_code
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'bundler/setup'
|
15
|
+
require "bundler/gem_tasks"
|
16
|
+
require 'rake'
|
17
|
+
|
18
|
+
begin
|
19
|
+
require 'rspec/core/rake_task'
|
20
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
21
|
+
spec.pattern = 'spec/*_spec.rb'
|
22
|
+
spec.rspec_opts = ['--color']
|
23
|
+
end
|
24
|
+
task :default => :spec
|
25
|
+
rescue LoadError
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
# # Ignore LoadError for jeweler when running on e.g. Travis-CI
|
30
|
+
# begin
|
31
|
+
# require 'jeweler'
|
32
|
+
# Jeweler::Tasks.new do |gem|
|
33
|
+
# # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
34
|
+
# gem.name = "rational_number"
|
35
|
+
# gem.homepage = "https://github.com/leifcr/rational_number"
|
36
|
+
# gem.license = "MIT"
|
37
|
+
# gem.summary = %Q{Rational Number basic class for Ruby}
|
38
|
+
# gem.description = %Q{Provide basic rational numbers for ruby}
|
39
|
+
# gem.email = "leifcr@gmail.com"
|
40
|
+
# gem.authors = ["Leif Ringstad"]
|
41
|
+
# gem.files.exclude [".ruby-*", ".travis.yml"]
|
42
|
+
# # dependencies defined in Gemfile
|
43
|
+
# end
|
44
|
+
# Jeweler::RubygemsDotOrgTasks.new
|
45
|
+
# rescue LoadError
|
46
|
+
# nil
|
47
|
+
# end
|
@@ -0,0 +1,264 @@
|
|
1
|
+
##
|
2
|
+
# Rational Numbers (tree) in ruby
|
3
|
+
#
|
4
|
+
# Read about rational numbers in tree structures here: http://arxiv.org/pdf/0806.3115v1.pdf
|
5
|
+
#
|
6
|
+
# Please note that sibling and child will be identical if you are start at "root" level, with the default values
|
7
|
+
# (nv = 0, dv = 1, snv = 1, sdv = 0)
|
8
|
+
#
|
9
|
+
# Rational numbers always require a "root" at the bottom of the tree
|
10
|
+
#
|
11
|
+
# You can find child values, sibling values, see if a value is parent or child of a given rational number.
|
12
|
+
# It is possible to verify child/parent relationships without even checking with a database.
|
13
|
+
#
|
14
|
+
|
15
|
+
class RationalNumber # < Object
|
16
|
+
include Comparable
|
17
|
+
attr :nv, :dv, :snv, :sdv, :number
|
18
|
+
|
19
|
+
##
|
20
|
+
# Compare to other (Comparable)
|
21
|
+
#
|
22
|
+
def <=>(other)
|
23
|
+
return 0 if (@nv === other.nv) and (@dv === other.dv) and (@snv == other.snv) and (@sdv == other.sdv)
|
24
|
+
if @number < other.number
|
25
|
+
-1
|
26
|
+
elsif @number > other.number
|
27
|
+
1
|
28
|
+
else
|
29
|
+
0
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Convert to string
|
35
|
+
#
|
36
|
+
# @return [String] String describing the rational number.
|
37
|
+
#
|
38
|
+
def to_s
|
39
|
+
"RationalNumber: number: #{@number} nv: #{@nv} dv: #{@dv} snv: #{@snv} sdv: #{@sdv}"
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Convert to Hash
|
44
|
+
#
|
45
|
+
# @return [Hash] hash containing the rational numbers
|
46
|
+
#
|
47
|
+
def to_hash
|
48
|
+
{
|
49
|
+
:nv => @nv,
|
50
|
+
:dv => @dv,
|
51
|
+
:snv => @snv,
|
52
|
+
:sdv => @sdv,
|
53
|
+
:number => @number
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Initialize rational number
|
59
|
+
#
|
60
|
+
# @param [Integer] The nominator value
|
61
|
+
# @param [Integer] The denomitaor value
|
62
|
+
# @param [Integer] The SNV value
|
63
|
+
# @param [Integer] The SDV Value
|
64
|
+
#
|
65
|
+
# @return [undefined]
|
66
|
+
#
|
67
|
+
def initialize(nv = 0, dv = 1, snv = 1, sdv = 0)
|
68
|
+
set_values(nv, dv, snv, sdv)
|
69
|
+
#super()
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Set the values of nv,dv,snv and sdv directly
|
74
|
+
#
|
75
|
+
# @param [Integer] The nominator value
|
76
|
+
# @param [Integer] The denomitaor value
|
77
|
+
# @param [Integer] The SNV value
|
78
|
+
# @param [Integer] The SDV Value
|
79
|
+
#
|
80
|
+
def set_values(nv, dv, snv, sdv)
|
81
|
+
@nv = nv
|
82
|
+
@dv = dv
|
83
|
+
@snv = snv
|
84
|
+
@sdv = sdv
|
85
|
+
@number = Float(nv)/Float(dv)
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# Will set the values from another RationalNumber
|
90
|
+
#
|
91
|
+
# @param [RationalNumber]
|
92
|
+
#
|
93
|
+
# @return [undefined]
|
94
|
+
#
|
95
|
+
def set_from_other(other)
|
96
|
+
set_values(other.nv, other.dv, other.snv, other.sdv)
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# See if rational number is root
|
101
|
+
#
|
102
|
+
def root?
|
103
|
+
(@nv === 0) and (@dv === 1) and (@snv === 1) and (@sdv === 0)
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# Get the calculated postion at the current "level" for this rational number in a "tree"
|
108
|
+
#
|
109
|
+
# @return [Integer] The position
|
110
|
+
#
|
111
|
+
def position
|
112
|
+
_parent = self.parent
|
113
|
+
((@nv - _parent.nv) / _parent.snv)
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# Returns parent as a rational number
|
118
|
+
#
|
119
|
+
# @return [RationalNumber] The parent
|
120
|
+
#
|
121
|
+
def parent
|
122
|
+
raise NoParentRationalNumberIsRootError if root?
|
123
|
+
numerator = @nv
|
124
|
+
denominator = @dv
|
125
|
+
_parent = RationalNumber.new
|
126
|
+
compare_key = RationalNumber.new
|
127
|
+
# make sure we break if we get root values! (numerator == 0 + denominator == 0)
|
128
|
+
while ((compare_key.nv < @nv) && (compare_key.dv < @dv)) && ((numerator > 0) && (denominator > 0))
|
129
|
+
div = numerator / denominator
|
130
|
+
mod = numerator % denominator
|
131
|
+
# set return values to previous values, as they are the parent values
|
132
|
+
_parent.set_from_other(compare_key)
|
133
|
+
|
134
|
+
# temporary calculations (needed)
|
135
|
+
parent_nv = _parent.nv + (div * _parent.snv)
|
136
|
+
parent_dv = _parent.dv + (div * _parent.sdv)
|
137
|
+
|
138
|
+
compare_key.set_values( parent_nv , #nv
|
139
|
+
parent_dv , #dv
|
140
|
+
parent_nv + _parent.snv, #snv
|
141
|
+
parent_dv + _parent.sdv) #sdv
|
142
|
+
numerator = mod
|
143
|
+
if (numerator != 0)
|
144
|
+
denominator = denominator % mod
|
145
|
+
denominator = 1 if denominator == 0
|
146
|
+
end
|
147
|
+
end
|
148
|
+
_parent
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# Return the next sibling rational number
|
153
|
+
#
|
154
|
+
# Uses this RationalNumber parent values
|
155
|
+
#
|
156
|
+
# @return [RationalNumber] The sibling
|
157
|
+
#
|
158
|
+
def next_sibling
|
159
|
+
# Raise error in case we are root
|
160
|
+
raise RationalNumberIsRootNoSiblingsError if root?
|
161
|
+
|
162
|
+
_parent = self.parent # Get parent already to avoid duplicate calculations
|
163
|
+
_position = ((@nv - _parent.nv) / _parent.snv) + 1
|
164
|
+
value_from_parent_and_position(_parent, _position)
|
165
|
+
end
|
166
|
+
|
167
|
+
##
|
168
|
+
# Return the sibling rational number from a given position.
|
169
|
+
#
|
170
|
+
# Uses this RationalNumber parent values
|
171
|
+
#
|
172
|
+
# @param [Integer] The position
|
173
|
+
#
|
174
|
+
# @return [RationalNumber] The sibling
|
175
|
+
#
|
176
|
+
def sibling_from_position(_position)
|
177
|
+
raise RationalNumberIsRootNoSiblingsError if root?
|
178
|
+
_parent = self.parent
|
179
|
+
value_from_parent_and_position(_parent, _position)
|
180
|
+
end
|
181
|
+
|
182
|
+
##
|
183
|
+
# Return the rational number from parent and position
|
184
|
+
#
|
185
|
+
# @param [RationalNumber] The parents RationalNumber for a given RationalNumber and the new sibling
|
186
|
+
# @param [Integer] The position
|
187
|
+
#
|
188
|
+
# @return [RationalNumber] The rational number
|
189
|
+
#
|
190
|
+
def value_from_parent_and_position(_parent, _position)
|
191
|
+
sibling = RationalNumber.new(
|
192
|
+
_parent.nv + (_position * _parent.snv), # nv
|
193
|
+
_parent.dv + (_position * _parent.sdv), # dv
|
194
|
+
_parent.nv + ((_position + 1) * _parent.snv), # snv
|
195
|
+
_parent.dv + ((_position + 1) * _parent.sdv) # sdv
|
196
|
+
)
|
197
|
+
end
|
198
|
+
|
199
|
+
##
|
200
|
+
# Return the child rational number from given position
|
201
|
+
#
|
202
|
+
# @param [Integer] The position
|
203
|
+
#
|
204
|
+
# @return [RationalNumber] The child rational number
|
205
|
+
#
|
206
|
+
def child_from_position(_position)
|
207
|
+
value_from_parent_and_position(self, _position)
|
208
|
+
end
|
209
|
+
|
210
|
+
##
|
211
|
+
# Check if the child is a immediate child of an parent
|
212
|
+
#
|
213
|
+
# @param [RationalNumber] The parents to verify against
|
214
|
+
#
|
215
|
+
# @return [Boolean] true if the parent to verify against is the same as the childs parent
|
216
|
+
#
|
217
|
+
def is_child_of?(_parent)
|
218
|
+
return false if (self == _parent) or self.root?
|
219
|
+
_parent == self.parent
|
220
|
+
end
|
221
|
+
|
222
|
+
##
|
223
|
+
# Check if the parent is a immediate parent of a child
|
224
|
+
#
|
225
|
+
# @param [RationalNumber] The parents to verify against
|
226
|
+
#
|
227
|
+
# @return [Boolean] true if the parent to verify against is the same as the childs parent
|
228
|
+
#
|
229
|
+
def is_parent_of?(_child)
|
230
|
+
return false if self == _child
|
231
|
+
_child.is_child_of?(self)
|
232
|
+
end
|
233
|
+
|
234
|
+
##
|
235
|
+
# Check if the child is a descendant of an parent (at any level)
|
236
|
+
#
|
237
|
+
# @param [RationalNumber] The parents to verify against
|
238
|
+
#
|
239
|
+
# @return [Boolean] true if the parent is any parent above in the hierarchy
|
240
|
+
#
|
241
|
+
def is_descendant_of?(_parent)
|
242
|
+
return false if (self == _parent) or self.root?
|
243
|
+
verify_parent = self # start with beeing self
|
244
|
+
while !verify_parent.root? do
|
245
|
+
verify_parent = verify_parent.parent
|
246
|
+
return true if _parent == verify_parent
|
247
|
+
end
|
248
|
+
false
|
249
|
+
end
|
250
|
+
|
251
|
+
end # class RationalNumber
|
252
|
+
|
253
|
+
|
254
|
+
##
|
255
|
+
# The rational number is root and therefore has no siblings
|
256
|
+
#
|
257
|
+
class RationalNumberIsRootNoSiblingsError < StandardError
|
258
|
+
end
|
259
|
+
|
260
|
+
##
|
261
|
+
# The rational number is root and therefore has no parent
|
262
|
+
#
|
263
|
+
class NoParentRationalNumberIsRootError < StandardError
|
264
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rational_number/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rational_number"
|
7
|
+
s.version = RationalNumberGem::VERSION
|
8
|
+
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.required_ruby_version = ">= 1.9.2"
|
11
|
+
|
12
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
13
|
+
s.authors = ["Leif Ringstad"]
|
14
|
+
s.date = "2013-08-21"
|
15
|
+
s.summary = "Rational Numbers for trees"
|
16
|
+
s.description = "Provide basic rational numbers for trees"
|
17
|
+
s.email = "leifcr@gmail.com"
|
18
|
+
s.extra_rdoc_files = [ "README.md" ]
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
|
22
|
+
s.homepage = "https://github.com/leifcr/rational_number"
|
23
|
+
s.licenses = ["MIT"]
|
24
|
+
s.require_paths = ["lib"]
|
25
|
+
s.rubygems_version = "2.0.3"
|
26
|
+
|
27
|
+
s.add_development_dependency("rake")
|
28
|
+
s.add_development_dependency("rspec")
|
29
|
+
s.add_development_dependency("simplecov")
|
30
|
+
s.add_development_dependency("simplecov-gem-adapter")
|
31
|
+
|
32
|
+
if s.respond_to? :specification_version then
|
33
|
+
s.specification_version = 4
|
34
|
+
|
35
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
36
|
+
s.add_development_dependency(%q<bundler>, [">= 1.3.0"])
|
37
|
+
else
|
38
|
+
s.add_dependency(%q<bundler>, [">= 1.3.0"])
|
39
|
+
end
|
40
|
+
else
|
41
|
+
s.add_dependency(%q<bundler>, [">= 1.3.0"])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "RationalNumber" do
|
3
|
+
before(:each) do
|
4
|
+
@root = RationalNumber.new
|
5
|
+
@first_child = @root.child_from_position(1)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should verify that @root is @root" do
|
9
|
+
@root.root?.should == true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should raise an error when trying to get parent rational number on @root" do
|
13
|
+
expect {@root.parent}.to raise_error(NoParentRationalNumberIsRootError)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should raise an error when trying to get a sibling on @root" do
|
17
|
+
expect {@root.next_sibling}.to raise_error(RationalNumberIsRootNoSiblingsError)
|
18
|
+
expect {@root.sibling_from_position(0)}.to raise_error(RationalNumberIsRootNoSiblingsError)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should verify values" do
|
22
|
+
@root.nv.should == 0
|
23
|
+
@root.dv.should == 1
|
24
|
+
@root.snv.should == 1
|
25
|
+
@root.sdv.should == 0
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should get the first child values" do
|
29
|
+
@first_child.nv.should == 1
|
30
|
+
@first_child.dv.should == 1
|
31
|
+
@first_child.snv.should == 2
|
32
|
+
@first_child.sdv.should == 1
|
33
|
+
@first_child.number.should == Float(@first_child.nv)/Float(@first_child.dv)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should verify the parent values of the first child" do
|
37
|
+
parent = @first_child.parent
|
38
|
+
child = @first_child
|
39
|
+
parent.should == child.parent
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should verify the parent values of a child of the first child" do
|
43
|
+
parent = @first_child
|
44
|
+
child = @first_child.child_from_position(5)
|
45
|
+
parent.should == child.parent
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should get the child values from a given position" do
|
49
|
+
fifth_child = @root.child_from_position(5)
|
50
|
+
fifth_child.nv.should == 5
|
51
|
+
fifth_child.dv.should == 1
|
52
|
+
fifth_child.snv.should == 6
|
53
|
+
fifth_child.sdv.should == 1
|
54
|
+
fifth_child.number.should == Float(fifth_child.nv)/Float(fifth_child.dv)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should get the next sibling from first child" do
|
58
|
+
next_sibling = @first_child.next_sibling
|
59
|
+
next_sibling.nv.should == 2
|
60
|
+
next_sibling.dv.should == 1
|
61
|
+
next_sibling.snv.should == 3
|
62
|
+
next_sibling.sdv.should == 1
|
63
|
+
next_sibling.number.should == Float(next_sibling.nv)/Float(next_sibling.dv)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should get fifth sibling from first child" do
|
67
|
+
fifth_sibling = @first_child.sibling_from_position(5)
|
68
|
+
fifth_sibling.nv.should == 5
|
69
|
+
fifth_sibling.dv.should == 1
|
70
|
+
fifth_sibling.snv.should == 6
|
71
|
+
fifth_sibling.sdv.should == 1
|
72
|
+
fifth_sibling.number.should == Float(fifth_sibling.nv)/Float(fifth_sibling.dv)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should verify two children of the first child" do
|
76
|
+
child_1_1 = @first_child.child_from_position(1)
|
77
|
+
child_1_1.nv.should == 3
|
78
|
+
child_1_1.dv.should == 2
|
79
|
+
child_1_1.snv.should == 5
|
80
|
+
child_1_1.sdv.should == 3
|
81
|
+
child_1_1.number.should == Float(child_1_1.nv)/Float(child_1_1.dv)
|
82
|
+
|
83
|
+
child_1_3 = @first_child.child_from_position(3)
|
84
|
+
|
85
|
+
child_1_3.nv.should == 7
|
86
|
+
child_1_3.dv.should == 4
|
87
|
+
child_1_3.snv.should == 9
|
88
|
+
child_1_3.sdv.should == 5
|
89
|
+
child_1_3.number.should == Float(child_1_3.nv)/Float(child_1_3.dv)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should verify the position of three rational numbers" do
|
93
|
+
child_1_1 = @first_child.child_from_position(1)
|
94
|
+
child_1_1.position.should == 1
|
95
|
+
child_1_3 = @first_child.child_from_position(3)
|
96
|
+
child_1_3.position.should == 3
|
97
|
+
fifth_child = @root.child_from_position(5)
|
98
|
+
fifth_child.position.should == 5
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should verify comparison of rational numbers" do
|
102
|
+
child_1 = @first_child
|
103
|
+
child_1_1 = @first_child.child_from_position(1)
|
104
|
+
child_1_3 = @first_child.child_from_position(3)
|
105
|
+
child_2 = @first_child.next_sibling
|
106
|
+
|
107
|
+
child_1.should < child_1_1
|
108
|
+
child_1_1.should < child_1_3
|
109
|
+
child_1_3.should < child_2
|
110
|
+
child_2.should > child_1
|
111
|
+
child_2.should > child_1_1
|
112
|
+
child_2.should > child_1_3
|
113
|
+
child_1_1.should == child_1_1
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should set values directoy" do
|
117
|
+
a = RationalNumber.new
|
118
|
+
b = @first_child.child_from_position(3)
|
119
|
+
a.set_from_other(b)
|
120
|
+
b.should == a
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should set values from other RationalNumber" do
|
124
|
+
a = RationalNumber.new
|
125
|
+
b = @first_child.child_from_position(3)
|
126
|
+
a.set_values(b.nv,b.dv,b.snv,b.sdv)
|
127
|
+
b.should == a
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should check if the RationalNumber resonds to being a child of an given parent" do
|
131
|
+
child_1_4 = @first_child.child_from_position(4)
|
132
|
+
@first_child.is_child_of?(@root).should == true
|
133
|
+
child_1_4.is_child_of?(@root).should == false
|
134
|
+
child_1_4.is_child_of?(@first_child).should == true
|
135
|
+
child_1_4.is_child_of?(child_1_4).should == false # should return false for same object
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should check if the RationalNumber responds to being a parent of a given child" do
|
139
|
+
child_1_4 = @first_child.child_from_position(4)
|
140
|
+
@root.is_parent_of?(@first_child).should == true
|
141
|
+
@root.is_parent_of?(child_1_4).should == false
|
142
|
+
@first_child.is_parent_of?(child_1_4).should == true
|
143
|
+
child_1_4.is_parent_of?(child_1_4).should == false # should return false for same object
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should respons if the RationalNumber is a descendant of given parent" do
|
147
|
+
child_1_4 = @first_child.child_from_position(4)
|
148
|
+
child_1_4_9 = child_1_4.child_from_position(9)
|
149
|
+
child_1_4_9.is_descendant_of?(@root).should == true
|
150
|
+
child_1_4_9.is_descendant_of?(@first_child).should == true
|
151
|
+
child_1_4_9.is_descendant_of?(child_1_4).should == true
|
152
|
+
|
153
|
+
child_1_4.is_descendant_of?(@root).should == true
|
154
|
+
child_1_4.is_descendant_of?(@first_child).should == true
|
155
|
+
child_1_4.is_descendant_of?(child_1_4_9).should == false
|
156
|
+
|
157
|
+
@first_child.is_descendant_of?(@root).should == true
|
158
|
+
@first_child.is_descendant_of?(child_1_4).should == false
|
159
|
+
|
160
|
+
@root.is_descendant_of?(@root).should == false
|
161
|
+
@first_child.is_descendant_of?(@first_child).should == false
|
162
|
+
@root.is_descendant_of?(child_1_4_9).should == false
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler/setup'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
if ENV['TRAVIS']
|
9
|
+
require 'coveralls'
|
10
|
+
Coveralls.wear!
|
11
|
+
elsif ENV['COVERAGE'] && RUBY_VERSION > "1.8"
|
12
|
+
require 'simplecov'
|
13
|
+
SimpleCov.start do
|
14
|
+
add_filter 'spec'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'rational_number'
|
19
|
+
|
20
|
+
Bundler.require(:default, :test)
|
21
|
+
|
22
|
+
RSpec.configure do |c|
|
23
|
+
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rational_number
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Leif Ringstad
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: simplecov
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov-gem-adapter
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.3.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.3.0
|
83
|
+
description: Provide basic rational numbers for trees
|
84
|
+
email: leifcr@gmail.com
|
85
|
+
executables: []
|
86
|
+
extensions: []
|
87
|
+
extra_rdoc_files:
|
88
|
+
- README.md
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- .rspec
|
92
|
+
- .ruby-gemset
|
93
|
+
- .ruby-version
|
94
|
+
- .travis.yml
|
95
|
+
- Gemfile
|
96
|
+
- Gemfile.lock
|
97
|
+
- LICENSE
|
98
|
+
- README.md
|
99
|
+
- Rakefile
|
100
|
+
- lib/rational_number.rb
|
101
|
+
- lib/rational_number/version.rb
|
102
|
+
- rational_number.gemspec
|
103
|
+
- spec/rational_number_spec.rb
|
104
|
+
- spec/spec_helper.rb
|
105
|
+
homepage: https://github.com/leifcr/rational_number
|
106
|
+
licenses:
|
107
|
+
- MIT
|
108
|
+
metadata: {}
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.9.2
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 2.0.3
|
126
|
+
signing_key:
|
127
|
+
specification_version: 4
|
128
|
+
summary: Rational Numbers for trees
|
129
|
+
test_files:
|
130
|
+
- spec/rational_number_spec.rb
|
131
|
+
- spec/spec_helper.rb
|