greek_stemmer 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,261 @@
1
+ step_1_exceptions:
2
+ ΦΑΓΙΑ: ΦΑ
3
+ ΦΑΓΙΟΥ: ΦΑ
4
+ ΦΑΓΙΩΝ: ΦΑ
5
+ ΣΚΑΓΙΑ: ΣΚΑ
6
+ ΣΚΑΓΙΟΥ: ΣΚΑ
7
+ ΣΚΑΓΙΩΝ: ΣΚΑ
8
+ ΟΛΟΓΙΟΥ: ΟΛΟ
9
+ ΟΛΟΓΙΑ: ΟΛΟ
10
+ ΟΛΟΓΙΩΝ: ΟΛΟ
11
+ ΣΟΓΙΟΥ: ΣΟ
12
+ ΣΟΓΙΑ: ΣΟ
13
+ ΣΟΓΙΩΝ: ΣΟ
14
+ ΤΑΤΟΓΙΑ: ΤΑΤΟ
15
+ ΤΑΤΟΓΙΟΥ: ΤΑΤΟ
16
+ ΤΑΤΟΓΙΩΝ: ΤΑΤΟ
17
+ ΚΡΕΑΣ: ΚΡΕ
18
+ ΚΡΕΑΤΟΣ: ΚΡΕ
19
+ ΚΡΕΑΤΑ: ΚΡΕ
20
+ ΚΡΕΑΤΩΝ: ΚΡΕ
21
+ ΠΕΡΑΣ: ΠΕΡ
22
+ ΠΕΡΑΤΟΣ: ΠΕΡ
23
+ ΠΕΡΑΤΑ: ΠΕΡ
24
+ ΠΕΡΑΤΩΝ: ΠΕΡ
25
+ ΤΕΡΑΣ: ΤΕΡ
26
+ ΤΕΡΑΤΟΣ: ΤΕΡ
27
+ ΤΕΡΑΤΑ: ΤΕΡ
28
+ ΤΕΡΑΤΩΝ: ΤΕΡ
29
+ ΦΩΣ: ΦΩ
30
+ ΦΩΤΟΣ: ΦΩ
31
+ ΦΩΤΑ: ΦΩ
32
+ ΦΩΤΩΝ: ΦΩ
33
+ ΚΑΘΕΣΤΩΣ: ΚΑΘΕΣΤ
34
+ ΚΑΘΕΣΤΩΤΟΣ: ΚΑΘΕΣΤ
35
+ ΚΑΘΕΣΤΩΤΑ: ΚΑΘΕΣΤ
36
+ ΚΑΘΕΣΤΩΤΩΝ: ΚΑΘΕΣΤ
37
+ ΓΕΓΟΝΟΣ: ΓΕΓΟΝ
38
+ ΓΕΓΟΝΟΤΟΣ: ΓΕΓΟΝ
39
+ ΓΕΓΟΝΟΤΑ: ΓΕΓΟΝ
40
+ ΓΕΓΟΝΟΤΩΝ: ΓΕΓΟΝ
41
+
42
+ protected_words:
43
+ - ΑΚΡΙΒΩΣ
44
+ - ΑΛΑ
45
+ - ΑΛΛΑ
46
+ - ΑΛΛΙΩΣ
47
+ - ΑΛΛΟΤΕ
48
+ - ΑΜΑ
49
+ - ΑΝΩ
50
+ - ΑΝΑ
51
+ - ΑΝΑΜΕΣΑ
52
+ - ΑΝΑΜΕΤΑΞΥ
53
+ - ΑΝΕΥ
54
+ - ΑΝΤΙ
55
+ - ΑΝΤΙΠΕΡΑ
56
+ - ΑΝΤΙΟ
57
+ - ΑΞΑΦΝΑ
58
+ - ΑΠΟ
59
+ - ΑΠΟΨΕ
60
+ - ΑΡΑ
61
+ - ΑΡΑΓΕ
62
+ - ΑΥΡΙΟ
63
+ - ΑΦΟΙ
64
+ - ΑΦΟΥ
65
+ - ΑΦΟΤΟΥ
66
+ - ΒΡΕ
67
+ - ΓΕΙΑ
68
+ - ΓΙΑ
69
+ - ΓΙΑΤΙ
70
+ - ΓΡΑΜΜΑ
71
+ - ΔΕΗ
72
+ - ΔΕΝ
73
+ - ΔΗΛΑΔΗ
74
+ - ΔΙΧΩΣ
75
+ - ΔΥΟ
76
+ - ΕΑΝ
77
+ - ΕΓΩ
78
+ - ΕΔΩ
79
+ - ΕΔΑ
80
+ - ΕΙΘΕ
81
+ - ΕΙΜΑΙ
82
+ - ΕΙΜΑΣΤΕ
83
+ - ΕΙΣΑΙ
84
+ - ΕΙΣΑΣΤΕ
85
+ - ΕΙΝΑΙ
86
+ - ΕΙΣΤΕ
87
+ - ΕΙΤΕ
88
+ - ΕΚΕΙ
89
+ - ΕΚΟ
90
+ - ΕΛΑ
91
+ - ΕΜΑΣ
92
+ - ΕΜΕΙΣ
93
+ - ΕΝΤΕΛΩΣ
94
+ - ΕΝΤΟΣ
95
+ - ΕΝΤΩΜΕΤΑΞΥ
96
+ - ΕΝΩ
97
+ - ΕΞΙ
98
+ - ΕΞΙΣΟΥ
99
+ - ΕΞΗΣ
100
+ - ΕΞΩ
101
+ - ΕΟΚ
102
+ - ΕΠΑΝΩ
103
+ - ΕΠΕΙΔΗ
104
+ - ΕΠΕΙΤΑ
105
+ - ΕΠΙ
106
+ - ΕΠΙΣΗΣ
107
+ - ΕΠΟΜΕΝΩΣ
108
+ - ΕΠΤΑ
109
+ - ΕΣΑΣ
110
+ - ΕΣΕΙΣ
111
+ - ΕΣΤΩ
112
+ - ΕΣΥ
113
+ - ΕΣΩ
114
+ - ΕΤΣΙ
115
+ - ΕΥΓΕ
116
+ - ΕΦΕ
117
+ - ΕΦΕΞΗΣ
118
+ - ΕΧΤΕΣ
119
+ - ΕΩΣ
120
+ - ΗΔΗ
121
+ - ΗΜΙ
122
+ - ΗΠΑ
123
+ - ΗΤΟΙ
124
+ - ΘΕΣ
125
+ - ΙΔΙΩΣ
126
+ - ΙΔΗ
127
+ - ΙΚΑ
128
+ - ΙΣΩΣ
129
+ - ΚΑΘΕ
130
+ - ΚΑΘΕΤΙ
131
+ - ΚΑΘΟΛΟΥ
132
+ - ΚΑΘΩΣ
133
+ - ΚΑΙ
134
+ - ΚΑΝ
135
+ - ΚΑΠΟΤΕ
136
+ - ΚΑΠΟΥ
137
+ - ΚΑΤΑ
138
+ - ΚΑΤΙ
139
+ - ΚΑΤΟΠΙΝ
140
+ - ΚΑΤΩ
141
+ - ΚΕΙ
142
+ - ΚΙΧ
143
+ - ΚΚΕ
144
+ - ΚΥΡΙΩΣ
145
+ - ΚΩΣ
146
+ - ΜΑΚΑΡΙ
147
+ - ΜΑΛΙΣΤΑ
148
+ - ΜΑΛΛΟΝ
149
+ - ΜΑΙ
150
+ - ΜΑΟ
151
+ - ΜΑΟΥΣ
152
+ - ΜΑΣ
153
+ - ΜΕΘΑΥΡΙΟ
154
+ - ΜΕΣ
155
+ - ΜΕΣΑ
156
+ - ΜΕΤΑ
157
+ - ΜΕΤΑΞΥ
158
+ - ΜΕΧΡΙ
159
+ - ΜΗΔΕ
160
+ - ΜΗΝ
161
+ - ΜΗΠΩΣ
162
+ - ΜΗΤΕ
163
+ - ΜΙΑ
164
+ - ΜΙΑΣ
165
+ - ΜΙΣ
166
+ - ΜΜΕ
167
+ - ΜΟΛΟΝΟΤΙ
168
+ - ΜΟΥ
169
+ - ΜΠΑ
170
+ - ΜΠΑΣ
171
+ - ΜΠΡΟΣ
172
+ - ΝΑΙ
173
+ - ΝΕΣ
174
+ - ΝΤΑ
175
+ - ΝΤΕ
176
+ - ΞΑΝΑ
177
+ - ΟΗΕ
178
+ - ΟΚΤΩ
179
+ - ΟΜΩΣ
180
+ - ΟΝΕ
181
+ - ΟΠΑ
182
+ - ΟΠΟΥ
183
+ - ΟΠΩΣ
184
+ - ΟΣΟ
185
+ - ΟΤΑΝ
186
+ - ΟΤΕ
187
+ - ΟΤΙ
188
+ - ΟΥΤΕ
189
+ - ΟΧΙ
190
+ - ΠΑΛΙ
191
+ - ΠΑΝ
192
+ - ΠΑΝΟ
193
+ - ΠΑΝΤΟΤΕ
194
+ - ΠΑΝΤΟΥ
195
+ - ΠΑΝΤΩΣ
196
+ - ΠΑΝΩ
197
+ - ΠΑΡΑ
198
+ - ΠΕΡΑ
199
+ - ΠΕΡΙ
200
+ - ΠΕΡΙΠΟΥ
201
+ - ΠΙΑ
202
+ - ΠΙΟ
203
+ - ΠΙΣΩ
204
+ - ΠΛΑΙ
205
+ - ΠΛΕΟΝ
206
+ - ΠΛΗΝ
207
+ - ΠΟΤΕ
208
+ - ΠΟΥ
209
+ - ΠΡΟ
210
+ - ΠΡΟΣ
211
+ - ΠΡΟΧΤΕΣ
212
+ - ΠΡΟΧΘΕΣ
213
+ - ΡΟΔΙ
214
+ - ΠΩΣ
215
+ - ΣΑΙ
216
+ - ΣΑΣ
217
+ - ΣΑΝ
218
+ - ΣΕΙΣ
219
+ - ΣΙΑ
220
+ - ΣΚΙ
221
+ - ΣΟΙ
222
+ - ΣΟΥ
223
+ - ΣΡΙ
224
+ - ΣΥΝ
225
+ - ΣΥΝΑΜΑ
226
+ - ΣΧΕΔΟΝ
227
+ - ΤΑΔΕ
228
+ - ΤΑΞΙ
229
+ - ΤΑΧΑ
230
+ - ΤΕΙ
231
+ - ΤΗΝ
232
+ - ΤΗΣ
233
+ - ΤΙΠΟΤΑ
234
+ - ΤΙΠΟΤΕ
235
+ - ΤΙΣ
236
+ - ΤΟΝ
237
+ - ΤΟΤΕ
238
+ - ΤΟΥ
239
+ - ΤΟΥΣ
240
+ - ΤΣΑ
241
+ - ΤΣΕ
242
+ - ΤΣΙ
243
+ - ΤΣΟΥ
244
+ - ΤΩΝ
245
+ - ΥΠΟ
246
+ - ΥΠΟΨΗ
247
+ - ΥΠΟΨΙΝ
248
+ - ΥΣΤΕΡΑ
249
+ - ΦΕΤΟΣ
250
+ - ΦΙΣ
251
+ - ΦΠΑ
252
+ - ΧΑΦ
253
+ - ΧΘΕΣ
254
+ - ΧΤΕΣ
255
+ - ΧΩΡΙΣ
256
+ - ΩΣ
257
+ - ΩΣΑΝ
258
+ - ΩΣΟΤΟΥ
259
+ - ΩΣΠΟΥ
260
+ - ΩΣΤΕ
261
+ - ΩΣΤΟΣΟ-
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'greek_stemmer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "greek_stemmer"
8
+ spec.version = GreekStemmer::VERSION
9
+ spec.authors = ["Tasos Stathopoulos", "Giorgos Tsiftsis"]
10
+ spec.email = ["stathopa@skroutz.gr", "giorgos.tsiftsis@skroutz.gr"]
11
+ spec.summary = %q{A simple Greek stemmer}
12
+ spec.description = %q{A simple Greek stemmer}
13
+ spec.homepage = "https://gitlab.skroutz.gr/greek_stemmer"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+
25
+ if RUBY_VERSION >= "2.0.0"
26
+ spec.add_development_dependency "pry-byebug"
27
+ else
28
+ spec.add_development_dependency "pry"
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module GreekStemmer
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,230 @@
1
+ # coding: utf-8
2
+ require "greek_stemmer/version"
3
+ require "yaml"
4
+
5
+ # Please note that we use only upcase letters for all methods. One should
6
+ # normalize input streams before using the `stem` method. Normalization means
7
+ # detone and upcase.
8
+ module GreekStemmer
9
+ extend self
10
+
11
+ # Helper method for loading settings
12
+ #
13
+ # @param key [String] the key
14
+ def load_settings(key)
15
+ config_path = File.expand_path("../../config/stemmer.yml", __FILE__)
16
+
17
+ begin
18
+ YAML.load_file(config_path)[key]
19
+ rescue => e
20
+ raise "Please provide a valid config/stemmer.yml file, #{e}"
21
+ end
22
+ end
23
+
24
+ # Transformations for step 1 words
25
+ STEP_1_EXCEPTIONS = load_settings("step_1_exceptions")
26
+
27
+ # Protected words
28
+ PROTECTED_WORDS = load_settings("protected_words")
29
+
30
+ # Regular expression that checks if the word contains only Greek characters
31
+ ALPHABET = Regexp.new("^[ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ]+$").freeze
32
+
33
+ # Stems Greek words
34
+ #
35
+ # @param word [String] the word to be stemmed
36
+ # @return [String] the stemmed word
37
+ def stem(word)
38
+ return word if word.length < 3
39
+ stem = word.dup
40
+ return stem if PROTECTED_WORDS.include?(stem) || !greek?(word)
41
+
42
+ step_1_regexp = /(.*)(#{STEP_1_EXCEPTIONS.keys.join("|")})$/u
43
+
44
+ # step 1
45
+ stem.scan(step_1_regexp) do |st, suffix|
46
+ stem = st + STEP_1_EXCEPTIONS[suffix]
47
+ end
48
+
49
+ # step 2a
50
+ stem.scan(/^(.+?)(ΑΔΕΣ|ΑΔΩΝ)$/u) do |st, suffix|
51
+ stem = st
52
+ stem << "ΑΔ" unless st =~ /(ΟΚ|ΜΑΜ|ΜΑΝ|ΜΠΑΜΠ|ΠΑΤΕΡ|ΓΙΑΓΙ|ΝΤΑΝΤ|ΚΥΡ|ΘΕΙ|ΠΕΘΕΡ|ΚΑΠΛΑΜ|ΠΑΡ|ΨΑΡ|ΤΖΟΥΡ|ΤΑΜΠΟΥΡ)$/u
53
+ end
54
+
55
+ # step 2b
56
+ stem.scan(/^(.+?)(ΕΔΕΣ|ΕΔΩΝ)$/u) do |st, suffix|
57
+ stem = st
58
+ stem << "ΕΔ" if st =~ /(ΟΠ|ΙΠ|ΕΜΠ|ΥΠ|ΓΗΠ|ΔΑΠ|ΚΡΑΣΠ|ΜΙΛ)$/u
59
+ end
60
+
61
+ # step 2c
62
+ stem.scan(/^(.+?)(ΟΥΔΕΣ|ΟΥΔΩΝ)$/u) do |st, suffix|
63
+ stem = st
64
+ stem << "ΟΥΔ" if st =~ /(ΑΡΚ|ΚΑΛΙΑΚ|ΠΕΤΑΛ|ΛΙΧ|ΠΛΕΞ|ΣΚ|Σ|ΦΛ|ΦΡ|ΒΕΛ|ΛΟΥΛ|ΧΝ|ΣΠ|ΤΡΑΓ|ΦΕ)$/u
65
+ end
66
+
67
+ # step 2d
68
+ stem.scan(/^(.+?)(ΕΩΣ|ΕΩΝ|ΕΑΣ|ΕΑ)$/u) do |st, suffix|
69
+ stem = st
70
+ stem << "Ε" if st =~ /^(Θ|Δ|ΕΛ|ΓΑΛ|Ν|Π|ΙΔ|ΠΑΡ|ΣΤΕΡ|ΟΡΦ|ΑΝΔΡ|ΑΝΤΡ)$/u
71
+ end
72
+
73
+ # step 3
74
+ stem.scan(/^(.+?)(ΙΟΥΣ|ΙΑΣ|ΙΕΣ|ΙΟΣ|ΙΟΥ|ΙΟΙ|ΙΩΝ|ΙΟΝ|ΙΑ|ΙΟ)$/u) do |st, suffix|
75
+ stem = st
76
+ stem << "Ι" if ends_on_vowel?(st) || st.length < 2 || st=~ /^(ΑΓ|ΑΓΓΕΛ|ΑΓΡ|ΑΕΡ|ΑΘΛ|ΑΚΟΥΣ|ΑΞ|ΑΣ|Β|ΒΙΒΛ|ΒΥΤ|Γ|ΓΙΑΓ|ΓΩΝ|Δ|ΔΑΝ|ΔΗΛ|ΔΗΜ|ΔΟΚΙΜ|ΕΛ|ΖΑΧΑΡ|ΗΛ|ΗΠ|ΙΔ|ΙΣΚ|ΙΣΤ|ΙΟΝ|ΙΩΝ|ΚΙΜΩΛ|ΚΟΛΟΝ|ΚΟΡ|ΚΤΗΡ|ΚΥΡ|ΛΑΓ|ΛΟΓ|ΜΑΓ|ΜΠΑΝ|ΜΠΡ|ΝΑΥΤ|ΝΟΤ|ΟΠΑΛ|ΟΞ|ΟΡ|ΟΣ|ΠΑΝΑΓ|ΠΑΤΡ|ΠΗΛ|ΠΗΝ|ΠΛΑΙΣ|ΠΟΝΤ|ΡΑΔ|ΡΟΔ|ΣΚ|ΣΚΟΡΠ|ΣΟΥΝ|ΣΠΑΝ|ΣΤΑΔ|ΣΥΡ|ΤΗΛ|ΤΙΜ|ΤΟΚ|ΤΟΠ|ΤΡΟΧ|ΦΙΛ|ΦΩΤ|Χ|ΧΙΛ|ΧΡΩΜ|ΧΩΡ)$/u
77
+ stem << "ΑΙ" if st =~ /^(ΠΑΛ)$/u
78
+ end
79
+
80
+ # step 4
81
+ stem.scan(/^(.+?)(ΙΚΟΣ|ΙΚΟΝ|ΙΚΕΙΣ|ΙΚΟΙ|ΙΚΕΣ|ΙΚΟΥΣ|ΙΚΗ|ΙΚΗΣ|ΙΚΟ|ΙΚΑ|ΙΚΟΥ|ΙΚΩΝ|ΙΚΩΣ)$/u) do |st, suffix|
82
+ stem = st
83
+ stem << "ΙΚ" if ends_on_vowel?(st) || st =~ /^(ΑΔ|ΑΛ|ΑΜΑΝ|ΑΜΕΡ|ΑΜΜΟΧΑΛ|ΑΝΗΘ|ΑΝΤΙΔ|ΑΠΛ|ΑΤΤ|ΑΦΡ|ΒΑΣ|ΒΡΩΜ|ΓΕΝ|ΓΕΡ|Δ|ΔΥΤ|ΕΙΔ|ΕΝΔ|ΕΞΩΔ|ΗΘ|ΘΕΤ|ΚΑΛΛΙΝ|ΚΑΛΠ|ΚΑΤΑΔ|ΚΡ|ΚΩΔ|ΛΟΓ|Μ|ΜΕΡ|ΜΟΝΑΔ|ΜΟΥΛ|ΜΟΥΣ|ΜΠΑΓΙΑΤ|ΜΠΑΝ|ΜΠΟΛ|ΜΠΟΣ|ΜΥΣΤ|Ν|ΝΙΤ|ΞΙΚ|ΟΠΤ|ΠΑΝ|ΠΕΤΣ|ΠΙΚΑΝΤ|ΠΙΤΣ|ΠΛΑΣΤ|ΠΛΙΑΤΣ|ΠΟΝΤ|ΠΟΣΤΕΛΝ|ΠΡΩΤΟΔ|ΣΕΡΤ|ΣΗΜΑΝΤ|ΣΤΑΤ|ΣΥΝΑΔ|ΣΥΝΟΜΗΛ|ΤΕΛ|ΤΕΧΝ|ΤΡΟΠ|ΤΣΑΜ|ΥΠΟΔ|Φ|ΦΙΛΟΝ|ΦΥΛΟΔ|ΦΥΣ|ΧΑΣ)$/ || st =~ /(ΦΟΙΝ)$/u
84
+ end
85
+
86
+ # step 5a
87
+ stem = "ΑΓΑΜ" if word == 'ΑΓΑΜΕ'
88
+
89
+ stem.scan(/^(.+?)(ΑΓΑΜΕ|ΗΣΑΜΕ|ΟΥΣΑΜΕ|ΗΚΑΜΕ|ΗΘΗΚΑΜΕ)$/u) do |st, suffix|
90
+ stem = st
91
+ end
92
+
93
+ stem.scan(/^(.+?)(ΑΜΕ)$/u) do |st, suffix|
94
+ stem = st
95
+ stem << "ΑΜ" if st =~ /^(ΑΝΑΠ|ΑΠΟΘ|ΑΠΟΚ|ΑΠΟΣΤ|ΒΟΥΒ|ΞΕΘ|ΟΥΛ|ΠΕΘ|ΠΙΚΡ|ΠΟΤ|ΣΙΧ|Χ)$/
96
+ end
97
+
98
+ # step 5b
99
+ stem.scan(/^(.+?)(ΑΓΑΝΕ|ΗΣΑΝΕ|ΟΥΣΑΝΕ|ΙΟΝΤΑΝΕ|ΙΟΤΑΝΕ|ΙΟΥΝΤΑΝΕ|ΟΝΤΑΝΕ|ΟΤΑΝΕ|ΟΥΝΤΑΝΕ|ΗΚΑΝΕ|ΗΘΗΚΑΝΕ)$/u) do |st, suffix|
100
+ stem = st
101
+ stem << "ΑΓΑΝ" if st =~ /^(ΤΡ|ΤΣ)$/
102
+ end
103
+
104
+ stem.scan(/^(.+?)(ΑΝΕ)$/u) do |st, suffix|
105
+ stem = st
106
+ stem << "ΑΝ" if st =~ /^(ΒΕΤΕΡ|ΒΟΥΛΚ|ΒΡΑΧΜ|Γ|ΔΡΑΔΟΥΜ|Θ|ΚΑΛΠΟΥΖ|ΚΑΣΤΕΛ|ΚΟΡΜΟΡ|ΛΑΟΠΛ|ΜΩΑΜΕΘ|Μ|ΜΟΥΣΟΥΛΜ|Ν|ΟΥΛ|Π|ΠΕΛΕΚ|ΠΛ|ΠΟΛΙΣ|ΠΟΡΤΟΛ|ΣΑΡΑΚΑΤΣ|ΣΟΥΛΤ|ΤΣΑΡΛΑΤ|ΟΡΦ|ΤΣΙΓΓ|ΤΣΟΠ|ΦΩΤΟΣΤΕΦ|Χ|ΨΥΧΟΠΛ|ΑΓ|ΟΡΦ|ΓΑΛ|ΓΕΡ|ΔΕΚ|ΔΙΠΛ|ΑΜΕΡΙΚΑΝ|ΟΥΡ|ΠΙΘ|ΠΟΥΡΙΤ|Σ|ΖΩΝΤ|ΙΚ|ΚΑΣΤ|ΚΟΠ|ΛΙΧ|ΛΟΥΘΗΡ|ΜΑΙΝΤ|ΜΕΛ|ΣΙΓ|ΣΠ|ΣΤΕΓ|ΤΡΑΓ|ΤΣΑΓ|Φ|ΕΡ|ΑΔΑΠ|ΑΘΙΓΓ|ΑΜΗΧ|ΑΝΙΚ|ΑΝΟΡΓ|ΑΠΗΓ|ΑΠΙΘ|ΑΤΣΙΓΓ|ΒΑΣ|ΒΑΣΚ|ΒΑΘΥΓΑΛ|ΒΙΟΜΗΧ|ΒΡΑΧΥΚ|ΔΙΑΤ|ΔΙΑΦ|ΕΝΟΡΓ|ΘΥΣ|ΚΑΠΝΟΒΙΟΜΗΧ|ΚΑΤΑΓΑΛ|ΚΛΙΒ|ΚΟΙΛΑΡΦ|ΛΙΒ|ΜΕΓΛΟΒΙΟΜΗΧ|ΜΙΚΡΟΒΙΟΜΗΧ|ΝΤΑΒ|ΞΗΡΟΚΛΙΒ|ΟΛΙΓΟΔΑΜ|ΟΛΟΓΑΛ|ΠΕΝΤΑΡΦ|ΠΕΡΗΦ|ΠΕΡΙΤΡ|ΠΛΑΤ|ΠΟΛΥΔΑΠ|ΠΟΛΥΜΗΧ|ΣΤΕΦ|ΤΑΒ|ΤΕΤ|ΥΠΕΡΗΦ|ΥΠΟΚΟΠ|ΧΑΜΗΛΟΔΑΠ|ΨΗΛΟΤΑΒ)$/ || ends_on_vowel2?(st)
107
+ end
108
+
109
+ # step 5c
110
+ stem.scan(/^(.+?)(ΗΣΕΤΕ)$/u) do |st, suffix|
111
+ stem = st
112
+ end
113
+
114
+ stem.scan(/^(.+?)(ΕΤΕ)$/u) do |st, suffix|
115
+ stem = st
116
+ stem << "ΕΤ" if ends_on_vowel2?(st) || st =~ /(ΟΔ|ΑΙΡ|ΦΟΡ|ΤΑΘ|ΔΙΑΘ|ΣΧ|ΕΝΔ|ΕΥΡ|ΤΙΘ|ΥΠΕΡΘ|ΡΑΘ|ΕΝΘ|ΡΟΘ|ΣΘ|ΠΥΡ|ΑΙΝ|ΣΥΝΔ|ΣΥΝ|ΣΥΝΘ|ΧΩΡ|ΠΟΝ|ΒΡ|ΚΑΘ|ΕΥΘ|ΕΚΘ|ΝΕΤ|ΡΟΝ|ΑΡΚ|ΒΑΡ|ΒΟΛ|ΩΦΕΛ)$/ || st =~ /^(ΑΒΑΡ|ΒΕΝ|ΕΝΑΡ|ΑΒΡ|ΑΔ|ΑΘ|ΑΝ|ΑΠΛ|ΒΑΡΟΝ|ΝΤΡ|ΣΚ|ΚΟΠ|ΜΠΟΡ|ΝΙΦ|ΠΑΓ|ΠΑΡΑΚΑΛ|ΣΕΡΠ|ΣΚΕΛ|ΣΥΡΦ|ΤΟΚ|Υ|Δ|ΕΜ|ΘΑΡΡ|Θ)$/
117
+ end
118
+
119
+ # step 5d
120
+ stem.scan(/^(.+?)(ΟΝΤΑΣ|ΩΝΤΑΣ)$/u) do |st, suffix|
121
+ stem = st
122
+ stem << "ΟΝΤ" if st =~ /^ΑΡΧ$/u
123
+ stem << "ΩΝΤ" if st =~ /ΚΡΕ$/u
124
+ end
125
+
126
+ # step 5e
127
+ stem.scan(/^(.+?)(ΟΜΑΣΤΕ|ΙΟΜΑΣΤΕ)$/u) do |st, suffix|
128
+ stem = st
129
+ stem << "ΟΜΑΣΤ" if st =~ /^ΟΝ$/u
130
+ end
131
+
132
+ # step 5f
133
+ stem.scan(/^(.+?)(ΙΕΣΤΕ)$/u) do |st, suffix|
134
+ stem = st
135
+ stem << "ΙΕΣΤ" if st =~ /^(Π|ΑΠ|ΣΥΜΠ|ΑΣΥΜΠ|ΑΚΑΤΑΠ|ΑΜΕΤΑΜΦ)$/
136
+ end
137
+
138
+ stem.scan(/^(.+?)(ΕΣΤΕ)$/u) do |st, suffix|
139
+ stem = st
140
+ stem << "ΕΣΤ" if st =~ /^(ΑΛ|ΑΡ|ΕΚΤΕΛ|Ζ|Μ|Ξ|ΠΑΡΑΚΑΛ|ΑΡ|ΠΡΟ|ΝΙΣ)$/
141
+ end
142
+
143
+ # step 5g
144
+ stem.scan(/^(.+?)(ΗΘΗΚΑ|ΗΘΗΚΕΣ|ΗΘΗΚΕ)$/u) do |st, suffix|
145
+ stem = st
146
+ end
147
+
148
+ stem.scan(/^(.+?)(ΗΚΑ|ΗΚΕΣ|ΗΚΕ)$/u) do |st, suffix|
149
+ stem = st
150
+ stem << "ΗΚ" if st =~ /(ΣΚΩΛ|ΣΚΟΥΛ|ΝΑΡΘ|ΣΦ|ΟΘ|ΠΙΘ)$/ || st =~ /^(ΔΙΑΘ|Θ|ΠΑΡΑΚΑΤΑΘ|ΠΡΟΣΘ|ΣΥΝΘ|)$/
151
+ end
152
+
153
+ # step 5h
154
+ stem.scan(/^(.+?)(ΟΥΣΑ|ΟΥΣΕΣ|ΟΥΣΕ)$/u) do |st, suffix|
155
+ stem = st
156
+ stem << "ΟΥΣ" if st =~ /^(ΦΑΡΜΑΚ|ΧΑΔ|ΑΓΚ|ΑΝΑΡΡ|ΒΡΟΜ|ΕΚΛΙΠ|ΛΑΜΠΙΔ|ΛΕΧ|Μ|ΠΑΤ|Ρ|Λ|ΜΕΔ|ΜΕΣΑΖ|ΥΠΟΤΕΙΝ|ΑΜ|ΑΙΘ|ΑΝΗΚ|ΔΕΣΠΟΖ|ΕΝΔΙΑΦΕΡ|ΔΕ|ΔΕΥΤΕΡΕΥ|ΚΑΘΑΡΕΥ|ΠΛΕ|ΤΣΑ)$/ || st =~ /(ΠΟΔΑΡ|ΒΛΕΠ|ΠΑΝΤΑΧ|ΦΡΥΔ|ΜΑΝΤΙΛ|ΜΑΛΛ|ΚΥΜΑΤ|ΛΑΧ|ΛΗΓ|ΦΑΓ|ΟΜ|ΠΡΩΤ)$/ || ends_on_vowel?(st)
157
+ end
158
+
159
+ # step 5i
160
+ stem.scan(/^(.+?)(ΑΓΑ|ΑΓΕΣ|ΑΓΕ)$/u) do |st, suffix|
161
+ stem = st
162
+ stem << "ΑΓ" if (st =~ /^(ΑΒΑΣΤ|ΠΟΛΥΦ|ΑΔΗΦ|ΠΑΜΦ|Ρ|ΑΣΠ|ΑΦ|ΑΜΑΛ|ΑΜΑΛΛΙ|ΑΝΥΣΤ|ΑΠΕΡ|ΑΣΠΑΡ|ΑΧΑΡ|ΔΕΡΒΕΝ|ΔΡΟΣΟΠ|ΞΕΦ|ΝΕΟΠ|ΝΟΜΟΤ|ΟΛΟΠ|ΟΜΟΤ|ΠΡΟΣΤ|ΠΡΟΣΩΠΟΠ|ΣΥΜΠ|ΣΥΝΤ|Τ|ΥΠΟΤ|ΧΑΡ|ΑΕΙΠ|ΑΙΜΟΣΤ|ΑΝΥΠ|ΑΠΟΤ|ΑΡΤΙΠ|ΔΙΑΤ|ΕΝ|ΕΠΙΤ|ΚΡΟΚΑΛΟΠ|ΣΙΔΗΡΟΠ|Λ|ΝΑΥ|ΟΥΛΑΜ|ΟΥΡ|Π|ΤΡ|Μ)$/ || st =~ /(ΟΦ|ΠΕΛ|ΧΟΡΤ|ΛΛ|ΣΦ|ΡΠ|ΦΡ|ΠΡ|ΛΟΧ|ΣΜΗΝ)$/) && !(st =~ /^(ΨΟΦ|ΝΑΥΛΟΧ)$/ || st =~ /(ΚΟΛΛ)$/)
163
+ end
164
+
165
+ # step 5j
166
+ stem.scan(/^(.+?)(ΗΣΕ|ΗΣΟΥ|ΗΣΑ)$/u) do |st, suffix|
167
+ stem = st
168
+ stem << "ΗΣ" if st =~ /^(Ν|ΧΕΡΣΟΝ|ΔΩΔΕΚΑΝ|ΕΡΗΜΟΝ|ΜΕΓΑΛΟΝ|ΕΠΤΑΝ|Ι)$/
169
+ end
170
+
171
+ # step 5k
172
+ stem.scan(/^(.+?)(ΗΣΤΕ)$/u) do |st, suffix|
173
+ stem = st
174
+ stem << "ΗΣΤ" if st =~ /^(ΑΣΒ|ΣΒ|ΑΧΡ|ΧΡ|ΑΠΛ|ΑΕΙΜΝ|ΔΥΣΧΡ|ΕΥΧΡ|ΚΟΙΝΟΧΡ|ΠΑΛΙΜΨ)$/
175
+ end
176
+
177
+ # step 5l
178
+ stem.scan(/^(.+?)(ΟΥΝΕ|ΗΣΟΥΝΕ|ΗΘΟΥΝΕ)$/u) do |st, suffix|
179
+ stem = st
180
+ stem << "ΟΥΝ" if st =~ /^(Ν|Ρ|ΣΠΙ|ΣΤΡΑΒΟΜΟΥΤΣ|ΚΑΚΟΜΟΥΤΣ|ΕΞΩΝ)$/
181
+ end
182
+
183
+ # step 5m
184
+ stem.scan(/^(.+?)(ΟΥΜΕ|ΗΣΟΥΜΕ|ΗΘΟΥΜΕ)$/u) do |st, suffix|
185
+ stem = st
186
+ stem << "ΟΥΜ" if st =~ /^(ΠΑΡΑΣΟΥΣ|Φ|Χ|ΩΡΙΟΠΛ|ΑΖ|ΑΛΛΟΣΟΥΣ|ΑΣΟΥΣ)$/
187
+ end
188
+
189
+ # step 6a
190
+ stem.scan(/^(.+?)(ΜΑΤΟΙ|ΜΑΤΟΥΣ|ΜΑΤΟ|ΜΑΤΑ|ΜΑΤΩΣ|ΜΑΤΩΝ|ΜΑΤΟΣ|ΜΑΤΕΣ|ΜΑΤΗ|ΜΑΤΗΣ|ΜΑΤΟΥ)$/u) do |st, suffix|
191
+ stem = st + "Μ"
192
+ if st =~ /^(ΓΡΑΜ)$/u
193
+ stem << "Α"
194
+ elsif st =~ /^(ΓΕ|ΣΤΑ)$/u
195
+ stem << "ΑΤ"
196
+ end
197
+ end
198
+
199
+ stem = long_stem_list(stem) if stem.length == word.length
200
+
201
+ stem.scan(/^(.+?)(ΕΣΤΕΡ|ΕΣΤΑΤ|ΟΤΕΡ|ΟΤΑΤ|ΥΤΕΡ|ΥΤΑΤ|ΩΤΕΡ|ΩΤΑΤ)$/u) do |st, suffix|
202
+ stem = st unless st =~ /^(ΕΞ|ΕΣ|ΑΝ|ΚΑΤ|Κ|ΠΡ)$/u
203
+
204
+ stem = st + "ΥΤ" if st =~ /^(ΚΑ|Μ|ΕΛΕ|ΛΕ|ΔΕ)$/u
205
+ end
206
+
207
+ stem
208
+ end
209
+
210
+ private
211
+
212
+ def ends_on_vowel?(word)
213
+ word =~ /[ΑΕΗΙΟΥΩ]$/
214
+ end
215
+
216
+ def ends_on_vowel2?(word)
217
+ word =~ /[ΑΕΗΙΟΩ]$/
218
+ end
219
+
220
+ def long_stem_list(word)
221
+ word.scan(/^(.+?)(Α|ΑΓΑΤΕ|ΑΓΑΝ|ΑΕΙ|ΑΜΑΙ|ΑΝ|ΑΣ|ΑΣΑΙ|ΑΤΑΙ|ΑΩ|Ε|ΕΙ|ΕΙΣ|ΕΙΤΕ|ΕΣΑΙ|ΕΣ|ΕΤΑΙ|Ι|ΙΕΜΑΙ|ΙΕΜΑΣΤΕ|ΙΕΤΑΙ|ΙΕΣΑΙ|ΙΕΣΑΣΤΕ|ΙΟΜΑΣΤΑΝ|ΙΟΜΟΥΝ|ΙΟΜΟΥΝΑ|ΙΟΝΤΑΝ|ΙΟΝΤΟΥΣΑΝ|ΙΟΣΑΣΤΑΝ|ΙΟΣΑΣΤΕ|ΙΟΣΟΥΝ|ΙΟΣΟΥΝΑ|ΙΟΤΑΝ|ΙΟΥΜΑ|ΙΟΥΜΑΣΤΕ|ΙΟΥΝΤΑΙ|ΙΟΥΝΤΑΝ|Η|ΗΔΕΣ|ΗΔΩΝ|ΗΘΕΙ|ΗΘΕΙΣ|ΗΘΕΙΤΕ|ΗΘΗΚΑΤΕ|ΗΘΗΚΑΝ|ΗΘΟΥΝ|ΗΘΩ|ΗΚΑΤΕ|ΗΚΑΝ|ΗΣ|ΗΣΑΝ|ΗΣΑΤΕ|ΗΣΕΙ|ΗΣΕΣ|ΗΣΟΥΝ|ΗΣΩ|Ο|ΟΙ|ΟΜΑΙ|ΟΜΑΣΤΑΝ|ΟΜΟΥΝ|ΟΜΟΥΝΑ|ΟΝΤΑΙ|ΟΝΤΑΝ|ΟΝΤΟΥΣΑΝ|ΟΣ|ΟΣΑΣΤΑΝ|ΟΣΑΣΤΕ|ΟΣΟΥΝ|ΟΣΟΥΝΑ|ΟΤΑΝ|ΟΥ|ΟΥΜΑΙ|ΟΥΜΑΣΤΕ|ΟΥΝ|ΟΥΝΤΑΙ|ΟΥΝΤΑΝ|ΟΥΣ|ΟΥΣΑΝ|ΟΥΣΑΤΕ|Υ|ΥΣ|Ω|ΩΝ|ΟΙΣ)$/u) do |st, suffix|
222
+ word = st
223
+ end
224
+ word
225
+ end
226
+
227
+ def greek?(word)
228
+ !! word.match(ALPHABET)
229
+ end
230
+ end
@@ -0,0 +1,115 @@
1
+ # step 1
2
+ ΚΡΕΑΣ: ΚΡΕ
3
+ ΠΑΝΓΚΡΕΑΣ: ΠΑΝΓΚΡΕ
4
+ ΗΜΙΦΩΣ: ΗΜΙΦΩ
5
+ ΚΟΜΠΟΛΟΓΙΑ: ΚΟΜΠΟΛΟ
6
+ ΠΑΤΕΡΑΣ: ΠΑΤΕΡ
7
+
8
+ # step 2a
9
+ ΓΙΑΓΙΑΔΩΝ: ΓΙΑΓΙ
10
+ ΟΜΑΔΕΣ: ΟΜΑΔ
11
+
12
+ # step 2b
13
+ ΚΑΦΕΔΩΝ: ΚΑΦ
14
+ ΓΗΠΕΔΩΝ: ΓΗΠΕΔ
15
+
16
+ # step 2c
17
+ ΠΑΠΠΟΥΔΩΝ: ΠΑΠΠ
18
+ ΑΡΚΟΥΔΕΣ: ΑΡΚΟΥΔ
19
+
20
+ # step 2d
21
+ ΥΠΟΘΕΣΕΩΣ: ΥΠΟΘΕΣ
22
+ ΥΠΟΘΕΣΕΩΝ: ΥΠΟΘΕΣ
23
+ ΘΕΩΝ: ΘΕ
24
+
25
+ # step 3
26
+ ΠΑΙΔΙΑ: ΠΑΙΔ
27
+ ΤΕΛΕΙΟΥ: ΤΕΛΕΙ
28
+ ΤΕΛΕΙΩΝ: ΤΕΛΕΙ
29
+
30
+ # step 4
31
+ ΖΗΛΙΑΡΙΚΟ: ΖΗΛΙΑΡ
32
+ ΑΓΡΟΙΚΟΥ: ΑΓΡΟΙΚ
33
+
34
+ # step 5
35
+ ΑΓΑΠΑΜΕ: ΑΓΑΠ
36
+ ΑΓΑΠΗΣΑΜΕ: ΑΓΑΠ
37
+ ΑΝΑΠΑΜΕ: ΑΝΑΠΑΜ
38
+
39
+ # step 5b
40
+ ΑΓΑΠΗΣΑΝΕ: ΑΓΑΠ
41
+ ΤΡΑΓΑΝΕ: ΤΡΑΓΑΝ
42
+ ΒΡΑΧΜΑΝΕ: ΒΡΑΧΜΑΝ
43
+ ΣΑΡΑΚΑΤΣΑΝΕ: ΣΑΡΑΚΑΤΣΑΝ
44
+
45
+ # step 5c
46
+ ΑΓΑΠΗΣΕΤΕ: ΑΓΑΠ
47
+ ΒΕΝΕΤΕ: ΒΕΝΕΤ
48
+
49
+ # step 5d
50
+ ΑΓΑΠΩΝΤΑΣ: ΑΓΑΠ
51
+ ΑΡΧΟΝΤΑΣ: ΑΡΧΟΝΤ
52
+ ΚΡΕΩΝΤΑΣ: ΚΡΕΩΝΤ
53
+
54
+ # step 5e
55
+ ΑΓΑΠΙΟΜΑΣΤΕ: ΑΓΑΠ
56
+ ΟΝΟΜΑΣΤΕ: ΟΝΟΜΑΣΤ
57
+
58
+ # step 5f
59
+ ΑΓΑΠΙΕΣΤΕ: ΑΓΑΠ
60
+ ΠΙΕΣΤΕ: ΠΙΕΣΤ
61
+ ΕΚΤΕΛΕΣΤΕ: ΕΚΤΕΛΕΣΤ
62
+
63
+ # step 5g
64
+ ΧΤΙΣΤΗΚΕ: ΧΤΙΣΤ
65
+ ΔΙΑΘΗΚΗ: ΔΙΑΘΗΚ
66
+ ΔΙΑΘΗΚΕΣ: ΔΙΑΘΗΚ
67
+ ΚΑΤΑΚΤΗΘΗΚΕ: ΚΑΤΑΚΤ
68
+ ΠΟΛΕΜΗΘΗΚΕ: ΠΟΛΕΜ
69
+
70
+ # step 5h
71
+ ΧΤΥΠΩ: ΧΤΥΠ
72
+ ΧΤΥΠΟΥΣΕΣ: ΧΤΥΠ
73
+ ΜΕΔΟΥΣΑ: ΜΕΔΟΥΣ
74
+ ΜΕΔΟΥΣΕΣ: ΜΕΔΟΥΣ
75
+
76
+ # step 5i
77
+ ΚΟΛΛΑΩ: ΚΟΛΛ
78
+ ΚΟΛΛΑΓΕΣ: ΚΟΛΛ
79
+ ΑΒΑΣΤΑΓΟ: ΑΒΑΣΤΑΓ
80
+ ΑΒΑΣΤΑΓΑ: ΑΒΑΣΤΑΓ
81
+
82
+ # step 5j
83
+ ΑΓΑΠΩ: ΑΓΑΠ
84
+ ΑΓΑΠΗΣΕ: ΑΓΑΠ
85
+ ΝΗΣΟΣ: ΝΗΣ
86
+ ΝΗΣΟΥ: ΝΗΣ
87
+
88
+ # step 5k
89
+ ΑΓΑΠΩ: ΑΓΑΠ
90
+ ΑΓΑΠΗΣΤΕ: ΑΓΑΠ
91
+ ΣΒΗΣΤΟΣ: ΣΒΗΣΤ
92
+ ΣΒΗΣΤΕ: ΣΒΗΣΤ
93
+
94
+ # step 5l
95
+ ΑΓΑΠΩ: ΑΓΑΠ
96
+ ΑΓΑΠΟΥΝΕ: ΑΓΑΠ
97
+ ΝΟΥΝΟΣ: ΝΟΥΝ
98
+ ΝΟΥΝΕ: ΝΟΥΝ
99
+
100
+ # step 5m
101
+ ΑΓΑΠΩ: ΑΓΑΠ
102
+ ΑΓΑΠΟΥΜΕ: ΑΓΑΠ
103
+ ΦΟΥΜΟΣ: ΦΟΥΜ
104
+ ΦΟΥΜΕ: ΦΟΥΜ
105
+
106
+ # step 6a
107
+ ΚΥΜΑ: ΚΥΜ
108
+ ΚΥΜΑΤΑ: ΚΥΜ
109
+ ΧΩΡΑΤΟ: ΧΩΡΑΤ
110
+ ΧΩΡΑΤΑ: ΧΩΡΑΤ
111
+
112
+ # step 7
113
+ ΠΛΗΣΙΕΣΤΑΤΟΣ: ΠΛΗΣΙ
114
+ ΜΕΓΑΛΥΤΕΡΗ: ΜΕΓΑΛ
115
+ ΚΟΝΤΟΤΕΡΟ: ΚΟΝΤ
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+ require 'spec_helper'
3
+ require "yaml"
4
+
5
+ describe GreekStemmer do
6
+ describe "#stem" do
7
+ let(:words) { YAML.load_file('spec/fixtures/examples.yml') }
8
+ it "stems words correctly" do
9
+ words.each_pair do |word, stem|
10
+ expect(described_class.stem(word)).to eq(stem)
11
+ end
12
+ end
13
+
14
+ context "when a non-greek word is used" do
15
+ it "does not stem it" do
16
+ expect(described_class.stem("englishΟΣ")).to eq("englishΟΣ")
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+ require "greek_stemmer"
9
+ require "pry"
10
+
11
+ RSpec.configure do |config|
12
+ config.treat_symbols_as_metadata_keys_with_true_values = true
13
+ config.run_all_when_everything_filtered = true
14
+ config.filter_run :focus
15
+
16
+ # Run specs in random order to surface order dependencies. If you find an
17
+ # order dependency and want to debug it, you can fix the order by providing
18
+ # the seed, which is printed after each run.
19
+ # --seed 1234
20
+ config.order = 'random'
21
+ end