方程式の結果を計算しますが、演算子の優先順位は選択可能です

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 than 10/(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. both 5 and 5.0 are
      to be accepted values.
    • For simplicity, negative numbers may not be included in the
      input, e.g. 6/3 is valid but 6/-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.
  • 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.

テストケース:

  1. 6.3*7.8 followed by any operator precedence
    specification prints 49.14
  2. 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
  3. 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
  4. 10/2+5-1 +-/* is parsed as
    10/((2+5)-1) and the printed result should be
    1.6666666…
  5. 2147480/90+10*5 +/-* is parsed as
    (2147480/(90+10))*5 and the printed result should be
    107374
  6. 3*55-5/8/4+1 -/+* is parsed as
    3*((((55-5)/8)/4)+1) should print 7.6875
  7. An input containing one thousand instances of the number
    1.015 separated by multiplier operators (i.e. the
    expanded multiplicative form of 1.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

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です