algorithmable 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,39 @@
1
+ module Algorithmable
2
+ module Cups
3
+ module RootCubeIssue
4
+ # What is the fastest way to compute cube root?
5
+
6
+ ACCURACY = 0.0001
7
+
8
+ def self.binary_search(num, accuracy = ACCURACY)
9
+ low = 0
10
+ high = num
11
+ mid = 0
12
+
13
+ loop do
14
+ mid = (low + high) / 2.0
15
+ cube = mid * mid * mid
16
+ break if (cube - num).abs <= accuracy
17
+ if cube > num
18
+ high = mid
19
+ else
20
+ low = mid
21
+ end
22
+ end
23
+ mid
24
+ end
25
+
26
+ def self.newton_approximation(num, accuracy = ACCURACY)
27
+ x = 1
28
+ n = 10
29
+ loop do
30
+ 0.upto(n).each do
31
+ x = (2 * x + num / (x * x)) / 3.0
32
+ end
33
+ break if ((x * x * x) - num).abs < accuracy
34
+ end
35
+ x
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,25 @@
1
+ module Algorithmable
2
+ module Cups
3
+ module StacksAndQueues
4
+ class StackSorter
5
+ include Algorithmable::DataStructs
6
+
7
+ def self.sort(stack)
8
+ new.sort(stack)
9
+ end
10
+
11
+ def sort(stack)
12
+ local_stack = new_lifo_queue
13
+ until stack.empty?
14
+ temp = stack.pop
15
+ while !local_stack.empty? && local_stack.peek < temp
16
+ stack.push local_stack.pop
17
+ end
18
+ local_stack.push temp
19
+ end
20
+ local_stack
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ module Algorithmable
2
+ module Cups
3
+ module StacksAndQueues
4
+ class StackWithMin < Algorithmable::DataStructs::Stack
5
+ MAX_INT = 2**32
6
+ NodeWithMin = Struct.new(:item, :minimum)
7
+
8
+ private_constant :NodeWithMin
9
+
10
+ def push(item)
11
+ new_min = [item, min].min
12
+ node = NodeWithMin.new item, new_min
13
+ super node
14
+ end
15
+
16
+ def min
17
+ return MAX_INT if empty?
18
+ peek.min
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,48 @@
1
+ module Algorithmable
2
+ module Cups
3
+ module StacksAndQueues
4
+ module TowersOfHanoi
5
+ class Tower
6
+ include Algorithmable::DataStructs
7
+
8
+ attr_reader :index
9
+
10
+ def initialize(index)
11
+ @disks = new_lifo_queue
12
+ @index = index
13
+ end
14
+
15
+ def add(disk)
16
+ fail "Error placing disk #{disk} on #{@disks.peek}." if !@disks.empty? && @disks.peek <= disk
17
+ @disks.push disk
18
+ end
19
+
20
+ def move_top_to_tower(other_tower)
21
+ top = @disks.pop
22
+ debug "Moving disk ##{top} from tower #{index} to #{other_tower.index}."
23
+ other_tower.add top
24
+ end
25
+
26
+ def move_disks(amount, destination, buffer)
27
+ return unless amount > 0
28
+ move_disks amount - 1, buffer, destination
29
+ move_top_to_tower destination
30
+ buffer.move_disks amount - 1, destination, self
31
+ end
32
+
33
+ def inspect
34
+ "#<Tower ##{index} #{@disks}>"
35
+ end
36
+
37
+ def to_a
38
+ @disks.to_a
39
+ end
40
+
41
+ def debug(message)
42
+ puts message
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,52 @@
1
+ module Algorithmable
2
+ module Cups
3
+ module StacksAndQueues
4
+ class TripleStack
5
+ MAX_INT = 2**32
6
+
7
+ def initialize(size)
8
+ @size = size + 1
9
+ @pointers = [0, 0, 0]
10
+ @array = Array.new (@size * 3)
11
+ 0.upto(2).each do |index|
12
+ @array[@size * index] = MAX_INT
13
+ end
14
+ end
15
+
16
+ def push(stack_num, item)
17
+ pointer = get_stack_pointer(stack_num) + 1
18
+ @pointers[stack_num] += 1
19
+ @array[pointer] = item
20
+ item
21
+ end
22
+
23
+ def pop(stack_num)
24
+ pointer = get_stack_pointer(stack_num)
25
+ value = @array[pointer]
26
+ @array[pointer] = nil
27
+ @pointers[stack_num] -= 1
28
+ value
29
+ end
30
+
31
+ def peek(stack_num)
32
+ pointer = get_stack_pointer(stack_num)
33
+ @array[pointer]
34
+ end
35
+
36
+ def empty?(stack_num)
37
+ @pointers[stack_num].zero?
38
+ end
39
+
40
+ def inspect
41
+ "#<Stack @pointers=#{@pointers} @stacks=#{@array}>"
42
+ end
43
+
44
+ private
45
+
46
+ def get_stack_pointer(stack_num)
47
+ @size * stack_num + @pointers[stack_num]
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,37 @@
1
+ module Algorithmable
2
+ module Cups
3
+ module StacksAndQueues
4
+ class TwoStacksQueue
5
+ include Algorithmable::DataStructs
6
+
7
+ def initialize
8
+ @stack_a = new_lifo_queue
9
+ @stack_b = new_lifo_queue
10
+ end
11
+
12
+ def size
13
+ @stack_a.size + @stack_b.size
14
+ end
15
+
16
+ def enqueue(item)
17
+ unless @stack_b.empty?
18
+ @stack_a.push @stack_b.pop until @stack_b.empty?
19
+ end
20
+ @stack_a.push(item)
21
+ end
22
+
23
+ def dequeue
24
+ return @stack_b.dequeue unless @stack_b.empty?
25
+ @stack_b.push @stack_a.pop until @stack_a.empty?
26
+ @stack_b.pop
27
+ end
28
+
29
+ def peek
30
+ return @stack_b.peek unless @stack_b.empty?
31
+ @stack_b.push @stack_a.pop until @stack_a.empty?
32
+ @stack_b.peek
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,31 @@
1
+ module Algorithmable
2
+ module Cups
3
+ module StacksAndQueues
4
+ autoload :TwoStacksQueue, 'algorithmable/cups/stacks_and_queues/two_stacks_queue'
5
+ autoload :StackWithMin, 'algorithmable/cups/stacks_and_queues/stack_with_min'
6
+ autoload :TripleStack, 'algorithmable/cups/stacks_and_queues/triple_stack'
7
+ autoload :StackSorter, 'algorithmable/cups/stacks_and_queues/stack_sorter'
8
+ autoload :TowersOfHanoi, 'algorithmable/cups/stacks_and_queues/towers_of_hanoi'
9
+
10
+ def new_triple_stack(size)
11
+ TripleStack.new size
12
+ end
13
+
14
+ def new_stack_with_min
15
+ StackWithMin.new
16
+ end
17
+
18
+ def new_two_stacks_queue
19
+ TwoStacksQueue.new
20
+ end
21
+
22
+ def sort_stack(stack)
23
+ StackSorter.sort stack
24
+ end
25
+
26
+ def new_tower_of_hanoi(index)
27
+ TowersOfHanoi::Tower.new index
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,80 @@
1
+ module Algorithmable
2
+ module Cups
3
+ module Stocks
4
+ # If you were only permitted to buy one share of the stock and sell one share of the stock,
5
+ # design an algorithm to find the best times to buy and sell.
6
+ def get_best_time(stocks)
7
+ min = 0
8
+ max_diff = 0
9
+ buy = 0
10
+ sell = 0
11
+ 0.upto(stocks.size - 1).each do |i|
12
+ min = i if stocks[i] < stocks[min]
13
+ diff = stocks[i] - stocks[min]
14
+ next unless diff > max_diff
15
+ buy = min
16
+ sell = i
17
+ max_diff = diff
18
+ end
19
+ { buy_at: buy, sell_at: sell, max_profit: max_diff }
20
+ end
21
+
22
+ # another way
23
+ #
24
+ def find_max_profit(arr)
25
+ max_diff = arr[1] - arr[0]
26
+ 0.upto(arr.size).each do |i|
27
+ (i + 1).upto(arr.size - 1).each do |j|
28
+ max_diff = arr[j] - arr[i] if arr[j] - arr[i] > max_diff
29
+ end
30
+ end
31
+ max_diff
32
+ end
33
+
34
+ # The cost of a stock on each current_day is given in an array, find the max profit that you can make by
35
+ # buying and selling in those days.
36
+ # For example, if the given array is {100, 180, 260, 310, 40, 535, 695},
37
+ # the maximum profit can earned by buying on current_day 0, selling on current_day 3.
38
+ # Again buy on current_day 4 and sell on current_day 6. If the given array of prices is sorted in decreasing order,
39
+ # then profit cannot be earned at all.
40
+
41
+ # If we are allowed to buy and sell only once, then we can use following algorithm.
42
+ # Maximum difference between two elements. Here we are allowed to buy and sell multiple times.
43
+ #
44
+ # Following is algorithm for this problem.
45
+ # 1. Find the local minima and store it as starting index. If not exists, return.
46
+ # 2. Find the local maxima. and store it as ending index. If we reach the end, set the end as ending index.
47
+ # 3. Update the solution (Increment count of buy sell pairs)
48
+ # 4. Repeat the above steps if end is not reached.
49
+ #
50
+ # http://www.geeksforgeeks.org/stock-buy-sell/
51
+ def ruby_buy_and_sell_stocks(stocks)
52
+ total_days = stocks.size - 1
53
+ current_day = 0
54
+ series_count = 0
55
+ series = []
56
+
57
+ while current_day < total_days
58
+ while current_day <= total_days && stocks[current_day + 1] <= stocks[current_day]
59
+ current_day += 1
60
+ end
61
+
62
+ return series if current_day == total_days
63
+
64
+ series[series_count] = { buy: 0, sell: 0 }
65
+ series[series_count][:buy] = current_day
66
+ current_day += 1
67
+
68
+ while current_day <= total_days && stocks[current_day] >= stocks[current_day - 1]
69
+ current_day += 1
70
+ end
71
+
72
+ series[series_count][:sell] = current_day - 1
73
+ series_count += 1
74
+ end
75
+
76
+ series
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,16 @@
1
+ module Algorithmable
2
+ module Cups
3
+ class TaskScheduleWithColdTime
4
+ # Task schedule: given a sequence of task like A B C(means 3 different tasks), and a coldtime, which means you need to wait for that much time to start next [same] task. Now----
5
+ #
6
+ # Input: string, n
7
+ # Output: the best task-finishing sequence.
8
+ #
9
+ # eg. input: AAABBB, 2
10
+ # Output: AB_AB_AB
11
+ # ( "_" represents do nothing and wait)
12
+ def solve(sequence_of_tasks)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,59 @@
1
+ module Algorithmable
2
+ module Cups
3
+ module TwoSum
4
+ # Given an array of integers, find two numbers such that they add up to a specific target number.
5
+ #
6
+ # The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
7
+ #
8
+ # For example:
9
+ #
10
+ # Input: numbers={2, 7, 11, 15}, target=9
11
+ # Output: index1=1, index2=2
12
+ class Quadratic
13
+ def solve(collection, target)
14
+ result = {}
15
+ collection.each_with_index do |_, index|
16
+ j = index + 1
17
+ while j < collection.size
18
+ if collection[index] + collection[j] == target
19
+ result[index] = collection[index]
20
+ result[j] = collection[j]
21
+ end
22
+ j += 1
23
+ end
24
+ end
25
+ result
26
+ end
27
+ end
28
+
29
+ # public class Solution {
30
+ # public int[] twoSum(int[] numbers, int target) {
31
+ # HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
32
+ # int[] result = new int[2];
33
+ #
34
+ # for (int i = 0; i < numbers.length; i++) {
35
+ # if (map.containsKey(numbers[i])) {
36
+ # int index = map.get(numbers[i]);
37
+ # result[0] = index+1 ;
38
+ # result[1] = i+1;
39
+ # break;
40
+ # } else {
41
+ # map.put(target - numbers[i], i);
42
+ # }
43
+ # }
44
+ #
45
+ # return result;
46
+ # }
47
+ # }
48
+
49
+ class Logarithmic
50
+ def solve(collection, target)
51
+ end
52
+ end
53
+
54
+ def new_quadratic_solution
55
+ Quadratic.new
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,5 +1,12 @@
1
1
  module Algorithmable
