ds 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +11 -0
  3. data/.rubocop_todo.yml +452 -0
  4. data/.travis.yml +12 -0
  5. data/Gemfile +1 -1
  6. data/README.rdoc +185 -214
  7. data/Rakefile +8 -3
  8. data/ds.gemspec +16 -13
  9. data/lib/ds.rb +20 -30
  10. data/lib/ds/{matrixes → arrays}/array_2d.rb +9 -10
  11. data/lib/ds/arrays/expandable_array.rb +34 -0
  12. data/lib/ds/arrays/heap_store.rb +32 -0
  13. data/lib/ds/arrays/tri_matrix.rb +33 -0
  14. data/lib/ds/lists/list.rb +310 -186
  15. data/lib/ds/lists/list_element.rb +14 -11
  16. data/lib/ds/pair.rb +4 -4
  17. data/lib/ds/queues/priority_queue.rb +33 -20
  18. data/lib/ds/queues/simple_queue.rb +55 -0
  19. data/lib/ds/sets/indexed_set.rb +37 -0
  20. data/lib/ds/stacks/stack.rb +25 -17
  21. data/lib/ds/trees/binary_heap.rb +71 -66
  22. data/lib/ds/trees/binary_tree.rb +40 -44
  23. data/lib/ds/trees/red_black_tree.rb +123 -0
  24. data/lib/ds/trees/red_black_tree/node.rb +21 -0
  25. data/lib/ds/trees/tree.rb +50 -48
  26. data/lib/ds/trees/tree_walker.rb +73 -144
  27. data/lib/ds/trees/trie.rb +67 -37
  28. data/lib/ds/trees/trie/node.rb +48 -0
  29. data/lib/ds/version.rb +2 -1
  30. data/test/help.rb +3 -6
  31. data/test/performance/binary_heap_performance_test.rb +20 -0
  32. data/test/performance/list_performance_test.rb +36 -0
  33. data/test/performance/priority_queue_performance.rb +32 -0
  34. data/test/performance/rbt_performance_test.rb +17 -0
  35. data/test/performance/simple_queue_performance_test.rb +37 -0
  36. data/test/performance/stack_test.rb +45 -0
  37. data/test/test_array2d.rb +29 -31
  38. data/test/test_binary_heap.rb +29 -23
  39. data/test/test_binary_tree.rb +30 -20
  40. data/test/test_expandable_array.rb +6 -10
  41. data/test/test_heap_store.rb +34 -0
  42. data/test/test_indexed_set.rb +26 -0
  43. data/test/test_list.rb +226 -109
  44. data/test/test_list_element.rb +34 -16
  45. data/test/test_pair.rb +5 -8
  46. data/test/test_priority_queue.rb +43 -64
  47. data/test/test_queue.rb +12 -61
  48. data/test/test_red_black_tree.rb +46 -0
  49. data/test/test_stack.rb +35 -39
  50. data/test/test_tree.rb +42 -29
  51. data/test/test_tree_walker.rb +27 -52
  52. data/test/test_tri_matrix.rb +6 -11
  53. data/test/test_trie.rb +59 -17
  54. metadata +80 -35
  55. data/lib/ds/ext/array_x.rb +0 -35
  56. data/lib/ds/graphs/digraph.rb +0 -20
  57. data/lib/ds/graphs/edge.rb +0 -15
  58. data/lib/ds/graphs/graph.rb +0 -111
  59. data/lib/ds/graphs/graph_as_matrix.rb +0 -113
  60. data/lib/ds/graphs/graph_as_tri_matrix.rb +0 -24
  61. data/lib/ds/lists/cyclic_list.rb +0 -21
  62. data/lib/ds/lists/ring.rb +0 -42
  63. data/lib/ds/matrixes/expandable_array.rb +0 -37
  64. data/lib/ds/matrixes/tri_matrix.rb +0 -30
  65. data/lib/ds/queues/queue.rb +0 -53
  66. data/lib/ds/sets/ordered_set.rb +0 -32
  67. data/lib/ds/trees/binary_search_tree.rb +0 -34
  68. data/lib/ds/trees/complete_binary_tree.rb +0 -60
  69. data/test/test_array_x.rb +0 -51
  70. data/test/test_binary_search_tree.rb +0 -39
  71. data/test/test_complete_binary_tree.rb +0 -58
  72. data/test/test_digraph.rb +0 -134
  73. data/test/test_graph.rb +0 -80
  74. data/test/test_ordered_set.rb +0 -28
  75. data/test/test_ring.rb +0 -28
