Skip to content

Instantly share code, notes, and snippets.

@theaspect
Last active May 13, 2020 08:46
Show Gist options
  • Save theaspect/bacf67baca9c38de6ec481b025dbc5e1 to your computer and use it in GitHub Desktop.
Save theaspect/bacf67baca9c38de6ec481b025dbc5e1 to your computer and use it in GitHub Desktop.
Functional Erlang Assignment 1
-module(assignment1).
-include_lib("eunit/include/eunit.hrl").
-export([hypotenuse/2, area/1, perimeter/1, enclose/1, bits/1, bits_tail/1]).
% You can run test with:
% c(assignment1).
% assignment1:test().
% Available shapes:
% {circle, {X,Y}, R}
% {rectangle, {X,Y}, H, W}
% {triangle, {X1,Y1}, {X2,Y2}, {X3,Y3}}
% Define a function perimeter/1 which takes a shape
% and returns the perimeter of the shape.
% Choose a suitable representation of triangles,
% and augment area/1 and perimeter/1 to handle this case too.
% Define a function enclose/1 that takes a shape
% and returns the smallest enclosing rectangle of the shape.
% Find line length by two coords
hypotenuse({X1,Y1}, {X2,Y2}) ->
math:sqrt((X2-X1)*(X2-X1) + (Y2-Y1)*(Y2-Y1)).
% Assignment
% Area of a shape
area({circle, {_X,_Y}, R}) ->
math:pi() * R*R;
area({rectangle, {_X,_Y}, H, W}) ->
H * W;
area({triangle, {X1,Y1}, {X2,Y2}, {X3,Y3}}) ->
% 2D vector cross-product, is area of parallelogram
abs(((X2-X1)*(Y3-Y1) - (X3-X1)*(Y2-Y1)) / 2).
% Perimeter of a shape
perimeter({circle, {_X,_Y}, R}) ->
2*math:pi()*R;
perimeter({rectangle, {_X,_Y}, H, W}) ->
2*H + 2*W;
perimeter({triangle, {X1,Y1}, {X2,Y2}, {X3,Y3}}) ->
hypotenuse({X1,Y1}, {X2,Y2}) +
hypotenuse({X1,Y1}, {X3,Y3}) +
hypotenuse({X2,Y2}, {X3,Y3}).
% Enclose rectangle of a shape
enclose({circle, {X,Y}, R}) ->
{rectangle, {X-R, Y-R}, 2*R, 2*R};
enclose({rectangle, {X,Y}, H, W}) ->
{rectangle, {X,Y}, H, W};
enclose({triangle, {X1,Y1}, {X2,Y2}, {X3,Y3}}) ->
X_MIN=lists:min([X1, X2, X3]),
X_MAX=lists:max([X1, X2, X3]),
Y_MIN=lists:min([Y1, Y2, Y3]),
Y_MAX=lists:max([Y1, Y2, Y3]),
% Find dimensions of enclosing rectangle and put in a left bottom coord of the triangle
{rectangle, {X_MIN,Y_MIN}, Y_MAX-Y_MIN, X_MAX-X_MIN}.
% Find sum of bits, direct recursive
bits(0) -> 0;
bits(X) -> (X band 1) + bits(X bsr 1).
% Find sum of bits, tail recursive
bits_tail(X) -> bits_tail(X, 0).
bits_tail(0, ACC) -> ACC;
bits_tail(X, ACC) -> bits_tail(X bsr 1, ACC + (X band 1)).
% All tests
hypotenuse_test() -> ?assert(hypotenuse({4,1},{1,5}) == 5).
area_test() -> [
?assert(area({circle, {0,0}, 1}) == math:pi()),
?assert(area({rectangle, {0,0}, 2, 3}) == 6),
?assert(area({triangle, {1,5}, {4,5}, {4,1}}) == 6)
].
perimeter_test() -> [
?assert(perimeter({circle, {0,0}, 1}) == 2 * math:pi()),
?assert(perimeter({rectangle, {0,0}, 2, 3}) == 10),
?assert(perimeter({triangle, {1,5}, {4,5}, {4,1}}) == 12)
].
enclose_test() -> [
?assert(enclose({circle, {1,1}, 1}) == {rectangle, {0,0}, 2, 2}),
?assert(enclose({rectangle, {0,0}, 2, 3}) == {rectangle, {0,0}, 2, 3}),
?assert(enclose({triangle, {1,5}, {4,5}, {4,1}}) == {rectangle, {1,1}, 4, 3})
].
bits_test() -> [
?assert(bits(7) == 3),
?assert(bits(8) == 1)
].
bits_tail_test() -> [
?assert(bits_tail(7) == 3),
?assert(bits_tail(8) == 1)
].
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment