ds 0.0.4 → 0.0.6
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 +7 -0
- data/.rubocop.yml +11 -0
- data/.rubocop_todo.yml +452 -0
- data/.travis.yml +12 -0
- data/Gemfile +1 -1
- data/README.rdoc +185 -214
- data/Rakefile +8 -3
- data/ds.gemspec +16 -13
- data/lib/ds.rb +20 -30
- data/lib/ds/{matrixes → arrays}/array_2d.rb +9 -10
- data/lib/ds/arrays/expandable_array.rb +34 -0
- data/lib/ds/arrays/heap_store.rb +32 -0
- data/lib/ds/arrays/tri_matrix.rb +33 -0
- data/lib/ds/lists/list.rb +310 -186
- data/lib/ds/lists/list_element.rb +14 -11
- data/lib/ds/pair.rb +4 -4
- data/lib/ds/queues/priority_queue.rb +33 -20
- data/lib/ds/queues/simple_queue.rb +55 -0
- data/lib/ds/sets/indexed_set.rb +37 -0
- data/lib/ds/stacks/stack.rb +25 -17
- data/lib/ds/trees/binary_heap.rb +71 -66
- data/lib/ds/trees/binary_tree.rb +40 -44
- data/lib/ds/trees/red_black_tree.rb +123 -0
- data/lib/ds/trees/red_black_tree/node.rb +21 -0
- data/lib/ds/trees/tree.rb +50 -48
- data/lib/ds/trees/tree_walker.rb +73 -144
- data/lib/ds/trees/trie.rb +67 -37
- data/lib/ds/trees/trie/node.rb +48 -0
- data/lib/ds/version.rb +2 -1
- data/test/help.rb +3 -6
- data/test/performance/binary_heap_performance_test.rb +20 -0
- data/test/performance/list_performance_test.rb +36 -0
- data/test/performance/priority_queue_performance.rb +32 -0
- data/test/performance/rbt_performance_test.rb +17 -0
- data/test/performance/simple_queue_performance_test.rb +37 -0
- data/test/performance/stack_test.rb +45 -0
- data/test/test_array2d.rb +29 -31
- data/test/test_binary_heap.rb +29 -23
- data/test/test_binary_tree.rb +30 -20
- data/test/test_expandable_array.rb +6 -10
- data/test/test_heap_store.rb +34 -0
- data/test/test_indexed_set.rb +26 -0
- data/test/test_list.rb +226 -109
- data/test/test_list_element.rb +34 -16
- data/test/test_pair.rb +5 -8
- data/test/test_priority_queue.rb +43 -64
- data/test/test_queue.rb +12 -61
- data/test/test_red_black_tree.rb +46 -0
- data/test/test_stack.rb +35 -39
- data/test/test_tree.rb +42 -29
- data/test/test_tree_walker.rb +27 -52
- data/test/test_tri_matrix.rb +6 -11
- data/test/test_trie.rb +59 -17
- metadata +80 -35
- data/lib/ds/ext/array_x.rb +0 -35
- data/lib/ds/graphs/digraph.rb +0 -20
- data/lib/ds/graphs/edge.rb +0 -15
- data/lib/ds/graphs/graph.rb +0 -111
- data/lib/ds/graphs/graph_as_matrix.rb +0 -113
- data/lib/ds/graphs/graph_as_tri_matrix.rb +0 -24
- data/lib/ds/lists/cyclic_list.rb +0 -21
- data/lib/ds/lists/ring.rb +0 -42
- data/lib/ds/matrixes/expandable_array.rb +0 -37
- data/lib/ds/matrixes/tri_matrix.rb +0 -30
- data/lib/ds/queues/queue.rb +0 -53
- data/lib/ds/sets/ordered_set.rb +0 -32
- data/lib/ds/trees/binary_search_tree.rb +0 -34
- data/lib/ds/trees/complete_binary_tree.rb +0 -60
- data/test/test_array_x.rb +0 -51
- data/test/test_binary_search_tree.rb +0 -39
- data/test/test_complete_binary_tree.rb +0 -58
- data/test/test_digraph.rb +0 -134
- data/test/test_graph.rb +0 -80
- data/test/test_ordered_set.rb +0 -28
- data/test/test_ring.rb +0 -28
data/lib/ds/trees/trie.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
17
|
+
@alphabet.keys
|
8
18
|
end
|
9
|
-
|
10
|
-
def
|
11
|
-
@
|
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
|
17
|
-
|
18
|
-
|
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
|
23
|
-
|
24
|
-
|
34
|
+
letters = get_letters(s)
|
35
|
+
node = root.get(letters, self)
|
36
|
+
node.data if node
|
25
37
|
end
|
26
38
|
|
27
|
-
|
28
|
-
|
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
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
49
|
-
|
50
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
data/lib/ds/version.rb
CHANGED
data/test/help.rb
CHANGED
@@ -1,17 +1,14 @@
|
|
1
1
|
if ENV['COVERAGE']
|
2
2
|
require 'simplecov'
|
3
3
|
SimpleCov.start do
|
4
|
-
add_filter
|
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
|
13
|
-
require
|
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
|
data/test/test_array2d.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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 [
|
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
|
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
|
-
|