algorithmable 0.8.0 → 0.9.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.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d896f5d72bec04a61e50d79c670e1ed9379b8cd
|
4
|
+
data.tar.gz: 701a49b6cb2d478a817baaef1ce743498a62813b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45b738fc98edaaf14ee58050bdf24f8d78345fcda7b6d06394d1d6d9cc26dbb9151ea6832f27a3fd05d4906b1c9e80e7fb3d2684e70080574edb1aeacf12e4ab
|
7
|
+
data.tar.gz: 404eca38ab9c2775ba3f07d6760f2f37cbf303d5b59f36bbbf6fc03af59abe028d3b8bed31ada0c2b747f15eb5eefa92fec78cad1a0bbdaaa9e4c94b0446acfb
|
data/README.md
CHANGED
@@ -2,7 +2,45 @@
|
|
2
2
|
|
3
3
|
# Algorithmable
|
4
4
|
|
5
|
-
Useful algorithms such as Sorting, Searches
|
5
|
+
Useful algorithms such as Sorting Strategies, Searches and Data Structures such as symbol tables, binary search tree BST, red black tree RBT,
|
6
|
+
hash tables, bag, linked list, deque, queue FIFO, stack LIFO, graphs & Graph Traversal strategies for everyday usage.
|
7
|
+
|
8
|
+
Algorithms and Data Structures implemented using Ruby, for fun.
|
9
|
+
|
10
|
+
Library also contains solutions for several puzzles solved by implemented algorithms and data structures.
|
11
|
+
|
12
|
+
## Data Structures
|
13
|
+
|
14
|
+
- Bag (primitive collection without ability to delete elements)
|
15
|
+
- Doubly Linked List
|
16
|
+
- Deque (double-ended queue)
|
17
|
+
- Queue (FIFO)
|
18
|
+
- Stack (LIFO)
|
19
|
+
- Ordered Symbol Table BST. Implementation using Unbalanced Binary Search Tree.
|
20
|
+
|
21
|
+
## Graphs
|
22
|
+
|
23
|
+
- Undirected graph
|
24
|
+
|
25
|
+
## Graph Traversals
|
26
|
+
|
27
|
+
- Breadth First Search (BFS)
|
28
|
+
- Death First Search (DFS)
|
29
|
+
|
30
|
+
## Search Algorithms
|
31
|
+
|
32
|
+
- Binary Search
|
33
|
+
|
34
|
+
## Sorting Algorithms
|
35
|
+
|
36
|
+
- Bubble sort
|
37
|
+
- Merge sort
|
38
|
+
- Heapsort ( Binary Heap )
|
39
|
+
|
40
|
+
# Usage
|
41
|
+
|
42
|
+
It is always better to check unit tests in order to understand how things going on.
|
43
|
+
Most of the components are encapsulated through the factory methods, so the are could be mixed to other objects.
|
6
44
|
|
7
45
|
## Installation
|
8
46
|
|
@@ -20,8 +58,6 @@ Or install it yourself as:
|
|
20
58
|
|
21
59
|
$ gem install algorithmable
|
22
60
|
|
23
|
-
## Usage
|
24
|
-
|
25
61
|
## Contributing
|
26
62
|
|
27
63
|
Bug reports and pull requests are welcome on GitHub at https://github.com/rlishtaba/algorithmable. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
@@ -0,0 +1,240 @@
|
|
1
|
+
module Algorithmable
|
2
|
+
module DataStructs
|
3
|
+
#
|
4
|
+
# Ordered Symbol Table. Implementation using Unbalanced Binary Tree.
|
5
|
+
#
|
6
|
+
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
|
226
|
+
|
227
|
+
class Node
|
228
|
+
attr_accessor :key, :value, :left, :right, :size
|
229
|
+
|
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
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -5,6 +5,7 @@ module Algorithmable
|
|
5
5
|
autoload :LinkedList, 'algorithmable/data_structs/linked_list'
|
6
6
|
autoload :Queue, 'algorithmable/data_structs/queue'
|
7
7
|
autoload :Stack, 'algorithmable/data_structs/stack'
|
8
|
+
autoload :OrderedSymbolTable, 'algorithmable/data_structs/ordered_symbol_table'
|
8
9
|
|
9
10
|
def new_bag
|
10
11
|
Bag.new
|
@@ -21,5 +22,9 @@ module Algorithmable
|
|
21
22
|
def new_lifo_queue
|
22
23
|
Stack.new
|
23
24
|
end
|
25
|
+
|
26
|
+
def new_ordered_symbol_table(key_type, value_type)
|
27
|
+
OrderedSymbolTable.new(key_type, value_type)
|
28
|
+
end
|
24
29
|
end
|
25
30
|
end
|
@@ -6,15 +6,17 @@ module Algorithmable
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def lookup(element, collection)
|
9
|
+
return if element.nil?
|
9
10
|
traverse element, collection, 0, collection.length - 1
|
10
11
|
end
|
11
12
|
|
12
13
|
def traverse(element, collection, low, high)
|
13
14
|
while low <= high
|
14
15
|
mid = low + (high - low) / 2
|
15
|
-
|
16
|
+
value_at = collection[mid]
|
17
|
+
if element < value_at
|
16
18
|
high = mid.pred
|
17
|
-
elsif element >
|
19
|
+
elsif element > value_at
|
18
20
|
low = mid.next
|
19
21
|
else
|
20
22
|
return mid
|
data/lib/algorithmable/search.rb
CHANGED
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.
|
4
|
+
version: 0.9.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-
|
11
|
+
date: 2016-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -144,6 +144,7 @@ files:
|
|
144
144
|
- lib/algorithmable/data_structs/bag.rb
|
145
145
|
- lib/algorithmable/data_structs/deque.rb
|
146
146
|
- lib/algorithmable/data_structs/linked_list.rb
|
147
|
+
- lib/algorithmable/data_structs/ordered_symbol_table.rb
|
147
148
|
- lib/algorithmable/data_structs/queue.rb
|
148
149
|
- lib/algorithmable/data_structs/stack.rb
|
149
150
|
- lib/algorithmable/errors.rb
|