基本的な電卓


20

計算機に入力される文字列を評価するプログラムを作成する必要があります。

プログラムは入力を受け入れ、正しい答えを出力する必要があります。標準の入出力関数を持たない言語の場合、関数readLineおよびを想定できますprint

必要条件

  • いかなる種類の「評価」関数も使用しません
  • 浮動小数点数と負数を処理できます
  • 少なくとも+、-、*、および/演算子をサポートします
  • 演算子と数字の間に1 つ以上のスペースを含む入力を処理できます
  • 式を左から右に評価します

最短のプログラムが勝ちます。同点の場合、最初に提出されたプログラムが勝ちます。

入力が有効で、正しい形式に従っていると想定できます

テストケース

入力

-4 + 5

出力

1


入力

-7.5 / 2.5

出力

-3


入力

-2 + 6 / 2 * 8 - 1 / 2.5 - 18

出力

-12

私の計算機postfixを使用しています。競合については、スタックオーバーフローでの数式の評価も参照してください(ただし、ルールが同一かどうかは確認していません)。
dmckee

3
3番目のテストケースは間違っています-操作の標準順序に従うか、すべての操作を左から右に実行するか。2番目のテストケースを見ると、計算機は各操作の結果を丸めていますか?
プリーズスタンド

2番目と3番目のテストケースを修正しました。結果は丸められません。
ケビンブラウン

3番目のテストケースは、標準の操作順序に従っていません。私たちの答えは?
ジョン

1
コマンドライン引数ARGVの使用はどうですか?これは、シェルが引数を自動分割してリストするためです。
明唐

回答:


7

ルビー-74 69 67 65文字

a=0
("+ "+$<.read).split.each_slice 2{|b,c|a=a.send b,c.to_f}
p a

1
代わりに使用してのb[0],b[1].to_f、置き換えることができる|b||b,c|して使うb,c.to_f
Nemo157

\ o /ありがとう!:-)
アルノールブラン

1
代わりにa.send(b,c.to_f)、を使用しますa.send b,c.to_f。文字を保存します
匿名の

1
次の$<代わりに使用できますARGF
-Dogbert

9

Befunge- 37 x 5 = 185 38 x 3 = 114文字

Befungeは浮動小数点をサポートしていないため、これは整数に制限されます。

&v      /& _ #`&# "-"$# -#<          v
 >~:0`!#v_:" "`! #v_:","`#^_"*"`#v_&*>
 ^      ># $ .# @#<              >&+ 

説明

Befungeの最大の特徴は、ほとんどの言語のような線形の命令セットではなく、それは、制御が任意の方向に流れることができる単一文字命令の2Dグリッドです。

最初は&単純に最初の数字を入力します。vそして>、次に2行目のメインパスに制御をリダイレクトします。

~:0`!#v_

これは文字を入力し(~)、それを複製し(:)、ゼロをスタックにプッシュし(0)、上の2つの要素をポップし、2番目の要素が最初の要素より大きいかどうかを判断し` ます取得するために `` `を使用できないことに驚いていますコードバックティック))、最上位要素の真実性を反転し(!)、ゼロの場合は右に、そうでない場合は下に(#v_)。

基本的には、入力が-1これ以上入力を表していないかどうかをチェックしています。

># $ .# @

入力が-1複製された入力値であった場合は破棄され($)、スタックの最上部は整数として出力され(.)、プログラムは停止します(@)。

:" "`! #v_

そうでない場合、入力がスペース以下かどうかを判別するために、同様のプロセスが繰り返されます。スペースである場合、コントロールはダウンします。

^      ># $ .# @#<

スペースの場合、左にリダイレクトされ<ます()。プログラムの停止(@)、出力(.)、および右リダイレクト(>)はすべて#; を使用してスキップされます。ただし、スタックからスペースを削除するために破棄が実行されます。最後に、次の実行を開始するためにリダイレクトされます(^)。

:","`#^_

それがスペースではなかった場合、同じプロセスが使用されて、それぞれ上[+, *]または[-, \]右にある場合と上にある場合に分割されます。

 >~                         "*"`#v_&*>
 ^                               >&+

