わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

Raccで6÷2(1+2)

以前,Rubyで6÷2(1+2)を書いたのですが,そのスクリプトで使用しているsyntax.rbは現在,ダウンロードできなくなっていたため,コードを新たに作りました.

Raccを使用しています.必要ならgem install raccとしたのち,実行すると,次のようになります.

$ ruby calc1.rb
1+2×3=7
3×(8+5×(6−2))÷2=42
6÷2(1+2)=1
6÷2×(1+2)=9

「6÷2(1+2)」と「6÷2×(1+2)」の評価結果が違うことも,確認できます.
以下,Rubyスクリプトの詳細を書きます.実行すると,カレントディレクトリにcalc.yとcalc.rbを作ります.calc.yは,次のページの内容をベースとしています.

違いもあります.演算子を「+−×÷」に変更し,「2(1+2)」を正しい式(連接による積)として認識するよう,CONCATというラベルで,定義を挿入しています*1.優先順位は,乗算・除算記号よりも上位としました.
さて,冒頭のTogetterまとめで,「1か9かどうかというのは実のところルール次第」とコメントしたので,「6÷2(1+2)=9」となるよう,ルールを変えてみましょう.

構文規則は変更せず,優先順位を「left '×' '÷' CONCAT」として乗除と同じにしました.
出力は…

$ ruby calc2.rb
1+2×3=7
3×(8+5×(6−2))÷2=42
2(1+2)−2=4
2(1+2)÷2=3
6÷2(1+2)=1
6÷2×(1+2)=9

残念ながら「6÷2(1+2)=1」と出まして,9ではありません.この対策について,今のところアイデアなしの状況です.
なお「2(1+2)−2=4」「2(1+2)÷2=3」は,動作確認用に追加したものです.これらは(「2(1+2)」を構文的に正しいという前提のもと)正しい評価結果です.優先順位の指定について,Rubyスクリプト

prechigh
  left '×' '÷'
  left CONCAT
  left '+' '−'
preclow

と書き換えてから,実行しなおすと,「2(1+2)÷2=2」になります.これは「(1+2)÷2=3÷2=1」と評価しており*2,期待した動作です.さらに

prechigh
  left '×' '÷'
  left '+' '−'
  left CONCAT
preclow

としてみると,「2(1+2)−2=2」と変わります.「(1+2)−2=1」が優先されています.
なのですが,上のように修正しても,「6÷2(1+2)=1」は変更ありません.
うーん,本日はここまでです.

*1:raccコマンド実行中に「10 shift/reduce conflicts」と出ます.ruby -d calc1.rbと実行しても,表示されるようにしています.

*2:「整数÷整数」は整数です.3÷2を有理数で表現することも可能で,http://d.hatena.ne.jp/takehikom/20110524/1306182300 で試みています.