R中反波兰符号的评价

时间:2015-03-03 19:14:03

标签: r parsing rpn

在R中评估RPN表示法的最有效算法是什么?

这是一个问题:假设我们有

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

如何编写评估任何输入RPN的通用函数?

R是否具有堆栈数据结构?

感谢您的提示

1 个答案:

答案 0 :(得分:10)

据我所知,没有可以推/弹等的专用堆栈结构,但您可以轻松使用列表来实现相同的效果。这里我们使用相同的列表来保存输入RPN字符串并充当堆栈:

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]]      
}

我们来测试一下:

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

更具挑战性的事情:

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

逻辑细分:

  • 列出包含代表运营商的数字和符号的列表
  • 从左到右走下列表
    • 如果点击一个数字,只需将指针移动到下一个值(指针左边的东西就是我们的堆栈,所以我们使用输入列表的一部分作为堆栈!)
    • 如果点击一个函数,将指针左边的两个项目(即堆栈中最右边的项目)合并到堆栈上的一个调用中,并重置指针

就是这样。我们利用R将调用存储为嵌套列表,而+-等只是R中的函数,因此这非常自然。

假设:

  • 函数被假定为二进制(即没有一元-+等)
  • 用户只输入有效的功能
  • 数字是整数(如果你调整正则表达式,这将扩展到数字)
  • RPN字符串需要有意义(即c("3", "+", "3"))将失败。