algorithmix 0.0.0.6 → 0.0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4efe294f4271fb203ede5876ef848b259eeb2531
4
- data.tar.gz: 3e6a589d25b1c73d3eb1245fd1444d3f79a9cdde
3
+ metadata.gz: 9b841e761d3260e365f81e11db31b1b6454ec4a1
4
+ data.tar.gz: e2860c4117c02773f9c82e078c09b24a1d40fc2d
5
5
  SHA512:
6
- metadata.gz: 38ef94987b0f520489e445de1f159e87377ce5b75e35187ee68ea99f78102321df03ff526ed419bfe53bb7e44aa2c5207acb30d9d819f4b5a639189f8702078a
7
- data.tar.gz: 56a265a61cfdf1aa60a841a29c035ed9248702e7a85a86ab45cc0db70b5e5f411d5b97b9db6f802d8bdd9690b8f34bd44236675fc8798b663a788fff9c3d13f7
6
+ metadata.gz: 31b818c03e94ea46811e207321d98b1075f8f1a9895e00e491e6470c4cd53c5e1cbffd543b0f805e68c171ddd6667f54a40ef9b5c522aed428894d8962ff147d
7
+ data.tar.gz: ccfe3058e9a25562585e89b8aa03000e5f265e93383620952085eee61db18b44b63adfd3fb931eb5922bdc76b5908be6ae4376c09b66730e4384267890e4f26d
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Algorithmix
2
2
 
