Notación polaca inversa


41

Debe evaluar una cadena escrita en notación polaca inversa y generar el resultado.

El programa debe aceptar una entrada y devolver la salida. Para los lenguajes de programación que no tienen funciones para recibir entrada / salida, puede asumir funciones como readLine / print.

No está permitido utilizar ningún tipo de "evaluación" en el programa.

Los números y operadores están separados por uno o más espacios.

Debe admitir al menos los operadores +, -, * y /.

Debe agregar soporte a los números negativos (por ejemplo, -4no es lo mismo que 0 4 -) y los números de coma flotante.

Puede suponer que la entrada es válida y sigue las reglas anteriores


Casos de prueba

Entrada:

-4 5 +

Salida:

1

Entrada:

5 2 /

Salida:

2.5

Entrada:

5 2.5 /

Salida:

2

Entrada:

5 1 2 + 4 * 3 - +

Salida:

14

Entrada:

4 2 5 * + 1 3 2 * + /

Salida:

2

8
Es una pena que no se permite eval, de lo contrario la solución GolfScript es 1 carácter: ~. :-P
Chris Jester-Young

55
Es por eso que no está permitido :-P, esta pregunta en StackOverflow recibió una respuesta de 4 caracteres con dc.

1
@SHiNKiROU: ¿Qué idioma requiere que uses evalpara analizar números? Suena bastante roto. (GolfScript es uno de esos lenguajes, que yo sepa. Creo que también está roto.)
Chris Jester-Young

3
¿Cómo es -4 no es lo mismo que 0 4 -?
Keith Randall

1
Creo que eval debería estar bien si solo fuera convertir cadenas a números. p.ej. en python eval(s)es mejor quefloat(s)
gnibbler

Respuestas:


15

Ruby - 95 77 caracteres

a=[]
gets.split.each{|b|a<<(b=~/\d/?b.to_f: (j,k=a.pop 2;j.send b,k))}
p a[0]

Toma entrada en stdin.

Código de prueba

[
  "-4 5 +",
  "5 2 /",
  "5 2.5 /",
  "5 1 2 + 4 * 3 - +",
  "4 2 5 * + 1 3 2 * + /",
  "12 8 3 * 6 / - 2 + -20.5 "
].each do |test|
  puts "[#{test}] gives #{`echo '#{test}' | ruby golf-polish.rb`}"
end

da

[-4 5 +] gives 1.0
[5 2 /] gives 2.5
[5 2.5 /] gives 2.0
[5 1 2 + 4 * 3 - +] gives 14.0
[4 2 5 * + 1 3 2 * + /] gives 2.0
[12 8 3 * 6 / - 2 + -20.5 ] gives 10.0

A diferencia de la versión C, esto devuelve el último resultado válido si hay números adicionales agregados a la entrada que parece.


1
Puedes afeitar a un personaje usando el mapa en lugar de cada uno
addison

10

Python - 124 caracteres

s=[1,1]
for i in raw_input().split():b,a=map(float,s[:2]);s[:2]=[[a+b],[a-b],[a*b],[a/b],[i,b,a]]["+-*/".find(i)]
print s[0]

Python - 133 caracteres

s=[1,1]
for i in raw_input().split():b,a=map(float,s[:2]);s={'+':[a+b],'-':[a-b],'*':[a*b],'/':[a/b]}.get(i,[i,b,a])+s[2:]
print s[0]

1
Me gusta la manipulación de la pila.
Alexandru

2
No se puede tener 0como segundo operando ...
JBernardo

2
[a/b]debe reemplazarse b and[a/b]para que pueda tener 0 como segundo operando.
flornquake

10

Esquema, 162 caracteres

(Se agregaron saltos de línea para mayor claridad; todos son opcionales).

(let l((s'()))(let((t(read)))(cond((number? t)(l`(,t,@s)))((assq t
`((+,+)(-,-)(*,*)(/,/)))=>(lambda(a)(l`(,((cadr a)(cadr s)(car s))
,@(cddr s)))))(else(car s)))))