@@ -1,61 +1,91 @@
1
1
  module DS
2
+ # Trie dictionary data structure
2
3
  class Trie < Tree
4
+ attr_accessor :root
3
5
 
4
- ALPHABET = %w{- a b c d e f g h i j k l m n o p q r s t u v w x y z}
6
+ def initialize(value = nil, alphabet = nil)
7
+ @root = Node.new(value)
8
+ self.alphabet = (alphabet || %w(- a b c d e f g h i j k l m n o p q r s t u v w x y z))
9
+ end
10
+
11
+ def alphabet=(arr)
12
+ @alphabet = {}
13
+ arr.each_with_index { |c, i| @alphabet[c] = i }
14
+ end
5
15
 
6
16
  def alphabet
7
- self.class::ALPHABET
17
+ @alphabet.keys
8
18
  end
9
-
10
- def initialize(value=nil)
11
- @children = Array.new(alphabet.size)
12
- @data = value
19
+
20
+ def key(chr)
21
+ @alphabet[chr]
13
22
  end
14
23
 
15
- def insert(s, value=true)
16
- letters = s.scan(/./)
17
- raise ArgumentError, "Not allowed symbol." unless (letters - alphabet).empty?
18
- priv_insert(letters, value)
24
+ def insert(s, value = true)
25
+ letters = get_letters(s)
26
+ root.put(letters, value, self)
27
+ end
28
+
29
+ def []=(k, v)
30
+ insert(k, v)
19
31
  end
20
32
 
21
33
  def find(s)
22
- letters = s.scan(/./)
23
- raise ArgumentError, "Not allowed symbol." unless (letters - alphabet).empty?
24
- priv_find(letters)
34
+ letters = get_letters(s)
35
+ node = root.get(letters, self)
36
+ node.data if node
25
37
  end
26
38
 
27
- protected
28
- def key(chr)
29
- k=alphabet.index(chr)
39
+ def [](k)
40
+ find(k)
30
41
  end
31
42
 
43
+ def delete(s)
44
+ letters = s.scan(/./)
45
+ root.delete(letters, self)
46
+ end
32
47
 
33
- def priv_insert(s, value)
34
- if s.empty?
35
- @data = value
36
- else
37
- index = key(s.first)
38
- subtree = if @children[index]
39
- @children[index]
40
- else
41
- @children[index] = Trie.new
42
- end
43
-
44
- subtree.priv_insert(s[1..-1], value)
48
+ def each(&block)
49
+ visit(root, '', &block)
50
+ end
51
+
52
+ def visit(node, prefix, &block)
53
+ yield prefix, node.data if node.data
54
+ node.children.each_with_index do |n, i|
55
+ visit(n, prefix + alphabet[i], &block) if n
45
56
  end
46
57
  end
47
58
 
48
- def priv_find(search)
49
- if search.empty?
50
- @data
59
+ def with_prefix(prefix, &block)
60
+ letters = get_letters(prefix)
61
+ node = root.get(letters, self)
62
+ if block_given?
63
+ return nil unless node
64
+ visit(node, prefix, &block)
51
65
  else
52
- index = key(search.first)
53
- if @children[index]
54
- @children[index].priv_find(search[1..-1])
55
- else
56
- nil
57
- end
66
+ arr = []
67
+ return arr unless node
68
+ visit(node, prefix) { |n| arr << n }
69
+ arr
58
70
  end