というのも[+, *]、それはa +かa かを決定するために再び分割されるからです*。場合+、それがダウン向けられ、その後、次の数(入力され&()およびそれらが追加される+)、その後、制御はラップアラウンドし、次の文字のメインパスまでリダイレクトされます。場合*、それは(入力&)と乗算(*)、直接ラップアラウンドします。

/& _ #`&# "-"$# -#<

なぜなら、[-, \]それは右から左に向かって始まるからです。#最初のパスがあるので、のは、それらの後の文字をスキップする"-"`_ことがある場合は、単純に決定します-/。そうである場合は/、入力(&)および除算(/)に進みます。そうである場合-、それは右ヘッド、再びそれが実行されるように文字をスキップ&"-"$-入力(ある数をもたらす&-文字捨て、スタックにプッシュされる("-"$)、次いで減算が計算されます(-)。その後、コントロールはメインパスにリダイレクトされます。


6

Python 3、105バイト

4つの基本操作を管理しますが、追加^またはにそれぞれ5文字しかかかりません%

f=float
x,*l=input().split()
while l:o,y,*l=l;x,y=f(x),f(y);x=[x+y,x-y,x*y,x/y]['+-*/'.find(o)]
print(x)

操作の優先順位は左から右です。


5

Python(156)

from operator import*
while 1:
 l=raw_input().split();f=float
 while len(l)>2:l[:3]=({'*':mul,'/':div,'+':add,'-':sub}[l[1]](f(l[0]),f(l[2])),)
 print l[0]

1
Python 3を使用する方が簡単です
jamylak


5

Tclの8.6、57の 48文字。

  • 引数からの入力:

    lm o\ b [las $argv a] {set a [exp $a$o$b]};pu $a
    
  • Stdinから(64 53

    lm o\ b [las [ge stdin] a] {set a [exp $a$o$b]};pu $a
    

両方のソリューションにインタラクティブシェルを使用する必要があります。

私は、最初の要素を取得し、それを割り当てる(TCLは、区切り記号としてスペースを使用して)リストとして入力を処理aし、私は残りの上を歩く、毎回2つの要素を取って、オペレータと第二数に演算子を適用$aし、$bそして割り当てますへの結果a。最後に結果はになりaます。


Ideoneは少なくともstdinをサポートしています。
ヨハネ

最後に、Rubyを倒しました。残念ながらIdoneはTcl 8.6をサポートしていませんが、その結果は必要ないlmapのでforeach、良い代替品です。
ヨハネス・クーン

4

Haskell:124114文字

j[o]=o
j(u:m:b:o)=j$show((case m of{"+"->(+);"-"->(-);"*"->(*);"/"->(/)})(read u)(read b)):o
main=interact$j.words

パターンマッチングと単純なcaseステートメントを使用して、手間をかけずに答える、かなり簡単な答えです。使用法:

> ./calc <<< "123 - 12 + -12 / 12.124 * 9.99 - 1"
80.57456285054437

1
代わりに、2文字少なく((case m of{..})(read u)(read b))書くことができます((case m of{..}$read u)$read b)
スウィッシュ

4

C:111の 108文字

main(c){float a,b;for(scanf("%f ",&a);~scanf("%c%f ",&c,&b);a=c^43?c%5?c%2?a/b:a*b:a-b:a+b);printf("%f",a);}

すべての要件、使用法を満たします:

> ./calc <<< "-43 - 56 + 14.123 / -13.22"
6.420348

1
~scanf交換でき+1ます。また、c^45-> c%5およびc^42-> c%2が機能するはずです。
ウゴレン

私のマシンではない@MDXFは、ここですべてのテストケースに合格します。私はかなり最新のIntel MacbookでClangを使用してコンパイルしていますが、非常にうまく機能します(今すぐもう一度テストし、ここからコードをコピーして、フラグなしでコンパイルしました)。どのコンパイラ、プロセッサアーキテクチャ、OSを使用していますか?
Fors

@Fors奇妙な振る舞いを引き起こす奇妙なフラグがいくつかあったと思います。私の間違い、それは今私のために働いています。お邪魔して申し訳ありません。
MD XF

3

C ++ 0xの205 203 198 194文字

#include<iostream>
#define P [](F l,F r){return l
int main(){typedef float F;F r,v,(*a[])(F,F)={P*r;},P+r;},0,P-r;},0,P/r;}};std::cin>>r;for(char o;std::cin>>o>>v;)r=a[o-42](r,v);std::cout<<r;}