3
+ ![logo](https://github.com/monzita/algorithmix/blob/master/logo.png)
4
+
3
5
  ![Gem](https://img.shields.io/gem/v/algorithmix.svg?style=flat-square) ![Gem](https://img.shields.io/gem/dt/algorithmix.svg?style=flat-square) ![Gem](https://img.shields.io/gem/dtv/algorithmix.svg?style=flat-square) ![Gem download rank (daily)](https://img.shields.io/gem/rd/algorithmix.svg?style=flat-square) ![Gem download rank](https://img.shields.io/gem/rt/algorithmix.svg?style=flat-square) ![Travis (.org)](https://img.shields.io/travis/monzita/algorithmix.svg?style=flat-square)
4
6
 
5
7
  The gem contains various implementations of known and unknown data structures and algorithms.
@@ -9,7 +11,7 @@ The gem contains various implementations of known and unknown data structures an
9
11
  :construction: Because the gem is still not ready, with each new implementation of a data structure or an algorithm, a new
10
12
  minor version will be released.
11
13
 
12
- ![](https://img.shields.io/badge/min-0.0.0.6-green.svg) [**LinkedList**](https://github.com/monzita/algorithmix/wiki/LinkedList)
14
+ ![](https://img.shields.io/badge/min-0.0.0.7-green.svg) [**DoubleLinkedList**](https://github.com/monzita/algorithmix/wiki/DoubleLinkedList), LinkedList bug fixes.
13
15
 
14
16
  [**All versions**](https://github.com/monzita/algorithmix/wiki/Versions)
15
17
 
@@ -11,7 +11,8 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = %q{The gem contains various implementations of known and uknown data structures and algorithms}
12
12
  spec.description = <<-DOC
13
13
  The gem contains various implementations of known and uknown data structures and algorithms.
14
- /Currently the gem contains: #stack, #queue, #deque, #binary_heap, #priority_queue, #linked_list/
14
+ /Currently the gem contains: #stack, #queue, #deque, #binary_heap, #priority_queue, #linked_list,
15
+ #double_linked_list/
15
16
  DOC
16
17
  spec.homepage = "https://github.com/monzita/algorithmix/wiki"
17
18
  spec.license = "MIT"
@@ -0,0 +1,461 @@
1
+ # Documentation: https://github.com/monzita/algorithmix/wiki/LinkedList
2
+
3
+ module Algorithmix
4
+ module DataStructure
5
+ module Generic
6
+
7
+ class LinkedList
8
+ attr_reader :length, :size, :front
9
+
10
+ # Creates a new linked list object.
11
+ #
12
+ # @param obj [#to_a] any object which responds to to_a method
13
+ # @kwarg copy [true, false] If specified with true it will copy the given object. By default is set to false.
14
+ # @raise ArgumentError if given object doesn't respond to to_a method
15
+ # @return [LinkedList] a newly created linked list
16
+ def initialize(obj = nil, copy: false)
17
+ @length = @size = 0
18
+ @front = nil
19
+
20
+ obj.nil? ? nil : from_obj(obj, copy)
21
+ end
22
+
23
+ # Assigns a content of an object to content of the linked list, removing all previously inserted elements.
24
+ #
25
+ # @param obj [#to_a]
26
+ # @kwarg copy [true, false] If specified with true it will copy the given object. By default is set to false.
27
+ # @raise ArgumentError if given object doesn't respond to to_a method
28
+ # @return [LinkedList] self object
29
+ def assign(obj, copy: false)
30
+ from_obj(obj, copy)
31
+ end
32
+
33
+ # Inserts a new element at the beginning of the list.
34
+ #
35
+ # @param value
36
+ # @return newly inserted element
37
+ def push_front(value)
38
+ tail = @front
39
+ rand_id = Random.new.rand((2**(0.size * 8 -2) -1) / 2)
40
+ id = @front.nil? ? rand_id : @front.id
41
+ @front = Node.new(value, tail, id)
42
+ @length = @size += 1
43
+
44
+ @front
45
+ end
46
+
47
+ # (see #push_front)
48
+ def >>(value)
49
+ push_front(value)
50
+ end
51
+
52
+ # Removes element at the beginning of the list.
53
+ #
54
+ # @raise Algorithmix::EmptyContainerError if the list is empty.
55
+ # @return removed value
56
+ def pop_front
57
+ raise EmptyContainerError, "The Linked list is empty." if @front.nil?
58
+
59
+ value = @front.value
60
+ @front = @front.next_node
61
+ @length = @size -= 1
62
+ value
63
+ end
64
+
65
+ # Inserts an element after the position specified by iterator.
66
+ #
67
+ # @param it, value [LinkedList::Iterator, #any]
68
+ # @raise ArgumentError, if given iterator doesn't point to any element of the list.
69
+ # @return self object
70
+ def insert_after(it, value)
71
+ raise ArgumentError, "Undefined method LinkedList#insert_after for #{it}:#{it.class}" unless it.is_a?(Iterator)
72
+ raise ArgumentError, "Invalid iterator." unless !@front.nil? && it.current.id == @front.id
73
+
74
+ tail = it.current.next_node
75
+ it.current.send(:next_node=, Node.new(value, it.current, it.current.id))
76
+ it.current.next_node.send(:next_node=, tail)
77
+ @length = @size += 1
78
+
79
+ it.next_node
80
+ end
81
+
82
+ # Removes the element after the position specified by the iterator.
83
+ #
84
+ # @param it[LinkedList::Iterator]
85
+ # @raise ArgumentIterator, if given iterator doesn't point to any element of the list.
86
+ # @return removed element
87
+ def erase_after(it)
88
+ raise ArgumentError, "Undefined method LinkedList#erase_after for #{it}:#{it.class}" unless it.is_a?(Iterator)
89
+ raise ArgumentError, "Invalid iterator." unless !@front.nil? && it.current.id == @front.id
90
+ raise OutOfBound, "There is no more elements" if it.current.next_node.nil?
91
+
92
+ node = it.current.next_node
93
+ it.current.send(:next_node=, it.current.next_node.next_node)
94
+ @size = @length -= 1
95
+ node.value
96
+ end
97
+
98
+ # Returns true if there are no elements in the list.
99
+ def empty?
100
+ @front.nil?
101
+ end
102
+
103
+ # Compares contents of two linked lists.
104
+ #
105
+ # @param linked_list [LinkedList]
106
+ # @raise ArgumentError if given object is not a linked_list
107
+ # @return [true, false] true if both lists are equal, false otherwise
108
+ def ==(linked_list)
109
+ raise ArgumentError, "Undefined method LinkedList#== for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
110
+ return false if @length != linked_list.length
111
+
112
+ it = @front
113
+ other_it = linked_list.front
114
+ until it.nil?
115
+ return false if it.value != other_it.value
116
+ it = it.next_node
117
+ end
118
+
119
+ true
120
+ end
121
+
122
+ # (see #==)
123
+ def eql?(linked_list)
124
+ raise ArgumentError, "Undefined method LinkedList#eql? for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
125
+ self == linked_list
126
+ end
127
+
128
+ # Compares contents of two linked lists.
129
+ #
130
+ # @param linked_list [LinkedList]
131
+ # @raise ArgumentError if given object is not a linked_list
132
+ # @return [true, false] true if both lists are different, false otherwise
133
+ def !=(linked_list)
134
+ raise ArgumentError, "Undefined method LinkedList#!= for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
135
+ return true if @length != linked_list.length
136
+
137
+ it = @front
138
+ other_it = linked_list.front
139
+ until it.nil?
140
+ return true if it.value != other_it.value
141
+ it = it.next_node
142
+ end
143
+
144
+ false
145
+ end
146
+
147
+ # (see #!=)
148
+ def diff?(linked_list)
149
+ raise ArgumentError, "Undefined method LinkedList#diff? for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
150
+ self != linked_list
151
+ end
152
+
153
+ # Compares contents of two linked lists.
154
+ #
155
+ # @param linked_list [LinkedList]
156
+ # @raise ArgumentError if given object is not a linked_list
157
+ # @return
158
+ # -1 if content of the self object is greater than content of the second.
159
+ # 0 if contents are equal.
160
+ # 1 if content of the self object is less than content of the first.
161
+ def <=>(linked_list)
162
+ raise ArgumentError, "Undefined method LinkedList#<=> for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
163
+ to_a <=> linked_list.to_a
164
+ end
165
+
166
+ # Converts content of the list to an array.
167
+ def to_a
168
+ convert
169
+ end
170
+
171
+ # Clears content of the list.
172
+ def clear
173
+ @front = nil
174
+ @length = @size = 0
175
+ self
176
+ end
177
+
178
+ # Concatenates contents of self object and linked_list given as argument.
179
+ #
180
+ # @param linked_list [LinedList]
181
+ # @raise ArgumentError, if given object is not a linked list
182
+ # @return [LinkedList] a new linked list
183
+ def +(linked_list)
184
+ raise ArgumentError, "Undefined method LinkedList#+ for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
185
+ LinkedList.new(to_a.reverse + linked_list.to_a.reverse)
186
+ end
187
+
188
+ # (see #+)
189
+ def concat(linked_list)
190
+ raise ArgumentError, "Undefined method LinkedList#concat for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
191
+ self + linked_list
192
+ end
193
+
194
+ # (see #+)
195
+ def merge(linked_list)
196
+ raise ArgumentError, "Undefined method LinkedList#merge for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
197
+ self + linked_list
198
+ end
199
+
200
+ # Concatenates contents of self object and linked_list given as argument.
201
+ #
202
+ # @param linked_list [LinedList]
203
+ # @raise ArgumentError, if given object is not a linked list
204
+ # @return [LinkedList] self object
205
+ def concat!(linked_list)
206
+ raise ArgumentError, "Undefined method LinkedList#concat! for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
207
+ from_obj(to_a.reverse + linked_list.to_a.reverse)
208
+ end
209
+
210
+ # (see #concat)
211
+ def merge!(linked_list)
212
+ raise ArgumentError, "Undefined method LinkedList#merge! for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
213
+ from_obj(to_a.reverse + linked_list.to_a.reverse)
214
+ end
215
+
216
+ # Finds the difference of contents of the self object and linked_list given as argument.
217
+ #
218
+ # @param linked_list [LinedList]
219
+ # @raise ArgumentError, if given object is not a linked list
220
+ # @return [LinkedList] a new linked list
221
+ def -(linked_list)
222
+ raise ArgumentError, "Undefined method LinkedList#- for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
223
+ LinkedList.new(to_a.reverse - linked_list.to_a.reverse)
224
+ end
225
+
226
+ # (see #-)
227
+ def difference(linked_list)
228
+ raise ArgumentError, "Undefined method LinkedList#difference for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
229
+ self - linked_list
230
+ end
231
+
232
+ # Finds the difference of contents of the self object and linked_list given as argument.
233
+ #
234
+ # @param linked_list [LinedList]
235
+ # @raise ArgumentError, if given object is not a linked list
236
+ # @return [LinkedList] self object
237
+ def difference!(linked_list)
238
+ raise ArgumentError, "Undefined method LinkedList#difference! for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
239
+ from_obj(to_a.reverse - linked_list.to_a.reverse)
240
+ end
241
+
242
+ # Finds the intersection of contents of the self object and linked_list given as argument.
243
+ #
244
+ # @param linked_list [LinedList]
245
+ # @raise ArgumentError, if given object is not a linked list
246
+ # @return [LinkedList] a new linked list
247
+ def &(linked_list)
248
+ raise ArgumentError, "Undefined method LinkedList#& for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
249
+ LinkedList.new(to_a.reverse & linked_list.to_a.reverse)
250
+ end
251
+
252
+ # (see #&)
253
+ def intersect(linked_list)
254
+ raise ArgumentError, "Undefined method LinkedList#intersect for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
255
+ self & linked_list
256
+ end
257
+
258
+ # Finds the intersection of contents of the self object and linked_list given as argument.
259
+ #
260
+ # @param linked_list [LinedList]
261
+ # @raise ArgumentError, if given object is not a linked list
262
+ # @return [LinkedList] self object
263
+ def intersect!(linked_list)
264
+ raise ArgumentError, "Undefined method LinkedList#intersect! for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
265
+ from_obj(to_a.reverse & linked_list.to_a.reverse)
266
+ end
267
+
268
+ # Finds the union of contents of the self object and linked_list given as argument.
269
+ #
270
+ # @param linked_list [LinedList]
271
+ # @raise ArgumentError, if given object is not a linked list
272
+ # @return [LinkedList] a new linked list
273
+ def |(linked_list)
274
+ raise ArgumentError, "Undefined method LinkedList#| for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
275
+ LinkedList.new(to_a.reverse | linked_list.to_a.reverse)
276
+ end
277
+
278
+ # (see #|)
279
+ def union(linked_list)
280
+ raise ArgumentError, "Undefined method LinkedList#union for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
281
+ self | linked_list
282
+ end
283
+
284
+ # Finds the union of contents of the self object and linked_list given as argument.
285
+ #
286
+ # @param linked_list [LinedList]
287
+ # @raise ArgumentError, if given object is not a linked list
288
+ # @return [LinkedList] self object
289
+ def union!(linked_list)
290
+ raise ArgumentError, "Undefined method LinkedList#union! for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
291
+ from_obj(to_a.reverse | linked_list.to_a.reverse)
292
+ end
293
+
294
+ # Finds the symmetric_difference of contents of the self object and linked_list given as argument.
295
+ #
296
+ # @param linked_list [LinedList]
297
+ # @raise ArgumentError, if given object is not a linked list
298
+ # @return [LinkedList] a new linked list
299
+ def ^(linked_list)
300
+ raise ArgumentError, "Undefined method LinkedList#^ for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
301
+ self_a, linked_list_a = to_a.reverse, linked_list.to_a.reverse
302
+ LinkedList.new((self_a | linked_list_a) - (self_a & linked_list_a))
303
+ end
304
+
305
+ # (see #^)
306
+ def symmetric_difference(linked_list)
307
+ raise ArgumentError, "Undefined method LinkedList#symmetric_difference for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
308
+ self ^ linked_list
309
+ end
310
+
311
+ # Finds the symmetric_difference of contents of the self object and linked_list given as argument.
312
+ #
313
+ # @param linked_list [LinedList]
314
+ # @raise ArgumentError, if given object is not a linked list
315
+ # @return [LinkedList] self object
316
+ def symmetric_difference!(linked_list)
317
+ raise ArgumentError, "Undefined method LinkedList#symmetric_difference! for #{linked_list}:#{linked_list.class}" unless linked_list.is_a?(LinkedList)
318
+ self_a, linked_list_a = to_a.reverse, linked_list.to_a.reverse
319
+ from_obj((self_a | linked_list_a) - (self_a & linked_list_a))
320
+ end
321
+
322
+ # Filters elements of the list by given condition.
323
+ #
324
+ # @param &block
325
+ # @return [LinkedList] a new linked list
326
+ def select(&block)
327
+ LinkedList.new(to_a.reverse.select { |e| block.call(e) })
328
+ end
329
+
330
+ # Filters elements of the list by given condition.
331
+ #
332
+ # @param &block
333
+ # @return [LinkedList] self object
334
+ def select!(&block)
335
+ from_obj(to_a.reverse.select { |e| block.call(e) })
336
+ end
337
+
338
+ # (see #select)
339
+ def filter(&block)
340
+ select(&block)
341
+ end
342
+
343
+ # (see #select!)
344
+ def filter!(&block)
345
+ select!(&block)
346
+ end
347
+
348
+ # (see #select)
349
+ def find_all(&block)
350
+ select(&block)
351
+ end
352
+
353
+ # (see #select!)
354
+ def find_all!(&block)
355
+ select!(&block)
356
+ end
357
+
358
+ # Applies a function to each element of the list.
359
+ #
360
+ # @param &block
361
+ # @return [LinkedList] a new linked_list
362
+ def map(&block)
363
+ LinkedList.new(to_a.reverse.map { |e| block.call(e) })
364
+ end
365
+
366
+ # Applies a function to each element of the list.
367
+ #
368
+ # @param &block
369
+ # @return [LinkedList] self object
370
+ def map!(&block)
371
+ from_obj(to_a.reverse.map { |e| block.call(e) })
372
+ end
373
+
374
+ # (see #map)
375
+ def apply(&block)
376
+ map(&block)
377
+ end
378
+
379
+ # (see #map!)
380
+ def apply!(&block)
381
+ map!(&block)
382
+ end
383
+
384
+ # Iterator class which gives couple of useful methods, for moving through the elements of a given list.
385
+ class Iterator
386
+ attr_reader :current, :next_node
387
+
388
+ def initialize(node)
389
+ raise ArgumentError, "Invalid argument" unless node.is_a?(Node) || node.is_a?(LinkedList)
390
+
391
+ @begin = @node.is_a?(Node) ? node : node.front
392
+ @current = @node.is_a?(Node) ? node : node.front
393
+ @next_node = @node.is_a?(Node) ? node : node.front
394
+
395
+ @next_node = @next_node.next_node
396
+ end
397
+
398
+ # Resets the current state of the iterator.
399
+ # All iterators will point to the front of the list.
400
+ def begin
401
+ @current = @next_node = @begin
402
+ end
403
+
404
+ # Moves the iterator to the next position, and sets the current iterator to the previous position
405
+ # of the next node.
406
+ def next
407
+ raise OutOfBound, "No more elements." if @next_node.nil?
408
+ @current = @next_node
409
+ @next_node = @next_node.next_node
410
+ self
411
+ end
412
+
413
+ # Returns the value at the current node.
414
+ def value
415
+ @current.value
416
+ end
417
+ end
418
+
419
+ private
420
+
421
+ class Node
422
+ attr_reader :id
423
+ attr_accessor :value, :next_node
424
+
425
+ def initialize(value = nil, next_node = nil, id = nil)
426
+ @value = value
427
+ @next_node = next_node
428
+ @id = id
429
+ end
430
+
431
+ private :next_node=
432
+ end
433
+
434
+ def convert
435
+ result = []
436
+ it = @front
437
+ until it.nil?
438
+ result << it.value
439
+ it = it.next_node
440
+ end
441
+
442
+ result
443
+ end
444
+
445
+ def from_obj(obj, copy=false)
446
+ raise ArgumentError, "Undefined method #to_a for #{obj}:{obj.class}" unless obj.respond_to?(:to_a)
447
+
448
+ @front = nil
449
+ rand_id = Random.new.rand((2**(0.size * 8 -2) -1) / 2)
450
+ obj.to_a.each do |e|
451
+ tail = @front
452
+ @front = Node.new(copy ? e.dup : e, tail, rand_id)
453
+ end
454
+ @length = @size = obj.to_a.length
455
+ self
456
+ end
457
+
458
+ end
459
+ end
460
+ end
461
+ end
@@ -1,3 +1,3 @@
1
1
  module Algorithmix
2
- VERSION = "0.0.0.6"
2
+ VERSION = "0.0.0.7"
3
3
  end
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algorithmix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0.6
4
+ version: 0.0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Monika Ilieva
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-26 00:00:00.000000000 Z
11
+ date: 2018-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -68,7 +68,8 @@ dependencies:
68
68
  version: 2.0.0
69
69
  description: " The gem contains various implementations of
70
70
  known and uknown data structures and algorithms. \n /Currently
71
- the gem contains: #stack, #queue, #deque, #binary_heap, #priority_queue, #linked_list/\n"
71
+ the gem contains: #stack, #queue, #deque, #binary_heap, #priority_queue, #linked_list,\n
72
+ \ #double_linked_list/\n"
72
73
  email:
73
74
  - "*@*.*"
74
75
  executables: []
@@ -88,12 +89,14 @@ files:
88
89
  - bin/setup
89
90
  - lib/algorithmix.rb
90
91
  - lib/algorithmix/data_structure/generic/deque.rb
92
+ - lib/algorithmix/data_structure/generic/linked_list.rb
91
93
  - lib/algorithmix/data_structure/generic/priority_queue.rb
92
94
  - lib/algorithmix/data_structure/generic/queue.rb
93
95
  - lib/algorithmix/data_structure/generic/stack.rb
94
96
  - lib/algorithmix/data_structure/heap/binary_heap.rb
95
97
  - lib/algorithmix/error.rb
96
98
  - lib/algorithmix/version.rb
99
+ - logo.png
97
100
  homepage: https://github.com/monzita/algorithmix/wiki
98
101
  licenses:
99
102
  - MIT