1
1

More than 5 years have passed since last update.

rubyで逆ポ

Last updated at Posted at 2012-08-29

http://d.hatena.ne.jp/torazuka/20120829/stackmachine
を読んで、ruby で逆ポを書いてみた。
最初は普通にやろうと思っていたんだが、書き始めてから正規表現で解決するという作戦に変更。
perl6 なら正規表現による置換一発でかけるのかもしれないなんて思いつつ、perl6 のことは全く知らないのでわからない。

rpn.rb
#!ruby

def rpn( s )
  return s if /\A[\d\.]+\Z/=~s
  raise "FAIL : #{s}" unless /([\d\.]+)\s+([\d\.]+)\s+([^\d\.\s]+)/=~s
  a, b=[$1,$2].map( &:to_f )
  r=case $3
    when '+'
      a+b
    when '-'
      a-b
    when '*'
      a*b
    when '/'
      a/b
    end
  rpn( s.gsub( $&, r.to_s ) )
end

DATA.each{ |a|
  i, x = a.split( "->" ).map( &:strip )
  ac = rpn(i)
  raise [i,x,ac].inspect unless ac.to_f==x.to_f
  puts "ok : %s -> %s"%[i,ac]
}
__END__
1 -> 1
1 2 + -> 3
3 1 - -> 2
10 2 / -> 5
2 5 8 + + -> 15
2 5 8 + * -> 26
2 5 8 * + -> 42
1 2 + 3 4 + * -> 21
2 3 * 4 5 * + -> 26

正規表現なんか使わなくてももっとすっと書けるような気がしてならないが、まあこんなところで。
なんとなく、eval は禁止の方向で。
二項じゃない演算子に対応するためには一手間必要か。
あと、再帰で書いているのでスタックがあふれる危険あり。
末尾再帰になっていると思うので、ループにするのは簡単だと思う。

1
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1