ds 0.0.4 → 0.0.6

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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +11 -0
  3. data/.rubocop_todo.yml +452 -0
  4. data/.travis.yml +12 -0
  5. data/Gemfile +1 -1
  6. data/README.rdoc +185 -214
  7. data/Rakefile +8 -3
  8. data/ds.gemspec +16 -13
  9. data/lib/ds.rb +20 -30
  10. data/lib/ds/{matrixes → arrays}/array_2d.rb +9 -10
  11. data/lib/ds/arrays/expandable_array.rb +34 -0
  12. data/lib/ds/arrays/heap_store.rb +32 -0
  13. data/lib/ds/arrays/tri_matrix.rb +33 -0
  14. data/lib/ds/lists/list.rb +310 -186
  15. data/lib/ds/lists/list_element.rb +14 -11
  16. data/lib/ds/pair.rb +4 -4
  17. data/lib/ds/queues/priority_queue.rb +33 -20
  18. data/lib/ds/queues/simple_queue.rb +55 -0
  19. data/lib/ds/sets/indexed_set.rb +37 -0
  20. data/lib/ds/stacks/stack.rb +25 -17
  21. data/lib/ds/trees/binary_heap.rb +71 -66
  22. data/lib/ds/trees/binary_tree.rb +40 -44
  23. data/lib/ds/trees/red_black_tree.rb +123 -0
  24. data/lib/ds/trees/red_black_tree/node.rb +21 -0
  25. data/lib/ds/trees/tree.rb +50 -48
  26. data/lib/ds/trees/tree_walker.rb +73 -144
  27. data/lib/ds/trees/trie.rb +67 -37
  28. data/lib/ds/trees/trie/node.rb +48 -0
  29. data/lib/ds/version.rb +2 -1
  30. data/test/help.rb +3 -6
  31. data/test/performance/binary_heap_performance_test.rb +20 -0
  32. data/test/performance/list_performance_test.rb +36 -0
  33. data/test/performance/priority_queue_performance.rb +32 -0
  34. data/test/performance/rbt_performance_test.rb +17 -0
  35. data/test/performance/simple_queue_performance_test.rb +37 -0
  36. data/test/performance/stack_test.rb +45 -0
  37. data/test/test_array2d.rb +29 -31
  38. data/test/test_binary_heap.rb +29 -23
  39. data/test/test_binary_tree.rb +30 -20
  40. data/test/test_expandable_array.rb +6 -10
  41. data/test/test_heap_store.rb +34 -0
  42. data/test/test_indexed_set.rb +26 -0
  43. data/test/test_list.rb +226 -109
  44. data/test/test_list_element.rb +34 -16
  45. data/test/test_pair.rb +5 -8
  46. data/test/test_priority_queue.rb +43 -64
  47. data/test/test_queue.rb +12 -61
  48. data/test/test_red_black_tree.rb +46 -0
  49. data/test/test_stack.rb +35 -39
  50. data/test/test_tree.rb +42 -29
  51. data/test/test_tree_walker.rb +27 -52
  52. data/test/test_tri_matrix.rb +6 -11
  53. data/test/test_trie.rb +59 -17
  54. metadata +80 -35
  55. data/lib/ds/ext/array_x.rb +0 -35
  56. data/lib/ds/graphs/digraph.rb +0 -20
  57. data/lib/ds/graphs/edge.rb +0 -15
  58. data/lib/ds/graphs/graph.rb +0 -111
  59. data/lib/ds/graphs/graph_as_matrix.rb +0 -113
  60. data/lib/ds/graphs/graph_as_tri_matrix.rb +0 -24
  61. data/lib/ds/lists/cyclic_list.rb +0 -21
  62. data/lib/ds/lists/ring.rb +0 -42
  63. data/lib/ds/matrixes/expandable_array.rb +0 -37
  64. data/lib/ds/matrixes/tri_matrix.rb +0 -30
  65. data/lib/ds/queues/queue.rb +0 -53
  66. data/lib/ds/sets/ordered_set.rb +0 -32
  67. data/lib/ds/trees/binary_search_tree.rb +0 -34
  68. data/lib/ds/trees/complete_binary_tree.rb +0 -60
  69. data/test/test_array_x.rb +0 -51
  70. data/test/test_binary_search_tree.rb +0 -39
  71. data/test/test_complete_binary_tree.rb +0 -58
  72. data/test/test_digraph.rb +0 -134
  73. data/test/test_graph.rb +0 -80
  74. data/test/test_ordered_set.rb +0 -28
  75. data/test/test_ring.rb +0 -28
