Skip to content

Instantly share code, notes, and snippets.

@robertsosinski
Last active January 5, 2017 00:53
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 robertsosinski/5364d9378229b26b74c220c97733af1f to your computer and use it in GitHub Desktop.
Save robertsosinski/5364d9378229b26b74c220c97733af1f to your computer and use it in GitHub Desktop.
Functional Dice Rolling
defmodule Dice do
def sum_probability(dice, target) do
prob = :math.pow(6, dice) |> round
total = 6 * dice
"#{sum_probability(dice, target, total)} / #{prob}"
end
defp sum_probability(dice, target, _total) when target < dice do
0
end
defp sum_probability(_dice, target, total) when target > total do
0
end
defp sum_probability(1, _target, _total) do
1
end
defp sum_probability(dice, target, _total) do
perform_rolls(dice, target, 0)
end
defp perform_rolls(_dice, target, acc) when acc > target do
0 # Prevents further rolls if accumulator result is higher then target
end
defp perform_rolls(0, target, acc) do
if target == acc, do: 1, else: 0
end
defp perform_rolls(rolls_left, target, acc) do
1..6
|> Enum.to_list
|> List.foldl(0, fn(roll, odds) ->
perform_rolls(rolls_left - 1, target, acc + roll) + odds
end)
end
end
defmodule DiceTest do
use ExUnit.Case
import Dice
test "sum_probability with valid values" do
assert sum_probability(1, 5) == "1 / 6"
assert sum_probability(2, 2) == "1 / 36"
assert sum_probability(2, 4) == "3 / 36"
assert sum_probability(3, 5) == "6 / 216"
end
test "sum_probability with invalid values" do
assert sum_probability(1, 15) == "0 / 6"
assert sum_probability(3, 1) == "0 / 216"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment