skn_utils 3.3.4 → 3.3.5
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/bin/bench_linklists.rb +74 -0
- data/bin/{benchmark.rb → bench_nested_result.rb} +15 -51
- data/lib/skn_utils/lists/circular_linked_list.rb +99 -46
- data/lib/skn_utils/lists/doubly_linked_list.rb +42 -8
- data/lib/skn_utils/lists/link_node.rb +8 -8
- data/lib/skn_utils/lists/linked_list.rb +34 -12
- data/lib/skn_utils/version.rb +1 -1
- data/spec/lib/skn_utils/lists/Circular_linked_list_spec.rb +165 -258
- data/spec/lib/skn_utils/lists/doubly_linked_list_spec.rb +165 -260
- data/spec/lib/skn_utils/lists/linked_list_spec.rb +145 -260
- data/spec/spec_helper.rb +1 -0
- data/spec/support/shared_examples_for_linked_list.rb +156 -0
- metadata +6 -3
@@ -2,275 +2,180 @@
|
|
2
2
|
# spec/lib/skn_utils/doubly_linked_list_spec.rb
|
3
3
|
#
|
4
4
|
|
5
|
+
require "support/shared_examples_for_linked_list"
|
6
|
+
|
5
7
|
RSpec.describe SknUtils::Lists::DoublyLinkedList, "Double-Ended LinkedList " do
|
6
8
|
|
7
|
-
|
8
|
-
it "can be initialized without params" do
|
9
|
-
expect(subject).to be
|
10
|
-
end
|
11
|
-
it "can insert the first value" do
|
12
|
-
expect(subject.empty?).to be true
|
13
|
-
expect(subject.insert(101)).to eq(1)
|
14
|
-
end
|
15
|
-
it "can be cleared" do
|
16
|
-
subject.insert(101)
|
17
|
-
expect(subject.clear).to eq(1)
|
18
|
-
end
|
19
|
-
it "can be initialized with one or more initial values" do
|
20
|
-
list = described_class.new(10,100,100)
|
21
|
-
expect(list.current).to eq(10)
|
22
|
-
end
|
23
|
-
it "is initially empty?" do
|
24
|
-
expect(subject.empty?).to be true
|
25
|
-
end
|
26
|
-
end
|
9
|
+
it_behaves_like "a linked list", 'double'
|
27
10
|
|
28
|
-
context "
|
29
|
-
let(:list) { described_class.new(10,20, 30, 40, 50, 60, 70, 80, 90, 100) }
|
11
|
+
context "DoublyLinkedList Specific" do
|
30
12
|
|
31
|
-
|
32
|
-
|
33
|
-
end
|
34
|
-
it "#next returns the second value" do
|
35
|
-
expect(list.first).to eq(10)
|
36
|
-
expect(list.next).to eq(20)
|
37
|
-
end
|
38
|
-
it "#current returns the first value" do
|
39
|
-
expect(list.current).to eq(10)
|
40
|
-
end
|
41
|
-
it "#prev returns the prior value" do
|
42
|
-
expect(list.prev).to eq(10)
|
43
|
-
end
|
44
|
-
it "#last returns the last value" do
|
45
|
-
expect(list.last).to eq(100)
|
46
|
-
end
|
47
|
-
it "#nth(6) returns the sixth value" do
|
48
|
-
expect(list.first).to eq(10)
|
49
|
-
expect(list.nth(6)).to eq(60)
|
50
|
-
expect(list.nth(-2)).to eq(40)
|
51
|
-
end
|
52
|
-
it "#at_index(6) returns the sixth value" do
|
53
|
-
expect(list.at_index(6)).to eq(60)
|
54
|
-
end
|
13
|
+
context "Navigation" do
|
14
|
+
let(:list) { described_class.new(10,20, 30, 40, 50, 60, 70, 80, 90, 100) }
|
55
15
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
it "#append(value) indicates a value was added" do
|
67
|
-
bsize = subject.size
|
68
|
-
expect(subject.append(110)).to eq(bsize + 1)
|
69
|
-
end
|
70
|
-
it "#insert_before(pvalue,value) indicates a value was added" do
|
71
|
-
subject.insert(120)
|
72
|
-
bsize = subject.size
|
73
|
-
expect(subject.insert_before(120, 110)).to eq(bsize + 1)
|
74
|
-
expect(subject.to_a).to eq([110,120])
|
75
|
-
end
|
76
|
-
it "#insert_after(value) indicates a value was added" do
|
77
|
-
subject.insert(120)
|
78
|
-
bsize = subject.size
|
79
|
-
expect(subject.insert_after(120, 125)).to eq(bsize + 1)
|
80
|
-
expect(subject.to_a).to eq([120,125])
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
context "Removals" do
|
85
|
-
let(:list) { described_class.new(10,20, 30, 40, 50, 60, 70, 80, 90, 100) }
|
86
|
-
|
87
|
-
it "#remove(value) removes first occurance of that value" do
|
88
|
-
bsize = list.size
|
89
|
-
expect(list.remove(30)).to eq(bsize - 1)
|
90
|
-
expect(list.to_a).to eq([10,20, 40, 50, 60, 70, 80, 90, 100])
|
16
|
+
it "#prev returns the prior value" do
|
17
|
+
expect(list.prev).to eq(10)
|
18
|
+
end
|
19
|
+
it "#nth(6) returns the sixth value" do
|
20
|
+
expect(list.nth(6)).to eq(60)
|
21
|
+
expect(list.nth(-2)).to eq(40)
|
22
|
+
end
|
23
|
+
it "#at_index(6) returns the sixth value" do
|
24
|
+
expect(list.at_index(6)).to eq(60)
|
25
|
+
end
|
91
26
|
end
|
92
27
|
|
93
|
-
|
94
|
-
|
95
|
-
expect(list.empty?).to be true
|
96
|
-
end
|
97
|
-
end
|
28
|
+
context "Edge cases " do
|
29
|
+
let(:list) { described_class.new(10,20, 30, 40, 50, 60, 70, 80, 90, 100) }
|
98
30
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
31
|
+
it "#at_index(-999) fails and returns the current element. " do
|
32
|
+
expect(list.at_index(-999)).to eq(10)
|
33
|
+
end
|
34
|
+
it "#at_index(0) fails and returns the current element. " do
|
35
|
+
expect(list.at_index(0)).to eq(10)
|
36
|
+
end
|
37
|
+
it "#at_index(999) fails and returns the current element. " do
|
38
|
+
expect(list.at_index(999)).to eq(10)
|
39
|
+
end
|
40
|
+
it "#at_index(n) returns the proper element. " do
|
41
|
+
expect(list.at_index(1)).to eq(10)
|
42
|
+
expect(list.at_index(list.size / 2)).to eq(50)
|
43
|
+
expect(list.at_index(list.size)).to eq(100)
|
44
|
+
end
|
45
|
+
it "#at_index(n) returns the proper element for linkedlist with one element. " do
|
46
|
+
only = described_class.new(55)
|
47
|
+
expect(only.at_index(1)).to eq(55)
|
48
|
+
expect(only.at_index(10)).to eq(55)
|
49
|
+
expect(only.at_index(-10)).to eq(55)
|
50
|
+
end
|
117
51
|
|
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
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
{key: 'z'}, {key: 'k'}, {key: 'N'}, {key: 'o'}, {key: 'A'}
|
246
|
-
) {|a| a[:key]}
|
247
|
-
}
|
248
|
-
|
249
|
-
it "#sort! redefines numeric list in asending order" do
|
250
|
-
expect(num_list.sort!).to eq(11)
|
251
|
-
expect(num_list.to_a).to eq([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110])
|
252
|
-
end
|
253
|
-
it "#sort!(:desc) redefines numeric list in descending order" do
|
254
|
-
expect(num_list.sort!(:desc)).to eq(11)
|
255
|
-
expect(num_list.to_a).to eq([110, 100, 90, 80, 70, 60, 50, 40, 30, 20, 10])
|
256
|
-
end
|
257
|
-
it "#sort! redefines alpha numeric list in asending order" do
|
258
|
-
expect(alpha_list.sort!).to eq(10)
|
259
|
-
expect(alpha_list.to_a).to eq(["A", "K", "N", "S", "Z", "k", "n", "o", "s", "z"])
|
260
|
-
end
|
261
|
-
it "#sort!(:desc) redefines alpha numeric list in descending order" do
|
262
|
-
expect(alpha_list.sort!(:desc)).to eq(10)
|
263
|
-
expect(alpha_list.to_a).to eq(["z", "s", "o", "n", "k", "Z", "S", "N", "K", "A"])
|
264
|
-
end
|
265
|
-
it "#sort!() redefines hash object values in default order" do
|
266
|
-
expect(hash_list.sort!).to eq(10)
|
267
|
-
expect(hash_list.to_a).to eq([{:key=>"A"}, {:key=>"K"}, {:key=>"N"}, {:key=>"S"}, {:key=>"Z"},
|
268
|
-
{:key=>"k"}, {:key=>"n"}, {:key=>"o"}, {:key=>"s"}, {:key=>"z"}])
|
269
|
-
end
|
270
|
-
it "#sort!() lambda overrides sort_condifiton and sorts hash object values in custom order" do
|
271
|
-
expect(hash_list.sort!() {|a,b| a[:key] <= b[:key] }).to eq(10)
|
272
|
-
expect(hash_list.to_a).to eq([{:key=>"z"}, {:key=>"s"}, {:key=>"o"}, {:key=>"n"}, {:key=>"k"},
|
273
|
-
{:key=>"Z"}, {:key=>"S"}, {:key=>"N"}, {:key=>"K"}, {:key=>"A"}])
|
52
|
+
it "#nth(-999) returns first initialization value." do
|
53
|
+
expect(list.nth(-999)).to eq(10)
|
54
|
+
end
|
55
|
+
it "#nth(0) returns current value, or last initialization value." do
|
56
|
+
expect(list.nth(0)).to eq(10)
|
57
|
+
end
|
58
|
+
it "#nth(999) returns last initialization value." do
|
59
|
+
expect(list.nth(999)).to eq(100)
|
60
|
+
end
|
61
|
+
it "#current equals first initialization value." do
|
62
|
+
expect(list.current).to eq(10)
|
63
|
+
end
|
64
|
+
it "#next after initialization equals last initialization value. " do
|
65
|
+
expect(list.next).to eq(20)
|
66
|
+
expect(list.next).to eq(30)
|
67
|
+
expect(list.next).to eq(40)
|
68
|
+
end
|
69
|
+
it "#prev after first returns first value repeatably. " do
|
70
|
+
expect(list.first).to eq(10)
|
71
|
+
expect(list.prev).to eq(10)
|
72
|
+
expect(list.prev).to eq(10)
|
73
|
+
end
|
74
|
+
it "#first, #next, #current, #prev, #nth, and #last return same value after initialization with one value. " do
|
75
|
+
only = described_class.new(55)
|
76
|
+
expect(only.first).to eq(55)
|
77
|
+
expect(only.next).to eq(55)
|
78
|
+
expect(only.prev).to eq(55)
|
79
|
+
expect(only.last).to eq(55)
|
80
|
+
expect(only.current).to eq(55)
|
81
|
+
expect(only.nth(1)).to eq(55)
|
82
|
+
expect(only.nth(11)).to eq(55)
|
83
|
+
end
|
84
|
+
it "#first, #next, #current, #prev, #nth, and #last return same value after initialization with no values. " do
|
85
|
+
only = described_class.new
|
86
|
+
expect(only.first).to be nil
|
87
|
+
expect(only.next).to be nil
|
88
|
+
expect(only.prev).to be nil
|
89
|
+
expect(only.last).to be nil
|
90
|
+
expect(only.current).to be nil
|
91
|
+
expect(only.nth(1)).to be nil
|
92
|
+
expect(only.nth(-1)).to be nil
|
93
|
+
end
|
94
|
+
it "#prepend enables navigation methods normal operations. " do
|
95
|
+
only = described_class.new
|
96
|
+
only.prepend(55)
|
97
|
+
expect(only.first).to eq(55)
|
98
|
+
expect(only.next).to eq(55)
|
99
|
+
expect(only.prev).to eq(55)
|
100
|
+
expect(only.last).to eq(55)
|
101
|
+
expect(only.current).to eq(55)
|
102
|
+
expect(only.nth(1)).to eq(55)
|
103
|
+
expect(only.nth(11)).to eq(55)
|
104
|
+
end
|
105
|
+
it "#append enables navigation methods normal operations. " do
|
106
|
+
only = described_class.new
|
107
|
+
only.append(55)
|
108
|
+
expect(only.first).to eq(55)
|
109
|
+
expect(only.next).to eq(55)
|
110
|
+
expect(only.prev).to eq(55)
|
111
|
+
expect(only.last).to eq(55)
|
112
|
+
expect(only.current).to eq(55)
|
113
|
+
expect(only.nth(1)).to eq(55)
|
114
|
+
expect(only.nth(11)).to eq(55)
|
115
|
+
end
|
116
|
+
it "#insert_before enables navigation methods normal operations. " do
|
117
|
+
only = described_class.new
|
118
|
+
only.insert_before(nil, 55)
|
119
|
+
expect(only.first).to eq(55)
|
120
|
+
expect(only.next).to eq(55)
|
121
|
+
expect(only.prev).to eq(55)
|
122
|
+
expect(only.last).to eq(55)
|
123
|
+
expect(only.current).to eq(55)
|
124
|
+
expect(only.nth(1)).to eq(55)
|
125
|
+
expect(only.nth(11)).to eq(55)
|
126
|
+
end
|
127
|
+
it "#insert_after enables navigation methods normal operations. " do
|
128
|
+
only = described_class.new
|
129
|
+
only.insert_after(nil, 55)
|
130
|
+
expect(only.first).to eq(55)
|
131
|
+
expect(only.next).to eq(55)
|
132
|
+
expect(only.prev).to eq(55)
|
133
|
+
expect(only.last).to eq(55)
|
134
|
+
expect(only.current).to eq(55)
|
135
|
+
expect(only.nth(1)).to eq(55)
|
136
|
+
expect(only.nth(11)).to eq(55)
|
137
|
+
end
|
138
|
+
it "#remove does not make navigation methods unstable when removing 2:2. " do
|
139
|
+
only = described_class.new(55,60)
|
140
|
+
only.remove(60)
|
141
|
+
expect(only.to_a).to eq([55])
|
142
|
+
expect(only.first).to eq(55)
|
143
|
+
expect(only.next).to eq(55)
|
144
|
+
expect(only.last).to eq(55)
|
145
|
+
expect(only.current).to eq(55)
|
146
|
+
expect(only.nth(2)).to eq(55)
|
147
|
+
expect(only.at_index(2)).to eq(55)
|
148
|
+
end
|
149
|
+
it "#remove does not make navigation methods unstable when removing 1:2. " do
|
150
|
+
only = described_class.new(55,60)
|
151
|
+
only.remove(55)
|
152
|
+
expect(only.first).to eq(60)
|
153
|
+
expect(only.next).to eq(60)
|
154
|
+
expect(only.last).to eq(60)
|
155
|
+
expect(only.current).to eq(60)
|
156
|
+
expect(only.nth(2)).to eq(60)
|
157
|
+
expect(only.at_index(2)).to eq(60)
|
158
|
+
end
|
159
|
+
it "#remove does not make navigation methods unstable if empty?. " do
|
160
|
+
only = described_class.new(55)
|
161
|
+
only.remove(55)
|
162
|
+
expect(only.first).to be nil
|
163
|
+
expect(only.next).to be nil
|
164
|
+
expect(only.last).to be nil
|
165
|
+
expect(only.current).to be nil
|
166
|
+
expect(only.nth(2)).to be nil
|
167
|
+
expect(only.at_index(2)).to be nil
|
168
|
+
end
|
169
|
+
it "#remove does not make navigation methods unstable when target not found. " do
|
170
|
+
only = described_class.new(55)
|
171
|
+
only.remove(20)
|
172
|
+
expect(only.first).to eq(55)
|
173
|
+
expect(only.next).to eq(55)
|
174
|
+
expect(only.last).to eq(55)
|
175
|
+
expect(only.current).to eq(55)
|
176
|
+
expect(only.nth(2)).to eq(55)
|
177
|
+
expect(only.at_index(2)).to eq(55)
|
178
|
+
end
|
274
179
|
end
|
275
180
|
end
|
276
181
|
|