Ein Taschenrechner als Liste von Zahlen und Operatoren

20

Ihre Aufgabe ist es, eine Liste von Argumenten zu erstellen, die entweder Ganzzahlen oder Operatoren sind, und diese wie folgt zu analysieren:

  1. Es gibt einen aktuellen Operator, der mit + beginnt.

  2. Jedes Mal, wenn ein Operator gefunden wird, wechselt der aktuelle Operator zu ihm.

  3. Die möglichen Operatoren sind: "+", "-", "*", "/" und "%", die ihrer Bedeutung in C und den meisten Sprachen entsprechen.

  4. Es wird eine laufende Lösung geführt, die bei 0 beginnt.

  5. Jedes Mal, wenn eine Ganzzahl gefunden wird, wird die Lösung abhängig vom Operator um die Zahl geändert. zB wenn der Operator "/" ist, wird die Lösung durch die Zahl geteilt.

  6. Wenn eine Operation zu einer gemischten Zahl führen würde (dh mit einer Dezimalzahl), muss sie auf eine Ganzzahl zurückgesetzt werden (dh die Dezimalzahl muss abgeschnitten werden).

  7. Geben Sie die endgültige Lösung aus.

Beispielsweise:

Die Argumente 5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14würden ergeben:

  5 8  25 * 9   6    2    - 104  / 4    7      + 6 % 14
0 5 13 38   342 2052 4104   4000   1000 142   148    8  -> 8

Die Eingaben erfolgen als Befehlszeilen- oder Funktionsargumente oder als Entsprechung für Ihre Sprache.

Kürzester Code gewinnt!

Trebuchette
quelle
Wenn Sie Bedeutungen in C sagen, meinen Sie damit genau das Gleiche wie in C, oder ist es in Ordnung, wenn Sie in %Richtung -inf statt 0 runden?
Maltysen
@Maltysen: Was auch immer deine Sprache tut.
Trebuchette,
3
Können die Ganzzahlen aus der Eingabe negativ sein?
Dennis
Die Punkte 3 und 6 widersprechen sich: In C und den meisten Sprachen rundet die Ganzzahldivision eher in Richtung Null als in Richtung Boden.
Peter Taylor
Es wäre interessant, eine weitere Herausforderung zu sehen, die dieser ähnelt, aber den Vorrang in Klammern einschließt ...
Joshpbarron,

Antworten:

6

Pyth - 24 23 22 20 Bytes

2 Bytes gespart dank @issacg und 1 dank @orlp!

Verwendungsreduzierung mit Basisfall von 0und Überprüfung auf 'Repräsentation zur Erkennung von String vs. Int.

u.xsv++GbH&=bHG+\+QZ

Funktioniert nicht online, da ich Full Eval verwende, das aus Sicherheitsgründen online deaktiviert ist. Nimmt die Eingabe von stdin in einer Liste als solche: 5, 8, 25, "*", 9, 6, 2, "-", 104, "/", 4, 7, "+", 6.

Maltysen
quelle
Sie können 2 Bytes speichern , indem Sie von einem Wechsel ?zu .x, da nur der else - Block eine Ausnahme auslösen kann, und es wird so jedes Mal tun. Du kannst es aber nicht Kmehr benutzen . u.xsv++GbH&=bHG+\+QZspeziell.
Isaacg
6

JavaScript (ES6) 53

Eine Funktion, die ein Array als Eingabe verwendet.

Führen Sie das Snippet zum Testen in Firefox aus.

f=a=>a.map(t=>t<'0'?o=t:v=eval(v+o+t)|0,v=0,o='+')&&v

// TEST
out=x=>O.innerHTML=x;

input = [5,8,25,"*",9,6,2,"-",104,"/",4,7,"+",6,"%",14];
out(input.join(' ')+' -> '+f(input));

function go() {
  i=I.value.split(/ +/),out(I.value+' -> '+f(i))
}  
<pre id=O></pre>
Your test:<input id=I><button onclick='go()'>GO</button>

