algorithmable 0.13.0 → 0.14.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 +4 -4
- data/.rubocop.yml +1 -1
- data/algorithmable.gemspec +1 -0
- data/lib/algorithmable/cache/imp.rb +19 -0
- data/lib/algorithmable/cache/primitive_max_heap.rb +38 -0
- data/lib/algorithmable/cache/primitive_min_heap.rb +38 -0
- data/lib/algorithmable/cache.rb +15 -0
- data/lib/algorithmable/cups/circular_dependencies.rb +27 -0
- data/lib/algorithmable/cups/longest_common_subsequence.rb +46 -0
- data/lib/algorithmable/cups/merge_two_arrays.rb +31 -0
- data/lib/algorithmable/cups/nested_lists_problem.rb +105 -0
- data/lib/algorithmable/cups/number_of_occurrences_in_array.rb +49 -0
- data/lib/algorithmable/cups/primitives.rb +205 -2
- data/lib/algorithmable/cups/root_cube_issue.rb +39 -0
- data/lib/algorithmable/cups/stacks_and_queues/stack_sorter.rb +25 -0
- data/lib/algorithmable/cups/stacks_and_queues/stack_with_min.rb +23 -0
- data/lib/algorithmable/cups/stacks_and_queues/towers_of_hanoi.rb +48 -0
- data/lib/algorithmable/cups/stacks_and_queues/triple_stack.rb +52 -0
- data/lib/algorithmable/cups/stacks_and_queues/two_stacks_queue.rb +37 -0
- data/lib/algorithmable/cups/stacks_and_queues.rb +31 -0
- data/lib/algorithmable/cups/stocks.rb +80 -0
- data/lib/algorithmable/cups/task_shedule_with_coldtime.rb +16 -0
- data/lib/algorithmable/cups/two_sum.rb +59 -0
- data/lib/algorithmable/cups.rb +7 -0
- data/lib/algorithmable/data_structs/linked_list/base.rb +21 -1
- data/lib/algorithmable/data_structs/linked_list/doubly.rb +1 -1
- data/lib/algorithmable/data_structs/linked_list/singly.rb +62 -1
- data/lib/algorithmable/data_structs/queue.rb +4 -0
- data/lib/algorithmable/data_structs/stack.rb +4 -0
- data/lib/algorithmable/data_structs/tree/binary.rb +10 -0
- data/lib/algorithmable/data_structs/tree/binary_search.rb +206 -0
- data/lib/algorithmable/data_structs/tree.rb +13 -0
- data/lib/algorithmable/data_structs.rb +6 -0
- data/lib/algorithmable/sort/bubble.rb +9 -16
- data/lib/algorithmable/sort/insertion.rb +24 -0
- data/lib/algorithmable/sort/merge.rb +4 -8
- data/lib/algorithmable/sort/quick_sort.rb +35 -0
- data/lib/algorithmable/sort/selection.rb +23 -0
- data/lib/algorithmable/sort/shell.rb +27 -0
- data/lib/algorithmable/sort/shuffle.rb +15 -0
- data/lib/algorithmable/sort/utils.rb +66 -0
- data/lib/algorithmable/sort.rb +28 -0
- data/lib/algorithmable/union_find.rb +51 -0
- data/lib/algorithmable/version.rb +1 -1
- data/lib/algorithmable.rb +2 -0
- data/script/benchmarks/sort.rb +37 -0
- metadata +46 -2
@@ -3,7 +3,7 @@ module Algorithmable
|
|
3
3
|
module LinkedList
|
4
4
|
class Singly < Base
|
5
5
|
class Node
|
6
|
-
attr_accessor :item, :next
|
6
|
+
attr_accessor :item, :next, :front
|
7
7
|
|
8
8
|
def initialize(item, next_pointer = nil)
|
9
9
|
@item = item
|
@@ -93,8 +93,69 @@ module Algorithmable
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
+
def merge(other)
|
97
|
+
front = recursive_merge_imp self.front, other.front
|
98
|
+
list = self.class.new
|
99
|
+
while front
|
100
|
+
list.push_back front.item
|
101
|
+
front = front.next
|
102
|
+
end
|
103
|
+
list
|
104
|
+
end
|
105
|
+
|
106
|
+
def reverse!
|
107
|
+
@back = @front
|
108
|
+
@front = reverse_imp @front
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
def sort!
|
113
|
+
sort_linked_list @front
|
114
|
+
end
|
115
|
+
|
96
116
|
private
|
97
117
|
|
118
|
+
def sort_linked_list(node)
|
119
|
+
return unless node || node.empty?
|
120
|
+
swapped = false
|
121
|
+
prev = nil
|
122
|
+
|
123
|
+
begin
|
124
|
+
swapped = false
|
125
|
+
current = node
|
126
|
+
|
127
|
+
until current.next == prev
|
128
|
+
if current.item > current.next.item
|
129
|
+
swap_nodes current, current.next
|
130
|
+
swapped = true
|
131
|
+
end
|
132
|
+
current = current.next
|
133
|
+
end
|
134
|
+
|
135
|
+
prev = current
|
136
|
+
end while swapped
|
137
|
+
end
|
138
|
+
|
139
|
+
def swap_nodes(node1, node2)
|
140
|
+
tmp = node1.item
|
141
|
+
node1.item = node2.item
|
142
|
+
node2.item = tmp
|
143
|
+
end
|
144
|
+
|
145
|
+
def recursive_merge_imp(node1, node2)
|
146
|
+
return node2 if node1.nil?
|
147
|
+
return node1 if node2.nil?
|
148
|
+
node1 = node1.dup
|
149
|
+
node2 = node2.dup
|
150
|
+
if node1.item < node2.item
|
151
|
+
node1.next = recursive_merge_imp(node1.next, node2)
|
152
|
+
node1
|
153
|
+
else
|
154
|
+
node2.next = recursive_merge_imp(node2.next, node1)
|
155
|
+
node2
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
98
159
|
def reverse_imp(root)
|
99
160
|
return root if root.nil? || root.next.nil?
|
100
161
|
node = reverse_imp(root.next)
|
@@ -0,0 +1,206 @@
|
|
1
|
+
module Algorithmable
|
2
|
+
module DataStructs
|
3
|
+
module Tree
|
4
|
+
class BinarySearch
|
5
|
+
include Enumerable
|
6
|
+
include Algorithmable::DataStructs
|
7
|
+
|
8
|
+
def initialize(collection = [])
|
9
|
+
@root = nil
|
10
|
+
collection.each { |item| put item }
|
11
|
+
end
|
12
|
+
|
13
|
+
def max_depth
|
14
|
+
max_height_of @root
|
15
|
+
end
|
16
|
+
|
17
|
+
alias_method :height, :max_depth
|
18
|
+
|
19
|
+
def min_depth
|
20
|
+
min_height_of @root
|
21
|
+
end
|
22
|
+
|
23
|
+
def size
|
24
|
+
size_of @root
|
25
|
+
end
|
26
|
+
|
27
|
+
def empty?
|
28
|
+
0 == size
|
29
|
+
end
|
30
|
+
|
31
|
+
def put(object)
|
32
|
+
@root = put_impl @root, object
|
33
|
+
end
|
34
|
+
|
35
|
+
def min
|
36
|
+
return if empty?
|
37
|
+
min_impl(@root).item
|
38
|
+
end
|
39
|
+
|
40
|
+
def max
|
41
|
+
return if empty?
|
42
|
+
max_impl(@root).item
|
43
|
+
end
|
44
|
+
|
45
|
+
def each(&block)
|
46
|
+
each_with_dfs(&block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def each_with_dfs(&block)
|
50
|
+
tmp = collect_nodes_with_dfs(@root).to_a
|
51
|
+
block_given? ? tmp.each(&block) : tmp
|
52
|
+
end
|
53
|
+
|
54
|
+
def each_with_bfs(&block)
|
55
|
+
tmp = collect_nodes_with_bfs(@root).to_a
|
56
|
+
block_given? ? tmp.each(&block) : tmp
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_print
|
60
|
+
return if empty?
|
61
|
+
queue = new_fifo_queue
|
62
|
+
level = 0
|
63
|
+
next_level = 1
|
64
|
+
out = []
|
65
|
+
queue.enqueue @root
|
66
|
+
until queue.empty?
|
67
|
+
level += 1
|
68
|
+
node = queue.dequeue
|
69
|
+
out << node.item << ' '
|
70
|
+
queue.enqueue node.left if node.left
|
71
|
+
queue.enqueue node.right if node.right
|
72
|
+
|
73
|
+
if level == next_level
|
74
|
+
next_level += queue.size
|
75
|
+
out << "\n"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
out.join
|
79
|
+
end
|
80
|
+
|
81
|
+
def reverse!
|
82
|
+
@root = reverse_bang_impl @root
|
83
|
+
end
|
84
|
+
|
85
|
+
def flip!
|
86
|
+
@root = flip_bang_imp! @root, 0
|
87
|
+
end
|
88
|
+
|
89
|
+
def flip_bang_imp!(n, count)
|
90
|
+
return unless n
|
91
|
+
return n unless n.left && n.right
|
92
|
+
new_head = flip_bang_imp! n.left, count + 1
|
93
|
+
n.left.left = n.right
|
94
|
+
n.left.right = n
|
95
|
+
if count == 0
|
96
|
+
n.left = nil
|
97
|
+
n.right = nil
|
98
|
+
end
|
99
|
+
new_head
|
100
|
+
end
|
101
|
+
|
102
|
+
def balanced?(diff = 1)
|
103
|
+
(max_depth - min_depth) <= diff
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def max_height_of(node)
|
109
|
+
return 0 unless node
|
110
|
+
1 + [max_height_of(node.left), max_height_of(node.right)].max
|
111
|
+
end
|
112
|
+
|
113
|
+
def min_height_of(node)
|
114
|
+
return 0 unless node
|
115
|
+
1 + [min_height_of(node.left), min_height_of(node.right)].min
|
116
|
+
end
|
117
|
+
|
118
|
+
def reverse_bang_impl(root)
|
119
|
+
return unless root
|
120
|
+
reverse_bang_impl root.left
|
121
|
+
reverse_bang_impl root.right
|
122
|
+
tmp = root.left
|
123
|
+
root.left = root.right
|
124
|
+
root.right = tmp
|
125
|
+
root
|
126
|
+
end
|
127
|
+
|
128
|
+
def collect_nodes_with_bfs(root)
|
129
|
+
queue = new_fifo_queue
|
130
|
+
stack = new_lifo_queue
|
131
|
+
queue.enqueue root
|
132
|
+
until queue.empty?
|
133
|
+
node = queue.dequeue
|
134
|
+
stack.push node.item
|
135
|
+
queue.enqueue node.left if node.left
|
136
|
+
queue.enqueue node.right if node.right
|
137
|
+
end
|
138
|
+
stack
|
139
|
+
end
|
140
|
+
|
141
|
+
def collect_nodes_with_dfs(node)
|
142
|
+
stack = []
|
143
|
+
dfs_impl node, stack
|
144
|
+
stack
|
145
|
+
end
|
146
|
+
|
147
|
+
# in-order traversal
|
148
|
+
def dfs_impl(node, stack)
|
149
|
+
dfs_impl node.left, stack if node.left
|
150
|
+
stack.push node.item
|
151
|
+
dfs_impl node.right, stack if node.right
|
152
|
+
end
|
153
|
+
|
154
|
+
def max_impl(node)
|
155
|
+
return node if node.right.nil?
|
156
|
+
max_impl(node.right)
|
157
|
+
end
|
158
|
+
|
159
|
+
def min_impl(node)
|
160
|
+
return node if node.left.nil?
|
161
|
+
min_impl(node.left)
|
162
|
+
end
|
163
|
+
|
164
|
+
def put_impl(node, object)
|
165
|
+
return make_node(object, 1) unless node
|
166
|
+
case object <=> node.item
|
167
|
+
when -1
|
168
|
+
node.left = put_impl(node.left, object)
|
169
|
+
when 1
|
170
|
+
node.right = put_impl(node.right, object)
|
171
|
+
else
|
172
|
+
node.item = object
|
173
|
+
end
|
174
|
+
node.size = 1 + size_of(node.left) + size_of(node.right)
|
175
|
+
node
|
176
|
+
end
|
177
|
+
|
178
|
+
def size_of(node)
|
179
|
+
return 0 if node.nil?
|
180
|
+
node.size
|
181
|
+
end
|
182
|
+
|
183
|
+
def make_node(object, size)
|
184
|
+
Node.new object, size
|
185
|
+
end
|
186
|
+
|
187
|
+
class Node
|
188
|
+
attr_accessor :item, :left, :right, :size
|
189
|
+
|
190
|
+
def initialize(value, size)
|
191
|
+
@item = value
|
192
|
+
@size = size
|
193
|
+
@left = nil
|
194
|
+
@right = nil
|
195
|
+
end
|
196
|
+
|
197
|
+
def <=>(other)
|
198
|
+
@item <=> other.item
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
private_constant :Node
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Algorithmable
|
2
|
+
module DataStructs
|
3
|
+
module Tree
|
4
|
+
autoload :Binary, 'algorithmable/data_structs/tree/binary'
|
5
|
+
autoload :BinarySearch, 'algorithmable/data_structs/tree/binary_search'
|
6
|
+
autoload :Node, 'algorithmable/data_structs/tree/node'
|
7
|
+
|
8
|
+
def new_ordered_binary_tree(collection = [])
|
9
|
+
BinarySearch.new(collection)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -7,8 +7,10 @@ module Algorithmable
|
|
7
7
|
autoload :Stack, 'algorithmable/data_structs/stack'
|
8
8
|
autoload :OrderedSymbolTable, 'algorithmable/data_structs/ordered_symbol_table'
|
9
9
|
autoload :Heap, 'algorithmable/data_structs/heap'
|
10
|
+
autoload :Tree, 'algorithmable/data_structs/tree'
|
10
11
|
|
11
12
|
include LinkedList
|
13
|
+
include Tree
|
12
14
|
|
13
15
|
def new_bag
|
14
16
|
Bag.new
|
@@ -22,6 +24,10 @@ module Algorithmable
|
|
22
24
|
Stack.new
|
23
25
|
end
|
24
26
|
|
27
|
+
def new_deque_queue
|
28
|
+
Deque.new
|
29
|
+
end
|
30
|
+
|
25
31
|
def new_ordered_symbol_table(key_type, value_type)
|
26
32
|
OrderedSymbolTable.new(key_type, value_type)
|
27
33
|
end
|
@@ -1,16 +1,18 @@
|
|
1
1
|
module Algorithmable
|
2
2
|
module Sort
|
3
3
|
class Bubble
|
4
|
+
extend Algorithmable::Sort::Utils
|
5
|
+
#
|
6
|
+
# Time О(N^2), stable and slow
|
7
|
+
# Space О(N)
|
8
|
+
#
|
4
9
|
def self.sort(collection)
|
5
|
-
|
6
|
-
end
|
7
|
-
|
8
|
-
def sort(collection)
|
10
|
+
length = collection.length - 1
|
9
11
|
loop do
|
10
12
|
swapped = false
|
11
|
-
(
|
12
|
-
if (collection[
|
13
|
-
|
13
|
+
0.upto(length).each do |i|
|
14
|
+
if 1 == (collection[i] <=> collection[i + 1])
|
15
|
+
swap(collection, i)
|
14
16
|
swapped = true
|
15
17
|
end
|
16
18
|
end
|
@@ -18,15 +20,6 @@ module Algorithmable
|
|
18
20
|
end
|
19
21
|
collection
|
20
22
|
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def swap(index, collection)
|
25
|
-
current = collection[index]
|
26
|
-
collection[index] = collection[index.next]
|
27
|
-
collection[index.next] = current
|
28
|
-
collection
|
29
|
-
end
|
30
23
|
end
|
31
24
|
end
|
32
25
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Algorithmable
|
2
|
+
module Sort
|
3
|
+
class Insertion
|
4
|
+
extend Algorithmable::Sort::Utils
|
5
|
+
#
|
6
|
+
# Time О(N^2), stable and slow
|
7
|
+
# Space Complexity: О(N)
|
8
|
+
#
|
9
|
+
def self.sort(collection)
|
10
|
+
return collection if 2 > collection.length
|
11
|
+
1.upto(collection.length - 1).each do |i|
|
12
|
+
curr_char = collection[i]
|
13
|
+
j = i - 1
|
14
|
+
while 0 <= j && collection[j] > curr_char
|
15
|
+
collection[j + 1] = collection[j]
|
16
|
+
j -= 1
|
17
|
+
end
|
18
|
+
collection[j + 1] = curr_char
|
19
|
+
end
|
20
|
+
collection
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -2,20 +2,16 @@ module Algorithmable
|
|
2
2
|
module Sort
|
3
3
|
class Merge
|
4
4
|
def self.sort(collection)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def sort(collection)
|
9
|
-
return collection if collection.size <= 1
|
10
|
-
mid = collection.size / 2
|
5
|
+
return collection if collection.length <= 1
|
6
|
+
mid = collection.length / 2
|
11
7
|
left = collection[0...mid]
|
12
|
-
right = collection[mid...collection.
|
8
|
+
right = collection[mid...collection.length]
|
13
9
|
merge(sort(left), sort(right))
|
14
10
|
end
|
15
11
|
|
16
12
|
private
|
17
13
|
|
18
|
-
def merge(left, right)
|
14
|
+
def self.merge(left, right)
|
19
15
|
sorted = []
|
20
16
|
until left.empty? || right.empty?
|
21
17
|
left.first <= right.first ? sorted << left.shift : sorted << right.shift
|