kaninchen 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 60f8b15a393a1f3f445c31196352d7e4d7233099
4
+ data.tar.gz: cfd89d83ea909a2801e2a280807c2150a1d7cf41
5
+ SHA512:
6
+ metadata.gz: 36f7653de76ebe90837cfe8dede0d9a0cc0ad72ee1e1297614e2921445254ad9929960038bfd854d4e7650562bf7939882c6a3bb15f151bf0d10747d00d4be72
7
+ data.tar.gz: 732eb364ce1df34e7aabc7f6475505a556cfe11e8a35d9259ad1b932727164508fd8b37a687d56dcaecc45c6ff3d2328aef6e26331e30cf16177cb20dfe7f206
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+
14
+ # Ignore byebug history
15
+ .byebug_history
16
+
17
+ # Ignore cache file
18
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.15.3
6
+ script: rspec
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby '2.4.1'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in kaninchen.gemspec
8
+ # gemspec
9
+ gem 'byebug'
10
+ gem 'rake'
11
+ gem 'rspec'
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Maxwell-Alexius
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,212 @@
1
+ # Kaninchen
2
+
3
+ [![Build Status](https://travis-ci.org/travis-ci/travis-web.svg?branch=master)](https://travis-ci.org/travis-ci/travis-web)
4
+
5
+ Simple implementation of data structures (and algorithms in future) in Ruby programming language.
6
+
7
+ Currently support data structures:
8
+
9
+ - Stacks
10
+ - Trees
11
+
12
+ Currently working on data structures:
13
+
14
+ - Queues
15
+ - Sets
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ ```ruby
22
+ gem 'kaninchen'
23
+ ```
24
+
25
+ And then execute:
26
+
27
+ $ bundle
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install kaninchen
32
+
33
+ ## Stack
34
+
35
+ ### Basic Usage
36
+
37
+ ```ruby
38
+ # Creata a new stack data structure
39
+ stack = Kaninchen::DataStructure::Stack.new
40
+
41
+ # Use the push method to push in data
42
+ stack.push(1)
43
+
44
+ # Chained method is also allowed
45
+ stack.push(2).push(3).push(4)
46
+
47
+ # Or you can use the #<< method which is alias to push
48
+ stack << 5 << 6 << 7
49
+
50
+ # Check the size of the stack
51
+ stack.size # -> 7
52
+
53
+ # Pop out stack
54
+ stack.pop # -> 7
55
+ stack.pop # -> 6
56
+ stack.pop # -> 5
57
+
58
+ # Empty stack will pop out nil value
59
+ empty_stack = Kaninchen::DataStructure::Stack.new
60
+ empty_stack.pop # -> nil
61
+
62
+ # Using bang method pop! in empty stack will raise error
63
+ empty_stack.pop!
64
+ # -> Kaninchen::PopEmptyStackError: Popping out empty stack
65
+ ```
66
+
67
+ ## Tree
68
+
69
+ ![Kaninchen Tree](readme_img/kaninchen_tree.png)
70
+
71
+ ### Basic Usage
72
+
73
+ ```ruby
74
+ # Create a new tree data structure and initialize the root node value
75
+ tree = Kaninchen::DataStructure::Tree.new 'ROOT'
76
+ tree.class # -> Kaninchen::DataStructure::Tree
77
+
78
+ # Tree has a root node which holds the string value 'ROOT'
79
+ tree.root.class # -> Kaninchen::DataStructure::Node
80
+ tree.root.value # -> 'ROOT'
81
+
82
+ # Root node is the root of the tree and is also a kind of tree node
83
+ tree.root.root? # -> true
84
+ tree.root.tree_node? # -> true
85
+
86
+ # Root node is not a nil node
87
+ tree.root.nil? # -> false
88
+
89
+ # Create a node which holds the value 'CHILD'
90
+ node = Kaninchen::DataStructure::Node.new 'CHILD'
91
+
92
+ # Node currently is not a tree node, which is also a kind of "nil node"
93
+ node.tree_node? # -> false
94
+ node.nil? # -> true
95
+
96
+ # Attach the node to the tree root node using the #<< method
97
+ tree.root << node
98
+
99
+ # Now the tree has a child node and the node's parent is the root node
100
+ tree.root.children.size # -> 1
101
+ tree.root.children[0] === node # -> true
102
+ node.parent === tree.root # -> true
103
+
104
+ # Now node is not nil node anymore, it belongs to the tree node
105
+ node.nil? # -> false
106
+ node.tree_node? # -> true
107
+ node.tree === tree # -> true
108
+ node.root? # -> false
109
+ ```
110
+
111
+ ### Attaching Nodes
112
+
113
+ Chained `#<<` method:
114
+
115
+ ```ruby
116
+ # Assume tree is the Kaninchen::DataStructure::Tree type and n1, n2, n3
117
+ # are Kaninchen::DataStructure::Node type
118
+
119
+ tree.root << n1 << n2 << n3
120
+ tree.root.children.size # -> 3
121
+ tree.root.children[0] === n1 # -> true
122
+ tree.root.children[1] === n2 # -> true
123
+ tree.root.children[2] === n3 # -> true
124
+ n1.parent === tree.root # -> true
125
+ n2.parent === tree.root # -> true
126
+ n3.parent === tree.root # -> true
127
+ ```
128
+
129
+ Array of nodes case:
130
+
131
+ ```ruby
132
+ # Assume tree is the Kaninchen::DataStructure::Tree type and n1, n2, n3
133
+ # are Kaninchen::DataStructure::Node type
134
+ tree.root << [n1, n2, n3]
135
+ tree.root.children.size # -> 3
136
+ tree.root.children[0] === n1 # -> true
137
+ tree.root.children[1] === n2 # -> true
138
+ tree.root.children[2] === n3 # -> true
139
+ n1.parent === tree.root # -> true
140
+ n2.parent === tree.root # -> true
141
+ n3.parent === tree.root # -> true
142
+ ```
143
+
144
+ Hash of nodes case:
145
+ ```ruby
146
+ # Assume tree is the Kaninchen::DataStructure::Tree type and n1, n2, n3
147
+ # are Kaninchen::DataStructure::Node type
148
+ tree.node << { n1 => n2, n3 => nil }
149
+ tree.root.children.size # -> 2
150
+ tree.root.children[0] === n1 # -> true
151
+ tree.root.children[1] === n3 # -> true
152
+ tree.root.children[0].size # -> 1
153
+ tree.root.children[1].size # -> 0
154
+ tree.root.children[0].children.size # -> 1
155
+ tree.root.children[0].children[0] === n2 # -> true
156
+ n1.parent === tree.root # -> true
157
+ n2.parent === n1 # -> true
158
+ n3.parent === tree.root # -> true
159
+ ```
160
+
161
+ Mixed structure case (array and hash composition):
162
+ ```ruby
163
+ # Assume tree is the Kaninchen::DataStructure::Tree type and n1, n2, n3
164
+ # n4, n5 are Kaninchen::DataStructure::Node type
165
+ tree.node << [n1, { n2 => [n3, n4], { n5 => nil } }]
166
+
167
+ # Tree Structure:
168
+ # ROOT ---> n1
169
+ # |-> n2 ---> n3
170
+ # | |-> n4
171
+ # |-> n5
172
+ #
173
+ ```
174
+
175
+ ### Tree Node Order & Traversal
176
+
177
+ Available methods associated with tree node order and traversal is listed below:
178
+
179
+ - `Tree#nodes`: Default returns an array of `Node` type objects which represents the preorder of the tree nodes
180
+ - `Tree#node_values`: Default returns an array of `Node` type objects' values which represents the preorder of the tree nodes
181
+ - `Tree#each_node`: Default iterates the tree nodes in preorder format which requires a given block
182
+ - `Tree#each_node_with_index`: Default iterates the tree nodes with index specified in preorder format which requires a given block
183
+
184
+ These methods can pass in optional parameter, when pass in:
185
+
186
+ - `:preorder` or `:depth_first`: Preorder mode
187
+ - `:inorder`: Inorder mode
188
+ - `:postorder`: Postorder mode
189
+ - `:levelorder` or `:breadth_first`: Level order mode
190
+
191
+ ### Properties of Tree
192
+
193
+ - `Tree#height`: The height of the tree
194
+ - `Tree#leaves`: The leaves of the tree
195
+
196
+ ### Properties of Tree Nodes
197
+
198
+ - `Node#type`: Returns the symbol object `:tree`
199
+ - `Node#degree`: The degree of the tree node (which is the count of the subtrees of the node)
200
+ - `Node#depth`: The depth of the tree node (which is the distance between the node and the tree root of the node)
201
+ - `Node#height`: The height of the tree node (which is the longest path to the leaves of the subtree of the node)
202
+ - `Node#subtree`: Returns the new tree type object which is the subtree of the node
203
+ - `Node#path`: Returns the path from the node to the root node as an array
204
+ - `Node#parent`: Returns the parent node of the node
205
+ - `Node#children`: Returns the child nodes of the node
206
+ - `Node#left_child`: Returns the left child node of the node
207
+ - `Node#right_child`: Returns the right child node of the node. (If there are over two children, it will return the second child node in default)
208
+ - `Node#leaf?`: Returns `true` if the node is the leaf of the tree
209
+
210
+ ## License
211
+
212
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'kaninchen'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require 'pry'
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/kaninchen.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'kaninchen/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'kaninchen'
9
+ spec.version = Kaninchen::VERSION
10
+ spec.authors = %w[Maxwell-Alexius]
11
+ spec.email = %w[destinydragon85614@gmail.com]
12
+
13
+ spec.summary = %q(Kaninchen gem contains a collection of fundamental data structures and algorithms in practice)
14
+ spec.description = %q(A simple implementation of basic data structure in Ruby)
15
+ # spec.homepage = 'TODO: Put your gem\'s website or public repo URL here.'
16
+ spec.license = 'MIT'
17
+
18
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
20
+ if spec.respond_to?(:metadata)
21
+ # spec.metadata['allowed_push_host'] = 'TODO: Set to "http://mygemserver.com"'
22
+ else
23
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
24
+ 'public gem pushes.'
25
+ end
26
+
27
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
28
+ f.match(%r{^(test|spec|features)/})
29
+ end
30
+ spec.bindir = 'exe'
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = %w[lib]
33
+
34
+ spec.add_development_dependency 'bundler', '~> 1.15'
35
+ spec.add_development_dependency 'rake', '~> 10.0'
36
+ spec.add_development_dependency 'rspec', '~> 3.0'
37
+ end
data/lib/kaninchen.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'kaninchen/version'
2
+ require 'kaninchen/data_structure'
3
+ require 'kaninchen/algorithm'
4
+ require 'kaninchen/errors'
5
+
6
+ module Kaninchen
7
+ class << self
8
+ def version
9
+ self::VERSION
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaninchen
4
+ module Algorithm
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kaninchen/data_structure/stack'
4
+ require 'kaninchen/data_structure/queue'
5
+ require 'kaninchen/data_structure/node'
6
+ require 'kaninchen/data_structure/tree'
7
+ require 'kaninchen/data_structure/set'
8
+
9
+ module Kaninchen
10
+ module DataStructure
11
+ def self.enable_extension!
12
+ require 'kaninchen/data_structure/extension'
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaninchen
4
+ module DataStructure
5
+ module Extension
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaninchen
4
+ module DataStructure
5
+ class Node
6
+ attr_reader :type, :value
7
+ def initialize(params = {})
8
+ if params.is_a? Hash
9
+ @type = params[:type]
10
+ @value = params[:value]
11
+ else
12
+ @value = params
13
+ @type = nil
14
+ end
15
+ end
16
+
17
+ def nil?
18
+ @type.nil?
19
+ end
20
+
21
+ def to_s
22
+ case @type
23
+ when nil
24
+ "<NilNode value=\"#{value}\">"
25
+ when :tree
26
+ "<TreeNode value=\"#{value}\" depth=\"#{depth}\" level=\"#{level}\" degree=\"#{degree}\">"
27
+ end
28
+ end
29
+ alias :inspect :to_s
30
+
31
+ class << self
32
+ def node_type(type)
33
+ define_method "#{type}_node?" do
34
+ @type === type
35
+ end
36
+
37
+ define_singleton_method "#{type}_node_attr_reader" do |*attrs|
38
+ attrs.each do |attr|
39
+ define_method attr do
40
+ send("#{type}_node?") ? instance_variable_get("@#{attr}") : nil
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaninchen
4
+ module DataStructure
5
+ class Queue
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaninchen
4
+ module DataStructure
5
+ class Set
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaninchen
4
+ module DataStructure
5
+ class Stack
6
+ def initialize(*items)
7
+ @stack ||= items
8
+ end
9
+
10
+ def push(item)
11
+ @stack.push item
12
+ self
13
+ end
14
+ alias :<< :push
15
+
16
+ def pop
17
+ @stack.pop
18
+ end
19
+
20
+ def pop!
21
+ popped = self.pop
22
+ raise Kaninchen::PopEmptyStackError, 'Popping out empty stack' if popped.nil?
23
+ popped
24
+ end
25
+
26
+ def empty?
27
+ @stack.size.zero?
28
+ end
29
+
30
+ def size
31
+ @stack.size
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kaninchen/data_structure/tree/properties'
4
+ require 'kaninchen/data_structure/tree/nodes'
5
+ require 'kaninchen/data_structure/tree/each_node'
6
+
7
+ module Kaninchen
8
+ module DataStructure
9
+ class Tree
10
+ attr_reader :root
11
+ def initialize(value)
12
+ if value.is_a? Kaninchen::DataStructure::Node
13
+ @root = value
14
+ else
15
+ @root = Kaninchen::DataStructure::Node.new value
16
+ end
17
+ @root.send(:set_tree_node_data, tree: self)
18
+ end
19
+
20
+ def to_s
21
+ "<Tree root=\"#{root}\" height=\"#{height}\">"
22
+ end
23
+ alias :inspect :to_s
24
+ end
25
+
26
+ class Node
27
+ node_type :tree
28
+ tree_node_attr_reader :tree, :parent, :children
29
+
30
+ def <<(params)
31
+ case
32
+ when (params.is_a?(Kaninchen::DataStructure::Node) and params.nil?)
33
+ params.send(:set_tree_node_data, tree: self.tree, parent: self)
34
+ set_tree_node_data(children: @children.push(params))
35
+ when params.is_a?(Array) then params.each { |node| self << node }
36
+ when params.is_a?(Hash)
37
+ params.each_pair do |key, value|
38
+ self << key
39
+ key << value if key.is_a? Kaninchen::DataStructure::Node
40
+ end
41
+ end
42
+ self
43
+ end
44
+
45
+ def root?
46
+ @parent.nil?
47
+ end
48
+
49
+ private
50
+
51
+ def set_tree_node_data(params)
52
+ @type = :tree
53
+ @tree ||= params[:tree]
54
+ @parent ||= params[:parent]
55
+ @children ||= params[:children] || []
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaninchen
4
+ module DataStructure
5
+ class Tree
6
+ def each_node(type = :preorder)
7
+ case
8
+ when %i[preorder depth_first].include?(type)
9
+ yield self.root
10
+ recursive_preorder_loop(self.root) { |node| yield node }
11
+ when type === :inorder
12
+ recursive_inorder_loop(first_leaf, :left_most) { |node| yield node }
13
+ when type === :postorder
14
+ recursive_postorder_loop(self.root) { |node| yield node }
15
+ when %i[levelorder breadth_first].include?(type)
16
+ yield self.root
17
+ recursive_levelorder_loop(self.root) { |node| yield node }
18
+ end
19
+ end
20
+
21
+ def each_node_with_index(type = :preorder)
22
+ index = 0
23
+ self.each_node(type) do |node|
24
+ yield node, index
25
+ index += 1
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def recursive_preorder_loop(parent_node)
32
+ parent_node.children.each do |child_node|
33
+ yield child_node
34
+ recursive_preorder_loop(child_node) { |node| yield node }
35
+ end
36
+ end
37
+
38
+ def recursive_inorder_loop(node, current_role, end_node = nil)
39
+ yield node
40
+ case current_role
41
+ when :left_most
42
+ until node === end_node or node.root?
43
+ recursive_inorder_loop(node.parent, :right_recursive, end_node) { |n| yield n } unless node.parent === end_node
44
+ node = node.parent
45
+ end
46
+ when :right_recursive
47
+ node.send(:right_children).each do |child_node|
48
+ left_most_child = child_node.send(:left_most_child)
49
+ recursive_inorder_loop(left_most_child, :left_most, end_node = node) { |n| yield n }
50
+ end
51
+ end
52
+ end
53
+
54
+ def recursive_postorder_loop(node)
55
+ unless node.leaf?
56
+ recursive_postorder_loop(node.left_child) { |n| yield n }
57
+ node.send(:right_children).each do |child_node|
58
+ recursive_postorder_loop(child_node) { |n| yield n }
59
+ end
60
+ end
61
+ yield node
62
+ end
63
+
64
+ def recursive_levelorder_loop(node)
65
+ children = node.children
66
+ children.each { |child_node| yield child_node }
67
+ children.each { |child_node| recursive_levelorder_loop(child_node) { |n| yield n } }
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaninchen
4
+ module DataStructure
5
+ class Tree
6
+ def nodes(type = nil)
7
+ if type.nil?
8
+ { self.root => recursive_get_struct(self.root) }
9
+ else
10
+ result = []
11
+ each_node(type) { |node| result.push(node) }
12
+ result
13
+ end
14
+ end
15
+
16
+ def node_values(type = nil)
17
+ if type.nil?
18
+ { self.root.value => recursive_get_struct_value(self.root) }
19
+ else
20
+ nodes(type).map(&:value)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def recursive_get_struct(node)
27
+ result = {}
28
+ node.children.each do |child_node|
29
+ result[child_node] = recursive_get_struct(child_node)
30
+ end
31
+ result.empty? ? nil : result
32
+ end
33
+
34
+ def recursive_get_struct_value(node)
35
+ result = {}
36
+ node.children.each do |child_node|
37
+ result[child_node.value] = recursive_get_struct_value(child_node)
38
+ end
39
+ result.empty? ? nil : result
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaninchen
4
+ module DataStructure
5
+ class Tree
6
+ def leaves
7
+ self.nodes(:preorder).select { |node| node.children.empty? }
8
+ end
9
+
10
+ def height
11
+ self.nodes(:preorder).map do |node|
12
+ count = 1
13
+ until node.parent.nil?
14
+ count += 1
15
+ node = node.parent
16
+ end
17
+ count
18
+ end.max
19
+ end
20
+
21
+ private
22
+
23
+ def first_leaf
24
+ self.each_node(:preorder) { |node| return node if node.children.empty? }
25
+ end
26
+ end
27
+
28
+ class Node
29
+ def degree
30
+ self.children.size
31
+ end
32
+
33
+ def path
34
+ node = self
35
+ arr = [node]
36
+ until node.root?
37
+ node = node.parent
38
+ arr << node
39
+ end
40
+ arr
41
+ end
42
+
43
+ def left_child
44
+ self.degree.zero? ? nil : self.children[0]
45
+ end
46
+
47
+ def right_child
48
+ self.degree < 2 ? nil : self.children[1]
49
+ end
50
+
51
+ def depth
52
+ count = 0
53
+ current_node = self
54
+ until current_node.root?
55
+ count += 1
56
+ current_node = current_node.parent
57
+ end
58
+ count
59
+ end
60
+
61
+ def level
62
+ depth + 1
63
+ end
64
+
65
+ def subtree
66
+ tree = Kaninchen::DataStructure::Tree.new(self.value)
67
+ recursive_attach_subtree_nodes(tree.root, self)
68
+ tree
69
+ end
70
+
71
+ def height
72
+ self.subtree.height
73
+ end
74
+
75
+ def leaf?
76
+ self.children.empty?
77
+ end
78
+
79
+ private
80
+
81
+ def recursive_attach_subtree_nodes(new_node, origin_node)
82
+ origin_node.children.each do |origin_child_node|
83
+ new_child_node = self.class.new(origin_child_node.value)
84
+ new_node << new_child_node
85
+ recursive_attach_subtree_nodes(new_child_node, origin_child_node)
86
+ end
87
+ end
88
+
89
+ # Right children is for the n-ary but not for the binary-tree system
90
+ # which will be served as private method due to the needs of the
91
+ # implementation of traversal
92
+ def right_children
93
+ self.degree < 2 ? [] : self.children[1..-1]
94
+ end
95
+
96
+ def left_most_child(node = self)
97
+ node = node.left_child until node.left_child.nil?
98
+ node
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kaninchen
4
+ class PopEmptyStackError < StandardError
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module Kaninchen
2
+ VERSION = '0.1.0'
3
+ end
Binary file
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kaninchen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Maxwell-Alexius
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-08-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.15'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.15'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: A simple implementation of basic data structure in Ruby
56
+ email:
57
+ - destinydragon85614@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - bin/console
70
+ - bin/setup
71
+ - kaninchen.gemspec
72
+ - lib/kaninchen.rb
73
+ - lib/kaninchen/algorithm.rb
74
+ - lib/kaninchen/data_structure.rb
75
+ - lib/kaninchen/data_structure/extension.rb
76
+ - lib/kaninchen/data_structure/node.rb
77
+ - lib/kaninchen/data_structure/queue.rb
78
+ - lib/kaninchen/data_structure/set.rb
79
+ - lib/kaninchen/data_structure/stack.rb
80
+ - lib/kaninchen/data_structure/tree.rb
81
+ - lib/kaninchen/data_structure/tree/each_node.rb
82
+ - lib/kaninchen/data_structure/tree/nodes.rb
83
+ - lib/kaninchen/data_structure/tree/properties.rb
84
+ - lib/kaninchen/errors.rb
85
+ - lib/kaninchen/version.rb
86
+ - readme_img/kaninchen_tree.png
87
+ homepage:
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.6.12
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Kaninchen gem contains a collection of fundamental data structures and algorithms
111
+ in practice
112
+ test_files: []