edc65
quelle
4

Julia, 85 83 Bytes

s->(o=0;p="+";for i=split(s) isdigit(i)?o=eval(parse("ifloor($o$p$i)")):(p=i)end;o)

Dadurch wird eine unbenannte Funktion erstellt, die eine Zeichenfolge als Eingabe akzeptiert und eine Ganzzahl zurückgibt.

Ungolfed:

function f(s::String)
    # Assign the starting output value o and operator p
    o = 0
    p = "+"

    # Split the input string into an array on spaces
    for i = split(s)
        if isdigit(i)
            # Assign o using string interpolation
            o = eval(parse("ifloor($o $p $i)"))
        else
            # Assign p to the new operator
            p = i
        end
    end
end

Problem behoben und 2 Bytes dank Glen O gespart.

Alex A.
quelle
Julia beschwert sich darüber, o is not definedwenn Sie versuchen, die Funktion neu zu starten. Es wird versucht, die Funktion "o = ifloor ..." in Main und nicht in der Funktion auszuführen (siehe hier github.com/JuliaLang/julia/issues/2386 ). Darf ich vorschlagen s->(o=0;p="+";for i=split(s) isdigit(i)?o=eval(parse("ifloor($o$p$i)")):p=i;end;o)?
Glen O
@ GlenO Ich weiß nicht, wie ich das nicht verstanden habe. : / Danke, behoben.
Alex A.
4

Elisp, 101 Bytes