59
71
  end
72
+
73
+ def to_h
74
+ h = {}
75
+ each { |k, v| h[k] = v }
76
+ h
77
+ end
78
+
79
+ private
80
+
81
+ def allowed?(letters)
82
+ (letters - alphabet).empty?
83
+ end
84
+
85
+ def get_letters(s)
86
+ letters = s.scan(/./)
87
+ raise ArgumentError, 'Not allowed symbol.' unless allowed?(letters)
88
+ letters
89
+ end
60
90
  end
61
91
  end
@@ -0,0 +1,48 @@
1
+ module DS
2
+ # Trie dictionary data structure
3
+ class Trie
4
+ # Trie node
5
+ class Node
6
+ attr_reader :children, :data
7
+
8
+ def initialize(value = nil)
9
+ @children = []
10
+ @data = value
11
+ end
12
+
13
+ def put(s, value, trie)
14
+ if s.empty?
15
+ @data = value
16
+ else
17
+ index = trie.key(s.first)
18
+ @children[index] ||= Node.new
19
+ @children[index].put(s[1..-1], value, trie)
20
+ end
21
+ end
22
+
23
+ def get(s, trie)
24
+ if s.empty?
25
+ self
26
+ else
27
+ index = trie.key(s.first)
28
+ @children[index].get(s[1..-1], trie) if @children[index]
29
+ end
30
+ end
31
+
32
+ def delete(s, trie)
33
+ return true if s.empty?
34
+ index = trie.key(s.first)
35
+ flag = @children[index].delete(s[1..-1], trie)
36
+ flag &&= one_child?
37
+ @children[index] = nil if flag
38
+ s.size < 2 ? true : flag && @data.nil?
39
+ end
40
+
41
+ private
42
+
43
+ def one_child?
44
+ @children.compact.size <= 1
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,4 @@
1
+ # Main module namespace
1
2
  module DS
2
- VERSION = "0.0.4"
3
+ VERSION = '0.0.6'.freeze
3
4
  end
@@ -1,17 +1,14 @@
1
1
  if ENV['COVERAGE']
2
2
  require 'simplecov'
3
3
  SimpleCov.start do
4
- add_filter "/test/"
4
+ add_filter '/test/'
5
5
  end
6
6
  end
7
7
 
8
-
9
8
  require 'rubygems'
10
- gem 'minitest'
11
9
  require 'minitest/autorun'
12
- require "minitest/benchmark" if ENV['BENCH']
13
- require "minitest/pride"
14
-
10
+ require 'minitest/benchmark' if ENV['BENCH']
11
+ require 'minitest/pride'
15
12
 
16
13
  require './lib/ds.rb'
17
14
  include DS
