silicium 0.0.2 → 0.0.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +3 -3
  3. data/.gitignore +13 -13
  4. data/.rakeTasks +8 -0
  5. data/.travis.yml +28 -25
  6. data/CODE_OF_CONDUCT.md +74 -74
  7. data/Gemfile +8 -8
  8. data/LICENSE.txt +21 -21
  9. data/Makefile +269 -269
  10. data/README.md +588 -46
  11. data/Rakefile +16 -16
  12. data/bin/console +14 -14
  13. data/bin/setup +8 -8
  14. data/docs/Object.html +117 -117
  15. data/docs/README_md.html +142 -142
  16. data/docs/Silicium/Combinatorics.html +270 -270
  17. data/docs/Silicium/Dice/Polyhedron.html +315 -315
  18. data/docs/Silicium/Dice/PolyhedronSet.html +321 -321
  19. data/docs/Silicium/Dice.html +99 -99
  20. data/docs/Silicium/Error.html +106 -106
  21. data/docs/Silicium/Geometry/Line2dCanon.html +243 -243
  22. data/docs/Silicium/Geometry/VariablesOrderException.html +106 -106
  23. data/docs/Silicium/Geometry.html +940 -940
  24. data/docs/Silicium/GraphVisualizer.html +226 -0
  25. data/docs/Silicium/Graphs/GraphError.html +106 -106
  26. data/docs/Silicium/Graphs/OrientedGraph.html +901 -775
  27. data/docs/Silicium/Graphs/UnorientedGraph.html +237 -284
  28. data/docs/Silicium/Graphs.html +374 -164
  29. data/docs/Silicium/IntegralDoesntExistError.html +106 -106
  30. data/docs/Silicium/NumericalIntegration.html +521 -521
  31. data/docs/Silicium/Optimization.html +629 -639
  32. data/docs/Silicium/Plotter/Image.html +297 -297
  33. data/docs/Silicium/Plotter.html +186 -186
  34. data/docs/Silicium.html +101 -101
  35. data/docs/created.rid +9 -9
  36. data/docs/css/fonts.css +167 -167
  37. data/docs/css/rdoc.css +619 -619
  38. data/docs/index.html +134 -132
  39. data/docs/js/darkfish.js +84 -84
  40. data/docs/js/navigation.js +105 -105
  41. data/docs/js/search.js +110 -110
  42. data/docs/js/search_index.js +1 -1
  43. data/docs/js/search_index.js.gz +0 -0
  44. data/docs/js/searcher.js +229 -229
  45. data/docs/table_of_contents.html +697 -608
  46. data/lib/algebra.rb +452 -0
  47. data/lib/algebra_diff.rb +258 -0
  48. data/lib/geometry/figure.rb +62 -0
  49. data/lib/geometry.rb +290 -236
  50. data/lib/geometry3d.rb +270 -0
  51. data/lib/graph/dfs.rb +42 -0
  52. data/lib/graph/kruskal.rb +36 -0
  53. data/lib/graph/scc.rb +97 -0
  54. data/lib/graph.rb +350 -164
  55. data/lib/graph_visualizer.rb +287 -0
  56. data/lib/ml_algorithms.rb +181 -0
  57. data/lib/numerical_integration.rb +184 -147
  58. data/lib/optimization.rb +209 -144
  59. data/lib/plotter.rb +256 -96
  60. data/lib/polynomial_division.rb +132 -0
  61. data/lib/polynomial_interpolation.rb +94 -0
  62. data/lib/regression.rb +120 -0
  63. data/lib/silicium/adding.rb +37 -0
  64. data/lib/silicium/conversions.rb +23 -0
  65. data/lib/silicium/multi.rb +82 -0
  66. data/lib/silicium/sparse.rb +76 -0
  67. data/lib/silicium/sugar.rb +37 -0
  68. data/lib/silicium/trans.rb +26 -0
  69. data/lib/silicium/version.rb +3 -3
  70. data/lib/silicium.rb +5 -5
  71. data/lib/theory_of_probability.rb +240 -226
  72. data/lib/topological_sort.rb +50 -0
  73. data/oriented_graph.png +0 -0
  74. data/plot.png +0 -0
  75. data/silicium.gemspec +38 -39
  76. metadata +38 -16