Versión completamente formateada (sin golf):

(let loop ((stack '()))
  (let ((token (read)))
    (cond ((number? token) (loop `(,token ,@stack)))
          ((assq token `((+ ,+) (- ,-) (* ,*) (/ ,/)))
           => (lambda (ass) (loop `(,((cadr ass) (cadr stack) (car stack))
                                    ,@(cddr stack)))))
          (else (car stack)))))

Comentario seleccionado

`(,foo ,@bar)es lo mismo que (cons foo bar)(es decir, (efectivamente ) devuelve una nueva lista con fooantepuesto a bar), excepto que es un carácter más corto si comprime todos los espacios.

Por lo tanto, puede leer las cláusulas de iteración como (loop (cons token stack))y (loop (cons ((cadr ass) (cadr stack) (car stack)) (cddr stack)))si eso es más fácil para usted.

`((+ ,+) (- ,-) (* ,*) (/ ,/))crea una lista de asociación con el símbolo + emparejado con el procedimiento + , y del mismo modo con los otros operadores. Por lo tanto, se trata de una simple tabla de búsqueda de símbolos (las palabras simples aparecen (read)como símbolos, por lo que no tokenes necesario seguir procesando ). Las listas de asociación tienen búsqueda O (n), y por lo tanto solo son adecuadas para listas cortas, como es el caso aquí. :-PAGS

† Esto no es técnicamente exacto, pero, para los programadores que no son de Lisp, tiene una idea bastante correcta.


¿Puedes leer eso? ¿Seriamente?

1
@ M28: La versión sin golf, sí. Programa en Scheme de forma semi-regular (para programas reales y serios).
Chris Jester-Young

Desafortunadamente, Scheme es un lenguaje detallado y muy difícil de jugar al golf. Por lo tanto, no me sorprendería ver que alguna presentación de Perl supera a esta.
Chris Jester-Young

77
Me gustan los cuatro smileys en la versión de golf.
tomsmeding

2
lambda (ass)+1 para la elección del nombre de la variable: P
Downgoat

7

c - 424 caracteres necesarios

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define O(X) g=o();g=o() X g;u(g);break;
char*p=NULL,*b;size_t a,n=0;float g,s[99];float o(){return s[--n];};
void u(float v){s[n++]=v;};int main(){getdelim(&p,&a,EOF,stdin);for(;;){
b=strsep(&p," \n\t");if(3>p-b){if(*b>='0'&&*b<='9')goto n;switch(*b){case 0:
case EOF:printf("%f\n",o());return 0;case'+':O(+)case'-':O(-)case'*':O(*)
case'/':O(/)}}else n:u(atof(b));}}

Asume que tiene una libc lo suficientemente nueva como para incluirla getdelimen stdio.h. El enfoque es directo, toda la entrada se lee en un búfer, luego se tokeniza con strsepy usamos la longitud y el carácter inicial para determinar la clase de cada uno. No hay protección contra malas entradas. Aliméntalo "+ - * / + - ...", y felizmente sacará cosas de la memoria "debajo" de la pila hasta que falle. Todos los no operadores se interpretan como flotantes, lo atofque significa un valor cero si no parecen números.

Legible y comentado:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *p=NULL,*b;
size_t a,n=0;
float g,s[99];
float o(){        /* pOp */
  //printf("\tpoping '%f'\n",s[n-1]);
  return s[--n];
};
void u(float v){  /* pUsh */
  //printf("\tpushing '%f'\n",v);
  s[n++]=v;
};
int main(){
  getdelim(&p,&a,EOF,stdin); /* get all the input */
  for(;;){
    b=strsep(&p," \n\t"); /* now *b though *(p-1) is a token and p
                 points at the rest of the input */
    if(3>p-b){
      if (*b>='0'&&*b<='9') goto n;
      //printf("Got 1 char token '%c'\n",*b);
      switch (*b) {
      case 0:
      case EOF: printf("%f\n",o()); return 0;
      case '+': g=o(); g=o()+g; u(g); break;
      case '-': g=o(); g=o()-g; u(g); break;
      case '*': g=o(); g=o()*g; u(g); break;
      case '/': g=o(); g=o()/g; u(g); break;
    /* all other cases viciously ignored */
      } 
    } else { n:
      //printf("Got token '%s' (%f)\n",b,atof(b));
      u(atof(b));
    }
  }
}

Validación:

 $ gcc -c99 rpn_golf.c 
 $ wc rpn_golf.c
  9  34 433 rpn_golf.c
 $ echo -4 5 + | ./a.out
1.000000
 $ echo 5 2 / | ./a.out
2.500000
 $ echo 5 2.5 / | ./a.out
2.000000

Je! Tengo que citar cualquier cosa que contenga *...

 $ echo "5 1 2 + 4 * 3 - +" | ./a.out
14.000000
 $ echo "4 2 5 * + 1 3 2 * + /" | ./a.out
2.000000

y mi propio caso de prueba

 $ echo "12 8 3 * 6 / - 2 + -20.5 " | ./a.out
-20.500000

Puedes proteger algunos personajes reemplazándolos casecon un makro.
FUZxxl

7

Haskell (155)

f#(a:b:c)=b`f`a:c
(s:_)![]=print s
s!("+":v)=(+)#s!v
s!("-":v)=(-)#s!v
s!("*":v)=(*)#s!v
s!("/":v)=(/)#s!v
s!(n:v)=(read n:s)!v
main=getLine>>=([]!).words

Puede eliminar 9 caracteres cambiando "(s: _)! [] = S" a "(s: _)! [] = Print s" y "main = getLine >> = putStrLn.show. ([]! .words)" a "principal = getLine >> = ([]) palabras"!.
Fors

Y luego elimine algunos otros caracteres mediante el uso de una declaración de caso de una línea.
Fors

s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!vahorraría 14 caracteres.
Fors

7

MATLAB - 158 , 147

C=strsplit(input('','s'));D=str2double(C);q=[];for i=1:numel(D),if isnan(D(i)),f=str2func(C{i});q=[f(q(2),q(1)) q(3:end)];else q=[D(i) q];end,end,q

(la entrada se lee desde la entrada del usuario, la salida se imprime).


A continuación se muestra el código prettificado y comentado, prácticamente implementa el algoritmo de postfix descrito (con el supuesto de que las expresiones son válidas):

C = strsplit(input('','s'));         % prompt user for input and split string by spaces
D = str2double(C);                   % convert to numbers, non-numeric are set to NaN
q = [];                              % initialize stack (array)
for i=1:numel(D)                     % for each value
    if isnan(D(i))                   % if it is an operator
        f = str2func(C{i});          % convert op to a function
        q = [f(q(2),q(1)) q(3:end)]; % pop top two values, apply op and push result
    else
        q = [D(i) q];                % else push value on stack
    end
end
q                                    % show result

Prima:

En el código anterior, suponemos que los operadores son siempre binario ( +, -, *, /). Podemos generalizarlo usando nargin(f)para determinar la cantidad de argumentos que requiere el operando / función, y extraer la cantidad correcta de valores de la pila en consecuencia, como en:

f = str2func(C{i});
n = nargin(f);
args = num2cell(q(n:-1:1));
q = [f(args{:}) q(n+1:end)];

De esa manera podemos evaluar expresiones como:

str = '6 5 1 2 mean_of_three 1 + 4 * +'

donde mean_of_threees una función definida por el usuario con tres entradas:

function d = mean_of_three(a,b,c)
    d = (a+b+c)/3;
end

6

Perl (134)

@a=split/\s/,<>;/\d/?push@s,$_:($x=pop@s,$y=pop@s,push@s,('+'eq$_?$x+$y:'-'eq$_?$y-$x:'*'eq$_?$x*$y:'/'eq$_?$y/$x:0))for@a;print pop@s

La próxima vez, voy a usar la cosa de expresión regular recursiva.

Sin golf:

@a = split /\s/, <>;
for (@a) {
    /\d/
  ? (push @s, $_)
  : ( $x = pop @s,
      $y = pop @s,
      push @s , ( '+' eq $_ ? $x + $y
                : '-' eq $_ ? $y - $x
                : '*' eq $_ ? $x * $y
                : '/' eq $_ ? $y / $x
                : 0 )
      )
}
print(pop @s);

Pensé que F # es el único lenguaje de programación de mis sueños ...


Tengo una implementación más corta de Perl 5.
dolmen

6

Windows PowerShell, 152 181 192

En forma legible, porque ahora son solo dos líneas sin posibilidad de separarlas:

$s=@()
switch -r(-split$input){
  '\+'        {$s[1]+=$s[0]}
  '-'         {$s[1]-=$s[0]}
  '\*'        {$s[1]*=$s[0]}
  '/'         {$s[1]/=$s[0]}
  '-?[\d.]+'  {$s=0,+$_+$s}
  '.'         {$s=$s[1..($s.count)]}}
$s

30-01-2010 11:07 (192) - Primer intento.

2010-01-30 11:09 (170) - Convertir la función en un bloque de script resuelve los problemas de alcance. Solo hace que cada invocación sea dos bytes más larga.

30-01-2010 11:19 (188) - No resolvió el problema del alcance, el caso de prueba simplemente lo enmascaró. Sin embargo, se eliminó el índice de la salida final y se eliminó un salto de línea superfluo. Y cambió el doble a float.

30-01-2010 11:19 (181) - Ni siquiera puedo recordar mi propio consejo. La conversión a un tipo numérico se puede hacer en un solo carácter.

30-01-2010 11:39 (152) - Gran reducción al usar la coincidencia de expresiones regulares en switch. Resuelve completamente los problemas de alcance anteriores con el acceso a la pila para reventarla.


5

Raqueta 131:

(let l((s 0))(define t(read))(cond[(real? t)
(l`(,t,@s))][(memq t'(+ - * /))(l`(,((eval t)(cadr s)
(car s)),@(cddr s)))][0(car s)]))

Saltos de línea opcionales.

Basado en la solución de Chris Jester-Young para Scheme.


4

Python, 166 caracteres

import os,operator as o
S=[]
for i in os.read(0,99).split():
 try:S=[float(i)]+S
 except:S=[{'+':o.add,'-':o.sub,'/':o.div,'*':o.mul}[i](S[1],S[0])]+S[2:]
print S[0]

El raw_input()código de uso no se divide en varias líneas.
JPvdMerwe

Entonces podría intentar: from operator import*y reemplazar o.divcon div.
JPvdMerwe

4

Python 3, 119 bytes

s=[]
for x in input().split():
 try:s+=float(x),
 except:o='-*+'.find(x);*s,a,b=s;s+=(a+b*~-o,a*b**o)[o%2],
print(s[0])

Entrada: 5 1 1 - -7 0 * + - 2 /

Salida: 2.5

(Puede encontrar una versión de Python 2 de 128 caracteres en el historial de edición).


Bastante inteligente :) Me gusta cómo no necesitas /en la cadena.
Daniel Lubarov


@EriktheOutgolfer que se rompe con a ZeroDivisionErrorcuando el segundo operando es 0 (por ejemplo 5 0 +).
flornquake el

Puede guardar 1 carácter utilizando el ord(x) - 42método
frederick99

@ frederick99 No veo cómo.
flornquake

3

JavaScript (157)

Este código supone que existen estas dos funciones: readLine e print

a=readLine().split(/ +/g);s=[];for(i in a){v=a[i];if(isNaN(+v)){f=s.pop();p=s.pop();s.push([p+f,p-f,p*f,p/f]['+-*/'.indexOf(v)])}else{s.push(+v)}}print(s[0])

Más corto si usa en prompt()lugar de readLine()(y tal alert()vez en lugar de print()coincidir prompt()).
nyuszika7h

3

Perl, 128

Esto no es realmente competitivo al lado de la otra respuesta de Perl, pero explora una ruta diferente (subóptima).

perl -plE '@_=split" ";$_=$_[$i],/\d||
do{($a,$b)=splice@_,$i-=2,2;$_[$i--]=
"+"eq$_?$a+$b:"-"eq$_?$a-$b:"*"eq$_?
$a*$b:$a/$b;}while++$i<@_'

Los caracteres cuentan como diff a una simple perl -e ''invocación.


2

Python, 161 caracteres:

from operator import*;s=[];i=raw_input().split(' ')
q="*+-/";o=[mul,add,0,sub,0,div]
for c in i:
 if c in q:s=[o[ord(c)-42](*s[1::-1])]+s 
 else:s=[float(c)]+s
print(s[0])

2

PHP, 439 265 263 262 244 240 caracteres

<? $c=fgets(STDIN);$a=array_values(array_filter(explode(" ",$c)));$s[]=0;foreach($a as$b){if(floatval($b)){$s[]=$b;continue;}$d=array_pop($s);$e=array_pop($s);$s[]=$b=="+"?$e+$d:($b=="-"?$e-$d:($b=="*"?$e*$d:($b=="/"?$e/$d:"")));}echo$s[1];

Este código debería funcionar con stdin, aunque no se ha probado con stdin.

Se ha probado en todos los casos, la salida (y el código) para el último está aquí:
http://codepad.viper-7.com/fGbnv6

Ungolfed, 314 330 326 caracteres

<?php
$c = fgets(STDIN);
$a = array_values(array_filter(explode(" ", $c)));
$s[] = 0;
foreach($a as $b){
    if(floatval($b)){
        $s[] = $b;
        continue;
    }
    $d = array_pop($s);
    $e = array_pop($s);
    $s[] = $b == "+" ? $e + $d : ($b == "-" ? $e - $d : ($b == "*" ? $e * $d : ($b == "/" ? $e / $d :"")));
}
echo $s[1];

Cita de la descripción de la tarea: »Para lenguajes de programación que no tienen funciones para recibir entrada / salida, puede asumir funciones como readLine / print.« - demostrablemente PHP tiene funciones para hacerlo, por lo tanto, la suposición es incorrecta.
Joey

Lo actualicé para usar stdin y lo jugué un poco más.
Kevin Brown

2

flex - 157

%{
float b[100],*s=b;
#define O(o) s--;*(s-1)=*(s-1)o*s;
%}
%%
-?[0-9.]+ *s++=strtof(yytext,0);
\+ O(+)
- O(-)
\* O(*)
\/ O(/)
\n printf("%g\n",*--s);
.
%%

Si no está familiarizado, compile con flex rpn.l && gcc -lfl lex.yy.c


2

Python, 130 caracteres

Serían 124 caracteres si lo dejamos caer b and(que faltan algunas de las respuestas de Python). ¡Y incorpora 42!

s=[]
for x in raw_input().split():
 try:s=[float(x)]+s
 except:b,a=s[:2];s[:2]=[[a*b,a+b,0,a-b,0,b and a/b][ord(x)-42]]
print s[0]

Muy buena respuesta. Pero cuento 130 caracteres. ;)
flornquake

