compsci 0.0.3.1 → 0.1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cc2eff6c2450cd9807ab097dd86eebb37420a7b7
4
- data.tar.gz: 470311b19fc70c7ab1a5d405c3aba939f57464e7
3
+ metadata.gz: 3df760b020e177135c9d73e20f455635ca82250c
4
+ data.tar.gz: '0850e990c79b14fa39533e0990d707cb3f1fe7cc'
5
5
  SHA512:
6
- metadata.gz: 37214ed2f4c2fd3f8837f1908fc78b07be79e624ba7f387f40c68aec49f93b1b866589fab0b863e02e6add2d6dcbfe4508c9ae1bdf1864269427dce25fdb15b4
7
- data.tar.gz: 52dc0115e1f44a769da4dc3f1e721624e3963cef0111d098af6ad6beb72728b120905aaaeb45161950c79455810bbf8caab5426fb22aee716f5e7e92f84244a4
6
+ metadata.gz: 8997da4e5f98d35b1250d8feab97d9e46d7a193aec42a89b74e720bfff50608624b054e7e3bb85709230d2a038557919c3a2ce0d6f9f4dc22ddf88e8357d6c8c
7
+ data.tar.gz: 90069e7be2f383c80e0edd09c41ca566ba8481b3659c4aca90c7b23000027c3eaa1139cf980ba74737ca9ba4d20e99bd0591623be7b5872d9d7cb06ac99ce2ad
data/README.md CHANGED
@@ -1,28 +1,70 @@
1
1
  [![Build Status](https://travis-ci.org/rickhull/compsci.svg?branch=master)](https://travis-ci.org/rickhull/compsci)
2
2
 
3
- # Introduction
3
+ # CompSci
4
4
 
5
5
  Provided are some toy implementations for some basic computer science problems.
6
6
 
7
- ## [`Tree`](/lib/compsci/tree.rb) data structures
8
-
9
- * `Node` - references children nodes only
10
- * `ChildNode` - references parent and children nodes
11
- * `Tree` - tracks the `root` node; provides `df_search` and `bf_search`
12
- * `NaryTree` - enforces number of children per node via `child_slots`
13
- * `BinaryTree` - `NaryTree` with `child_slots` == 2; provides `to_s`
14
- * `CompleteBinaryTree` - efficient Array implementation
7
+ ## [`Node`](lib/compsci/node.rb) data structure
8
+
9
+ * `Node`
10
+ - `@value`
11
+ - `@children`
12
+ * `ChildNode` adds
13
+ - `@parent`
14
+ - `#gen`
15
+ - `#siblings`
16
+
17
+ ## [`Tree`](lib/compsci/tree.rb) data structures
18
+
19
+ * `Tree`
20
+ - `@root`
21
+ - `#df_search`
22
+ - `#bf_search`
23
+ * `NaryTree`
24
+ - `@child_slots` (number of children per node)
25
+ - `#open_parent` O(n) to find a node with open child slots
26
+ - `#push` append `#open_parent.children`
27
+ - `#display` if initialized with `ChildNode`
28
+ * `BinaryTree`
29
+ - `NaryTree.new(child_slots: 2)`
30
+ - `#display` for `Node` and `ChildNode`
31
+ * `TernaryTree`
32
+ - `NaryTree.new(child_slots: 3)`
33
+ * `QuaternaryTree`
34
+ - `NaryTree.new(child_slots: 4)`
35
+
36
+ ## [`CompleteNaryTree`](lib/compsci/complete_tree.rb) data structure
37
+
38
+ Efficient Array implementation of a complete tree.
39
+
40
+ * `CompleteNaryTree`
41
+ - `CompleteNaryTree.parent_idx`
42
+ - `CompleteNaryTree.children_idx`
43
+ - `CompleteNaryTree.gen`
44
+ - `@array`
45
+ - `@child_slots`
46
+ - `#push`
47
+ - `#pop`
48
+ - `#size`
49
+ - `#last_idx`
50
+ - `#display` (alias `#to_s`)
51
+ * `CompleteBinaryTree`
52
+ - `CompleteNaryTree.new(child_slots: 2)`
53
+ * `CompleteTernaryTree`
54
+ - `CompleteNaryTree.new(child_slots: 3)`
55
+ * `CompleteQuaternaryTree`
56
+ - `CompleteNaryTree.new(child_slots: 4)`
15
57
 
16
58
  ## [`Heap`](lib/compsci/heap.rb) data structure
17
59
 
18
- Implemented with a `CompleteBinaryTree` for storage using simple arithmetic to
19
- determine array indices for parent and children. See the
60
+ `CompleteNaryTree` implementation. Both minheaps and maxheaps are supported.
61
+ Any number of children may be provided via `child_slots`. The primary
62
+ operations are `Heap#push` and `Heap#pop`. See the
20
63
  [heap example](examples/heap.rb) which can be executed (among other examples)
21
64
  via `rake examples`.
22
65
 
23
- Both minheaps and maxheaps are supported. The primary operations are
24
- `Heap#push` and `Heap#pop`. My basic Vagrant VM gets around 500k pushes per
25
- second, constant up past 1M pushes.
66
+ My basic Vagrant VM gets around 500k pushes per second, constant up past 1M
67
+ pushes.
26
68
 
27
69
  ## [`Fibonacci`](lib/compsci/fibonacci.rb) functions
28
70
 
@@ -93,3 +135,10 @@ cumulative: 0.828
93
135
  * `Fit.linear` - fits `y = a + bx`; returns a, b, r^2
94
136
  * `Fit.exponential` fits `y = ae^(bx)`; returns a, b, r^2
95
137
  * `Fit.power` fits `y = ax^b`; returns a, b, r^2
138
+
139
+ ## [`Names`](lib/compsci/names.rb) functions
140
+
141
+ * `Names.assign`
142
+ * `Names::Greek.upper`
143
+ * `Names::Greek.lower`
144
+ * `Names::Greek.symbol`
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3.1
1
+ 0.1.0.1
@@ -10,28 +10,11 @@ Gem::Specification.new do |s|
10
10
 
11
11
  s.version = File.read(File.join(__dir__, 'VERSION')).chomp
12
12
 
13
- s.files = %w[
14
- compsci.gemspec
15
- VERSION
16
- README.md
17
- Rakefile
18
- lib/compsci.rb
19
- lib/compsci/fibonacci.rb
20
- lib/compsci/fit.rb
21
- lib/compsci/heap.rb
22
- lib/compsci/timer.rb
23
- lib/compsci/tree.rb
24
- examples/binary_tree.rb
25
- examples/heap.rb
26
- test/fibonacci.rb
27
- test/fit.rb
28
- test/heap.rb
29
- test/timer.rb
30
- test/tree.rb
31
- test/bench/fibonacci.rb
32
- test/bench/heap.rb
33
- test/bench/tree.rb
34
- ]
13
+ s.files = %w[compsci.gemspec VERSION README.md Rakefile]
14
+ s.files += Dir['lib/**/*.rb']
15
+ s.files += Dir['test/**/*.rb']
16
+ s.files += Dir['examples/**/*.rb']
35
17
 
36
18
  s.add_development_dependency "minitest", "~> 5.0"
19
+ s.add_development_dependency "rake", "~> 0"
37
20
  end
@@ -13,7 +13,7 @@ EOF
13
13
  count = 0
14
14
  start = Timer.now
15
15
  start_1k = Timer.now
16
- tree = BinaryTree.new(ChildNode, rand(99))
16
+ tree = NaryTree.new(ChildNode, rand(99), child_slots: 2)
17
17
 
18
18
  loop {
19
19
  count += 1
@@ -47,20 +47,25 @@ puts <<EOF
47
47
 
48
48
  EOF
49
49
 
50
- vals = []
51
- 30.times { vals << rand(99) }
50
+ vals = Array.new(30) { rand 99 }
52
51
  p vals
53
52
 
54
- tree = BinaryTree.new(ChildNode, vals.shift)
53
+ tree = NaryTree.new(ChildNode, vals.shift, child_slots: 2)
55
54
  tree.push vals.shift until vals.empty?
56
-
57
55
  puts tree
58
56
 
57
+ p tree
58
+ puts
59
+
59
60
  tree.df_search { |n|
60
61
  puts "visited #{n}"
61
62
  false # or n.value > 90
62
63
  }
63
64
  puts
64
65
 
65
- p tree
66
+ vals = Array.new(30) { rand 99 }
67
+ puts "push: #{vals.inspect}"
68
+
69
+ tree.push vals.shift until vals.empty?
70
+ puts tree
66
71
  puts
@@ -0,0 +1,47 @@
1
+ require 'compsci/complete_tree'
2
+ require 'compsci/timer'
3
+
4
+ include CompSci
5
+
6
+ puts <<EOF
7
+ #
8
+ # Print CompleteBinary-, Ternary-, and QuaternaryTree
9
+ #
10
+
11
+ EOF
12
+
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
+ my_vals = vals.dup
21
+ p my_vals
22
+ tree = tree_class.new
23
+ tree.push my_vals.shift until my_vals.empty?
24
+ p tree
25
+ puts tree.display(width: 80)
26
+ puts
27
+ puts
28
+ puts
29
+
30
+
31
+ # TODO: add CompleteTree#df_search
32
+ # tree.df_search { |n|
33
+ # puts "visited #{n}"
34
+ # false # or n.value > 90
35
+ # }
36
+ # puts
37
+
38
+ # push different vals for each class
39
+ my_vals = Array.new(30) { rand 99 }
40
+ puts "push: #{my_vals.inspect}"
41
+
42
+ tree.push my_vals.shift until my_vals.empty?
43
+ puts tree.display(width: 80)
44
+ puts
45
+ puts
46
+ puts
47
+ }
@@ -13,7 +13,7 @@ EOF
13
13
  count = 0
14
14
  start = Timer.now
15
15
  start_100k = Timer.now
16
- h = BinaryHeap.new
16
+ h = Heap.new
17
17
 
18
18
  loop {
19
19
  count += 1
@@ -47,24 +47,36 @@ puts
47
47
 
48
48
  puts <<EOF
49
49
  #
50
- # 99 inserts; display the internal array
50
+ # display the results of TernaryHeap push and pop
51
51
  #
52
52
 
53
53
  EOF
54
54
 
55
- h = Heap.new
55
+ h = Heap.new(child_slots: 3)
56
56
 
57
- puts "push: %s" % Array.new(99) { rand(99).tap { |i| h.push i } }.join(' ')
58
- puts "heap store: #{h.store.inspect}"
57
+ puts "push: %s" % Array.new(30) { rand(99).tap { |i| h.push i } }.join(' ')
58
+ puts "array: #{h.array.inspect}"
59
59
  puts "heap: #{h.heap?}"
60
+ puts h
61
+ puts
60
62
  puts
61
63
 
62
64
  puts "pop: %i" % h.pop
63
- puts "heap store: #{h.store.inspect}"
65
+ puts "array: #{h.array.inspect}"
64
66
  puts "heap: #{h.heap?}"
67
+ puts h
68
+ puts
65
69
  puts
66
70
 
67
71
  puts "pop: %s" % Array.new(9) { h.pop }.join(' ')
68
- puts "heap store: #{h.store.inspect}"
72
+ puts "array: #{h.array.inspect}"
73
+ puts "heap: #{h.heap?}"
74
+ puts h
75
+ puts
76
+ puts
77
+
78
+ puts "push: %s" % Array.new(30) { rand(99).tap { |i| h.push i } }.join(' ')
79
+ puts "array: #{h.array.inspect}"
69
80
  puts "heap: #{h.heap?}"
81
+ puts h
70
82
  puts
@@ -0,0 +1,41 @@
1
+ require 'compsci/tree'
2
+ require 'compsci/timer'
3
+
4
+ include CompSci
5
+
6
+ puts <<EOF
7
+ #
8
+ # Try out Binary-, Ternary-, and QuaternaryTree
9
+ #
10
+
11
+ EOF
12
+
13
+ vals = Array.new(30) { rand 99 }
14
+
15
+ [BinaryTree, TernaryTree, QuaternaryTree].each { |tree_class|
16
+ # start with the same vals for each class
17
+ my_vals = vals.dup
18
+ p my_vals
19
+ tree = tree_class.new(ChildNode, my_vals.shift)
20
+ tree.push my_vals.shift until my_vals.empty?
21
+ p tree
22
+ puts tree.display(width: 80)
23
+ puts
24
+ visited = []
25
+ tree.df_search { |n|
26
+ visited << n
27
+ false # or n.value > 90
28
+ }
29
+ puts "df_search visited: %s" % visited.join(' ')
30
+ puts
31
+ puts
32
+
33
+ # push different vals for each class
34
+ my_vals = Array.new(30) { rand 99 }
35
+ puts "push: #{my_vals.inspect}"
36
+ tree.push my_vals.shift until my_vals.empty?
37
+ puts
38
+ puts tree.display(width: 80)
39
+ puts
40
+ puts
41
+ }
@@ -1,2 +1 @@
1
- module CompSci
2
- end
1
+ module CompSci; end
@@ -0,0 +1,109 @@
1
+ module CompSci
2
+ # A CompleteNaryTree can very efficiently use an array for storage using
3
+ # simple arithmetic to determine parent child relationships.
4
+ #
5
+ # It is kept separate from compsci/tree as it does not require compsci/node
6
+ #
7
+ class CompleteNaryTree
8
+ # integer math maps several children to one parent
9
+ def self.parent_idx(idx, n)
10
+ (idx-1) / n
11
+ end
12
+
13
+ def self.children_idx(idx, n)
14
+ Array.new(n) { |i| n*idx + i + 1 }
15
+ end
16
+
17
+ def self.gen(idx, n)
18
+ count = 0
19
+ loop {
20
+ pidx = self.parent_idx(idx, n)
21
+ break if pidx < 0
22
+ count += 1
23
+ idx = pidx
24
+ }
25
+ count
26
+ end
27
+
28
+ attr_reader :array
29
+
30
+ def initialize(array: [], child_slots: 2)
31
+ @array = array
32
+ @child_slots = child_slots
33
+ end
34
+
35
+ def push val
36
+ @array.push val
37
+ end
38
+
39
+ def pop
40
+ @array.pop
41
+ end
42
+
43
+ def size
44
+ @array.size
45
+ end
46
+
47
+ def last_idx
48
+ @array.size - 1 unless @array.empty?
49
+ end
50
+
51
+ # or, ya know, just iterate @array
52
+ def bf_search(&blk)
53
+ destinations = [0]
54
+ while !destinations.empty?
55
+ idx = destinations.shift
56
+ return idx if yield @array[idx]
57
+
58
+ # idx has a val and the block is false
59
+ # add existent children to destinations
60
+ self.class.children_idx(idx, @child_slots).each { |cidx|
61
+ destinations.push(cidx) if cidx < @array.size
62
+ }
63
+ end
64
+ end
65
+
66
+ def df_search(&blk)
67
+ puts "not yet"
68
+ end
69
+
70
+ def display(width: 80)
71
+ str = ''
72
+ old_level = 0
73
+ @array.each_with_index { |val, i|
74
+ val = val.to_s
75
+ level = self.class.gen(i, @child_slots)
76
+ if old_level != level
77
+ str += "\n"
78
+ old_level = level
79
+ end
80
+
81
+ # center in block_width
82
+ slots = @child_slots**level
83
+ block_width = width / slots
84
+ space = [(block_width + val.size) / 2, val.size + 1].max
85
+ str += val.ljust(space, ' ').rjust(block_width, ' ')
86
+ }
87
+ str
88
+ end
89
+ alias_method :to_s, :display
90
+ end
91
+
92
+ class CompleteBinaryTree < CompleteNaryTree
93
+ def initialize(array: [])
94
+ super(array: array, child_slots: 2)
95
+ end
96
+ end
97
+
98
+ class CompleteTernaryTree < CompleteNaryTree
99
+ def initialize(array: [])
100
+ super(array: array, child_slots: 3)
101
+ end
102
+ end
103
+
104
+ class CompleteQuaternaryTree < CompleteNaryTree
105
+ def initialize(array: [])
106
+ super(array: array, child_slots: 4)
107
+ end
108
+ end
109
+ end
@@ -1,39 +1,40 @@
1
- require 'compsci'
2
1
  autoload :Matrix, 'matrix'
3
2
 
4
- module CompSci::Fibonacci
5
- def self.classic(n)
6
- n < 2 ? n : classic(n-1) + classic(n-2)
7
- end
3
+ module CompSci
4
+ class Fibonacci
5
+ def self.classic(n)
6
+ n < 2 ? n : classic(n-1) + classic(n-2)
7
+ end
8
8
 
9
- def self.cache_recursive(n, cache = {})
10
- return n if n < 2
11
- cache[n] ||= cache_recursive(n-1, cache) + cache_recursive(n-2, cache)
12
- end
9
+ def self.cache_recursive(n, cache = {})
10
+ return n if n < 2
11
+ cache[n] ||= cache_recursive(n-1, cache) + cache_recursive(n-2, cache)
12
+ end
13
13
 
14
- def self.cache_iterative(n)
15
- cache = [0, 1]
16
- 2.upto(n) { |i| cache[i] = cache[i-1] + cache[i-2] }
17
- cache[n]
18
- end
14
+ def self.cache_iterative(n)
15
+ cache = [0, 1]
16
+ 2.upto(n) { |i| cache[i] = cache[i-1] + cache[i-2] }
17
+ cache[n]
18
+ end
19
19
 
20
- # traditional
21
- def self.dynamic(n)
22
- a, b = 0, 1
23
- n.times { a, b = b, a+b }
24
- a
25
- end
20
+ # traditional
21
+ def self.dynamic(n)
22
+ a, b = 0, 1
23
+ n.times { a, b = b, a+b }
24
+ a
25
+ end
26
26
 
27
- # fails for n == 0
28
- def self.dynamic_fast(n)
29
- a, b = 0, 1
30
- (n-1).times { a, b = b, a+b }
31
- b
32
- end
27
+ # fails for n == 0
28
+ def self.dynamic_fast(n)
29
+ a, b = 0, 1
30
+ (n-1).times { a, b = b, a+b }
31
+ b
32
+ end
33
33
 
34
- # https://gist.github.com/havenwood/02cf291b809327d96a3f
35
- # slower than dynamic until around n == 500
36
- def self.matrix(n)
37
- (Matrix[[0, 1], [1, 1]] ** n.pred)[1, 1].to_i
34
+ # https://gist.github.com/havenwood/02cf291b809327d96a3f
35
+ # slower than dynamic until around n == 500
36
+ def self.matrix(n)
37
+ (Matrix[[0, 1], [1, 1]] ** n.pred)[1, 1].to_i
38
+ end
38
39
  end
39
40
  end