@@ -0,0 +1,62 @@
1
+ module Silicium
2
+
3
+ module Geometry
4
+ class Figure
5
+ include Geometry
6
+ end
7
+
8
+ class Triangle < Figure
9
+
10
+ def initialize(p1, p2, p3)
11
+ s_p1p2 = distance_point_to_point2d(p1, p2)
12
+ s_p1p3 = distance_point_to_point2d(p1, p3)
13
+ s_p2p3 = distance_point_to_point2d(p2, p3)
14
+ if s_p1p2 + s_p2p3 <= s_p1p3 || s_p1p2 + s_p1p3 <= s_p2p3 || s_p2p3 + s_p1p3 <= s_p1p2
15
+ raise ArgumentError, 'Triangle does not exist'
16
+ else
17
+ @side_p1p2 = s_p1p2
18
+ @side_p1p3 = s_p1p3
19
+ @side_p2p3 = s_p2p3
20
+ end
21
+ end
22
+
23
+ def perimeter
24
+ @side_p1p2 + @side_p1p3 + @side_p2p3
25
+ end
26
+
27
+ def area
28
+ half_perimeter = perimeter / 2.0
29
+ Math.sqrt(half_perimeter * (half_perimeter - @side_p1p2) * (half_perimeter - @side_p2p3) * (half_perimeter - @side_p1p3))
30
+ end
31
+ end
32
+
33
+
34
+ ##
35
+ # TODO: Add a description
36
+ class Rectangle < Figure
37
+
38
+ def initialize(p1, p2, p3, p4)
39
+ raise ArgumentError, 'This is not a rectangle.' unless valid?(p1, p2, p3, p4)
40
+
41
+ @side1 = distance_point_to_point2d(p1, p2)
42
+ @side2 = distance_point_to_point2d(p2, p3)
43
+ @side3 = distance_point_to_point2d(p3, p4)
44
+ @side4 = distance_point_to_point2d(p4, p1)
45
+ end
46
+
47
+ ##
48
+ # Checks if input points form rectangle
49
+ def valid?(p1, p2, p3, p4)
50
+ distance_point_to_point2d(p1, p3) == distance_point_to_point2d(p2, p4)
51
+ end
52
+
53
+ def perimeter
54
+ @side1 + @side2 + @side3 + @side4
55
+ end
56
+
57
+ def area
58
+ @side1 * @side2
59
+ end
60
+ end
61
+ end
62
+ end
data/lib/geometry.rb CHANGED
@@ -1,236 +1,290 @@
1
- # frozen_string_literal: true
2
-
3
- module Silicium
4
-
5
- module Geometry
6
-
7
- ##
8
- # Represents a point as two coordinates
9
- # in two-dimensional space
10
- Point = Struct.new(:x, :y)
11
-
12
- ##
13
- # Represents a point as three coordinates
14
- # in three-dimensional space
15
- Point3d = Struct.new(:x, :y, :z)
16
-
17
- ##
18
- #Calculates the distance from given points in two-dimensional space
19
- def distance_point_to_point2d(a, b)
20
- Math.sqrt((b.x - a.x)**2 + (b.y - a.y)**2)
21
- end
22
-
23
- # Class represents a line as equation y = k*x +b
24
- # k - slope
25
- # b - free_term
26
- # in two-dimensional space
27
- class Line2dCanon
28
- attr_reader :slope
29
- attr_reader :free_term
30
-
31
- def initialize(p1, p2)
32
- if (p1.x == p2.x) && (p1.y == p2.y)
33
- raise ArgumentError, "You need 2 diffrent points"
34
- end
35
- if (p1.x == p2.x)
36
- raise ArgumentError, "The straight line equation cannot be written in canonical form"
37
- end
38
- @slope = (p2.y - p1.y) / (p2.x - p1.x).to_f
39
- @free_term = (p2.x * p1.y - p2.y * p1.x) / (p2.x - p1.x).to_f
40
- end
41
-
42
- ##
43
- # Checks the point lies on the line or not
44
- def point_is_on_line?(p1)
45
- p1.y == @slope * p1.x + @free_term
46
- end
47
- end
48
-
49
-
50
- ##
51
- # Calculates the distance from given points in three-dimensional space
52
- def distance_point_to_point3d(a, b)
53
- Math.sqrt((b.x - a.x)**2 + (b.y - a.y)**2 + (b.z - a.z)**2)
54
- end
55
-
56
- ##
57
- # The distance from a point to a line on a plane
58
- # The line is defined by two points
59
- # https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
60
- def distance_point_line2d(p1, p2, a)
61
- line_segment_length = distance_point_to_point2d(p1, p2)
62
- ((p2.y - p1.y) * a.x - (p2.x - p1.x) * a.y + p2.x * p1.y - p2.y * p1.x).abs / (line_segment_length * 1.0)
63
- end
64
-
65
- ##
66
- # The distance from a point to a line on a plane
67
- # Line defined by an equation
68
- # return 0 if the equation does not define a line.
69
- def distance_point_line_equation2d(a, b, c, p)
70
- if a == 0 and b == 0
71
- return 0
72
- end
73
- (a * p.x + b * p.y + c).abs / Math.sqrt(a**2 + b**2)
74
- end
75
-
76
- def oriented_area(a, b, c)
77
- a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)
78
- end
79
-
80
- ##
81
- # Determines if a clockwise crawl is performed
82
- # for defined order of points
83
- def clockwise(a, b, c)
84
- oriented_area(a, b, c).negative?
85
- end
86
-
87
- ##
88
- # Determines if a counter-clockwise crawl is
89
- # performed for defined order of points
90
- def counter_clockwise(a, b, c)
91
- oriented_area(a, b, c).positive?
92
- end
93
-
94
- def not_polygon?(points)
95
- points.empty? || points.size == 1 || points.size == 2
96
- end
97
-
98
- def put_point_in_part(part, point, direction)
99
- direction = method(direction)
100
- while part.size >= 2 && !direction.call(part[part.size - 2], part[part.size - 1], point)
101
- part.pop
102
- end
103
- part.push(point)
104
- end
105
-
106
- ##
107
- # Returns an array containing points that are included
108
- # in the minimal convex hull for a given array of points
109
- # https://e-maxx.ru/algo/convex_hull_graham
110
- def minimal_convex_hull_2d(points)
111
- return points if not_polygon?(points)
112
-
113
- points.sort_by! { |p| [p.x, p.y] }
114
- first = points[0]
115
- last = points.last
116
- up = [first]
117
- down = [first]
118
-
119
- (1...points.size).each do |i|
120
- point = points[i]
121
- is_last = i == points.size - 1
122
- if is_last || clockwise(first, point, last)
123
- put_point_in_part(up, point, :clockwise)
124
- end
125
- if is_last || counter_clockwise(first, point, last)
126
- put_point_in_part(down, point, :counter_clockwise)
127
- end
128
- end
129
-
130
- hull = up
131
- (1..(down.size - 2)).reverse_each do |j|
132
- hull.push(down[j])
133
- end
134
- hull
135
- end
136
-
137
- def process_cf(line_equation, variable)
138
- if line_equation.include?(variable)
139
- before = line_equation.index('/') + 1
140
- after = line_equation.index('=')
141
- line_equation.slice(before..after).gsub('=', '').sub('*', '').gsub('(', '').gsub(')', '').to_f
142
- else
143
- 0.0
144
- end
145
- end
146
-
147
- def cut_by_eq(line_equation)
148
- line_equation.slice(line_equation.index('='), line_equation.length).sub('=', '')
149
- end
150
-
151
- def process_line_by_coordinates(line_equation, func)
152
- copy_line = insert_eq(line_equation)
153
- func = method(func)
154
- res = []
155
- res[0] = func.call(copy_line, 'x')
156
- copy_line = cut_by_eq(copy_line)
157
- res[1] = func.call(copy_line, 'y')
158
- copy_line = cut_by_eq(copy_line)
159
- res[2] = func.call(copy_line, 'z')
160
- res
161
- end
162
-
163
- ##
164
- # Creates an array- directing vector in three-dimensional space .
165
- # The equation is specified in the canonical form.
166
- # Example, (x-0) / 26 = (y + 300) / * (- 15) = (z-200) / 51
167
- #
168
- # Important: mandatory order of variables: x, y, z
169
- def directing_vector3d(line_equation)
170
- process_line_by_coordinates(line_equation, :process_cf)
171
- end
172
-
173
- class VariablesOrderException < Exception
174
- end
175
-
176
- def needed_variables_order?(before, after)
177
- before < after
178
- end
179
-
180
- def process_free_member(line_equation, variable)
181
- if line_equation.include?(variable)
182
- before = line_equation.index(variable) + 1
183
- after = line_equation.index('/')
184
-
185
- unless needed_variables_order?(before, after)
186
- throw VariablesOrderException
187
- end
188
-
189
- line_equation.slice(before..after).gsub('/', '').to_f * (-1)
190
- else
191
- 0.0
192
- end
193
- end
194
-
195
- ##
196
- # Creates an array of coordinates of the point ([x, y, z] on the line
197
- # given by the equation in the canonical form.
198
- # Example, (x-0) / 26 = (y + 300) / * (- 15) = (z-200) / 51
199
- #
200
- # Important: mandatory order of variables: x, y, z
201
- def height_point_3d(line_equation)
202
- process_line_by_coordinates(line_equation, :process_free_member)
203
- end
204
-
205
- def vectors_product(v1, v2)
206
- res = Array.new(3)
207
- (0..2).each do |i|
208
- res[i] = v1[(i + 1) % 3] * v2[(i + 2) % 3] - v1[(i + 2) % 3] * v2[(i + 1) % 3]
209
- end
210
- res
211
- end
212
-
213
- def vector_length(vector)
214
- Math.sqrt(vector[0]**2 + vector[1]**2 + vector[2]**2)
215
- end
216
-
217
- ##
218
- # Calculates the distance from a point given by a Point3d structure
219
- # to a straight line given by a canonical equation.
220
- # Example, (x-0) / 26 = (y + 300) / * (- 15) = (z-200) / 51
221
- #
222
- # Important: mandatory order of variables: x, y, z
223
- def point_to_line_distance_3d(point, line_eq)
224
- dir_vector = directing_vector3d(line_eq)
225
- line_point = height_point_3d(line_eq)
226
- height_vector = [line_point[0] - point.x, line_point[1] - point.y, line_point[2] - point.z]
227
-
228
- height_on_dir = vectors_product(height_vector, dir_vector)
229
- vector_length(height_on_dir) / vector_length(dir_vector)
230
- end
231
-
232
- def insert_eq(line_equation)
233
- line_equation.gsub(' ', '').insert(line_equation.length, '=')
234
- end
235
- end
236
- end
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'geometry/figure'
4
+
5
+ module Silicium
6
+
7
+ module Geometry
8
+ ##
9
+ # Represents a point as two coordinates
10
+ # in two-dimensional space
11
+ Point = Struct.new(:x, :y)
12
+
13
+ ##
14
+ # Calculates the distance from given points in two-dimensional space
15
+ def distance_point_to_point2d(a, b)
16
+ Math.sqrt((b.x - a.x)**2 + (b.y - a.y)**2)
17
+ end
18
+
19
+ ##
20
+ # Class represents a line as equation Ax + By + C = 0
21
+ # in two-dimensional space
22
+ class Line2dCanon
23
+ attr_reader :x_coefficient
24
+ attr_reader :y_coefficient
25
+ attr_reader :free_coefficient
26
+
27
+ ##
28
+ # Initializes with two objects of type Point
29
+ def initialize(point1, point2)
30
+ raise ArgumentError, 'You need 2 different points' if point1.x.equal?(point2.x) && point1.y.equal?(point2.y)
31
+ if point1.x.equal?(point2.x)
32
+ @x_coefficient = 1
33
+ @y_coefficient = 0
34
+ @free_coefficient = - point1.x
35
+ else
36
+ slope_point = (point2.y - point1.y) / (point2.x - point1.x)
37
+ @x_coefficient = -slope_point
38
+ @y_coefficient = 1
39
+ @free_coefficient = - point1.y + slope_point * point1.x
40
+ end
41
+ end
42
+
43
+ # Initializes with coefficients
44
+ def initialize_with_coefficients(a, b, c)
45
+ raise ArgumentError, 'All coefficients cannot be 0 ' if a.equal?(0) && b.equal?(0) && (c.equal?(0) || !c.equal?(0))
46
+
47
+ @x_coefficient = a
48
+ @y_coefficient = b
49
+ @free_coefficient = c
50
+ end
51
+
52
+ ##
53
+ # Checks the point lies on the line or not
54
+ def point_is_on_line?(point)
55
+ ((@x_coefficient * point.x + @y_coefficient * point.y + @free_coefficient) - 0.0).abs < 0.0001
56
+ end
57
+
58
+ # Checks if two lines are parallel
59
+ def parallel?(other_line)
60
+ @x_coefficient.equal?(other_line.x_coefficient) && @y_coefficient.equal?(other_line.y_coefficient)
61
+ end
62
+
63
+ ##
64
+ # Checks if two lines are intersecting
65
+ def intersecting?(other_line)
66
+ @x_coefficient != other_line.x_coefficient || @y_coefficient != other_line.y_coefficient
67
+ end
68
+
69
+ ##
70
+ # Checks if two lines are perpendicular
71
+ def perpendicular?(other_line)
72
+ (@x_coefficient * other_line.x_coefficient).equal?(- @y_coefficient * other_line.y_coefficient)
73
+ end
74
+
75
+ ##
76
+ # Checking if the point is on a segment
77
+ def check_point_on_segment(point)
78
+ (@x_coefficient * point.x + @y_coefficient * point.y + @free_coefficient) - 0.0 <= 0.0001
79
+ end
80
+
81
+ ##
82
+ # Returns a point of intersection of two lines
83
+ # If not intersecting returns nil
84
+ def intersection_point(other_line)
85
+ return nil unless intersecting?(other_line)
86
+
87
+ divisor = @x_coefficient * other_line.y_coefficient - other_line.x_coefficient * @y_coefficient
88
+ x = (@y_coefficient * other_line.free_coefficient - other_line.y_coefficient * @free_coefficient) / divisor
89
+ y = (@free_coefficient * other_line.x_coefficient - other_line.free_coefficient * @x_coefficient) / divisor
90
+ Point.new(x, y)
91
+ end
92
+
93
+ ##
94
+ # Returns distance between lines
95
+ def distance_to_line(other_line)
96
+ return 0 if intersecting?(other_line)
97
+
98
+ (@free_coefficient - other_line.free_coefficient).abs / Math.sqrt(@x_coefficient**2 + @y_coefficient**2)
99
+ end
100
+
101
+ ##
102
+ # The distance from a point to a line on a plane
103
+ # return 0 if the equation does not define a line.
104
+ def distance_point_to_line(point)
105
+ return 0 if @x_coefficient.eql?(0) && @y_coefficient.eql?(0)
106
+
107
+ res = (@x_coefficient * point.x + @y_coefficient * point.y + @free_coefficient).abs
108
+ res / Math.sqrt(@x_coefficient**2 + @y_coefficient**2).to_f
109
+ end
110
+ ##
111
+ # Check if array of points is on the same line
112
+ def array_of_points_is_on_line(array)
113
+ raise ArgumentError, 'Array is empty!' if array.length == 0
114
+ res = Array.new
115
+ for i in 0..array.size-1 do
116
+ res.push(point_is_on_line?(array[i]))
117
+ end
118
+ res
119
+ end
120
+
121
+ ##
122
+ # The distance between parallel lines
123
+ def distance_between_parallel_lines(other_line)
124
+ raise ArgumentError, 'Lines are not parallel' if !parallel?(other_line)
125
+
126
+ (other_line.free_coefficient - @free_coefficient).abs / Math.sqrt(@x_coefficient**2 + @y_coefficient**2)
127
+ end
128
+ end
129
+
130
+ ##
131
+ # Function for checking sign of number
132
+ def sign(integer)
133
+ integer >= 0 ? 1 : -1
134
+ end
135
+ # The distance from a point to a line on a plane
136
+ # The line is defined by two points
137
+ # https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
138
+ def distance_point_line2d(p1, p2, a)
139
+ line_segment_length = distance_point_to_point2d(p1, p2)
140
+ ((p2.y - p1.y) * a.x - (p2.x - p1.x) * a.y + p2.x * p1.y - p2.y * p1.x).abs / (line_segment_length * 1.0)
141
+ end
142
+
143
+ ##
144
+ # The distance from a point to a line on a plane
145
+ # Normalized equation of the line
146
+ def distance_point_line_normalized2d(a, b, c, p)
147
+ (p.x * a + p.y * b - c).abs
148
+ end
149
+
150
+ def oriented_area(a, b, c)
151
+ a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)
152
+ end
153
+
154
+ ##
155
+ # Determines if a clockwise crawl is performed
156
+ # for defined order of points
157
+ def clockwise(a, b, c)
158
+ oriented_area(a, b, c).negative?
159
+ end
160
+
161
+ ##
162
+ # Determines if a counter-clockwise crawl is
163
+ # performed for defined order of points
164
+ def counter_clockwise(a, b, c)
165
+ oriented_area(a, b, c).positive?
166
+ end
167
+
168
+ def not_polygon?(points)
169
+ points.empty? || points.size == 1 || points.size == 2
170
+ end
171
+
172
+ def put_point_in_part(part, point, direction)
173
+ direction = method(direction)
174
+ part.pop while part.size >= 2 && !direction.call(part[part.size - 2], part[part.size - 1], point)
175
+ part.push(point)
176
+ end
177
+
178
+ ##
179
+ # Returns an array containing points that are included
180
+ # in the minimal convex hull for a given array of points
181
+ # https://e-maxx.ru/algo/convex_hull_graham
182
+ def minimal_convex_hull_2d(points)
183
+ return points if not_polygon?(points)
184
+
185
+ points.sort_by! { |p| [p.x, p.y] }
186
+ first = points[0]
187
+ last = points.last
188
+ up = [first]
189
+ down = [first]
190
+
191
+ (1...points.size).each do |i|
192
+ point = points[i]
193
+ is_last = i == points.size - 1
194
+ put_point_in_part(up, point, :clockwise) if is_last || clockwise(first, point, last)
195
+ put_point_in_part(down, point, :counter_clockwise) if is_last || counter_clockwise(first, point, last)
196
+ end
197
+ up + down[1...-1]
198
+ end
199
+
200
+ def process_cf(line_equation, variable)
201
+ if line_equation.include?(variable)
202
+ before = line_equation.index('/') + 1
203
+ after = line_equation.index('=')
204
+ line_equation.slice(before..after).gsub('=', '').sub('*', '').gsub('(', '').gsub(')', '').to_f
205
+ else
206
+ 0.0
207
+ end
208
+ end
209
+
210
+ def cut_by_eq(line_equation)
211
+ line_equation.slice(line_equation.index('='), line_equation.length).sub('=', '')
212
+ end
213
+
214
+ def process_line_by_coordinates(line_equation, func)
215
+ copy_line = insert_eq(line_equation)
216
+ func = method(func)
217
+ res = []
218
+ res[0] = func.call(copy_line, 'x')
219
+ copy_line = cut_by_eq(copy_line)
220
+ res[1] = func.call(copy_line, 'y')
221
+ copy_line = cut_by_eq(copy_line)
222
+ res[2] = func.call(copy_line, 'z')
223
+ res
224
+ end
225
+
226
+
227
+
228
+ class VariablesOrderException < RuntimeError
229
+ end
230
+
231
+ def needed_variables_order?(before, after)
232
+ before < after
233
+ end
234
+
235
+ def process_free_member(line_equation, variable)
236
+ if line_equation.include?(variable)
237
+ before = line_equation.index(variable) + 1
238
+ after = line_equation.index('/')
239
+
240
+ throw VariablesOrderException unless needed_variables_order?(before, after)
241
+
242
+ line_equation.slice(before..after).gsub('/', '').to_f * -1
243
+ else
244
+ 0.0
245
+ end
246
+ end
247
+
248
+
249
+
250
+ def vectors_product(v1, v2)
251
+ res = Array.new(3)
252
+ (0..2).each do |i|
253
+ res[i] = v1[(i + 1) % 3] * v2[(i + 2) % 3] - v1[(i + 2) % 3] * v2[(i + 1) % 3]
254
+ end
255
+ res
256
+ end
257
+
258
+ def vector_length(vector)
259
+ Math.sqrt(vector[0]**2 + vector[1]**2 + vector[2]**2)
260
+ end
261
+
262
+
263
+
264
+ # Closest pair of points_________________________
265
+ # find minimum distance between two points in set
266
+ def brute_min(points, current = Float::INFINITY)
267
+ return current if points.length < 2
268
+
269
+ head = points[0]
270
+ points.delete_at(0)
271
+ new_min = points.map { |x| distance_point_to_point2d(head, x)}.min
272
+ new_сurrent = [new_min, current].min
273
+ brute_min(points, new_сurrent)
274
+ end
275
+
276
+ def divide_min(points)
277
+ half = points.length / 2
278
+ points.sort_by! { |p| [p.x, p.y] }
279
+ minimum = [brute_min(points[0..half]), brute_min(points[half..points.length])].min
280
+ near_line = points.select { |x| x > half - minimum and x < half + minimum}
281
+ min([brute_min(near_line), minimum])
282
+ end
283
+
284
+ def insert_eq(line_equation)
285
+ line_equation.gsub(' ', '').insert(line_equation.length, '=')
286
+ end
287
+ end
288
+ end
289
+
290
+