@@ -0,0 +1,20 @@
1
+ require 'help'
2
+
3
+ if ENV['BENCH']
4
+ describe 'performance Bench' do
5
+ before do
6
+ @arr = (1..10_000).to_a.shuffle
7
+ @heap = BinaryHeap.new(*@arr)
8
+ end
9
+
10
+ bench_performance_constant 'creating new heap should be linear operation.', 0.999 do |_n|
11
+ BinaryHeap.new(*@arr)
12
+ end
13
+
14
+ bench_performance_constant 'accessing max element should be const operation.', 0.999 do |n|
15
+ n.times do
16
+ @heap.shift
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,36 @@
1
+ if ENV['BENCH']
2
+ describe 'Lists Bench' do
3
+ before do
4
+ @arr = (1..10_000).to_a.sort_by { rand }
5
+ @list = List.from_array([1, 2, 3, 4])
6
+ @second = @list.head.next
7
+
8
+ 10_000.times do
9
+ @list.append 4
10
+ end
11
+ end
12
+
13
+ bench_performance_constant '#append should be const operation.', 0.999 do |n|
14
+ n.times do
15
+ @list.append 3
16
+ end
17
+ end
18
+
19
+ bench_performance_constant '#insert after should be const operation.', 0.999 do |n|
20
+ n.times do
21
+ @list.insert_after(9, @second)
22
+ end
23
+ end
24
+
25
+ bench_performance_constant '#unshift should be const operation.', 0.999 do |n|
26
+ n.times do
27
+ @list.unshift 3
28
+ end
29
+ end
30
+
31
+ bench_performance_linear '#reverse! should be linear operation.', 0.999 do |n|
32
+ list = List.from_array(@arr[0..n])
33
+ list.reverse!
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,32 @@
1
+ require 'help'
2
+
3
+ if ENV['BENCH']
4
+ describe 'performance Bench' do
5
+ before do
6
+ @queue = PriorityQueue.new
7
+ 10_000.times do
8
+ @queue.push :elem, rand(10)
9
+ end
10
+
11
+ @empty_queue = PriorityQueue.new
12
+ end
13
+
14
+ bench_performance_constant '#accessing max element should be const operation.', 0.999 do |n|
15
+ n.times do
16
+ @queue.peek
17
+ end
18
+ end
19
+
20
+ # bench_performance_logarithmic '#removing max element should be log operation.', 0.999 do |n|
21
+ # n.times do
22
+ # @queue.dequeue
23
+ # end
24
+ # end
25
+
26
+ bench_performance_linear 'creating new priority queue should be linear operation.', 0.999 do |n|
27
+ n.times do
28
+ @empty_queue.push :elem, rand(10)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ require 'help'
2
+
3
+ if ENV['BENCH']
4
+ describe 'performance Bench' do
5
+ before do
6
+ @tree = RedBlackTree.new
7
+ end
8
+
9
+ bench_performance_constant 'insert is log(n) operation', 0.999 do |n|
10
+ key = 'a'
11
+ n.times do
12
+ key = key.succ
13
+ @tree.insert key, rand(10)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ require 'help'
2
+ if ENV['BENCH']
3
+ describe 'performance Bench' do
4
+ before do
5
+ @queue = SimpleQueue.new
6
+ @queue2 = SimpleQueue.create
7
+ 100_000.times do
8
+ @queue.push 4
9
+ @queue2.push 4
10
+ end
11
+ end
12
+
13
+ bench_performance_constant '#shift(array implementation) should be const operation.', 0.999 do |n|
14
+ n.times do
15
+ @queue.shift
16
+ end
17
+ end
18
+
19
+ bench_performance_constant '#shift(list implementation) should be const operation.', 0.999 do |n|
20
+ n.times do
21
+ @queue2.shift
22
+ end
23
+ end
24
+
25
+ bench_performance_constant '#push(array implementation) should be const operation.', 0.999 do |n|
26
+ n.times do
27
+ @queue.push 2
28
+ end
29
+ end
30
+
31
+ bench_performance_constant '#push(list implementation) should be const operation.', 0.999 do |n|
32
+ n.times do
33
+ @queue2.push 2
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,45 @@
1
+ require 'help'
2
+
3
+ if ENV['BENCH']
4
+ describe 'implement as Array Bench' do
5
+ before do
6
+ @stack = Stack.new
7
+ 100_000.times do
8
+ @stack.push 4
9
+ end
10
+ end
11
+
12
+ bench_performance_constant 'array #pop should be const op', 0.999 do |n|
13
+ n.times do
14
+ @stack.pop
15
+ end
16
+ end
17
+
18
+ bench_performance_constant 'array #push should be const op', 0.999 do |n|
19
+ n.times do
20
+ @stack.push 3
21
+ end
22
+ end
23
+ end
24
+
25
+ describe 'implement as List Bench' do
26
+ before do
27
+ @stack = Stack.create
28
+ 100_000.times do
29
+ @stack.push 4
30
+ end
31
+ end
32
+
33
+ bench_performance_constant 'list #pop should be const op', 0.999 do |n|
34
+ n.times do
35
+ @stack.pop
36
+ end
37
+ end
38
+
39
+ bench_performance_constant 'list #push should be const op.', 0.999 do |n|
40
+ n.times do
41
+ @stack.push 3
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,61 +1,59 @@
1
1
  require 'help'
