mll 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +13 -1
- data/lib/mll.rb +77 -29
- data/mll.gemspec +1 -1
- data/spec/_spec.rb +372 -70
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1826ae5ecd9c663432d75b8d35387762e7d3ce85
|
4
|
+
data.tar.gz: 1387511b30a66d4331ab6fe978682dfc0e4607af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e791cfab9e6f9e979b3c68a6364a2e8fd362696ae7592083f934165a543a525828f9b7504d137a32984988490c22b9e2bc891df7542f94bbcc1c3241b9c3e94
|
7
|
+
data.tar.gz: 71d9d47ec39472b8666db934b34fb33042a18b64e5543f0e8c19c1a39982e035335bf1075521069732014529b49ae59f298cb88f6ed10daea28c3f1dd13b255a
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
## Why
|
8
8
|
|
9
|
-
1. Важной является реализация https://reference.wolfram.com/language/ref/Listable.html: автоматическое применение функции ко всем элементам аргумента, если тот является List-ом (Array-ем в среде Ruby).
|
9
|
+
1. Важной является реализация https://reference.wolfram.com/language/ref/Listable.html: автоматическое применение функции ко всем элементам аргумента, если тот является List-ом (Array-ем в среде Ruby).
|
10
10
|
2. `::range`, в отличие от рубишного, может иметь отрицательный step.
|
11
11
|
3. `::table`, в отличие от рубишного `.map`, может создавать многомерные массивы одним вызовом, а не только вложенными.
|
12
12
|
|
@@ -24,6 +24,18 @@
|
|
24
24
|
# => [[[111, 112, 113, 114], [121, 122, 123, 124], [131, 132, 133, 134]],
|
25
25
|
[[211, 212, 213, 214], [221, 222, 223, 224], [231, 232, 233, 234]]]
|
26
26
|
|
27
|
+
MLL::table MLL.method(:times), 9, 9
|
28
|
+
# => [[1, 2, 3, 4, 5, 6, 7, 8, 9],
|
29
|
+
[2, 4, 6, 8, 10, 12, 14, 16, 18],
|
30
|
+
[3, 6, 9, 12, 15, 18, 21, 24, 27],
|
31
|
+
[4, 8, 12, 16, 20, 24, 28, 32, 36],
|
32
|
+
[5, 10, 15, 20, 25, 30, 35, 40, 45],
|
33
|
+
[6, 12, 18, 24, 30, 36, 42, 48, 54],
|
34
|
+
[7, 14, 21, 28, 35, 42, 49, 56, 63],
|
35
|
+
[8, 16, 24, 32, 40, 48, 56, 64, 72],
|
36
|
+
[9, 18, 27, 36, 45, 54, 63, 72, 81]]
|
37
|
+
|
38
|
+
|
27
39
|
## Installation
|
28
40
|
|
29
41
|
$ gem install mll
|
data/lib/mll.rb
CHANGED
@@ -1,14 +1,67 @@
|
|
1
1
|
module MLL
|
2
2
|
|
3
|
-
|
3
|
+
def self.nest_list f, expr, n
|
4
|
+
Enumerator.new do |e|
|
5
|
+
e << expr
|
6
|
+
n.times do
|
7
|
+
e << expr = f.call(expr)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
# def self.nest *args
|
12
|
+
# nest_list(*args).last
|
13
|
+
# end
|
14
|
+
def self.nest f, expr, n
|
15
|
+
n.times{ expr = f.call expr }
|
16
|
+
expr
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.fold_list f, x, list = nil
|
20
|
+
# TODO teach it to accept Range ?
|
21
|
+
x, *list = x unless list
|
22
|
+
# use Ruby#inject ?
|
23
|
+
Enumerator.new do |e|
|
24
|
+
e << x
|
25
|
+
list.each do |i|
|
26
|
+
e << x = f.call(x, i)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.table f, *args
|
32
|
+
[].tap do |result|
|
33
|
+
[[result, args.map{ |r| # add lazy?
|
34
|
+
r.respond_to?(:map) && r.first.respond_to?(:map) ?
|
35
|
+
r.first : range(*r)
|
36
|
+
}]].tap do |stack|
|
37
|
+
stack.each do |ai, ri|
|
38
|
+
# TODO try to make #table lazy (Enumerator instead of Array)
|
39
|
+
# "no implicit conversion of Enumerator::Lazy into Array"
|
40
|
+
# "undefined method `replace' for #<Enumerator::Lazy: []>"
|
41
|
+
ai.replace ri.first.map{ |i|
|
42
|
+
if ri.size == 1
|
43
|
+
f.call(*ai, i)
|
44
|
+
else
|
45
|
+
[*ai.dup, i].tap{ |t| stack << [t, ri.drop(1)] }
|
46
|
+
end
|
47
|
+
}#.to_a # WTF
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# http://reference.wolfram.com/language/ref/Listable.html
|
4
54
|
def self.define_listable_function name, &block
|
5
55
|
(class << self; self end).class_eval do # http://stackoverflow.com/a/12792313/322020
|
6
56
|
define_method name do |*args|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
57
|
+
case args.map{ |i| i.respond_to? :map }
|
58
|
+
when [true] ; args.first.lazy.map &method(name)
|
59
|
+
when [true, true] ; args.first.lazy.zip(args.last).map{ |i, j| send name, i, j }
|
60
|
+
when [true, false] ; args.first.lazy.map{ |i| send name, i, args.last }
|
61
|
+
when [false, true] ; args.last.lazy.map{ |i| send name, args.first, i }
|
62
|
+
else
|
63
|
+
block.call *args
|
64
|
+
end
|
12
65
|
end
|
13
66
|
end
|
14
67
|
end
|
@@ -36,37 +89,32 @@ module MLL
|
|
36
89
|
end
|
37
90
|
end
|
38
91
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
if ri.size == 1
|
51
|
-
f.call(*ai, i)
|
52
|
-
else
|
53
|
-
[*ai.dup, i].tap{ |t| stack << [t, ri.drop(1)] }
|
54
|
-
end
|
55
|
-
}#.to_a # WTF
|
92
|
+
define_listable_function (:subtract) { |a, b| a - b }
|
93
|
+
define_listable_function (:divide) { |a, b| a / b }
|
94
|
+
define_listable_function (:_plus) { |a, b| a + b }
|
95
|
+
define_listable_function (:_times) { |a, b| a * b }
|
96
|
+
|
97
|
+
# http://reference.wolfram.com/language/ref/Orderless.html
|
98
|
+
def self.define_orderless_function name, &block
|
99
|
+
(class << self; self end).class_eval do # http://stackoverflow.com/a/12792313/322020
|
100
|
+
define_method name do |*args|
|
101
|
+
args.inject do |memo, obj|
|
102
|
+
block.call memo, obj
|
56
103
|
end
|
57
104
|
end
|
58
105
|
end
|
59
106
|
end
|
60
107
|
|
61
|
-
|
62
|
-
|
63
|
-
end
|
108
|
+
define_orderless_function (:plus) { |a, b| _plus a, b }
|
109
|
+
define_orderless_function (:times) { |a, b| _times a, b }
|
64
110
|
|
65
111
|
def self.subdivide *args
|
66
112
|
case args.size
|
67
|
-
|
68
|
-
|
69
|
-
|
113
|
+
when 1 ; subdivide 1, args[0]
|
114
|
+
when 2 ; subdivide 0, args[0], args[1]
|
115
|
+
when 3 ; range(args[0], args[1], (args[1] - args[0]) * 1.0 / args[2])
|
116
|
+
## using only pure Ruby methods makes unittests more reliable
|
117
|
+
# when 3 ; plus args[0], divide(times(1.0, args[1] - args[0], range(0, args[2])), args[2])
|
70
118
|
else
|
71
119
|
raise ArgumentError.new("wrong number of arguments (#{args.size} for 1..3)")
|
72
120
|
end
|
data/mll.gemspec
CHANGED
data/spec/_spec.rb
CHANGED
@@ -1,9 +1,26 @@
|
|
1
1
|
require_relative File.join "..", "lib", "mll"
|
2
2
|
|
3
3
|
|
4
|
-
#
|
5
|
-
#
|
6
|
-
|
4
|
+
# PERMATODO test all implemented exceptions
|
5
|
+
# PERMATODO test all types returned (not actually all but about lazyness)
|
6
|
+
# PERMATODO check for "Details" paragraphs to make more trivial examples
|
7
|
+
# PERMATODO leave here only useful tests, not demostrations -- move them to README.rb
|
8
|
+
# PERMATODO single element Arrays tests
|
9
|
+
# PERMATODO move Properties & Relations to some separate contexts maybe
|
10
|
+
|
11
|
+
# TODO test all implemented exceptions
|
12
|
+
# TODO test all types returned (not actually all but about lazyness)
|
13
|
+
# TODO check for "Details" paragraphs to make more trivial examples
|
14
|
+
# TODO leave here only useful tests, not demostrations -- move them to README.rb
|
15
|
+
# TODO single element Arrays tests
|
16
|
+
# TODO move Properties & Relations to some separate contexts maybe
|
17
|
+
|
18
|
+
# TODO @fraggedICE wishes using Rational -- would also allow implementing more examples
|
19
|
+
# TODO rake task for appending TODOs and pendings to README.rb
|
20
|
+
# TODO rename examples according to their description not content
|
21
|
+
# TODO elegantly get rid of repetitive type checks
|
22
|
+
# TODO implement #power for use in unittests
|
23
|
+
# TODO let(:fake_lambda){ ->(*args){fail} } ?
|
7
24
|
|
8
25
|
# http://reference.wolfram.com/language/guide/LanguageOverview.html
|
9
26
|
describe MLL do
|
@@ -14,13 +31,35 @@ describe MLL do
|
|
14
31
|
# NO URL
|
15
32
|
describe "Mathematics & Operators" do
|
16
33
|
|
34
|
+
# http://reference.wolfram.com/language/ref/Subtract.html
|
35
|
+
describe "#subtract" do
|
36
|
+
|
37
|
+
describe "Basic Examples" do
|
38
|
+
|
39
|
+
example "subtract(n1, n2)" do
|
40
|
+
expect(MLL::subtract(10,3)).to eq 7
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "Scope" do
|
46
|
+
|
47
|
+
example "subtract(list, n)" do
|
48
|
+
expect(MLL::subtract([1,2,3,4],0.5)).to be_a Enumerator
|
49
|
+
expect(MLL::subtract([1,2,3,4],0.5).to_a).to eq [0.5,1.5,2.5,3.5]
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
17
56
|
# http://reference.wolfram.com/language/ref/Divide.html
|
18
57
|
describe "#divide" do
|
19
58
|
|
20
59
|
describe "Basic Examples" do
|
21
60
|
|
22
|
-
example "n1
|
23
|
-
expect(MLL::divide(77,11)).to be_a Fixnum
|
61
|
+
example "divide(n1, n2)" do
|
62
|
+
# expect(MLL::divide(77,11)).to be_a Fixnum
|
24
63
|
expect(MLL::divide(77,11)).to eq 7
|
25
64
|
end
|
26
65
|
|
@@ -28,11 +67,11 @@ describe MLL do
|
|
28
67
|
|
29
68
|
describe "Scope" do
|
30
69
|
|
31
|
-
example "list
|
70
|
+
example "divide(list, n)" do
|
32
71
|
expect(MLL::divide([2,3,4,5],2.0)).to be_a Enumerator
|
33
72
|
expect(MLL::divide([2,3,4,5],2.0).to_a).to eq [1,1.5,2,2.5]
|
34
73
|
end
|
35
|
-
example "list
|
74
|
+
example "divide(list, list)" do
|
36
75
|
expect(MLL::divide([2,3,4],[2,1,4])).to be_a Enumerator
|
37
76
|
expect(MLL::divide([2,3,4],[2,1,4]).to_a).to eq [1,3,1]
|
38
77
|
end
|
@@ -41,11 +80,6 @@ describe MLL do
|
|
41
80
|
|
42
81
|
describe "Applications" do
|
43
82
|
|
44
|
-
example "foldlist(divide, 1, range(10))" do
|
45
|
-
pending "#foldlist is yet to be implemented"
|
46
|
-
fail
|
47
|
-
end
|
48
|
-
|
49
83
|
# TODO: "Successive ratios in a list:"
|
50
84
|
|
51
85
|
end
|
@@ -56,7 +90,7 @@ describe MLL do
|
|
56
90
|
pending "#nestlist is yet to be implemented"
|
57
91
|
fail
|
58
92
|
end
|
59
|
-
example "table(
|
93
|
+
example "table(function, n1, n2)" do
|
60
94
|
expect(MLL::table(MLL.method(:divide), [[3,6]], 4.0)).to be_a Array
|
61
95
|
expect(MLL::table(MLL.method(:divide), [[6]], 4.0)).to eq [[6.0,3.0,2.0,1.5]]
|
62
96
|
end
|
@@ -65,6 +99,73 @@ describe MLL do
|
|
65
99
|
|
66
100
|
end
|
67
101
|
|
102
|
+
# TODO common tests for threading functions like times, plus, etc.
|
103
|
+
|
104
|
+
# http://reference.wolfram.com/language/ref/Plus.html
|
105
|
+
describe "#plus" do
|
106
|
+
|
107
|
+
describe "Basic Examples" do
|
108
|
+
|
109
|
+
example "plus(n1, n2, n3)" do
|
110
|
+
expect(MLL::plus(2,3,4)).to eq 9
|
111
|
+
end
|
112
|
+
example "plus([n1, n2, n3], n)" do
|
113
|
+
expect(MLL::plus([3,4,5],2)).to be_a Enumerator
|
114
|
+
expect(MLL::plus([3,4,5],2).to_a).to eq [5,6,7]
|
115
|
+
end
|
116
|
+
example "plus(n1, n2, [n3, n4])" do
|
117
|
+
expect(MLL::plus(2,3,[4,5])).to be_a Enumerator
|
118
|
+
expect(MLL::plus(2,3,[4,5]).to_a).to eq [9,10]
|
119
|
+
end
|
120
|
+
example "plus(list, list)" do
|
121
|
+
expect(MLL::plus([10,20,30],[1,2,3])).to be_a Enumerator
|
122
|
+
expect(MLL::plus([10,20,30],[1,2,3]).to_a).to eq [11,22,33]
|
123
|
+
end
|
124
|
+
example "plus(list_of_lists, n)" do
|
125
|
+
expect(MLL::plus([[1,2],[3,4]],5)).to be_a Enumerator
|
126
|
+
expect(MLL::plus([[1,2],[3,4]],5).to_a.map(&:to_a)).to eq [[6,7],[8,9]]
|
127
|
+
end
|
128
|
+
example "plus(list_of_lists, list_of_lists)" do
|
129
|
+
expect(MLL::plus([[1,2],[3,4]],[[5,6],[7,8]])).to be_a Enumerator
|
130
|
+
expect(MLL::plus([[1,2],[3,4]],[[5,6],[7,8]]).to_a.map(&:to_a)).to eq [[6,8],[10,12]]
|
131
|
+
end
|
132
|
+
example "plus([[n1, n2], [n3, n4]], [n5, n6])" do
|
133
|
+
expect(MLL::plus([[1,2],[3,4]],[5,6])).to be_a Enumerator
|
134
|
+
expect(MLL::plus([[1,2],[3,4]],[5,6]).to_a.map(&:to_a)).to eq [[6,7],[9,10]]
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
# TODO "Accumulate makes a cumulative sum:"
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
# http://reference.wolfram.com/language/ref/Times.html
|
144
|
+
describe "#times" do
|
145
|
+
|
146
|
+
describe "Basic Examples" do
|
147
|
+
|
148
|
+
example "times(n1, n2, n3)" do
|
149
|
+
# expect(MLL::times(2,3,4)).to be_a Fixnum
|
150
|
+
expect(MLL::times(2,3,4)).to eq 24
|
151
|
+
end
|
152
|
+
example "times(n, [n1, n2, n3])" do
|
153
|
+
expect(MLL::times(2,[3,4,5])).to be_a Enumerator
|
154
|
+
expect(MLL::times(2,[3,4,5]).to_a).to eq [6,8,10]
|
155
|
+
end
|
156
|
+
example "times(n1, n2, [n3, n4])" do
|
157
|
+
expect(MLL::times(2,3,[4,5])).to be_a Enumerator
|
158
|
+
expect(MLL::times(2,3,[4,5]).to_a).to eq [24,30]
|
159
|
+
end
|
160
|
+
example "times([[n1, n2], [n3, n4]], [n5, n6])" do
|
161
|
+
expect(MLL::times([[1,2],[3,4]],[5,6])).to be_a Enumerator
|
162
|
+
expect(MLL::times([[1,2],[3,4]],[5,6]).to_a.map(&:to_a)).to eq [[5,10],[18,24]]
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
68
169
|
end
|
69
170
|
|
70
171
|
end
|
@@ -75,6 +176,66 @@ describe MLL do
|
|
75
176
|
# http://reference.wolfram.com/language/guide/ConstructingLists.html
|
76
177
|
describe "Constructing Lists" do
|
77
178
|
|
179
|
+
# http://reference.wolfram.com/language/ref/Table.html
|
180
|
+
describe "#table" do
|
181
|
+
|
182
|
+
describe "Basic Examples" do
|
183
|
+
|
184
|
+
example "table(lambda, n)" do
|
185
|
+
expect(MLL::table(->(i){ i**2 }, 10)).to be_a Array
|
186
|
+
expect(MLL::table(->(i){ i**2 }, 10)).to eq [1,4,9,16,25,36,49,64,81,100]
|
187
|
+
end
|
188
|
+
example "table(lambda, [min, max, step])" do
|
189
|
+
expect(MLL::table(->(i){ i+2 }, [0, 20, 2])).to be_a Array
|
190
|
+
expect(MLL::table(->(i){ i+2 }, [0, 20, 2])).to eq [2,4,6,8,10,12,14,16,18,20,22]
|
191
|
+
end
|
192
|
+
example "table(lambda, n1, n2)" do
|
193
|
+
# TODO example to README.rb about multiplication table
|
194
|
+
expect(MLL::table(->(i,j){ 10*i + j }, 4, 3)).to be_a Array
|
195
|
+
expect(MLL::table(->(i,j){ 10*i + j }, 4, 3)).to eq [[11,12,13],[21,22,23],[31,32,33],[41,42,43]]
|
196
|
+
end
|
197
|
+
example "table(lambda, n1, min..max, [max, min, -step])" do
|
198
|
+
expect(MLL::table(->(i,j,k){ [i,j,k] }, 3, 2..3, [5, 1, -2])).to be_a Array
|
199
|
+
expect(MLL::table(->(i,j,k){ [i,j,k] }, 3, 2..3, [5, 1, -2])).to eq \
|
200
|
+
[
|
201
|
+
[[[1, 2, 5], [1, 2, 3], [1, 2, 1]], [[1, 3, 5], [1, 3, 3], [1, 3, 1]]],
|
202
|
+
[[[2, 2, 5], [2, 2, 3], [2, 2, 1]], [[2, 3, 5], [2, 3, 3], [2, 3, 1]]],
|
203
|
+
[[[3, 2, 5], [3, 2, 3], [3, 2, 1]], [[3, 3, 5], [3, 3, 3], [3, 3, 1]]]
|
204
|
+
]
|
205
|
+
end
|
206
|
+
|
207
|
+
example "matrix_form table(lambda, n1, n2)" do
|
208
|
+
pending "#matrix_form is yet to be implemented"
|
209
|
+
expect(MLL::matrix_form MLL::table(->(i,j){ 10*i + j }, 4, 3)).to eq "
|
210
|
+
"
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "Scope" do
|
216
|
+
|
217
|
+
# TODO: "Make a triangular array:"
|
218
|
+
|
219
|
+
example "table(lambda, [list1], [list2])" do
|
220
|
+
expect(MLL::table(->(base, power){ base ** power }, [[1,2,4]], [[1,3,4]])).to be_a Array
|
221
|
+
expect(MLL::table(->(base, power){ base ** power }, [[1,2,4]], [[1,3,4]])).to eq [[1,1,1],[2,8,16],[4,64,256]]
|
222
|
+
expect(MLL::table(MLL::method(:plus), [[1]], [[2]])).to be_a Array
|
223
|
+
expect(MLL::table(MLL::method(:plus), [[1]], [[2]])).to eq [[3]]
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "Applications" do
|
229
|
+
|
230
|
+
example "column table(binomial, )" do
|
231
|
+
pending "#binomial and #column are yet to be implemented"
|
232
|
+
fail
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
238
|
+
|
78
239
|
# http://reference.wolfram.com/language/ref/Range.html
|
79
240
|
describe "#range" do
|
80
241
|
|
@@ -160,60 +321,163 @@ describe MLL do
|
|
160
321
|
|
161
322
|
end
|
162
323
|
|
163
|
-
# http://reference.wolfram.com/language/ref/
|
164
|
-
describe "#
|
165
|
-
|
324
|
+
# http://reference.wolfram.com/language/ref/Subdivide.html
|
325
|
+
describe "#subdivide" do
|
326
|
+
|
327
|
+
example "subdivide(n)" do
|
328
|
+
expect(MLL::subdivide(4)).to be_a Enumerator
|
329
|
+
expect(MLL::subdivide(4).to_a).to eq [0,0.25,0.5,0.75,1]
|
330
|
+
end
|
331
|
+
example "subdivide(max, n)" do
|
332
|
+
expect(MLL::subdivide(10,5)).to be_a Enumerator
|
333
|
+
expect(MLL::subdivide(10,5).to_a).to eq [0,2,4,6,8,10]
|
334
|
+
end
|
335
|
+
example "subdivide(min, max, n)" do
|
336
|
+
expect(MLL::subdivide(-1,1,8)).to be_a Enumerator
|
337
|
+
expect(MLL::subdivide(-1,1,8).to_a).to eq [-1,-0.75,-0.5,-0.25,0,0.25,0.5,0.75,1]
|
338
|
+
end
|
339
|
+
example "subdivide(max, min, n)" do
|
340
|
+
expect(MLL::subdivide(1,-1,8)).to be_a Enumerator
|
341
|
+
expect(MLL::subdivide(1,-1,8).to_a).to eq [1,0.75,0.5,0.25,0,-0.25,-0.5,-0.75,-1]
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
345
|
+
|
346
|
+
# http://reference.wolfram.com/language/ref/NestList.html
|
347
|
+
describe "#nest_list" do
|
348
|
+
|
349
|
+
example "#nest_list gives a list of length n+1" do
|
350
|
+
expect(MLL::nest_list(->{}, 0, 5)).to be_a Enumerator
|
351
|
+
expect(MLL::nest_list(->(*args){}, 0, 5).to_a.size).to eq 6
|
352
|
+
end
|
166
353
|
|
167
354
|
describe "Basic Examples" do
|
168
355
|
|
169
|
-
example "
|
170
|
-
|
171
|
-
|
356
|
+
example "'nest_list with #cos starting with 1.0)'" do
|
357
|
+
pending "#cos is yet to be implemented"
|
358
|
+
fail
|
172
359
|
end
|
173
|
-
|
174
|
-
|
175
|
-
|
360
|
+
|
361
|
+
end
|
362
|
+
|
363
|
+
describe "Scope" do
|
364
|
+
|
365
|
+
example "nesting can return a single number" do
|
366
|
+
pending "#sqrt is yet to be implemented"
|
367
|
+
fail
|
176
368
|
end
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
369
|
+
|
370
|
+
end
|
371
|
+
|
372
|
+
describe "Applications" do
|
373
|
+
|
374
|
+
example "powers of 2" do
|
375
|
+
expect(MLL::nest_list(->(i){ 2*i }, 1, 10)).to be_a Enumerator
|
376
|
+
expect(MLL::nest_list(->(i){ 2*i }, 1, 10).to_a).to eq [1,2,4,8,16,32,64,128,256,512,1024]
|
181
377
|
end
|
182
|
-
example "
|
183
|
-
expect(MLL::
|
184
|
-
expect(MLL::
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
378
|
+
example "iterates in the problem" do
|
379
|
+
expect(MLL::nest_list(->(i){ i.even? ? i/2 : (i*3+1)/2 }, 100, 20)).to be_a Enumerator
|
380
|
+
expect(MLL::nest_list(->(i){ i.even? ? i/2 : (i*3+1)/2 }, 100, 20).to_a).to eq [100,50,25,38,19,29,44,22,11,17,26,13,20,10,5,8,4,2,1,2,1]
|
381
|
+
end
|
382
|
+
example "linear congruential pseudorandom generator" do
|
383
|
+
expect(MLL::nest_list(->(i){ (i*59)%101 }, 1, 15)).to be_a Enumerator
|
384
|
+
expect(MLL::nest_list(->(i){ (i*59)%101 }, 1, 15).to_a).to eq [1,59,47,46,88,41,96,8,68,73,65,98,25,61,64,39]
|
385
|
+
end
|
386
|
+
example "random walk" do
|
387
|
+
expect(( r = Random.new(0); MLL::nest_list(->(i){ i+[-1,1][r.rand(2)] }, 0, 20) )).to be_a Enumerator
|
388
|
+
expect(( r = Random.new(0); MLL::nest_list(->(i){ i+[-1,1][r.rand(2)] }, 0, 20).to_a )).to eq [0,-1,0,1,0,1,2,3,4,5,6,7,6,5,6,5,4,3,2,1,2]
|
389
|
+
end
|
390
|
+
example "successively rotate a list" do
|
391
|
+
expect(MLL::nest_list(->(i){ i.rotate 1 }, [1,2,3,4], 4)).to be_a Enumerator
|
392
|
+
expect(MLL::nest_list(->(i){ i.rotate 1 }, [1,2,3,4], 4).to_a).to eq [[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3],[1,2,3,4]]
|
190
393
|
end
|
191
394
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
395
|
+
end
|
396
|
+
|
397
|
+
describe "Properties & Relations" do
|
398
|
+
|
399
|
+
# TODO "Nest gives the last element of NestList:"
|
400
|
+
|
401
|
+
example "nesting zero times simply returns to the original argument" do
|
402
|
+
expect(MLL::nest_list(->{fail}, 5, 0)).to be_a Enumerator
|
403
|
+
expect(MLL::nest_list(->(*args){fail}, 5, 0).to_a).to eq [5]
|
404
|
+
end
|
405
|
+
example "#fold_list automatically inserts second arguments from a list" do
|
406
|
+
expect(MLL::nest_list(->(i ){ i*2 }, 3, 4).to_a).to eq \
|
407
|
+
MLL::fold_list(->(i,j){ i*j }, 3, [2]*4).to_a
|
196
408
|
end
|
197
409
|
|
198
410
|
end
|
199
411
|
|
200
|
-
|
412
|
+
end
|
201
413
|
|
202
|
-
|
414
|
+
end
|
203
415
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
416
|
+
# http://reference.wolfram.com/language/guide/ApplyingFunctionsToLists.html
|
417
|
+
describe "Applying Functions to Lists" do
|
418
|
+
|
419
|
+
describe "#fold_list" do
|
420
|
+
|
421
|
+
describe "Basic Examples" do
|
422
|
+
|
423
|
+
example "fold_list(function, list)" do
|
424
|
+
expect(MLL::fold_list(MLL.method(:plus),[1,2,3,4])).to be_a Enumerator
|
425
|
+
expect(MLL::fold_list(MLL.method(:plus),[1,2,3,4]).to_a).to eq [1,3,6,10]
|
426
|
+
end
|
427
|
+
example "fold_list(function, n, list)" do
|
428
|
+
expect(MLL::fold_list(MLL.method(:plus),5,[1,2,3,4])).to be_a Enumerator
|
429
|
+
expect(MLL::fold_list(MLL.method(:plus),5,[1,2,3,4]).to_a).to eq [5,6,8,11,15]
|
430
|
+
end
|
431
|
+
example "fold_list(lambda, n, list)" do
|
432
|
+
expect(MLL::fold_list(->(base, power){ base ** power },2,[3,2,1])).to be_a Enumerator
|
433
|
+
expect(MLL::fold_list(->(base, power){ base ** power },2,[3,2,1]).to_a).to eq [2,8,64,64]
|
209
434
|
end
|
210
435
|
|
211
436
|
end
|
212
437
|
|
213
438
|
describe "Applications" do
|
214
439
|
|
215
|
-
example "
|
216
|
-
|
440
|
+
example "fold_list(function, n, list)" do
|
441
|
+
expect(MLL::fold_list(MLL.method(:times), [*1..10])).to be_a Enumerator
|
442
|
+
expect(MLL::fold_list(MLL.method(:times), [*1..10]).to_a).to eq [1,2,6,24,120,720,5040,40320,362880,3628800]
|
443
|
+
end
|
444
|
+
example "fold_list(lambda, n, list)" do
|
445
|
+
expect(MLL::fold_list(->(a,b){ 10*a + b }, 0, [4,5,1,6,7,8])).to be_a Enumerator
|
446
|
+
expect(MLL::fold_list(->(a,b){ 10*a + b }, 0, [4,5,1,6,7,8]).to_a).to eq [0,4,45,451,4516,45167,451678]
|
447
|
+
end
|
448
|
+
example "fold_list(lambda, n, list)" do
|
449
|
+
expect(( r = Random.new(0); MLL::fold_list(MLL.method(:plus), 0, Array.new(20){ [-1,1][r.rand(2)] }) )).to be_a Enumerator
|
450
|
+
expect(( r = Random.new(0); MLL::fold_list(MLL.method(:plus), 0, Array.new(20){ [-1,1][r.rand(2)] }).to_a )).to eq [0,-1,0,1,0,1,2,3,4,5,6,7,6,5,6,5,4,3,2,1,2]
|
451
|
+
end
|
452
|
+
|
453
|
+
# TODO "Find successively deeper parts in an expression:"
|
454
|
+
|
455
|
+
end
|
456
|
+
|
457
|
+
describe "Properties & Relations" do
|
458
|
+
|
459
|
+
example "#fold_list makes a list of length n+1" do
|
460
|
+
expect(MLL::fold_list(->{}, 0, [*1..10])).to be_a Enumerator
|
461
|
+
expect(MLL::fold_list(->(*args){}, 0, [*1..10]).to_a.size).to eq 11
|
462
|
+
end
|
463
|
+
example "folding with an empty list does not apply the function at all" do
|
464
|
+
expect(MLL::fold_list(->{}, 0, [])).to be_a Enumerator
|
465
|
+
expect(MLL::fold_list(->(*args){}, 0, []).to_a).to eq [0]
|
466
|
+
end
|
467
|
+
example "Ruby#inject gives the last element of #fold_list" do
|
468
|
+
f = ->(i,j){ i+j }
|
469
|
+
expect(MLL::fold_list(f, [1,2,3])).to be_a Enumerator
|
470
|
+
expect(MLL::fold_list(f, [1,2,3]).to_a.last).to eq [1,2,3].inject(&f)
|
471
|
+
end
|
472
|
+
# TODO "Functions that ignore their second argument give the same result as in NestList:"
|
473
|
+
# TODO "Accumulate is equivalent to FoldList with Plus:"
|
474
|
+
|
475
|
+
end
|
476
|
+
|
477
|
+
describe "Neat Examples" do
|
478
|
+
|
479
|
+
example "compute the minimum number of coins of different value needed to make up an amount" do
|
480
|
+
pending "at least #mod is yet to be implemented"
|
217
481
|
fail
|
218
482
|
end
|
219
483
|
|
@@ -221,40 +485,78 @@ describe MLL do
|
|
221
485
|
|
222
486
|
end
|
223
487
|
|
224
|
-
|
225
|
-
|
488
|
+
end
|
489
|
+
|
490
|
+
# TODO http://reference.wolfram.com/language/guide/ElementsOfLists.html
|
491
|
+
# TODO http://reference.wolfram.com/language/guide/RearrangingAndRestructuringLists.html
|
492
|
+
# TODO http://reference.wolfram.com/language/guide/MathematicalAndCountingOperationsOnLists.html
|
493
|
+
|
494
|
+
end
|
495
|
+
|
496
|
+
# http://reference.wolfram.com/language/guide/FunctionalProgramming.html
|
497
|
+
describe "Functional Programming" do
|
498
|
+
|
499
|
+
# http://reference.wolfram.com/language/guide/FunctionalIteration.html
|
500
|
+
describe "Iteratively Applying Functions" do
|
501
|
+
|
502
|
+
# TODO move #nest_list and #fold_list and others here?
|
503
|
+
|
504
|
+
describe "#nest" do
|
505
|
+
|
506
|
+
describe "Basic Examples" do
|
507
|
+
|
508
|
+
example "the function to nest can be a pure function" do
|
509
|
+
expect(MLL::nest(->(i){ (1+i)**2 }, 1, 3)).to eq 676
|
510
|
+
end
|
226
511
|
|
227
|
-
example "subdivide(n)" do
|
228
|
-
expect(MLL::subdivide(4)).to be_a Enumerator
|
229
|
-
expect(MLL::subdivide(4).to_a).to eq [0,0.25,0.5,0.75,1]
|
230
512
|
end
|
231
|
-
|
232
|
-
|
233
|
-
|
513
|
+
|
514
|
+
describe "Scope" do
|
515
|
+
|
516
|
+
example "nesting can return a single number" do
|
517
|
+
pending "#sqrt is yet to be implemented"
|
518
|
+
fail
|
519
|
+
end
|
520
|
+
|
234
521
|
end
|
235
|
-
|
236
|
-
|
237
|
-
|
522
|
+
|
523
|
+
describe "Applications" do
|
524
|
+
|
525
|
+
example "newton iterations for" do
|
526
|
+
pending "need to deal with Rationals first"
|
527
|
+
fail
|
528
|
+
end
|
529
|
+
example "consecutive pairs of Fibonacci numbers" do
|
530
|
+
pending "implement #dot ?"
|
531
|
+
fail
|
532
|
+
end
|
533
|
+
|
238
534
|
end
|
239
|
-
|
240
|
-
|
241
|
-
|
535
|
+
|
536
|
+
describe "Properties & Relations" do
|
537
|
+
|
538
|
+
example "#fold automatically inserts second arguments from a list" do
|
539
|
+
expect(MLL::nest(->(i){ i*2 }, 3, 4)).to eq \
|
540
|
+
([2]*4).inject(3){ |i,j| i*j }
|
541
|
+
end
|
542
|
+
|
242
543
|
end
|
243
544
|
|
545
|
+
# TODO neat graphic examples
|
546
|
+
|
244
547
|
end
|
245
548
|
|
246
549
|
end
|
247
550
|
|
248
|
-
# http://reference.wolfram.com/language/guide/ElementsOfLists.html
|
249
|
-
# http://reference.wolfram.com/language/guide/RearrangingAndRestructuringLists.html
|
250
|
-
# http://reference.wolfram.com/language/guide/ApplyingFunctionsToLists.html
|
251
|
-
# http://reference.wolfram.com/language/guide/MathematicalAndCountingOperationsOnLists.html
|
252
|
-
|
253
551
|
end
|
254
552
|
|
255
|
-
# http://reference.wolfram.com/language/guide/FunctionalProgramming.html
|
256
|
-
|
257
553
|
end
|
258
554
|
|
259
|
-
|
260
|
-
|
555
|
+
# TODO http://reference.wolfram.com/language/guide/HandlingArraysOfData.html
|
556
|
+
# TODO http://reference.wolfram.com/language/guide/ComputationWithStructuredDatasets.html
|
557
|
+
|
558
|
+
__END__
|
559
|
+
|
560
|
+
Table Array
|
561
|
+
Times Product
|
562
|
+
Plus Total Sum?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mll
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Maslov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|