Skip to content

Instantly share code, notes, and snippets.

@ivan3bx
Created April 20, 2019 20:01
Show Gist options
  • Save ivan3bx/e21ee7eee834314c71daa4cae6653554 to your computer and use it in GitHub Desktop.
Save ivan3bx/e21ee7eee834314c71daa4cae6653554 to your computer and use it in GitHub Desktop.
implementing the soundex algorithm for fun
require 'minitest/autorun'
require 'text'
# An exercise to implement the 'soundex' algorithm
#
# See https://en.wikipedia.org/wiki/Soundex for details
#
# Compare with 'text' gem impl: https://github.com/threedaymonk/text/blob/master/lib/text/soundex.rb
class Soundex
def process(input)
return nil unless input.is_a?(String)
return nil unless input =~ /^[A-Za-z]/
input = input.downcase.gsub(/hw/, '').split('')
result = input.each_with_object("") do |letter, acc|
case letter
when /[aeiouy]/
acc << '0' # insert vowel spacer
when /[bfpv]/
acc << '1'
when /[cgjkqsxz]/
acc << '2'
when /[dt]/
acc << '3'
when /[l]/
acc << '4'
when /[mn]/
acc << '5'
when /[r]/
acc << '6'
end
end
# Rule #3 (remove duplicate numbers including first position)
result.gsub!(/(\d)\1/, '\\1')
# Place first letter of input in first position
result[0] = input[0].upcase
# Remove any vowel spacers
result.delete!('0')
# Return four character representation (first letter + 3 numbers)
result.ljust(4, '0')[0, 4]
end
end
class TestSoundex < Minitest::Test
def setup
@soundex = Soundex.new
end
def test_non_words
assert_nil @soundex.process(nil)
assert_nil @soundex.process('')
assert_nil @soundex.process('123')
end
def test_short_words
assert_equal 'A000', @soundex.process('a')
assert_equal 'A500', @soundex.process('am')
end
def test_words
assert_equal 'F623', @soundex.process('first')
assert_equal 'T623', @soundex.process('thirst')
assert_equal 'W623', @soundex.process('worst')
assert_equal 'C623', @soundex.process('cursed')
end
def test_hw_rule
assert_equal 'A261', @soundex.process('Ashcroft')
assert_equal 'A261', @soundex.process('Ashcraft')
end
def test_tricky_words
assert_equal 'T522', @soundex.process('Tymczak')
assert_equal 'P236', @soundex.process('Pfister')
assert_equal 'H555', @soundex.process('Honeymoon')
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment