No.24
umashika-news.jp - umashika-news リソースおよび情報(63÷21)×18−27+53 = 35+72−81×(12÷36)
$ ruby pmtd-parser-no_tw.rb "(63÷21)×18-27+53" (63÷21)×18-27+53=80 $ ruby pmtd-parser-no_tw.rb "35+72-81×(12÷36)" 35+72-81×(12÷36)=107
あれ,合いません.どうやら,12÷36を0と評価してしまうのが問題のようです.
ではスクリプトをいじりましょう.整数と加減乗除なので,有理数が扱えれば十分です.Rubyでは,「require "rational"」とすることで,Rationalクラスが使用できます.
出来上がりは,またもgistに置いています.今回も,syntax.rbは必要です.
前のスクリプトで,文字列を整数値に変換しているのは,インスタンス変数@numの中の
val = x.join.to_i()
でした.これを
val = Rational(x.join)
とすると,Ruby 1.9では問題なく動作しましたが,1.8ではエラーになります.
val = Rational(x.join.to_i)
とすることで,Ruby 1.8/1.9両対応になりました.
次に,Rationalのインスタンスの出力は,整数値になる場合でも「80/1」のように,分母が表示されてしまいます.これは,Rational#to_sの定義を上書きしました.
あとちょっと欲張って,入力の数字やプラスマイナス,それとカッコは,日本語文字でもいいことにしてみました.これをASCII文字に変換するのに,String#trを使ったのですが,Ruby 1.9では文字単位,1.8ではバイト単位なのを忘れていて,訳の分からない出力になり苦労しました.Ruby 1.8では,jcodeをロードすることで,解決しました.
出力は次のとおり.12÷36が「1/3」になっています.
$ ruby -v ruby 1.8.8dev (2011-03-03) [i386-cygwin] $ ruby pmtd-parser-rational.rb (63÷21)×18-27+53=80 35+72-81×(12÷36)=80 $ ruby -d pmtd-parser-rational.rb (略) expr2: x=[Rational(12, 1), [["÷", Rational(36, 1)]]]:Array, val=1/3 expr: x=[Rational(1, 3), []]:Array, val=1/3 prim_par: x=["(", Rational(1, 3), ")"]:Array, val=1/3 prim2: x=[Rational(1, 3), []]:Array, val=1/3 prim3_num: x=Rational(1, 3):Rational, val=1/3 expr2: x=[Rational(81, 1), [["×", Rational(1, 3)]]]:Array, val=27 expr: x=[Rational(35, 1), [["+", Rational(72, 1)], ["-", Rational(27, 1)]]]:Array, val=80 80