compsci 0.3.0.1 → 0.3.1.1

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