Umgekehrte polnische Notation


41

Sie müssen eine in umgekehrter polnischer Schreibweise geschriebene Zeichenfolge auswerten und das Ergebnis ausgeben.

Das Programm muss eine Eingabe akzeptieren und die Ausgabe zurückgeben. Für Programmiersprachen, die keine Ein- / Ausgabefunktionen haben, können Sie Funktionen wie readLine / print übernehmen.

Sie dürfen keine Art von "eval" im Programm verwenden.

Zahlen und Operatoren werden durch ein oder mehrere Leerzeichen getrennt.

Sie müssen mindestens die Operatoren +, -, * und / unterstützen.

Sie müssen negative Zahlen und Gleitkommazahlen unterstützen (dies ist beispielsweise -4nicht dasselbe wie 0 4 -).

Sie können davon ausgehen, dass die Eingabe gültig ist und die obigen Regeln befolgt


Testfälle

Eingang:

-4 5 +

Ausgabe:

1

Eingang:

5 2 /

Ausgabe:

2.5

Eingang:

5 2.5 /

Ausgabe:

2

Eingang:

5 1 2 + 4 * 3 - +

Ausgabe:

14

Eingang:

4 2 5 * + 1 3 2 * + /

Ausgabe:

2

8
Es ist eine Schande nicht eval darf, da sonst die GolfScript Lösung ist 1 Zeichen: ~. :-P
Chris Jester-Young

5
Deshalb ist es nicht erlaubt :-P, diese Frage auf StackOverflow hat eine 4 Zeichen Antwort mit dc erhalten.

1
@SHiNKiROU: In welcher Sprache müssen Sie evalZahlen analysieren? Es klingt ziemlich kaputt. (GolfScript ist eine solche Sprache, soweit ich weiß. Ich denke, es ist auch kaputt.)
Chris Jester-Young

3
Wie ist -4 nicht gleich 0 4 -?
Keith Randall

1
Ich denke, eval sollte in Ordnung sein, wenn es nur um die Umwandlung von Zeichenfolgen in Zahlen geht. z.B. in Python eval(s)ist besser alsfloat(s)
Knabberzeug

Antworten:


15

Ruby - 95 77 Zeichen

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

Übernimmt die Eingabe für stdin.

Code testen

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

gibt

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

Im Gegensatz zur C-Version gibt dies das letzte gültige Ergebnis zurück, wenn zusätzliche Zahlen an die Eingabe angehängt werden.


1
Sie können einen Charakter abschneiden, indem Sie stattdessen eine Karte verwenden
addison

10

Python - 124 Zeichen

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 Zeichen

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
Ich mag die Stapelbearbeitung.
Alexandru

2
Sie können nicht 0als zweiter Operand haben ...
JBernardo

2
[a/b]sollte durch ersetzt werden, b and[a/b]damit Sie 0 als zweiten Operanden haben können.
Flornquake

10

Schema, 162 Zeichen

(Aus Gründen der Übersichtlichkeit wurden Zeilenumbrüche hinzugefügt. Alle Angaben sind optional.)

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

Vollformatierte (ungolfed) Version:

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

Ausgewählter Kommentar

`(,foo ,@bar)ist dasselbe wie (cons foo bar)(dh es gibt (effektiv ) eine neue Liste mit foovorangestelltem an zurück bar), außer dass es ein Zeichen kürzer ist, wenn Sie alle Leerzeichen heraus komprimieren.

So können Sie die Iteration Klauseln gelesen (loop (cons token stack))und (loop (cons ((cadr ass) (cadr stack) (car stack)) (cddr stack)))wenn es das ist einfacher auf Ihren Augen.

`((+ ,+) (- ,-) (* ,*) (/ ,/))Erstellt eine Zuordnungsliste mit dem Symbol, das + mit der Prozedur + und ebenfalls mit den anderen Operatoren gepaart ist . Somit handelt es sich um eine einfache Symbol-Nachschlagetabelle (bloße Wörter sind (read)als Symbole enthalten, weshalb keine weitere Verarbeitung tokenerforderlich ist). Assoziationslisten haben O (n) Lookup und sind daher nur für kurze Listen geeignet, wie dies hier der Fall ist. :-P

