algorithmable 0.9.0 → 0.10.0

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: 3d896f5d72bec04a61e50d79c670e1ed9379b8cd
4
- data.tar.gz: 701a49b6cb2d478a817baaef1ce743498a62813b
3
+ metadata.gz: e0f425945316b488e5f78067168f54dd56415392
4
+ data.tar.gz: c9dd9353cf0883de156a9860472d18233c227ea2
5
5
  SHA512:
6
- metadata.gz: 45b738fc98edaaf14ee58050bdf24f8d78345fcda7b6d06394d1d6d9cc26dbb9151ea6832f27a3fd05d4906b1c9e80e7fb3d2684e70080574edb1aeacf12e4ab
7
- data.tar.gz: 404eca38ab9c2775ba3f07d6760f2f37cbf303d5b59f36bbbf6fc03af59abe028d3b8bed31ada0c2b747f15eb5eefa92fec78cad1a0bbdaaa9e4c94b0446acfb
6
+ metadata.gz: 6fd0bb3ef1d1f3fe956aaa0fce478fcd1dc474d54b02ea86619802873ab620d181f3e49c7fefaf86c805fdd917f69e00d5a2e6f50f5971d97afb2462a91d62af
7
+ data.tar.gz: 5bdbf61cfb48f980c4d3d3721b7fc48a3f2c6aa26a249753b27bae965e83b41886855cbdae5e5b5904cbc621a3ee03456b826ee0e9345c1b59e338340dee923e
data/README.md CHANGED
@@ -25,7 +25,7 @@ Library also contains solutions for several puzzles solved by implemented algori
25
25
  ## Graph Traversals
26
26
 
27
27
  - Breadth First Search (BFS)
28
- - Death First Search (DFS)
28
+ - Depth First Search (DFS)
29
29
 
30
30
  ## Search Algorithms
31
31
 
@@ -37,6 +37,7 @@ module Algorithmable
37
37
  @succ.each(&block) if @succ
38
38
  end
39
39
  end
40
+ private_constant :Node
40
41
  end
41
42
  end
42
43
  end
@@ -1,10 +1,11 @@
1
1
  module Algorithmable
2
2
  module DataStructs
3
3
  class Deque
4
- include Enumerable
5
4
  include Algorithmable::Errors
6
5
 
7
6
  Node = Struct.new(:prev, :next, :item)
7
+ private_constant :Node
8
+
8
9
  attr_reader :size
9
10
 
10
11
  def initialize(collection = [])
@@ -89,23 +90,37 @@ module Algorithmable
89
90
  end
90
91
 
91
92
  # represent fifo iterator
92
- def each
93
- return unless @front
94
- node = @front
95
- while node
96
- yield node.item
97
- node = node.next
98
- end
93
+ def each(&block)
94
+ collect_items(:forward).each(&block)
99
95
  end
100
96
 
101
97
  # represent lifo iterator
102
- def reverse_each
103
- return unless @back
104
- node = @back
105
- while node
106
- yield node.item
107
- node = node.prev
98
+ def reverse_each(&block)
99
+ collect_items(:backward).each(&block)
100
+ end
101
+
102
+ def to_a
103
+ each.to_a
104
+ end
105
+
106
+ def map(&block)
107
+ each.map(&block)
108
+ end
109
+
110
+ private
111
+
112
+ def collect_items(order)
113
+ variable = order == :backward ? @back : @front
114
+ action = order == :backward ? :prev : :next
115
+ items = []
116
+ if variable
117
+ node = variable
118
+ while node
119
+ items << node.item
120
+ node = node.public_send action
121
+ end
108
122
  end
123
+ items
109
124
  end
110
125
  end
111
126
  end
@@ -95,6 +95,7 @@ module Algorithmable
95
95
  @succ = succ
96
96
  end
97
97
  end
98
+ private_constant :Node
98
99
  end
99
100
  end
100
101
  end
@@ -1,239 +1,13 @@
1
1
  module Algorithmable
2
2
  module DataStructs
3
- #
4
- # Ordered Symbol Table. Implementation using Unbalanced Binary Tree.
5
- #
6
3
  class OrderedSymbolTable
