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,182 @@
|
|
2
2
|
# spec/lib/skn_utils/circular_linked_list_spec.rb
|
3
3
|
#
|
4
4
|
|
5
|
+
require "support/shared_examples_for_linked_list"
|
6
|
+
|
5
7
|
RSpec.describe SknUtils::Lists::CircularLinkedList, "Circular 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", 'circular'
|
27
10
|
|
28
|
-
context "
|
29
|
-
let(:list) { described_class.new(10,20, 30, 40, 50, 60, 70, 80, 90, 100) }
|
11
|
+
context "CircularLinkedList 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(100)
|
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])
|
16
|
+
it "#prev returns the prior value" do
|
17
|
+
expect(list.prev).to eq(100)
|
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
|
75
26
|
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
27
|
|
87
|
-
|
88
|
-
|
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])
|
91
|
-
end
|
28
|
+
context "Edge cases " do
|
29
|
+
let(:list) { described_class.new(10,20, 30, 40, 50, 60, 70, 80, 90, 100) }
|
92
30
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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(2)).to eq(55)
|
49
|
+
expect(only.at_index(10)).to eq(55)
|
50
|
+
end
|
98
51
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
expect(list.each).to be_a(Enumerator)
|
109
|
-
expect(list.each.first).to eq(10)
|
110
|
-
end
|
111
|
-
it "#to_a returns the contents of linkedlist as an Array" do
|
112
|
-
base = list.to_a
|
113
|
-
expect(base).to be_a(Array)
|
114
|
-
expect(base).to eq([10,20, 30, 40, 50, 60, 70, 80, 90, 100])
|
115
|
-
end
|
116
|
-
end
|
52
|
+
it "#nth(-999) fails and returns current value." do
|
53
|
+
expect(list.nth(-999)).to eq(10)
|
54
|
+
end
|
55
|
+
it "#nth(0) fails and returns current value." do
|
56
|
+
expect(list.nth(0)).to eq(10)
|
57
|
+
end
|
58
|
+
it "#nth(999) fails and returns current value." do
|
59
|
+
expect(list.nth(999)).to eq(10)
|
60
|
+
end
|
117
61
|
|
118
|
-
|
119
|
-
|
62
|
+
it "#current equals first initialization value." do
|
63
|
+
expect(list.current).to eq(10)
|
64
|
+
end
|
65
|
+
it "#next after initialization returns correctly. " do
|
66
|
+
expect(list.next).to eq(20)
|
67
|
+
expect(list.next).to eq(30)
|
68
|
+
expect(list.next).to eq(40)
|
69
|
+
end
|
70
|
+
it "#prev after first returns proper sequence of values. " do
|
71
|
+
expect(list.first).to eq(10)
|
72
|
+
expect(list.prev).to eq(100)
|
73
|
+
expect(list.prev).to eq(90)
|
74
|
+
end
|
120
75
|
|
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
|
-
expect(only.nth(11)).to eq(55)
|
227
|
-
end
|
228
|
-
it "#remove does not make navigation methods unstable if only element. " do
|
229
|
-
only = described_class.new(55)
|
230
|
-
only.remove(55)
|
231
|
-
expect(only.first).to be nil
|
232
|
-
expect(only.next).to be nil
|
233
|
-
expect(only.prev).to be nil
|
234
|
-
expect(only.last).to be nil
|
235
|
-
expect(only.current).to be nil
|
236
|
-
expect(only.nth(1)).to be nil
|
237
|
-
expect(only.nth(-1)).to be nil
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
context "Sort Feature" do
|
242
|
-
let(:num_list) { described_class.new(100, 50, 10, 40, 80, 30, 60, 90, 70, 20, 110) }
|
243
|
-
let(:alpha_list) { described_class.new('Z', 'K', 'S', 'n', 's', 'z', 'k', 'N', 'o', 'A') }
|
244
|
-
let(:hash_list) { described_class.new({key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'},
|
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"}])
|
76
|
+
it "#first, #next, #current, #prev, #nth, and #last return same value when size == 1. " do
|
77
|
+
only = described_class.new(55)
|
78
|
+
expect(only.first).to eq(55)
|
79
|
+
expect(only.next).to eq(55)
|
80
|
+
expect(only.prev).to eq(55)
|
81
|
+
expect(only.last).to eq(55)
|
82
|
+
expect(only.current).to eq(55)
|
83
|
+
expect(only.nth(2)).to eq(55)
|
84
|
+
expect(only.at_index(2)).to eq(55)
|
85
|
+
end
|
86
|
+
it "#first, #next, #current, #prev, #nth, and #last return nil value when size == 0. " do
|
87
|
+
only = described_class.new
|
88
|
+
expect(only.first).to be nil
|
89
|
+
expect(only.next).to be nil
|
90
|
+
expect(only.prev).to be nil
|
91
|
+
expect(only.last).to be nil
|
92
|
+
expect(only.current).to be nil
|
93
|
+
expect(only.nth(2)).to be nil
|
94
|
+
expect(only.at_index(2)).to be nil
|
95
|
+
end
|
96
|
+
it "#prepend enables navigation methods normal operations. " do
|
97
|
+
only = described_class.new
|
98
|
+
only.prepend(55)
|
99
|
+
expect(only.first).to eq(55)
|
100
|
+
expect(only.next).to eq(55)
|
101
|
+
expect(only.prev).to eq(55)
|
102
|
+
expect(only.last).to eq(55)
|
103
|
+
expect(only.current).to eq(55)
|
104
|
+
expect(only.nth(2)).to eq(55)
|
105
|
+
expect(only.at_index(2)).to eq(55)
|
106
|
+
end
|
107
|
+
it "#append enables navigation methods normal operations. " do
|
108
|
+
only = described_class.new
|
109
|
+
only.append(55)
|
110
|
+
expect(only.first).to eq(55)
|
111
|
+
expect(only.next).to eq(55)
|
112
|
+
expect(only.prev).to eq(55)
|
113
|
+
expect(only.last).to eq(55)
|
114
|
+
expect(only.current).to eq(55)
|
115
|
+
expect(only.nth(2)).to eq(55)
|
116
|
+
expect(only.at_index(2)).to eq(55)
|
117
|
+
end
|
118
|
+
it "#insert_before enables navigation methods normal operations. " do
|
119
|
+
only = described_class.new
|
120
|
+
only.insert_before(nil, 55)
|
121
|
+
expect(only.first).to eq(55)
|
122
|
+
expect(only.next).to eq(55)
|
123
|
+
expect(only.prev).to eq(55)
|
124
|
+
expect(only.last).to eq(55)
|
125
|
+
expect(only.current).to eq(55)
|
126
|
+
expect(only.nth(2)).to eq(55)
|
127
|
+
expect(only.at_index(2)).to eq(55)
|
128
|
+
end
|
129
|
+
it "#insert_after enables navigation methods normal operations. " do
|
130
|
+
only = described_class.new
|
131
|
+
only.insert_after(nil, 55)
|
132
|
+
expect(only.first).to eq(55)
|
133
|
+
expect(only.next).to eq(55)
|
134
|
+
expect(only.prev).to eq(55)
|
135
|
+
expect(only.last).to eq(55)
|
136
|
+
expect(only.current).to eq(55)
|
137
|
+
expect(only.nth(2)).to eq(55)
|
138
|
+
expect(only.at_index(2)).to eq(55)
|
139
|
+
end
|
140
|
+
it "#remove does not make navigation methods unstable when removing 2:2. " do
|
141
|
+
only = described_class.new(55,60)
|
142
|
+
only.remove(60)
|
143
|
+
expect(only.first).to eq(55)
|
144
|
+
expect(only.next).to eq(55)
|
145
|
+
expect(only.last).to eq(55)
|
146
|
+
expect(only.current).to eq(55)
|
147
|
+
expect(only.nth(2)).to eq(55)
|
148
|
+
expect(only.at_index(2)).to eq(55)
|
149
|
+
end
|
150
|
+
it "#remove does not make navigation methods unstable when removing 1:2. " do
|
151
|
+
only = described_class.new(55,60)
|
152
|
+
only.remove(55)
|
153
|
+
expect(only.first).to eq(60)
|
154
|
+
expect(only.next).to eq(60)
|
155
|
+
expect(only.last).to eq(60)
|
156
|
+
expect(only.current).to eq(60)
|
157
|
+
expect(only.nth(2)).to eq(60)
|
158
|
+
expect(only.at_index(2)).to eq(60)
|
159
|
+
end
|
160
|
+
it "#remove does not make navigation methods unstable if empty?. " do
|
161
|
+
only = described_class.new(55)
|
162
|
+
only.remove(55)
|
163
|
+
expect(only.first).to be nil
|
164
|
+
expect(only.next).to be nil
|
165
|
+
expect(only.last).to be nil
|
166
|
+
expect(only.current).to be nil
|
167
|
+
expect(only.nth(2)).to be nil
|
168
|
+
expect(only.at_index(2)).to be nil
|
169
|
+
end
|
170
|
+
it "#remove does not make navigation methods unstable when target not found. " do
|
171
|
+
only = described_class.new(55)
|
172
|
+
only.remove(20)
|
173
|
+
expect(only.to_a).to eq([55])
|
174
|
+
expect(only.first).to eq(55)
|
175
|
+
expect(only.next).to eq(55)
|
176
|
+
expect(only.last).to eq(55)
|
177
|
+
expect(only.current).to eq(55)
|
178
|
+
expect(only.nth(2)).to eq(55)
|
179
|
+
expect(only.at_index(2)).to eq(55)
|
180
|
+
end
|
274
181
|
end
|
275
182
|
end
|
276
183
|
|