@flornquake tienes razón, gracias por la corrección.
Daniel Lubarov

2

Python 3, 126 132 caracteres

s=[2,2]
for c in input().split():
    a,b=s[:2]
    try:s[:2]=[[a+b,b-a,a*b,a and b/a]["+-*/".index(c)]]
    except:s=[float(c)]+s
print(s[0])

Ya ha habido mejores soluciones, pero ahora que lo había escrito (sin haber leído las presentaciones anteriores, por supuesto, aunque tengo que admitir que mi código parece haberlas pegado), quería compartirlo, también.


b/adebe reemplazarse con a and b/a, de lo contrario, esta solución no funcionará si el segundo operando es 0 (por ejemplo 4 0 -).
flornquake

@flornquake lo arregló para él.
mbomb007

2

c99 gcc 235

Esto funciona para mí (con advertencias):

#include <stdlib.h>
#define O(x):--d;s[d]=s[d]x s[d+1];break;
float s[99];main(c,v)char**v;{for(int i=1,d=0;i<c;i++)switch(!v[i][1]?*v[i]:' '){case'+'O(+)case'-'O(-)case'*'O(*)case'/'O(/)default:s[++d]=atof(v[i]);}printf("%f\n",s[1]);}

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 -std=c99 x.c C:\Applications\mingw32\i686-w64-mingw32\lib\CRT_noglob.o