data/Rakefile CHANGED
@@ -4,10 +4,15 @@ require 'rake/testtask'
4
4
  Rake::TestTask.new do |t|
5
5
  t.libs << 'test'
6
6
  t.test_files = FileList['test/test*.rb']
7
- #t.pattern = "test/test_*.rb"
8
7
  t.verbose = true
9
8
  end
10
9
 
11
- desc "Run tests"
12
- task :default => :test
10
+ Rake::TestTask.new do |t|
11
+ t.name = 'test:performance'
12
+ t.libs << 'test'
13
+ t.test_files = FileList['test/performance/*test.rb']
14
+ t.verbose = true
15
+ end
13
16
 
17
+ desc 'Run tests'
18
+ task default: :test
data/ds.gemspec CHANGED
@@ -1,20 +1,23 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "ds/version"
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'ds/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
- s.name = "ds"
6
+ s.name = 'ds'
7
7
  s.version = DS::VERSION
8
- s.authors = ["knife"]
9
- s.email = ["satre@o2.pl"]
10
- s.homepage = ""
11
- s.summary = %q{Some common data structures.}
12
- s.description = %q{Data structures (lists,stacks, trees, heaps, graphs..) in pure Ruby.}
13
-
14
- s.rubyforge_project = "ds"
8
+ s.authors = ['knife']
9
+ s.email = ['satre@o2.pl']
10
+ s.homepage = ''
11
+ s.summary = 'Some common data structures.'
12
+ s.description = 'Data structures (lists, stacks, trees, heaps, graphs..) in pure Ruby.'
13
+ s.rubyforge_project = 'ds'
15
14
 
16
15
  s.files = `git ls-files`.split("\n")
