BIDMASを忘れて!方程式とを演算子優先順位でとり、その結果を出力するプログラムを書く。
入力フォーマットの例:
1.2+3.4*5.6/7.8-9.0 */+-
Rules & guidelines:
- The only operators that are defined are addition (+),
subtraction (-), multiplication (*), and division (/). No
parentheses, no exponentiation. - Associativity is always left-to-right. For example,
10/4/2
is to be interpreted as(10/4)/2
with a result of 1.25, rather than10/(4/2)
. - The input format is as follows:
- An equation, followed by a space, followed by the operator
precedence specification (or two string arguments, one for the
equation and the other for the precedence). - The equation comprises base-10 decimal numbers separated by
operators, with no spaces. Integer values do not have to contain a
period character, i.e. both5
and5.0
are
to be accepted values. - For simplicity, negative numbers may not be included in the
input, e.g.6/3
is valid but6/-3
is not.
Input also may not contain a leading or trailing operator, so
-6/3
isn’t considered valid, nor is
6-3+
. - The precedence specification string is always 4 characters long
and always contains the characters+
,-
,
/
, and*
once each. Precedence is read as
left-to-right, e.g.*/+-
specifies multiplication with
the highest precedence, division next, then addition, and finally
subtraction. EDIT: It is acceptable to take the
precedence string in reverse order (lowest to highest) as long as
you specify this in your answer.
- An equation, followed by a space, followed by the operator
- Input is a string to be taken via command line arguments,
STDIN, or the default input format in programming languages that do
not support these input methods. - You are free to assume that the given input will be in the
correct format. - Output is via STDOUT or your language’s normal output
method. - The printed result should be in base-10 decimal.
- Results must be computed to at least 4 decimal points of
accuracy when compared to a correct implementation that uses double
precision (64-bit) floating point arithmetic. This degree of
freedom is designed to allow for the use of fixed-point arithmetic
in languages that have no floating-point support. - Divide by zero, overflow, and underflow are undefined
behaviour. Your code is free to assume that no inputs will be given
that will trigger these cases. - You may not call out to any external services (e.g. Wolfram
Alpha) - You may not call out to any programs whose primary function is
to solve these types of problems.
テストケース:
-
6.3*7.8
followed by any operator precedence
specification prints 49.14 -
2.2*3.3+9.9/8.8-1.1 */+-
is parsed as
((2.2*3.3)+(9.9/8.8))-1.1
and should print 7.285 -
2.2*3.3+9.9/8.8-1.1 +*/-
is parsed as
((2.2*(3.3+9.9))/8.8)-1.1
and should print 2.2 -
10/2+5-1 +-/*
is parsed as
10/((2+5)-1)
and the printed result should be
1.6666666… -
2147480/90+10*5 +/-*
is parsed as
(2147480/(90+10))*5
and the printed result should be
107374 -
3*55-5/8/4+1 -/+*
is parsed as
3*((((55-5)/8)/4)+1)
should print 7.6875 - An input containing one thousand instances of the number
1.015
separated by multiplier operators (i.e. the
expanded multiplicative form of1.015^1000
), followed
by any operated precedence specification, should print a number
within 0.0001 of 2924436.8604.
コードゴルフでは、最短のコードが勝ちます。
ベストアンサー
JavaScript(ES6)、94バイト
特に短くはないが、楽しい。場所全体のかっこを追加する…
s=>([e,o]=s.split` `,[...o].map(x=>e=e.split(x).join((a+=')')+x+(b+='(')),a=b=''),eval(b+e+a))
テストケース
<div class=”snippet” data-lang=”js” data-hide=”true”
data-console=”true” data-babel=”false”> <div
class=”snippet-code snippet-currently-hidden”>
let f =
s=>([e,o]=s.split` `,[...o].map(x=>e=e.split(x).join((a+=')')+x+(b+='(')),a=b=''),eval(b+e+a))
console.log(f("6.3*7.8 +-*/")) //49.14
console.log(f("2.2*3.3+9.9/8.8-1.1 */+-")) //7.285
console.log(f("2.2*3.3+9.9/8.8-1.1 +*/-")) //2.2
console.log(f("10/2+5-1 +-/*")) //1.6666
console.log(f("2147480/90+10*5 +/-*")) //107374
console.log(f("3*55-5/8/4+1 -/+*")) //7.6875
</div> </div>
ヒストリーノート
同様の方法が初期のFORTRANコンパイラで使用されていました。 archive.orgから関連記事へのリンクですコンピュータとオートメーション
Donald E. Knuth によって書かれた>。
例
表現 2.2 * 3.3 + 9.9/8.8-1.1
を考えてみましょう。
演算子の優先順位が */+ -
の場合、次のように展開されます。
((((2.2)*(3.3)))+(((9.9))/((8.8))))-((((1.1))))
演算子の優先順位 + */ -
を使用すると、次のように展開されます。
((((2.2))*((3.3)+(9.9)))/(((8.8))))-((((1.1))))
すべての括弧を削除すると、次のようになります。
((2.2*3.3)+(9.9/8.8))-1.1 = 7.285
そして:
((2.2*(3.3+9.9))/8.8)-1.1 = 2.2