Notation polonaise inversée


41

Vous devez évaluer une chaîne écrite en notation polonaise inversée et générer le résultat.

Le programme doit accepter une entrée et renvoyer la sortie. Pour les langages de programmation qui ne disposent pas de fonctions pour recevoir des entrées / sorties, vous pouvez assumer des fonctions telles que readLine / print.

Vous n'êtes pas autorisé à utiliser n'importe quel type de "eval" dans le programme.

Les nombres et les opérateurs sont séparés par un ou plusieurs espaces.

Vous devez prendre en charge au moins les opérateurs +, -, * et /.

Vous devez ajouter un support aux nombres négatifs (par exemple, ce -4n'est pas la même chose 0 4 -) et aux nombres à virgule flottante.

Vous pouvez supposer que la saisie est valide et respecte les règles ci-dessus


Cas de test

Contribution:

-4 5 +

Sortie:

1

Contribution:

5 2 /

Sortie:

2.5

Contribution:

5 2.5 /

Sortie:

2

Contribution:

5 1 2 + 4 * 3 - +

Sortie:

14

Contribution:

4 2 5 * + 1 3 2 * + /

Sortie:

2

8
Il est dommage pas eval est autorisé, sinon la solution GolfScript est 1 caractère: ~. :-P
Chris Jester-Young le

5
C'est pourquoi il n'est pas permis :-P, cette question sur StackOverflow a reçu une réponse à 4 caractères avec dc.

1
@SHiNKiROU: Quelle langue vous oblige à utiliser evalpour analyser les numéros? Cela semble assez cassé. (GolfScript est l'un de ces langages, à ma connaissance. Je pense qu'il est cassé aussi.)
Chris Jester-Young Le

3
Comment -4 n'est-il pas identique à 0 4 -?
Keith Randall

1
Je pense que eval devrait convenir s’il ne s’agissait que de convertir des chaînes en nombres. par exemple. en python eval(s)est meilleur quefloat(s)
gnibbler

Réponses:


15

Ruby - 95 77 caractères

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

Prend une entrée sur stdin.

Code de test

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

donne

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

Contrairement à la version C, cela renvoie le dernier résultat valide s'il semble y avoir des numéros supplémentaires ajoutés à l'entrée.


1
Vous pouvez raser un personnage en utilisant une carte à la place de chacun
addison

10

Python - 124 caractères

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 caractères

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
J'aime la manipulation de la pile.
Alexandru

2
Vous ne pouvez pas avoir 0comme second opérande ...
JBernardo

2
[a/b]doit être remplacé par b and[a/b]afin que vous puissiez avoir 0 comme second opérande.
Flornquake

10

Schéma, 162 caractères

(Les sauts de ligne ajoutés pour plus de clarté - tous sont facultatifs.)

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

Version entièrement formatée (non-golfée):

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

Commentaire sélectionné

`(,foo ,@bar)est identique à (cons foo bar)(c'est-à-dire qu'il (effectivement ) retourne une nouvelle liste avec foopréfixe à bar), sauf que le caractère est plus court si vous compressez tous les espaces.

Ainsi, vous pouvez lire les clauses d’itération au fur (loop (cons token stack))et à mesure (loop (cons ((cadr ass) (cadr stack) (car stack)) (cddr stack)))que cela vous paraît plus facile.

`((+ ,+) (- ,-) (* ,*) (/ ,/))crée une liste d'association avec le symbole + associé à la procédure + , et de la même manière avec les autres opérateurs. Il s’agit donc d’une simple table de consultation de symboles (les mots nus sont (read)sous forme de symboles, raison pour laquelle aucun traitement supplémentaire n’a lieu).token n’est nécessaire). Les listes d'associations ont une recherche O (n) et ne conviennent donc que pour les listes courtes, comme c'est le cas ici. :-P

† Ce n'est pas techniquement exact, mais, pour les programmeurs non Lisp, il en a une idée assez juste.


Pouvez-vous lire ça? Sérieusement?

1
@ M28: La version sans golf, oui. Je programme dans Scheme sur une base semi-régulière (pour de vrais programmes sérieux).
Chris Jester-Young

Malheureusement, Scheme est un langage verbeux et notoirement difficile à bien jouer au golf. Je ne serais donc pas surpris de voir une soumission de Perl battre celle-ci.
Chris Jester-Young

7
J'aime les quatre smileys dans la version golfée.
Tomsmeding

2
lambda (ass)+1 pour le choix du nom de la variable: P
Downgoat

7

c - 424 caractère nécessaire

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

Supposons que vous ayez une nouvelle bibliothèque suffisante à inclure getdelimdans stdio.h. L'approche est tout droit, l'entrée entière est lue dans une mémoire tampon, puis nous tokenisons avec strsepet utilisons longueur et caractère initial pour déterminer la classe de chacun. Il n'y a pas de protection contre les mauvaises entrées. Chargez-le "+ - * / + - ...", et il sautera volontiers dans la mémoire "en dessous" de la pile jusqu'à ce qu'il se sépare des erreurs. Tous les non-opérateurs sont interprétés comme des flottants, atofce qui signifie une valeur nulle s'ils ne ressemblent pas à des nombres.

Lisible et commenté:

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

Validation:

 $ 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

Il h! Je dois citer n'importe quoi avec *dedans ...

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

et mon propre cas de test

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

Vous pouvez protéger certains caractères en les remplaçant casepar 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

Vous pouvez supprimer 9 caractères en remplaçant "(s: _)! [] = S" par "(s: _)! [] = Print s" et "main = getLine >> = putStrLn.show. ([]! ) .words » à "principale = getLine >> = ([]) mots!".
Fors

Et ensuite, supprimez quelques autres caractères en utilisant une instruction de cas d'une ligne.
Fors

s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!vpermettrait d'économiser 14 caractères.
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

(l’entrée est lue à partir de l’utilisateur, la sortie est imprimée).


Ci-dessous, le code prettifié et commenté, il implémente assez bien l' algorithme postfixif décrit (en supposant que les expressions sont valides):

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

Prime:

Dans le code ci - dessus, nous supposons que les opérateurs sont toujours binaires ( +, -, *, /). Nous pouvons le généraliser en utilisant nargin(f)pour déterminer le nombre d'arguments requis par l'opérande / la fonction, et extraire en conséquence la bonne quantité de valeurs de la pile, comme dans:

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

De cette façon, nous pouvons évaluer des expressions telles que:

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

mean_of_threeest une fonction définie par l'utilisateur avec trois entrées:

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 prochaine fois, je vais utiliser la chose récursive regexp.

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

Je pensais que F # était le seul langage de programmation de mes rêves ...


J'ai une implémentation Perl 5 plus courte.
dolmen le

6

Windows PowerShell, 152 181 192

Sous une forme lisible, parce qu’il n’ya plus que deux lignes pour le moment:

$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

2010-01-30 11:07 (192) - Première tentative.

2010-01-30 11:09 (170) - Le fait de transformer la fonction en scriptblock résout les problèmes de portée. Allonge simplement chaque appel de deux octets.

2010-01-30 11:19 (188) - Le problème de la portée n'a pas été résolu, le scénario de test l'a masqué. Suppression de l'index de la sortie finale et suppression d'un saut de ligne superflu. Et changé double enfloat .

2010-01-30 11:19 (181) - Je ne me souviens même pas de mes propres conseils. La conversion en un type numérique peut être réalisée en un seul caractère.

2010-01-30 11:39 (152) - Réduit considérablement en utilisant la correspondance de regex dans le fichier switch. Résout complètement les problèmes de portée précédents avec l'accès à la pile pour la faire apparaître.


5

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

Les sauts de ligne sont facultatifs.

Basé sur la solution de Chris Jester-Young pour Scheme.


4

Python, 166 caractères

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]

