compsci 0.3.0.1 → 0.3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +138 -79
- data/Rakefile +3 -1
- data/VERSION +1 -1
- data/compsci.gemspec +2 -2
- data/examples/binary_search_tree.rb +43 -8
- data/examples/complete_tree.rb +21 -22
- data/examples/flex_node.rb +117 -0
- data/examples/heap.rb +40 -2
- data/examples/heap_push.rb +7 -1
- data/examples/ternary_search_tree.rb +30 -0
- data/examples/tree.rb +27 -25
- data/lib/compsci/complete_tree.rb +6 -7
- data/lib/compsci/fit.rb +17 -0
- data/lib/compsci/flex_node.rb +90 -0
- data/lib/compsci/heap.rb +1 -2
- data/lib/compsci/names/pokemon.rb +62 -0
- data/lib/compsci/node.rb +109 -59
- data/lib/compsci/simplex/parse.rb +10 -6
- data/lib/compsci/simplex.rb +19 -20
- data/lib/compsci/timer.rb +61 -1
- data/lib/compsci.rb +10 -1
- data/test/bench/fibonacci.rb +29 -128
- data/test/bench/flex_node.rb +30 -0
- data/test/complete_tree.rb +16 -14
- data/test/compsci.rb +25 -0
- data/test/fibonacci.rb +6 -5
- data/test/fit.rb +84 -42
- data/test/flex_node.rb +226 -0
- data/test/heap.rb +46 -46
- data/test/names.rb +95 -56
- data/test/node.rb +177 -85
- data/test/simplex_parse.rb +23 -15
- data/test/timer.rb +10 -10
- metadata +17 -17
- data/examples/tree_push.rb +0 -72
- data/lib/compsci/binary_search_tree.rb +0 -86
- data/lib/compsci/tree.rb +0 -142
- data/test/bench/tree.rb +0 -31
- data/test/binary_search_tree.rb +0 -98
- data/test/tree.rb +0 -200
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5a7f1f7282649dec4f08ef08ce3eb3b5b3b97183137624deaa9f20567650185a
|
4
|
+
data.tar.gz: 57081ef332e9adc6d3dbdc06b3ff2c9c76955d26b4fdd90402b7547b5544e0fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdb60b8e1230cdc175ac43afca1efe51bb163ce71dfb2cdd29ffa8ff8ab586456ec181dd46389d54b768edb360f5f9f56d6729bbd65ee86fcd7fa7acee0f417e
|
7
|
+
data.tar.gz: 3f20b69bd337aebc862a7f40e1e1177386979f71065200fa18e4dd69bdefb3a382dd8cbd066903d2ba5793cf5c71acd9cd09b79088c4c15b38982b8196bfb0c2
|
data/README.md
CHANGED
@@ -1,88 +1,105 @@
|
|
1
|
-
[![
|
1
|
+
[![CI Status](https://github.com/rickhull/compsci/actions/workflows/ci.yaml/badge.svg)](https://github.com/rickhull/compsci/actions/workflows/ci.yaml)
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/compsci.svg)](https://badge.fury.io/rb/compsci)
|
2
3
|
|
3
4
|
# CompSci
|
4
5
|
|
5
6
|
Provided are some toy implementations for some basic computer science problems.
|
6
7
|
|
7
|
-
## [`Node`](lib/compsci/node.rb)
|
8
|
+
## [`Node`](lib/compsci/node.rb) classes
|
9
|
+
|
10
|
+
### `Node`
|
11
|
+
|
12
|
+
A *Node* provides a tree structure by assigning other *Nodes* to `@children`.
|
8
13
|
|
9
14
|
* `Node`
|
10
15
|
- `@value`
|
11
16
|
- `@children`
|
12
|
-
- `#
|
13
|
-
|
14
|
-
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
- `#[]` - child node at index
|
18
|
+
- `#[]=` - set child node at index
|
19
|
+
- `display` - display full tree with all descendents
|
20
|
+
|
21
|
+
* [examples/tree.rb](examples/tree.rb)
|
22
|
+
* [test/node.rb](test/node.rb#L7)
|
23
|
+
|
24
|
+
### `KeyNode`
|
25
|
+
|
26
|
+
A *KeyNode* adds `@key` and allows a comparison based search on the key.
|
27
|
+
[Binary search trees](https://en.wikipedia.org/wiki/Binary_search_tree)
|
28
|
+
are supported, and the `@duplicated` flag determines whether duplicate keys
|
29
|
+
are allowed to be inserted. Any duplicates will not be returned from
|
30
|
+
`#search`. A Ternary search tree is also supported, and it inherently allows
|
31
|
+
duplicates keys. `#search` returns an array of `KeyNode`, possibly empty.
|
32
|
+
|
33
|
+
* `KeyNode < Node`
|
34
|
+
- `KeyNode.key_cmp_idx` - compare 2 keys to decide on a child slot
|
35
|
+
- `@key` - any *Comparable*
|
36
|
+
- `@duplicates` - boolean flag relevant for @children.size == 2
|
37
|
+
- `#cidx` - calls `KeyNode.key_cmp_idx`
|
38
|
+
- `#insert`
|
39
|
+
- `#search`
|
40
|
+
|
41
|
+
* [examples/binary_search_tree.rb](examples/binary_search_tree.rb)
|
42
|
+
* [examples/ternary_search_tree.rb](examples/ternary_search_tree.rb)
|
43
|
+
* [test/node.rb](test/node.rb#L43)
|
44
|
+
|
45
|
+
### `ChildNode`
|
46
|
+
|
47
|
+
A *ChildNode* adds reference to its `@parent`.
|
48
|
+
|
49
|
+
* `ChildNode < Node`
|
20
50
|
- `@parent`
|
21
51
|
- `#gen`
|
22
52
|
- `#siblings`
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
-
|
33
|
-
-
|
34
|
-
|
35
|
-
- `@child_slots` (number of children per node)
|
36
|
-
- `#open_parent` O(n) to find a node with open child slots
|
37
|
-
- `#push` append `#open_parent.children`
|
38
|
-
- `#display` if initialized with `ChildNode`
|
39
|
-
* `BinaryTree`
|
40
|
-
- `NaryTree.new(child_slots: 2)`
|
41
|
-
- `#display` for `Node` and `ChildNode`
|
42
|
-
* `TernaryTree`
|
43
|
-
- `NaryTree.new(child_slots: 3)`
|
44
|
-
* `QuaternaryTree`
|
45
|
-
- `NaryTree.new(child_slots: 4)`
|
46
|
-
|
47
|
-
## [`CompleteNaryTree`](lib/compsci/complete_tree.rb) data structure
|
48
|
-
|
49
|
-
Efficient Array implementation of a complete tree.
|
50
|
-
|
51
|
-
* `CompleteNaryTree`
|
52
|
-
- `CompleteNaryTree.parent_idx`
|
53
|
-
- `CompleteNaryTree.children_idx`
|
54
|
-
- `CompleteNaryTree.gen`
|
53
|
+
|
54
|
+
* [test/node.rb](test/node.rb#L190)
|
55
|
+
|
56
|
+
## [`CompleteTree`](lib/compsci/complete_tree.rb) classes
|
57
|
+
|
58
|
+
Efficient *Array* implementation of a complete tree uses arithmetic to
|
59
|
+
determine parent/child relationships.
|
60
|
+
|
61
|
+
* `CompleteTree`
|
62
|
+
- `CompleteTree.parent_idx`
|
63
|
+
- `CompleteTree.children_idx`
|
64
|
+
- `CompleteTree.gen`
|
55
65
|
- `@array`
|
56
66
|
- `@child_slots`
|
57
67
|
- `#push`
|
58
68
|
- `#pop`
|
59
69
|
- `#size`
|
60
70
|
- `#last_idx`
|
61
|
-
- `#display`
|
62
|
-
* `CompleteBinaryTree`
|
63
|
-
-
|
64
|
-
* `CompleteTernaryTree`
|
65
|
-
-
|
66
|
-
* `CompleteQuaternaryTree`
|
67
|
-
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
71
|
+
- `#display` - alias `#to_s`
|
72
|
+
* `CompleteBinaryTree < CompleteTree`
|
73
|
+
- `@child_slots = 2`
|
74
|
+
* `CompleteTernaryTree < CompleteTree`
|
75
|
+
- `@child_slots = 3`
|
76
|
+
* `CompleteQuaternaryTree < CompleteTree`
|
77
|
+
- `@child_slots = 4`
|
78
|
+
|
79
|
+
* [examples/complete_tree.rb](examples/complete_tree.rb)
|
80
|
+
* [test/complete_tree.rb](test/complete_tree.rb)
|
81
|
+
* [test/bench/complete_tree.rb](test/bench/complete_tree.rb)
|
82
|
+
|
83
|
+
## [`Heap`](lib/compsci/heap.rb) class
|
84
|
+
|
85
|
+
*CompleteTree* implementation. Both *minheaps* and *maxheaps* are
|
86
|
+
supported. Any number of children may be provided via `child_slots`.
|
87
|
+
The primary operations are `Heap#push` and `Heap#pop`. My basic Vagrant VM
|
88
|
+
gets over [500k pushes per second](reports/examples#L533), constant up past
|
89
|
+
1M pushes.
|
90
|
+
|
91
|
+
* `Heap < CompleteTree`
|
92
|
+
- `#push`
|
93
|
+
- `#pop`
|
94
|
+
- `#sift_up`
|
95
|
+
- `#sift_down`
|
81
96
|
|
82
|
-
|
83
|
-
|
97
|
+
* [examples/heap.rb](examples/heap.rb)
|
98
|
+
* [examples/heap_push.rb](examples/heap_push.rb)
|
99
|
+
* [test/heap.rb](test/heap.rb)
|
100
|
+
* [test/bench/heap.rb](test/bench/heap.rb)
|
84
101
|
|
85
|
-
## [`Fibonacci`](lib/compsci/fibonacci.rb)
|
102
|
+
## [`Fibonacci`](lib/compsci/fibonacci.rb) module
|
86
103
|
|
87
104
|
* `Fibonacci.classic(n)` - naive, recursive
|
88
105
|
* `Fibonacci.cache_recursive(n)` - as above, caching already computed results
|
@@ -90,13 +107,22 @@ pushes](reports/examples#L484).
|
|
90
107
|
* `Fibonacci.dynamic(n)` - as above but without a cache structure
|
91
108
|
* `Fibonacci.matrix(n)` - matrix is magic; beats dynamic around n=500
|
92
109
|
|
93
|
-
|
110
|
+
* [test/fibonacci.rb](test/fibonacci.rb)
|
111
|
+
* [test/bench/fibonacci.rb](test/bench/fibonacci.rb)
|
112
|
+
|
113
|
+
## [`Timer`](/lib/compsci/timer.rb) module
|
94
114
|
|
95
115
|
* `Timer.now` - uses `Process::CLOCK_MONOTONIC` if available
|
96
116
|
* `Timer.since` - provides the elapsed time since a prior time
|
97
117
|
* `Timer.elapsed` - provides the elapsed time to run a block
|
98
118
|
* `Timer.loop_avg` - loops a block; returns final value and mean elapsed time
|
99
119
|
|
120
|
+
* [examples/heap_push.rb](examples/heap_push.rb)
|
121
|
+
* [test/timer.rb](test/timer.rb)
|
122
|
+
* [test/bench/complete_tree.rb](test/bench/complete_tree.rb)
|
123
|
+
* [test/bench/simplex.rb](test/bench/simplex.rb)
|
124
|
+
* [test/timer.rb](test/timer.rb)
|
125
|
+
|
100
126
|
```ruby
|
101
127
|
require 'compsci/timer'
|
102
128
|
|
@@ -142,36 +168,69 @@ elapsed: 0.304
|
|
142
168
|
cumulative: 0.828
|
143
169
|
```
|
144
170
|
|
145
|
-
## [`Fit`](lib/compsci/fit.rb)
|
171
|
+
## [`Fit`](lib/compsci/fit.rb) module
|
146
172
|
|
147
173
|
* `Fit.sigma` - sums the result of a block applied to array values
|
148
174
|
* `Fit.error` - returns a generic r^2 value, the coefficient of determination
|
149
|
-
* `Fit.constant`
|
175
|
+
* `Fit.constant` - fits `y = a + 0x`; returns the mean and variance
|
150
176
|
* `Fit.logarithmic` - fits `y = a + b*ln(x)`; returns a, b, r^2
|
151
|
-
* `Fit.linear`
|
152
|
-
* `Fit.exponential` fits `y = ae^(bx)`; returns a, b, r^2
|
153
|
-
* `Fit.power` fits `y = ax^b`; returns a, b, r^2
|
177
|
+
* `Fit.linear` - fits `y = a + bx`; returns a, b, r^2
|
178
|
+
* `Fit.exponential` - fits `y = ae^(bx)`; returns a, b, r^2
|
179
|
+
* `Fit.power` - fits `y = ax^b`; returns a, b, r^2
|
180
|
+
* `Fit.best` - applies known fits; returns the fit with highest r^2
|
181
|
+
|
182
|
+
* [test/bench/complete_tree.rb](test/bench/complete_tree.rb)
|
183
|
+
* [test/fit.rb](test/fit.rb)
|
184
|
+
|
185
|
+
## [`Names`](lib/compsci/names.rb) module
|
154
186
|
|
155
|
-
|
187
|
+
This helps map a range of small integers to friendly names, typically in
|
188
|
+
alphabetical order.
|
156
189
|
|
190
|
+
* `ENGLISH_UPPER` `ENGLISH_LOWER` `WW1` `WW2` `NATO` `CRYPTO` `PLANETS` `SOLAR`
|
157
191
|
* `Names.assign`
|
158
|
-
|
159
|
-
*
|
160
|
-
*
|
192
|
+
|
193
|
+
* [examples/binary_search_tree.rb](examples/binary_search_tree.rb)
|
194
|
+
* [examples/ternary_search_tree.rb](examples/ternary_search_tree.rb)
|
195
|
+
* [test/names.rb](test/names.rb)
|
196
|
+
* [test/node.rb](test/node.rb)
|
197
|
+
|
198
|
+
### [`Names::Greek`](lib/compsci/names/greek.rb) module
|
199
|
+
|
200
|
+
- `UPPER` `LOWER` `SYMBOLS` `CHAR_MAP` `LATIN_SYMBOLS` `SYMBOLS26`
|
201
|
+
- `Names::Greek.upper`
|
202
|
+
- `Names::Greek.lower`
|
203
|
+
- `Names::Greek.sym`
|
204
|
+
|
205
|
+
### [`Names::Pokemon`](lib/compsci/names/pokemon.rb) module
|
206
|
+
|
207
|
+
- `Names::Pokemon.array`
|
208
|
+
- `Names::Pokemon.hash`
|
209
|
+
- `Names::Pokemon.grep`
|
210
|
+
- `Names::Pokemon.sample`
|
161
211
|
|
162
212
|
## [`Simplex`](lib/compsci/simplex.rb) class
|
163
213
|
|
164
|
-
|
165
|
-
|
166
|
-
|
214
|
+
### WORK IN PROGRESS; DO NOT USE
|
215
|
+
|
216
|
+
The [Simplex algorithm](https://en.wikipedia.org/wiki/Simplex_algorithm)
|
217
|
+
is a technique for
|
218
|
+
[Linear programming](https://en.wikipedia.org/wiki/Linear_programming).
|
219
|
+
Typically the problem is to maximize some linear expression of variables
|
220
|
+
given some constraints on those variables in terms of linear inequalities.
|
167
221
|
|
168
|
-
|
222
|
+
* [test/bench/simplex.rb](test/bench/simplex.rb)
|
223
|
+
* [test/simplex.rb](test/simplex.rb)
|
224
|
+
|
225
|
+
### [`Simplex::Parse`](lib/compsci/simplex/parse.rb) module
|
169
226
|
|
170
227
|
* `Parse.tokenize` - convert a string to an array of tokens
|
171
228
|
* `Parse.term` - parse certain tokens into [coefficient, varname]
|
172
229
|
* `Parse.expression` - parse a string representing a sum of terms
|
173
230
|
* `Parse.inequality` - parse a string like "#{expression} <= #{const}"
|
174
231
|
|
232
|
+
* [test/simplex_parse.rb](test/simplex_parse.rb)
|
233
|
+
|
175
234
|
With `Simplex::Parse`, one can obtain solutions via:
|
176
235
|
|
177
236
|
* `Simplex.maximize` - takes an expression to maximize followed by a variable
|
data/Rakefile
CHANGED
@@ -78,7 +78,9 @@ scripts = [
|
|
78
78
|
"examples/heap.rb",
|
79
79
|
"examples/heap_push.rb",
|
80
80
|
"examples/tree.rb",
|
81
|
-
"examples/
|
81
|
+
"examples/flex_node.rb",
|
82
|
+
"examples/binary_search_tree.rb",
|
83
|
+
"examples/ternary_search_tree.rb",
|
82
84
|
]
|
83
85
|
|
84
86
|
desc "Run ruby-prof on examples/"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.2.1
|
data/compsci.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.homepage = "https://github.com/rickhull/compsci"
|
7
7
|
s.license = "LGPL-3.0"
|
8
8
|
|
9
|
-
s.required_ruby_version = "~>
|
9
|
+
s.required_ruby_version = "~> 3.0"
|
10
10
|
|
11
11
|
s.version = File.read(File.join(__dir__, 'VERSION')).chomp
|
12
12
|
|
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
|
18
18
|
s.add_development_dependency "buildar", "~> 3.0"
|
19
19
|
s.add_development_dependency "minitest", "~> 5.0"
|
20
|
-
s.add_development_dependency "rake", "~>
|
20
|
+
s.add_development_dependency "rake", "~> 12.3" # CVE-2020-8130
|
21
21
|
s.add_development_dependency "flog", "~> 0"
|
22
22
|
s.add_development_dependency "flay", "~> 0"
|
23
23
|
s.add_development_dependency "roodi", "~> 0"
|
@@ -1,16 +1,51 @@
|
|
1
1
|
require 'compsci/node'
|
2
|
-
require 'compsci/binary_search_tree'
|
3
2
|
require 'compsci/names'
|
4
3
|
|
5
4
|
include CompSci
|
6
5
|
|
7
|
-
|
6
|
+
puts <<EOF
|
7
|
+
|
8
|
+
#
|
9
|
+
# Insert nodes into a BST (random keys, duplicates: true)
|
10
|
+
#
|
11
|
+
|
12
|
+
EOF
|
13
|
+
|
14
|
+
randmax = 99
|
8
15
|
|
9
16
|
p vals = Names::WW1.shuffle
|
10
|
-
p keys = Array.new(vals.size) { rand
|
17
|
+
p keys = Array.new(vals.size) { rand randmax }
|
18
|
+
|
19
|
+
root = KeyNode.new(vals.shift, key: keys.shift, children: 2, duplicates: true)
|
20
|
+
root.insert(keys.shift, vals.shift) until keys.empty?
|
21
|
+
|
22
|
+
puts root.display
|
23
|
+
puts
|
24
|
+
|
25
|
+
puts <<EOF
|
26
|
+
|
27
|
+
#
|
28
|
+
# Insert 30 nodes into a BST (unique keys, duplicates: false)
|
29
|
+
#
|
30
|
+
|
31
|
+
EOF
|
32
|
+
|
33
|
+
keys = (1..30).to_a.shuffle
|
34
|
+
vals = keys.map { rand 99 }
|
35
|
+
|
36
|
+
root = KeyNode.new(vals.shift, key: keys.shift, children: 2)
|
37
|
+
root.insert(keys.shift, vals.shift) while !keys.empty?
|
38
|
+
puts root.display
|
39
|
+
|
40
|
+
puts <<EOF
|
41
|
+
|
42
|
+
#
|
43
|
+
# Search for 30 different keys
|
44
|
+
#
|
45
|
+
|
46
|
+
EOF
|
11
47
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
puts tree
|
48
|
+
(1..30).each { |key|
|
49
|
+
node = root.search(key)
|
50
|
+
puts "found #{node}"
|
51
|
+
}
|
data/examples/complete_tree.rb
CHANGED
@@ -1,47 +1,46 @@
|
|
1
1
|
require 'compsci/complete_tree'
|
2
|
-
require 'compsci/timer'
|
3
2
|
|
4
3
|
include CompSci
|
5
4
|
|
6
|
-
|
5
|
+
vals = Array.new(30) { rand 99 }
|
6
|
+
|
7
|
+
[CompleteBinaryTree,
|
8
|
+
CompleteTernaryTree,
|
9
|
+
CompleteQuaternaryTree].each { |tree_class|
|
10
|
+
|
11
|
+
puts <<EOF
|
12
|
+
|
7
13
|
#
|
8
|
-
# Print
|
14
|
+
# Print #{tree_class} filled with static vals
|
9
15
|
#
|
10
16
|
|
11
17
|
EOF
|
12
18
|
|
13
|
-
vals = Array.new(30) { rand 99 }
|
14
|
-
|
15
|
-
[CompleteBinaryTree,
|
16
|
-
CompleteTernaryTree,
|
17
|
-
CompleteQuaternaryTree,
|
18
|
-
].each { |tree_class|
|
19
|
-
# start with the same vals for each class
|
20
19
|
my_vals = vals.dup
|
21
|
-
|
20
|
+
puts "initial vals: #{my_vals.inspect}"
|
22
21
|
tree = tree_class.new
|
23
22
|
tree.push my_vals.shift until my_vals.empty?
|
23
|
+
|
24
24
|
p tree
|
25
|
-
puts tree.display(width: 80)
|
26
|
-
puts
|
27
25
|
puts
|
26
|
+
puts tree.display(width: 80)
|
28
27
|
puts
|
29
28
|
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
puts <<EOF
|
31
|
+
|
32
|
+
#
|
33
|
+
# Push random vals and print again
|
34
|
+
#
|
35
|
+
|
36
|
+
EOF
|
37
37
|
|
38
|
-
# push different vals for each class
|
39
38
|
my_vals = Array.new(30) { rand 99 }
|
40
|
-
puts "
|
39
|
+
puts "new vals: #{my_vals.inspect}"
|
41
40
|
|
42
41
|
tree.push my_vals.shift until my_vals.empty?
|
43
|
-
puts tree.display(width: 80)
|
44
42
|
puts
|
43
|
+
puts tree.display(width: 80)
|
45
44
|
puts
|
46
45
|
puts
|
47
46
|
}
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'compsci/flex_node'
|
2
|
+
require 'compsci/timer'
|
3
|
+
|
4
|
+
include CompSci
|
5
|
+
|
6
|
+
puts <<EOF
|
7
|
+
|
8
|
+
#
|
9
|
+
# Try out Binary, Ternary, and Quaternary FlexNodes
|
10
|
+
# Push the same vals to each
|
11
|
+
#
|
12
|
+
|
13
|
+
EOF
|
14
|
+
|
15
|
+
vals = Array.new(30) { rand 99 }
|
16
|
+
|
17
|
+
[2, 3, 4].each { |child_slots|
|
18
|
+
my_vals = vals.dup
|
19
|
+
p my_vals
|
20
|
+
|
21
|
+
root = ChildFlexNode.new my_vals.shift
|
22
|
+
root.push(my_vals.shift, child_slots) until my_vals.empty?
|
23
|
+
p root
|
24
|
+
puts root.display(width: 80)
|
25
|
+
puts
|
26
|
+
visited = []
|
27
|
+
root.df_search { |n|
|
28
|
+
visited << n
|
29
|
+
false # or n.value > 90
|
30
|
+
}
|
31
|
+
puts "df_search visited: %s" % visited.join(' ')
|
32
|
+
puts
|
33
|
+
puts
|
34
|
+
|
35
|
+
# push different vals for each class
|
36
|
+
my_vals = Array.new(30) { rand 99 }
|
37
|
+
puts "push: #{my_vals.inspect}"
|
38
|
+
root.push(my_vals.shift, child_slots) until my_vals.empty?
|
39
|
+
puts
|
40
|
+
puts root.display(width: 80)
|
41
|
+
puts
|
42
|
+
puts
|
43
|
+
}
|
44
|
+
|
45
|
+
puts <<EOF
|
46
|
+
|
47
|
+
#
|
48
|
+
# 30 ChildFlexNode pushes and df_search
|
49
|
+
#
|
50
|
+
|
51
|
+
EOF
|
52
|
+
|
53
|
+
vals = Array.new(30) { rand 99 }
|
54
|
+
p vals
|
55
|
+
|
56
|
+
root = ChildFlexNode.new vals.shift
|
57
|
+
child_slots = 2
|
58
|
+
root.push(vals.shift, child_slots) until vals.empty?
|
59
|
+
p root
|
60
|
+
puts root.display
|
61
|
+
puts
|
62
|
+
|
63
|
+
root.df_search { |n|
|
64
|
+
puts "visited #{n}"
|
65
|
+
false # or n.value > 90
|
66
|
+
}
|
67
|
+
puts
|
68
|
+
|
69
|
+
vals = Array.new(30) { rand 99 }
|
70
|
+
puts "push: #{vals.inspect}"
|
71
|
+
|
72
|
+
root.push(vals.shift, child_slots) until vals.empty?
|
73
|
+
puts root.display
|
74
|
+
puts
|
75
|
+
|
76
|
+
|
77
|
+
runtime = (ARGV.shift || "3").to_i
|
78
|
+
puts <<EOF
|
79
|
+
|
80
|
+
#
|
81
|
+
# #{runtime} seconds worth of Binary ChildFlexNode pushes
|
82
|
+
#
|
83
|
+
|
84
|
+
EOF
|
85
|
+
|
86
|
+
count = 0
|
87
|
+
start = Timer.now
|
88
|
+
start_1k = Timer.now
|
89
|
+
root = ChildFlexNode.new(rand 99)
|
90
|
+
child_slots = 2
|
91
|
+
|
92
|
+
loop {
|
93
|
+
count += 1
|
94
|
+
|
95
|
+
if count % 100 == 0
|
96
|
+
_ans, push_elapsed = Timer.elapsed {
|
97
|
+
root.push(rand(99), child_slots)
|
98
|
+
}
|
99
|
+
puts "%ith push: %0.8f s" % [count, push_elapsed]
|
100
|
+
|
101
|
+
if count % 1000 == 0
|
102
|
+
push_1k_elapsed = Timer.since start_1k
|
103
|
+
puts "-----------"
|
104
|
+
puts " 1k push: %0.4f s (%i push / s)" %
|
105
|
+
[push_1k_elapsed, 1000.to_f / push_1k_elapsed]
|
106
|
+
puts
|
107
|
+
start_1k = Timer.now
|
108
|
+
end
|
109
|
+
else
|
110
|
+
root.push(rand(99), child_slots)
|
111
|
+
end
|
112
|
+
|
113
|
+
break if Timer.since(start) > runtime
|
114
|
+
}
|
115
|
+
|
116
|
+
puts "pushed %i items in %0.1f s" % [count, Timer.since(start)]
|
117
|
+
puts
|
data/examples/heap.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'compsci/heap'
|
2
|
-
require 'compsci/timer'
|
3
2
|
|
4
3
|
include CompSci
|
5
4
|
|
6
5
|
puts <<EOF
|
6
|
+
|
7
7
|
#
|
8
|
-
# display the results of
|
8
|
+
# display the results of ternary Heap push and pop
|
9
9
|
#
|
10
10
|
|
11
11
|
EOF
|
@@ -38,3 +38,41 @@ puts "array: #{h.array.inspect}"
|
|
38
38
|
puts "heap: #{h.heap?}"
|
39
39
|
puts h
|
40
40
|
puts
|
41
|
+
|
42
|
+
|
43
|
+
puts <<EOF
|
44
|
+
|
45
|
+
#
|
46
|
+
# display the results of binary Heap push and pop
|
47
|
+
#
|
48
|
+
|
49
|
+
EOF
|
50
|
+
|
51
|
+
h = Heap.new(child_slots: 2)
|
52
|
+
|
53
|
+
puts "push: %s" % Array.new(30) { rand(99).tap { |i| h.push i } }.join(' ')
|
54
|
+
puts "array: #{h.array.inspect}"
|
55
|
+
puts "heap: #{h.heap?}"
|
56
|
+
puts h
|
57
|
+
puts
|
58
|
+
puts
|
59
|
+
|
60
|
+
puts "pop: %i" % h.pop
|
61
|
+
puts "array: #{h.array.inspect}"
|
62
|
+
puts "heap: #{h.heap?}"
|
63
|
+
puts h
|
64
|
+
puts
|
65
|
+
puts
|
66
|
+
|
67
|
+
puts "pop: %s" % Array.new(9) { h.pop }.join(' ')
|
68
|
+
puts "array: #{h.array.inspect}"
|
69
|
+
puts "heap: #{h.heap?}"
|
70
|
+
puts h
|
71
|
+
puts
|
72
|
+
puts
|
73
|
+
|
74
|
+
puts "push: %s" % Array.new(30) { rand(99).tap { |i| h.push i } }.join(' ')
|
75
|
+
puts "array: #{h.array.inspect}"
|
76
|
+
puts "heap: #{h.heap?}"
|
77
|
+
puts h
|
78
|
+
puts
|
data/examples/heap_push.rb
CHANGED
@@ -6,12 +6,18 @@ include CompSci
|
|
6
6
|
runtime = (ARGV.shift || "3").to_i
|
7
7
|
|
8
8
|
puts <<EOF
|
9
|
+
|
9
10
|
#
|
10
|
-
#
|
11
|
+
# #{runtime} seconds worth of Heap pushes
|
11
12
|
#
|
12
13
|
|
13
14
|
EOF
|
14
15
|
|
16
|
+
|
17
|
+
# pregenerate a sequence of random numbers
|
18
|
+
# every NUMBERWANGth request, shift the sequence and push a new random
|
19
|
+
# this should mitigate random number generation from interfering with timing
|
20
|
+
# while also mitigating any chance of cyclic behavior
|
15
21
|
RANDMAX = 1_000
|
16
22
|
NUMBERWANG = 1_000
|
17
23
|
NUMS = (0..(RANDMAX - 1)).to_a.shuffle
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'compsci/node'
|
2
|
+
require 'compsci/names'
|
3
|
+
|
4
|
+
include CompSci
|
5
|
+
|
6
|
+
randmax = (ARGV.shift || 50).to_i
|
7
|
+
|
8
|
+
puts <<EOF
|
9
|
+
|
10
|
+
#
|
11
|
+
# Insert #{randmax} nodes into a ternary search tree (random keys)
|
12
|
+
#
|
13
|
+
|
14
|
+
EOF
|
15
|
+
|
16
|
+
root = KeyNode.new(rand(randmax), key: rand(randmax), children: 3)
|
17
|
+
randmax.times { puts root.insert(rand(randmax), rand(randmax)) }
|
18
|
+
puts root.display
|
19
|
+
|
20
|
+
puts <<EOF
|
21
|
+
|
22
|
+
#
|
23
|
+
# Search for #{randmax} keys in order
|
24
|
+
#
|
25
|
+
|
26
|
+
EOF
|
27
|
+
|
28
|
+
randmax.times { |key|
|
29
|
+
puts "search #{key}: #{root.search(key).map { |n| n.value }.join(' ')}"
|
30
|
+
}
|