2
2
  module Cups
3
3
  autoload :Primitives, 'algorithmable/cups/primitives'
4
+ autoload :Stocks, 'algorithmable/cups/stocks'
5
+ autoload :StacksAndQueues, 'algorithmable/cups/stacks_and_queues'
6
+ autoload :NestedListsProblem, 'algorithmable/cups/nested_lists_problem'
7
+ autoload :TwoSum, 'algorithmable/cups/two_sum'
8
+ autoload :NumberOfOccurrencesInArray, 'algorithmable/cups/stacks_and_queues/number_of_occurrences_in_array'
9
+ autoload :LongestCommonSubSequence, 'algorithmable/cups/longest_common_subsequence'
10
+ autoload :RootCubeIssue, 'algorithmable/cups/root_cube_issue'
4
11
  end
5
12
  end
@@ -53,7 +53,15 @@ module Algorithmable
53
53
  fail NotImplementedError
54
54
  end
55
55
 
56
- def reverse
56
+ def reverse!
57
+ fail NotImplementedError
58
+ end
59
+
60
+ def sort!
61
+ fail NotImplementedError
62
+ end
63
+
64
+ def merge!(_other_list)
57
65
  fail NotImplementedError
58
66
  end
59
67
 
@@ -61,6 +69,18 @@ module Algorithmable
61
69
  fail NotImplementedError
62
70
  end
63
71
 
72
+ def find_intersect(_other)
73
+ fail NotImplementedError
74
+ end
75
+
76
+ def to_s
77
+ to_a.join('->')
78
+ end
79
+
80
+ def to_a
81
+ each.map(&:item)
82
+ end
83
+
64
84
  private
65
85
 
66
86
  def search(item)