Una calculadora como una lista de números y operadores.

20

Su tarea es tomar una lista de argumentos que sean enteros u operadores, y analizarlos así:

  1. Hay un operador actual, que comienza como +.

  2. Cada vez que se encuentra un operador, el operador actual cambiará a él.

  3. Los operadores posibles son: "+", "-", "*", "/" y "%", que corresponden a sus significados en C y la mayoría de los lenguajes.

  4. Hay una solución en ejecución que comienza en 0.

  5. Cada vez que se encuentra un número entero, la solución se modifica por el número dependiendo del operador; por ejemplo, si el operador es "/", entonces la solución se divide por el número.

  6. Si una operación daría como resultado un número mixto (es decir, con un decimal), debe volver a un número entero (es decir, el decimal debe cortarse).

  7. Salida de la solución final.

Por ejemplo:

Los argumentos 5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14darían como resultado:

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

Las entradas serán como argumentos de línea de comando o función, o un equivalente para su idioma.

¡El código más corto gana!

Trebuchette
fuente
cuando dices significados en C, ¿quieres decir exactamente como lo hacen en C, o está bien si se %redondea hacia -inf en lugar de 0?
Maltysen
@Maltysen: Sea cual sea tu idioma.
Trebuchette
3
¿Pueden los enteros de entrada ser negativos?
Dennis
Los puntos 3 y 6 se contradicen entre sí: en C y en la mayoría de los lenguajes, la división de enteros se redondea a cero en lugar de al piso.
Peter Taylor
Sería interesante ver otro desafío similar a este, pero incluyendo la precedencia de paréntesis ...
Joshpbarron

Respuestas:

6

Pyth - 24 23 22 20 bytes

¡2 bytes guardados gracias a @issacg y 1 gracias a @orlp!

Los usos se reducen con el caso base 0y se comprueba si 'está en repr para detectar la cadena frente a int.

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

No funciona en línea porque uso eval completo que está deshabilitado en línea por razones de seguridad. Toma de entrada de la entrada estándar en una lista como tal: 5, 8, 25, "*", 9, 6, 2, "-", 104, "/", 4, 7, "+", 6.

Maltysen
fuente
Puede guardar 2 bytes cambiando de ?a .x, porque solo el bloque else puede lanzar una excepción, y lo hará cada vez. Sin Kembargo, ya no puedes usar . u.xsv++GbH&=bHG+\+QZespecíficamente.
isaacg
6

JavaScript (ES6) 53

Una función que toma una matriz como entrada.

Ejecute el fragmento en Firefox para probar.

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
fuente
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)

Esto crea una función sin nombre que acepta una cadena como entrada y devuelve un entero.

Sin golf:

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

Problema solucionado y ahorró 2 bytes gracias a Glen O.

Alex A.
fuente
Julia se queja de que o is not definedcuando intentas ejecutar la función recién. Intenta ejecutar la función "o = ifloor ..." en Main, en lugar de dentro de la función (ver aquí github.com/JuliaLang/julia/issues/2386 ). ¿Puedo sugerir s->(o=0;p="+";for i=split(s) isdigit(i)?o=eval(parse("ifloor($o$p$i)")):p=i;end;o)?
Glen O
@GlenO No sé cómo no entendí eso. : / Gracias, arreglado.
Alex A.
4

elisp, 101 bytes

Con los argumentos pasados ​​como una lista citada: ej. (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))

Versión con nuevas líneas:

    (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))
Espeso
fuente
4

CJam, 24 bytes

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

Este es un programa completo que lee la entrada como argumentos de línea de comandos.

Para probar el código en línea en el intérprete de CJam (que no admite argumentos de línea de comandos), reemplace eacon lS/para leer desde STDIN simulado.

Cómo funciona

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
fuente
3

JavaScript, 85 bytes

r=0;o="+";prompt().split(" ").forEach(t=>+t+1?r=parseInt(eval(r+o+ +t)):o=t);alert(r)
Ypnypn
fuente
¿Por qué o+ +t? De todos modos, está creando una cadena, no es necesario convertir a número. Además, .forEachno tiene lugar en Code Golf: use.map
edc65
... y ~~ en lugar de 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

Sin golf:

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
fuente
3

Powershell, 57 bytes

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

sin golf

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

Si la variable implícita en for-each es un operador en lugar de un número, Invoke-Expression (POSH's eval()) fallará y el estado de ejecución $?será falso.

Floor en POSH es difícil de manejar, $foo=[math]::floor($foo)y $foo-=$foo%1fue la alternativa de golf que se me ocurrió.

tomkandy
fuente
Agradable. Lo leí un poco más literalmente asumiendo una entrada de cadena y analizándola en espacios, luego ifingiriendo dígitos, pero esencialmente lo mismo. 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 (con la extensión eval, + dc), 102

(La puntuación incluye +1 para la opción -r de sed.)

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

Transforma la expresión de entrada a notación polaca inversa y luego la usa dcpara evaluarla.

Prueba de salida:

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

CJam, 34 bytes

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

Pruébalo en línea

Pensé que esto sería bastante razonable. Pero no fui lo suficientemente rápido para publicarlo como para ser la respuesta más corta de CJam al menos por un momento. :(

Reto Koradi
fuente
2

Python 3: 131 bytes 129 bytes 121 bytes 116 bytes

Gracias a Maltysen por eliminar dos bytes, Beta Decay por eliminar 8 y Steven Rumbalski por eliminar 5.

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

Estoy tratando de encontrar una manera de reducir la longitud de la declaración if, pero por ahora esto parece lo más complejo posible. Toma la entrada como una lista.

col
fuente
puede guardar algunos bytes en la sangría y reemplazar intcon//1
Maltysen
Además, ¿por qué los padres en el 'if?
Maltysen
@ Maltysen grita, olvidé que no necesitaba los paréntesis en la declaración if. Gracias. No creo que se permita usar // 1, aunque no pensé en usarlo, ya que parece dejar un 0 al final (por ejemplo, 10.0) que no creo que esté permitido.
cole
No creo que necesites ese espacio entre iny la cita.
Maltysen
Puede guardar algunos bytes suponiendo que la lista se pasa en los argumentos de la función y deshacerse de ella .split().
Beta Decay
2

Bash, 69

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

Esto solo funciona con enteros no negativos: no está claro en la pregunta si está bien o no.

Trauma digital
fuente
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}

Manifestación:

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

Sin golf:

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
fuente
1

gcc (con advertencias) 165 (si el final de línea cuenta como 1)

#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);}

Pero si lo está compilando con mingw32, debe desactivar el globbing (consulte https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ) compilando así:

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

Perl 5.10+, 52 bytes

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

Manifestación:

$ 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

(Tenga en cuenta que *se debe escapar en mi shell para que no se interprete como un patrón global).

Sin golf:

$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
fuente
1

C #, 132165168 bytes

Esta función asume que la entrada es válida. Esto es difícil para C # dado que no hay evalequivalente.

¡Gracias edc65 por guardar 33 bytes!

Sangrado por claridad.

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
fuente
Puede eliminar la mayoría de las nuevas líneas.
Trebuchette
No he contado ninguna línea nueva o espacio en blanco insignificante.
Hand-E-Food
1
132 usando ?:->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

Prueba de funcionamiento:

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