Last active
December 15, 2015 07:08
-
-
Save d11wtq/5220747 to your computer and use it in GitHub Desktop.
Reverse Polish Notation Calculator in Erlang
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 characters
%% @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. |
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 characters
%% @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