defmodule Words do

  @unicode_alnum_and_hyphen ~r/[\p{L}\p{M}*0-9-]+/u

  @doc """
  Count the number of words in the sentence.

  Words are compared case-insensitively.
  """
  @spec count(String.t()) :: map
  def count(sentence) do
    sentence
    |> String.downcase
    |> tokenise_into_words
    |> get_word_count
  end

  defp tokenise_into_words(sentence) do
    @unicode_alnum_and_hyphen
    |> Regex.scan(sentence)
    |> List.flatten
  end

  defp get_word_count(words_list) do
    Enum.reduce(words_list, %{}, fn curr_word, count_map ->
      Map.update(count_map, curr_word, 1, &(&1 + 1))
    end)
  end
end