Mit den Argumenten als Anführungszeichen übergeben: zB (c '(5 5 * 10))

    (defun c(a)(let((f 0)(o '+))(dolist(x a)(if(not(integerp x))(setf o x)(setq f (eval(list o f x)))))f))

Version mit neuen Zeilen:

    (defun c (a)
      (let ((f 0)
            (o '+))
        (dolist (x a)
          (if (not (integerp x))
              (setf o x) 
            (setq f (eval (list o f x)))))
        f))
Suppe
quelle
4

CJam, 24 Bytes

0'+ea+{_A,s&O{:O;}?S}%s~

Dies ist ein vollständiges Programm, das die Eingabe als Befehlszeilenargumente liest.

Um den Code online im CJam-Interpreter zu testen (der keine Befehlszeilenargumente unterstützt), ersetzen Sie ihn eamit lS/, um aus simuliertem STDIN zu lesen.

Wie es funktioniert

0'+                       Push a 0 and the character '+'.
   ea                     Push the array of command-line arguments.
     +                    Prepend the character to the array.
      {             }%    For each element:
       _                    Push a copy.
        A,s                 Push "0123456789".
           &                Intersect the copy with the string of digits.
             {   }?         If the intersection is non-empty:
            O                 The element is a number. Push O.
              :O;             The element is an operator. Save it in O.
                   S        Push a space.
                      s~  Flatten the array of strings and evaluate it.
Dennis
quelle
3

JavaScript, 85 Bytes

r=0;o="+";prompt().split(" ").forEach(t=>+t+1?r=parseInt(eval(r+o+ +t)):o=t);alert(r)
Ypnypn
quelle
warum o+ +t? Sie bauen sowieso eine Zeichenkette, ohne sie in eine Zahl umwandeln zu müssen. Außerdem .forEachhat Code Golf keinen Platz: use.map
edc65
... und ~~ anstelle von parseInt ( codegolf.stackexchange.com/a/2788/21348 )
edc65
prompt(o="+",r=0).split(" ").forEach(t=>+t+1?r=+eval(r+o+ +t):o=t);alert(r)-> 75 Bytes.
Ismael Miguel
3

Lua, 142 Bytes

function f(s)o="+"r=0 for c in s:gmatch"%S+" do if tonumber(c)~=nil then loadstring("r=r"..o..c)() else o=c end r=math.floor(r)end print(r)end

Ungolfed:

function f(s)
    o="+" --original operator
    r=0 --return value
    for c in s:gmatch"%S+" do --split by spaces
        if tonumber(c)~=nil then --check if the current character is a number
            loadstring("r=r"..o..c)() --appends the current operator and current character ex "r=r+5" and then evaluates as another Lua script 
        else 
            o=c --if the character is not a number, it is the new operator
        end
        r=math.floor(r) --floor after each operation
    end 
    print(r) --print the result
end
Nikolai97
quelle
3

Powershell, 57 Bytes

$o="+"
$args|%{$r=iex "$r$o$_"
if(!$?){$o=$_}$r-=$r%1}
$r

ungolfed;

$operator="+"
$args | ForEach-Object
{
    $result = Invoke-Expression "$result $operator $_"
    if(!$?)
    {
        $operator=$_
    }
    $result -= $result % 1
}
$result

Wenn die implizite Variable in der for-each-Anweisung kein Zahl, sondern ein Operator ist, schlagen die POSH-Anweisungen (Invoke-Expression eval()) fehl und der Ausführungsstatus $?ist falsch.

Boden in POSH ist unhandlich - $foo=[math]::floor($foo)und $foo-=$foo%1war die golferischste Alternative, die ich mir vorstellen konnte.

Tomkandy
quelle
Nett. Ich las es ein bisschen wörtlicher, indem ich eine Zeichenketteneingabe annahm und sie nach Leerzeichen analysierte, dann ifnach Ziffern, aber im Wesentlichen gleich. 89 Bytes $o="+";$r=0;$args-split'\s+'|%{if($_-match'^\d+$'){$r=iex $r$o$_;$r-=$r%1}Else{$o=$_}};$r
AdmBorkBork
3

GNU Sed (mit der Erweiterung eval, + dc), 102

(Die Punktzahl enthält +1 für die Option -r für sed.)

s/.*/0 + &p/
s/([-+/*%]) ([0-9]+)/\2 \1/g
:
s/([-+/*%] )([0-9]+ )([0-9]+)/\1\2\1\3/
t
s/.*/dc<<<'&'/e

Wandelt den Eingabeausdruck in eine umgekehrte polnische Notation um und dcwertet sie dann aus.

Testausgang:

$ sed -rf calclist.sed <<< '5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14'
8
$ 
Digitales Trauma
quelle
2

CJam, 34 Bytes

'+0lS/{"+-*/%"1$#){@;\}{i2$~}?}/\;

Probieren Sie es online aus

Ich dachte, das wäre ziemlich vernünftig. Aber ich war nicht schnell genug, es zu veröffentlichen, um zumindest für einen Moment die kürzeste CJam-Antwort zu sein. :(

Reto Koradi
quelle
2

Python 3 - 131 Bytes 129 Bytes 121 Bytes 116 Bytes

Dank an Maltysen für das Abschneiden von zwei Bytes, Beta Decay für das Abschneiden von 8 Bytes und Steven Rumbalski für das Abschneiden von 5 Bytes.

def f(x):
    a,b="+",0
    for i in x:
        if i in"+-*/%":a=i
        else:b=int(eval(str(b)+a+i))
    return b

Ich versuche, einen Weg zu finden, um die Länge der if-Anweisung zu reduzieren, aber im Moment scheint dies so gut wie möglich zu funktionieren. Übernimmt die Eingabe als Liste.

cole
quelle
Sie können einige Bytes beim Einrücken und Ersetzen intdurch//1
Maltysen
auch, warum die parens im `wenn?
Maltysen
@ Maltysen Hoppla, ich habe vergessen, dass ich die Klammern in der if-Anweisung nicht benötigt habe. Vielen Dank. Ich denke nicht, dass die Verwendung von // 1 erlaubt ist, obwohl ich nicht daran gedacht habe, es zu verwenden, da es eine nachgestellte 0 (z. B. 10.0) zu hinterlassen scheint, was ich nicht für zulässig halte.
Cole
Ich glaube nicht, dass Sie diesen Zwischenraum inund das Zitat brauchen .
Maltysen
Sie könnten einige Bytes einsparen, indem Sie davon ausgehen, dass die Liste in den Funktionsargumenten übergeben wird, und diese entfernen .split().
Beta-Zerfall
2

Bash, 69

set -f
for t in $*
do
((1${t}1>2))&&((r${o-+}=$t))||o=$t
done
echo $r

Dies funktioniert nur mit nicht negativen ganzen Zahlen - es ist in der Frage nicht klar, ob dies in Ordnung ist oder nicht.

Digitales Trauma
quelle
2

Groovy, 79 Bytes

def f(x,a=0,b='+'){x.each{z->a=z=~/\d/?Eval.me(a+b+z)as int:a;b=z=~/\d/?b:z};a}

Demo:

groovy> f([5,8,25,'*',9,6,2,'-',104,'/',4,7,'+',6,'%', 14])
Result: 8

Ungolfed:

def f(x, a=0, b='+') {                                   
    x.each {z->
        a = z =~ /\d/ ? Eval.me(a+b+z) as int : a
        b = z =~ /\d/ ? b : z
    }
    a
}
egyb2h9
quelle
1

gcc (mit Warnungen) 165 (wenn das Zeilenende als 1 zählt)

#define A atoi(*a);break;case
o='+',s=0;main(c,a)char**a;{while(*++a)if(**a<48)o=**a;else switch(o){case'+':s+=A'-':s-=A'*':s*=A'/':s/=A'%':s%=A 0:;}printf("%d",s);}

Wenn Sie es jedoch mit mingw32 kompilieren, müssen Sie das Globbing deaktivieren (siehe https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html) ), indem Sie wie kompilieren:

gcc x.c C:\Applications\mingw32\i686-w64-mingw32\lib\CRT_noglob.o
Jerry Jeremiah
quelle
1

Perl 5.10+, 52 Bytes

perl -E '$o="+";/\D/?$o=$_:eval"\$x=int\$x$o$_"for@ARGV;say$x'

Demo:

$ perl -E '$o="+";/\D/?$o=$_:eval"\x=int\$x$o$_"for@ARGV;say$x' 5 8 25 \* 9 6 2 - 104 / 4 7 + 6 % 14
8

(Beachten Sie, dass *es in meiner Shell maskiert werden muss, damit es nicht als Glob-Muster interpretiert wird.)

Ungolfed:

$o="+";                      # Start with addition
/\D/ ? $o=$_                 # If not a number, update the current operator
     : eval"\$x=int\$x$o$_"  # Otherwise, make a string like '$x=int$x+1' and eval it
for@ARGV;                    # Repeat for each item in the argument list
say$x                        # Print the result
ThisSuitIsBlackNot
quelle
1

C #, 132 165 168 Bytes

Diese Funktion setzt voraus, dass die Eingabe gültig ist. Dies ist schwierig für C #, vorausgesetzt, es gibt keineeval Äquivalent gibt.

Danke edc65 für das Speichern von 33 Bytes!

Zur Verdeutlichung eingerückt.

int C(string[]a){
    int o=1,r=0,n;
    foreach(var b in a)
        n=int.TryParse(b,out n)
            ?r=o<0?r%n
              :o<1?r*n
              :o<2?r+n
              :o<4?r-n
                  :r/n
            :o=b[0]-42;
    return r;
}
Hand-E-Food
quelle
Sie können die meisten Zeilenumbrüche entfernen.
Trebuchette,
Ich habe keine Zeilenumbrüche oder unbedeutenden Leerzeichen gezählt.
Hand-E-Food
1
132 using ?:->int C(string[]a){int o=1,r=0,n;foreach(var b in a)n=int.TryParse(b,out n)?r=o<0?r%n:o<1?r*n:o<3?r+n:o<5?r-n:r/n:o=b[0]-42;return r;}
edc65
1

Ruby, 59 Bytes

a=0
o=?+
gets.split.map{|s|s=~/\d/?a=eval([a,s]*o):o=s}
p a

Testlauf:

$ ruby calc.rb <<< "5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14"
8
daniero
quelle