Skip to content

Instantly share code, notes, and snippets.

@bcaccinolo
Last active July 6, 2017 15:29
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 bcaccinolo/0205d4f4b0a8337303a98da273228309 to your computer and use it in GitHub Desktop.
Save bcaccinolo/0205d4f4b0a8337303a98da273228309 to your computer and use it in GitHub Desktop.
My Elixir bowling kata implementation (presentation of the problem: http://codingdojo.org/kata/Bowling/)
defmodule Bowling do
def score rolls do
calculate 1, rolls
end
def calculate i, list do
if i > 10 do
0
else
case calculate_frame_score(list) do
{:strike, score} -> score + calculate(i+1, Enum.slice(list, 1, 20))
{:spare , score} -> score + calculate(i+1, Enum.slice(list, 2, 20))
{:normal, score} -> score + calculate(i+1, Enum.slice(list, 2, 20))
end
end
end
def calculate_frame_score rolls_list do
case rolls_list do
[10 | _ ] -> strike rolls_list
[f1, f2 | _] when f1 + f2 == 10 -> spare rolls_list
[f1, f2 | _] when f1 + f2 < 10 -> normal rolls_list
_ -> 0
end
end
def strike list do
{:strike, Enum.slice(list, 0..2) |> Enum.reduce(fn(x, acc) -> x + acc end)}
end
def spare list do
{:spare, Enum.slice(list, 0..2) |> Enum.reduce(fn(x, acc) -> x + acc end)}
end
def normal list do
{:normal, Enum.slice(list, 0..1) |> Enum.reduce(fn(x, acc) -> x + acc end)}
end
end
full_strikes = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
spares = [9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9 ]
spares2 = [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
nines_list = [9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0]
IO.puts Bowling.score full_strikes
IO.puts Bowling.score spares
IO.puts Bowling.score spares2
IO.puts Bowling.score nines_list
@doomspork
Copy link

defmodule Bowling do
  def score(rolls), do: calculate(1, rolls)

  def calculate(i, _list) when i > 10, do: 0
  def calculate(i, list) do
    case calculate_frame_score(list) do
      {:strike, score} -> score + calculate(i+1, Enum.slice(list, 1, 20))
      {:spare , score} -> score + calculate(i+1, Enum.slice(list, 2, 20))
      {:normal, score} -> score + calculate(i+1, Enum.slice(list, 2, 20))
    end        
  end

  def calculate_frame_score([10|_] = rolls), do: strike(rolls)
  def calculate_frame_score([f1, f2 |_] = rolls) when f1 + f2 == 10, do: spare(rolls)
  def calculate_frame_score(rolls), do: normal(rolls)

  def calculate_frame_score([10|_] = rolls), do: strike(rolls)

  def strike(list), do: {:strike, slice_and_dice(list)} 

  def spare(list), do: {:spare, slice_and_dice(list)}

  def normal(list), do: {:normal, slice_and_dice(list, 0..1)}

  defp slice_and_dice(list, range \\ 0..2) do
    list
    |> Enum.slice(range) 
    |> Enum.reduce(&(&1 + &2))
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment