linked_lists 0.1.0

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.
@@ -0,0 +1,985 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'linked_list/node'
4
+
5
+ # An `Enumerable` data structure
6
+ # which implements a singly linked list.
7
+ # It's a proper `Enumerable` object like `Array`, `Hash` or `Set`.
8
+ #
9
+ # Its API has been heavily inspired by `Set` and `Array`.
10
+ #
11
+ # list = LinkedList[1, 2, 3, :foo]
12
+ #
13
+ # Prepending and shifting items is very fast and happens in *O(1)*.
14
+ #
15
+ # list = LinkedList[:foo]
16
+ # list.unshift :bar
17
+ # list.prepend :baz
18
+ # list >> 'foobar'
19
+ # list #=> LinkedList["foobar", :baz, :bar, :foo]
20
+ #
21
+ # Appending is possible but requires the entire list to be traversed, which gives
22
+ # a time complexity of *O(n)*.
23
+ #
24
+ # list = LinkedList[:foo]
25
+ # list.push :bar
26
+ # list.append :baz
27
+ # list << 'foobar'
28
+ # list #=> LinkedList[:foo, :bar, :baz, 'foobar']
29
+ #
30
+ # Optimal traversing is only possible in one direction, from head (first element)
31
+ # to tail (last element).
32
+ #
33
+ # To get the length of a linked list, the entire list has to be traversed
34
+ # which happens in *O(n)*.
35
+ #
36
+ # LinkedList[].size #=> 0
37
+ # LinkedList[:foo].length #=> 1
38
+ # LinkedList[:foo, 1, 2, 3].count #=> 4
39
+ #
40
+ # Getting items by index is possible, but the list needs to be
41
+ # traversed from head to the index, which gives a time complexity of *O(n)*.
42
+ #
43
+ # list = LinkedList["foobar", :baz, :bar, :foo]
44
+ # list[0] #=> "foobar"
45
+ # list.slice(0) #=> "foobar"
46
+ # list[2] #=> :bar
47
+ # list[-1] #=> :foo
48
+ # list[1, 2] #=> [:baz, :bar]
49
+ # list.slice(1, 2) #=> LinkedList[:baz, :bar]
50
+ # list[1..3] #=> [:baz, :bar, :foo]
51
+ #
52
+ class LinkedList
53
+ include ::Enumerable
54
+
55
+ class << self
56
+ # Create a new `LinkedList` with these elements
57
+ # inserted.
58
+ #
59
+ # @param elements [Array]
60
+ def [](*elements)
61
+ new(elements)
62
+ end
63
+ end
64
+
65
+ # The first element of the linked list.
66
+ # Time complexity: *O(1)*
67
+ #
68
+ # @return [Node, nil]
69
+ attr_accessor :head
70
+
71
+ # @param enum [Object] Enumerable object that will be converted.
72
+ def initialize(enum = nil)
73
+ @head = nil
74
+ return if enum.nil?
75
+
76
+ concat(enum)
77
+ end
78
+
79
+ # The last element of the linked list.
80
+ #
81
+ # Keep in mind that in order to retrieve it the entire
82
+ # list needs to be traversed.
83
+ #
84
+ # Time complexity is *O(n)*.
85
+ #
86
+ # @return [Node, nil]
87
+ def tail
88
+ each_node { |node| return node if node.next.nil? }
89
+ end
90
+
91
+ # Freezes the list and its every node.
92
+ #
93
+ # Time complexity is *O(n)*.
94
+ #
95
+ # @return [self]
96
+ def freeze
97
+ super
98
+ each_node(&:freeze)
99
+
100
+ self
101
+ end
102
+
103
+ # Removes all elements from `self`.
104
+ # Sets the `head` to `nil`.
105
+ #
106
+ # Time complexity: *O(1)*.
107
+ #
108
+ # @return [self]
109
+ def clear
110
+ @head = nil
111
+ self
112
+ end
113
+
114
+ # Checks if `head` is `nil`.
115
+ #
116
+ # Time complexity: *O(1)*.
117
+ #
118
+ # @return [Boolean]
119
+ def empty?
120
+ @head.nil?
121
+ end
122
+
123
+ # The number of elements in the list.
124
+ # Keep in mind that the entire list needs to be traversed in order
125
+ # to find out it's length.
126
+ #
127
+ # Time complexity is *O(n)*.
128
+ #
129
+ # @return [Integer]
130
+ def size
131
+ return 0 if empty?
132
+
133
+ length = 0
134
+ each_with_index { |_, i| length = i }
135
+
136
+ length + 1
137
+ end
138
+ alias length size
139
+
140
+ # Returns the last element, or the last `length` elements, of the linked list.
141
+ # If the list is empty, the first form returns `nil`, and the second form returns an empty list.
142
+ #
143
+ # Keep in mind that it's only possible to traverse this list in one direction
144
+ # from head to tail. So the entire list has to be traversed in order
145
+ # to retrieve the last elements.
146
+ #
147
+ # Time complexity is *O(2n)*.
148
+ #
149
+ # @param length [Integer]
150
+ # @return [Object, Array]
151
+ def last(*args)
152
+ to_a.last(*args)
153
+ end
154
+
155
+ # Returns the index of the first object in the linked list such that the object is `==` to `obj`.
156
+ # Time complexity: *O(n)*
157
+ #
158
+ # If a block is given instead of an argument, returns the index
159
+ # of the first object for which the block returns `true`. Returns `nil` if no match is found.
160
+ #
161
+ # Time complexity: *O(n)*
162
+ #
163
+ # @param obj [Object] Value that will be compared with the nodes of this list.
164
+ # @return [Object, nil]
165
+ def index(obj = nil)
166
+ if block_given?
167
+ each_with_index do |element, i|
168
+ return i if yield(element)
169
+ end
170
+
171
+ return
172
+ end
173
+
174
+ each_with_index do |element, i|
175
+ return i if obj == element
176
+ end
177
+
178
+ nil
179
+ end
180
+
181
+ # Returns the node at the provided index.
182
+ # This list in not indexed so the entire list will have to
183
+ # be traversed in the worst case.
184
+ # Time complexity: *O(n)*
185
+ #
186
+ # @param index [Integer]
187
+ # @return [Node, nil]
188
+ def node_at(index)
189
+ index = index.to_int
190
+ return each_node.to_a.at(index) if index.negative?
191
+
192
+ each_node.with_index do |node, i|
193
+ return node if i == index
194
+ end
195
+
196
+ nil
197
+ end
198
+
199
+ # Returns the item at the provided index.
200
+ # This list in not indexed so the entire list will have to
201
+ # be traversed in the worst case.
202
+ # Time complexity: *O(n)*
203
+ #
204
+ # @param index [Integer]
205
+ # @return [Object, nil]
206
+ def at(index)
207
+ node_at(index)&.value
208
+ end
209
+
210
+ # Get the elements at the specified index. Head of the list is `0`.
211
+ #
212
+ # This list in not indexed so the entire list will have to
213
+ # be traversed in the worst case.
214
+ # Time complexity: *O(n)*
215
+ #
216
+ # @param index [Integer]
217
+ # @param length [Integer, nil]
218
+ # @return [Object, Array]
219
+ def [](index, length = nil)
220
+ slice_with_enum(::Array, index, length)
221
+ end
222
+
223
+ # Get the elements at the specified index. Head of the list is `0`.
224
+ #
225
+ # This list in not indexed so the entire list will have to
226
+ # be traversed in the worst case.
227
+ # Time complexity: *O(n)*
228
+ #
229
+ # @param index [Integer]
230
+ # @param length [Integer, nil]
231
+ # @return [Object, self]
232
+ def slice(index, length = nil)
233
+ slice_with_enum(self.class, index, length)
234
+ end
235
+
236
+ # Calls the given block once for each element in linked list, passing
237
+ # the element as a parameter. Returns an enumerator if no block is
238
+ # given.
239
+ #
240
+ # Time complexity: *O(n)*
241
+ #
242
+ # @yieldparam [Object] An element of the list.
243
+ # @return [self, Enumerator]
244
+ def each
245
+ return enum_for(__method__) unless block_given?
246
+
247
+ each_node { |node| yield node.value }
248
+ end
249
+
250
+ alias each_value each
251
+
252
+ # Calls the given block once for each node in the linked list, passing
253
+ # the node as a parameter. Returns an enumerator if no block is
254
+ # given.
255
+ #
256
+ # Time complexity: *O(n)*
257
+ #
258
+ # @yieldparam [Node] A node of the list.
259
+ # @return [self, Enumerator]
260
+ def each_node
261
+ return enum_for(__method__) unless block_given?
262
+ return unless @head
263
+
264
+ element = @head
265
+ loop do
266
+ yield element
267
+ break if (element = element.next).nil?
268
+ end
269
+
270
+ self
271
+ end
272
+
273
+ # Returns a new `LinkedList` with the elements of `self` in reverse order.
274
+ # Time complexity: *O(2n)*
275
+ #
276
+ # @return [self]
277
+ def reverse
278
+ result = self.class.new
279
+ reverse_each do |obj|
280
+ result << obj
281
+ end
282
+
283
+ result
284
+ end
285
+
286
+ # Returns a new `LinkedList` which consists of the values returned by the block.
287
+ # Returns an enumerator if no block is given.
288
+ #
289
+ # Time complexity: *O(n)*
290
+ #
291
+ # @yieldparam [Object] An element of the list.
292
+ # @return [self, Enumerator]
293
+ def map
294
+ return enum_for(__method__) unless block_given?
295
+
296
+ result = self.class.new
297
+ each_node do |node|
298
+ result << yield(node.value)
299
+ end
300
+
301
+ result
302
+ end
303
+ alias collect map
304
+
305
+ # Returns a list containing truthy elements returned by the block.
306
+ #
307
+ # With a block given, calls the block with successive elements;
308
+ # returns a list containing each truthy value returned by the block.
309
+ #
310
+ # Time complexity: *O(n)*
311
+ #
312
+ # @yieldparam [Object] An element of the list.
313
+ # @return [self, Enumerator]
314
+ def filter_map
315
+ return enum_for(__method__) unless block_given?
316
+
317
+ result = self.class.new
318
+ each_node do |node|
319
+ next unless (block_result = yield(node.value))
320
+
321
+ result << block_result
322
+ end
323
+
324
+ result
325
+ end
326
+
327
+ # Replaces the elements with ones returned by the block.
328
+ # Returns an enumerator if no block is given.
329
+ #
330
+ # Time complexity: *O(n)*
331
+ #
332
+ # @yieldparam [Object] An element of the list.
333
+ # @return [self, Enumerator]
334
+ def map!
335
+ return enum_for(__method__) unless block_given?
336
+
337
+ each_node do |node|
338
+ node.value = yield(node.value)
339
+ end
340
+
341
+ self
342
+ end
343
+ alias collect! map!
344
+
345
+ # Returns a new `LinkedList` object whose entries are those for which the block returns a falsey value.
346
+ # Or a new `Enumerator` if no block given.
347
+ #
348
+ # Time complexity: *O(n)*
349
+ #
350
+ # @yieldparam [Object] An element of the list.
351
+ # @return [self, Enumerator]
352
+ def reject
353
+ return enum_for(__method__) unless block_given?
354
+
355
+ select { |o| !yield(o) }
356
+ end
357
+
358
+ # Returns a new `LinkedList` object whose entries are those for which the block returns a truthy value.
359
+ # Or a new Enumerator if no block given.
360
+ #
361
+ # Time complexity: *O(n)*
362
+ #
363
+ # @yieldparam [Object] An element of the list.
364
+ # @return [self, Enumerator]
365
+ def select
366
+ return enum_for(__method__) unless block_given?
367
+
368
+ result = self.class.new
369
+ each do |value|
370
+ result << value if yield(value)
371
+ end
372
+
373
+ result
374
+ end
375
+ alias filter select
376
+
377
+ # Returns self whose entries are those for which the block returns a truthy value.
378
+ # Or a new `Enumerator` if no block given.
379
+ #
380
+ # Time complexity: *O(n)*
381
+ #
382
+ # @yieldparam [Object] An element of the list.
383
+ # @return [self, Enumerator, nil]
384
+ def delete_if(&block)
385
+ reject!(&block) || self
386
+ end
387
+
388
+ # Deletes the first item from `self` that is equal to `obj`.
389
+ # Returns the deleted item, or `nil` if no matching item is found.
390
+ #
391
+ # Time complexity: *O(n)*
392
+ #
393
+ # @param obj [Object] object to be deleted
394
+ # @return [Object]
395
+ def delete(obj)
396
+ removed = nil
397
+ prev_node = nil
398
+ each_node do |n|
399
+ next (prev_node = n) unless n.value == obj
400
+
401
+ delete_node_with_prev(prev_node, n.next)
402
+ return n.value
403
+ end
404
+
405
+ removed
406
+ end
407
+
408
+ # Deletes all items from `self` that are equal to `obj`.
409
+ # Returns the last deleted item, or `nil` if no matching item is found.
410
+ #
411
+ # Time complexity: *O(n)*
412
+ #
413
+ # @param obj [Object] object to be deleted
414
+ # @return [Object]
415
+ def delete_all(obj)
416
+ removed = nil
417
+ delete_if do |element|
418
+ removed = element if element == obj
419
+ end
420
+
421
+ removed
422
+ end
423
+
424
+ # Deletes a node from `self` that is the same object as the given `node`.
425
+ # Returns the deleted node, or `nil` if no matching item is found.
426
+ #
427
+ # Time complexity: *O(n)*
428
+ #
429
+ # @param node [Node] node to be deleted
430
+ # @return [Node, nil]
431
+ def delete_node(node)
432
+ raise ::ArgumentError, 'value should be a node' unless node.is_a?(Node)
433
+
434
+ removed = nil
435
+ prev_node = nil
436
+ each_node do |n|
437
+ next (prev_node = n) unless n == node
438
+
439
+ delete_node_with_prev(prev_node, n.next)
440
+ return n
441
+ end
442
+
443
+ removed
444
+ end
445
+
446
+ # Deletes the element at the specified index
447
+ # returning that element, or `nil` if the `index` is out of range.
448
+ #
449
+ # This list in not indexed so the entire list will have to
450
+ # be traversed in the worst case.
451
+ # Time complexity: *O(n)*
452
+ #
453
+ # @param index [Integer]
454
+ # @return [Object, nil]
455
+ def delete_at(index)
456
+ prev_node = nil
457
+ each_node.with_index do |node, i|
458
+ return node.value if i == index && delete_node_with_prev(prev_node, node.next)
459
+
460
+ prev_node = node
461
+ end
462
+
463
+ nil
464
+ end
465
+
466
+ # Removes and returns leading elements.
467
+ # When no argument is given, removes and returns the first element.
468
+ # When positive Integer argument `length` is given, removes the first `length` elements
469
+ # and returns those elements in a new `Array`.
470
+ #
471
+ # Time complexity is *O(1)* when no `length` is given.
472
+ # Otherwise it's *O(min(m, n))*, where *m* is the given `length` of elements to be shifted
473
+ # and *n* is the length of `self`.
474
+ #
475
+ # @param length [Integer, nil]
476
+ # @return [Object, Array]
477
+ def shift(length = nil)
478
+ raise ::TypeError, "no implicit conversion of #{length.class} into Integer" unless length.nil? || length.respond_to?(:to_int)
479
+ raise ::ArgumentError, 'negative linked list size' if length&.negative?
480
+ return if empty?
481
+
482
+ unless length
483
+ prev_head = @head
484
+ @head = @head.next
485
+ return prev_head.value
486
+ end
487
+
488
+ length = length.to_int
489
+ removed = []
490
+ each_node.with_index do |node, i|
491
+ break if i == length
492
+
493
+ removed << @head.value
494
+ @head = node.next
495
+ end
496
+
497
+ removed
498
+ end
499
+
500
+ # Removes and returns trailing elements.
501
+ #
502
+ # When no argument is given and self is not empty, removes and returns the last element
503
+ #
504
+ # Keep in mind that the entire list has to be traversed
505
+ # in the worst case to pop an item.
506
+ #
507
+ # Time complexity: *O(n)*.
508
+ #
509
+ # @param length [Integer, nil]
510
+ # @return [Object, Array]
511
+ def pop(length = nil)
512
+ raise ::TypeError, "no implicit conversion of #{length.class} into Integer" unless length.nil? || length.respond_to?(:to_int)
513
+ return [] if length&.zero?
514
+ raise ::ArgumentError, 'negative linked list size' if length&.negative?
515
+
516
+ index = length ? -length : -1
517
+ ary = each_node.to_a
518
+ node = ary[index] || @head
519
+ prev_node = ary[index - 1]
520
+
521
+ if prev_node.nil?
522
+ @head = nil
523
+ else
524
+ prev_node.next = nil
525
+ end
526
+
527
+ return node&.value unless length
528
+
529
+ node&.to_list.to_a
530
+ end
531
+
532
+ # Returns self whose entries are those for which the block returns a falsey value.
533
+ # A new `Enumerator` if no block given.
534
+ # Or `nil` if no entries were removed.
535
+ #
536
+ # Time complexity: *O(n)*
537
+ #
538
+ # @yieldparam [Object] An element of the list.
539
+ # @return [self, Enumerator, nil]
540
+ def reject!
541
+ return enum_for(__method__) unless block_given?
542
+
543
+ select! { |o| !yield(o) }
544
+ end
545
+
546
+ # Returns self whose entries are those for which the block returns a truthy value.
547
+ # Or a new `Enumerator` if no block given.
548
+ #
549
+ # Time complexity: *O(n)*
550
+ #
551
+ # @yieldparam [Object] An element of the list.
552
+ # @return [self, Enumerator, nil]
553
+ def keep_if(&block)
554
+ select!(&block) || self
555
+ end
556
+
557
+ # Returns self whose entries are those for which the block returns a truthy value.
558
+ # A new `Enumerator` if no block given.
559
+ # Or `nil` if no entries were removed.
560
+ #
561
+ # Time complexity: *O(n)*
562
+ #
563
+ # @yieldparam [Object] An element of the list.
564
+ # @return [self, Enumerator, nil]
565
+ def select!
566
+ return enum_for(__method__) unless block_given?
567
+ return if empty?
568
+
569
+ removed = false
570
+ prev_node = nil
571
+ node = @head
572
+ next_node = node.next
573
+ loop do
574
+ keep = yield(node.value)
575
+ if keep
576
+ prev_node = node
577
+ node = prev_node.next
578
+ next_node = node&.next
579
+ else
580
+ removed = true
581
+ prev_node, node, next_node = delete_node_with_prev(prev_node, next_node)
582
+ end
583
+
584
+ break if node.nil?
585
+ end
586
+
587
+ return unless removed
588
+
589
+ self
590
+ end
591
+ alias filter! select!
592
+
593
+ # Time complexity: *O(n)*
594
+ #
595
+ # @param separator [String, nil]
596
+ # @yieldparam [Object]
597
+ # @return [String]
598
+ def join(separator = nil)
599
+ result = ::String.new
600
+ each_node do |node|
601
+ string_value = block_given? ? yield(node.value) : node.value
602
+ result << string_value.to_s
603
+ result << separator if separator && node.next
604
+ end
605
+
606
+ result
607
+ end
608
+
609
+ # Appends the given `objects` to `self`.
610
+ #
611
+ # Time complexity: *O(n)*.
612
+ #
613
+ # @param objects [Object]
614
+ # @return [self]
615
+ def push(*objects)
616
+ return self if objects.empty?
617
+
618
+ @head = Node.new objects.shift if empty?
619
+ tail.insert_after(*objects)
620
+
621
+ self
622
+ end
623
+ alias << push
624
+ alias add push
625
+ alias append push
626
+
627
+ # Prepends the given `objects` to `self`.
628
+ #
629
+ # Time complexity is *O(1)* if one item is given.
630
+ # Otherwise it's *O(m)*, where *m* is the length of given `objects`.
631
+ #
632
+ # @param objects [Array]
633
+ # @return [self]
634
+ def unshift(*objects)
635
+ objects.reverse_each do |obj|
636
+ new_node = Node.new obj
637
+ new_node.next = @head
638
+ @head = new_node
639
+ end
640
+
641
+ self
642
+ end
643
+ alias >> unshift
644
+ alias prepend unshift
645
+
646
+ # Inserts given objects before or after the element at `Integer` index offset; returns `self`.
647
+ #
648
+ # Inserts all given objects before the element at offset index:
649
+ #
650
+ # a = LinkedList[:foo, 'bar', 2]
651
+ # a.insert(1, :bat, :bam) # => LinkedList[:foo, :bat, :bam, "bar", 2]
652
+ #
653
+ # Extends the list if `index` is beyond the list (`index` >= `self.size`):
654
+ #
655
+ # a = LinkedList[:foo, 'bar', 2]
656
+ # a.insert(5, :bat, :bam)
657
+ # a # => LinkedList[:foo, "bar", 2, nil, nil, :bat, :bam]
658
+ #
659
+ # Does nothing if no objects given:
660
+ #
661
+ # a = LinkedList[:foo, 'bar', 2]
662
+ # a.insert(1)
663
+ # a.insert(50)
664
+ # a.insert(-50)
665
+ # a # => LinkedList[:foo, "bar", 2]
666
+ #
667
+ # @param index [Integer]
668
+ # @param objects [Array]
669
+ # @return [self]
670
+ def insert(index, *objects)
671
+ index = index.to_int
672
+
673
+ raise ::ArgumentError, 'negative list index' if index.negative?
674
+ return unshift(*objects) if index.zero?
675
+ return self if objects.empty?
676
+
677
+ last_node = nil
678
+ prev_node = nil
679
+ found_index = false
680
+ last_index = 0
681
+ each_node.with_index do |node, i|
682
+ last_index = i
683
+ last_node = node
684
+ next (prev_node = node) unless i >= index
685
+
686
+ found_index = true
687
+ prev_node.insert_after(*objects)
688
+ break
689
+ end
690
+
691
+ return self if found_index
692
+
693
+ @head = last_node = Node.new if empty?
694
+
695
+ loop do
696
+ last_index += 1
697
+ break if last_index >= index
698
+
699
+ new_node = Node.new
700
+ last_node.next = new_node
701
+ last_node = new_node
702
+ end
703
+ last_node.insert_after(*objects)
704
+
705
+ self
706
+ end
707
+
708
+ # Concatenates this linked list with another linked list or `Enumerable`.
709
+ #
710
+ # Time complexity is *O(m)*, where *m* is the length of given `enum`.
711
+ #
712
+ # @param enum [Object]
713
+ # @return [self]
714
+ def concat(enum)
715
+ do_with_enum(enum) { |o| self << o }
716
+
717
+ self
718
+ end
719
+
720
+ # Concatenates this linked list with another linked list.
721
+ #
722
+ # This version is faster for two linked lists but more unsafe
723
+ # because concatenating them happens in place
724
+ # by just linking the tail of the first list to the head of the second one.
725
+ # This means that modifying the second list after concatenating it
726
+ # will change the concatenated list as well!
727
+ #
728
+ # Time complexity is *O(n)*, where *n* is the length of `self`.
729
+ #
730
+ # @param list [self]
731
+ # @return [self]
732
+ def concat!(list)
733
+ raise ::ArgumentError, 'value must be a linked list' unless list.instance_of?(self.class)
734
+
735
+ tail.next = list.head
736
+
737
+ self
738
+ end
739
+
740
+ # Returns a new `LinkedList` containing all non-nil elements from `self`
741
+ #
742
+ # Time complexity: *O(n)*
743
+ #
744
+ # @return [self]
745
+ def compact
746
+ result = self.class.new
747
+
748
+ each do |value|
749
+ next if value.nil?
750
+
751
+ result << value
752
+ end
753
+
754
+ result
755
+ end
756
+
757
+ # Removes all `nil` elements from `self`.
758
+ #
759
+ # Returns `self` if any elements removed, otherwise `nil`.
760
+ #
761
+ # Time complexity: *O(n)*
762
+ #
763
+ # @return [self, nil]
764
+ def compact!
765
+ removed = nil
766
+ prev_node = nil
767
+ each_node do |node|
768
+ if node.value.nil?
769
+ removed = true
770
+ prev_node, = delete_node_with_prev(prev_node, node.next)
771
+ next
772
+ end
773
+
774
+ prev_node = node
775
+ end
776
+ return self if removed
777
+
778
+ nil
779
+ end
780
+
781
+ # Checks whether `self` is a superlist of the provided list `other`
782
+ # (if the `other` list is a sublist of `self`).
783
+ # Time complexity is *O(n)*, where *n* is the length of `self`.
784
+ #
785
+ # @param other [self]
786
+ # @return [Boolean]
787
+ def superlist?(other)
788
+ raise ::ArgumentError, 'value must be a linked list' unless other.is_a?(self.class)
789
+
790
+ other.sublist?(self)
791
+ end
792
+
793
+ # Checks whether `self` is a sublist of the provided list `other`.
794
+ # Time complexity is *O(m)*, where *m* is the length of `other`.
795
+ #
796
+ # @param other [self]
797
+ # @return [Boolean]
798
+ def sublist?(other)
799
+ return true if equal?(other)
800
+ raise ::ArgumentError, 'value must be a linked list' unless other.is_a?(self.class)
801
+ return true if (empty? && !other.empty?) || (empty? && other.empty?)
802
+ return false if !empty? && other.empty?
803
+
804
+ self_node = @head
805
+ other_node = other.head
806
+
807
+ at_least_one_equal = false
808
+ loop do
809
+ return true if self_node.equal?(other_node)
810
+ return true if self_node.nil?
811
+ return false if other_node.nil?
812
+
813
+ if self_node.value == other_node.value
814
+ at_least_one_equal = true
815
+ self_node = self_node.next
816
+ other_node = other_node.next
817
+ next
818
+ end
819
+
820
+ return false if at_least_one_equal
821
+
822
+ other_node = other_node.next
823
+ end
824
+
825
+ true
826
+ end
827
+
828
+ # Returns a new LinkedList which is the result of
829
+ # concatenating this linked list with another linked list or `Enumerable`.
830
+ #
831
+ # Time complexity is *O(n + m)*, where *n* is the length of `self` and *m* is the length of `other`.
832
+ #
833
+ # @param enum [Object]
834
+ # @return [self]
835
+ def +(other)
836
+ dup.concat(other)
837
+ end
838
+
839
+ # Returns true if two linked lists are equal. The equality of each couple
840
+ # of elements is defined according to `#==`.
841
+ #
842
+ # Time complexity is *O(min(n, m))*, where *n* is the length of `self`
843
+ # and *m* is the length of `other`.
844
+ #
845
+ # LinkedList[1, 2] == LinkedList[1, 2] #=> true
846
+ # LinkedList[1, 2] == LinkedList[1, 2.0] #=> true
847
+ # LinkedList[1, 3, 5] == LinkedList[1, 5] #=> false
848
+ # LinkedList[1, 3, 5] == LinkedList[1, 3] #=> false
849
+ # LinkedList['a', 'b', 'c'] == LinkedList['a', 'c', 'b'] #=> true
850
+ # LinkedList['a', 'b', 'c'] == ['a', 'c', 'b'] #=> false
851
+ #
852
+ # @return [Boolean]
853
+ def eql?(other)
854
+ return true if equal?(other)
855
+ return false unless other.is_a?(self.class)
856
+
857
+ self_node = @head
858
+ other_node = other.head
859
+ loop do
860
+ break if self_node.nil? && other_node.nil?
861
+ return false if self_node.nil? || other_node.nil?
862
+ return false if self_node.value != other_node.value
863
+
864
+ self_node = self_node.next
865
+ other_node = other_node.next
866
+ end
867
+
868
+ true
869
+ end
870
+ alias == eql?
871
+
872
+ # Returns `true` if the given object is a member of the list,
873
+ # and `false` otherwise.
874
+ #
875
+ # Keep in mind that checking for inclusion will
876
+ # will require the list to be traversed in its entirety
877
+ # in the worst case.
878
+ # Time complexity: *O(n)*.
879
+ #
880
+ # Used in case statements:
881
+ #
882
+ # case :apple
883
+ # when LinkedList[:potato, :carrot]
884
+ # "vegetable"
885
+ # when LinkedList[:apple, :banana]
886
+ # "fruit"
887
+ # end
888
+ # # => "fruit"
889
+ #
890
+ # Or by itself:
891
+ #
892
+ # LinkedList[1, 2, 3] === 2 #=> true
893
+ # LinkedList[1, 2, 3] === 4 #=> false
894
+ #
895
+ alias === include?
896
+
897
+ # @return [Set]
898
+ def to_set
899
+ set = ::Set.new
900
+ each do |value|
901
+ set << value
902
+ end
903
+
904
+ set
905
+ end
906
+
907
+ # @return [String]
908
+ def inspect
909
+ "#<#{self.class}: {#{join(', ', &:inspect)}}>"
910
+ end
911
+
912
+ private
913
+
914
+ def slice_with_enum(klass, index, length = nil)
915
+ return klass.new if length&.zero?
916
+ return at(index) if length.nil? && index.is_a?(::Numeric)
917
+ return if length&.negative?
918
+
919
+ range = if index.is_a?(::Range)
920
+ index
921
+ elsif length
922
+ index..(index + length - 1)
923
+ else
924
+ index..index
925
+ end
926
+
927
+ if range.begin&.negative? || range.end&.negative?
928
+ result = to_a[range]
929
+ return result unless result.is_a?(::Array)
930
+
931
+ return klass[*result]
932
+ end
933
+
934
+ result = klass.new
935
+ added = nil
936
+ each_with_index do |val, i|
937
+ includes = range.include? i
938
+ break if added && !includes
939
+ next unless includes
940
+
941
+ added ||= true
942
+ result << val
943
+ end
944
+ return result unless result.empty?
945
+
946
+ nil
947
+ end
948
+
949
+ def delete_node_with_prev(prev_node, next_node)
950
+ if prev_node.nil?
951
+ node = @head = next_node
952
+ next_node = node&.next
953
+
954
+ return [prev_node, node, next_node]
955
+ end
956
+
957
+ prev_node.next = next_node
958
+ node = next_node
959
+ next_node = node&.next
960
+
961
+ [prev_node, node, next_node]
962
+ end
963
+
964
+ def initialize_dup(orig)
965
+ super
966
+ @head = nil
967
+ orig.each { |o| self << o }
968
+ end
969
+
970
+ def initialize_clone(orig)
971
+ super
972
+ @head = nil
973
+ orig.each { |o| self << o }
974
+ end
975
+
976
+ # @param enum [Object]
977
+ # @return [void]
978
+ def do_with_enum(enum, &block)
979
+ return unless block
980
+ return enum.each_entry(&block) if enum.respond_to?(:each_entry)
981
+ return enum.each(&block) if enum.respond_to?(:each)
982
+
983
+ raise ::ArgumentError, 'value must be enumerable'
984
+ end
985
+ end