silicium 0.0.2 → 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +3 -3
- data/.gitignore +13 -13
- data/.rakeTasks +8 -0
- data/.travis.yml +28 -25
- data/CODE_OF_CONDUCT.md +74 -74
- data/Gemfile +8 -8
- data/LICENSE.txt +21 -21
- data/Makefile +269 -269
- data/README.md +588 -46
- data/Rakefile +16 -16
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/docs/Object.html +117 -117
- data/docs/README_md.html +142 -142
- data/docs/Silicium/Combinatorics.html +270 -270
- data/docs/Silicium/Dice/Polyhedron.html +315 -315
- data/docs/Silicium/Dice/PolyhedronSet.html +321 -321
- data/docs/Silicium/Dice.html +99 -99
- data/docs/Silicium/Error.html +106 -106
- data/docs/Silicium/Geometry/Line2dCanon.html +243 -243
- data/docs/Silicium/Geometry/VariablesOrderException.html +106 -106
- data/docs/Silicium/Geometry.html +940 -940
- data/docs/Silicium/GraphVisualizer.html +226 -0
- data/docs/Silicium/Graphs/GraphError.html +106 -106
- data/docs/Silicium/Graphs/OrientedGraph.html +901 -775
- data/docs/Silicium/Graphs/UnorientedGraph.html +237 -284
- data/docs/Silicium/Graphs.html +374 -164
- data/docs/Silicium/IntegralDoesntExistError.html +106 -106
- data/docs/Silicium/NumericalIntegration.html +521 -521
- data/docs/Silicium/Optimization.html +629 -639
- data/docs/Silicium/Plotter/Image.html +297 -297
- data/docs/Silicium/Plotter.html +186 -186
- data/docs/Silicium.html +101 -101
- data/docs/created.rid +9 -9
- data/docs/css/fonts.css +167 -167
- data/docs/css/rdoc.css +619 -619
- data/docs/index.html +134 -132
- data/docs/js/darkfish.js +84 -84
- data/docs/js/navigation.js +105 -105
- data/docs/js/search.js +110 -110
- data/docs/js/search_index.js +1 -1
- data/docs/js/search_index.js.gz +0 -0
- data/docs/js/searcher.js +229 -229
- data/docs/table_of_contents.html +697 -608
- data/lib/algebra.rb +452 -0
- data/lib/algebra_diff.rb +258 -0
- data/lib/geometry/figure.rb +62 -0
- data/lib/geometry.rb +290 -236
- data/lib/geometry3d.rb +270 -0
- data/lib/graph/dfs.rb +42 -0
- data/lib/graph/kruskal.rb +36 -0
- data/lib/graph/scc.rb +97 -0
- data/lib/graph.rb +350 -164
- data/lib/graph_visualizer.rb +287 -0
- data/lib/ml_algorithms.rb +181 -0
- data/lib/numerical_integration.rb +184 -147
- data/lib/optimization.rb +209 -144
- data/lib/plotter.rb +256 -96
- data/lib/polynomial_division.rb +132 -0
- data/lib/polynomial_interpolation.rb +94 -0
- data/lib/regression.rb +120 -0
- data/lib/silicium/adding.rb +37 -0
- data/lib/silicium/conversions.rb +23 -0
- data/lib/silicium/multi.rb +82 -0
- data/lib/silicium/sparse.rb +76 -0
- data/lib/silicium/sugar.rb +37 -0
- data/lib/silicium/trans.rb +26 -0
- data/lib/silicium/version.rb +3 -3
- data/lib/silicium.rb +5 -5
- data/lib/theory_of_probability.rb +240 -226
- data/lib/topological_sort.rb +50 -0
- data/oriented_graph.png +0 -0
- data/plot.png +0 -0
- data/silicium.gemspec +38 -39
- 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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# in
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
#
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
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
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
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
|
+
|