きれいにフォーマット:

#include<iostream>

int main()
{
    float r,v;
    float (*a[])(float,float)   ={  [](float l,float r){return l*r;},
                                    [](float l,float r){return l+r;},
                                    0,
                                    [](float l,float r){return l-r;},
                                    0,
                                    [](float l,float r){return l/r;}
                                 };

    std::cin>>r;
    for(char o;std::cin>>o>>v;)
        r=a[o-42](r,v);

    std::cout<<r;
}

3

Perl(97)

$b=shift;eval"\$b$r=$s"while($r=shift,$s=shift);print$b

引数から読み取る

$b=shift;$b=($r eq'+'?$b+$s:$r eq'-'?$b-$s:$r eq'*'?$b*$s:$b/$s)while($r=shift,$s=shift);print$b;

入力から読み取る

@_=split/ /,<>;$b=shift@_;$b=($r eq'+'?$b+$s:$r eq'-'?$b-$s:$r eq'*'?$b*$s:$b/$s)while($r=shift@_,$s=shift@_);print$b

3

PostScript(145)

もう1つのPostScriptエントリ(PostScriptにとって興味深いゴルフを掘り下げてくれたluser droogに感謝します!):

[/+{add}/-{sub}/*{mul}/{div}>>begin(%stdin)(r)file
999 string readline
pop{token not{exit}if
count 4 eq{3 1 roll
4 1 roll
cvx exec}if
exch}loop
=

ゴルフをしていない:

[/+{add}/-{sub}/*{mul}/ {div}>>begin
% Read the input
(%stdin)(r)file 999 string readline pop
{                        % .. string
  token not{exit}if      % .. string token
  % If we have 4 objects on the stack, we have two operands, one operator
  % and the input string. This means, we can calculate now.
  count 4 eq{            % a op string b
    % perform operation a op b = c (where op can be +,-,*,/)
    3 1 roll             % a b op string
    4 1 roll             % string a b op 
    cvx exec             % string c
  }if                    % string token (or c)
  exch                   % token string
}loop
=

あなたは私をbeり続けます!+1これは非常にエキサイティングです。
luserはドローグ

あなたが私のクロスワードを打ち負かすことができれば、私はあなたに賞金を与えます!NB投稿がCWになり、投票でrepポイントを獲得するまで、10回しか編集できません。
luser droog

私はあなたを打ち負かすことができるものだけを選んだので、あなたをyouり続けます;-)。クロスワードグリッドを使用できるかどうかはわかりません。試しますが、数週間しかかかりません。
トーマスW.

1
コミュニティWiki。これは、投稿が何度も編集され、コミュニティに属していることを意味します。すべてのユーザーはそれを編集でき(通常の提案された編集に必要なモデレーターの承認をバイパスします)、それ以上のポイントはありません。だから何をするにしても、Rev 9でやめてください。ギターのタブ1でほとんど吹いてしまいました。
luserはドローグ

1
すべてのCWグリップを無視します。彼らはそれを修正しました!
luserはドローグ

3

パイソン-308

import sys;i=sys.argv[1].split();o=[];s=[];a=o.append;b=s.pop;c=s.append
for t in i:
 if t in"+-*/":
  if s!=[]:a(b())
  c(t)
 else:a(t)
if s!=[]:a(b())
for t in o:
 if t=="+":c(b()+b())
 elif t=="-":m=b();c(b()-m)
 elif t=="*":c(b()*b())
 elif t=="/":m=b();c(b()/m)
 else:c(float(t))
print(b())

読み取り可能なバージョン:

# Infix expression calc

import sys

# Shunting-yard algorithm
input = sys.argv[1].split()
output = []
stack = []

for tkn in input:
    if tkn in "+-*/":
        while stack != []:
            output.append(stack.pop())
        stack.append(tkn)
    else:
        output.append(tkn)

while stack != []:
    output.append(stack.pop())

# Eval postfix notation
for tkn in output:
    if tkn == "+":
        stack.append(stack.pop() + stack.pop())
    elif tkn == "-":
        tmp = stack.pop()
        stack.append(stack.pop() - tmp)
    elif tkn == "*":
        stack.append(stack.pop() * stack.pop())
    elif tkn == "/":
        tmp = stack.pop()
        stack.append(stack.pop()/tmp)
    else:
        stack.append(float(tkn))

print(stack.pop())

式をコマンドライン引数として取り、標準出力に出力します。


2

追記(340)

/D<</+{add}/-{sub}/*{mul}/ {div}>>def/eval{/P null def{token not{exit}if exch/rem exch def
dup D exch known{/P load null ne{D/P load get exch/P exch def exec}{/P exch def}ifelse}if
rem}loop/P load null ne{D/P load get exec}if}def {(> )print flush{(%lineedit)(r)file
dup bytesavailable string readline pop eval == flush}stopped{quit}if}loop

そしてもう少し読みやすい:

%!
/oper<</+{add}/-{sub}/*{mul}/ {div}>>def

/eval{
    /op null def
    {
        token not {exit} if
        exch /rem exch def
        dup oper exch known {
            /op load null ne {
                oper /op load get
                exch /op exch def
                exec
            }{
                /op exch def
            } ifelse
        } if
        rem
    } loop
    /op load null ne { oper /op load get exec } if
} def

{
    (> )print flush
    {
    (%lineedit)(r)file
    dup bytesavailable string readline pop
    eval == flush
    } stopped { quit } if
} loop

2

JavaScript(208文字を圧縮)

わかりやすくするために、これは圧縮するのコード(JS-Fiddle)です。

function math(match, leftDigit, operator, rightDigit, offset, string) {
    var L = parseFloat(leftDigit)
    var R = parseFloat(rightDigit)
    switch (operator)
    {
        case '*': return L*R;
        case '/': return L/R;
        case '+': return L+R;
        case '-': return L-R;
    }
};

str = prompt("Enter some math:", "-2 + 6 / 2 * 8 - 1 / 2.5 - 18").replace(/ /g, "");
var mathRegex = /(\-?\d+\.?\d*)([\*\/\+\-])(\-?\d+\.?\d*)/;
while(mathRegex.test(str)) {
    str = str.replace(mathRegex, math);
}
alert(str)

ここでは、208文字に圧縮されています(そのJS-Fiddle):

function m(x,l,o,r){
    L=(f=parseFloat)(l);
    R=f(r);
    return o=='*'?L*R:o=='/'?L/R:o=='+'?L+R:L-R;
};

M=/(\-?\d+\.?\d*)([\*\/\+\-])(\-?\d+\.?\d*)/;
for(s=prompt().replace(/ /g, "");M.test(s);s=s.replace(M,m)){};
alert(s)

行をセミコロンで終了しているため、すべての削除可能な空白は文字カウントのために無視されましたが、明確にするために残しました。


2

ハスケル-124

let p=let f[x]=Just$read x;f(x:o:r)=lookup o[("-",(-)),("+",(+)),("*",(*)),("/",(/))]<*>f r<*>Just(read x)in f.reverse.words

結果はMaybeモナドに包まれます

λ: p"-2 + 6 / 2 * 8 - 1 / 2.5 - 18"
Just (-12.0)

また、<*>からのインポートが必要ですが、インポートControl.Applicativeはコードの外部で実行できるため、許可されていることを望みます。


2

C# (234) (231) (229) (223) (214)

class A{void Main(string[]s){var n=1;var o="";var r=0F;foreach(var t in s){if(n>0){var v=float.Parse(t);if(o=="")r=v;if(o=="+")r+=v;if(o=="-")r-=v;if(o=="*")r*=v;if(o=="/")r/=v;}o=t;n=-n;}System.Console.Write(r);}}

class A{
    void Main(string[] s)
    {
      var n = 1;
      var o = "";
      var r = 0F;

      foreach (var t in s)
      {
        if (n > 0)
        {
          var v = float.Parse(t);
          if (o == "") r = v;
          if (o == "+") r += v;
          if (o == "-") r -= v;
          if (o == "*") r *= v;
          if (o == "/") r /= v;
        }
        o = t;
        n = -n;
      }
      System.Console.Write(r);
    }
}

「1 + 1」に対して「0」を取得しています。 IDEONE-
ロブ

@Mike入力は、stdinではなく引数として。
ヨハネ


1

Java 11、151(ラムダ関数として)

s->{float r=0,t;int o=43,q;for(var x:s.split(" ")){if(x.length()>1|(q=x.charAt(0))>47){t=new Float(x);r=o<43?r*t:o<44?r+t:o<46?r-t:r/t;}o=q;}return r;}

String入力を受け取り、floatを出力するLambda関数。

オンラインでお試しください。

Java 11、241バイト(要求されたI / Oを備えた完全なプログラムとして)

interface M{static void main(String[]a){float r=0,t;int o=43,q;for(var x:new java.util.Scanner(System.in).nextLine().split(" ")){if(x.length()>1|(q=x.charAt(0))>47){t=new Float(x);r=o<43?r*t:o<44?r+t:o<46?r-t:r/t;}o=q;}System.out.print(r);}}

STDINを介して文字列行を取得し、STDOUTに出力する完全なプログラム。

オンラインでお試しください。

説明:

interface M{                  // Class
  static void main(String[]a){//  Mandatory main-method
    float r=0,                //   Result float, starting at 0
          t;                  //   Temp float
    int o=43,                 //   Operator flag, starting at '+'
        q;                    //   Temp operator flag
    for(var x:new java.util.Scanner(System.in)
                              //   Create an STDIN-reader
               .nextLine()    //   Get the user input
               .split(" ")){  //   Split it on spaces, and loop over it:
      if(x.length()>1         //    If the current String length is larger than 1
                              //    (work-around for negative values)
         |(q=x.charAt(0))>47){//    Or the first character is an operator
                              //    (and set `q` to this first character at the same time)
        t=new Float(x);       //     Convert the String to a float, and set it to `t`
        r=                    //     Change `r` to:
          o<43?               //      If `o` is a '*':
            r*t               //       Multiply `r` by `t`
          :o<44?              //      Else-if `o` is a '+':
            r+t               //       Add `r` and `t` together
          :o<46?              //      Else-if `o` is a '-':
            r-t               //       Subtract `t` from `r`
          :                   //      Else (`o` is a '/'):
            r/t;}             //       Divide `r` by `t`
      o=q;}                   //    And at the end of every iteration: set `o` to `q`
    System.out.print(r);}}    //    Print the result `r` to STDOUT

1

05AB1E、30 バイト

#ćs2ôívy`…+-*sk©i-ë®>i+ë®<i*ë/

オンラインそれを試してみたり、すべてのテストケースを検証します

説明:

#           # Split the (implicit) input-string by spaces
 ć          # Pop the list, and push the remainder and first item separated to the stack
  s         # Swap so the remainder is at the top of the stack
   2ô       # Split it into parts of size 2 (operator + number pairs)
     í      # Reverse each pair so the numbers are before the operators
v           # Loop over each of the pairs:
 y`         #  Push the number and operator separated to the stack
   …+-*     #  Push a string "+-*"
       sk   #  Get the index of the operator in this string
         ©  #  Store this index in the register (without popping)
   i        #  If the index is 1 (the "-"):
    -       #   Subtract the numbers from each other
   ë®>i     #  Else-if the index is 0 (the "+"):
       +    #   Add the numbers together
   ë®<i     #  Else-if the index is 2 (the "*"):
       *    #   Multiply the numbers with each other
   ë        #  Else (the index is -1, so "/"):
    /       #   Divide the numbers from each other
            # (and output the result implicitly)

eval組み込みが許可されている場合、これは代替アプローチ(16バイト)である可能性があります

#ćs2ôJv…(ÿ)y«}.E

オンラインそれを試してみたり、すべてのテストケースを検証します

説明:

#ćs2ô    # Same as above
     J   # Join each operator+number pair together to a single string
v        # Loop over the operator+number strings:
 …(ÿ)    #  Surround the top of the stack in parenthesis
     y«  #  And append the operator+number string
}.E      # After the loop: evaluate the string using a Python-eval

これは、ビルトインを使用"-2 + 6 / 2 * 8 - 1 / 2.5 - 18"する"((((((-2)+6)/2)*8)-1)/2.5)-18"前に変更されますeval.E直接使用すると、演算子の優先順位が*/over +-になるため、最初に括弧を使用した変換が行われます)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.