Notazione polacca inversa


41

È necessario valutare una stringa scritta in notazione polacca inversa e produrre il risultato.

Il programma deve accettare un input e restituire l'output. Per i linguaggi di programmazione che non dispongono di funzioni per ricevere input / output, è possibile assumere funzioni come readLine / print.

Non è consentito utilizzare alcun tipo di "valutazione" nel programma.

I numeri e gli operatori sono separati da uno o più spazi.

È necessario supportare almeno gli operatori +, -, * e /.

Devi aggiungere supporto ai numeri negativi (ad esempio, -4non è la stessa cosa di 0 4 -) e ai numeri in virgola mobile.

Puoi presumere che l'input sia valido e segua le regole sopra


Casi test

Ingresso:

-4 5 +

Produzione:

1

Ingresso:

5 2 /

Produzione:

2.5

Ingresso:

5 2.5 /

Produzione:

2

Ingresso:

5 1 2 + 4 * 3 - +

Produzione:

14

Ingresso:

4 2 5 * + 1 3 2 * + /

Produzione:

2

8
E 'un peccato non è consentita alcuna eval, altrimenti la soluzione GolfScript è 1 carattere: ~. :-P
Chris Jester-Young,

5
Ecco perché non è permesso :-P, questa domanda su StackOverflow ha ricevuto una risposta di 4 caratteri con dc.

1
@SHiNKiROU: quale lingua devi utilizzare evalper analizzare i numeri? Sembra abbastanza rotto. (GolfScript è uno di questi linguaggi, per quanto ne so. Penso che sia rotto anche lui.)
Chris Jester-Young,

3
In che modo -4 non è uguale a 0 4 -?
Keith Randall,

1
Penso che eval dovrebbe andare bene se fosse solo per convertire le stringhe in numeri. per esempio. in python eval(s)è meglio difloat(s)
gnibbler il

Risposte:


15

Rubino - 95 77 caratteri

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

Accetta input su stdin.

Codice di prova

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

A differenza della versione C, questo restituisce l'ultimo risultato valido se ci sono numeri aggiuntivi aggiunti all'input che sembra.


1
Puoi radere un personaggio usando la mappa invece di ciascuno
addison

10

Python - 124 caratteri

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 caratteri

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
Mi piace la manipolazione dello stack.
Alexandru,

2
Non puoi avere 0come secondo operando ...
JBernardo,

2
[a/b]deve essere sostituito in b and[a/b]modo da poter avere 0 come secondo operando.
terremoto del

10

Schema, 162 caratteri

(Le interruzioni di riga sono state aggiunte per maggiore chiarezza: tutte sono opzionali.)

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

Versione completamente formattata (non giocata):

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

Commento selezionato

`(,foo ,@bar)è uguale a (cons foo bar)(cioè, effettivamente ( ) restituisce un nuovo elenco con fooanteposto abar ), tranne per il fatto che è più corto di un carattere se comprimi tutti gli spazi.

Pertanto, puoi leggere le clausole di iterazione come (loop (cons token stack))e (loop (cons ((cadr ass) (cadr stack) (car stack)) (cddr stack)))se è più facile per i tuoi occhi.

`((+ ,+) (- ,-) (* ,*) (/ ,/))crea un elenco di associazioni con il simbolo + associato alla procedura + e allo stesso modo con gli altri operatori. Quindi è una semplice tabella di ricerca dei simboli (le parole nude sono (read)presenti come simboli, motivo per cui non è possibile elaborarle ulteriormentetoken è necessaria ). Gli elenchi di associazioni hanno una ricerca O (n) e quindi sono adatti solo per elenchi brevi, come nel caso qui. :-P

† Questo non è tecnicamente accurato, ma, per i programmatori non Lisp, ottiene un'idea abbastanza giusta.


Puoi leggerlo? Sul serio?

1
@ M28: la versione non golfata, sì. Programma in Scheme su base semi-regolare (per programmi reali e seri).
Chris Jester-Young,

Sfortunatamente, Scheme è un linguaggio prolisso e notoriamente difficile da giocare bene a golf. Quindi non sarei sorpreso di vedere un po 'di sottomissione al Perl battere questo.
Chris Jester-Young,

7
Mi piacciono le quattro faccine nella versione golf.
Tomsmeding

2
lambda (ass)+1 per la scelta del nome variabile: P
Downgoat

7

c - 424 caratteri necessari

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