† Dies ist technisch nicht korrekt, aber für Nicht-Lisp-Programmierer wird eine hinreichende Vorstellung vermittelt.


Kannst du das lesen? Ernsthaft?

1
@ M28: Die ungolfed version, ja. Ich programmiere in regelmäßigen Abständen (für echte, seriöse Programme).
Chris Jester-Young

Leider ist Scheme eine wörtliche Sprache und es ist bekanntermaßen schwierig, gut Golf zu spielen. Es würde mich also nicht wundern, wenn einige Perl-Einsendungen diese schlagen würden.
Chris Jester-Young

7
Ich mag die vier Smileys in der Golfversion.
Tomsmeding

2
lambda (ass)+1 für die Wahl des Variablennamens: P
Downgoat

7

c - 424 notwendiges Zeichen

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

Angenommen, Sie haben eine neue Libc, die getdelimin stdio.h aufgenommen werden kann. Der Ansatz ist direkt, die gesamte Eingabe wird in einen Puffer eingelesen, dann wird mit der strsepLänge und dem Anfangszeichen getoken und die Klasse der einzelnen Zeichen bestimmt. Es gibt keinen Schutz vor schlechten Eingaben. Füttere es mit "+ - * / + - ...", und es wird fröhlich "unter" dem Stapel Zeug aus dem Speicher entfernen, bis es einen Fehler aufweist. Alle Nicht-Operatoren werden als Gleitkommazahlen interpretiert, atofwas bedeutet, dass der Wert Null ist, wenn sie nicht wie Zahlen aussehen.

Lesbar und kommentiert:

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

Validierung:

 $ 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! Muss irgendetwas damit zitieren *...

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

und mein eigener Testfall

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

Sie können einige Zeichen casesichern, indem Sie sie durch ein Makro ersetzen.
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

Sie können 9 Zeichen entfernen, indem Sie "(s: _)! [] = S" in "(s: _)! [] = Print s" und "main = getLine >> = putStrLn.show. ([]! ) .words "bis" main = getLine >> = ([]!). words "
Fors

Entfernen Sie dann einige andere Zeichen mit einer einzeiligen case-Anweisung.
Fors

s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!vwürde 14 Zeichen speichern.
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

(Eingabe wird von Benutzereingabe gelesen, Ausgabe ausgedruckt).


Ist der Code unten hübsch und kommentiert, implementiert er den beschriebenen Postfix-Algorithmus (mit der Annahme, dass Ausdrücke gültig sind):

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

Bonus:

In dem obigen Code gehen wir davon aus Operatoren immer binär sind ( +, -, *, /). Wir können es verallgemeinern, indem wir nargin(f)die Anzahl der Argumente bestimmen, die der Operand / die Funktion benötigt, und dementsprechend die richtige Anzahl von Werten aus dem Stapel ziehen, wie in:

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

Auf diese Weise können wir Ausdrücke wie die folgenden auswerten:

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

wo mean_of_three ist eine benutzerdefinierte Funktion mit drei Eingaben:

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

Nächstes Mal werde ich das rekursive Regexp-Ding verwenden.

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

Ich denke, F # ist meine einzige Traum-Programmiersprache ...


Ich habe eine kürzere Perl 5-Implementierung.
Dolmen

6

Windows PowerShell, 152 181 192

In lesbarer Form, da es sich derzeit nur um zwei Zeilen handelt, die nicht getrennt werden können:

$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) - Erster Versuch.

2010-01-30 11:09 (170) - Durch die Umwandlung der Funktion in einen Scriptblock werden die Probleme mit dem Gültigkeitsbereich behoben. Nur macht jeder Aufruf zwei Bytes länger.

2010-01-30 11:19 (188) - Das Problem mit dem Gültigkeitsbereich wurde nicht behoben, der Testfall hat es nur maskiert. Der Index wurde aus der endgültigen Ausgabe entfernt und ein überflüssiger Zeilenumbruch wurde entfernt. Und wechselte doppelt zufloat .

2010-01-30 11:19 (181) - Ich kann mich nicht einmal an meinen eigenen Rat erinnern. Die Umwandlung in einen numerischen Typ kann in einem Zeichen erfolgen.