Si no lo hace *, el CRT de mingw32 lo expande automáticamente.

¿Alguien sabe cómo convertirse break;case'*':s[--d]*=s[d+1];en una macro que acepte el carácter + como parámetro porque entonces los cuatro casos seríanO(+)O(-)O(*)O(/)

H:\Desktop>gcc -std=c99 x.c C:\Applications\mingw32\i686-w64-mingw32\lib\CRT_noglob.o
x.c:3:13: warning: return type defaults to 'int'
 float s[99];main(c,v)char**v;{for(int i=1,d=0;i<c;i++)switch(!v[i][1]?*v[i]:' '){case'+'O(+)case'-'O(-)case'*'O(*)case'/'O(/)default:s[++d]=atof(v[i]);}printf("%f\n",s[1]);}
x.c: In function 'main':
x.c:3:13: warning: type of 'c' defaults to 'int'
x.c:3:1: warning: implicit declaration of function 'atof' [-Wimplicit-function-declaration]
 float s[99];main(c,v)char**v;{for(int i=1,d=0;i<c;i++)switch(!v[i][1]?*v[i]:' '){case'+'O(+)case'-'O(-)case'*'O(*)case'/'O(/)default:s[++d]=atof(v[i]);}printf("%f\n",s[1]);}
x.c:3:1: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]
x.c:3:153: warning: incompatible implicit declaration of built-in function 'printf'
 float s[99];main(c,v)char**v;{for(int i=1,d=0;i<c;i++)switch(!v[i][1]?*v[i]:' '){case'+'O(+)case'-'O(-)case'*'O(*)case'/'O(/)default:s[++d]=atof(v[i]);}printf("%f\n",s[1]);}
