确实简洁,不妨想一下 Ruby 怎么写?来自《Haskell 趣学指南》。
import Data.List
solveRPN = head . foldl foldingFunction [] . words
where foldingFunction (x:y:ys) "*" = (x * y):ys
foldingFunction (x:y:ys) "+" = (x + y):ys
foldingFunction (x:y:ys) "-" = (y - x):ys
foldingFunction xs numberString = read numberString:xs
--solveRPN "10 4 3 +"
haskell 本身写递归就非常合适 所以当然短啦
而且很巧。。前两天刚写了这个: https://github.com/tony612/reverse-polish-notation-transition/blob/master/postfix.rb
除了计算出结果,还有转化为 postfix 和 infix 的
(PS:不过话说,这个“10 4 3 +”好像不是合法的逆波兰式吧。。)
def solveRPN rpnexp
rpnexp.split.inject [] do |stack, cur|
foldingFunction stack, cur
end.first
end
def foldingFunction stack, cur
case cur
when '*'
stack << stack.pop.to_i * stack.pop.to_i
when '+'
stack << stack.pop.to_i + stack.pop.to_i
when '-'
stack << 0 - stack.pop.to_i + stack.pop.to_i
else
stack << cur
end
end
puts solveRPN "10 4 3 + 2 * -"
照着这个 Haskell 的版本写了一个,当年看这本 learn you a haskell 就是这章 Functional Solving Problems 特别有启发,推荐读读这一章!
The ruby way...
def solve_rpn expr
expr.scan(%r"(\d+)|([+\-*/])").inject [] do |stack, (num, op)|
stack << (num ? num.to_i : stack.pop(2).reverse.inject(op))
end.last
end
solve_rpn "10 4 3 + 2 * -"
def solveRPN rpnexp
rpnexp.split.inject [] do |stack, c|
stack<<("+-*\\".include?(c)? stack.pop(2).reverse.map(&:to_f).inject(c) : c)
end.first
end
solveRPN "10 4.1 3.0e1 + -2 * -"
require "scanf"
def solveRPN1 exp
stk=[];
exp.split.each{|c|stk<<(c.scanf('%f').first||stk.pop(2).reverse.inject(c))}
stk.first
end
solveRPN1 "10 4.1 3.0e1 + -2 * -"