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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/algorithmable.gemspec +1 -0
  4. data/lib/algorithmable/cache/imp.rb +19 -0
  5. data/lib/algorithmable/cache/primitive_max_heap.rb +38 -0
  6. data/lib/algorithmable/cache/primitive_min_heap.rb +38 -0
  7. data/lib/algorithmable/cache.rb +15 -0
  8. data/lib/algorithmable/cups/circular_dependencies.rb +27 -0
  9. data/lib/algorithmable/cups/longest_common_subsequence.rb +46 -0
  10. data/lib/algorithmable/cups/merge_two_arrays.rb +31 -0
  11. data/lib/algorithmable/cups/nested_lists_problem.rb +105 -0
  12. data/lib/algorithmable/cups/number_of_occurrences_in_array.rb +49 -0
  13. data/lib/algorithmable/cups/primitives.rb +205 -2
  14. data/lib/algorithmable/cups/root_cube_issue.rb +39 -0
  15. data/lib/algorithmable/cups/stacks_and_queues/stack_sorter.rb +25 -0
  16. data/lib/algorithmable/cups/stacks_and_queues/stack_with_min.rb +23 -0
  17. data/lib/algorithmable/cups/stacks_and_queues/towers_of_hanoi.rb +48 -0
  18. data/lib/algorithmable/cups/stacks_and_queues/triple_stack.rb +52 -0
  19. data/lib/algorithmable/cups/stacks_and_queues/two_stacks_queue.rb +37 -0
  20. data/lib/algorithmable/cups/stacks_and_queues.rb +31 -0
  21. data/lib/algorithmable/cups/stocks.rb +80 -0
  22. data/lib/algorithmable/cups/task_shedule_with_coldtime.rb +16 -0
  23. data/lib/algorithmable/cups/two_sum.rb +59 -0
  24. data/lib/algorithmable/cups.rb +7 -0
  25. data/lib/algorithmable/data_structs/linked_list/base.rb +21 -1
  26. data/lib/algorithmable/data_structs/linked_list/doubly.rb +1 -1
  27. data/lib/algorithmable/data_structs/linked_list/singly.rb +62 -1
  28. data/lib/algorithmable/data_structs/queue.rb +4 -0
  29. data/lib/algorithmable/data_structs/stack.rb +4 -0
  30. data/lib/algorithmable/data_structs/tree/binary.rb +10 -0
  31. data/lib/algorithmable/data_structs/tree/binary_search.rb +206 -0
  32. data/lib/algorithmable/data_structs/tree.rb +13 -0
  33. data/lib/algorithmable/data_structs.rb +6 -0
  34. data/lib/algorithmable/sort/bubble.rb +9 -16
  35. data/lib/algorithmable/sort/insertion.rb +24 -0
  36. data/lib/algorithmable/sort/merge.rb +4 -8
  37. data/lib/algorithmable/sort/quick_sort.rb +35 -0
  38. data/lib/algorithmable/sort/selection.rb +23 -0
  39. data/lib/algorithmable/sort/shell.rb +27 -0
  40. data/lib/algorithmable/sort/shuffle.rb +15 -0
  41. data/lib/algorithmable/sort/utils.rb +66 -0
  42. data/lib/algorithmable/sort.rb +28 -0
  43. data/lib/algorithmable/union_find.rb +51 -0
  44. data/lib/algorithmable/version.rb +1 -1
  45. data/lib/algorithmable.rb +2 -0
  46. data/script/benchmarks/sort.rb +37 -0
  47. metadata +46 -2
@@ -3,7 +3,7 @@ module Algorithmable
3
3
  module LinkedList
4
4
  class Doubly < Base
5
5
  class Node
6
- attr_accessor :item, :prev, :next
6
+ attr_accessor :item, :prev, :next, :front
7
7
 
8
8
  def initialize(item, prev_pointer = nil, next_pointer = nil)
9
9
  @item = item
@@ -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)
@@ -23,6 +23,10 @@ module Algorithmable
23
23
  def dequeue
24
24
  @imp.pop_front
25
25
  end
26
+
27
+ def to_s
28
+ to_a.join('->')
29
+ end
26
30
  end
27
31
  end
28
32
  end
@@ -24,6 +24,10 @@ module Algorithmable
24
24
  def pop
25
25
  @imp.pop_front
26
26
  end
27
+
28
+ def to_s
29
+ to_a.join '->'
30
+ end
27
31
  end
28
32
  end
29
33
  end
@@ -0,0 +1,10 @@
1
+ module Algorithmable
2
+ module DataStructs
3
+ module Tree
4
+ class Binary
5
+ include Enumerable
6
+ include Algorithmable::DataStructs
7
+ end
8
+ end
9
+ end
10
+ end
@@ -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
- new.sort(collection)
6
- end
7
-
8
- def sort(collection)
10
+ length = collection.length - 1
9
11
  loop do
10
12
  swapped = false
11
- (collection.size.pred).times do |index|
12
- if (collection[index] <=> collection[index.next]) == 1
13
- collection = swap(index, collection)
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
- new.sort(collection)
6
- end
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.size]
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