mll 0.3.0 → 0.4.0
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 +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
|