phonetic 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +98 -0
  7. data/Rakefile +1 -0
  8. data/lib/phonetic.rb +10 -0
  9. data/lib/phonetic/algorithm.rb +24 -0
  10. data/lib/phonetic/caverphone.rb +68 -0
  11. data/lib/phonetic/caverphone2.rb +69 -0
  12. data/lib/phonetic/core_ext/string.rb +3 -0
  13. data/lib/phonetic/core_ext/string/caverphone.rb +11 -0
  14. data/lib/phonetic/core_ext/string/caverphone2.rb +11 -0
  15. data/lib/phonetic/core_ext/string/double_metaphone.rb +18 -0
  16. data/lib/phonetic/core_ext/string/metaphone.rb +12 -0
  17. data/lib/phonetic/core_ext/string/nysiis.rb +12 -0
  18. data/lib/phonetic/core_ext/string/refined_soundex.rb +12 -0
  19. data/lib/phonetic/core_ext/string/soundex.rb +12 -0
  20. data/lib/phonetic/double_metaphone.rb +640 -0
  21. data/lib/phonetic/metaphone.rb +161 -0
  22. data/lib/phonetic/metaphone2.rb +5 -0
  23. data/lib/phonetic/nysiis.rb +63 -0
  24. data/lib/phonetic/refined_soundex.rb +39 -0
  25. data/lib/phonetic/soundex.rb +39 -0
  26. data/lib/phonetic/version.rb +3 -0
  27. data/phonetic.gemspec +26 -0
  28. data/spec/phonetic/algorithm_spec.rb +15 -0
  29. data/spec/phonetic/caverphone2_spec.rb +66 -0
  30. data/spec/phonetic/caverphone_spec.rb +115 -0
  31. data/spec/phonetic/core_ext/string/caverphone2_spec.rb +9 -0
  32. data/spec/phonetic/core_ext/string/caverphone_spec.rb +9 -0
  33. data/spec/phonetic/core_ext/string/double_metaphone_spec.rb +15 -0
  34. data/spec/phonetic/core_ext/string/metaphone_spec.rb +11 -0
  35. data/spec/phonetic/core_ext/string/nysiis_spec.rb +12 -0
  36. data/spec/phonetic/core_ext/string/refined_soundex_spec.rb +10 -0
  37. data/spec/phonetic/core_ext/string/soundex_spec.rb +14 -0
  38. data/spec/phonetic/double_metaphone_spec.rb +16 -0
  39. data/spec/phonetic/metaphone2_spec.rb +9 -0
  40. data/spec/phonetic/metaphone_spec.rb +81 -0
  41. data/spec/phonetic/nysiis_spec.rb +20 -0
  42. data/spec/phonetic/refined_soundex_spec.rb +13 -0
  43. data/spec/phonetic/soundex_spec.rb +24 -0
  44. data/spec/spec_helper.rb +11 -0
  45. data/spec/support/double_metaphone_data.rb +142 -0
  46. data/spec/support/nysiis_data.rb +31 -0
  47. 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,5 @@
1
+ require 'phonetic/double_metaphone'
2
+
3
+ module Phonetic
4
+ Metaphone2 = DoubleMetaphone
5
+ 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
@@ -0,0 +1,3 @@
1
+ module Phonetic
2
+ VERSION = '1.0.0'
3
+ end
@@ -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