Presuppone che tu abbia una libc abbastanza nuova da includere getdelimin stdio.h. L'approccio è diretto, l'intero input viene letto in un buffer, quindi tokenize con strsepe usiamo lunghezza e carattere iniziale per determinare la classe di ciascuno. Non esiste protezione contro input errati. Alimentalo "+ - * / + - ...", e farà felicemente espellere le cose dalla memoria "sotto" lo stack fino a quando non si guasta. Tutti i non operatori sono interpretati come float, il atofche significa valore zero se non sembrano numeri.

Leggibile e commentato:

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

convalida:

 $ 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

Eh! Devo citare qualcosa con *dentro ...

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

e il mio test case

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

Puoi proteggere alcuni personaggi sostituendoli 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

Puoi rimuovere 9 caratteri cambiando "(s: _)! [] = S" in "(s: _)! [] = Print s" e "main = getLine >> = putStrLn.show. ([]! ) .words "a" main = getLine >> = ([]!). words "
Fors

E quindi rimuovere ulteriormente alcuni altri caratteri usando un'istruzione case di una riga.
Fors,

s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!vsalverebbe 14 caratteri.
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'input viene letto dall'input dell'utente, l'output viene stampato).


Di seguito è riportato il codice preimpostato e commentato, implementa praticamente l' algoritmo Postfix descritto (presupponendo che le espressioni siano valide):

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:

Nel codice, ipotizziamo operatori sono sempre binario ( +, -, *, /). Possiamo generalizzarlo usando nargin(f)per determinare il numero di argomenti richiesti dall'operando / funzione e far comparire di conseguenza la giusta quantità di valori dallo stack, come in:

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

In questo modo possiamo valutare espressioni come:

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

dove mean_of_threeè una funzione definita dall'utente con tre ingressi:

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 prossima volta, userò la cosa regexp ricorsiva.

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

Anche se F # è il mio unico linguaggio di programmazione dei sogni ...


Ho un'implementazione più breve di Perl 5.
dolmen

6

Windows PowerShell, 152 181 192

In forma leggibile, perché ormai sono solo due righe senza possibilità di romperle:

$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) - Primo tentativo.

30/01/2010 11:09 (170) - La trasformazione della funzione in uno scriptblock risolve i problemi relativi all'ambito. Rende solo ogni chiamata più lunga di due byte.

30/01/2010 11:19 (188) - Non è stato risolto il problema relativo all'ambito, il caso di test lo ha semplicemente mascherato. Rimosso l'indice dall'output finale e rimosso un'interruzione di linea superflua. E cambiato doppio in float.

30/01/2010 11:19 (181) - Non ricordo nemmeno il mio consiglio. La trasmissione in un tipo numerico può essere eseguita in un singolo carattere.

30/01/2010 11:39 (152) - Ridotto notevolmente usando la corrispondenza regex in switch. Risolve completamente i precedenti problemi dell'ambito con l'accesso allo stack per visualizzarlo.


5

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

Interruzioni di riga facoltative.

Basato sulla soluzione di Chris Jester-Young per Scheme.


4

Python, 166 caratteri

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]

Il raw_input()codice d' uso non è suddiviso su più righe.
JPvd Merwe,

Quindi potresti provare: from operator import*e sostituirlo o.divcon div.
JPvd Merwe

4

Python 3, 119 byte

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

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

Produzione: 2.5

(Puoi trovare una versione Python 2 di 128 caratteri nella cronologia delle modifiche.)


Abbastanza intelligente :) Mi piace come non ti serva /nella stringa.
Daniel Lubarov,


@EriktheOutgolfer che si interrompe con a ZeroDivisionErrorquando il secondo operando è 0 (ad es 5 0 +.).
terremoto del

Puoi salvare 1 carattere usando il ord(x) - 42metodo
frederick99,

@ frederick99 Non vedo come.
terremoto del

3

JavaScript (157)

Questo codice presuppone che ci siano queste due funzioni: 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])

Più corto se usi prompt()invece di readLine()(e forse alert()invece di print()abbinare prompt()).
nyuszika7h

3

Perl, 128

Questo non è realmente competitivo accanto all'altra risposta del Perl, ma esplora un percorso diverso (non ottimale).

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

I personaggi contati come diff in una semplice perl -e ''invocazione.


2

Python, 161 caratteri:

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 caratteri

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

Questo codice dovrebbe funzionare con stdin, sebbene non sia stato testato con stdin.

È stato testato su tutti i casi, l'output (e il codice) per l'ultimo è qui:
http://codepad.viper-7.com/fGbnv6

Ungolfed, 314 330 326 caratteri

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

Citazione dalla descrizione dell'attività: »Per i linguaggi di programmazione che non dispongono di funzioni per ricevere input / output, è possibile assumere funzioni come readLine / print.« - dimostra che PHP ha funzioni per farlo, quindi il presupposto non è corretto.
Joey,

