algorithmix 0.0.0.6 → 0.0.0.7

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: 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