prefix_tree 1.0.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 +7 -0
- data/lib/prefix_tree/csv_controller.rb +44 -0
- data/lib/prefix_tree/node.rb +80 -0
- data/lib/prefix_tree.rb +159 -0
- metadata +45 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4f64aa5bba6e670976b5fbeb9fe4045af84e48be0e3f9f5601d560d6ec4281fe
|
4
|
+
data.tar.gz: f87e303415e69c57a7fbe6c5d6ccef6be8eeb552602748f55ecc6c4d09af727d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0e9daf017cbdc0de5f457ab0d326a42648e1a3f07f25659249f6cb8c7a1d8cc3466dc260d69b4da46b266f16c8affe03da802edc122a6ef6f7250a8bae61b5ad
|
7
|
+
data.tar.gz: dcf40a6123e877375fffaf49902a828b175c1bb642bd4ee86157ba33e9ca750d4cd98455d107ce2dc9fe4639b00791ad12715bb4d68a9ad0ce36d6104cf99644
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# CSV file reader and writer
|
2
|
+
|
3
|
+
$LOAD_PATH << '../../lib'
|
4
|
+
|
5
|
+
require'../prefix_tree'
|
6
|
+
|
7
|
+
class CsvController
|
8
|
+
def initialize(tree = PrefixTree.new)
|
9
|
+
@tree = tree
|
10
|
+
end
|
11
|
+
|
12
|
+
def fill_csv
|
13
|
+
strings = @tree.dictionary.map { |key, value| [key, value] }
|
14
|
+
|
15
|
+
CSV.open('dictionary.csv', 'w') do |csv|
|
16
|
+
csv << %w[id name]
|
17
|
+
strings.each { |string| csv << string }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def read_csv
|
22
|
+
strings = CSV.parse(File.read('strings_for_tree.csv'), headers: true).by_col[1]
|
23
|
+
fill_tree(strings)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def fill_tree(strings)
|
29
|
+
strings.each { |string| @tree.add(string) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
tree = PrefixTree.new
|
34
|
+
|
35
|
+
tree.add('dsbh')
|
36
|
+
tree.add('mmss')
|
37
|
+
tree.delete('dsbh')
|
38
|
+
tree.add('string')
|
39
|
+
|
40
|
+
csv_controller = CsvController.new(tree)
|
41
|
+
|
42
|
+
csv_controller.read_csv
|
43
|
+
csv_controller.fill_csv
|
44
|
+
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# create node class
|
2
|
+
|
3
|
+
$LOAD_PATH << '../../lib'
|
4
|
+
|
5
|
+
class Node
|
6
|
+
attr_reader :value, :number_size, :children, :is_end_point, :strings_indexs
|
7
|
+
|
8
|
+
@@nodes = []
|
9
|
+
|
10
|
+
def self.nodes
|
11
|
+
@@nodes
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(value = 'root')
|
15
|
+
@value = value
|
16
|
+
@children ||= []
|
17
|
+
@strings_indexs = []
|
18
|
+
@number_size = 0
|
19
|
+
@@nodes << self
|
20
|
+
@is_end_point = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_child(char)
|
24
|
+
@children << child = Node.new(char)
|
25
|
+
child
|
26
|
+
end
|
27
|
+
|
28
|
+
def delete_node
|
29
|
+
@children.delete_if { |node| node.number_size.zero? }
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
@value
|
34
|
+
end
|
35
|
+
|
36
|
+
def include?(char)
|
37
|
+
@children.any? { |node| node.value == char }
|
38
|
+
end
|
39
|
+
|
40
|
+
def find(char)
|
41
|
+
@children.each { |node| return node if node.value == char }
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
def become_end_point
|
46
|
+
@is_end_point = true
|
47
|
+
end
|
48
|
+
|
49
|
+
def not_end_point
|
50
|
+
@is_end_point = false
|
51
|
+
end
|
52
|
+
|
53
|
+
def increment_size
|
54
|
+
@number_size += 1
|
55
|
+
end
|
56
|
+
|
57
|
+
def decrement_size
|
58
|
+
@number_size -= 1
|
59
|
+
end
|
60
|
+
|
61
|
+
def add_strings_indexs(index)
|
62
|
+
@strings_indexs << index
|
63
|
+
end
|
64
|
+
|
65
|
+
def delete_strings_indexs
|
66
|
+
@children.each do |node|
|
67
|
+
erase_indexs(node)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete_element(value)
|
72
|
+
@strings_indexs.delete_if { |element| element.eql? value }
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def erase_indexs(node)
|
78
|
+
@strings_indexs -= node.strings_indexs if node.number_size.zero?
|
79
|
+
end
|
80
|
+
end
|
data/lib/prefix_tree.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
# create prefix tree
|
2
|
+
$LOAD_PATH << '../lib'
|
3
|
+
require 'prefix_tree/node'
|
4
|
+
|
5
|
+
|
6
|
+
WORD_EXIST = 'This word is already exist in prefix tree'
|
7
|
+
ADD_NEW_WORD = 'Add new word in prefix tree'
|
8
|
+
NO_WORD = 'This word is not in tree'
|
9
|
+
|
10
|
+
class PrefixTree
|
11
|
+
attr_reader :dictionary
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@root = Node.new
|
15
|
+
@number_of_input_strings = 0
|
16
|
+
@dictionary = {}
|
17
|
+
@dictionary_by_strings = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def add(input_value)
|
21
|
+
input_value = convert_to_string(input_value)
|
22
|
+
add_word(input_value.downcase)
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete(input_value)
|
26
|
+
return NO_WORD unless find(input_value)
|
27
|
+
|
28
|
+
decrease_size(input_value)
|
29
|
+
delete_string_index(input_value)
|
30
|
+
delete_nodes(input_value)
|
31
|
+
end
|
32
|
+
|
33
|
+
def include?(input_value)
|
34
|
+
find_prefix_node(input_value) ? true : false
|
35
|
+
end
|
36
|
+
|
37
|
+
def find(input_value)
|
38
|
+
node = find_prefix_node(input_value)
|
39
|
+
return false unless node
|
40
|
+
|
41
|
+
node.is_end_point
|
42
|
+
end
|
43
|
+
|
44
|
+
def list(input_value)
|
45
|
+
node = @root
|
46
|
+
input_value.each_char do |char|
|
47
|
+
node = find_node(node, char)
|
48
|
+
return false unless node
|
49
|
+
end
|
50
|
+
write_appropriate_strings(node, input_value)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def write_appropriate_strings(node, input_value)
|
56
|
+
if input_value == ''
|
57
|
+
puts @dictionary.values
|
58
|
+
else
|
59
|
+
puts_answer(node.strings_indexs)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def puts_answer(indexs)
|
64
|
+
indexs.each { |index| puts @dictionary[index] }
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_word(input_value)
|
68
|
+
return WORD_EXIST if find(input_value)
|
69
|
+
|
70
|
+
dictionary_filler(input_value)
|
71
|
+
fill_tree(input_value)
|
72
|
+
ADD_NEW_WORD
|
73
|
+
end
|
74
|
+
|
75
|
+
def dictionary_filler(input_value)
|
76
|
+
add_in_dictionary(input_value)
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_in_dictionary(input_value)
|
80
|
+
@number_of_input_strings += 1
|
81
|
+
@dictionary_by_strings[input_value] = @number_of_input_strings
|
82
|
+
@dictionary[@number_of_input_strings] = input_value
|
83
|
+
end
|
84
|
+
|
85
|
+
def fill_tree(input_value)
|
86
|
+
node = @root
|
87
|
+
input_value.each_char { |char| node = back_new_node(node, char) }
|
88
|
+
node.become_end_point
|
89
|
+
end
|
90
|
+
|
91
|
+
def back_new_node(node, char)
|
92
|
+
new_node = create_or_find_node(node, char)
|
93
|
+
new_node.add_strings_indexs(@number_of_input_strings)
|
94
|
+
new_node.increment_size
|
95
|
+
new_node
|
96
|
+
end
|
97
|
+
|
98
|
+
def convert_to_string(input_value)
|
99
|
+
input_value.to_s
|
100
|
+
end
|
101
|
+
|
102
|
+
def find_prefix_node(input_value)
|
103
|
+
node = @root
|
104
|
+
input_value.each_char do |char|
|
105
|
+
node = find_node(node, char)
|
106
|
+
return false unless node
|
107
|
+
end
|
108
|
+
node
|
109
|
+
end
|
110
|
+
|
111
|
+
def create_or_find_node(node, char)
|
112
|
+
if node.include?(char)
|
113
|
+
node.find(char)
|
114
|
+
else
|
115
|
+
node.create_child(char)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def find_node(node, char)
|
120
|
+
node.include?(char) ? node.find(char) : false
|
121
|
+
end
|
122
|
+
|
123
|
+
def delete_string_index(input_value)
|
124
|
+
index = @dictionary_by_strings[input_value]
|
125
|
+
@dictionary.delete(index)
|
126
|
+
@dictionary_by_strings.delete(input_value)
|
127
|
+
end
|
128
|
+
|
129
|
+
def decrease_size(input_value)
|
130
|
+
node = @root
|
131
|
+
input_value.each_char do |char|
|
132
|
+
node = node.find(char)
|
133
|
+
change_size(node, input_value)
|
134
|
+
end
|
135
|
+
node.not_end_point
|
136
|
+
end
|
137
|
+
|
138
|
+
def change_size(node, input_value)
|
139
|
+
node.decrement_size
|
140
|
+
node.delete_element(@dictionary_by_strings[input_value])
|
141
|
+
end
|
142
|
+
|
143
|
+
def delete_nodes(input_value)
|
144
|
+
node = @root
|
145
|
+
input_value.each_char do |char|
|
146
|
+
break unless node
|
147
|
+
|
148
|
+
delete_nodes_in_node_class(node)
|
149
|
+
node = node.find(char)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def delete_nodes_in_node_class(node)
|
154
|
+
node.delete_strings_indexs
|
155
|
+
node.delete_node
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
|
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: prefix_tree
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- tato
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-05-06 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: prefix_tree gem
|
14
|
+
email: tzpanchulidze@unisens.ge
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/prefix_tree.rb
|
20
|
+
- lib/prefix_tree/csv_controller.rb
|
21
|
+
- lib/prefix_tree/node.rb
|
22
|
+
homepage: ''
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
metadata: {}
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubygems_version: 3.2.32
|
42
|
+
signing_key:
|
43
|
+
specification_version: 4
|
44
|
+
summary: prefix_tree
|
45
|
+
test_files: []
|