ds 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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