Created
February 26, 2017 09:15
-
-
Save danielrhodeswarp/a15aff80ff571fbce3b36e647082008c to your computer and use it in GitHub Desktop.
Revisions
-
danielrhodeswarp created this gist
Feb 26, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,120 @@ -module(one_24). -export([perimeter / 1, area / 1, enclose / 1]). % shapes -export([bits / 1]). % summing the bits -export([testAll / 0, testArea / 0, testPerimeter / 0, testEnclose / 0, testBits / 0]). % tests for shapes AND bits % ==== MASTER TESTER ================ % run all automated tests (and return "has everything passed?" boolean) testAll() -> io:format("Running all tests~n"), true == ( testArea() and testPerimeter() and testEnclose() % and testBits() ). % ==== SHAPES ================ % shape tuples used: % {circle, {X, Y}, Radius} where {X, Y} is centre of circle % {rectangle, {X, Y}, Height, Width} where {X, Y} is centre of rectangle % {triangle, {X, Y}, SideLength1, SideLength2, SideLength3} where {X, Y} is centre of triangle % (for sure, not so realistic! but to keep a bit of consistency with circle and rectangle) % % NOTE that I don't really pay attention to the {X, Y} coords of shapes! % get perimeter of a shape perimeter({circle, {_X, _Y}, Radius}) -> Diameter = 2 * Radius, math:pi() * Diameter; perimeter({rectangle, {_X, _Y}, Height, Width}) -> (2 * Height) + (2 * Width); perimeter({triangle, {_X, _Y}, SideLength1, SideLength2, SideLength3}) -> SideLength1 + SideLength2 + SideLength3. % get area of a shape area({circle, {_X, _Y}, Radius}) -> math:pi() * Radius * Radius; area({rectangle, {_X, _Y}, Height, Width}) -> Height * Width; area({triangle, {X, Y}, SideLength1, SideLength2, SideLength3}) -> % we use Heron's formula which is based on side lengths and the semiperimeter Semiperimeter = perimeter({triangle, {X, Y}, SideLength1, SideLength2, SideLength3}) / 2, math:sqrt(Semiperimeter * (Semiperimeter - SideLength1) * (Semiperimeter - SideLength2) * (Semiperimeter - SideLength3)). % get smallest bounding box of a shape % (returns a rectangle shape) enclose({circle, {_X, _Y}, Radius}) -> Diameter = Radius * 2, {rectangle, {0, 0}, Diameter, Diameter}; enclose({rectangle, {X, Y}, Height, Width}) -> % return same rectangle that was input % (is there a shorthand way to do this?) {rectangle, {X, Y}, Height, Width}; % or reset X and Y to zero for consistency? enclose({triangle, {_X, _Y}, SideLength1, SideLength2, SideLength3}) -> % oops. not sure I can do this accurately without the coords of each % triangle point. % http://www.mathopenref.com/coordtriangleareabox.html looks super % useful here % FTTB use a square of biggest side length MaxSideLength = max(SideLength1, max(SideLength2, SideLength3)), % from lesson 1.15 ;-) {rectangle, {0, 0}, MaxSideLength, MaxSideLength}. % test for perimeter (and return "passed?" boolean) testPerimeter() -> io:format("Testing perimeter()~n"), (perimeter({circle, {10, 10}, 1}) == 6.283185307179586) and % how to round / reduce the precision here? (perimeter({rectangle, {10, 10}, 10, 20}) == 60) and (perimeter({triangle, {10, 10}, 3, 4, 5}) == 12). % test for area (and return "passed?" boolean) testArea() -> io:format("Testing area()~n"), (area({circle, {10, 10}, 1}) == 3.141592653589793) and % how to round / reduce the precision here? (area({rectangle, {10, 10}, 10, 20}) == 200) and (area({triangle, {10, 10}, 3, 4, 5}) == 6). % result from area() calc will be 6.0 but a 6 here matches too % test for enclose (and return "passed?" boolean) testEnclose() -> io:format("Testing enclose()~n"), (enclose({circle, {10, 10}, 1}) == {rectangle, {0, 0}, 2, 2}) and (enclose({rectangle, {10, 10}, 10, 20}) == {rectangle, {10, 10}, 10, 20}) and (enclose({triangle, {10, 10}, 3, 4, 5}) == {rectangle, {0, 0}, 5, 5}). % ==== SUMMING THE BITS ================ % "Define a function bits/1 that takes a positive integer N % and returns the sum of the bits in the binary representation. % For example bits(7) is 3 and bits(8) is 1." % % or, in Daniel language, "how many 1's in the binary representation?" bits(N) -> bits(N, 128, 0). % NOTE we only supporting 8 bits unsigned integers (ie. biggest column is 128 so biggest val is 255) % not sure if the stop case is the CurrentColun reaching 1 or the % remaining ValueToSpread reaching 0 (or both) :-/ bits(_N, 1, BitsSoFar) -> % N should prob be zero here BitsSoFar; bits(0, _CurrentColumn, BitsSoFar) -> BitsSoFar; bits(ValueToSpread, CurrentColumn, BitsSoFar) -> % or when N <= 255 ? io:format("col ~p, val ~p, bitsSoFar ~p~n", [CurrentColumn, ValueToSpread, BitsSoFar]), %BitSetForCurrentColumn = (ValueToSpread >= CurrentColumn), DecimalValueInColumn = max(-1, ValueToSpread - CurrentColumn), % anything less than -1 is clipped to -1 BitValueForCurrentColumn = min(1, DecimalValueInColumn), RemainingValueToSpread = ValueToSpread - (CurrentColumn * BitValueForCurrentColumn), % move one column right bits(RemainingValueToSpread, CurrentColumn / 2, BitsSoFar + BitValueForCurrentColumn). % test for bits (and return "passed?" boolean) testBits() -> io:format("Testing bits()~n"), (bits(7) == 3) and (bits(8) == 1).