Created
May 3, 2016 10:44
-
-
Save romul/29ca43111a4c4554a53db3075d2725e2 to your computer and use it in GitHub Desktop.
Reverse polish notation parser implemented in Elixir
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
defmodule RPN do | |
@binary_ops ~w(+ - / * ^) | |
@unary_ops ~w(+ - sqrt ln) | |
@ops @binary_ops ++ @unary_ops | |
def convert(str) do | |
str |> String.split(" ") |> Enum.reduce([], &convert_rpn(&1, &2)) |> hd | |
end | |
defp convert_rpn(op, [a, b | tail]) when op in @binary_ops do | |
case op do | |
"+" -> [b+a | tail] | |
"-" -> [b-a | tail] | |
"*" -> [b*a | tail] | |
"/" -> [b/a | tail] | |
"^" -> [:math.pow(b, a) | tail] | |
end | |
end | |
defp convert_rpn(op, [a | tail]) when op in @unary_ops do | |
case op do | |
"+" -> [a | tail] | |
"-" -> [-a | tail] | |
"sqrt" -> [:math.sqrt(a) | tail] | |
"ln" -> [:math.log(a) | tail] | |
end | |
end | |
defp convert_rpn(op, _) when op in @ops do | |
raise ArgumentError, message: "insufficient arguments count for #{op}" | |
end | |
defp convert_rpn(num_str, acc) do | |
number = case Float.parse(num_str) do | |
{num, _} -> num | |
:error -> raise ArgumentError, message: "#{num_str} is not a number" | |
end | |
[number | acc] | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment