compsci 0.3.1.1 → 0.3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/VERSION +1 -1
- data/compsci.gemspec +3 -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 +14 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a7f1f7282649dec4f08ef08ce3eb3b5b3b97183137624deaa9f20567650185a
|
4
|
+
data.tar.gz: 57081ef332e9adc6d3dbdc06b3ff2c9c76955d26b4fdd90402b7547b5544e0fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdb60b8e1230cdc175ac43afca1efe51bb163ce71dfb2cdd29ffa8ff8ab586456ec181dd46389d54b768edb360f5f9f56d6729bbd65ee86fcd7fa7acee0f417e
|
7
|
+
data.tar.gz: 3f20b69bd337aebc862a7f40e1e1177386979f71065200fa18e4dd69bdefb3a382dd8cbd066903d2ba5793cf5c71acd9cd09b79088c4c15b38982b8196bfb0c2
|
data/README.md
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
[![
|
1
|
+
[![CI Status](https://github.com/rickhull/compsci/actions/workflows/ci.yaml/badge.svg)](https://github.com/rickhull/compsci/actions/workflows/ci.yaml)
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/compsci.svg)](https://badge.fury.io/rb/compsci)
|
3
|
-
[![Dependency Status](https://gemnasium.com/rickhull/compsci.svg)](https://gemnasium.com/rickhull/compsci)
|
4
|
-
[![Security Status](https://hakiri.io/github/rickhull/compsci/master.svg)](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.1
|
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
|
|
@@ -16,8 +16,8 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.files += Dir['examples/**/*.rb']
|
17
17
|
|
18
18
|
s.add_development_dependency "buildar", "~> 3.0"
|
19
|
-
s.add_development_dependency "minitest", "
|
20
|
-
s.add_development_dependency "rake", "
|
19
|
+
s.add_development_dependency "minitest", "~> 5.0"
|
20
|
+
s.add_development_dependency "rake", "~> 12.3" # CVE-2020-8130
|
21
21
|
s.add_development_dependency "flog", "~> 0"
|
22
22
|
s.add_development_dependency "flay", "~> 0"
|
23
23
|
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,14 +1,14 @@
|
|
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.1
|
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
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: buildar
|
@@ -28,30 +28,30 @@ dependencies:
|
|
28
28
|
name: minitest
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '5.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '5.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 12.3
|
47
|
+
version: '12.3'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 12.3
|
54
|
+
version: '12.3'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: flog
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +123,7 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '2.0'
|
125
125
|
description: Trees, Heaps, Timers, Error fitting, etc
|
126
|
-
email:
|
126
|
+
email:
|
127
127
|
executables: []
|
128
128
|
extensions: []
|
129
129
|
extra_rdoc_files: []
|
@@ -172,7 +172,7 @@ homepage: https://github.com/rickhull/compsci
|
|
172
172
|
licenses:
|
173
173
|
- LGPL-3.0
|
174
174
|
metadata: {}
|
175
|
-
post_install_message:
|
175
|
+
post_install_message:
|
176
176
|
rdoc_options: []
|
177
177
|
require_paths:
|
178
178
|
- lib
|
@@ -180,15 +180,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
180
180
|
requirements:
|
181
181
|
- - "~>"
|
182
182
|
- !ruby/object:Gem::Version
|
183
|
-
version: '
|
183
|
+
version: '3.0'
|
184
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
185
|
requirements:
|
186
186
|
- - ">="
|
187
187
|
- !ruby/object:Gem::Version
|
188
188
|
version: '0'
|
189
189
|
requirements: []
|
190
|
-
rubygems_version: 3.
|
191
|
-
signing_key:
|
190
|
+
rubygems_version: 3.2.26
|
191
|
+
signing_key:
|
192
192
|
specification_version: 4
|
193
193
|
summary: Toy implementations for some basic computer science problems
|
194
194
|
test_files: []
|