compsci 0.3.1.1 → 0.3.2.3
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 +4 -4
- data/README.md +3 -3
- data/VERSION +1 -1
- data/compsci.gemspec +5 -3
- data/lib/compsci/fit.rb +17 -0
- data/lib/compsci/names/pokemon.rb +2 -2
- data/lib/compsci/simplex/parse.rb +6 -2
- data/lib/compsci/simplex.rb +17 -16
- data/lib/compsci/timer.rb +61 -1
- data/test/fit.rb +54 -16
- metadata +28 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 265cce45b9c0791d768d79d890bdfd3b2f3dd0f9d3b5346798274095bd38efa1
|
4
|
+
data.tar.gz: c921f58718dc3df31cb89572a9b428cbf9add53e6ed8d7b3f433fb8eb4dde0a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f7bf484573f12573ed1f3705634aacd3f7c47508df8983e5bfe92908923d4bf9495dc3ae65deb69749fa326185ec08a8233dd2689f4b400db553a65d2272708
|
7
|
+
data.tar.gz: c5db4b1e31b10b031dec20a21806fae10853ad7cd9bc62817f374fbef10df4934d1a16c6ea1d9a7d0ebb3c46f9c470077984d983f94755a417a130330d101431
|
data/README.md
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
[](https://github.com/rickhull/compsci/actions/workflows/ci.yaml)
|
2
2
|
[](https://badge.fury.io/rb/compsci)
|
3
|
-
[](https://gemnasium.com/rickhull/compsci)
|
4
|
-
[](https://hakiri.io/github/rickhull/compsci/master)
|
5
3
|
|
6
4
|
# CompSci
|
7
5
|
|
@@ -213,6 +211,8 @@ alphabetical order.
|
|
213
211
|
|
214
212
|
## [`Simplex`](lib/compsci/simplex.rb) class
|
215
213
|
|
214
|
+
### WORK IN PROGRESS; DO NOT USE
|
215
|
+
|
216
216
|
The [Simplex algorithm](https://en.wikipedia.org/wiki/Simplex_algorithm)
|
217
217
|
is a technique for
|
218
218
|
[Linear programming](https://en.wikipedia.org/wiki/Linear_programming).
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.2.3
|
data/compsci.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.homepage = "https://github.com/rickhull/compsci"
|
7
7
|
s.license = "LGPL-3.0"
|
8
8
|
|
9
|
-
s.required_ruby_version = "~>
|
9
|
+
s.required_ruby_version = "~> 3.0"
|
10
10
|
|
11
11
|
s.version = File.read(File.join(__dir__, 'VERSION')).chomp
|
12
12
|
|
@@ -15,9 +15,11 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.files += Dir['test/**/*.rb']
|
16
16
|
s.files += Dir['examples/**/*.rb']
|
17
17
|
|
18
|
+
s.add_dependency "matrix", "~> 0.4"
|
19
|
+
|
18
20
|
s.add_development_dependency "buildar", "~> 3.0"
|
19
|
-
s.add_development_dependency "minitest", "
|
20
|
-
s.add_development_dependency "rake", "
|
21
|
+
s.add_development_dependency "minitest", "~> 5.0"
|
22
|
+
s.add_development_dependency "rake", "~> 12.3" # CVE-2020-8130
|
21
23
|
s.add_development_dependency "flog", "~> 0"
|
22
24
|
s.add_development_dependency "flay", "~> 0"
|
23
25
|
s.add_development_dependency "roodi", "~> 0"
|
data/lib/compsci/fit.rb
CHANGED
@@ -153,5 +153,22 @@ module CompSci
|
|
153
153
|
|
154
154
|
return Math.exp(a), b, self.error(xys) { |x| (Math.exp(a) * (x ** b)) }
|
155
155
|
end
|
156
|
+
|
157
|
+
def self.predict(model, a, b, x)
|
158
|
+
case model
|
159
|
+
when :constant
|
160
|
+
a
|
161
|
+
when :logarithmic
|
162
|
+
a + b * Math.log(x)
|
163
|
+
when :linear
|
164
|
+
a + b * x
|
165
|
+
when :exponential
|
166
|
+
a * Math::E ** (b * x)
|
167
|
+
when :power
|
168
|
+
a * x ** b
|
169
|
+
else
|
170
|
+
raise("unknown model: #{model}")
|
171
|
+
end
|
172
|
+
end
|
156
173
|
end
|
157
174
|
end
|
@@ -34,8 +34,8 @@ module CompSci::Names::Pokemon
|
|
34
34
|
# a hash of all the names, keyed by the first letter
|
35
35
|
def self.read_hash(path: DATAFILE)
|
36
36
|
hsh = Hash.new { |h, k| h[k] = [] }
|
37
|
-
File.open(path).each_line { |
|
38
|
-
hsh[
|
37
|
+
File.open(path).each_line { |line|
|
38
|
+
hsh[line.chr] << line.chomp
|
39
39
|
}
|
40
40
|
hsh
|
41
41
|
end
|
@@ -82,7 +82,11 @@ class CompSci::Simplex
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
-
def self.problem(
|
85
|
+
def self.problem(**kwargs)
|
86
|
+
self.new(*self.get_params(**kwargs))
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.get_params(maximize: nil, constraints: [], **kwargs)
|
86
90
|
if maximize
|
87
91
|
expr, maximize = maximize, true
|
88
92
|
elsif kwargs[:minimize]
|
@@ -116,7 +120,7 @@ class CompSci::Simplex
|
|
116
120
|
a.push cofs
|
117
121
|
b.push rhs
|
118
122
|
}
|
119
|
-
|
123
|
+
[c, a, b]
|
120
124
|
end
|
121
125
|
|
122
126
|
def self.maximize(expression, *ineqs)
|
data/lib/compsci/simplex.rb
CHANGED
@@ -26,35 +26,36 @@ class CompSci::Simplex
|
|
26
26
|
@max_pivots = DEFAULT_MAX_PIVOTS
|
27
27
|
|
28
28
|
# Problem dimensions; these never change
|
29
|
-
@
|
30
|
-
@
|
31
|
-
@
|
29
|
+
@num_free_vars = num_vars
|
30
|
+
@num_basic_vars = num_inequalities
|
31
|
+
@total_vars = @num_free_vars + @num_basic_vars
|
32
32
|
|
33
33
|
# Set up initial matrix A and vectors b, c
|
34
|
-
|
34
|
+
# store all input values as Rational (via #rationalize)
|
35
|
+
@c = c.map { |flt| -1 * flt.rationalize } + Array.new(@num_basic_vars, 0)
|
35
36
|
@a = a.map.with_index { |ary, i|
|
36
|
-
if ary.size != @
|
37
|
+
if ary.size != @num_free_vars
|
37
38
|
raise ArgumentError, "a is inconsistent"
|
38
39
|
end
|
39
|
-
#
|
40
|
-
ary
|
40
|
+
# add identity matrix
|
41
|
+
ary.map { |flt| flt.rationalize } +
|
42
|
+
Array.new(@num_basic_vars) { |ci| ci == i ? 1 : 0 }
|
41
43
|
}
|
42
|
-
@b = b
|
44
|
+
@b = b.map { |flt| flt.rationalize }
|
43
45
|
|
44
|
-
|
45
|
-
@basic_vars = (@num_non_slack_vars...@num_vars).to_a
|
46
|
+
@basic_vars = (@num_free_vars...@total_vars).to_a
|
46
47
|
self.update_solution
|
47
48
|
end
|
48
49
|
|
49
50
|
# does not modify vector / matrix
|
50
51
|
def update_solution
|
51
|
-
@x = Array.new(@
|
52
|
+
@x = Array.new(@total_vars, 0)
|
52
53
|
|
53
54
|
@basic_vars.each { |basic_var|
|
54
55
|
idx = nil
|
55
|
-
@
|
56
|
+
@num_basic_vars.times { |i|
|
56
57
|
if @a[i][basic_var] == 1
|
57
|
-
idx =i
|
58
|
+
idx = i
|
58
59
|
break
|
59
60
|
end
|
60
61
|
}
|
@@ -78,7 +79,7 @@ class CompSci::Simplex
|
|
78
79
|
end
|
79
80
|
|
80
81
|
def current_solution
|
81
|
-
@x[0...@
|
82
|
+
@x[0...@num_free_vars]
|
82
83
|
end
|
83
84
|
|
84
85
|
def can_improve?
|
@@ -121,7 +122,7 @@ class CompSci::Simplex
|
|
121
122
|
}
|
122
123
|
|
123
124
|
# update A and B
|
124
|
-
@
|
125
|
+
@num_basic_vars.times { |i|
|
125
126
|
next if i == pivot_row
|
126
127
|
r = @a[i][pivot_column]
|
127
128
|
@a[i] = @a[i].map.with_index { |val, j| val - r * @a[pivot_row][j] }
|
@@ -134,7 +135,7 @@ class CompSci::Simplex
|
|
134
135
|
def pivot_row(column_ix)
|
135
136
|
min_ratio = nil
|
136
137
|
idx = nil
|
137
|
-
@
|
138
|
+
@num_basic_vars.times { |i|
|
138
139
|
a, b = @a[i][column_ix], @b[i]
|
139
140
|
next if a == 0 or (b < 0) ^ (a < 0)
|
140
141
|
ratio = Rational(b, a)
|
data/lib/compsci/timer.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
module CompSci
|
2
|
-
|
2
|
+
class Timer
|
3
|
+
SECS_PER_MIN = 60
|
4
|
+
MINS_PER_HOUR = 60
|
5
|
+
SECS_PER_HOUR = SECS_PER_MIN * MINS_PER_HOUR
|
6
|
+
|
3
7
|
# lifted from seattlerb/minitest
|
4
8
|
if defined? Process::CLOCK_MONOTONIC
|
5
9
|
def self.now
|
@@ -32,5 +36,61 @@ module CompSci
|
|
32
36
|
}
|
33
37
|
return val, self.since(start) / i.to_f
|
34
38
|
end
|
39
|
+
|
40
|
+
# YYYY-MM-DD HH::MM::SS.mmm
|
41
|
+
def self.timestamp(t)
|
42
|
+
t.strftime "%Y-%m-%d %H:%M:%S.%L"
|
43
|
+
end
|
44
|
+
|
45
|
+
# HH::MM::SS.mmm.uuuuuuuu
|
46
|
+
def self.elapsed_display(elapsed_ms, show_us: false)
|
47
|
+
elapsed_s, ms = elapsed_ms.divmod 1000
|
48
|
+
ms_only, ms_fraction = ms.round(8).divmod 1
|
49
|
+
|
50
|
+
h = elapsed_s / SECS_PER_HOUR
|
51
|
+
elapsed_s -= h * SECS_PER_HOUR
|
52
|
+
m, s = elapsed_s.divmod SECS_PER_MIN
|
53
|
+
|
54
|
+
hmsms = [[h, m, s].map { |i| i.to_s.rjust(2, '0') }.join(':'),
|
55
|
+
ms_only.to_s.rjust(3, '0')]
|
56
|
+
hmsms << (ms_fraction * 10 ** 8).round.to_s.ljust(8, '0') if show_us
|
57
|
+
hmsms.join('.')
|
58
|
+
end
|
59
|
+
|
60
|
+
def restart(t = Time.now)
|
61
|
+
@start = t
|
62
|
+
self
|
63
|
+
end
|
64
|
+
alias_method :initialize, :restart
|
65
|
+
|
66
|
+
def timestamp(t = Time.now)
|
67
|
+
self.class.timestamp t
|
68
|
+
end
|
69
|
+
|
70
|
+
def timestamp!(t = Time.now)
|
71
|
+
puts '-' * 70, timestamp(t), '-' * 70
|
72
|
+
end
|
73
|
+
|
74
|
+
def elapsed(t = Time.now)
|
75
|
+
t - @start
|
76
|
+
end
|
77
|
+
|
78
|
+
def elapsed_ms(t = Time.now)
|
79
|
+
elapsed(t) * 1000
|
80
|
+
end
|
81
|
+
|
82
|
+
def elapsed_display(t = Time.now)
|
83
|
+
self.class.elapsed_display(elapsed_ms(t))
|
84
|
+
end
|
85
|
+
alias_method :to_s, :elapsed_display
|
86
|
+
alias_method :inspect, :elapsed_display
|
87
|
+
|
88
|
+
def stamp(msg = '', t = Time.now)
|
89
|
+
format("%s %s", elapsed_display(t), msg)
|
90
|
+
end
|
91
|
+
|
92
|
+
def stamp!(msg = '', t = Time.now)
|
93
|
+
puts stamp(msg, t)
|
94
|
+
end
|
35
95
|
end
|
36
96
|
end
|
data/test/fit.rb
CHANGED
@@ -15,14 +15,14 @@ describe Fit do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
describe "Fit.sigma" do
|
18
|
-
it "
|
18
|
+
it "answers correctly" do
|
19
19
|
expect(Fit.sigma([1, 2, 3])).must_equal 6
|
20
20
|
expect(Fit.sigma([1, 2, 3]) { |n| n ** 2 }).must_equal 14
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
describe "Fit.error" do
|
25
|
-
it "
|
25
|
+
it "calculates r^2" do
|
26
26
|
expect(Fit.error([[1, 1], [2, 2], [3, 3]]) { |x| x }).must_equal 1.0
|
27
27
|
expect(Fit.error([[1, 1], [2, 2], [3, 4]]) { |x|
|
28
28
|
x
|
@@ -36,7 +36,7 @@ describe Fit do
|
|
36
36
|
# alternate measure. A low slope and r2 for linear fit, maybe.
|
37
37
|
#
|
38
38
|
describe "Fit.constant" do
|
39
|
-
it "
|
39
|
+
it "returns zero variance with truly constant inputs" do
|
40
40
|
[0, 1, 10, 100, 1000, 9999].each { |a|
|
41
41
|
y_bar, variance = Fit.constant(@xs, @xs.map { |x| a })
|
42
42
|
expect(y_bar).must_equal a
|
@@ -47,7 +47,7 @@ describe Fit do
|
|
47
47
|
|
48
48
|
# y = a + b*ln(x)
|
49
49
|
describe "Fit.logarithmic" do
|
50
|
-
it "
|
50
|
+
it "accepts logarithmic data" do
|
51
51
|
[-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |a|
|
52
52
|
[-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |b|
|
53
53
|
ary = Fit.logarithmic(@xs, @xs.map { |x| a + b * Math.log(x) })
|
@@ -61,7 +61,7 @@ describe Fit do
|
|
61
61
|
|
62
62
|
# y = a + bx
|
63
63
|
describe "Fit.linear" do
|
64
|
-
it "
|
64
|
+
it "accepts linear data" do
|
65
65
|
[-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |a|
|
66
66
|
[-9999, -2000, -500, -0.01, 0.01, 500, 2000, 9999].each { |b|
|
67
67
|
ary = Fit.linear(@xs, @xs.map { |x| a + b * x })
|
@@ -72,7 +72,7 @@ describe Fit do
|
|
72
72
|
}
|
73
73
|
end
|
74
74
|
|
75
|
-
it "
|
75
|
+
it "accepts constant data" do
|
76
76
|
[0, 1, 10, 100, 1000, 9999].each { |a|
|
77
77
|
ary = Fit.linear(@xs, @xs.map { |x| a })
|
78
78
|
expect(ary[0]).must_equal a
|
@@ -84,7 +84,7 @@ describe Fit do
|
|
84
84
|
# note, this test can possibly fail depending on the uniformity of
|
85
85
|
# rand's output for our sample
|
86
86
|
#
|
87
|
-
it "
|
87
|
+
it "accepts noisy constant data" do
|
88
88
|
r2s = []
|
89
89
|
[0, 1, 10, 100, 1000, 9999].each { |a|
|
90
90
|
ary = Fit.linear(@xs, @xs.map { |x| a + noise() })
|
@@ -96,16 +96,14 @@ describe Fit do
|
|
96
96
|
expect(mean_r2).must_be_close_to 0.15, 0.15
|
97
97
|
end
|
98
98
|
|
99
|
-
it "
|
100
|
-
|
101
|
-
xs = [1, 10, 100, 1000]
|
99
|
+
it "rejects x^2" do
|
100
|
+
xs = Array.new(99) { |i| i }
|
102
101
|
_a, _b, r2 = Fit.linear(xs, xs.map { |x| x**2 })
|
103
102
|
expect(r2).must_be :<, 0.99
|
104
103
|
end
|
105
104
|
|
106
|
-
it "
|
107
|
-
|
108
|
-
xs = [1, 10, 100, 1000]
|
105
|
+
it "rejects x^3" do
|
106
|
+
xs = Array.new(99) { |i| i }
|
109
107
|
_a, _b, r2 = Fit.linear(xs, xs.map { |x| x**3 })
|
110
108
|
expect(r2).must_be :<, 0.99
|
111
109
|
end
|
@@ -113,7 +111,7 @@ describe Fit do
|
|
113
111
|
|
114
112
|
# y = ae^(bx)
|
115
113
|
describe "Fit.exponential" do
|
116
|
-
it "
|
114
|
+
it "accepts exponential data" do
|
117
115
|
[0.001, 7.5, 500, 1000, 5000, 9999].each { |a|
|
118
116
|
[-1.4, -1.1, -0.1, 0.01, 0.5, 0.75].each { |b|
|
119
117
|
ary = Fit.exponential(@xs, @xs.map { |x| a * Math::E**(b * x) })
|
@@ -127,10 +125,13 @@ describe Fit do
|
|
127
125
|
|
128
126
|
# y = ax^b
|
129
127
|
describe "Fit.power" do
|
130
|
-
it "
|
128
|
+
it "accepts power data" do
|
131
129
|
[0.01, 7.5, 500, 1000, 5000, 9999].each { |a|
|
132
130
|
[-114, -100, -10, -0.5, -0.1, 0.1, 0.75, 10, 50, 60].each { |b|
|
133
|
-
|
131
|
+
# [ -100, -10, -0.5, -0.1, 0.1, 0.75, 10, 50, 60].each { |b|
|
132
|
+
# note: on Ruby 2.4.x and older, b == -114 throws
|
133
|
+
# warning: Bignum out of Float range
|
134
|
+
# also: TruffleRuby as of Jan '22: ary[2] is NaN rather than 1.0
|
134
135
|
ary = Fit.power(@xs, @xs.map { |x| a * x**b })
|
135
136
|
expect(ary[0]).must_be_close_to a
|
136
137
|
expect(ary[1]).must_be_close_to b
|
@@ -139,4 +140,41 @@ describe Fit do
|
|
139
140
|
}
|
140
141
|
end
|
141
142
|
end
|
143
|
+
|
144
|
+
describe "Fit.predict" do
|
145
|
+
before do
|
146
|
+
@a, @b, @x = 1, 2, 3
|
147
|
+
end
|
148
|
+
|
149
|
+
it "accepts a few different models" do
|
150
|
+
[:constant, :logarithmic, :linear, :exponential, :power].each { |model|
|
151
|
+
expect(Fit.predict(model, @a, @b, @x)).must_be_kind_of(Numeric)
|
152
|
+
}
|
153
|
+
expect { Fit.predict(:invalid, @a, @b, @x) }.must_raise RuntimeError
|
154
|
+
end
|
155
|
+
|
156
|
+
it "predicts constant relationships" do
|
157
|
+
expect(Fit.predict(:constant, @a, @b, @x)).must_equal @a
|
158
|
+
expect(Fit.predict(:constant, @a, @x, @b)).must_equal @a
|
159
|
+
expect(Fit.predict(:constant, @x, @a, @b)).must_equal @x
|
160
|
+
end
|
161
|
+
|
162
|
+
it "predicts logarithmic relationships" do
|
163
|
+
expect(Fit.predict(:logarithmic, @a, @b, @x)
|
164
|
+
).must_equal @a + @b * Math.log(@x)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "predicts linear relationships" do
|
168
|
+
expect(Fit.predict(:linear, @a, @b, @x)).must_equal @a + @b * @x
|
169
|
+
end
|
170
|
+
|
171
|
+
it "predicts exponential relationships" do
|
172
|
+
expect(Fit.predict(:exponential, @a, @b, @x)
|
173
|
+
).must_equal @a * Math::E ** (@b * @x)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "predicts power relationships" do
|
177
|
+
expect(Fit.predict(:power, @a, @b, @x)).must_equal @a * @x ** @b
|
178
|
+
end
|
179
|
+
end
|
142
180
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: compsci
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rick Hull
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: matrix
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.4'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: buildar
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -28,30 +42,30 @@ dependencies:
|
|
28
42
|
name: minitest
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- - "
|
45
|
+
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
47
|
version: '5.0'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
|
-
- - "
|
52
|
+
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '5.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- - "
|
59
|
+
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: 12.3
|
61
|
+
version: '12.3'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- - "
|
66
|
+
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: 12.3
|
68
|
+
version: '12.3'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: flog
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +137,7 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '2.0'
|
125
139
|
description: Trees, Heaps, Timers, Error fitting, etc
|
126
|
-
email:
|
140
|
+
email:
|
127
141
|
executables: []
|
128
142
|
extensions: []
|
129
143
|
extra_rdoc_files: []
|
@@ -172,7 +186,7 @@ homepage: https://github.com/rickhull/compsci
|
|
172
186
|
licenses:
|
173
187
|
- LGPL-3.0
|
174
188
|
metadata: {}
|
175
|
-
post_install_message:
|
189
|
+
post_install_message:
|
176
190
|
rdoc_options: []
|
177
191
|
require_paths:
|
178
192
|
- lib
|
@@ -180,15 +194,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
180
194
|
requirements:
|
181
195
|
- - "~>"
|
182
196
|
- !ruby/object:Gem::Version
|
183
|
-
version: '
|
197
|
+
version: '3.0'
|
184
198
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
199
|
requirements:
|
186
200
|
- - ">="
|
187
201
|
- !ruby/object:Gem::Version
|
188
202
|
version: '0'
|
189
203
|
requirements: []
|
190
|
-
rubygems_version: 3.
|
191
|
-
signing_key:
|
204
|
+
rubygems_version: 3.2.26
|
205
|
+
signing_key:
|
192
206
|
specification_version: 4
|
193
207
|
summary: Toy implementations for some basic computer science problems
|
194
208
|
test_files: []
|