SyntaxHighlighter

2014年5月8日木曜日

Pythonで逆ポーランド記法の計算

後輩が楽しそうに解いてたので便乗して解いてみました
入力なんかの想定はAOJのコレ

素直に解く

まずはCやJavaなんかで解く時と同じような要領で
演算を辞書に押し込んでしまえば条件分岐が減ってすっきりします

ops = {"+": lambda a, b: b + a,
       "-": lambda a, b: b - a,
       "*": lambda a, b: b * a}
stack = []
for s in raw_input().split():
    if s in ops:
        stack.append(ops[s](stack.pop(), stack.pop()))
    else:
        stack.append(int(s))
print stack[-1]

listを継承して解く

要素を入れたら勝手に合成してくれるstackを作ってみました
あんまり上手な書き方ではないかもしれません

class RPN(list):
    ops = {"+": lambda a, b: b + a,
           "-": lambda a, b: b - a,
           "*": lambda a, b: b * a}
    def __init__(self):
        list.__init__(self)
    def append(self, value):
        if value in self.ops:
            list.append(self, self.ops[value](self.pop(), self.pop()))
        else:
            list.append(self, int(value))

rpn = RPN()    
for s in raw_input().split():
    rpn.append(s)
print rpn[-1]

高階関数を使って解く

組み込み関数のreduceを使って解きます
stackをリレーするイメージ

ops = {"+": lambda a, b: b + a,
       "-": lambda a, b: b - a,
       "*": lambda a, b: b * a}
def calc(stack, s):
    if s in ops:
        stack.append(ops[s](stack.pop(), stack.pop()))
    else:
        stack.append(int(s))
    return stack
print reduce(calc, raw_input().split(), [])[-1]

一行で解く

先の解き方からの発展形
if-elseが面倒でついにevalを使ってしまいましたが、もちろん使わなくても解けます

print reduce(lambda stack, s: stack[:-2] + [eval("{} {} {}".format(stack[-2], s, stack[-1]))] if s in "+-*" else stack + [int(s)], raw_input().split(), [])[-1]

まとめ

一つの問題を解くにもアプローチの仕方は様々
ワンライナーを目指すと2度楽しい