7
- def initialize(key_type, value_type)
8
- @key_type = key_type
9
- @value_type = value_type
10
- @root = nil
11
- end
12
-
13
- def empty?
14
- !size.nonzero?
15
- end
16
-
17
- def size
18
- node_size(@root)
19
- end
20
-
21
- def key?(key)
22
- assert_key_type(key)
23
- !self[key].nil?
24
- end
25
-
26
- def [](key)
27
- assert_key_type(key)
28
- impl_get(@root, key)
29
- end
30
-
31
- def []=(key, value)
32
- assert_value_type(value)
33
- assert_key_type(key)
34
- delete key
35
- @root = impl_put(@root, key, value)
36
- check_tree
37
- end
38
-
39
- def delete_min
40
- @root = impl_delete_min @root
41
- check_tree
42
- end
43
-
44
- def delete_max
45
- @root = impl_delete_max @root
46
- check_tree
47
- end
48
-
49
- def delete(key)
50
- assert_key_type(key)
51
- @root = impl_delete(@root, key)
52
- check_tree
53
- end
54
-
55
- def min
56
- impl_min(@root).key
57
- end
58
-
59
- def max
60
- impl_max(@root).key
61
- end
62
-
63
- def floor(key)
64
- assert_key_type(key)
65
- return unless key || empty?
66
- found = impl_floor(@root, key)
67
- return unless found
68
- found.key
69
- end
70
-
71
- def ceiling(key)
72
- assert_key_type(key)
73
- return unless key || empty?
74
- found = impl_ceiling(@root, key)
75
- return unless found
76
- found.key
77
- end
78
-
79
- def select(integer)
80
- return if integer < 0 || integer >= size
81
- found = impl_select(@root, integer)
82
- found.key
83
- end
84
-
85
- def rank(key)
86
- assert_key_type(key)
87
- return unless key
88
- impl_rank @root, key
89
- end
90
-
91
- private
92
-
93
- def check_tree
94
- true
95
- end
96
-
97
- def assert_value_type(value)
98
- fail "Type expectation not met. Use value type `#{@value_type}` instead." unless value.is_a? @value_type
99
- end
100
-
101
- def assert_key_type(key)
102
- fail "Type expectation not met. Use key type `#{@key_type}` instead." unless key.is_a? @key_type
103
- end
104
-
105
- def impl_rank(node, key)
106
- return 0 unless node
107
- comparison = key <=> node.key
108
- if comparison < 0
109
- impl_rank(node.left, key)
110
- elsif comparison > 0
111
- 1 + node_size(node.left) + impl_rank(node.right, key)
112
- else
113
- node_size node.left
114
- end
115
- end
116
-
117
- def impl_select(node, index)
118
- return unless node
119
- left_size = node_size(node.left)
120
- if left_size > index
121
- impl_select(node.left, index)
122
- elsif left_size < index
123
- impl_select node.right, (index - left_size - 1)
124
- else
125
- node
126
- end
127
- end
128
-
129
- def impl_ceiling(node, key)
130
- return unless node
131
- comparison = key <=> node.key
132
- return node if 0 == comparison
133
- if comparison < 0
134
- found = impl_ceiling(node.left, key)
135
- return found if found
136
- return node
137
- end
138
- impl_ceiling node.right, key
139
- end
140
-
141
- def impl_floor(node, key)
142
- return unless node
143
- comparison = key <=> node.key
144
- return node if 0 == comparison
145
- return impl_floor(node.left, key) if comparison < 0
146
- found = impl_floor(node.right, key)
147
- return found if found
148
- node
149
- end
150
-
151
- def impl_delete(node, key)
152
- return unless node
153
- comparison = key <=> node.key
154
- if comparison < 0
155
- node.left = impl_delete(node.left, key)
156
- elsif comparison > 0
157
- node.right = impl_delete(node.right, key)
158
- else
159
- return unless node.left || node.right
160
- temp = node
161
- node = impl_min(temp.right)
162
- node.right = impl_delete_min(temp.right)
163
- node.left = temp.left
164
- end
165
- node.size = computed_node_size(node)
166
- node
167
- end
168
-
169
- def impl_max(node)
170
- return node unless node.right
171
- impl_max node.right
172
- end
173
-
174
- def impl_min(node)
175
- return node unless node.left
176
- impl_min node.left
177
- end
178
-
179
- def impl_delete_max(node)
180
- return node.left unless node.right
181
- node.right = impl_delete_max(node.right)
182
- node.size = computed_node_size(node)
183
- node
184
- end
185
-
186
- def impl_delete_min(node)
187
- return node.right unless node.left
188
- node.left = impl_delete_min(node.left)
189
- node.size = computed_node_size(node)
190
- node
191
- end
192
-
193
- def impl_put(node, key, value)
194
- return Node.new(key, value, 1) unless node
195
- comparison = key <=> node.key
196
- if comparison < 0
197
- node.left = impl_put(node.left, key, value)
198
- elsif comparison > 0
199
- node.right = impl_put(node.right, key, value)
200
- else
201
- node.value = value
202
- end
203
- node.size = computed_node_size(node)
204
- node
205
- end
206
-
207
- def impl_get(node, key)
208
- return unless node
209
- comparison = key <=> node.key
210
- if comparison < 0
211
- impl_get(node.left, key)
212
- elsif comparison > 0
213
- impl_get(node.right, key)
214
- else
215
- node.value
216
- end
217
- end
218
-
219
- def node_size(node)
220
- node.nil? ? 0 : node.size
221
- end
222
-
223
- def computed_node_size(node)
224
- 1 + node_size(node.left) + node_size(node.right)
225
- end
4
+ extend Forwardable
226
5
 
