skn_utils 3.3.4 → 3.3.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8fc867ac95eebf226b53be3336ddf721265150d4
4
- data.tar.gz: a70380b703cd8f20d25b314f7710720788953669
3
+ metadata.gz: 84cb7bcd483e3369c94109704c491658263a497d
4
+ data.tar.gz: 0fefb9e19e864638acfeaa605dd315e12db33a0c
5
5
  SHA512:
6
- metadata.gz: 5a72919f92f6e597edec5bedb80beece8a45b68741471e3c9e422ca6a572b6029e023b226ecd26966f27706653426d772737bdca241c0072f525802145588b07
7
- data.tar.gz: b7f22a691d0c272dc4d48ae92713bbf73ededd4666994d04ec3ee1d6e463cbf86598f0833e619007eed81251624baea8c3fe87342987a67ca0a0703b17d1a087
6
+ metadata.gz: 66f1414ed28fae1ab9e2701c6d21590e9ea463303964c23de9ffd0f3eabe5df701bc18bb6cceb9c98752d353038d79bbffb97909d1dd447c683eeafc88c9cb12
7
+ data.tar.gz: 3552bd034096bc4c60f339082af9a22f09bfe57e4c53b589507306e3e190e7598a5b765da62f7ad561fa5270df14652f6272d9d939359c32901cc10802c54abe
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # Ref: https://github.com/evanphx/benchmark-ips
5
+ #
6
+
7
+ require 'bundler/setup'
8
+ require 'skn_utils'
9
+ require 'ostruct'
10
+ require 'benchmark/ips'
11
+
12
+ class GCSuite
13
+ def warming(*)
14
+ run_gc
15
+ end
16
+
17
+ def running(*)
18
+ run_gc
19
+ end
20
+
21
+ def warmup_stats(*)
22
+ end
23
+
24
+ def add_report(*)
25
+ end
26
+
27
+ private
28
+
29
+ def run_gc
30
+ GC.enable
31
+ GC.start
32
+ GC.disable
33
+ end
34
+ end
35
+
36
+ suite = GCSuite.new
37
+
38
+ # Warming up --------------------------------------
39
+ # LinkedList Ops 2.297k i/100ms
40
+ # Array Ops 34.468k i/100ms
41
+ # Calculating -------------------------------------
42
+ # LinkedList Ops 17.015k (±35.2%) i/s - 71.207k in 5.100193s
43
+ # Array Ops 377.943k (± 7.3%) i/s - 1.896M in 5.048217s
44
+ #
45
+ # Comparison:
46
+ # Array Ops: 377942.7 i/s
47
+ # LinkedList Ops: 17015.4 i/s - 22.21x slower
48
+
49
+
50
+ Benchmark.ips do |x|
51
+ x.config(:suite => suite)
52
+
53
+ adders = [50, 10, 110, 6, 30, 101, 12, 33, 4]
54
+ vargs = [70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
55
+ cproc = lambda {|a| a}
56
+
57
+ x.report('LinkedList Ops') do
58
+ ll = SknUtils::Lists::LinkedList.new(*vargs, &cproc)
59
+ adders.each {|x| ll.insert_after(74, x)}
60
+ value = ll.sort!
61
+ ll.first
62
+ ll.clear
63
+ end
64
+
65
+ x.report('Array Ops') do
66
+ ary = Array.new(vargs)
67
+ adders.each {|x| ary.insert(5, x)}
68
+ value = ary.sort!
69
+ ary.first
70
+ ary.clear
71
+ end
72
+
73
+ x.compare!
74
+ end
@@ -35,6 +35,21 @@ end
35
35
 
36
36
  suite = GCSuite.new
37
37
 
38
+ # Warming up --------------------------------------
39
+ # regular class 179.755k i/100ms
40
+ # OpenStruct class 11.367k i/100ms
41
+ # NestedResult class 9.674k i/100ms
42
+ # Calculating -------------------------------------
43
+ # regular class 3.674M (±17.4%) i/s - 17.256M in 5.001576s
44
+ # OpenStruct class 155.394k (±31.2%) i/s - 670.653k in 5.095404s
45
+ # NestedResult class 119.896k (±39.0%) i/s - 493.374k in 5.212147s
46
+ #
47
+ # Comparison:
48
+ # regular class: 3673640.5 i/s
49
+ # OpenStruct class: 155394.0 i/s - 23.64x slower
50
+ # NestedResult class: 119896.1 i/s - 30.64x slower
51
+ #
52
+
38
53
  Benchmark.ips do |x|
39
54
  x.config(:suite => suite)
40
55
 
@@ -65,54 +80,3 @@ Benchmark.ips do |x|
65
80
 
66
81
  x.compare!
67
82
  end
68
-
69
- # Warming up --------------------------------------
70
- # regular class 179.755k i/100ms
71
- # OpenStruct class 11.367k i/100ms
72
- # NestedResult class 9.674k i/100ms
73
- # Calculating -------------------------------------
74
- # regular class 3.674M (±17.4%) i/s - 17.256M in 5.001576s
75
- # OpenStruct class 155.394k (±31.2%) i/s - 670.653k in 5.095404s
76
- # NestedResult class 119.896k (±39.0%) i/s - 493.374k in 5.212147s
77
- #
78
- # Comparison:
79
- # regular class: 3673640.5 i/s
80
- # OpenStruct class: 155394.0 i/s - 23.64x slower
81
- # NestedResult class: 119896.1 i/s - 30.64x slower
82
- #
83
- # Warming up --------------------------------------
84
- # LinkedList Ops 2.297k i/100ms
85
- # Array Ops 34.468k i/100ms
86
- # Calculating -------------------------------------
87
- # LinkedList Ops 17.015k (±35.2%) i/s - 71.207k in 5.100193s
88
- # Array Ops 377.943k (± 7.3%) i/s - 1.896M in 5.048217s
89
- #
90
- # Comparison:
91
- # Array Ops: 377942.7 i/s
92
- # LinkedList Ops: 17015.4 i/s - 22.21x slower
93
-
94
-
95
- Benchmark.ips do |x|
96
- x.config(:suite => suite)
97
-
98
- adders = [50, 10, 110, 6, 30, 101, 12, 33, 4]
99
- vargs = [70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
100
-
101
- x.report('LinkedList Ops') do
102
- ll = SknUtils::Lists::LinkedList.new(*vargs)
103
- adders.each {|x| ll.insert_after(74, x)}
104
- value = ll.sort!
105
- ll.first
106
- ll.clear
107
- end
108
-
109
- x.report('Array Ops') do
110
- ary = Array.new(vargs)
111
- adders.each {|x| ary.insert(5, x)}
112
- value = ary.sort!
113
- ary.first
114
- ary.clear
115
- end
116
-
117
- x.compare!
118
- end
@@ -1,3 +1,26 @@
1
+ ##
2
+ # File <SknUtils>/lib/skn_utils/lists/circular_linked_list.rb
3
+ #
4
+ # ll = SknUtils::Lists::CircularLinkedList.new(*vargs, &compare_key_proc)
5
+ # - or -
6
+ # ll = SknUtils::Lists::CircularLinkedList.new(1,2,3,4,5) {|element| element[:key] }
7
+ # - or -
8
+ # ll = SknUtils::Lists::CircularLinkedList.new(
9
+ # {key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'}
10
+ # ) {|el| el[:key] }
11
+ # - or -
12
+ # cmp_proc = lambda { |el| el[:key] }
13
+ # vargs = [{key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'}]
14
+ # ll = SknUtils::Lists::CircularLinkedList.new(*vargs, &cmp_proc)
15
+ ###
16
+ # value = ll.first
17
+ # value = ll.at_index(4)
18
+ # count = ll.insert({key: 'anyValue'})
19
+ # ...
20
+ # count = ll.sort! -- defaults to :asc
21
+ # count = ll.sort!(:desc)
22
+ # count = ll.sort!() {|a,b| a[:key] <= b[:key] }
23
+ ##
1
24
 
2
25
  module SknUtils
3
26
  module Lists
@@ -29,7 +52,7 @@ module SknUtils
29
52
  # return values and position current to last node accessed
30
53
  # prevent @current from nil assignment
31
54
  def first
32
- @current = head if head
55
+ @current = self.head if self.head
33
56
  @current.value rescue nil
34
57
  end
35
58
 
@@ -48,7 +71,7 @@ module SknUtils
48
71
  end
49
72
 
50
73
  def last
51
- @current = tail if tail
74
+ @current = self.tail if self.tail
52
75
  @current.value rescue nil
53
76
  end
54
77
 
@@ -81,7 +104,7 @@ module SknUtils
81
104
  end
82
105
 
83
106
  def empty?
84
- size == 0
107
+ self.size == 0
85
108
  end
86
109
 
87
110
  #
@@ -96,12 +119,12 @@ module SknUtils
96
119
 
97
120
  # return new size
98
121
  def prepend(value)
99
- temp = head.value rescue nil
122
+ temp = self.head.value rescue nil
100
123
  insert_before(temp, value)
101
124
  end
102
125
  # return new size
103
126
  def append(value)
104
- temp = tail.value rescue nil
127
+ temp = self.tail.value rescue nil
105
128
  insert_after(temp, value)
106
129
  end
107
130
 
@@ -109,9 +132,19 @@ module SknUtils
109
132
  def insert_before(position_value, value)
110
133
  target = find_by_value(position_value)
111
134
  node = LinkNode.new(value, target, :circle_before, &@match_value)
112
- @current = node if target
113
- self.head = node if head === target
114
- self.tail = node if tail.nil?
135
+ @current = node
136
+ if self.size == 0 # only
137
+ self.head = node
138
+ self.tail = node
139
+ elsif self.head == target # new head
140
+ self.head = node
141
+ node.prev = self.tail
142
+ self.tail.next = node
143
+ elsif self.tail == target
144
+ self.tail = node
145
+ node.next = self.head
146
+ self.head.prev = node
147
+ end
115
148
  self.size += 1
116
149
  end
117
150
 
@@ -120,8 +153,18 @@ module SknUtils
120
153
  target = find_by_value(position_value)
121
154
  node = LinkNode.new(value, target, :circle_after, &@match_value)
122
155
  @current = node
123
- self.head = node if head.nil?
124
- self.tail = node if tail === target
156
+ if self.size == 0 # only
157
+ self.head = node
158
+ self.tail = node
159
+ elsif self.tail == target
160
+ self.tail = node
161
+ node.next = self.head
162
+ self.head.prev = node
163
+ elsif self.head == target # new head
164
+ self.head = node
165
+ node.prev = self.tail
166
+ self.tail.next = node
167
+ end
125
168
  self.size += 1
126
169
  end
127
170
 
@@ -129,25 +172,40 @@ module SknUtils
129
172
  def remove(value)
130
173
  target_node = find_by_value(value)
131
174
  if target_node
132
- @current = target_node.prev
133
- @current.next = target_node.next
134
- @current.next.prev = @current if @current and @current.next and @current.next.prev
175
+ if self.size == 1 # will become zero
176
+ @current = nil
177
+ self.head = nil
178
+ self.tail = nil
179
+ elsif target_node === self.head # top
180
+ @current = target_node.next
181
+ @current.prev = target_node.prev
182
+ self.tail.next = @current
183
+ self.head = @current
184
+ elsif target_node === self.tail # bottom
185
+ @current = target_node.prev
186
+ @current.next = target_node.next
187
+ self.head.prev = @current
188
+ self.tail = @current
189
+ else # middle
190
+ @current = target_node.prev
191
+ @current.next = target_node.next
192
+ @current.next.prev = @current
193
+ end
135
194
  target_node.remove!
195
+ self.size -= 1
136
196
  end
137
- self.tail = @current if tail === target_node
138
- self.head = @current if head === target_node
139
- self.size -= 1
140
197
  end
141
198
 
199
+
142
200
  # return number cleared
143
201
  def clear
144
202
  rc = 0
145
- node = head
146
- position = head
203
+ node = self.head
204
+ position = node
147
205
  while node do
148
206
  node = node.remove!
149
207
  rc += 1
150
- break if position === node
208
+ break if position.equal?(node)
151
209
  end
152
210
 
153
211
  @current = nil
@@ -163,8 +221,8 @@ module SknUtils
163
221
 
164
222
  # perform each() or return enumerator
165
223
  def each(&block)
166
- @current = head
167
- position = head
224
+ @current = self.head
225
+ position = self.head
168
226
  if block_given?
169
227
  while position do
170
228
  block.call( position.value.dup )
@@ -184,13 +242,13 @@ module SknUtils
184
242
 
185
243
  # convert self to a value array
186
244
  def to_a
187
- @current = head
188
- position = head
245
+ @current = self.head
246
+ position = self.head
189
247
  result = []
190
248
  while position do
191
249
  result << position.value.dup
192
250
  position = position.next
193
- break if position === @current
251
+ break if position.equal?(@current)
194
252
  end
195
253
  result
196
254
  end
@@ -206,33 +264,34 @@ module SknUtils
206
264
  else
207
265
  @sort_condition
208
266
  end
209
- sorted = merge_sort(to_a)
267
+ sorted = merge_sort(self.to_a)
210
268
  clear
211
269
  sorted.each {|item| insert(item) }
212
- size
270
+ self.size
213
271
  end
214
272
 
215
- private
273
+ protected
216
274
 
217
275
  attr_accessor :head, :tail
218
276
 
219
277
  def find_by_value(value)
220
- return nil if head.nil? or value.nil? or size == 0
221
- prior = head
222
- target = prior
223
- while target and not target.match_by_value(value)
224
- prior = target
225
- target = prior.next
226
- @current = target if target
278
+ return nil if value.nil? || self.size == 0
279
+ stop_node = self.head
280
+ target = stop_node
281
+ rtn_node = nil
282
+ while !target.match_by_value(value)
283
+ target = target.next
284
+ break if stop_node.equal?(target)
227
285
  end
286
+ target = nil unless target.match_by_value(value)
228
287
  target
229
288
  end
230
289
 
231
290
  def find_by_index(index)
232
- return nil if head.nil? or index < 1 or index > size
233
- node = head
234
- node = node.next while ((index -= 1) > 0 and node.next)
235
- @current = node if node
291
+ return nil if ( index > self.size || index < 1 )
292
+ node = self.head
293
+ node = node.next while ( (index -= 1) > 0 )
294
+ @current = node
236
295
  node
237
296
  end
238
297
 
@@ -240,26 +299,20 @@ module SknUtils
240
299
  # arr is Array to be sorted, sort_cond is Proc expecting a/b params returning true/false
241
300
  def merge_sort(arr)
242
301
  return arr if arr.size < 2
243
-
244
302
  middle = arr.size / 2
245
-
246
- left = merge_sort(arr[0...middle])
247
- right = merge_sort(arr[middle..arr.size])
248
-
303
+ left = merge_sort(arr[0...middle])
304
+ right = merge_sort(arr[middle..arr.size])
249
305
  merge(left, right)
250
306
  end
251
307
 
252
308
  def merge(left, right)
253
309
  sorted = []
254
-
255
310
  while left.any? && right.any?
256
-
257
311
  if @active_sort_condition.call(left.first, right.first)
258
312
  sorted.push right.shift
259
313
  else
260
314
  sorted.push left.shift
261
315
  end
262
-
263
316
  end
264
317
 
265
318
  sorted + left + right
@@ -1,3 +1,26 @@
1
+ ##
2
+ # File <SknUtils>/lib/skn_utils/lists/doubly_linked_list.rb
3
+ #
4
+ # ll = SknUtils::Lists::DoublyLinkedList.new(*vargs, &compare_key_proc)
5
+ # - or -
6
+ # ll = SknUtils::Lists::DoublyLinkedList.new(1,2,3,4,5) {|element| element[:key] }
7
+ # - or -
8
+ # ll = SknUtils::Lists::DoublyLinkedList.new(
9
+ # {key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'}
10
+ # ) {|el| el[:key] }
11
+ # - or -
12
+ # cmp_proc = lambda { |el| el[:key] }
13
+ # vargs = [{key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'}]
14
+ # ll = SknUtils::Lists::DoublyLinkedList.new(*vargs, &cmp_proc)
15
+ ###
16
+ # value = ll.first
17
+ # value = ll.at_index(4)
18
+ # count = ll.insert({key: 'anyValue'})
19
+ # ...
20
+ # count = ll.sort! -- defaults to :asc
21
+ # count = ll.sort!(:desc)
22
+ # count = ll.sort!() {|a,b| a[:key] <= b[:key] }
23
+ ##
1
24
 
2
25
  module SknUtils
3
26
  module Lists
@@ -127,14 +150,26 @@ module SknUtils
127
150
  def remove(value)
128
151
  target_node = find_by_value(value)
129
152
  if target_node
130
- @current = target_node.prev if target_node.prev
131
- @current.next = target_node.next if target_node.next
132
- @current.next.prev = @current if @current and @current.next and @current.next.prev
153
+ if size == 1 # will become zero
154
+ @current = nil
155
+ self.head = nil
156
+ self.tail = nil
157
+ elsif target_node.prev.nil? # top
158
+ @current = target_node.next
159
+ @current.prev = nil
160
+ self.head = @current
161
+ elsif target_node.next.nil? # bottom
162
+ @current = target_node.prev
163
+ @current.next = nil
164
+ self.tail = @current
165
+ else # middle
166
+ @current = target_node.prev
167
+ @current.next = target_node.next
168
+ target_node.next.prev = @current
169
+ end
133
170
  target_node.remove!
171
+ self.size -= 1
134
172
  end
135
- self.tail = @current if tail === target_node
136
- self.head = @current if head === target_node
137
- self.size -= 1
138
173
  end
139
174
 
140
175
  # return number cleared
@@ -215,13 +250,12 @@ module SknUtils
215
250
  attr_accessor :head, :tail
216
251
 
217
252
  def find_by_value(value)
218
- return nil if head.nil? or value.nil?
253
+ return nil if head.nil? || value.nil? || size == 0
219
254
  prior = head
220
255
  target = prior
221
256
  while target and not target.match_by_value(value)
222
257
  prior = target
223
258
  target = prior.next
224
- @current = target if target
225
259
  end
226
260
  target
227
261
  end
@@ -16,26 +16,26 @@ module SknUtils
16
16
 
17
17
  case strategy
18
18
  when :single # after logic
19
- anchor_node.next = self if anchor_node
19
+ if anchor_node
20
+ @next = anchor_node.next
21
+ anchor_node.next = self
22
+ end
20
23
  when :before
21
24
  @prev = anchor_node.prev if anchor_node
22
- @next = anchor_node
23
25
  anchor_node.prev = self if anchor_node
26
+ @next = anchor_node
24
27
  when :after
25
- @prev = anchor_node
26
28
  @next = anchor_node.next if anchor_node
27
29
  anchor_node.next = self if anchor_node
28
- @next.prev = self if @next
30
+ @prev = anchor_node
29
31
  when :circle_before
30
32
  @prev = anchor_node ? anchor_node.prev : self
31
- @next = anchor_node ? anchor_node : self
32
33
  anchor_node.prev = self if anchor_node
33
- @prev.next = self if anchor_node
34
+ @next = anchor_node ? anchor_node : self
34
35
  when :circle_after
35
- @prev = anchor_node ? anchor_node : self
36
36
  @next = anchor_node ? anchor_node.next : self
37
37
  anchor_node.next = self if anchor_node
38
- @next.prev = self if anchor_node
38
+ @prev = anchor_node ? anchor_node : self
39
39
  end
40
40
  end
41
41
 
@@ -1,3 +1,26 @@
1
+ ##
2
+ # File <SknUtils>/lib/skn_utils/lists/linked_list.rb
3
+ #
4
+ # ll = SknUtils::Lists::LinkedList.new(*vargs, &compare_key_proc)
5
+ # - or -
6
+ # ll = SknUtils::Lists::LinkedList.new(1,2,3,4,5) {|element| element[:key] }
7
+ # - or -
8
+ # ll = SknUtils::Lists::LinkedList.new(
9
+ # {key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'}
10
+ # ) {|el| el[:key] }
11
+ # - or -
12
+ # cmp_proc = lambda { |el| el[:key] }
13
+ # vargs = [{key: 'Z'}, {key: 'K'}, {key: 'S'}, {key: 'n'}, {key: 's'}]
14
+ # ll = SknUtils::Lists::LinkedList.new(*vargs, &cmp_proc)
15
+ ###
16
+ # value = ll.first
17
+ # value = ll.at_index(4)
18
+ # count = ll.insert({key: 'anyValue'})
19
+ # ...
20
+ # count = ll.sort! -- defaults to :asc
21
+ # count = ll.sort!(:desc)
22
+ # count = ll.sort!() {|a,b| a[:key] <= b[:key] }
23
+ ##
1
24
 
2
25
  module SknUtils
3
26
  module Lists
@@ -50,7 +73,7 @@ module SknUtils
50
73
  @current.value rescue nil
51
74
  end
52
75
 
53
- # -+ int position from current node
76
+ # +int position from current node
54
77
  def nth(index)
55
78
  node = @current
56
79
  while index > 1 and node and node.next
@@ -60,8 +83,6 @@ module SknUtils
60
83
  end
61
84
  # no reverse or prev for Single List
62
85
  current
63
- rescue NoMethodError
64
- nil
65
86
  end
66
87
 
67
88
  # return node at positive index from head
@@ -119,10 +140,11 @@ module SknUtils
119
140
 
120
141
  # return remaining size
121
142
  def remove(value)
122
- @current, target_node = find_by_value(value)
123
- @current.next = target_node.remove!
124
- self.tail = @current.next if tail === target_node
125
- self.head = @current if head === target_node
143
+ prior, target_node = find_by_value(value)
144
+ @current = prior.nil? ? target_node.next : prior
145
+ @current.next = target_node.remove! if @current && target_node
146
+ self.tail = @current.next if @current && tail === target_node
147
+ self.head = @current.next if @current && head === target_node
126
148
  self.size -= 1
127
149
  end
128
150
 
@@ -203,19 +225,19 @@ module SknUtils
203
225
  attr_accessor :head, :tail
204
226
 
205
227
  def find_by_value(value)
206
- return [nil,nil] if head.nil? or value.nil?
207
- prior = head
228
+ return [@current, nil] if head.nil? || value.nil?
229
+ prior = head
208
230
  target = prior
209
231
  while target and not target.match_by_value(value)
210
232
  prior = target
211
- target = prior.next
212
- @current = target if target
233
+ target = target.next
234
+ @current = prior if target
213
235
  end
214
236
  [prior, target]
215
237
  end
216
238
 
217
239
  def find_by_index(index)
218
- return nil if head.nil? or index < 1 or index > size
240
+ return nil if head.nil? || index < 1 || index > size
219
241
  node = head
220
242
  node = node.next while ((index -= 1) > 0 and node.next)
221
243
  @current = node if node
@@ -3,7 +3,7 @@ module SknUtils
3
3
  class Version
4
4
  MAJOR = 3
5
5
  MINOR = 3
6
- PATCH = 4
6
+ PATCH = 5
7
7
 
8
8
  def self.to_s
9
9
  [MAJOR, MINOR, PATCH].join('.')