17
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- s.require_paths = ["lib"]
16
+ s.test_files = `git ls-files -- test/**/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
18
+ s.require_paths = ['lib']
19
+
20
+ s.add_development_dependency 'bundler'
21
+ s.add_development_dependency 'rake'
22
+ s.add_development_dependency 'minitest'
20
23
  end
data/lib/ds.rb CHANGED
@@ -1,36 +1,26 @@
1
- require "ds/version"
1
+ require 'ds/version'
2
2
 
3
- require "ds/ext/array_x"
4
- require "ds/pair"
3
+ require 'ds/pair'
5
4
 
6
- require "ds/matrixes/expandable_array"
7
- require "ds/matrixes/array_2d"
8
- require "ds/matrixes/tri_matrix"
5
+ require 'ds/arrays/expandable_array'
6
+ require 'ds/arrays/array_2d'
7
+ require 'ds/arrays/tri_matrix'
8
+ require 'ds/arrays/heap_store'
9
9
 
10
- require "ds/sets/ordered_set"
11
-
12
- require "ds/lists/list_element"
13
- require "ds/lists/list"
14
- require "ds/lists/cyclic_list"
15
- require "ds/lists/ring"
16
-
17
- require "ds/stacks/stack"
18
- require "ds/queues/queue"
19
- require "ds/queues/priority_queue"
20
-
21
- require "ds/trees/tree"
22
- require "ds/trees/tree_walker"
23
- require "ds/trees/binary_tree"
24
- require "ds/trees/binary_search_tree"
25
- require "ds/trees/complete_binary_tree"
26
- require "ds/trees/binary_heap"
27
- require "ds/trees/trie"
28
-
29
- require "ds/graphs/edge"
30
- require "ds/graphs/graph_as_matrix"
31
- require "ds/graphs/graph_as_tri_matrix"
32
- require "ds/graphs/graph"
33
- require "ds/graphs/digraph"
10
+ require 'ds/sets/indexed_set'
34
11
 
12
+ require 'ds/lists/list_element'
13
+ require 'ds/lists/list'
35
14
 
15
+ require 'ds/stacks/stack'
16
+ require 'ds/queues/simple_queue'
17
+ require 'ds/queues/priority_queue'
36
18
 
19
+ require 'ds/trees/tree'
20
+ require 'ds/trees/tree_walker'
21
+ require 'ds/trees/binary_tree'
22
+ require 'ds/trees/binary_heap'
23
+ require 'ds/trees/red_black_tree'
24
+ require 'ds/trees/red_black_tree/node'
25
+ require 'ds/trees/trie'
26
+ require 'ds/trees/trie/node'
@@ -1,17 +1,13 @@
1
1
  module DS
2
-
3
- #Implements two dimensional array.
2
+ # Implements two dimensional array.
4
3
  class Array2D
5
-
6
-
7
- #Creates new two dimensional array. Init is the default value of the array.
8
- def initialize(size=1,init=0)
4
+ # Creates new two dimensional array. Init is the default value of the array.
5
+ def initialize(size = 1, init = 0)
9
6
  @init = init
10
- @store = Array.new(size){Array.new(size){init}}
7
+ @store = Array.new(size) { Array.new(size) { init } }
11
8
  end
12
9
 
13
-
14
- def [](x,y)
10
+ def [](x, y)
15
11
  if @store[x].nil?
16
12
  @store[x] = []
17
13
  @init
@@ -22,7 +18,7 @@ module DS
22
18
  end
23
19
  end
24
20
 
25
- def []=(x,y,v)
21
+ def []=(x, y, v)
26
22
  @store[x] = [] if @store[x].nil?
27
23
  @store[x][y] = v
28
24
  end
@@ -35,5 +31,8 @@ module DS
35
31
  @store.flatten
36
32
  end
37
33
 
34
+ def size
35
+ @store.size
36
+ end
38
37
  end
39
38
  end
@@ -0,0 +1,34 @@
1
+ module DS
2
+ # Class provides access to any element in array. If index i
3
+ # is greter than array size then elements from size to i are
4
+ # filled with extender.
5
+ class ExpandableArray < Array
6
+ def initialize(size = 0, extender = 0)
7
+ @extender = extender
8
+ super(size, extender)
9
+ end
10
+
11
+ # Returns element at index. If index is greater than size of array then
12
+ # elements from size to index are filled with extender.
13
+ def [](x)
14
+ expand(size, x) if x >= size
15
+ super(x)
16
+ end
17
+
18
+ # Sets the element at index. If index is greater than size of array then
19
+ # elements from size to index are filled with extender.
20
+ def []=(x, v)
21
+ old_size = size
22
+ super(x, v)
23
+ expand(old_size, size - 2) if size - old_size > 1
24
+ end
25
+
26
+ private
27
+
28
+ def expand(from, to)
29
+ (from..to).each do |i|
30
+ self[i] = @extender
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,32 @@
1
+ require 'forwardable'
2
+
3
+ module DS
4
+ # Simple Array-like data structure with indexing starting from one.
5
+ class HeapStore
6
+ extend Forwardable
7
+
8
+ def_delegators :@store, :push, :pop, :[], :[]=
9
+
10
+ def initialize(*args)
11
+ @store = [nil] + args.to_a
12
+ end
13
+
14
+ def length
15
+ @store.size - 1
16
+ end
17
+
18
+ def first
19
+ @store[1]
20
+ end
21
+
22
+ alias size length
23
+
24
+ def empty?
25
+ length <= 0
26
+ end
27
+
28
+ def to_a
29
+ @store[1..-1]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ module DS
2
+ # Class implements Triangular Matrix (lower).
3
+ class TriMatrix
4
+ # Creates new triangular matrix.
5
+ def initialize(init = 0)
6
+ @store = ExpandableArray.new(0, init)
7
+ @max = 0
8
+ end
9
+
10
+ # Returns element at index x,y (or y,x).
11
+ def [](x, y)
12
+ x, y = y, x if y > x
13
+ index = (x * x + x) / 2 + y
14
+ @store[index]
15
+ end
16
+
17
+ # Sets the element at index x,y (or y,x).
18
+ def []=(x, y, v)
19
+ x, y = y, x if y > x
20
+ index = (x * x + x) / 2 + y
21
+ @max = x if x > @max
22
+ @store[index] = v
23
+ end
24
+
25
+ def to_a
26
+ @store
27
+ end
28
+
29
+ def size
30
+ @max
31
+ end
32
+ end
33
+ end
@@ -1,300 +1,424 @@
1
1
  module DS
2
+ class ListError < StandardError; end
2
3
 
3
- #Implements simple list data structure.
4
+ # Implements simple list data structure.
4
5
  class List
5
-
6
6
  include Enumerable
7
+ include Comparable
7
8
 
8
9
  attr_accessor :head, :tail
9
10
 
10
- #Creates new list.
11
- def initialize(x=nil)
12
- @head = ListElement.new(x)
13
- @tail = @head
11
+ # Creates new list.
12
+ def initialize(*arr)
13
+ @size = 0
14
+ @head = nil
15
+ @tail = nil
16
+ from_array(arr) if arr.any?
14
17
  end
15
18
 
16
- #Creates list from array.
17
- def self.from_array(arr)
18
- list = new(arr.shift)
19
- tail = list.head
20
- arr.each{ |e| tail = tail.append(e) }
21
- list.tail = tail
19
+ # Clones list
20
+ def clone
21
+ list = self.class.new
22
+ each { |e| list.append(e.data) }
22
23
  list
23
24
  end
24
25
 
25
- #Appends new element to list.
26
+ # Clears list by reseting head and tail to nil
27
+ def clear
28
+ @size = 0
29
+ @head = nil
30
+ @tail = nil
31
+ end
32
+
33
+ # Appends new element to list. Returns list tail
26
34
  def append(x)
27
- last_elem = self.tail
28
35
  if !empty?
29
- @tail = last_elem.append(x)
36
+ @tail = tail.append(x)
37
+ increment_size
30
38
  else
31
- @head = ListElement.new(x)
32
- @tail = @head
39
+ create_first(x)
33
40
  end
41
+ @tail
34
42
  end
35
43
 
36
- alias :<< :append
44
+ alias << append
45
+ alias push append
37
46
 
38
- #Prepends new element to list.
39
- def prepend(x)
47
+ # Prepends new element to list. Returns list head
48
+ def unshift(x)
40
49
  el = ListElement.new(x)
41
50
  el.next = @head
51
+ @head.prev = el if @head
52
+
53
+ increment_size
42
54
  @head = el
43
55
  end
44
56
 
45
- #Removes element x from list.
46
- def remove(x)
47
- if x == head
48
- self.head = head.next
49
- x.next = nil
50
- else
57
+ # Removes list head.
58
+ def shift
59
+ raise ListError, 'List already empty' if empty?
60
+ remove(head).data
61
+ end
51
62
 
52
- el = head
53
- while el and el != x
54
- prev = el
55
- el = el.next
56
- end
63
+ # Return ListElement if it is on list otherwise returns nil
64
+ def get(x)
65
+ el = head
66
+ el = el.next while el && el != x
67
+ el
68
+ end
57
69
 
58
- raise ListError, "Element not found" unless el
70
+ # Return ListElement if it is on list or raises error
71
+ def get!(x)
72
+ found = get(x)
73
+ raise ListError, 'Element not found' unless found
74
+ end
59
75
 
60
- prev.next = el.next
61
- el.next = nil
76
+ # Returns list element on given index.
77
+ def at(index)
78
+ found = nil
79
+ find_index = lambda do |element, i|
80
+ if i == index
81
+ found = element
82
+ break
83
+ end
62
84
  end
63
- x
85
+ if index >= 0
86
+ each_with_index(&find_index)
87
+ else
88
+ reverse_each(&find_index)
89
+ end
90
+ found
64
91
  end
65
92
 
66
- #Removes list head.
67
- def shift
68
- remove(head).data
93
+ # Returns list element on given index.
94
+ def [](i, count = nil)
95
+ return [] if count && count < 0
96
+ i = (i...i + count) if count && count > 0
97
+ case i
98
+ when Integer
99
+ at(i)
100
+ when Range
101
+ elements_in_range(i)
102
+ end
69
103
  end
70
104
 
71
- #Inserts element x after another element.
72
- def insert_after(x,rel)
73
- x = ListElement.new(x)
74
-
75
- el = head
76
- while el and el != rel
77
- el = el.next
105
+ # Sets list element on given index.
106
+ def []=(i, count = 1, val)
107
+ if i.is_a? Range
108
+ index = i.first
109
+ count = i.size
110
+ else
111
+ index = i
78
112
  end
79
113
 
80
- raise "Element not found" unless el
114
+ raise ListError, 'Ivalid count parameter' unless valid_count?(count, index)
81
115
 
82
- x.next = el.next
83
- el.next = x
116
+ el = at(index)
117
+ raise ListError, 'Element not found' unless el
118
+ if val.is_a? Array
119
+ replace(el, List.new(*val), count)
120
+ else
121
+ el.data = val
122
+ end
123
+ end
84
124
 
85
- if x.tail?
86
- self.tail = x
125
+ # Replaces list elements with other list
126
+ def replace(el, list, count = 1)
127
+ if el.head?
128
+ replace_head(el, list, count)
129
+ elsif el.tail?
130
+ replace_tail(el, list, count)
131
+ else
132
+ replace_inside(el, list, count)
87
133
  end
88
134
  end
89
135
 
90
- #Inserts element x before another element.
91
- def insert_before(x,rel)
92
- x = ListElement.new(x)
136
+ # Checks if two lists are equal
137
+ def <=>(other)
138
+ a = head
139
+ b = other.head
140
+ while a && b && a.data == b.data
141
+ a = a.next
142
+ b = b.next
143
+ end
144
+ compare_list_elements(a, b)
145
+ end
93
146
 
94
- #inserting at the beginnig of the list
147
+ # Appends one list to other
148
+ def concat(other)
149
+ other.head.prev = tail
150
+ tail.next = other.head
151
+ self.tail = other.tail
152
+ @size += other.size
153
+ self
154
+ end
155
+
156
+ # Inserts element x after another element.
157
+ def insert_after(x, rel)
158
+ x = ListElement.new(x)
159
+
160
+ el = rel
161
+ nxt = el.next
162
+ x.next = nxt
163
+ nxt.prev = x if nxt
164
+ el.next = x
165
+ x.prev = el
166
+ self.tail = x if x.nil?
167
+
168
+ increment_size
169
+
170
+ self
171
+ end
172
+
173
+ # Inserts element x before another element.
174
+ def insert_before(x, rel)
95
175
  if rel == head
96
- x.next = head
97
- self.head = x
176
+ unshift(x)
177
+ else
178
+ x = ListElement.new(x)
179
+
180
+ prev = rel.prev
181
+ prev.next = x
182
+ x.prev = prev
183
+ x.next = rel
184
+ rel.prev = x
185
+ end
186
+ increment_size
187
+ self
188
+ end
98
189
 
99
- #inserting in the tail of the list
190
+ # Removes element x from list.
191
+ def remove(x)
192
+ if x == head
193
+ self.head = head.next
194
+ x.next = nil
195
+ head.prev = nil if head
100
196
  else
101
- el = head
102
- prev = head
103
- while el and el != rel
104
- prev = el
105
- el = el.next
106
- end
197
+ nxt = x.next
198
+ prev = x.prev
199
+ prev.next = nxt
200
+ nxt.prev = prev if nxt
201
+ x.next = nil
202
+ x.prev = nil
107
203
 
108
- if el.nil?
109
- raise ListError, "List element not found"
110
- else
111
- prev.next = x
112
- x.next = el
113
- end
204
+ self.tail = prev if nxt.nil?
114
205
  end
206
+ decrement_size
207
+ x
115
208
  end
116
209
 
210
+ # Removes last element from list.
211
+ def pop
212
+ remove(tail).data
213
+ end
117
214
 
118
- #Checks if list is empty.
215
+ # Checks if list is empty.
119
216
  def empty?
120
- head.data.nil?
217
+ @size.zero?
121
218
  end
122
219
 
123
- #Returns last element of the list.
220
+ # Returns last element of the list.
124
221
  def last
125
222
  tail.data
126
223
  end
127
224
 
225
+ # Returns first element of the list.
128
226
  def first
129
227
  head.data
130
228
  end
131
229
 
132
- #Returns length of the list.
230
+ # Returns length of the list.
133
231
  def length
134
- count
232
+ @size
135
233
  end
136
234
 
137
- #Checks if list is linked at the end with other list.
235
+ alias size length
236
+
237
+ # Checks if list is linked at the end with other list.
138
238
  def zip?(other)
139
- tail.equal? other.tail
239
+ tail.equal? other.tail
140
240
  end
141
241
 
142
- #Returns joint element if exists, otherwise returns nil.
242
+ # Returns joint element if exists, otherwise returns nil.
143
243
  def joint
144
244
  elem = head
145
245
  elem2 = elem.next
146
246
 
147
- while elem and elem2
247
+ while elem && elem2
148
248
 
149
- #traversing by 1
249
+ # traversing by 1
150
250
  elem = elem.next
151
251
 
152
- #traversing by 2
252
+ # traversing by 2
153
253
  elem2 = elem2.next
154
254
  elem2 = elem2.next if elem2
155
255
 
156
- if elem2.equal? elem
157
- return elem
158
- end
256
+ return elem if elem2.equal? elem
159
257
  end
160
-
161
258
  nil
162
259
  end
163
260
 
164
- #Returns true if list has cycle.
261
+ # Returns true if list has cycle.
165
262
  def looped?
166
- !!joint
263
+ !joint.nil?
167
264
  end
168
265
 
266
+ # Returns cycle size or nil if list has no cycles
267
+ def cycle_size
268
+ return unless looped?
269
+ counter = 0
270
+ start = joint
271
+ if start
272
+ counter = 1
273
+ elem = start.next
274
+ while elem != start
275
+ elem = elem.next
276
+ counter += 1
277
+ end
278
+ end
279
+ counter
280
+ end
169
281
 
170
- #Orderize list by evaluating block. Block should evaluate to one of these
171
- #values: 1,0,-1 (same as Comparable).
172
- def orderize
173
-
174
- zero = List.new
175
- plus = List.new
176
- minus = List.new
282
+ # Reverses list.
283
+ def reverse!
284
+ @tail = head
285
+ prev = head
286
+ elem = prev.next
287
+ prev.next = nil
288
+ while elem
289
+ nxt = elem.next
290
+ elem.next = prev
291
+ prev.prev = elem
292
+ prev = elem
293
+ elem = nxt
294
+ end
177
295
 
178
- el = self.head
296
+ @head = prev
297
+ self
298
+ end
179
299
 
180
- while el
181
- case yield el.data
182
- when 0
183
- zero_tail = zero.append(el.data)
184
- when 1
185
- plus_tail = plus.append(el.data)
186
- when -1
187
- minus_tail = minus.append(el.data)
188
- end
300
+ # Converts list to array.
301
+ def to_a
302
+ map(&:data)
303
+ end
189
304
 
190
- el = el.next
305
+ # Default list iterator.
306
+ def each
307
+ elem = head
308
+ while elem
309
+ yield elem
310
+ elem = elem.next
191
311
  end
192
-
193
- minus_tail.next = zero.head
194
- zero_tail.next = plus.head
195
- return minus
196
312
  end
197
313
 
314
+ # Reverse list iterator.
315
+ def reverse_each
316
+ elem = tail
317
+ i = 0
318
+ while elem
319
+ i -= 1
320
+ yield elem, i
321
+ elem = elem.prev
322
+ end
323
+ end
198
324
 
199
- # Removes elements that exists on the other list.
200
- def remove!(other)
201
- a = head
202
- b = other.head
325
+ def to_s
326
+ to_a.join('=')
327
+ end
203
328
 
204
- while a and b
329
+ private
205
330
 
206
- while a.data < b.data
207
- prev = a
208
- a = a.next
209
- end
331
+ def from_array(arr)
332
+ create_first(arr.shift)
333
+ arr.each { |e| append(e) }
334
+ end
210
335
 
211
- while b.data < a.data
212
- b = b.next
213
- end
336
+ # Creates first element in list.
337
+ def create_first(x)
338
+ first = unshift(x)
339
+ self.head = first
340
+ self.tail = first
341
+ self
342
+ end
214
343
 
215
- if prev.nil?
216
- prev = a
217
- a = a.next
218
- prev.next = nil
219
- self.head = a
220
- b = b.next
221
- else
222
- a = a.next
223
- prev.next = a
224
- b = b.next
225
- end
344
+ def elements_in_range(range)
345
+ arr = []
346
+ each_with_index do |e, i|
347
+ arr << e if range.include?(i)
226
348
  end
227
- self
349
+ arr
228
350
  end
229
351
 
230
- # Merge list with other list.
231
- def merge(other)
352
+ def increment_size
353
+ @size += 1
354
+ end
232
355
 
233
- a = self.head
234
- b = other.head
356
+ def decrement_size
357
+ @size -= 1
358
+ end
235
359
 
236
- if a.data < b.data
237
- result = List.new(a.data)
238
- a = a.next
360
+ def compare_list_elements(a, b)
361
+ if a.nil? && b.nil?
362
+ 0
363
+ elsif a && b
364
+ a.data <=> b.data
365
+ elsif a.nil?
366
+ -1
239
367
  else
240
- result = List.new(b.data)
241
- b = b.next
368
+ 1
242
369
  end
370
+ end
243
371
 
244
- while a and b
245
- if a.data < b.data
246
- result.append(a.data)
247
- a = a.next
248
- else
249
- result.append(b.data)
250
- b = b.next
251
- end
252
- end
253
- if !b
254
- result.tail.next = a
255
- result.tail = self.tail
256
- elsif !a
257
- result.tail.next = b
258
- result.tail = other.tail
259
- end
260
- result
372
+ def valid_count?(count, index)
373
+ return true if count.nil?
374
+ !(count < 1 || count + index > size)
261
375
  end
262
376
 
263
- #Reverses list.
264
- def reverse!
265
- @tail = self.head
266
- prev = self.head
267
- elem = prev.next
268
- prev.next = nil
269
- while elem
270
- nxt = elem.next
271
- elem.next = prev
272
- prev = elem
273
- elem = nxt
377
+ def replace_head(el, list, count)
378
+ count.times do
379
+ temp = el.next
380
+ remove(el)
381
+ el = temp
274
382
  end
275
-
276
- @head = prev
277
- self
383
+ list.concat self
384
+ @size = list.size
385
+ self.head = list.head
278
386
  end
279
387
 
280
-
281
- #Converts list to array.
282
- def to_a
283
- map { |e| e.data}
388
+ def replace_tail(el, list, count)
389
+ count.times do
390
+ temp = el.next
391
+ remove(el)
392
+ el = temp
393
+ end
394
+ concat list
284
395
  end
285
396
 
286
- #Default list iterator.
287
- def each
288
- elem = @head
289
- while elem
290
- yield elem
291
- elem = elem.next
397
+ def replace_inside(el, list, count)
398
+ first = el
399
+ last = find_last_element(el, count)
400
+ if last.tail?
401
+ self.tail = list.tail
402
+ else
403
+ nxt = last.next
404
+ nxt.prev = list.tail
405
+ list.tail.next = nxt
406
+ last.next = nil
292
407
  end
408
+ prev = first.prev
409
+ list.head.prev = prev
410
+ prev.next = list.head
411
+ first.prev = nil
412
+ @size = @size - count + list.size
293
413
  end
294
414
 
415
+ def find_last_element(el, count)
416
+ last = el
417
+ (count - 1).times do
418
+ temp = last.next if last.next
419
+ last = temp
420
+ end
421
+ last
422
+ end
295
423
  end
296
-
297
- class ListError < StandardError
298
- end
299
-
300
424
  end