Skip to content

Instantly share code, notes, and snippets.

@d11wtq
Last active December 15, 2015 07:08
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d11wtq/5220747 to your computer and use it in GitHub Desktop.
Save d11wtq/5220747 to your computer and use it in GitHub Desktop.
Reverse Polish Notation Calculator in Erlang
%% @doc Reverse Polish Notation Calculator.
%%
%% Parses expressions like "1 2 3 + -" = -4
%%
%% This is an exercise in Learn You some Erlang for Great Good,
%% however I didn't read the text and just implemented it.
%%
%% I guess understanding stack-based parsing helps here.
-module(calc).
-export([rpn/1]).
%% @doc Parse and calculate the RPN expression from a string.
%%
%% @spec rpn("1 2 3 + -") -> -4
%% @spec rpn("1 2 3 -") -> throw(invalid_expr)
rpn(Expr) ->
parse(string:tokens(Expr, " "), []).
%% @private
parse([], Stack) ->
case length(Stack) of
1 -> hd(Stack);
_ -> throw(invalid_expr)
end;
parse([Token|Tail], Stack) ->
case Token of
"+" ->
parse(Tail, reduce(fun(A, B) -> A + B end, Stack));
"-" ->
parse(Tail, reduce(fun(A, B) -> A - B end, Stack));
"*" ->
parse(Tail, reduce(fun(A, B) -> A * B end, Stack));
"/" ->
parse(Tail, reduce(fun(A, B) -> A / B end, Stack));
_ ->
parse(Tail, [list_to_integer(Token)|Stack])
end.
%% @private
reduce(F, Stack = [A,B|Tail]) ->
case length(Stack) < 2 of
true -> throw(invalid_expr);
false -> [F(B, A)|Tail]
end.
%% @doc Reverse Polish Notation Calculator.
%%
%% Parses expressions like "1 2 3 + -" = -4
%%
%% This is an exercise in Learn You some Erlang for Great Good
%% and this is the succinct solution in the book.
-module(calc).
-export([rpn/1]).
%% @doc Parse and calculate the RPN expression from a string.
%%
%% @spec rpn("1 2 3 + -") -> -4
rpn(Expr) ->
hd([_] = lists:foldl(fun parse/2, [], string:tokens(Expr, " "))).
%% @private
parse("+", [A,B|Tail]) ->
[B+A|Tail];
parse("-", [A,B|Tail]) ->
[B-A|Tail];
parse("*", [A,B|Tail]) ->
[B*A|Tail];
parse("/", [A,B|Tail]) ->
[B/A|Tail];
parse(Token, Stack) ->
[list_to_integer(Token)|Stack].
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment