 defmodule BookStore do
-  use Agent
   @type book :: integer
 
   @base_price 800

  def discounts([n]), do: [n * @base_price]

  def discounts(frequencies) do
    cached = Agent.get(:discount, &Map.get(&1, frequencies))

    if cached do
      cached
    else
      discount =
        for num_books <- 2..5,
            {picked, left} <- pick_n_distinct_from(num_books, frequencies),
            remove_picked = picked |> Enum.map(&(&1 - 1)) |> Enum.reject(&(&1 == 0)),
            costs <- discounts(Enum.sort(remove_picked ++ left)),
            do: costs + num_books * @discount[num_books]

      Agent.update(:discount, &Map.put(&1, frequencies, discount))
      discount
    end
  end

  def pick_n_distinct_from(n, list) when length(list) < n, do: %{}


  def frequencies(list) do
    list
    |> Enum.reduce(%{}, &Map.update(&2, &1, 1, fn count -> count + 1 end))
    |> Map.values()
  end

