Notação polonesa reversa

41

Você deve avaliar uma string escrita em notação polonesa reversa e produzir o resultado.

O programa deve aceitar uma entrada e retornar a saída. Para linguagens de programação que não possuem funções para receber entrada / saída, você pode assumir funções como readLine / print.

Você não tem permissão para usar nenhum tipo de "avaliação" no programa.

Números e operadores são separados por um ou mais espaços.

Você deve suportar pelo menos os operadores +, -, * e /.

Você precisa adicionar suporte a números negativos (por exemplo, -4não é a mesma coisa que 0 4 -) e números de ponto flutuante.

Você pode assumir que a entrada é válida e segue as regras acima


Casos de teste

Entrada:

-4 5 +

Saída:

1

Entrada:

5 2 /

Saída:

2.5

Entrada:

5 2.5 /

Saída:

2

Entrada:

5 1 2 + 4 * 3 - +

Saída:

14

Entrada:

4 2 5 * + 1 3 2 * + /

Saída:

2

fonte
8
É uma pena não eval é permitido, caso contrário, a solução GolfScript é um personagem: ~. :-P
Chris Jester-Young
5
É por isso que não é permitido :-P, esta pergunta no StackOverflow recebeu uma resposta de 4 caracteres com dc.
11
@SHiNKiROU: Qual idioma exige que você use evalpara analisar números? Parece bastante quebrado. (GolfScript é uma tal linguagem, tanto quanto eu estou ciente que eu acho que está quebrado também..)
Chris Jester-Young
3
Como -4 não é o mesmo que 0 4 -?
Keith Randall
11
Eu acho que eval deveria ficar bem se fosse apenas para converter strings em números. por exemplo. em python eval(s)é melhor quefloat(s)
gnibbler

Respostas:

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]

Recebe entrada em stdin.

Código de teste

[
  "-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

[-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

Diferente da versão C, ele retorna o último resultado válido se houver números extras anexados à entrada que parece.

Nemo157
fonte
11
Você pode raspar um personagem usando o mapa em vez de cada um
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]
mordedor
fonte
11
Eu gosto da manipulação de pilha.
Alexandru
2
Você não pode ter 0como segundo operando ...
JBernardo
2
[a/b]deve ser substituído por b and[a/b]para que você possa ter 0 como segundo operando.
flornquake
10

Esquema, 162 caracteres

(Quebras de linha adicionadas para maior clareza - todas são opcionais.)

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

Versão totalmente formatada (não destruída):

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

Comentário selecionado

`(,foo ,@bar)é o mesmo que (cons foo bar)(ou seja, (efetivamente ) retorna uma nova lista com fooanexado a bar), exceto que é um caractere menor se você compactar todos os espaços.

Assim, você pode ler as cláusulas de iteração como (loop (cons token stack))e (loop (cons ((cadr ass) (cadr stack) (car stack)) (cddr stack)))se isso for mais fácil para seus olhos.

`((+ ,+) (- ,-) (* ,*) (/ ,/))cria uma lista de associação com o símbolo + associado ao procedimento + e da mesma forma com os outros operadores. Portanto, é uma tabela simples de pesquisa de símbolos (palavras simples estão (read)como símbolos, e é por isso que nenhum processamento adicional tokené necessário). As listas de associação têm pesquisa O (n) e, portanto, são adequadas apenas para listas curtas, como é o caso aqui. :-P

† Isso não é tecnicamente preciso, mas, para programadores que não são do Lisp, ele tem uma idéia o suficiente.

Chris Jester-Young
fonte
Você pode ler isso? A sério?
11
@ M28: A versão não destruída, sim. Eu programa no Scheme em regime semi-regular (para programas reais e sérios).
Chris Jester-Young
Infelizmente, Scheme é uma linguagem detalhada e notoriamente difícil de jogar bem. Então, eu não ficaria surpreso ao ver algumas finalizações do Perl vencerem essa.
perfil completo de Chris Jester-Young
7
Eu gosto dos quatro smileys na versão golfed.
tomsmeding
2
lambda (ass)1 para a escolha nome da variável: P
Downgoat
7

c - 424 caracteres necessários

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

Supõe que você tenha uma nova libc suficiente para incluir getdelimno stdio.h. A abordagem é direta, toda a entrada é lida em um buffer e, em seguida, usamos o token strsepe o comprimento e o caractere inicial para determinar a classe de cada um. Não há proteção contra entrada incorreta. Alimente "+ - * / + - ..." e, felizmente, sairá da memória "abaixo" da pilha até falhar. Todos os não operadores são interpretados como flutuadores, o atofque significa valor zero se não parecerem números.

Legível e 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));
    }
  }
}

Validação:

 $ 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

Heh! Tem que citar qualquer coisa com *ele ...

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

e meu próprio caso de teste

 $ echo "12 8 3 * 6 / - 2 + -20.5 " | ./a.out
