compsci 0.3.0.1 → 0.3.1.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.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: compsci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.1
4
+ version: 0.3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rick Hull
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-15 00:00:00.000000000 Z
11
+ date: 2020-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: buildar
@@ -28,30 +28,30 @@ dependencies:
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '5.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '5.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 12.3.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 12.3.3
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: flog
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -134,39 +134,40 @@ files:
134
134
  - compsci.gemspec
135
135
  - examples/binary_search_tree.rb
136
136
  - examples/complete_tree.rb
137
+ - examples/flex_node.rb
137
138
  - examples/heap.rb
138
139
  - examples/heap_push.rb
140
+ - examples/ternary_search_tree.rb
139
141
  - examples/tree.rb
140
- - examples/tree_push.rb
141
142
  - lib/compsci.rb
142
- - lib/compsci/binary_search_tree.rb
143
143
  - lib/compsci/complete_tree.rb
144
144
  - lib/compsci/fibonacci.rb
145
145
  - lib/compsci/fit.rb
146
+ - lib/compsci/flex_node.rb
146
147
  - lib/compsci/heap.rb
147
148
  - lib/compsci/names.rb
148
149
  - lib/compsci/names/greek.rb
150
+ - lib/compsci/names/pokemon.rb
149
151
  - lib/compsci/node.rb
150
152
  - lib/compsci/simplex.rb
151
153
  - lib/compsci/simplex/parse.rb
152
154
  - lib/compsci/timer.rb
153
- - lib/compsci/tree.rb
154
155
  - test/bench/complete_tree.rb
155
156
  - test/bench/fibonacci.rb
157
+ - test/bench/flex_node.rb
156
158
  - test/bench/heap.rb
157
159
  - test/bench/simplex.rb
158
- - test/bench/tree.rb
159
- - test/binary_search_tree.rb
160
160
  - test/complete_tree.rb
161
+ - test/compsci.rb
161
162
  - test/fibonacci.rb
162
163
  - test/fit.rb
164
+ - test/flex_node.rb
163
165
  - test/heap.rb
164
166
  - test/names.rb
165
167
  - test/node.rb
166
168
  - test/simplex.rb
167
169
  - test/simplex_parse.rb
168
170
  - test/timer.rb
169
- - test/tree.rb
170
171
  homepage: https://github.com/rickhull/compsci
171
172
  licenses:
172
173
  - LGPL-3.0
@@ -186,8 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
187
  - !ruby/object:Gem::Version
187
188
  version: '0'
188
189
  requirements: []
189
- rubyforge_project:
190
- rubygems_version: 2.6.8
190
+ rubygems_version: 3.0.6
191
191
  signing_key:
192
192
  specification_version: 4
193
193
  summary: Toy implementations for some basic computer science problems