227
- class Node
228
- attr_accessor :key, :value, :left, :right, :size
6
+ def_delegators :@imp, :[]=, :[], :key?, :empty?, :size, :keys, :max, :min, :floor, :ceiling, :rank, :delete
229
7
 
230
- def initialize(key = nil, value = nil, size = 0)
231
- @key = key
232
- @value = value
233
- @left = nil
234
- @right = nil
235
- @size = size
236
- end
8
+ def initialize(key_type, value_type)
9
+ search_strategy_factory = Object.new.extend Algorithmable::Searches
10
+ @imp = search_strategy_factory.new_binary_search_tree(key_type, value_type)
237
11
  end
238
12
  end
239
13
  end
@@ -2,10 +2,9 @@ module Algorithmable
2
2
  module DataStructs
3
3
  class Queue
4
4
  include Algorithmable::Errors
5
- include Enumerable
6
5
  extend Forwardable
7
6
 
8
- def_delegators :@imp, :empty?, :size, :each
7
+ def_delegators :@imp, :empty?, :size, :each, :map, :to_a
9
8
 
10
9
  def initialize(collection = [])
11
10
  @imp = Deque.new collection
@@ -2,10 +2,9 @@ module Algorithmable
2
2
  module DataStructs
3
3
  class Stack
4
4
  include Algorithmable::Errors
5
- include Enumerable
6
5
  extend Forwardable
7
6
 
8
- def_delegators :@imp, :empty?, :size, :each
7
+ def_delegators :@imp, :empty?, :size, :each, :map, :to_a
9
8
 
10
9
  def initialize(collection = [])
11
10
  @imp = Deque.new
@@ -1,6 +1,6 @@
1
1
  module Algorithmable
2
- module Search
3
- class Binary
2
+ module Searches
3
+ class BinarySearch
4
4
  def self.lookup(element, in_collection)
5
5
  new.lookup(element, in_collection)
6
6
  end