H:\Desktop>a -4 5 +
1.000000
H:\Desktop>a 5 2 /
2.500000
H:\Desktop>a 5 2.5 /
2.000000
H:\Desktop>a 5 1 2 + 4 * 3 - +
14.000000
H:\Desktop>a 4 2 5 * + 1 3 2 * + /
2.000000

2

C, 232 229 bytes

Diversión con recursividad.

#include <stdlib.h>
#define b *p>47|*(p+1)>47
char*p;float a(float m){float n=strtof(p,&p);b?n=a(n):0;for(;*++p==32;);m=*p%43?*p%45?*p%42?m/n:m*n:m-n:m+n;return*++p&&b?a(m):m;}main(c,v)char**v;{printf("%f\n",a(strtof(v[1],&p)));}

Sin golf:

#include <stdlib.h>

/* Detect if next char in buffer is a number */
#define b *p > 47 | *(p+1) > 47

char*p; /* the buffer */

float a(float m)
{
    float n = strtof(p, &p); /* parse the next number */

    /* if the next thing is another number, recursively evaluate */
    b ? n = a(n) : 0;

    for(;*++p==32;); /* skip spaces */

    /* Perform the arithmetic operation */
    m = *p%'+' ? *p%'-' ? *p%'*' ? m/n : m*n : m-n : m+n;

    /* If there's more stuff, recursively parse that, otherwise return the current computed value */
    return *++p && b ? a(m) : m;
}