2010-01-30 11:39 (152) - Stark reduziert durch Verwendung von Regex-Matching in der switch. Behebt vollständig die vorherigen Probleme mit dem Zugriff auf den Stack, um ihn zu öffnen.


5

Schläger 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)]))

Zeilenumbrüche optional.

Basierend auf der Lösung von Chris Jester-Young für Scheme.


4

Python, 166 Zeichen

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]

Der Verwendungscode raw_input()ist nicht auf mehrere Zeilen aufgeteilt.
JPvdMerwe

Dann könnten Sie versuchen: from operator import*und ersetzen o.divdurch 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])

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

Ausgabe: 2.5

(Eine Python 2-Version mit 128 Zeichen finden Sie im Bearbeitungsverlauf.)


Ziemlich schlau :) Mir gefällt, wie du nicht /in der Zeichenfolge brauchst .
Daniel Lubarov


@EriktheOutgolfer, der mit a bricht, ZeroDivisionErrorwenn der zweite Operand 0 ist (z 5 0 +. B. ).
Flornquake

Sie können 1 Zeichen speichern, indem Sie die ord(x) - 42Methode verwenden.
Frederick99

@ frederick99 Ich verstehe nicht wie.
Flornquake

3

JavaScript (157)

In diesem Code wird davon ausgegangen, dass diese beiden Funktionen vorhanden sind: readLine und 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])

Kürzere, wenn Sie prompt()statt verwenden readLine()(und vielleicht alert()statt print()zu entsprechen prompt()).
nyuszika7h

3

Perl, 128

Dies ist nicht wirklich konkurrenzfähig neben der anderen Perl-Antwort, sondern untersucht einen anderen (suboptimalen) Pfad.

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

Zeichen, die bei einem einfachen perl -e ''Aufruf als unterschiedlich gezählt werden .


2

Python, 161 Zeichen:

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 Zeichen

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

Dieser Code sollte mit stdin funktionieren, obwohl er nicht mit stdin getestet wurde.

Es wurde in allen Fällen getestet. Die Ausgabe (und der Code) für den letzten Fall finden Sie hier:
http://codepad.viper-7.com/fGbnv6

Ungolfed, 314 330 326 Zeichen

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

Zitat aus der Aufgabenbeschreibung: »Für Programmiersprachen, die keine Ein- / Ausgabefunktionen haben, können Sie Funktionen wie readLine / print übernehmen.« - PHP hat nachweislich Funktionen dazu, daher ist die Annahme falsch.
Joey

Es wurde aktualisiert, um Standard zu verwenden, und es wurde ein bisschen mehr Golf gespielt.
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);
.
%%

Wenn Sie nicht vertraut sind, kompilieren Sie mit flex rpn.l && gcc -lfl lex.yy.c


2

Python, 130 Zeichen

Wäre 124 Zeichen, wenn wir fallen gelassen würden b and(wobei einige der Python-Antworten fehlen). Und es enthält 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]

Wirklich schöne Antwort. Aber ich zähle 130 Zeichen. ;)
Flornquake

@flornquake du hast recht, danke für die korrektur.
Daniel Lubarov

2

Python 3, 126 132 Zeichen

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

Es gab bereits bessere Lösungen, aber jetzt, wo ich sie geschrieben hatte (natürlich ohne die vorherigen Beiträge gelesen zu haben - obwohl ich zugeben muss, dass mein Code so aussieht, als hätte ich sie gemeinsam kopiert), wollte ich sie teilen. zu.


b/asollte durch ersetzt werden a and b/a, sonst funktioniert diese Lösung nicht, wenn der zweite Operand 0 ist (zB 4 0 -).
Flornquake

@flornquake Reparierte es für ihn.
mbomb007

2

c99 gcc 235

Das funktioniert bei mir (mit Warnungen):

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

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 folgt kompilieren:

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

Wenn Sie dies nicht tun, wird * automatisch durch die mingw32-CRT erweitert.

Weiß jemand, wie man sich break;case'*':s[--d]*=s[d+1];in ein Makro verwandelt , das das Zeichen + als Parameter akzeptiert, denn dann wären alle vier Fälle einfachO(+)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

