Class: RationalNumber
- Inherits:
-
Object
- Object
- RationalNumber
- Includes:
- Comparable
- Defined in:
- lib/rational_number.rb
Overview
Rational Numbers (tree) in ruby
Read about rational numbers in tree structures here: arxiv.org/pdf/0806.3115v1.pdf
Please note that sibling and child will be identical if you are start at “root” level, with the default values (nv = 0, dv = 1, snv = 1, sdv = 0)
Rational numbers always require a “root” at the bottom of the tree
You can find child values, sibling values, see if a value is parent or child of a given rational number. It is possible to verify child/parent relationships without even checking with a database.
Instance Attribute Summary collapse
-
#dv ⇒ Object
readonly
Returns the value of attribute dv.
-
#number ⇒ Object
readonly
Returns the value of attribute number.
-
#nv ⇒ Object
readonly
Returns the value of attribute nv.
-
#sdv ⇒ Object
readonly
Returns the value of attribute sdv.
-
#snv ⇒ Object
readonly
Returns the value of attribute snv.
Instance Method Summary collapse
-
#<=>(other) ⇒ Object
Compare to other (Comparable).
-
#child_from_position(_position) ⇒ RationalNumber
Return the child rational number from given position.
-
#initialize(nv = 0, dv = 1, snv = 1, sdv = 0) ⇒ undefined
constructor
Initialize rational number.
-
#is_child_of?(_parent) ⇒ Boolean
Check if the child is a immediate child of an parent.
-
#is_descendant_of?(_parent) ⇒ Boolean
Check if the child is a descendant of an parent (at any level).
-
#is_parent_of?(_child) ⇒ Boolean
Check if the parent is a immediate parent of a child.
-
#next_sibling ⇒ RationalNumber
Return the next sibling rational number.
-
#parent ⇒ RationalNumber
Returns parent as a rational number.
-
#position ⇒ Integer
Get the calculated postion at the current “level” for this rational number in a “tree”.
-
#root? ⇒ Boolean
See if rational number is root.
-
#set_from_other(other) ⇒ undefined
Will set the values from another RationalNumber.
-
#set_values(nv, dv, snv, sdv) ⇒ Object
Set the values of nv,dv,snv and sdv directly.
-
#sibling_from_position(_position) ⇒ RationalNumber
Return the sibling rational number from a given position.
-
#to_hash ⇒ Hash
Convert to Hash.
-
#to_s ⇒ String
Convert to string.
-
#value_from_parent_and_position(_parent, _position) ⇒ RationalNumber
Return the rational number from parent and position.
Constructor Details
#initialize(nv = 0, dv = 1, snv = 1, sdv = 0) ⇒ undefined
Initialize rational number
67 68 69 70 |
# File 'lib/rational_number.rb', line 67 def initialize(nv = 0, dv = 1, snv = 1, sdv = 0) set_values(nv, dv, snv, sdv) #super() end |
Instance Attribute Details
#dv ⇒ Object (readonly)
Returns the value of attribute dv.
17 18 19 |
# File 'lib/rational_number.rb', line 17 def dv @dv end |
#number ⇒ Object (readonly)
Returns the value of attribute number.
17 18 19 |
# File 'lib/rational_number.rb', line 17 def number @number end |
#nv ⇒ Object (readonly)
Returns the value of attribute nv.
17 18 19 |
# File 'lib/rational_number.rb', line 17 def nv @nv end |
#sdv ⇒ Object (readonly)
Returns the value of attribute sdv.
17 18 19 |
# File 'lib/rational_number.rb', line 17 def sdv @sdv end |
#snv ⇒ Object (readonly)
Returns the value of attribute snv.
17 18 19 |
# File 'lib/rational_number.rb', line 17 def snv @snv end |
Instance Method Details
#<=>(other) ⇒ Object
Compare to other (Comparable)
22 23 24 25 26 27 28 29 30 31 |
# File 'lib/rational_number.rb', line 22 def <=>(other) return 0 if (@nv === other.nv) and (@dv === other.dv) and (@snv == other.snv) and (@sdv == other.sdv) if @number < other.number -1 elsif @number > other.number 1 else 0 end end |
#child_from_position(_position) ⇒ RationalNumber
Return the child rational number from given position
206 207 208 |
# File 'lib/rational_number.rb', line 206 def child_from_position(_position) value_from_parent_and_position(self, _position) end |
#is_child_of?(_parent) ⇒ Boolean
Check if the child is a immediate child of an parent
217 218 219 220 |
# File 'lib/rational_number.rb', line 217 def is_child_of?(_parent) return false if (self == _parent) or self.root? _parent == self.parent end |
#is_descendant_of?(_parent) ⇒ Boolean
Check if the child is a descendant of an parent (at any level)
241 242 243 244 245 246 247 248 249 |
# File 'lib/rational_number.rb', line 241 def is_descendant_of?(_parent) return false if (self == _parent) or self.root? verify_parent = self # start with beeing self while !verify_parent.root? do verify_parent = verify_parent.parent return true if _parent == verify_parent end false end |
#is_parent_of?(_child) ⇒ Boolean
Check if the parent is a immediate parent of a child
229 230 231 232 |
# File 'lib/rational_number.rb', line 229 def is_parent_of?(_child) return false if self == _child _child.is_child_of?(self) end |
#next_sibling ⇒ RationalNumber
Return the next sibling rational number
Uses this RationalNumber parent values
158 159 160 161 162 163 164 165 |
# File 'lib/rational_number.rb', line 158 def next_sibling # Raise error in case we are root raise RationalNumberIsRootNoSiblingsError if root? _parent = self.parent # Get parent already to avoid duplicate calculations _position = ((@nv - _parent.nv) / _parent.snv) + 1 value_from_parent_and_position(_parent, _position) end |
#parent ⇒ RationalNumber
Returns parent as a rational number
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/rational_number.rb', line 121 def parent raise NoParentRationalNumberIsRootError if root? numerator = @nv denominator = @dv _parent = RationalNumber.new compare_key = RationalNumber.new # make sure we break if we get root values! (numerator == 0 + denominator == 0) while ((compare_key.nv < @nv) && (compare_key.dv < @dv)) && ((numerator > 0) && (denominator > 0)) div = numerator / denominator mod = numerator % denominator # set return values to previous values, as they are the parent values _parent.set_from_other(compare_key) # temporary calculations (needed) parent_nv = _parent.nv + (div * _parent.snv) parent_dv = _parent.dv + (div * _parent.sdv) compare_key.set_values( parent_nv , #nv parent_dv , #dv parent_nv + _parent.snv, #snv parent_dv + _parent.sdv) #sdv numerator = mod if (numerator != 0) denominator = denominator % mod denominator = 1 if denominator == 0 end end _parent end |
#position ⇒ Integer
Get the calculated postion at the current “level” for this rational number in a “tree”
111 112 113 114 |
# File 'lib/rational_number.rb', line 111 def position _parent = self.parent ((@nv - _parent.nv) / _parent.snv) end |
#root? ⇒ Boolean
See if rational number is root
102 103 104 |
# File 'lib/rational_number.rb', line 102 def root? (@nv === 0) and (@dv === 1) and (@snv === 1) and (@sdv === 0) end |
#set_from_other(other) ⇒ undefined
Will set the values from another RationalNumber
95 96 97 |
# File 'lib/rational_number.rb', line 95 def set_from_other(other) set_values(other.nv, other.dv, other.snv, other.sdv) end |
#set_values(nv, dv, snv, sdv) ⇒ Object
Set the values of nv,dv,snv and sdv directly
80 81 82 83 84 85 86 |
# File 'lib/rational_number.rb', line 80 def set_values(nv, dv, snv, sdv) @nv = nv @dv = dv @snv = snv @sdv = sdv @number = Float(nv)/Float(dv) end |
#sibling_from_position(_position) ⇒ RationalNumber
Return the sibling rational number from a given position.
Uses this RationalNumber parent values
176 177 178 179 180 |
# File 'lib/rational_number.rb', line 176 def sibling_from_position(_position) raise RationalNumberIsRootNoSiblingsError if root? _parent = self.parent value_from_parent_and_position(_parent, _position) end |
#to_hash ⇒ Hash
Convert to Hash
47 48 49 50 51 52 53 54 55 |
# File 'lib/rational_number.rb', line 47 def to_hash { :nv => @nv, :dv => @dv, :snv => @snv, :sdv => @sdv, :number => @number } end |
#to_s ⇒ String
Convert to string
38 39 40 |
# File 'lib/rational_number.rb', line 38 def to_s "RationalNumber: number: #{@number} nv: #{@nv} dv: #{@dv} snv: #{@snv} sdv: #{@sdv}" end |
#value_from_parent_and_position(_parent, _position) ⇒ RationalNumber
Return the rational number from parent and position
190 191 192 193 194 195 196 197 |
# File 'lib/rational_number.rb', line 190 def value_from_parent_and_position(_parent, _position) sibling = RationalNumber.new( _parent.nv + (_position * _parent.snv), # nv _parent.dv + (_position * _parent.sdv), # dv _parent.nv + ((_position + 1) * _parent.snv), # snv _parent.dv + ((_position + 1) * _parent.sdv) # sdv ) end |