Skip to content

Instantly share code, notes, and snippets.

@tjstankus
Created November 6, 2019 22:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tjstankus/1de98b2a1e3b6e150b3b30ab982e3e34 to your computer and use it in GitHub Desktop.
Save tjstankus/1de98b2a1e3b6e150b3b30ab982e3e34 to your computer and use it in GitHub Desktop.
defmodule CountdownSong do
def song(%{upper: upper, lower: lower}, verse_template) do
verses(upper, lower, verse_template)
end
def verses(upper, lower, verse_template) do
upper..lower
|> Enum.map(fn n -> verse(n, verse_template) end)
|> Enum.join("\n")
end
def verse(num, verse_template) do
verse_template.lyrics(num)
end
end
defmodule Bottles do
defstruct upper: 99, lower: 0
end
defmodule VerseTemplate do
@callback lyrics(integer) :: String.t()
end
defmodule BottleVerse do
@behaviour VerseTemplate
@impl VerseTemplate
def lyrics(num) do
"#{bottle_number(num) |> String.capitalize()} of beer on the wall, " <>
"#{bottle_number(num)} of beer.\n" <>
"#{action(num)}, " <>
"#{successor(num) |> bottle_number()} of beer on the wall.\n"
end
def bottle_number(num) do
"#{amount(num)} #{container(num)}"
end
defp container(6), do: "six-pack"
defp container(1), do: "bottle"
defp container(_), do: "bottles"
defp pronoun(1), do: "it"
defp pronoun(_), do: "one"
defp amount(6), do: "1"
defp amount(0), do: "no more"
defp amount(num), do: "#{num}"
defp action(0), do: "Go to the store and buy some more"
defp action(num), do: "Take #{pronoun(num)} down and pass it around"
defp successor(0), do: 99
defp successor(num), do: num - 1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment