40 lines
1.2 KiB
Elixir
40 lines
1.2 KiB
Elixir
defmodule Soundex do
|
|
def soundex([]), do: []
|
|
def soundex(str) do
|
|
[head|tail] = String.upcase(str) |> to_char_list
|
|
[head | isoundex(tail, [], todigit(head))]
|
|
end
|
|
|
|
defp isoundex([], acc, _) do
|
|
case length(acc) do
|
|
n when n == 3 -> Enum.reverse(acc)
|
|
n when n < 3 -> isoundex([], [?0 | acc], :ignore)
|
|
n when n > 3 -> isoundex([], Enum.slice(acc, n-3, n), :ignore)
|
|
end
|
|
end
|
|
defp isoundex([head|tail], acc, lastn) do
|
|
dig = todigit(head)
|
|
if dig != ?0 and dig != lastn do
|
|
isoundex(tail, [dig | acc], dig)
|
|
else
|
|
case head do
|
|
?H -> isoundex(tail, acc, lastn)
|
|
?W -> isoundex(tail, acc, lastn)
|
|
n when n in ?A..?Z -> isoundex(tail, acc, dig)
|
|
_ -> isoundex(tail, acc, lastn) # This clause handles non alpha characters
|
|
end
|
|
end
|
|
end
|
|
|
|
@digits '01230120022455012623010202'
|
|
defp todigit(chr) do
|
|
if chr in ?A..?Z, do: Enum.at(@digits, chr - ?A),
|
|
else: ?0 # Treat non alpha characters as a vowel
|
|
end
|
|
end
|
|
|
|
IO.puts Soundex.soundex("Soundex")
|
|
IO.puts Soundex.soundex("Example")
|
|
IO.puts Soundex.soundex("Sownteks")
|
|
IO.puts Soundex.soundex("Ekzampul")
|