int main(int c, char **v)
{
    printf("%f\n", a(strtof(v[1], &p)));
}

Casos de prueba:

$ ./a.out "-4 5 +"
1.000000
$ ./a.out "5 2 /"
2.500000
$ ./a.out "5 2.5 /"
2.000000
$ ./a.out "5 1 2 + 4 * 3 - +"
14.000000
$ ./a.out "4 2 5 * + 1 3 2 * + /"
2.000000


1

PHP - 259 caracteres

$n=explode(" ",$_POST["i"]);$s=array();for($i=0;$i<count($n);$s=$d-->0?array_merge($s,!$p?array($b,$a,$c):array($p)):$s){if($c=$n[$i++]){$d=1;$a=array_pop($s);$b=array_pop($s);$p=$c=="+"?$b+$a:($c=="-"?$b-$a:($c=="*"?$b*$a:($c=="/"?$b/$a:false)));}}echo$s[2];

Asumiendo entrada en la variable POST i .


2
Citado de la descripción original »Para los lenguajes de programación que no tienen funciones para recibir entrada / salida, puede asumir funciones como readLine / print.« PHP tiene una manera de obtener stdin a través de flujos.
Kevin Brown

1

C # - 392 caracteres

namespace System.Collections.Generic{class P{static void Main(){var i=Console.ReadLine().Split(' ');var k=new Stack<float>();float o;foreach(var s in i)switch (s){case "+":k.Push(k.Pop()+k.Pop());break;case "-":o=k.Pop();k.Push(k.Pop()-o);break;case "*":k.Push(k.Pop()*k.Pop());break;case "/":o=k.Pop();k.Push(k.Pop()/o);break;default:k.Push(float.Parse(s));break;}Console.Write(k.Pop());}}}