-20.500000
dmckee
fonte
Você pode proteger alguns caracteres substituindo-os casepor um 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
marinus
fonte
Você pode remover 9 caracteres alterando "(s: _)! [] = S" para "(s: _)! [] = Print s" e "main = getLine >> = putStrLn.show. ([]] ) .words "para" main = getLine >> = ([]!). words ")
Fors
E depois remova alguns outros caracteres usando uma declaração de caso de uma linha.
Fors
s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!veconomizaria 14 caracteres.
quer
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

(a entrada é lida na entrada do usuário, a saída é impressa).


Abaixo está o código prettificado e comentado, ele implementa praticamente o algoritmo postfix descrito (com a suposição de que expressões são 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

Bônus:

No código acima, assumimos operadores são sempre binário ( +, -, *, /). Podemos generalizá-lo usando nargin(f)para determinar o número de argumentos que o operando / função exige e exibir a quantidade certa de valores da pilha de acordo, como em:

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

Dessa forma, podemos avaliar expressões como:

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

onde mean_of_threeé uma função definida pelo usuário com três entradas:

function d = mean_of_three(a,b,c)
    d = (a+b+c)/3;
end
Amro
fonte
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

Da próxima vez, vou usar a coisa regexp recursiva.

Ungolfed:

@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);

Embora o F # seja minha única linguagem de programação de sonhos ...

Ming-Tang
fonte
Eu tenho uma implementação Perl 5 mais curta.
dolmen
6

Windows PowerShell, 152 181 192

De forma legível, porque agora são apenas duas linhas sem chance de quebrá-las:

$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) - Primeira tentativa.

30-01-2010 11:09 (170) - Transformar a função em um scriptblock resolve os problemas de escopo. Apenas torna cada invocação dois bytes mais longos.

30-01-2010 11:19 (188) - Não resolveu o problema de escopo, o caso de teste apenas o ocultou. Removeu o índice da saída final e removeu uma quebra de linha supérflua. E mudou duas vezes para float.

30-01-2010 11:19 (181) - Nem me lembro dos meus próprios conselhos. A conversão para um tipo numérico pode ser feita em um único caractere.

30-01-2010 11:39 (152) - Muito reduzido usando a correspondência de regex no switch. Resolve completamente os problemas anteriores de escopo ao acessar a pilha para abri-la.

Joey
fonte
5

Raquete 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)]))

Quebras de linha opcionais.

Baseado na solução de Chris Jester-Young para Scheme.

Sam Tobin-Hochstadt
fonte
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]
Keith Randall
fonte
O raw_input()código de uso não está dividido em várias linhas.
precisa saber é o seguinte
Então você pode tentar: from operator import*e substituir o.divpor div.
precisa saber é o seguinte
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 /

Saída: 2.5

(Você pode encontrar uma versão Python 2 de 128 caracteres no histórico de edições.)

flornquake
fonte
Bastante inteligente :) Eu gosto de como você não precisa /na string.
Daniel Lubarov
114 bytes
Erik the Outgolfer
@EriktheOutgolfer que quebra com a ZeroDivisionErrorquando o segundo operando é 0 (por exemplo 5 0 +).
Flornquake #
Você pode salvar 1 caractere usando o ord(x) - 42método
frederick99
@ frederick99 Não vejo como.
flornquake
3

JavaScript (157)

Este código assume que existem duas funções: 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])

fonte
Menor se você usar em prompt()vez de readLine()(e talvez em alert()vez de print()combinarprompt() ).
usar o seguinte código
3

Perl, 128

Isso não é realmente competitivo ao lado da outra resposta Perl, mas explora um caminho diferente (subótimo).

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<@_'

Caracteres contados como diff para uma simples perl -e ''invocação.

JB
fonte
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])
Thomas O
fonte
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 deve funcionar com o stdin, embora não seja testado com o stdin.

Foi testado em todos os casos, a saída (e código) do último está aqui:
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];
Kevin Brown
fonte
Cite a descrição da tarefa: »Para linguagens de programação que não possuem funções para receber entrada / saída, você pode assumir funções como readLine / print.« - comprovadamente o PHP tem funções para fazê-lo, portanto a suposição está incorreta.
Joey
Atualizei para usar stdin e joguei um pouco mais.
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);
.
%%

Se você não estiver familiarizado, compile com flex rpn.l && gcc -lfl lex.yy.c

Geoff Reedy
fonte
2

Python, 130 caracteres

Seriam 124 caracteres se deixássemos cair b and(que faltam algumas das respostas do Python). E 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]
Daniel Lubarov
fonte
Resposta muito boa. Mas conto 130 caracteres. ;)
flornquake 15/09/14
@ Flornquake você está certo, obrigado pela correção.
Daniel Lubarov 15/09/14
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])