Le raw_input()code d' utilisation n'est pas divisé sur plusieurs lignes.
JPvdMerwe

Ensuite, vous pouvez essayer: from operator import*et remplacer o.divpar div.
JPvdMerwe

4

Python 3, 119 octets

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

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

Sortie: 2.5

(Vous pouvez trouver une version Python 2 à 128 caractères dans l'historique des modifications.)


Assez intelligent :) J'aime comment vous n'avez pas besoin /de la chaîne.
Daniel Lubarov


@EriktheOutgolfer qui rompt avec a ZeroDivisionErrorlorsque le deuxième opérande est 0 (par exemple 5 0 +).
Flornquake

Vous pouvez enregistrer 1 caractère en utilisant la ord(x) - 42méthode.
frederick99

@ frederick99 Je ne vois pas comment.
Flornquake

3

JavaScript (157)

Ce code suppose qu'il existe deux fonctions: readLine et 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])

Plus court si vous utilisez prompt()au lieu de readLine()(et peut-être alert()au lieu de print()faire correspondre prompt()).
nyuszika7h

3

Perl, 128

Ce n'est pas vraiment compétitif à côté de l'autre réponse Perl, mais explore un chemin différent (sous-optimal).

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

Les caractères comptés comme diff à une simple perl -e ''invocation.


2

Python, 161 caractères:

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 caractères

<? $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];

Ce code devrait fonctionner avec stdin, bien qu'il ne soit pas testé avec stdin.

Il a été testé sur tous les cas, la sortie (et le code) pour le dernier est ici:
http://codepad.viper-7.com/fGbnv6

Ungolfed, 314 330 326 caractères

<?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];

Citation tirée de la description de la tâche: »Pour les langages de programmation qui ne disposent pas de fonctions pour recevoir des entrées / sorties, vous pouvez assumer des fonctions telles que readLine / print.« - de manière manifeste PHP a fonctions pour le faire, par conséquent l'hypothèse est incorrecte.
Joey

