aboutsummaryrefslogtreecommitdiff
path: root/learn-you-some-erlang/calc.erl
diff options
context:
space:
mode:
Diffstat (limited to 'learn-you-some-erlang/calc.erl')
-rw-r--r--learn-you-some-erlang/calc.erl51
1 files changed, 51 insertions, 0 deletions
diff --git a/learn-you-some-erlang/calc.erl b/learn-you-some-erlang/calc.erl
new file mode 100644
index 0000000..c41ffb6
--- /dev/null
+++ b/learn-you-some-erlang/calc.erl
@@ -0,0 +1,51 @@
+-module(calc).
+-export([rpn/1, rpn_test/0]).
+
+%% rpn(List()) -> Int() | Float()
+%% parses an RPN string and outputs the results.
+rpn(L) when is_list(L) ->
+ [Res] = lists:foldl(fun rpn/2, [], string:tokens(L, " ")),
+ Res.
+
+%% rpn(Str(), List()) -> List()
+%% Returns the new stack after an operation has been done.
+%% If no operator is found, we assume a number.
+rpn("+", [N1,N2|S]) -> [N2+N1|S];
+rpn("-", [N1,N2|S]) -> [N2-N1|S];
+rpn("*", [N1,N2|S]) -> [N2*N1|S];
+rpn("/", [N1,N2|S]) -> [N2/N1|S];
+rpn("^", [N1,N2|S]) -> [math:pow(N2,N1)|S];
+rpn("ln", [N|S]) -> [math:log(N)|S];
+rpn("log10", [N|S]) -> [math:log10(N)|S];
+rpn("sum", Stack) -> [lists:sum(Stack)];
+rpn("prod", Stack) -> [lists:foldl(fun erlang:'*'/2, 1, Stack)];
+rpn(X, Stack) -> [read(X)|Stack].
+
+%% read(String()) -> Int() | Float()
+read(N) ->
+ case string:to_float(N) of
+ {error,no_float} -> list_to_integer(N);
+ {F,_} -> F
+ end.
+
+%% returns 'ok' iff successful
+rpn_test() ->
+ 5 = rpn("2 3 +"),
+ 87 = rpn("90 3 -"),
+ -4 = rpn("10 4 3 + 2 * -"),
+ -2.0 = rpn("10 4 3 + 2 * - 2 /"),
+ ok = try
+ rpn("90 34 12 33 55 66 + * - +")
+ catch
+ error:{badmatch,[_|_]} -> ok
+ end,
+ 4037 = rpn("90 34 12 33 55 66 + * - + -"),
+ 8.0 = rpn("2 3 ^"),
+ true = math:sqrt(2) == rpn("2 0.5 ^"),
+ true = math:log(2.7) == rpn("2.7 ln"),
+ true = math:log10(2.7) == rpn("2.7 log10"),
+ 50 = rpn("10 10 10 20 sum"),
+ 10.0 = rpn("10 10 10 20 sum 5 /"),
+ 1000.0 = rpn("10 10 20 0.5 prod"),
+ ok.
+