lib/algorithms/countingsort.ex

defmodule Countingsort do
  @moduledoc """
  Documentation for `Counting sort` algorithm. All important
  informations about counting sort you can find at
  [Wikipedia](https://en.wikipedia.org/wiki/Counting_sort) page.

	### Annotations
   - n - number of elements in list
   - range of the non-negative key values.
	"""

  @doc """
  Sort list
   - Normal complexity: O(n)
   - Worst complexity: O(n + k)

  ## Examples

      iex> Countingsort.run([4, 1, 3, 5, 2])
      [1, 2, 3, 4, 5]

      iex> Countingsort.run([1, 2, 4, 3])
      [1, 2, 3, 4]

  """
  @spec run(list(integer)) :: list(integer)
  def run([]), do: []

  def run(list) do
    {min, max} = Enum.min_max(list)
    # Create empty touple for each number in <min, max>
    count = Tuple.duplicate(0, max - min + 1)
    # Count the occurrences the same numbers in the list
    counted = Enum.reduce(list, count, fn item, acc ->
      index = item - min
      put_elem(acc, index, elem(acc, index) + 1)
    end)

    Enum.flat_map(min..max, &List.duplicate(&1, elem(counted, &1 - min)))
  end

end