Spaß mit Rekursion.

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

Testfälle:

$ ./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

2

JavaScript ES7, 119 Byte

Ich bekomme einen Fehler mit dem Array-Verständnis, den ich verwendet habe .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)

Probieren Sie es online bei ESFiddle


Gibt es einen ES7-Interpreter?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ das sollte unter Firefox funktionieren. Sie könnten versuchen, babeljs.io/repl
Downgoat

Oh, ich verstehe. ^ _ ^ Danke!
Conor O'Brien

1

PHP - 259 Zeichen

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

Annahme der Eingabe in der POST-Variablen i .


2
Zitiert aus der Originalbeschreibung »Für Programmiersprachen, die keine Funktionen zum Empfangen von Ein- / Ausgängen haben, können Sie Funktionen wie readLine / print übernehmen.« PHP hat eine Möglichkeit, Standardinhalte über Streams zu erhalten.
Kevin Brown

1

C # - 392 Zeichen

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

Wenn jedoch Argumente anstelle von Standardeingaben verwendet werden können, können wir dies auf reduzieren

C # - 366 Zeichen

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

Sie können 23 Zeichen mit einer kleinen Optimierung speichern: 1. Entfernen Sie den Namespace-Trick, und qualifizieren Sie die beiden Typen, die ihn benötigen, explizit. Sie speichern das Schlüsselwort "Namespace" und die entsprechenden Klammern. 2. Entfernen Sie Leerzeichen zwischen string [] und i, case keywords und labels, switch und seine Parens. 3. Befreien Sie sich von float o und verwenden Sie einfach math, um die richtigen Ergebnisse zu erhalten (dh -k.Pop () + k.Pop () für minus und 1 / k.Pop () * k.Pop () für dividieren .
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())

Ungolfed-Version:

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

Eingabe vom Befehlszeilenargument; Ausgabe auf Standardausgabe.


1

ECMAScript 6 (131)

Einfach in ein paar Sekunden zusammen tippen, damit es wahrscheinlich weiter golfen oder vielleicht sogar besser angefahren werden kann. Ich könnte es morgen noch einmal besuchen:

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

Bearbeiten: Das Ersetzen des Stapels durch ein Array ist viel kürzer

Edit2: Ersetzte das ifs durch einen ternären Ausdruck


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

1

Python 2

Ich habe verschiedene Ansätze zu den bisher veröffentlichten ausprobiert. Keines davon ist so kurz wie die besten Python-Lösungen, aber für einige von Ihnen könnten sie dennoch interessant sein.

Rekursion verwenden, 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]

Verwenden der Listenbearbeitung, 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]

Verwenden 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

Sie können 2 weitere Bytes sparen, indem Sie alles auf eine Zeile setzen (oder einen Texteditor verwenden, der nur ein Zeichen für die neue Zeile verwendet)
Hoki

@Hoki Ich benutze nur neue Leitungen, wenn kein Zeilenumbruch erforderlich wäre ;. Ich denke, die Anzahl der Bytes ist die gleiche
Luis Mendo

Nicht genau, die meisten Fenster-Texteditoren verwenden cr+lfeine neue Zeile mit 2 Zeichen. Mein Notizblock ++ zählte 230 Zeichen in Ihrer 3-Zeilen-Version, aber nur 128, wenn ich alles in eine Zeile klebe (2 * 2 = 4 Zeichen aus den 2 Zeilen entfernt und zwei hinzugefügt ;). Probieren Sie es selbst;)
Hoki

@Hoki Du hast recht. Wenn ich die dreizeilige Version in mothereff.in/byte-counter einfüge (was ich zum Zählen von Textbytes verwendet habe), ergibt sich eine 228. Und das ergibt sich natürlich auch, wenn ich alles in eine einzige einfüge Linie. Ich weiß nicht, woher ich die Nummer 230 habe. Vielen Dank! Korrigiert
Luis Mendo

1

K5, 70 Bytes

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

Ich bin nicht sicher , wenn K5 veröffentlicht wurde, so dass diese Macht nicht zählen. Immer noch toll!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.