Sin embargo, si se pueden usar argumentos en lugar de una entrada estándar, podemos reducirlo a

C # - 366 caracteres

namespace System.Collections.Generic{class P{static void Main(string[] i){var k=new Stack<float>();float o;foreach(var s in i)switch (s){case "+":k.Push(k.Pop()+k.Pop());break;case "-":o=k.Pop();k.Push(k.Pop()-o);break;case "*":k.Push(k.Pop()*k.Pop());break;case "/":o=k.Pop();k.Push(k.Pop()/o);break;default:k.Push(float.Parse(s));break;}Console.Write(k.Pop());}}}

Puede guardar 23 caracteres con una pequeña optimización: 1. elimine el truco del espacio de nombres, califique explícitamente los dos tipos que lo necesitan. Guarda la palabra clave "espacio de nombres" y los corchetes correspondientes. 2. Elimine espacios entre la cadena [] e i, palabras clave y etiquetas de mayúsculas y minúsculas, switch y sus parens. 3. Deshágase del flotador o y simplemente use las matemáticas para obtener los resultados correctos (es decir, -k.Pop () + k.Pop () para menos, y 1 / k.Pop () * k.Pop () para dividir .
MikeP

1

Scala 412 376 349 335 312:

object P extends App{
def p(t:List[String],u:List[Double]):Double={
def a=u drop 2
t match{
case Nil=>u.head
case x::y=>x match{
case"+"=>p(y,u(1)+u(0)::a)
case"-"=>p(y,u(1)-u(0)::a)
case"*"=>p(y,u(1)*u(0)::a)
case"/"=>p(y,u(1)/u(0)::a)
case d=>p(y,d.toDouble::u)}}}
println(p((readLine()split " ").toList,Nil))}

1

Python - 206

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

Versión sin golf:

# RPN

import sys

input = sys.argv[1].split()
stack = []

# Eval postfix notation
for tkn in input:
    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())

Entrada del argumento de la línea de comandos; salida en salida estándar.


1

ECMAScript 6 (131)

Solo escribí juntos en unos pocos segundos, por lo que probablemente se pueda jugar más golf o tal vez incluso abordarlo mejor. Podría volver a visitarlo mañana:

f=s=>(p=[],s.split(/\s+/).forEach(t=>+t==t?p.push(t):(b=+p.pop(),a=+p.pop(),p.push(t=='+'?a+b:t=='-'?a-b:t=='*'?a*b:a/b))),p.pop())

1

C # - 323 284 241