Mise à jour pour utiliser stdin et golfé un peu plus.
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 vous n'êtes pas familier, compilez avec flex rpn.l && gcc -lfl lex.yy.c


2

Python, 130 caractères

Serait 124 caractères si nous avons laissé b and (certaines réponses Python sont manquantes). Et il en incorpore 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]

Vraiment bonne réponse. Mais je compte 130 caractères. ;)
flornquake

@flornquake vous avez raison, merci pour la correction.
Daniel Lubarov

2

Python 3, 126 132 caractères

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

Il y avait déjà de meilleures solutions, mais maintenant que je l'avais écrit (sans avoir lu les soumissions précédentes, bien sûr - même si je dois admettre que mon code a l'air de les avoir copypés ensemble), je voulais le partager, aussi.


b/adoit être remplacé par a and b/a, sinon cette solution ne fonctionnera pas si le deuxième opérande est 0 (par exemple 4 0 -).
Flornquake

@flornquake l'a corrigé.
mbomb007

2

c99 gcc 235

Cela fonctionne pour moi (avec des avertissements):

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

Mais si vous le compilez avec mingw32, vous devez désactiver la fonction de globbing (voir https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ) en compilant comme suit :

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

Si vous ne le faites pas *, le CRT mingw32 l'étend automatiquement.

Est-ce que quelqu'un sait comment transformer break;case'*':s[--d]*=s[d+1];en une macro qui accepte le caractère + en tant que paramètre, car alors les quatre cas seraient simplementO(+)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 octets

Amusez-vous avec la récursion.

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

Cas de test:

$ ./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 caractères

$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];

En supposant une entrée dans la variable POST i .


2
Citation de la description originale »Pour les langages de programmation qui n'ont pas de fonctions pour recevoir des entrées / sorties, vous pouvez assumer des fonctions telles que readLine / print.« PHP dispose d'un moyen d'obtenir de stdin à travers des flux.
Kevin Brown

1

C # - 392 caractères

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

Cependant, si les arguments peuvent être utilisés à la place de l'entrée standard, nous pouvons le réduire à

C # - 366 caractères

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

Vous pouvez enregistrer 23 caractères avec un peu d’optimisation: 1. supprimez l’astuce de l’espace de nommage, qualifiez explicitement les deux types qui en ont besoin. Vous enregistrez le mot-clé "namespace" et les parenthèses correspondantes. 2. Supprimez les espaces entre chaîne [] et i, les mots-clés de cas et les étiquettes, switch et ses parenthèses. 3. Supprimez float o et utilisez simplement les mathématiques pour obtenir les bons résultats (par exemple -k.Pop () + k.Pop () pour moins, et 1 / k.Pop () * k.Pop () pour diviser .
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())

Version non-golfée:

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

Entrée à partir d'un argument de ligne de commande; sortie sur sortie standard.


1

ECMAScript 6 (131)

Il suffit de taper ensemble en quelques secondes pour pouvoir jouer au golf encore plus loin ou même mieux s’en approcher. Je pourrais le revoir demain:

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

Edit: Remplacement de la pile par un tableau est beaucoup plus court

Edit2: Remplacé les if par une expression ternaire


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

1

Python 2

J'ai essayé différentes approches de celles publiées jusqu'à présent. Aucune de celles-ci n'est aussi courte que les meilleures solutions Python, mais elles pourraient néanmoins intéresser certains d'entre vous.

Utilisation de la récursivité, 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]

Utilisation de la manipulation de liste, 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]

Utilisation 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}

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

Vous pouvez économiser 2 octets supplémentaires en plaçant le tout sur une seule ligne (ou en utilisant un éditeur de texte n'utilisant qu'un seul caractère pour la nouvelle ligne)
Hoki

@Hoki I'm only using new lines when not breaking the line would require a ;. So I think the byte count is the same
Luis Mendo

pas exactement, la plupart des éditeurs de texte de fenêtre utilisent cr+lfune nouvelle ligne, composée de 2 caractères. Mon bloc-notes ++ comptait 230 caractères dans votre version à 3 lignes, mais seulement 128 si je colle tout dans une ligne (2 * 2 supprimés = 4 caractères des 2 nouvelles lignes et deux ajoutés ;). Essayez vous-même;)
Hoki

@Hoki Vous avez raison. En fait, si je colle la version en trois lignes sur mothereff.in/byte-counter (ce qui est ce que j’ai utilisé pour compter les octets de texte), cela donne 228. Et bien sûr, c’est aussi ce que j’obtiens en le mettant tout en un. ligne. Je ne sais pas d'où j'ai tiré le numéro 230. Merci! Corrigé
Luis Mendo

1

K5, 70 octets

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

I'm not sure when K5 was released, so this might not count. Still awesome!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.