phonetic 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +98 -0
- data/Rakefile +1 -0
- data/lib/phonetic.rb +10 -0
- data/lib/phonetic/algorithm.rb +24 -0
- data/lib/phonetic/caverphone.rb +68 -0
- data/lib/phonetic/caverphone2.rb +69 -0
- data/lib/phonetic/core_ext/string.rb +3 -0
- data/lib/phonetic/core_ext/string/caverphone.rb +11 -0
- data/lib/phonetic/core_ext/string/caverphone2.rb +11 -0
- data/lib/phonetic/core_ext/string/double_metaphone.rb +18 -0
- data/lib/phonetic/core_ext/string/metaphone.rb +12 -0
- data/lib/phonetic/core_ext/string/nysiis.rb +12 -0
- data/lib/phonetic/core_ext/string/refined_soundex.rb +12 -0
- data/lib/phonetic/core_ext/string/soundex.rb +12 -0
- data/lib/phonetic/double_metaphone.rb +640 -0
- data/lib/phonetic/metaphone.rb +161 -0
- data/lib/phonetic/metaphone2.rb +5 -0
- data/lib/phonetic/nysiis.rb +63 -0
- data/lib/phonetic/refined_soundex.rb +39 -0
- data/lib/phonetic/soundex.rb +39 -0
- data/lib/phonetic/version.rb +3 -0
- data/phonetic.gemspec +26 -0
- data/spec/phonetic/algorithm_spec.rb +15 -0
- data/spec/phonetic/caverphone2_spec.rb +66 -0
- data/spec/phonetic/caverphone_spec.rb +115 -0
- data/spec/phonetic/core_ext/string/caverphone2_spec.rb +9 -0
- data/spec/phonetic/core_ext/string/caverphone_spec.rb +9 -0
- data/spec/phonetic/core_ext/string/double_metaphone_spec.rb +15 -0
- data/spec/phonetic/core_ext/string/metaphone_spec.rb +11 -0
- data/spec/phonetic/core_ext/string/nysiis_spec.rb +12 -0
- data/spec/phonetic/core_ext/string/refined_soundex_spec.rb +10 -0
- data/spec/phonetic/core_ext/string/soundex_spec.rb +14 -0
- data/spec/phonetic/double_metaphone_spec.rb +16 -0
- data/spec/phonetic/metaphone2_spec.rb +9 -0
- data/spec/phonetic/metaphone_spec.rb +81 -0
- data/spec/phonetic/nysiis_spec.rb +20 -0
- data/spec/phonetic/refined_soundex_spec.rb +13 -0
- data/spec/phonetic/soundex_spec.rb +24 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/double_metaphone_data.rb +142 -0
- data/spec/support/nysiis_data.rb +31 -0
- metadata +180 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'phonetic/algorithm'
|
2
|
+
|
3
|
+
module Phonetic
|
4
|
+
# Metaphone is a phonetic algorithm, published by Lawrence Philips in 1990,
|
5
|
+
# for indexing words by their English pronunciation.
|
6
|
+
# This class implements this algorithm.
|
7
|
+
# @see http://aspell.net/metaphone/metaphone.basic Original Basic code by Lawrence Philips (1990)
|
8
|
+
# @example
|
9
|
+
# Phonetic::Metaphone.encode('Accola') # => 'AKKL'
|
10
|
+
# Phonetic::Metaphone.encode('Nikki') # => 'NK'
|
11
|
+
# Phonetic::Metaphone.encode('Wright') #=> 'RT'
|
12
|
+
class Metaphone < Algorithm
|
13
|
+
VOWELS = 'AEIOU'
|
14
|
+
FRONT_VOWELS = 'EIY'
|
15
|
+
VARSON = 'CSPTG'
|
16
|
+
|
17
|
+
# Encode word to its Metaphone code
|
18
|
+
def self.encode_word(word, options = { size: 4 })
|
19
|
+
code_size = options[:size] || 4
|
20
|
+
w = word.upcase.gsub(/[^A-Z]/, '')
|
21
|
+
return if w.empty?
|
22
|
+
two = w[0, 2]
|
23
|
+
if ['PN', 'AE', 'KN', 'GN', 'WR'].include?(two) then w[0] = '' end
|
24
|
+
if w[0] == 'X' then w[0] = 'S' end
|
25
|
+
if two == 'WH' then w[1] = '' end
|
26
|
+
l = w.size
|
27
|
+
metaph = ''
|
28
|
+
for n in 0..(l - 1)
|
29
|
+
break unless metaph.size < code_size
|
30
|
+
symb = w[n]
|
31
|
+
if !(symb != 'C' && n > 0 && w[n - 1] == symb)
|
32
|
+
case
|
33
|
+
when vowel?(symb) && n == 0
|
34
|
+
metaph = symb
|
35
|
+
when symb == 'B'
|
36
|
+
unless n == l - 1 && w[n - 1] == 'M'
|
37
|
+
metaph = metaph + symb
|
38
|
+
end
|
39
|
+
when symb == 'C'
|
40
|
+
if !(n > 0 && w[n - 1] == 'S' && front_vowel?(w[n + 1]))
|
41
|
+
if w[n + 1, 2] == 'IA'
|
42
|
+
metaph = metaph + 'X'
|
43
|
+
else
|
44
|
+
if front_vowel?(w[n + 1])
|
45
|
+
metaph = metaph + 'S'
|
46
|
+
else
|
47
|
+
if n > 0 && w[n + 1] == 'H' && w[n - 1] == 'S'
|
48
|
+
metaph = metaph + 'K'
|
49
|
+
else
|
50
|
+
if w[n + 1] == 'H'
|
51
|
+
if n == 0 && !vowel?(w[n + 2])
|
52
|
+
metaph = metaph + 'K'
|
53
|
+
else
|
54
|
+
metaph = metaph + 'X'
|
55
|
+
end
|
56
|
+
else
|
57
|
+
metaph = metaph + 'K'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
when symb == 'D'
|
64
|
+
if w[n + 1] == 'G' && front_vowel?(w[n + 2])
|
65
|
+
metaph = metaph + 'J'
|
66
|
+
else
|
67
|
+
metaph = metaph + 'T'
|
68
|
+
end
|
69
|
+
when symb == 'G'
|
70
|
+
silent = (w[n + 1] == 'H' && !vowel?(w[n + 2]))
|
71
|
+
if n > 0 && (w[n + 1] == 'N' || w[n + 1, 3] == 'NED')
|
72
|
+
silent = true
|
73
|
+
end
|
74
|
+
if n > 0 && w[n - 1] == 'D' && front_vowel?(w[n + 1])
|
75
|
+
silent = true
|
76
|
+
end
|
77
|
+
hard = (n > 0 && w[n - 1] == 'G')
|
78
|
+
unless silent
|
79
|
+
if front_vowel?(w[n + 1]) && !hard
|
80
|
+
metaph = metaph + 'J'
|
81
|
+
else
|
82
|
+
metaph = metaph + 'K'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
when symb == 'H'
|
86
|
+
if !(n == l - 1 || (n > 0 && VARSON[w[n - 1]]))
|
87
|
+
if vowel?(w[n + 1])
|
88
|
+
metaph = metaph + 'H'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
when 'FJLMNR'[symb]
|
92
|
+
metaph = metaph + symb
|
93
|
+
when symb == 'K'
|
94
|
+
if n > 0 && w[n - 1] != 'C'
|
95
|
+
metaph = metaph + 'K'
|
96
|
+
else
|
97
|
+
if n == 0
|
98
|
+
metaph = 'K'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
when symb == 'P'
|
102
|
+
if w[n + 1] == 'H'
|
103
|
+
metaph = metaph + 'F'
|
104
|
+
else
|
105
|
+
metaph = metaph + 'P'
|
106
|
+
end
|
107
|
+
when symb == 'Q'
|
108
|
+
metaph = metaph + 'K'
|
109
|
+
when symb == 'S'
|
110
|
+
if w[n + 1] == 'I' && (w[n + 2] == 'O' || w[n + 2] == 'A')
|
111
|
+
metaph += 'X'
|
112
|
+
else
|
113
|
+
if w[n + 1] == 'H'
|
114
|
+
metaph += 'X'
|
115
|
+
else
|
116
|
+
metaph += 'S'
|
117
|
+
end
|
118
|
+
end
|
119
|
+
when symb == 'T'
|
120
|
+
if w[n + 1] == 'I' && (w[n + 2] == 'O' || w[n + 2] == 'A')
|
121
|
+
metaph = metaph + 'X'
|
122
|
+
else
|
123
|
+
if w[n + 1] == 'H'
|
124
|
+
if !(n > 0 && w[n - 1] == 'T')
|
125
|
+
metaph = metaph + '0'
|
126
|
+
end
|
127
|
+
else
|
128
|
+
if !(w[n + 1] == 'C' && w[n + 2] == 'H')
|
129
|
+
metaph = metaph + 'T'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
when symb == 'V'
|
134
|
+
metaph = metaph + 'F'
|
135
|
+
when symb == 'W' || symb == 'Y'
|
136
|
+
if vowel?(w[n + 1])
|
137
|
+
metaph = metaph + symb
|
138
|
+
end
|
139
|
+
when symb == 'X'
|
140
|
+
metaph = metaph + 'KS'
|
141
|
+
when symb == 'Z'
|
142
|
+
metaph = metaph + 'S'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
metaph
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def self.vowel?(symbol)
|
152
|
+
v = VOWELS[symbol.to_s]
|
153
|
+
!v.nil? && !v.empty?
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.front_vowel?(symbol)
|
157
|
+
v = FRONT_VOWELS[symbol.to_s]
|
158
|
+
!v.nil? && !v.empty?
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'phonetic/algorithm'
|
2
|
+
|
3
|
+
module Phonetic
|
4
|
+
# This class implements original version of NYSIIS algorithm.
|
5
|
+
# @example
|
6
|
+
# Phonetic::NYSIIS.encode('Alexandra') # => 'ALAXANDR'
|
7
|
+
# Phonetic::NYSIIS.encode('Aumont') # => 'AANAD'
|
8
|
+
# Phonetic::NYSIIS.encode('Bonnie') # => 'BANY'
|
9
|
+
class NYSIIS < Algorithm
|
10
|
+
FIRST_CHAR_TABLE = {
|
11
|
+
/^MAC/ => 'MCC',
|
12
|
+
/^KN/ => 'NN',
|
13
|
+
/^K/ => 'C',
|
14
|
+
/^(PH|PF)/ => 'FF',
|
15
|
+
/^SCH/ => 'SSS'
|
16
|
+
}
|
17
|
+
|
18
|
+
LAST_CHAR_TABLE = {
|
19
|
+
/(EE|IE)$/ => 'Y',
|
20
|
+
/(DT|RT|RD|NT|ND)$/ => 'D'
|
21
|
+
}
|
22
|
+
|
23
|
+
REMAINING_TABLE = {
|
24
|
+
'EV' => 'AF',
|
25
|
+
/[AEIOU]+/ => 'A',
|
26
|
+
'Q' => 'G',
|
27
|
+
'Z' => 'S',
|
28
|
+
'M' => 'N',
|
29
|
+
'KN' => 'N',
|
30
|
+
'K' => 'C',
|
31
|
+
'SCH' => 'SSS',
|
32
|
+
'PH' => 'FF',
|
33
|
+
/([^AEIOU])H/ => '\1',
|
34
|
+
/(.)H[^AEIOU]/ => '\1',
|
35
|
+
/[AEIOU]W/ => 'A'
|
36
|
+
}
|
37
|
+
|
38
|
+
LAST_TABLE = {
|
39
|
+
/S$/ => '',
|
40
|
+
/AY$/ => 'Y',
|
41
|
+
/A$/ => ''
|
42
|
+
}
|
43
|
+
|
44
|
+
# Convert word to its NYSIIS code
|
45
|
+
def self.encode_word(word, options = { trim: true })
|
46
|
+
return if !word or word.empty?
|
47
|
+
trim = options[:trim]
|
48
|
+
w = word.upcase
|
49
|
+
w.gsub!(/[^A-Z]/, '')
|
50
|
+
return if w.empty?
|
51
|
+
FIRST_CHAR_TABLE.each{ |rx, str| break if w.sub!(rx, str) }
|
52
|
+
LAST_CHAR_TABLE.each{ |rx, str| w.sub!(rx, str) }
|
53
|
+
first = w[0]
|
54
|
+
w = w[1...w.size].to_s
|
55
|
+
REMAINING_TABLE.each{ |rx, str| w.gsub!(rx, str) }
|
56
|
+
LAST_TABLE.each{ |rx, str| w.gsub!(rx, str) }
|
57
|
+
w.gsub!(/[^\w\s]|(.)(?=\1)/, '') # remove duplicates
|
58
|
+
w = first + w
|
59
|
+
w = w[0..5] if trim
|
60
|
+
w
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'phonetic/algorithm'
|
2
|
+
|
3
|
+
module Phonetic
|
4
|
+
# Class for encoding string to Refined Soundex code.
|
5
|
+
# A refined soundex code is optimized for spell checking words.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# Phonetic::RefinedSoundex.encode('Caren') # => 'C30908'
|
9
|
+
# Phonetic::RefinedSoundex.encode('Hayers') # => 'H093'
|
10
|
+
# Phonetic::RefinedSoundex.encode('Lambard') # => 'L7081096'
|
11
|
+
class RefinedSoundex < Algorithm
|
12
|
+
CODE = {
|
13
|
+
B: 1, P: 1,
|
14
|
+
F: 2, V: 2,
|
15
|
+
C: 3, K: 3, S: 3,
|
16
|
+
G: 4, J: 4,
|
17
|
+
Q: 5, X: 5, Z: 5,
|
18
|
+
D: 6, T: 6,
|
19
|
+
L: 7,
|
20
|
+
M: 8, N: 8,
|
21
|
+
R: 9
|
22
|
+
}
|
23
|
+
|
24
|
+
# Encode word to its Refined Soundex value
|
25
|
+
def self.encode_word(word, options = {})
|
26
|
+
w = word.upcase
|
27
|
+
res = w[0]
|
28
|
+
pg = nil
|
29
|
+
w.chars.each do |c|
|
30
|
+
g = CODE[c.to_sym] || 0
|
31
|
+
if pg != g
|
32
|
+
res += g.to_s
|
33
|
+
pg = g
|
34
|
+
end
|
35
|
+
end
|
36
|
+
res
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'phonetic/algorithm'
|
2
|
+
|
3
|
+
module Phonetic
|
4
|
+
# Soundex phonetic algorithm was developed by Robert C. Russell and Margaret K. Odell.
|
5
|
+
# This class implements American Soundex version of algorithm.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# Phonetic::Soundex.encode('Ackerman') # => 'A265'
|
9
|
+
# Phonetic::Soundex.encode('ammonium') # => 'A500'
|
10
|
+
# Phonetic::Soundex.encode('implementation') # => 'I514'
|
11
|
+
class Soundex < Algorithm
|
12
|
+
CODE = {
|
13
|
+
B: 1, P: 1, F: 1, V: 1,
|
14
|
+
C: 2, S: 2, K: 2, G: 2, J: 2, Q: 2, X: 2, Z: 2,
|
15
|
+
D: 3, T: 3,
|
16
|
+
L: 4,
|
17
|
+
M: 5, N: 5,
|
18
|
+
R: 6
|
19
|
+
}
|
20
|
+
|
21
|
+
# Convert word to its Soundex code
|
22
|
+
def self.encode_word(word, options = {})
|
23
|
+
return '' if word.empty?
|
24
|
+
w = word.upcase
|
25
|
+
res = w[0]
|
26
|
+
pg = CODE[w[0].to_sym]
|
27
|
+
(1...w.size).each do |i|
|
28
|
+
g = CODE[w[i].to_sym]
|
29
|
+
if g and pg != g
|
30
|
+
res += g.to_s
|
31
|
+
pg = g
|
32
|
+
end
|
33
|
+
break if res.size > 3
|
34
|
+
end
|
35
|
+
res = res.ljust(4, '0')
|
36
|
+
res
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/phonetic.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'phonetic/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'phonetic'
|
8
|
+
spec.version = Phonetic::VERSION
|
9
|
+
spec.authors = ['n7v']
|
10
|
+
spec.email = ['novsem@gmail.com']
|
11
|
+
spec.description = %q{Ruby library for phonetic algorithms.}
|
12
|
+
spec.summary = %q{Ruby library for phonetic algorithms. It supports Soundex, Metaphone, Caverphone, NYSIIS and others}
|
13
|
+
spec.homepage = 'http://github.com/n7v/phonetic'
|
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', '~> 1.3'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'rspec'
|
24
|
+
spec.add_development_dependency 'simplecov'
|
25
|
+
spec.add_development_dependency 'yard'
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Phonetic::Algorithm do
|
4
|
+
describe '.encode_word' do
|
5
|
+
it 'should return not modified word' do
|
6
|
+
Phonetic::Algorithm.encode_word('cat').should == 'cat'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.encode' do
|
11
|
+
it 'should return list of words without extra spaces' do
|
12
|
+
Phonetic::Algorithm.encode(' cat dog ').should == 'cat dog'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Examples are taken from Caversham Project's paper
|
4
|
+
# http://caversham.otago.ac.nz/files/working/ctp150804.pdf
|
5
|
+
CAVERPHONE2_TEST_TABLE = {
|
6
|
+
'STFNSN1111' => ['Stevenson'],
|
7
|
+
'PTA1111111' => ['Peter'],
|
8
|
+
'AT11111111' => [
|
9
|
+
'add', 'aid', 'at', 'art', 'eat', 'earth', 'head', 'hit', 'hot',
|
10
|
+
'hold', 'hard', 'heart', 'it', 'out', 'old'
|
11
|
+
],
|
12
|
+
'RTA1111111' => ['rather', 'ready', 'writer'],
|
13
|
+
'SSA1111111' => ['social'],
|
14
|
+
'APA1111111' => ['able', 'appear'],
|
15
|
+
'TTA1111111' => [
|
16
|
+
'Darda', 'Datha', 'Dedie', 'Deedee', 'Deerdre', 'Deidre', 'Deirdre',
|
17
|
+
'Detta', 'Didi', 'Didier', 'Dido', 'Dierdre', 'Dieter', 'Dita',
|
18
|
+
'Ditter', 'Dodi', 'Dodie', 'Dody', 'Doherty', 'Dorthea', 'Dorthy',
|
19
|
+
'Doti', 'Dotti', 'Dottie', 'Dotty', 'Doty', 'Doughty', 'Douty',
|
20
|
+
'Dowdell', 'Duthie', 'Tada', 'Taddeo', 'Tadeo', 'Tadio', 'Tati',
|
21
|
+
'Teador', 'Tedda', 'Tedder', 'Teddi', 'Teddie', 'Teddy', 'Tedi',
|
22
|
+
'Tedie', 'Teeter', 'Teodoor', 'Teodor', 'Terti', 'Theda', 'Theodor',
|
23
|
+
'Theodore', 'Theta', 'Thilda', 'Thordia', 'Tilda', 'Tildi', 'Tildie',
|
24
|
+
'Tildy', 'Tita', 'Tito', 'Tjader', 'Toddie', 'Toddy', 'Torto', 'Tuddor',
|
25
|
+
'Tudor', 'Turtle', 'Tuttle', 'Tutto'
|
26
|
+
],
|
27
|
+
'KLN1111111' => [
|
28
|
+
'Cailean', 'Calan', 'Calen', 'Callahan', 'Callan', 'Callean',
|
29
|
+
'Carleen', 'Carlen', 'Carlene', 'Carlin', 'Carline', 'Carlyn',
|
30
|
+
'Carlynn', 'Carlynne', 'Charlean', 'Charleen', 'Charlene',
|
31
|
+
'Charline', 'Cherlyn', 'Chirlin', 'Clein', 'Cleon', 'Cline',
|
32
|
+
'Cohleen', 'Colan', 'Coleen', 'Colene', 'Colin', 'Colleen',
|
33
|
+
'Collen', 'Collin', 'Colline', 'Colon', 'Cullan', 'Cullen',
|
34
|
+
'Cullin', 'Gaelan', 'Galan', 'Galen', 'Garlan', 'Garlen',
|
35
|
+
'Gaulin', 'Gayleen', 'Gaylene', 'Giliane', 'Gillan', 'Gillian',
|
36
|
+
'Glen', 'Glenn', 'Glyn', 'Glynn', 'Gollin', 'Gorlin', 'Kalin',
|
37
|
+
'Karlan', 'Karleen', 'Karlen', 'Karlene', 'Karlin', 'Karlyn',
|
38
|
+
'Kaylyn', 'Keelin', 'Kellen', 'Kellene', 'Kellyann', 'Kellyn',
|
39
|
+
'Khalin', 'Kilan', 'Kilian', 'Killen', 'Killian', 'Killion',
|
40
|
+
'Klein', 'Kleon', 'Kline', 'Koerlin', 'Kylen', 'Kylynn', 'Quillan',
|
41
|
+
'Quillon', 'Qulllon', 'Xylon'
|
42
|
+
],
|
43
|
+
'TN11111111' => [
|
44
|
+
'Dan', 'Dane', 'Dann', 'Darn', 'Daune', 'Dawn', 'Ddene', 'Dean', 'Deane',
|
45
|
+
'Deanne', 'DeeAnn', 'Deeann', 'Deeanne', 'Deeyn', 'Den', 'Dene', 'Denn',
|
46
|
+
'Deonne', 'Diahann', 'Dian', 'Diane', 'Diann', 'Dianne', 'Diannne', 'Dine',
|
47
|
+
'Dion', 'Dione', 'Dionne', 'Doane', 'Doehne', 'Don', 'Donn', 'Doone', 'Dorn',
|
48
|
+
'Down', 'Downe', 'Duane', 'Dun', 'Dunn', 'Duyne', 'Dyan', 'Dyane', 'Dyann',
|
49
|
+
'Dyanne', 'Dyun', 'Tan', 'Tann', 'Teahan', 'Ten', 'Tenn', 'Terhune', 'Thain',
|
50
|
+
'Thaine', 'Thane', 'Thanh', 'Thayne', 'Theone', 'Thin', 'Thorn', 'Thorne',
|
51
|
+
'Thun', 'Thynne', 'Tien', 'Tine', 'Tjon', 'Town', 'Towne', 'Turne', 'Tyne'
|
52
|
+
]
|
53
|
+
}
|
54
|
+
|
55
|
+
describe Phonetic::Caverphone2 do
|
56
|
+
describe '.encode' do
|
57
|
+
it 'should return Caverphone 2 value of string' do
|
58
|
+
CAVERPHONE2_TEST_TABLE.each do |code, words|
|
59
|
+
words.each do |word|
|
60
|
+
res = Phonetic::Caverphone2.encode(word)
|
61
|
+
res.should eq(code), "expected: #{code}\ngot: #{res}\nword: #{word}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
CAVERPHONE_TEST_TABLE = {
|
4
|
+
'Addis' => 'ATS111',
|
5
|
+
'Alcantara' => 'AKNTR1',
|
6
|
+
'Allegra' => 'ALKR11',
|
7
|
+
'Allende' => 'ALNT11',
|
8
|
+
'America' => 'AMRK11',
|
9
|
+
'Andera' => 'ANTR11',
|
10
|
+
'Annamarie' => 'ANMR11',
|
11
|
+
'Anya' => 'ANY111',
|
12
|
+
'Ariane' => 'ARN111',
|
13
|
+
'Arnoldo' => 'ANT111',
|
14
|
+
'Beltran' => 'PTRN11',
|
15
|
+
'Blanch' => 'PLNK11',
|
16
|
+
'Blose' => 'PLS111',
|
17
|
+
'Bodie' => 'PT1111',
|
18
|
+
'Celentano' => 'SLNTN1',
|
19
|
+
'Celestine' => 'SLSTN1',
|
20
|
+
'Charmain' => 'KMN111',
|
21
|
+
'Chelsea' => 'KS1111',
|
22
|
+
'Coleman' => 'KLMN11',
|
23
|
+
'Collis' => 'KLS111',
|
24
|
+
'Crysta' => 'KRST11',
|
25
|
+
'Culwell' => 'KW1111',
|
26
|
+
'Dilworth' => 'TWT111',
|
27
|
+
'Dinkins' => 'TNKNS1',
|
28
|
+
'Donetta' => 'TNT111',
|
29
|
+
'Dreama' => 'TRM111',
|
30
|
+
'Dulce' => 'TS1111',
|
31
|
+
'Eastwood' => 'ASTWT1',
|
32
|
+
'Eddy' => 'AT1111',
|
33
|
+
'Ellett' => 'ALT111',
|
34
|
+
'Fazekas' => 'FSKS11',
|
35
|
+
'Francesco' => 'FRNSSK',
|
36
|
+
'Gary' => 'KR1111',
|
37
|
+
'Genoveva' => 'KNFF11',
|
38
|
+
'Gossman' => 'KSMN11',
|
39
|
+
'Goudy' => 'KT1111',
|
40
|
+
'Greta' => 'KRT111',
|
41
|
+
'Gunn' => 'KN1111',
|
42
|
+
'Hackman' => 'AKMN11',
|
43
|
+
'Hassie' => 'AS1111',
|
44
|
+
'Henrietta' => 'ANRT11',
|
45
|
+
'Hollaway' => 'ALW111',
|
46
|
+
'Hulbert' => 'APT111',
|
47
|
+
'Isaacson' => 'ASKSN1',
|
48
|
+
'Ishibashi' => 'ASPS11',
|
49
|
+
'Isreal' => 'ASR111',
|
50
|
+
'Jerez' => 'YRS111',
|
51
|
+
'Joette' => 'YT1111',
|
52
|
+
'Jonathon' => 'YNTN11',
|
53
|
+
'Karin' => 'KRN111',
|
54
|
+
'Kenneth' => 'KNT111',
|
55
|
+
'Koontz' => 'KNTS11',
|
56
|
+
'Korey' => 'KR1111',
|
57
|
+
'Krystle' => 'KRSTL1',
|
58
|
+
'Landey' => 'LNT111',
|
59
|
+
'Lashaunda' => 'LSNT11',
|
60
|
+
'Legere' => 'LKR111',
|
61
|
+
'Lela' => 'LL1111',
|
62
|
+
'Louis' => 'LS1111',
|
63
|
+
'Lovely' => 'LFL111',
|
64
|
+
'Lozano' => 'LSN111',
|
65
|
+
'Margo' => 'MK1111',
|
66
|
+
'Maricle' => 'MRKL11',
|
67
|
+
'Mario' => 'MR1111',
|
68
|
+
'Mccormick' => 'MKMK11',
|
69
|
+
'Melody' => 'MLT111',
|
70
|
+
'Mike' => 'MK1111',
|
71
|
+
'Milagros' => 'MLKRS1',
|
72
|
+
'Modesto' => 'MTST11',
|
73
|
+
'Mor' => 'M11111',
|
74
|
+
'Muse' => 'MS1111',
|
75
|
+
'Neil' => 'N11111',
|
76
|
+
'Nicolas' => 'NKLS11',
|
77
|
+
'Olney' => 'AN1111',
|
78
|
+
'Pannell' => 'PN1111',
|
79
|
+
'Posada' => 'PST111',
|
80
|
+
'Raeann' => 'RN1111',
|
81
|
+
'Rameau' => 'RM1111',
|
82
|
+
'Regal' => 'RK1111',
|
83
|
+
'Renetta' => 'RNT111',
|
84
|
+
'Sachiko' => 'SKK111',
|
85
|
+
'Samira' => 'SMR111',
|
86
|
+
'Sammie' => 'SM1111',
|
87
|
+
'Sara' => 'SR1111',
|
88
|
+
'Searcy' => 'SS1111',
|
89
|
+
'Seeley' => 'SL1111',
|
90
|
+
'Shannon' => 'SNN111',
|
91
|
+
'Siegmund' => 'SKMNT1',
|
92
|
+
'Silvera' => 'SFR111',
|
93
|
+
'Sitz' => 'STS111',
|
94
|
+
'Smyth' => 'SMT111',
|
95
|
+
'Steedley' => 'STTL11',
|
96
|
+
'Teri' => 'TR1111',
|
97
|
+
'Tourville' => 'TFL111',
|
98
|
+
'Ute' => 'AT1111',
|
99
|
+
'Vernon' => 'FNN111',
|
100
|
+
'Vidaurri' => 'FTR111',
|
101
|
+
'Wolff' => 'WF1111',
|
102
|
+
'Zeck' => 'SK1111',
|
103
|
+
'Zirkind' => 'SKNT11'
|
104
|
+
}
|
105
|
+
|
106
|
+
describe Phonetic::Caverphone do
|
107
|
+
describe '.encode' do
|
108
|
+
it 'should return Caverphone value of string' do
|
109
|
+
CAVERPHONE_TEST_TABLE.each do |word, code|
|
110
|
+
res = Phonetic::Caverphone.encode(word)
|
111
|
+
res.should eq(code), "expected: #{code}\ngot: #{res}\nword: #{word}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|