@@ -0,0 +1,291 @@
1
+ module Algorithmable
2
+ module Searches
3
+ class BinarySearchTree
4
+ def initialize(key_type, value_type)
5
+ @key_type = key_type
6
+ @value_type = value_type
7
+ @root = nil
8
+ end
9
+
10
+ def empty?
11
+ !size.nonzero?
12
+ end
13
+
14
+ def size
15
+ node_size(@root)
16
+ end
17
+
18
+ def key?(key)
19
+ assert_key_type(key)
20
+ !self[key].nil?
21
+ end
22
+
23
+ def [](key)
24
+ assert_key_type(key)
25
+ impl_get(@root, key)
26
+ end
27
+
28
+ def []=(key, value)
29
+ assert_value_type(value)
30
+ assert_key_type(key)
31
+ delete key
32
+ @root = impl_put(@root, key, value)
33
+ check_tree_consistency
34
+ end
35
+
36
+ def delete_min
37
+ @root = impl_delete_min @root
38
+ check_tree_consistency
39
+ end
40
+
41
+ def delete_max
42
+ @root = impl_delete_max @root
43
+ check_tree_consistency
44
+ end
45
+
46
+ def delete(key)
47
+ assert_key_type(key)
48
+ @root = impl_delete(@root, key)
49
+ check_tree_consistency
50
+ end
51
+
52
+ def min
53
+ return if empty?
54
+ impl_min(@root).key
55
+ end
56
+
57
+ def max
58
+ return if empty?
59
+ impl_max(@root).key
60
+ end
61
+
62
+ def floor(key)
63
+ assert_key_type(key)
64
+ return unless key || empty?
65
+ found = impl_floor(@root, key)
66
+ return unless found
67
+ found.key
68
+ end
69
+
70
+ def ceiling(key)
71
+ assert_key_type(key)
72
+ return unless key || empty?
73
+ found = impl_ceiling(@root, key)
74
+ return unless found
75
+ found.key
76
+ end
77
+
78
+ def select(integer)
79
+ return if integer < 0 || integer >= size
80
+ found = impl_select(@root, integer)
81
+ found.key
82
+ end
83
+
84
+ def rank(key)
85
+ assert_key_type(key)
86
+ return unless key
87
+ impl_rank @root, key
88
+ end
89
+
90
+ def size_consistent?
91
+ impl_size_consistent?(@root)
92
+ end
93
+
94
+ def rank_consistent?
95
+ size.times do |time|
96
+ break false unless time != rank(select(time))
97
+ end
98
+ keys.each do |key|
99
+ comparison = key <=> select(rank(key))
100
+ break false if comparison != 0
101
+ end
102
+ true
103
+ end
104
+
105
+ def symmetric_ordered?
106
+ impl_symmetric_ordered? @root
107
+ end
108
+
109
+ def keys(low = min, high = max)
110
+ queue = Algorithmable::DataStructs::Queue.new
111
+ impl_keys @root, queue, low, high
112
+ queue
113
+ end
114
+
115
+ private
116
+
117
+ def check_tree_consistency
118
+ $stderr.puts 'Tree is not in symmetric order' unless a = symmetric_ordered?
119
+ $stderr.puts 'Tree has size inconsistency' unless b = size_consistent?
120
+ $stderr.puts 'Tree has ranking inconsistency' unless c = rank_consistent?
121
+ a && b && c
122
+ end
123
+
124
+ def impl_symmetric_ordered?(node, min_key = nil, max_key = nil)
125
+ return true unless node
126
+ return false if !min_key.nil? && (node.key <=> min_key) <= 0
127
+ return false if !max_key.nil? && (node.key <=> max_key) >= 0
128
+ impl_symmetric_ordered?(node.left, min_key, node.key) && impl_symmetric_ordered?(node.right, node.key, max_key)
129
+ end
130
+
131
+ def impl_keys(node, queue, low, high)
132
+ return unless node
133
+ cmp_low = low <=> node.key
134
+ cmp_high = high <=> node.key
135
+ impl_keys(node.left, queue, low, high) if cmp_low < 0
136
+ queue.enqueue node.key if cmp_low <= 0 && cmp_high >= 0
137
+ impl_keys(node.right, queue, low, high) if cmp_high > 0
138
+ end
139
+
140
+ def impl_size_consistent?(node)
141
+ return true unless node
142
+ return false if (node.size != node_size(node.left) + node_size(node.right) + 1)
143
+ impl_size_consistent?(node.left) && impl_size_consistent?(node.right)
144
+ end
145
+
146
+ def assert_value_type(value)
147
+ fail "Type expectation not met. Use value type `#{@value_type}` instead." unless value.is_a? @value_type
148
+ end
149
+
150
+ def assert_key_type(key)
151
+ fail "Type expectation not met. Use key type `#{@key_type}` instead." unless key.is_a? @key_type
152
+ end
153
+
154
+ def impl_rank(node, key)
155
+ return 0 unless node
156
+ comparison = key <=> node.key
157
+ if comparison < 0
158
+ impl_rank(node.left, key)
159
+ elsif comparison > 0
160
+ 1 + node_size(node.left) + impl_rank(node.right, key)
161
+ else
162
+ node_size node.left
163
+ end
164
+ end
165
+
166
+ def impl_select(node, index)
167
+ return unless node
168
+ left_size = node_size(node.left)
169
+ if left_size > index
170
+ impl_select(node.left, index)
171
+ elsif left_size < index
172
+ impl_select node.right, (index - left_size - 1)
173
+ else
174
+ node
175
+ end
176
+ end
177
+
178
+ def impl_ceiling(node, key)
179
+ return unless node
180
+ comparison = key <=> node.key
181
+ return node if 0 == comparison
182
+ if comparison < 0
183
+ found = impl_ceiling(node.left, key)
184
+ return found if found
185
+ return node
186
+ end
187
+ impl_ceiling node.right, key
188
+ end
189
+
190
+ def impl_floor(node, key)
191
+ return unless node
192
+ comparison = key <=> node.key
193
+ return node if 0 == comparison
194
+ return impl_floor(node.left, key) if comparison < 0
195
+ found = impl_floor(node.right, key)
196
+ return found if found
197
+ node
198
+ end
199
+
200
+ def impl_delete(node, key)
201
+ return unless node
202
+ comparison = key <=> node.key
203
+ if comparison < 0
204
+ node.left = impl_delete(node.left, key)
205
+ elsif comparison > 0
206
+ node.right = impl_delete(node.right, key)
207
+ else
208
+ return node.right if node.left.nil?
209
+ return node.left if node.right.nil?
210
+ temp = node
211
+ node = impl_min(temp.right)
212
+ node.right = impl_delete_min(temp.right)
213
+ node.left = temp.left
214
+ end
215
+ node.size = computed_node_size(node)
216
+ node
217
+ end
218
+
219
+ def impl_max(node)
220
+ return node unless node.right
221
+ impl_max node.right
222
+ end
223
+
224
+ def impl_min(node)
225
+ return node unless node.left
226
+ impl_min node.left
227
+ end
228
+
229
+ def impl_delete_max(node)
230
+ return node.left unless node.right
231
+ node.right = impl_delete_max(node.right)
232
+ node.size = computed_node_size(node)
233
+ node
234
+ end
235
+
236
+ def impl_delete_min(node)
237
+ return node.right unless node.left
238
+ node.left = impl_delete_min(node.left)
239
+ node.size = computed_node_size(node)
240
+ node
241
+ end
242
+
243
+ def impl_put(node, key, value)
244
+ return Node.new(key, value, 1) unless node
245
+ comparison = key <=> node.key
246
+ if comparison < 0
247
+ node.left = impl_put(node.left, key, value)
248
+ elsif comparison > 0
249
+ node.right = impl_put(node.right, key, value)
250
+ else
251
+ node.value = value
252
+ end
253
+ node.size = computed_node_size(node)
254
+ node
255
+ end
256
+
257
+ def impl_get(node, key)
258
+ return unless node
259
+ comparison = key <=> node.key
260
+ if comparison < 0
261
+ impl_get(node.left, key)
262
+ elsif comparison > 0
263
+ impl_get(node.right, key)
264
+ else
265
+ node.value
266
+ end
267
+ end
268
+
269
+ def node_size(node)
270
+ node.nil? ? 0 : node.size
271
+ end
272
+
273
+ def computed_node_size(node)
274
+ 1 + node_size(node.left) + node_size(node.right)
275
+ end
276
+
277
+ class Node
278
+ attr_accessor :key, :value, :left, :right, :size
279
+
280
+ def initialize(key = nil, value = nil, size = 0)
281
+ @key = key
282
+ @value = value
283
+ @left = nil
284
+ @right = nil
285
+ @size = size
286
+ end
287
+ end
288
+ private_constant :Node
289
+ end
290
+ end
291
+ end
@@ -0,0 +1,14 @@
1
+ module Algorithmable
2
+ module Searches
3
+ autoload :BinarySearch, 'algorithmable/search/binary_search'
4
+ autoload :BinarySearchTree, 'algorithmable/search/binary_search_tree'
5
+
6
+ def binary_search(element, collection)
7
+ BinarySearch.lookup(element, collection)
8
+ end
9
+
10
+ def new_binary_search_tree(key_type, value_type)
11
+ BinarySearchTree.new key_type, value_type
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Algorithmable
2
- VERSION = '0.9.0'
2
+ VERSION = '0.10.0'
3
3
  end
