defmodule Anagram do @doc """ Returns all candidates that are anagrams of, but not equal to, 'base'. """ @spec match(String.t(), [String.t()]) :: [String.t()] def match(base, candidates) do candidates |> Enum.filter(&anagram?(normalize(base), normalize(&1))) end defp anagram?(base, base), do: false defp anagram?(base, candidate), do: hash(base) == hash(candidate) @spec normalize(String.t()) :: String.t() defp normalize(string), do: string |> String.downcase() |> String.graphemes() @spec hash(String.t()) :: Map.t() defp hash(string) do Enum.reduce(string, %{}, fn char, acc -> Map.update(acc, char, 1, &(&1 + 1)) end) end end