class P{static void Main(string[] i){int x=0;var a=new float[i.Length];foreach(var s in i){var o="+-*/".IndexOf(s);if(o>-1){float y=a[--x],z=a[--x];a[x++]=o>3?z/y:o>2?z*y:o>1?z-y:y+z;}else a[x++]=float.Parse(s);}System.Console.Write(a[0]);}}

Editar: reemplazar la pila con una matriz es mucho más corto

Edit2: reemplazó los ifs con una expresión ternaria


string[] i=> string[]i.
Zacharý

1

Python 2

He probado algunos enfoques diferentes a los publicados hasta ahora. Ninguno de estos es tan corto como las mejores soluciones de Python, pero pueden ser interesantes para algunos de ustedes.

Usando recursividad, 146

def f(s):
 try:x=s.pop();r=float(x)
 except:b,s=f(s);a,s=f(s);r=[a+b,a-b,a*b,b and a/b]['+-*'.find(x)]
 return r,s
print f(raw_input().split())[0]

Usando la manipulación de listas, 149

s=raw_input().split()
i=0
while s[1:]:
 o='+-*/'.find(s[i])
 if~o:i-=2;a,b=map(float,s[i:i+2]);s[i:i+3]=[[a+b,a-b,a*b,b and a/b][o]]
 i+=1
print s[0]

Usando reduce(), 145

print reduce(lambda s,x:x in'+-*/'and[(lambda b,a:[a+b,a-b,a*b,b and a/b])(*s[:2])['+-*'.find(x)]]+s[2:]or[float(x)]+s,raw_input().split(),[])[0]

1

Matlab, 228

F='+-/*';f={@plus,@minus,@rdivide,@times};t=strsplit(input('','s'),' ');i=str2double(t);j=~isnan(i);t(j)=num2cell(i(j));while numel(t)>1
n=find(cellfun(@(x)isstr(x),t),1);t{n}=bsxfun(f{t{n}==F},t{n-2:n-1});t(n-2:n-1)=[];end
t{1}

Sin golf:

F = '+-/*'; %// possible operators
f = {@plus,@minus,@rdivide,@times}; %// to be used with bsxfun
t = strsplit(input('','s'),' '); %// input string and split by one or multiple spaces
i = str2double(t); %// convert each split string to number
j =~ isnan(i); %// these were operators, not numbers ...
t(j) = num2cell(i(j)); %// ... so restore them
while numel(t)>1
    n = find(cellfun(@(x)isstr(x),t),1); %// find left-most operator
    t{n} = bsxfun(f{t{n}==F}, t{n-2:n-1}); %// apply it to preceding numbers and replace
    t(n-2:n-1)=[]; %// remove used numbers
end
t{1} %// display result

Puede guardar 2 bytes más al poner todo en una línea (o usar un editor de texto que solo usa un carácter para la nueva línea)
Hoki

@Hoki Solo estoy usando nuevas líneas cuando no romper la línea requeriría a ;. Así que creo que el número de bytes es el mismo
Luis Mendo

no exactamente, la mayoría de los editores de texto de ventana usan cr+lfuna nueva línea, que tiene 2 caracteres. Mi bloc de notas ++ contó 230 caracteres en su versión de 3 líneas, pero solo 128 si pego todo en una línea (eliminé 2 * 2 = 4 caracteres de las 2 líneas nuevas y agregué dos ;). Pruébelo usted mismo;)
Hoki

@Hoki Tienes razón. De hecho, si pego la versión de tres líneas en mothereff.in/byte-counter (que es lo que usé para contar bytes de texto), da 228. Y, por supuesto, eso es lo que obtengo al poner todo en un solo línea. No sé de dónde saqué el número 230. ¡Gracias! Corregido
Luis Mendo

1

K5, 70 bytes

`0:*{$[-9=@*x;((*(+;-;*;%)@"+-*/"?y).-2#x;x,.y)@47<y;(.x;.y)]}/" "\0:`

No estoy seguro de cuándo se lanzó K5, por lo que esto podría no contar. ¡Sigue siendo increíble!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.