Class: FractionTree::Node
- Inherits:
-
Object
- Object
- FractionTree::Node
- Extended by:
- Forwardable
- Includes:
- Comparable
- Defined in:
- lib/fraction_tree/node.rb
Constant Summary collapse
- IDENTITY_MATRIX =
Matrix.identity(2)
- LEFT_MATRIX =
Matrix[[1,1]
- RIGHT_MATRIX =
Instance Attribute Summary collapse
-
#denominator ⇒ Object
readonly
Returns the value of attribute denominator.
-
#number ⇒ Object
(also: #to_r)
readonly
Returns the value of attribute number.
-
#numerator ⇒ Object
readonly
Returns the value of attribute numerator.
Class Method Summary collapse
-
.decimal_power(logarithmand) ⇒ Integer
The decimal power of the provided number.
-
.decode(string) ⇒ FractionTree::Node
The fraction decoded from the given string.
-
.encode(number, limit: Float::INFINITY) ⇒ String
The Stern-Brocot encoding of number.
-
.plus_minus(num, diff) ⇒ Array
Pair of numbers less and greater than the provided number by provided difference.
Instance Method Summary collapse
-
#+(rhs) ⇒ FractionTree::Node
Sum of self and another node.
-
#-(rhs) ⇒ FractionTree::Node
Difference of self and another node.
- #<=>(rhs) ⇒ Object
- #==(rhs) ⇒ Object
-
#child_with(num) ⇒ FractionTree::Node
Child of self and given number.
-
#common_ancestors_with(num) ⇒ Array
The ancestors shared by self and the given number.
-
#descendancy_from(depth: 5) ⇒ Array
Of fraction tree nodes, descending from parents of number.
-
#encoding(limit: Float::INFINITY) ⇒ String
Encoding of self.
-
#eql?(rhs) ⇒ Boolean
Needed for intersection operations to work.
- #hash ⇒ Object
-
#initialize(num) ⇒ Node
constructor
A new instance of Node.
- #inspect ⇒ Object (also: #to_s)
-
#nearest_common_ancestor_with(num) ⇒ FractionTree::Node
(also: #nca_with)
The nearest common ancestor of self and the given number.
-
#neighbors(r = 10**(self.class.decimal_power(number.numerator)+2)) ⇒ Array
Of [FractionTree::Node], sequence of Farey neighbors to self.
-
#parents ⇒ Array
A pair of fraction tree nodes leading to the given number.
-
#path(limit: Float::INFINITY) ⇒ Array
Set of fraction tree nodes leading to the given number.
Constructor Details
#initialize(num) ⇒ Node
Returns a new instance of Node.
16 17 18 19 |
# File 'lib/fraction_tree/node.rb', line 16 def initialize(num) (@numerator, @denominator) = fraction_pair(num) @number = num end |
Instance Attribute Details
#denominator ⇒ Object (readonly)
Returns the value of attribute denominator.
10 11 12 |
# File 'lib/fraction_tree/node.rb', line 10 def denominator @denominator end |
#number ⇒ Object (readonly) Also known as: to_r
Returns the value of attribute number.
10 11 12 |
# File 'lib/fraction_tree/node.rb', line 10 def number @number end |
#numerator ⇒ Object (readonly)
Returns the value of attribute numerator.
10 11 12 |
# File 'lib/fraction_tree/node.rb', line 10 def numerator @numerator end |
Class Method Details
.decimal_power(logarithmand) ⇒ Integer
Returns the decimal power of the provided number.
85 86 87 |
# File 'lib/fraction_tree/node.rb', line 85 def decimal_power(logarithmand) Math.log10(logarithmand.abs).floor end |
.decode(string) ⇒ FractionTree::Node
Returns the fraction decoded from the given string.
28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/fraction_tree/node.rb', line 28 def decode(string) result = IDENTITY_MATRIX string.split("").each do |direction| case direction when "L", "0", "l" result = result * LEFT_MATRIX when "R", "1", "r" result = result * RIGHT_MATRIX end end FractionTree.node(Rational(result.row(1).sum, result.row(0).sum)) end |
.encode(number, limit: Float::INFINITY) ⇒ String
Returns the Stern-Brocot encoding of number.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/fraction_tree/node.rb', line 47 def encode(number, limit: Float::INFINITY) return nil if (number.infinite? || number.zero?) m = number.numerator n = number.denominator return "I" if m == n "".tap do |string| while m != n && string.length < limit if m < n string << "L" n = n - m else string << "R" m = m - n end end end end |
.plus_minus(num, diff) ⇒ Array
Returns pair of numbers less and greater than the provided number by provided difference.
75 76 77 |
# File 'lib/fraction_tree/node.rb', line 75 def plus_minus(num, diff) [num - diff, num + diff] end |
Instance Method Details
#+(rhs) ⇒ FractionTree::Node
Returns sum of self and another node.
210 211 212 |
# File 'lib/fraction_tree/node.rb', line 210 def +(rhs) tree.node(Rational(self.numerator+rhs.numerator, self.denominator+rhs.denominator)) end |
#-(rhs) ⇒ FractionTree::Node
Returns difference of self and another node.
219 220 221 |
# File 'lib/fraction_tree/node.rb', line 219 def -(rhs) tree.node(Rational((self.numerator-rhs.numerator).abs, (self.denominator-rhs.denominator).abs)) end |
#<=>(rhs) ⇒ Object
228 229 230 |
# File 'lib/fraction_tree/node.rb', line 228 def <=>(rhs) self.number <=> rhs.number end |
#==(rhs) ⇒ Object
232 233 234 |
# File 'lib/fraction_tree/node.rb', line 232 def ==(rhs) self.number == rhs.number end |
#child_with(num) ⇒ FractionTree::Node
return nil if bc - ad |= 1, for a/b, c/d
Returns child of self and given number.
192 193 194 |
# File 'lib/fraction_tree/node.rb', line 192 def child_with(num) tree.child_of(number, num) end |
#common_ancestors_with(num) ⇒ Array
Returns the ancestors shared by self and the given number.
158 159 160 |
# File 'lib/fraction_tree/node.rb', line 158 def common_ancestors_with(num) path & tree.node(num).path end |
#descendancy_from(depth: 5) ⇒ Array
Returns of fraction tree nodes, descending from parents of number.
181 182 183 184 |
# File 'lib/fraction_tree/node.rb', line 181 def descendancy_from(depth: 5) (parent1, parent2) = parents tree.descendants_of(parent1.number, parent2.number, depth:) end |
#encoding(limit: Float::INFINITY) ⇒ String
Returns encoding of self.
201 202 203 |
# File 'lib/fraction_tree/node.rb', line 201 def encoding(limit: Float::INFINITY) self.class.encode(number, limit:) end |
#eql?(rhs) ⇒ Boolean
Needed for intersection operations to work. blog.mnishiguchi.com/ruby-intersection-of-object-arrays shortrecipes.blogspot.com/2006/10/ruby-intersection-of-two-arrays-of.html Also, allows using with Set, which uses Hash as storage and equality of its elements is determined according to Object#eql? and Object#hash.
241 242 243 |
# File 'lib/fraction_tree/node.rb', line 241 def eql?(rhs) rhs.instance_of?(self.class) && number == rhs.number end |
#hash ⇒ Object
245 246 247 248 249 |
# File 'lib/fraction_tree/node.rb', line 245 def hash p, q = 17, 37 p = q * @id.hash p = q * @name.hash end |
#inspect ⇒ Object Also known as: to_s
223 224 225 |
# File 'lib/fraction_tree/node.rb', line 223 def inspect "(#{numerator}/#{denominator})" end |
#nearest_common_ancestor_with(num) ⇒ FractionTree::Node Also known as: nca_with
Returns the nearest common ancestor of self and the given number.
169 170 171 |
# File 'lib/fraction_tree/node.rb', line 169 def nearest_common_ancestor_with(num) common_ancestors_with(num).last end |
#neighbors(r = 10**(self.class.decimal_power(number.numerator)+2)) ⇒ Array
Returns of [FractionTree::Node], sequence of Farey neighbors to self. A Farey neighbor is a number c/d, who’s relationship to a/b is such that ad − bc = 1, when c/d < a/b and bc − ad = 1 when c/d > a/b.
138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/fraction_tree/node.rb', line 138 def neighbors(r = 10**(self.class.decimal_power(number.numerator)+2)) ratio = number.to_r denominator = ratio.denominator [].tap do |collection| (1..r-1).each do |i| lower, upper = self.class.plus_minus(ratio, Rational(1,i*denominator)) collection << tree.node(lower) if tree.neighbors?(ratio, lower) collection << tree.node(upper) if tree.neighbors?(ratio, upper) end end end |
#parents ⇒ Array
Returns a pair of fraction tree nodes leading to the given number.
127 128 129 130 |
# File 'lib/fraction_tree/node.rb', line 127 def parents tmp = path [tmp[-2], tmp[-2..-1].inject(&:-)].sort end |
#path(limit: Float::INFINITY) ⇒ Array
Returns set of fraction tree nodes leading to the given number.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/fraction_tree/node.rb', line 96 def path(limit: Float::INFINITY) return nil if infinite? || zero? ln = tree.node(FractionTree.left_node) rn = tree.node(FractionTree.right_node) mn = ln + rn return [ln, rn, mn] if mn == tree.node(number) result = IDENTITY_MATRIX m = numerator n = denominator [].tap do |p| p << ln << rn << mn while m != n && p.length < limit if m < n result = result * LEFT_MATRIX n = n - m else result = result * RIGHT_MATRIX m = m - n end p << tree.node(Rational(result.row(1).sum,result.row(0).sum)) end end end |