Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Evaluation of Reverse Polish Notation in R

Tags:

parsing

r

rpn

What is the most efficient algorithm to evaluate a RPN notation in R?

Here is the question: suppose we have

c("4", "13", "5", "/", "+") -> (4 + (13 / 5)) -> 6

How to write a general purpose function that evaluates any input RPN ?

Does R have stack data structure ?

Thanks for your hints

like image 674
Sam Avatar asked Mar 03 '15 19:03

Sam


People also ask

How do you evaluate a reverse Polish notation?

The method is follows, evaluating the expression from left to right: When you encounter an operand, push it onto the stack. When you encounter an operator, pop two values from the stack and push the result back onto the stack. When you have finished (been through the whole expression), pop the final answer from the ...

Can we evaluate Polish notation?

Stacks can be used to evaluate postfix notation equations (also known as Reverse Polish notation ). So the algorithm moves along the expression, pushing each operand on the stack while operators cause two items to be popped off the stack , evaluated and the result pushed back on the stacks .

What is the purpose of reverse Polish notation?

What Does Reverse Polish Notation (RPN) Mean? Reverse Polish notation (RPN) is a method for conveying mathematical expressions without the use of separators such as brackets and parentheses. In this notation, the operators follow their operands, hence removing the need for brackets to define evaluation priority.

What is Polish and Reverse Polish Notation give examples for each?

Reverse Polish notation (RPN) is a method for representing expressions in which the operator symbol is placed after the arguments being operated on. Polish notation, in which the operator comes before the operands, was invented in the 1920s by the Polish mathematician Jan Lucasiewicz.


1 Answers

To my knowledge there isn't a dedicated stack structure that you can push/pop etc., but you can easily use lists to achieve the same effect. Here we use the same list to hold the input RPN string and to act as the stack:

rpn <- function(v) {
  l <- lapply(v, function(x) if(grepl("^\\d+$", x)) as.numeric(x) else as.name(x))
  i <- 1
  while(length(l) >= i) {
    if(!is.numeric(l[[i]])) {
      l[[i - 2]] <- as.call(l[c(i, i - 2, i - 1)])
      l[i:(i - 1)] <- NULL
      i <- i - 1
    } else i <- i + 1
  }
  l[[1]]      
}

Let's test:

v <- c("4", "13", "5", "/", "+")
rpn(v)              # un-evaluated reparsed expression
# 4 + 13/5
eval(rpn(v))        # which you can evaluate
# [1] 6.6

Something more challenging:

v <- c("4", "13", "+", "5", "/", "8", "-", "10", "3", "+", "*")
rpn(v)
# ((4 + 13)/5 - 8) * (10 + 3)
eval(rpn(v))
# [1] -59.8

A breakdown of the logic:

  • make a list with numbers and symbols representing the operators
  • walk down list left to right
    • if hit a number, just move pointer to next value (the stuff to the left of the pointer is our stack, so we are using part of our input list as the stack!)
    • if hit a function, combine the two items to the left of the pointer (i.e. rightmost items in stack) into one call on the stack, and reset pointer

That's it. We take advantage that R stores calls as nested lists and that +, -, etc. are just functions in R so this works very naturally.

Assumptions:

  • functions are assumed binary (i.e. no unary - or +, among other things)
  • the user is only inputing valid functions
  • the numbers are integers (this will extend to numerics if you tweak the regular expression)
  • the RPN string needs to make sense (i.e. c("3", "+", "3")) will fail.
like image 178
BrodieG Avatar answered Oct 16 '22 17:10

BrodieG