ds 0.0.4 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|