Já existem soluções melhores, mas agora que eu as escrevi (sem ter lido as observações anteriores, é claro - mesmo que eu tenha que admitir que meu código parece ter copiado-as juntos), eu queria compartilhá-las, também.

cemper93
fonte
b/adeve ser substituído por a and b/a, caso contrário, esta solução não funcionará se o segundo operando for 0 (por exemplo 4 0 -).
flornquake
@flornquake Corrigido para ele.
mbomb007
2

c99 gcc 235

Isso funciona para mim (com avisos):

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

Mas se você estiver compilando com o mingw32, precisará desativar o globbing (consulte https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ) compilando assim:

gcc -std=c99 x.c C:\Applications\mingw32\i686-w64-mingw32\lib\CRT_noglob.o

Caso contrário, * será automaticamente expandido pelo mingw32 CRT.

Alguém sabe como se transformar break;case'*':s[--d]*=s[d+1];em uma macro que aceita o caractere + como parâmetro porque todos os quatro casos seriamO(+)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
Jerry Jeremiah
fonte
2

C, 232 229 bytes

Diversão com recursão.

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

Ungolfed:

#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 teste:

$ ./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
Cole Cameron
fonte
2

JavaScript ES7, 119 bytes

Estou recebendo um bug com a compreensão de array, então usei .map

(s,t=[])=>(s.split` `.map(i=>+i?t.unshift(+i):t.unshift((r=t.pop(),o=t.pop(),[r+o,r-o,r*o,r/o]['+-*/'.indexOf(i)]))),t)

Experimente online no ESFiddle

Downgoat
fonte
Existe um intérprete ES7 disponível?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ isso deve funcionar no Firefox. Você pode tentar babeljs.io/repl
Downgoat
Ah eu vejo. ^ _ ^ Obrigado!
Conor O'Brien
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];

Assumindo entrada na variável POST i .

Aurel Bílý
fonte
2
Citado na descrição original »Para linguagens de programação que não possuem funções para receber entrada / saída, você pode assumir funções como readLine / print.« O PHP tem uma maneira de obter o stdin através dos fluxos.
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());}}}

No entanto, se argumentos podem ser usados ​​em vez de entrada padrão, podemos reduzi-lo 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());}}}
MiffTheFox
fonte
Você pode salvar 23 caracteres com um pouco de otimização: 1. remova o truque de namespace, qualifique explicitamente os dois tipos que precisam dele. Você salva a palavra-chave "namespace" e os colchetes correspondentes. 2. Remova os espaços entre as cadeias [] e i, palavras-chave e rótulos de maiúsculas e minúsculas, switch e seus parênteses. 3. Livre-se do float o e simplesmente use math para obter os resultados certos (por exemplo, -k.Pop () + k.Pop () para menos e 1 / k.Pop () * k.Pop () para dividir #
511 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))}
Usuário desconhecido
fonte
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())

Versão não destruída:

# 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 do argumento da linha de comando; saída na saída padrão.

golfer9338
fonte
1

ECMAScript 6 (131)

Apenas digitados juntos em alguns segundos, para que provavelmente possa ser mais jogado ou talvez até melhor. Eu posso revisitá-lo amanhã:

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())
Ingo Bürk
fonte
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: Substituir a pilha por uma matriz é bem mais curta

Edit2: Substituído os ifs por uma expressão ternária

kev
fonte
string[] i=> string[]i.
Zacharý
1

Python 2

Eu tentei algumas abordagens diferentes das publicadas até agora. Nenhuma delas é tão curta quanto as melhores soluções Python, mas elas ainda podem ser interessantes para alguns de vocês.

Usando recursão, 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 manipulação de lista, 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]
flornquake
fonte
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}

Ungolfed:

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
Luis Mendo
fonte
Você pode economizar mais 2 bytes, colocando tudo em uma linha (ou use um editor de texto que utiliza apenas um caractere para nova linha)
Hoki
@Hoki Eu só estou usando novas linhas quando não quebrar a linha exigiria a ;. Então eu acho que a contagem de bytes é o mesmo
Luis Mendo
não exatamente, a maioria dos editores de texto de janela usa cr+lfpara uma nova linha, com dois caracteres. Meu bloco de notas ++ contava 230 caracteres na sua versão de 3 linhas, mas apenas 128 se eu colocar tudo em uma linha (removi 2 * 2 = 4 caracteres das 2 novas linhas e adicionei dois ;). Tente você mesmo;)
Hoki
@Hoki Você está certo. De fato, se eu colar a versão de três linhas em mothereff.in/byte-counter (que é o que eu usei para contar bytes de texto), ela fornece 228. E é claro que também é o que recebo ao colocar tudo em uma única linha. Não sei de onde consegui o número 230. Obrigado! Corrigido
Luis Mendo
1

K5, 70 bytes

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

Não tenho certeza de quando o K5 foi lançado, então isso pode não contar. Ainda impressionante!

kirbyfan64sos
fonte