Aggiornato per usare stdin e giocare a golf un po 'di più.
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 non hai familiarità, compila con flex rpn.l && gcc -lfl lex.yy.c


2

Python, 130 caratteri

Sarebbe 124 caratteri se cadessimo b and(mancando alcune delle risposte di 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]

Davvero una bella risposta. Ma conto 130 caratteri. ;)
terremoto del

@flornquake hai ragione, grazie per la correzione.
Daniel Lubarov,

2

Python 3, 126 132 caratteri

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

Ci sono già state soluzioni migliori, ma ora che l'ho scritto (senza aver letto le osservazioni precedenti, ovviamente - anche se devo ammettere che il mio codice sembra averli copiati insieme), volevo condividerlo, pure.


b/adeve essere sostituito a and b/a, altrimenti questa soluzione non funzionerà se il secondo operando è 0 (ad es 4 0 -.).
terremoto del

@flornquake Risolto il problema per lui.
mbomb007,

2

c99 gcc 235

Questo funziona per me (con avvertenze):

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

Ma se lo stai compilando con mingw32 devi disattivare il globbing (vedi https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ) compilando in questo modo:

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

In caso contrario * viene automaticamente espanso dal CRT mingw32.

Qualcuno sa come trasformarsi break;case'*':s[--d]*=s[d+1];in una macro che accetta il carattere + come parametro perché tutti e quattro i casi lo sarebberoO(+)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 byte

Divertimento con la ricorsione.

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

Casi 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 caratteri

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

Supponendo un input nella variabile POST i .


2
Citato dalla descrizione originale »Per i linguaggi di programmazione che non dispongono di funzioni per ricevere input / output, è possibile assumere funzioni come readLine / print.« PHP ha un modo per ottenere lo stdin attraverso gli stream.
Kevin Brown,

1

C # - 392 caratteri

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

Tuttavia, se è possibile utilizzare argomenti al posto dello standard input, possiamo portarlo a

C # - 366 caratteri

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

È possibile salvare 23 caratteri con una piccola ottimizzazione: 1. rimuovere il trucco dello spazio dei nomi, qualificare esplicitamente i due tipi che ne hanno bisogno. Si salva la parola chiave "namespace" e le parentesi corrispondenti. 2. Rimuovere gli spazi tra stringa [] e i, parole chiave ed etichette del caso, switch e relative parentesi. 3. Sbarazzati di float o e usa semplicemente la matematica per ottenere i risultati giusti (es. -K.Pop () + k.Pop () per meno, e 1 / k.Pop () * k.Pop () per dividere .
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())

Versione non golfata:

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

Input dall'argomento della riga di comando; uscita su uscita standard.


1

ECMAScript 6 (131)

Appena digitato insieme in pochi secondi, quindi probabilmente può essere ulteriormente giocato a golf o forse anche affrontato meglio. Potrei rivederlo domani:

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

Modifica: la sostituzione della pila con una matrice è molto più breve

Edit2: ha sostituito gli if con un'espressione ternaria


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

1

Python 2

Ho provato alcuni approcci diversi a quelli pubblicati finora. Nessuna di queste è abbastanza breve come le migliori soluzioni Python, ma potrebbero essere interessanti per alcuni di voi.

Usando la ricorsione, 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]

Utilizzo della manipolazione di elenchi, 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]

Utilizzando 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

Puoi salvare altri 2 byte mettendo tutto su una riga (o utilizzare un editor di testo che utilizza solo un carattere per la nuova riga)
Hoki,

@Hoki Sto usando solo nuove linee quando non spezzare la linea richiederebbe un ;. Quindi penso che il conteggio dei byte sia lo stesso
Luis Mendo il

non esattamente, la maggior parte degli editor di testi di finestre usa cr+lfper una nuova riga, che è di 2 caratteri. Il mio blocco note ++ ha contato 230 caratteri nella tua versione a 3 righe, ma solo 128 se ho incollato tutto in una riga (rimosso 2 * 2 = 4 caratteri dalle 2 nuove righe e aggiunto due ;). Provalo tu;)
Hoki,

@Hoki Hai ragione. In effetti, se incollo la versione a tre righe su mothereff.in/byte-counter (che è quello che ho usato per contare i byte di testo), dà 228. E ovviamente è anche quello che ottengo dal mettere tutto in un unico linea. Non so da dove ho preso il numero 230. Grazie! Corretto
Luis Mendo il

1

K5, 70 byte

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

Non sono sicuro del rilascio di K5, quindi potrebbe non essere valido. Comunque fantastico!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.