diff --git a/triangle/README.md b/triangle/README.md new file mode 100644 index 0000000..b4fe084 --- /dev/null +++ b/triangle/README.md @@ -0,0 +1,25 @@ +# Triangle + +Write a program that can tell you if a triangle is equilateral, isosceles, or scalene. + +The program should raise an error if the triangle cannot exist. + +Tests are provided, delete one `skip` at a time. + +## Hint + +The sum of the lengths of any two sides of a triangle always exceeds the +length of the third side, a principle known as the _triangle +inequality_. + +## Running tests + +```bash +$ elixir bob_test.exs +``` + +(Replace `bob_test.exs` with the name of the test file.) + +## Source + +The Ruby Koans triangle project, parts 1 & 2 [view source](http://rubykoans.com) diff --git a/triangle/triangle.exs b/triangle/triangle.exs new file mode 100644 index 0000000..3b0a914 --- /dev/null +++ b/triangle/triangle.exs @@ -0,0 +1,22 @@ +defmodule Triangle do + @type kind :: :equilateral | :isosceles | :scalene + + @doc """ + Return the kind of triangle of a triangle with 'a', 'b' and 'c' as lengths. + """ + @spec kind(number, number, number) :: { :ok, kind } | { :error, String.t } + def kind(a, b, c) do + cond do + a <= 0 || b <= 0 || c <= 0 -> { :error, "all side lengths must be positive" } + a == b && b == c -> { :ok, :equilateral } + + (a == b || a == c || b == c) && valid_triangle?(Enum.sort([a,b,c])) -> { :ok, :isosceles } + (a != b || a != c || b != c) && valid_triangle?(Enum.sort([a,b,c])) -> { :ok, :scalene } + (a != b || a != c || b != c) && !valid_triangle?(Enum.sort([a,b,c])) -> { :error, "side lengths violate triangle inequality" } + end + end + + defp valid_triangle?(l) do + (Enum.at(l,0) + Enum.at(l,1)) > Enum.at(l,2) + end +end diff --git a/triangle/triangle_test.exs b/triangle/triangle_test.exs new file mode 100644 index 0000000..9bb6267 --- /dev/null +++ b/triangle/triangle_test.exs @@ -0,0 +1,72 @@ +if System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("example.exs") +else + Code.load_file("triangle.exs") +end + +ExUnit.start + +defmodule TriangleTest do + use ExUnit.Case, async: true + + test "equilateral triangles have equal sides" do + assert Triangle.kind(2, 2, 2) == { :ok, :equilateral } + end + + test "larger equilateral triangles also have equal sides" do + assert Triangle.kind(10, 10, 10) == { :ok, :equilateral } + end + + test "isosceles triangles have last two sides equal" do + assert Triangle.kind(3, 4, 4) == { :ok, :isosceles } + end + + test "isosceles triangles have first and last sides equal" do + assert Triangle.kind(4, 3, 4) == { :ok, :isosceles } + end + + test "isosceles triangles have two first sides equal" do + assert Triangle.kind(4, 4, 3) == { :ok, :isosceles } + end + + test "isosceles triangles have in fact exactly two sides equal" do + assert Triangle.kind(10, 10, 2) == { :ok, :isosceles } + end + + test "scalene triangles have no equal sides" do + assert Triangle.kind(3, 4, 5) == { :ok, :scalene } + end + + test "scalene triangles have no equal sides at a larger scale too" do + assert Triangle.kind(10, 11, 12) == { :ok, :scalene } + end + + test "scalene triangles have no equal sides in descending order either" do + assert Triangle.kind(5, 4, 2) == { :ok, :scalene } + end + + test "very small triangles are legal" do + assert Triangle.kind(0.4, 0.6, 0.3) == { :ok, :scalene } + end + + test "triangles with no size are illegal" do + assert Triangle.kind(0, 0, 0) == { :error, "all side lengths must be positive" } + end + + test "triangles with negative sides are illegal" do + assert Triangle.kind(3, 4, -5) == { :error, "all side lengths must be positive" } + end + + test "triangles violating triangle inequality are illegal" do + assert Triangle.kind(1, 1, 3) == { :error, "side lengths violate triangle inequality" } + end + + test "triangles violating triangle inequality are illegal 2" do + assert Triangle.kind(2, 4, 2) == { :error, "side lengths violate triangle inequality" } + end + + test "triangles violating triangle inequality are illegal 3" do + assert Triangle.kind(7, 3, 2) == { :error, "side lengths violate triangle inequality" } + end +end +