2
2
 
3
3
  describe Array2D do
4
-
5
- describe "initialized with 0" do
6
-
4
+ describe 'initialized with 0' do
7
5
  before do
8
- @zero_matrix = Array2D.new(2,0)
6
+ @zero_matrix = Array2D.new(2, 0)
9
7
  end
10
8
 
11
- it "should return zero for any index." do
12
- @zero_matrix[1,1].must_equal 0
13
- @zero_matrix[0,0].must_equal 0
9
+ it 'should return zero for any index.' do
10
+ @zero_matrix[1, 1].must_equal 0
11
+ @zero_matrix[0, 0].must_equal 0
14
12
  end
15
13
 
16
- it "#flatten should return matrix flattened to array." do
14
+ it '#flatten should return matrix flattened to array.' do
17
15
  @zero_matrix.flatten.must_be_instance_of Array
18
- @zero_matrix.flatten.must_equal [0,0,0,0]
16
+ @zero_matrix.flatten.must_equal [0, 0, 0, 0]
19
17
  end
20
-
21
- it "#to_a should return internal representation (nested arrays)" do
18
+
19
+ it '#to_a should return internal representation (nested arrays)' do
22
20
  @zero_matrix.to_a.must_be_instance_of Array
23
- @zero_matrix.to_a.must_equal [[0,0],[0,0]]
21
+ @zero_matrix.to_a.must_equal [[0, 0], [0, 0]]
24
22
  end
25
23
 
26
- it "#should extend magically." do
27
- @zero_matrix[3,3].must_equal 0
28
- @zero_matrix[4,8].wont_be_nil
24
+ it '#should extend magically.' do
25
+ @zero_matrix[3, 3].must_equal 0
26
+ @zero_matrix[4, 8].wont_be_nil
29
27
  end
30
28
  end
31
29
 
32
- describe "initialized with false" do
33
-
30
+ describe 'initialized with false' do
34
31
  before do
35
- @discrete_matrix = Array2D.new(3,false)
32
+ @discrete_matrix = Array2D.new(3, false)
36
33
  end
37
34
 
38
- it "should return false for any index." do
39
- refute @discrete_matrix[1,1]
40
- refute @discrete_matrix[0,0]
35
+ it 'should return false for any index.' do
36
+ refute @discrete_matrix[1, 1]
37
+ refute @discrete_matrix[0, 0]
41
38
  end
42
39
 
43
- it "#flatten should return matrix flattened to array." do
40
+ it '#flatten should return matrix flattened to array.' do
44
41
  @discrete_matrix.flatten.must_be_instance_of Array
45
- @discrete_matrix.flatten.must_equal [false,false,false,false,false,false,false,false,false]
42
+ @discrete_matrix.flatten.must_equal [false, false, false, false, false, false, false, false, false]
46
43
  end
47
44
 
48
- it "#to_a should return internal representation (nested arrays)" do
45
+ it '#to_a should return internal representation (nested arrays)' do
49
46
  @discrete_matrix.to_a.must_be_instance_of Array
50
- @discrete_matrix.to_a.must_equal [[false,false,false],[false,false,false],[false,false,false]]
47
+ @discrete_matrix.to_a.must_equal [
48
+ [false, false, false],
49
+ [false, false, false],
50
+ [false, false, false]
51
+ ]
51
52
  end
52
53
 
53
- it "#should extend magically." do
54
- refute @discrete_matrix[3,3]
55
- @discrete_matrix[4,8].wont_be_nil
54
+ it '#should extend magically.' do
55
+ refute @discrete_matrix[3, 3]
56
+ @discrete_matrix[4, 8].wont_be_nil
56
57
  end
57
-
58
58
  end
59
59
  end
60
-
61
-