@@ -1,72 +0,0 @@
1
- require 'compsci/node'
2
- require 'compsci/tree'
3
- require 'compsci/timer'
4
-
5
- include CompSci
6
-
7
- puts <<EOF
8
- #
9
- # 3 seconds worth of pushes
10
- #
11
-
12
- EOF
13
-
14
- count = 0
15
- start = Timer.now
16
- start_1k = Timer.now
17
- tree = BinaryTree.new ChildFlexNode, rand(99)
18
-
19
- loop {
20
- count += 1
21
-
22
- if count % 100 == 0
23
- _ans, push_elapsed = Timer.elapsed { tree.push rand 99 }
24
- puts "%ith push: %0.8f s" % [count, push_elapsed]
25
-
26
- if count % 1000 == 0
27
- push_1k_elapsed = Timer.since start_1k
28
- puts "-----------"
29
- puts " 1k push: %0.4f s (%i push / s)" %
30
- [push_1k_elapsed, 1000.to_f / push_1k_elapsed]
31
- puts
32
- start_1k = Timer.now
33
- end
34
- else
35
- tree.push rand 99
36
- end
37
-
38
- break if Timer.since(start) > 3
39
- }
40
-
41
- puts "pushed %i items in %0.1f s" % [count, Timer.since(start)]
42
- puts
43
-
44
- puts <<EOF
45
- #
46
- # 30 inserts, puts, df_search
47
- #
48
-
49
- EOF
50
-
51
- vals = Array.new(30) { rand 99 }
52
- p vals
53
-
54
- tree = BinaryTree.new ChildFlexNode, vals.shift
55
- tree.push vals.shift until vals.empty?
56
- puts tree
57
-
58
- p tree
59
- puts
60
-
61
- tree.df_search { |n|
62
- puts "visited #{n}"
63
- false # or n.value > 90
64
- }
65
- puts
66
-
67
- vals = Array.new(30) { rand 99 }
68
- puts "push: #{vals.inspect}"
69
-
70
- tree.push vals.shift until vals.empty?
71
- puts tree
72
- puts
@@ -1,86 +0,0 @@
1
- require 'compsci/node'
2
- require 'compsci/tree'
3
-
4
- module CompSci
5
- class BinarySearchTree < BinaryTree
6
- def self.display_level(nodes: [], width: 80)
7
- unless self.power_of?(nodes.size, 2)
8
- raise "unexpected node count: #{nodes.size}"
9
- end
10
- block_width = [width / nodes.size, 1].max
11
- nodes.map { |node|
12
- str = node ? node.to_s : '_'
13
- space = [(block_width + str.size) / 2, str.size + 1].max
14
- str.ljust(space, ' ').rjust(block_width, ' ')
15
- }.join
16
- end
17
-
18
- # helper method; any object which responds to key, value, and children
19
- # may be used
20
- def self.new_node(key, val)
21
- CompSci::KeyNode.new(val, key: key, children: 2)
22
- end
23
-
24
- def self.new_with_kv(key, val)
25
- self.new(self.new_node(key, val))
26
- end
27
-
28
- def initialize(root_node)
29
- @node_class = root_node.class
30
- @child_slots = 2
31
- if root_node.children.size == @child_slots
32
- @root = root_node
33
- else
34
- raise "bad root: #{root_node}; expected #{@child_slots} child slots"
35
- end
36
- end
37
-
38
- def search_recursive(key, node: @root)
39
- return node if node.nil? or node.key == key
40
- child = key < node.key ? node.children[0] : node.children[1]
41
- search_recursive(key, node: child)
42
- end
43
-
44
- def search_iterative(key, node: @root)
45
- while !node.nil?
46
- return node if node.key == key
47
- node = key < node.key ? node.children[0] : node.children[1]
48
- end
49
- node
50
- end
51
-
52
- def insert_recursive(key, val, node: @root)
53
- return nil if node.nil? or node.key == key
54
- if key < node.key
55
- if node.children[0]
56
- insert_recursive(key, val, node: node.children[0])
57
- else
58
- node.children[0] = @node_class.new(val, key: key, children: 2)
59
- end
60
- else
61
- if node.children[1]
62
- insert_recursive(key, val, node: node.children[1])
63
- else
64
- node.children[1] = @node_class.new(val, key: key, children: 2)
65
- end
66
- end
67
- end
68
- alias_method :insert, :insert_recursive
69
- alias_method :[]=, :insert
70
-
71
- def display(node: @root, width: 80)
72
- levels = [self.class.display_level(nodes: [node], width: width)]
73
- nodes = node.children
74
- while nodes.any? { |n| !n.nil? }
75
- levels << self.class.display_level(nodes: nodes, width: width)
76
- children = []
77
- nodes.each { |n|
78
- children += n ? n.children : Array.new(@child_slots)
79
- }
80
- nodes = children
81
- end
82
- levels.join("\n")
83
- end
84
- alias_method :to_s, :display
85
- end
86
- end
@@ -1,142 +0,0 @@
1
- # require 'compsci/node'
2
-
3
- module CompSci
4
- # for now at least, this assumes children simply stack up
5
- # children like: [nil, child1, child2] are not supported
6
- class Tree
7
- attr_reader :root
8
-
9
- def initialize(node_class, val)
10
- @root = node_class.new val
11
- end
12
-
13
- # does not support children gaps
14
- def df_search(node: nil, &blk)
15
- node ||= @root
16
- return node if yield node
17
- node.children.each { |c|
18
- stop_node = self.df_search(node: c, &blk)
19
- return stop_node if stop_node
20
- }
21
- nil
22
- end
23
-
24
- # does not support children gaps
25
- def bf_search(node: nil, &blk)
26
- node ||= @root
27
- destinations = [node]
28
- while !destinations.empty?
29
- node = destinations.shift
30
- return node if yield node
31
- destinations += node.children
32
- end
33
- nil
34
- end
35
-
36
- def df_search_generic(node: nil, &blk)
37
- # Perform pre-order operation
38
- # children.each { Perform in-order operation }
39
- # Perform post-order operation
40
- puts "not defined yet"
41
- end
42
- end
43
-
44
- class NaryTree < Tree
45
- # thanks apeiros
46
- # https://gist.github.com/rickhull/d0b579aa08c85430b0dc82a791ff12d6
47
- def self.power_of?(num, base)
48
- return false if base <= 1
49
- mod = 0
50
- num, mod = num.divmod(base) until num == 1 || mod > 0
51
- mod == 0
52
- end
53
-
54
- attr_reader :child_slots
55
-
56
- def initialize(node_class, val, child_slots:)
57
- super(node_class, val)
58
- @child_slots = child_slots
59
- end
60
-
61
- def open_parent?(node)
62
- node.children.size < @child_slots
63
- end
64
-
65
- def open_sibling
66
- # try siblings first, only possible with Node#parent
67
- if @open_parent.respond_to?(:siblings)
68
- @open_parent.siblings.find { |s| self.open_parent?(s) }
69
- end
70
- end
71
-
72
- def open_parent
73
- @open_parent ||= @root
74
- return @open_parent if self.open_parent?(@open_parent)
75
- open_sibling = self.open_sibling
76
- return @open_parent = open_sibling if open_sibling
77
- @open_parent = self.bf_search { |n| self.open_parent?(n) }
78
- end
79
-
80
- def push(value)
81
- self.open_parent.new_child value
82
- end
83
-
84
- def display(width: nil)
85
- str = ''
86
- old_level = 0
87
- width ||= @child_slots * 40
88
- self.bf_search { |node|
89
- raise "#{node.class} not yet supported" unless node.respond_to? :gen
90
- level = node.gen
91
- if old_level != level
92
- str += "\n"
93
- old_level = level
94
- end
95
- # center in block_width
96
- slots = @child_slots**level
97
- block_width = width / slots
98
- val = node.to_s
99
- space = [(block_width + val.size) / 2, val.size + 1].max
100
- str += val.ljust(space, ' ').rjust(block_width, ' ')
101
- false
102
- }
103
- str
104
- end
105
- alias_method :to_s, :display
106
- end
107
-
108
- class BinaryTree < NaryTree
109
- def initialize(node_class, val)
110
- super(node_class, val, child_slots: 2)
111
- end
112
-
113
- def display(width: 80)
114
- count = 0
115
- str = ''
116
- self.bf_search { |node|
117
- count += 1
118
- level = Math.log(count, 2).floor
119
- block_width = width / (2**level)
120
- val = node.to_s
121
- str += "\n" if 2**level == count and count > 1
122
- space = [(block_width + val.size) / 2, val.size + 1].max
123
- str += val.ljust(space, ' ').rjust(block_width, ' ')
124
- false # keep searching to visit every node
125
- }
126
- str
127
- end
128
- alias_method :to_s, :display
129
- end
130
-
131
- class TernaryTree < NaryTree
132
- def initialize(node_class, val)
133
- super(node_class, val, child_slots: 3)
134
- end
135
- end
136
-
137
- class QuaternaryTree < NaryTree
138
- def initialize(node_class, val)
139
- super(node_class, val, child_slots: 4)
140
- end
141
- end
142
- end
@@ -1,31 +0,0 @@
1
- require 'compsci/node'
2
- require 'compsci/tree'
3
- require 'benchmark/ips'
4
-
5
- include CompSci
6
-
7
- Benchmark.ips do |b|
8
- b.config time: 3, warmup: 0.5
9
-
10
- b.report("99x BinaryTree(ChildNode)#push") do
11
- tree = BinaryTree.new(ChildFlexNode, 42)
12
- 99.times { tree.push rand 99 }
13
- end
14
-
15
- b.report("99x BinaryTree(FlexNode)#push") do
16
- tree = BinaryTree.new(FlexNode, 42)
17
- 99.times { tree.push rand 99 }
18
- end
19
-
20
- b.report("99x TernaryTree(ChildFlexNode)#push") do
21
- tree = TernaryTree.new(ChildFlexNode, 42)
22
- 99.times { tree.push rand 99 }
23
- end
24
-
25
- b.report("99x TernaryTree(FlexNode)#push") do
26
- tree = TernaryTree.new(FlexNode, 42)
27
- 99.times { tree.push rand 99 }
28
- end
29
-
30
- b.compare!
31
- end
@@ -1,98 +0,0 @@
1
- require 'compsci/node'
2
- require 'compsci/binary_search_tree'
3
- require 'compsci/names'
4
- require 'minitest/autorun'
5
-
6
- include CompSci
7
-
8
- describe BinarySearchTree do
9
- before do
10
- @keys = Array.new(4) { |i| Names::WW2[i] }
11
- @values = Array.new(4) { Names::SOLAR.sample }
12
- @nodes = Array.new(4) { |i|
13
- KeyNode.new(@values[i], key: @keys[i], children: 2)
14
- }
15
- @tree = BinarySearchTree.new(@nodes.first)
16
-
17
- # tree will look like:
18
- # A:val1
19
- # B:val2
20
- # C:val3
21
- # D:val4
22
- end
23
-
24
- it "must display_level" do
25
- str = BinarySearchTree.display_level nodes: @nodes, width: 80
26
- str.size.must_be :>=, 80 # it can overflow
27
-
28
- str = BinarySearchTree.display_level nodes: @nodes, width: 200
29
- str.size.must_equal 200 # it won't overflow
30
-
31
- @keys.each { |k| str.must_include k.to_s }
32
- @values.each { |v| str.must_include v.to_s }
33
- end
34
-
35
- it "must provide a new_node" do
36
- node = BinarySearchTree.new_node('the key', 'the value')
37
- node.must_be_kind_of Node
38
- node.must_be_kind_of KeyNode
39
- node.key.must_equal 'the key'
40
- node.value.must_equal 'the value'
41
- end
42
-
43
- it "must instantiate with key and value" do
44
- tree = BinarySearchTree.new_with_kv('the key', 'the value')
45
- node = tree.root
46
- node.must_be_kind_of Node
47
- node.must_be_kind_of KeyNode
48
- node.key.must_equal 'the key'
49
- node.value.must_equal 'the value'
50
- end
51
-
52
- it "must decide what to do with duplicate nodes" do
53
- end
54
-
55
- it "must decide what to do with duplicate keys" do
56
- end
57
-
58
- it "must insert nodes" do
59
- 1.upto(@nodes.size - 1) { |i| @tree[@keys[i]] = @values[i] }
60
- @tree.root.children.wont_be_empty
61
- @tree.root.children[0].nil?.must_equal true
62
- @tree.root.children[1].key.must_equal @keys[1]
63
- @tree.root.children[1].children[0].nil?.must_equal true
64
- @tree.root.children[1].children[1].value.must_equal @values[2]
65
- end
66
-
67
- it "must search nodes" do
68
- tree = nil
69
- new_order = (0..9).to_a.shuffle
70
- new_order.each { |i|
71
- k, v = Names::NATO[i], Names::SOLAR.sample
72
- if tree.nil?
73
- tree = BinarySearchTree.new_with_kv(k, v)
74
- else
75
- tree[k] = v
76
- end
77
- }
78
-
79
- 2.times {
80
- i = new_order.sample
81
- key = Names::NATO[new_order.sample]
82
- node = tree.search_iterative key
83
- node.wont_be_nil
84
- node.key.must_equal key
85
- }
86
-
87
- 2.times {
88
- i = new_order.sample
89
- key = Names::NATO[new_order.sample]
90
- node = tree.search_recursive key
91
- node.wont_be_nil
92
- node.key.must_equal key
93
- }
94
-
95
- tree.search_iterative(Names::SOLAR.sample).must_be_nil
96
- tree.search_recursive(Names::SOLAR.sample).must_be_nil
97
- end
98
- end