compsci 0.0.3.1 → 0.1.0.1
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 +4 -4
- data/README.md +63 -14
- data/VERSION +1 -1
- data/compsci.gemspec +5 -22
- data/examples/binary_tree.rb +11 -6
- data/examples/complete_tree.rb +47 -0
- data/examples/heap.rb +19 -7
- data/examples/tree.rb +41 -0
- data/lib/compsci.rb +1 -2
- data/lib/compsci/complete_tree.rb +109 -0
- data/lib/compsci/fibonacci.rb +31 -30
- data/lib/compsci/fit.rb +135 -135
- data/lib/compsci/heap.rb +14 -108
- data/lib/compsci/names.rb +132 -0
- data/lib/compsci/node.rb +67 -0
- data/lib/compsci/timer.rb +30 -29
- data/lib/compsci/tree.rb +48 -138
- data/test/bench/tree.rb +2 -2
- data/test/complete_tree.rb +131 -0
- data/test/heap.rb +121 -34
- data/test/names.rb +96 -0
- data/test/node.rb +89 -0
- data/test/tree.rb +49 -237
- metadata +24 -2
data/test/bench/tree.rb
CHANGED
@@ -13,14 +13,14 @@ describe "BinaryTree#push Benchmark" do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
bench_performance_constant "BinaryTree#push (constant)" do |n|
|
16
|
-
tree =
|
16
|
+
tree = NaryTree.new(ChildNode, 42, child_slots: 2)
|
17
17
|
n.times { tree.push rand 99 }
|
18
18
|
end
|
19
19
|
|
20
20
|
bench_performance_linear "BinaryTree#push (linear)" do |n|
|
21
21
|
skip "this fails with r^2 around 0.91"
|
22
22
|
|
23
|
-
tree =
|
23
|
+
tree = NaryTree.new(ChildNode, 42, child_slots: 2)
|
24
24
|
n.times { tree.push rand 99 }
|
25
25
|
end
|
26
26
|
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'compsci/complete_tree'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
include CompSci
|
5
|
+
|
6
|
+
describe CompleteNaryTree do
|
7
|
+
it "must calculate a parent index for N=2" do
|
8
|
+
valid = {
|
9
|
+
1 => 0,
|
10
|
+
2 => 0,
|
11
|
+
3 => 1,
|
12
|
+
4 => 1,
|
13
|
+
5 => 2,
|
14
|
+
6 => 2,
|
15
|
+
7 => 3,
|
16
|
+
8 => 3,
|
17
|
+
9 => 4,
|
18
|
+
10 => 4,
|
19
|
+
}
|
20
|
+
|
21
|
+
invalid = {
|
22
|
+
0 => -1,
|
23
|
+
-1 => -1,
|
24
|
+
-2 => -2,
|
25
|
+
}
|
26
|
+
valid.each { |idx, pidx|
|
27
|
+
CompleteNaryTree.parent_idx(idx, 2).must_equal pidx
|
28
|
+
}
|
29
|
+
invalid.each { |idx, pidx|
|
30
|
+
CompleteNaryTree.parent_idx(idx, 2).must_equal pidx
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
it "must calculate children indices for N=2" do
|
35
|
+
valid = {
|
36
|
+
0 => [1, 2],
|
37
|
+
1 => [3, 4],
|
38
|
+
2 => [5, 6],
|
39
|
+
3 => [7, 8],
|
40
|
+
4 => [9, 10],
|
41
|
+
5 => [11, 12],
|
42
|
+
6 => [13, 14],
|
43
|
+
7 => [15, 16],
|
44
|
+
8 => [17, 18],
|
45
|
+
9 => [19, 20],
|
46
|
+
10 => [21, 22],
|
47
|
+
}
|
48
|
+
|
49
|
+
invalid = {
|
50
|
+
-3 => [-5, -4],
|
51
|
+
-2 => [-3, -2],
|
52
|
+
-1 => [-1, 0],
|
53
|
+
}
|
54
|
+
|
55
|
+
valid.each { |idx, cidx|
|
56
|
+
CompleteNaryTree.children_idx(idx, 2).must_equal cidx
|
57
|
+
}
|
58
|
+
invalid.each { |idx, cidx|
|
59
|
+
CompleteNaryTree.children_idx(idx, 2).must_equal cidx
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
it "must calculate a parent index for N=3" do
|
64
|
+
valid = {
|
65
|
+
1 => 0,
|
66
|
+
2 => 0,
|
67
|
+
3 => 0,
|
68
|
+
4 => 1,
|
69
|
+
5 => 1,
|
70
|
+
6 => 1,
|
71
|
+
7 => 2,
|
72
|
+
8 => 2,
|
73
|
+
9 => 2,
|
74
|
+
10 => 3,
|
75
|
+
}
|
76
|
+
|
77
|
+
invalid = {
|
78
|
+
0 => -1,
|
79
|
+
-1 => -1,
|
80
|
+
-2 => -1,
|
81
|
+
}
|
82
|
+
valid.each { |idx, pidx|
|
83
|
+
CompleteNaryTree.parent_idx(idx, 3).must_equal pidx
|
84
|
+
}
|
85
|
+
invalid.each { |idx, pidx|
|
86
|
+
CompleteNaryTree.parent_idx(idx, 3).must_equal pidx
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
it "must calculate children indices for N=3" do
|
91
|
+
valid = {
|
92
|
+
0 => [1, 2, 3],
|
93
|
+
1 => [4, 5, 6],
|
94
|
+
2 => [7, 8, 9],
|
95
|
+
3 => [10, 11, 12],
|
96
|
+
}
|
97
|
+
|
98
|
+
invalid = {
|
99
|
+
-3 => [-8, -7, -6],
|
100
|
+
-2 => [-5, -4, -3],
|
101
|
+
-1 => [-2, -1, 0],
|
102
|
+
}
|
103
|
+
|
104
|
+
valid.each { |idx, cidx|
|
105
|
+
CompleteNaryTree.children_idx(idx, 3).must_equal cidx
|
106
|
+
}
|
107
|
+
invalid.each { |idx, cidx|
|
108
|
+
CompleteNaryTree.children_idx(idx, 3).must_equal cidx
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "instance" do
|
113
|
+
before do
|
114
|
+
@array = (0..99).sort_by { rand }
|
115
|
+
@empty = CompleteNaryTree.new(child_slots: 5)
|
116
|
+
@nonempty = CompleteQuaternaryTree.new(array: @array)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "must have a size" do
|
120
|
+
@empty.size.must_equal 0
|
121
|
+
@nonempty.size.must_equal @array.size
|
122
|
+
end
|
123
|
+
|
124
|
+
it "must have a last_idx, nil when empty" do
|
125
|
+
@empty.last_idx.nil?.must_equal true
|
126
|
+
@nonempty.last_idx.must_equal 99
|
127
|
+
end
|
128
|
+
|
129
|
+
# TODO: push, pop, display
|
130
|
+
end
|
131
|
+
end
|
data/test/heap.rb
CHANGED
@@ -4,43 +4,130 @@ require 'minitest/autorun'
|
|
4
4
|
include CompSci
|
5
5
|
|
6
6
|
describe Heap do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
describe "MaxHeap" do
|
8
|
+
before do
|
9
|
+
@maxheap = Heap.new
|
10
|
+
@inserts = Array.new(10) { |i| i + 1 }.each { |i| @maxheap.push i }
|
11
|
+
end
|
12
|
+
|
13
|
+
it "must satisfy the heap property" do
|
14
|
+
@maxheap.heap?.must_equal true
|
15
|
+
@maxheap.array.wont_equal @inserts
|
16
|
+
@maxheap.array.wont_equal @inserts.reverse
|
17
|
+
end
|
18
|
+
|
19
|
+
it "must recognize heap violations" do
|
20
|
+
@maxheap.array.unshift 0
|
21
|
+
@maxheap.heap?.must_equal false
|
22
|
+
@maxheap.array.shift
|
23
|
+
@maxheap.heap?.must_equal true
|
24
|
+
|
25
|
+
@maxheap.array.push 10
|
26
|
+
@maxheap.heap?.must_equal false
|
27
|
+
@maxheap.sift_up @maxheap.last_idx
|
28
|
+
@maxheap.heap?.must_equal true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "must pop" do
|
32
|
+
@maxheap.pop.must_equal 10
|
33
|
+
@maxheap.peek.wont_equal 10
|
34
|
+
@maxheap.heap?.must_equal true
|
35
|
+
end
|
36
|
+
|
37
|
+
it "must heapish?" do
|
38
|
+
@maxheap.array[0].must_be :>, @maxheap.array[1]
|
39
|
+
@maxheap.heapish?(0, 1).must_equal true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "must heapiest" do
|
43
|
+
@maxheap.heapiest([1, 2]).must_equal 1
|
44
|
+
@maxheap.heapiest([3, 4]).must_equal 4
|
45
|
+
@maxheap.heapiest([5, 6]).must_equal 6
|
46
|
+
@maxheap.heapiest([7, 8]).must_equal 8
|
47
|
+
end
|
15
48
|
end
|
16
49
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
50
|
+
describe "MinHeap" do
|
51
|
+
before do
|
52
|
+
@minheap = Heap.new(minheap: true)
|
53
|
+
@inserts = Array.new(10) { |i| i + 1 }.each { |i| @minheap.push i }
|
54
|
+
end
|
55
|
+
|
56
|
+
it "must satisfy the heap property" do
|
57
|
+
@minheap.heap?.must_equal true
|
58
|
+
@minheap.array.must_equal @inserts
|
59
|
+
end
|
60
|
+
|
61
|
+
it "must recognize heap violations" do
|
62
|
+
@minheap.array.unshift 10
|
63
|
+
@minheap.heap?.must_equal false
|
64
|
+
@minheap.array.shift
|
65
|
+
@minheap.heap?.must_equal true
|
66
|
+
|
67
|
+
@minheap.array.push 0
|
68
|
+
@minheap.heap?.must_equal false
|
69
|
+
@minheap.sift_up @minheap.last_idx
|
70
|
+
@minheap.heap?.must_equal true
|
71
|
+
end
|
72
|
+
|
73
|
+
it "must pop" do
|
74
|
+
@minheap.pop.must_equal 1
|
75
|
+
@minheap.peek.wont_equal 1
|
76
|
+
@minheap.heap?.must_equal true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "must heapish?" do
|
80
|
+
@minheap.array[0].must_be :<, @minheap.array[1]
|
81
|
+
@minheap.heapish?(0, 1).must_equal true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "must heapiest" do
|
85
|
+
@minheap.heapiest([1, 2]).must_equal 1
|
86
|
+
@minheap.heapiest([3, 4]).must_equal 3
|
87
|
+
@minheap.heapiest([5, 6]).must_equal 5
|
88
|
+
@minheap.heapiest([7, 8]).must_equal 7
|
89
|
+
end
|
23
90
|
end
|
24
91
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
92
|
+
describe "TernaryHeap" do
|
93
|
+
before do
|
94
|
+
@heap3 = Heap.new(child_slots: 3)
|
95
|
+
@inserts = Array.new(10) { |i| i + 1 }.each { |i| @heap3.push i }
|
96
|
+
end
|
97
|
+
|
98
|
+
it "must satisfy the heap property" do
|
99
|
+
@heap3.heap?.must_equal true
|
100
|
+
@heap3.array.wont_equal @inserts
|
101
|
+
@heap3.array.wont_equal @inserts.reverse
|
102
|
+
end
|
103
|
+
|
104
|
+
it "must recognize heap violations" do
|
105
|
+
@heap3.array.unshift 0
|
106
|
+
@heap3.heap?.must_equal false
|
107
|
+
@heap3.array.shift
|
108
|
+
@heap3.heap?.must_equal true
|
109
|
+
|
110
|
+
@heap3.array.push 10
|
111
|
+
@heap3.heap?.must_equal false
|
112
|
+
@heap3.sift_up @heap3.last_idx
|
113
|
+
@heap3.heap?.must_equal true
|
114
|
+
end
|
115
|
+
|
116
|
+
it "must pop" do
|
117
|
+
@heap3.pop.must_equal 10
|
118
|
+
@heap3.peek.wont_equal 10
|
119
|
+
@heap3.heap?.must_equal true
|
120
|
+
end
|
121
|
+
|
122
|
+
it "must heapish?" do
|
123
|
+
@heap3.array[0].must_be :>, @heap3.array[1]
|
124
|
+
@heap3.heapish?(0, 1).must_equal true
|
125
|
+
end
|
126
|
+
|
127
|
+
it "must heapiest" do
|
128
|
+
@heap3.heapiest([1, 2, 3]).must_equal 2
|
129
|
+
@heap3.heapiest([4, 5, 6]).must_equal 6
|
130
|
+
@heap3.heapiest([7, 8, 9]).must_equal 9
|
131
|
+
end
|
45
132
|
end
|
46
133
|
end
|
data/test/names.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'compsci/names'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
include CompSci
|
5
|
+
|
6
|
+
describe Names do
|
7
|
+
describe "alphabetic constants" do
|
8
|
+
it "must have size 26" do
|
9
|
+
Names::WW1.size.must_equal 26
|
10
|
+
Names::WW2.size.must_equal 26
|
11
|
+
Names::NATO.size.must_equal 26
|
12
|
+
Names::ENGLISH_UPPER.size.must_equal 26
|
13
|
+
Names::ENGLISH_LOWER.size.must_equal 26
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "Names.assign" do
|
18
|
+
it "must handle English / ASCII strings" do
|
19
|
+
upper_lower = Names::ENGLISH_UPPER + Names::ENGLISH_LOWER
|
20
|
+
Names.assign('cat', Names::ENGLISH_UPPER).must_equal 'C'
|
21
|
+
Names.assign('Cat', Names::ENGLISH_UPPER).must_equal 'C'
|
22
|
+
Names.assign('cat', Names::ENGLISH_LOWER).must_equal 'c'
|
23
|
+
Names.assign('Cat', Names::ENGLISH_LOWER).must_equal 'c'
|
24
|
+
Names.assign('Cat', upper_lower).must_equal 'C'
|
25
|
+
Names.assign('cat', upper_lower).must_equal 'c'
|
26
|
+
Names.assign('cat', Names::NATO).must_equal :charlie
|
27
|
+
Names.assign('Cat', Names::NATO).must_equal :charlie
|
28
|
+
Names.assign('Dog', Names::CRYPTO).must_equal :david
|
29
|
+
Names.assign('2', Names::PLANETS).must_equal :earth
|
30
|
+
end
|
31
|
+
|
32
|
+
it "must handle integers" do
|
33
|
+
upper_lower = Names::ENGLISH_UPPER + Names::ENGLISH_LOWER
|
34
|
+
Names.assign(36, upper_lower).must_equal 'k'
|
35
|
+
Names.assign(0, upper_lower).must_equal 'A'
|
36
|
+
Names.assign(0, Names::ENGLISH_UPPER).must_equal 'A'
|
37
|
+
Names.assign(3, Names::ENGLISH_LOWER).must_equal 'd'
|
38
|
+
Names.assign(3, Names::PLANETS).must_equal :mars
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe Names::Greek do
|
43
|
+
describe "greek alphabetic constants" do
|
44
|
+
it "must have size 24" do
|
45
|
+
Names::Greek::UPPER.size.must_equal 24
|
46
|
+
Names::Greek::LOWER.size.must_equal 24
|
47
|
+
Names::Greek::SYMBOLS.size.must_equal 24
|
48
|
+
Names::Greek::CHAR_MAP.size.must_equal 24
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "SYMBOLS26" do
|
53
|
+
it "must work well with Names.assign" do
|
54
|
+
s26 = Names::Greek::SYMBOLS26
|
55
|
+
Names.assign('iota', s26).must_equal :iota
|
56
|
+
Names.assign('jota', s26).must_equal :xi
|
57
|
+
Names.assign('Query', s26).must_equal :xi
|
58
|
+
Names.assign('who', s26).must_equal :xi
|
59
|
+
Names.assign('zeta', s26).must_equal :omega
|
60
|
+
Names.assign(0, s26).must_equal :alpha
|
61
|
+
Names.assign('1', s26).must_equal :beta
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "Greek.sym" do
|
67
|
+
it "must handle strings and integers" do
|
68
|
+
Names::Greek.sym('cat').must_equal :gamma
|
69
|
+
Names::Greek.sym('Cat').must_equal :gamma
|
70
|
+
Names::Greek.sym('zeta').must_equal :omega
|
71
|
+
Names::Greek.sym(0).must_equal :alpha
|
72
|
+
Names::Greek.sym('1').must_equal :beta
|
73
|
+
Names::Greek.sym(23).must_equal :omega
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "Greek.lower" do
|
78
|
+
it "must handle strings and integers" do
|
79
|
+
third = Names::Greek::LOWER[2]
|
80
|
+
Names::Greek.lower('cat').must_equal third
|
81
|
+
Names::Greek.lower('Cat').must_equal third
|
82
|
+
Names::Greek.lower(2).must_equal third
|
83
|
+
Names::Greek.lower('2').must_equal third
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "Greek.upper" do
|
88
|
+
it "must handle strings and integers" do
|
89
|
+
fourth = Names::Greek::UPPER[3]
|
90
|
+
Names::Greek.upper('dog').must_equal fourth
|
91
|
+
Names::Greek.upper('Dog').must_equal fourth
|
92
|
+
Names::Greek.upper(3).must_equal fourth
|
93
|
+
Names::Greek.upper('3').must_equal fourth
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/test/node.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'compsci/node'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
include CompSci
|
5
|
+
|
6
|
+
describe Node do
|
7
|
+
before do
|
8
|
+
@martin_sheen = Node.new 'martin'
|
9
|
+
@charlie_sheen = Node.new 'charlie'
|
10
|
+
@emilio_estevez = Node.new 'emilio'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "must start with no children" do
|
14
|
+
[@martin_sheen, @charlie_sheen, @emilio_estevez].each { |n|
|
15
|
+
n.children.must_be_empty
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
it "must track children" do
|
20
|
+
@charlie_sheen.add_parent(@martin_sheen)
|
21
|
+
@martin_sheen.children.must_include @charlie_sheen
|
22
|
+
|
23
|
+
@martin_sheen.children.wont_include @emilio_estevez
|
24
|
+
@martin_sheen.add_child @emilio_estevez
|
25
|
+
@martin_sheen.children.must_include @emilio_estevez
|
26
|
+
end
|
27
|
+
|
28
|
+
it "must not respond to :parent" do
|
29
|
+
@martin_sheen.respond_to?(:parent).must_equal false
|
30
|
+
end
|
31
|
+
|
32
|
+
it "must create children from scalars" do
|
33
|
+
@martin_sheen.new_child 'fake_emilio'
|
34
|
+
@martin_sheen.children.size.must_equal 1
|
35
|
+
@martin_sheen.children.first.value.must_equal 'fake_emilio'
|
36
|
+
@martin_sheen.children.wont_include @emilio_estevez
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe ChildNode do
|
41
|
+
before do
|
42
|
+
@martin_sheen = ChildNode.new 'martin'
|
43
|
+
@charlie_sheen = ChildNode.new 'charlie'
|
44
|
+
@emilio_estevez = ChildNode.new 'emilio'
|
45
|
+
end
|
46
|
+
|
47
|
+
it "must start with neither parent nor children" do
|
48
|
+
[@martin_sheen, @charlie_sheen, @emilio_estevez].each { |n|
|
49
|
+
n.parent.nil?.must_equal true
|
50
|
+
n.children.must_be_empty
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
it "must track parent and children" do
|
55
|
+
@charlie_sheen.add_parent(@martin_sheen)
|
56
|
+
@charlie_sheen.parent.must_equal @martin_sheen
|
57
|
+
@martin_sheen.children.must_include @charlie_sheen
|
58
|
+
|
59
|
+
@martin_sheen.children.wont_include @emilio_estevez
|
60
|
+
@martin_sheen.add_child @emilio_estevez
|
61
|
+
@martin_sheen.children.must_include @emilio_estevez
|
62
|
+
@emilio_estevez.parent.must_equal @martin_sheen
|
63
|
+
end
|
64
|
+
|
65
|
+
it "must determine a node's generation" do
|
66
|
+
@emilio_estevez.gen.must_equal 0
|
67
|
+
@martin_sheen.add_child @emilio_estevez
|
68
|
+
@emilio_estevez.gen.must_equal 1
|
69
|
+
end
|
70
|
+
|
71
|
+
it "must create children from scalars" do
|
72
|
+
@martin_sheen.new_child 'fake_emilio'
|
73
|
+
@martin_sheen.children.size.must_equal 1
|
74
|
+
@martin_sheen.children.first.value.must_equal 'fake_emilio'
|
75
|
+
@martin_sheen.children.wont_include @emilio_estevez
|
76
|
+
end
|
77
|
+
|
78
|
+
it "must recognize siblings" do
|
79
|
+
@charlie_sheen.add_parent @martin_sheen
|
80
|
+
@emilio_estevez.add_parent @martin_sheen
|
81
|
+
@martin_sheen.new_child 'fake_emilio'
|
82
|
+
|
83
|
+
@charlie_sheen.siblings.must_include @emilio_estevez
|
84
|
+
@charlie_sheen.siblings.wont_include @martin_sheen
|
85
|
+
@emilio_estevez.siblings.must_include @charlie_sheen
|
86
|
+
@martin_sheen.siblings.must_be_empty
|
87
|
+
@emilio_estevez.siblings.find { |n| n.value == 'fake_emilio' }.wont_be_nil
|
88
|
+
end
|
89
|
+
end
|