これはPerlに依存していたせいで、ほとんど知らない他言語の機能(主にD言語)を学ぶ為に書いたコードです。多分もっと最適化できます。
なるべく見やすい・読みやすいように書き直しました。import std.conv : to; import std.math : pow; import std.stdio : writefln,readln; import std.regexp : RegExp,search,sub; import std.string : split,chomp,replace,format; import std.exception : collectException; alias collectException escape; const real function (real,real)[string] operator; static this () { operator = [ "+": function (real x,real y) { return x + y; }, "-": function (real x,real y) { return x - y; }, "*": function (real x,real y) { return x * y; }, "/": function (real x,real y) { return !y ? 0 : x / y; }, "%": function (real x,real y) { return !y ? x : x % y; }, "^": function (real x,real y) { return pow(x,y); }, ]; } void main () { RegExp part; string formula,sum; const string express = r"(^|\()([^\(\)]+)(\)|$)"; const string formatted = format(" %%.%dg ",to!(string)(real.max).length); INPUT: while ((formula = chomp(readln())).length) { while ((part = search(formula,express)) !is null) { if (!escape(to!(real)(sub(formula,"^ | $","","g")))) break; else if ((sum = arithmetic(part[2],formatted)) !is null) formula = replace(formula,part[0],sum); else continue INPUT; } writefln("=%s\n",sum ? formula : " 0 "); sum = null; } } string arithmetic (string formula,string formatted) { real sum = 0; string symbol = "+"; foreach (string part; split(formula," ")) { if (!part.length) continue; else if (symbol is null && part in operator) symbol = part; else if (symbol !is null && !escape(to!(real)(part))) { sum = operator[symbol](sum,to!(real)(part)); symbol = null; } else { error(symbol,part); return null; } } return format(formatted,sum); } void error (string symbol,string part) { writefln((symbol is null ? "Symbol" : "Numeric") ~ " Error: %s\n",part); }
過去に書いてたコードは酷いものだったので、これからはこの書き方を意識したいと思います。
初め数値判定に std.string の isNumeric 使ってたのですが、真を返しても to!(real) で一部の数値形式で例外発生したんで、
色々試してみたら collectException による例外の制御で何とかなりました。isNumericはいらない。
それにしても Python の数値演算どうなってんの・・・。
このプログラム書いてたせいでアニメレビュー遅れてしまった。今日こそやると思います。
0 件のコメント:
コメントを投稿