data/lib/algorithmable.rb CHANGED
@@ -7,7 +7,7 @@ require 'English'
7
7
  module Algorithmable
8
8
  autoload :Errors, 'algorithmable/errors'
9
9
  autoload :Sort, 'algorithmable/sort'
10
- autoload :Search, 'algorithmable/search'
10
+ autoload :Searches, 'algorithmable/searches'
11
11
  autoload :DataStructs, 'algorithmable/data_structs'
12
12
  autoload :Graphs, 'algorithmable/graphs'
13
13
  autoload :Puzzles, 'algorithmable/puzzles'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algorithmable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Lishtaba
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-01-09 00:00:00.000000000 Z
11
+ date: 2016-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -157,8 +157,9 @@ files:
157
157
  - lib/algorithmable/puzzles.rb
158
158
  - lib/algorithmable/puzzles/dijkstras_two_stacks.rb
159
159
  - lib/algorithmable/puzzles/josephus_problem.rb
160
- - lib/algorithmable/search.rb
161
- - lib/algorithmable/search/binary.rb
160
+ - lib/algorithmable/search/binary_search.rb
161
+ - lib/algorithmable/search/binary_search_tree.rb
162
+ - lib/algorithmable/searches.rb
162
163
  - lib/algorithmable/sort.rb
163
164
  - lib/algorithmable/sort/binary_heap.rb
164
165
  - lib/algorithmable/sort/bubble.rb
@@ -1,11 +0,0 @@
1
- module Algorithmable
2
- module Search
3
- autoload :Binary, 'algorithmable/search/binary'
4
-
5
- class << self
6
- def binary(element, collection)
7
- Binary.lookup(element, collection)
8
- end
9
- end
10
- end
11
- end