Skip to content

Instantly share code, notes, and snippets.

@DavidAntaramian
Created November 24, 2016 01:04
Show Gist options
  • Save DavidAntaramian/317a2ff1bec962ed458b528abe7d40fc to your computer and use it in GitHub Desktop.
Save DavidAntaramian/317a2ff1bec962ed458b528abe7d40fc to your computer and use it in GitHub Desktop.
defmodule Johnann do
def john(day) when day >= 1 do
get(day, :john)
end
def ann(day) when day >= 1 do
get(day, :ann)
end
def sum_john(day) when day >= 1 do
john(day)
|> Enum.sum()
end
def sum_ann(day) when day >= 1 do
ann(day)
|> Enum.sum()
end
defp get(day, person) do
day
|> get_or_calculate()
|> Map.get(person)
|> Enum.sort()
|> Enum.map(fn {_, v} -> v end)
end
defp get_or_calculate(day) do
get_or_calculate(day, %{john: %{0 => 0}, ann: %{0 => 1}})
end
# The number of calculations have an upper-bound on the number of days
# that have been calculated for John. When the number of entries in
# John's cache are equal to or greater than the day being requested,
# there is no need for further calculation
defp get_or_calculate(day, %{john: john, ann: ann}) when map_size(john) < day do
# The number of days calculated so far
new_index = map_size(john)
previous_index = new_index - 1
johns_katas = calculate(john, ann, new_index, previous_index)
john = Map.put(john, new_index, johns_katas)
anns_katas = calculate(ann, john, new_index, previous_index)
ann = Map.put(ann, new_index, anns_katas)
get_or_calculate(day, %{ john: john, ann: ann })
end
defp get_or_calculate(_, cache) do
cache
end
defp calculate(origin, other, new_index, previous_index) do
old_index = Map.get(origin, previous_index)
new_index - Map.get(other, old_index)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment