Membalikkan notasi Polandia

41

Anda harus mengevaluasi string yang ditulis dalam notasi Reverse Polish dan menghasilkan hasilnya.

Program harus menerima input dan mengembalikan output. Untuk bahasa pemrograman yang tidak memiliki fungsi untuk menerima input / output, Anda dapat mengasumsikan fungsi seperti readLine / print.

Anda tidak diizinkan menggunakan "eval" dalam program apa pun.

Angka dan operator dipisahkan oleh satu ruang atau lebih .

Anda harus mendukung setidaknya +, -, * dan / operator.

Anda perlu menambahkan dukungan ke angka negatif (misalnya, -4tidak sama dengan 0 4 -) dan angka floating point.

Anda dapat menganggap input tersebut valid dan mengikuti aturan di atas


Uji Kasus

Memasukkan:

-4 5 +

Keluaran:

1

Memasukkan:

5 2 /

Keluaran:

2.5

Memasukkan:

5 2.5 /

Keluaran:

2

Memasukkan:

5 1 2 + 4 * 3 - +

Keluaran:

14

Memasukkan:

4 2 5 * + 1 3 2 * + /

Keluaran:

2

sumber
8
Sayang tidak ada eval diperbolehkan, jika solusi GolfScript adalah 1 karakter: ~. :-P
Chris Jester-Young
5
Itu sebabnya tidak diizinkan :-P, pertanyaan tentang StackOverflow ini menerima jawaban 4 karakter dengan dc.
1
@SHiNKiROU: Bahasa apa yang mengharuskan Anda untuk menggunakan evalnomor parse? Kedengarannya sangat rusak. (GolfScript adalah salah satu bahasa seperti itu, sejauh yang saya tahu. Saya pikir itu rusak juga.)
Chris Jester-Young
3
Bagaimana -4 tidak sama dengan 0 4 -?
Keith Randall
1
Saya pikir eval harus baik-baik saja jika hanya untuk mengubah string menjadi angka. misalnya. di python eval(s)lebih baik daripadafloat(s)
gnibbler

Jawaban:

15

Ruby - 95 77 karakter

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

Mengambil input pada stdin.

Kode pengujian

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

memberi

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

Tidak seperti versi C, ini mengembalikan hasil valid terakhir jika ada angka tambahan yang ditambahkan ke input.

Nemo157
sumber
1
Anda bisa mencukur satu karakter dengan menggunakan peta alih-alih masing
addison
10

Python - 124 karakter

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 karakter

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]
gnibbler
sumber
1
Saya suka manipulasi tumpukan.
Alexandru
2
Anda tidak dapat memiliki 0operan kedua ...
JBernardo
2
[a/b]harus diganti dengan b and[a/b]sehingga Anda dapat memiliki 0 sebagai operan kedua.
flornquake
10

Skema, 162 karakter

(Jeda baris ditambahkan untuk kejelasan — semua adalah opsional.)

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

Versi berformat penuh (ungolfed):

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

Komentar yang dipilih

`(,foo ,@bar)sama dengan (cons foo bar)(yaitu, (secara efektif ) mengembalikan daftar baru dengan fooprepended to bar), kecuali satu karakter lebih pendek jika Anda mengompres semua spasi.

Dengan demikian, Anda dapat membaca klausa iterasi sebagai (loop (cons token stack))dan (loop (cons ((cadr ass) (cadr stack) (car stack)) (cddr stack)))jika itu lebih mudah di mata Anda.

`((+ ,+) (- ,-) (* ,*) (/ ,/))membuat daftar asosiasi dengan simbol yang + dipasangkan dengan prosedur + , dan juga dengan operator lain. Jadi ini adalah tabel pencarian simbol sederhana (kata-kata telanjang adalah (read)sebagai simbol, itulah sebabnya tidak diperlukan proses lebih lanjut token). Daftar asosiasi memiliki pencarian O (n), dan karenanya hanya cocok untuk daftar pendek, seperti halnya di sini. :-P

† Ini secara teknis tidak akurat, tetapi, untuk programmer non-Lisp, ia mendapatkan ide yang cukup tepat.

Chris Jester-Young
sumber
Bisakah kamu baca itu? Serius?
1
@ M28: Versi ungolfed, ya. Saya memprogram dalam Skema secara semi-reguler (untuk program nyata dan serius).
Chris Jester-Young
Sayangnya, Skema adalah bahasa verbal dan sangat sulit untuk bermain golf dengan baik. Jadi saya tidak akan terkejut melihat beberapa pengajuan Perl mengalahkan yang ini.
Chris Jester-Young
7
Saya suka empat smiley dalam versi golf.
tomsmeding
2
lambda (ass)+1 untuk pilihan nama variabel: P
Downgoat
7

c - 424 karakter yang diperlukan

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

Asumsikan bahwa Anda memiliki libc yang cukup baru untuk dimasukkan getdelimdalam stdio.h. Pendekatannya lurus ke depan, seluruh input dibaca ke dalam buffer, lalu kita tokenize dengan strsepmenggunakan panjang dan karakter awal untuk menentukan kelas masing-masing. Tidak ada perlindungan terhadap input yang buruk. Beri makan "+ - * / + - ...", dan ia dengan senang hati akan mengeluarkan barang-barang dari memori "di bawah" tumpukan hingga rusak. Semua non-operator ditafsirkan sebagai pelampung atofyang berarti nilai nol jika mereka tidak terlihat seperti angka.

Dapat dibaca dan dikomentari:

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

Validasi:

 $ 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! Harus mengutip apa pun dengan *di dalamnya ...

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

dan test case saya sendiri

 $ echo "12 8 3 * 6 / - 2 + -20.5 " | ./a.out
-20.500000
dmckee
sumber
Anda dapat mengamankan beberapa karakter dengan mengganti casedengan 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
sumber
Anda bisa menghapus 9 karakter dengan mengubah "(s: _)! [] = S" ke "(s: _)! [] = Print s" dan "main = getLine >> = putStrLn.show. ([]! ) .words "to" main = getLine >> = ([]!). kata "
Fors
Dan selanjutnya menghapus beberapa karakter lain dengan menggunakan pernyataan kasus satu baris.
Fors
s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!vakan menghemat 14 karakter.
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

(input dibaca dari input pengguna, output dicetak).


Di bawah ini adalah kode yang telah diprogram dan dikomentari, cukup banyak mengimplementasikan algoritma postfix yang dijelaskan (dengan asumsi bahwa ekspresi adalah valid):

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:

Pada kode di atas, kita asumsikan operator selalu biner ( +, -, *, /). Kita dapat menggeneralisasikannya dengan menggunakan nargin(f)untuk menentukan jumlah argumen yang dibutuhkan oleh operand / function, dan memunculkan jumlah nilai yang tepat dari stack sesuai dengan itu, seperti pada:

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

Dengan begitu kita dapat mengevaluasi ekspresi seperti:

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

di mana mean_of_threefungsi yang ditentukan pengguna dengan tiga input:

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

Lain kali, saya akan menggunakan regexp hal rekursif.

Tidak Disatukan:

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

Saya pikir F ​​# adalah satu-satunya bahasa pemrograman impian saya ...

Ming-Tang
sumber
Saya memiliki implementasi Perl 5 yang lebih pendek.
dolmen
6

Windows PowerShell, 152 181 192

Dalam bentuk yang dapat dibaca, karena saat ini hanya ada dua baris tanpa peluang untuk memecahnya:

$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) - Upaya pertama.

2010-01-30 11:09 (170) - Mengubah fungsi menjadi scriptblock memecahkan masalah ruang lingkup. Buat setiap doa dua byte lebih lama.

2010-01-30 11:19 (188) - Tidak menyelesaikan masalah ruang lingkup, test case hanya menutupinya. Menghapus indeks dari hasil akhir dan menghapus jeda baris yang berlebihan. Dan berubah ganda menjadi float.

2010-01-30 11:19 (181) - Bahkan tidak bisa mengingat saran saya sendiri. Casting ke tipe numerik dapat dilakukan dalam satu karakter.

2010-01-30 11:39 (152) - Sangat dikurangi dengan menggunakan pencocokan regex di switch. Selesaikan sepenuhnya masalah ruang lingkup sebelumnya dengan mengakses tumpukan untuk melewatinya.

Joey
sumber
5

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

Pemutusan saluran opsional.

Berdasarkan solusi Chris Jester-Young untuk Skema.

Sam Tobin-Hochstadt
sumber
4

Python, 166 karakter

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
sumber
Gunakan raw_input()kode tidak terbagi dalam beberapa baris.
JPvdMerwe
Kemudian Anda dapat mencoba: from operator import*dan ganti o.divdengan div.
JPvdMerwe
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])

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

Keluaran: 2.5

(Anda dapat menemukan versi 128-karakter Python dalam sejarah edit.)

gempa bumi
sumber
Cukup pintar :) Saya suka bagaimana Anda tidak perlu /dalam string.
Daniel Lubarov
114 byte
Erik the Outgolfer
@EriktheOutgolfer yang terputus dengan ZeroDivisionErrorsaat operan kedua adalah 0 (mis 5 0 +.).
flornquake
Anda dapat menyimpan 1 karakter dengan menggunakan ord(x) - 42metode ini.
frederick99
@ frederick99 Saya tidak mengerti caranya.
flornquake
3

JavaScript (157)

Kode ini mengasumsikan ada dua fungsi ini: readLine dan cetak

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

sumber
Lebih pendek jika Anda menggunakan prompt()bukan readLine()(dan mungkin alert()bukan print()untuk mencocokkan prompt()).
nyuszika7h
3

Perl, 128

Ini tidak benar-benar kompetitif di sebelah jawaban Perl lainnya, tetapi mengeksplorasi jalur (suboptimal) yang berbeda.

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

Karakter dihitung sebagai berbeda dengan perl -e ''doa sederhana .

JB
sumber
2

Python, 161 karakter:

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
sumber
2

PHP, 439 265 263 262 244 240 karakter

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

Kode ini harus bekerja dengan stdin, meskipun tidak diuji dengan stdin.

Telah diuji pada semua kasus, output (dan kode) untuk yang terakhir ada di sini:
http://codepad.viper-7.com/fGbnv6

Tidak dikumpulkan, 314 330 326 karakter

<?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
sumber
Kutipan dari uraian tugas: »Untuk bahasa pemrograman yang tidak memiliki fungsi untuk menerima input / output, Anda dapat mengasumsikan fungsi seperti readLine / print.« - PHP dapat dibuktikan memiliki fungsi untuk melakukannya, oleh karena itu anggapannya salah.
Joey
Diperbarui untuk menggunakan stdin dan golf sedikit lebih.
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);
.
%%

Jika Anda tidak terbiasa, kompilasi dengan flex rpn.l && gcc -lfl lex.yy.c

Geoff Reedy
sumber
2

Python, 130 karakter

Akan menjadi 124 karakter jika kita menjatuhkan b and(yang beberapa jawaban Python hilang). Dan itu menggabungkan 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
sumber
Jawaban yang sangat bagus. Tapi saya menghitung 130 karakter. ;)
flornquake
@flake Anda benar, terima kasih atas koreksinya.
Daniel Lubarov
2

Python 3, 126 132 karakter

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

Sudah ada solusi yang lebih baik, tetapi sekarang saya telah menulisnya (tanpa harus membaca kiriman sebelumnya, tentu saja - meskipun saya harus mengakui bahwa kode saya terlihat seolah-olah saya telah menyalinnya bersama-sama), saya ingin membagikannya, terlalu.

cemper93
sumber
b/aharus diganti dengan a and b/a, jika tidak solusi ini tidak akan berfungsi jika operan kedua adalah 0 (mis 4 0 -.).
flornquake
@flakee Memperbaikinya untuknya.
mbomb007
2

c99 gcc 235

Ini bekerja untuk saya (dengan peringatan):

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

Tetapi jika Anda mengompilasinya dengan mingw32 Anda harus mematikan globbing (lihat https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ) dengan mengkompilasi seperti ini:

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

Jika Anda tidak * secara otomatis diperluas oleh mingw32 CRT.

Adakah yang tahu bagaimana cara berubah break;case'*':s[--d]*=s[d+1];menjadi makro yang menerima karakter + sebagai parameter karena dengan demikian keempat kasus hanya akan menjadiO(+)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
sumber
2

C, 232 229 byte

Bersenang-senang dengan rekursi.

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

Tidak Disatukan:

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

Kasus uji:

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

JavaScript ES7, 119 byte

Saya mendapatkan bug dengan pemahaman array jadi saya gunakan .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)

Cobalah online di ESFiddle

Downgoat
sumber
Apakah ada juru bahasa ES7 yang tersedia?
Conor O'Brien
@CᴏɴᴏʀO'Bʀɪᴇɴ ini seharusnya bisa digunakan di Firefox. Anda bisa mencoba babeljs.io/repl
Downgoat
Oh begitu. ^ _ ^ Terima kasih!
Conor O'Brien
1

PHP - 259 karakter

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

Mengasumsikan input dalam variabel POST i .

Aurel Bílý
sumber
2
Dikutip dari deskripsi asli »Untuk bahasa pemrograman yang tidak memiliki fungsi untuk menerima input / output, Anda dapat mengasumsikan fungsi seperti readLine / print.« PHP memiliki cara untuk mendapatkan stdin melalui stream.
Kevin Brown
1

C # - 392 karakter

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

Namun, jika argumen dapat digunakan alih-alih input standar, kita dapat membawanya ke

C # - 366 karakter

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
sumber
Anda dapat menyimpan 23 karakter dengan sedikit optimasi: 1. menghapus trik namespace, secara eksplisit memenuhi syarat dua jenis yang membutuhkannya. Anda menyimpan kata kunci "namespace" dan tanda kurung yang sesuai. 2. Hapus spasi antara string [] dan i, kata kunci dan label kasus, alihkan dan parensnya. 3. Singkirkan float o dan cukup gunakan matematika untuk mendapatkan hasil yang benar (mis. -K.Pop () + k.Pop () untuk minus, dan 1 / k.Pop () * k.Pop () untuk membagi .
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))}
Pengguna tidak diketahui
sumber
1

Python - 206

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

Versi tidak disatukan:

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

Masukan dari argumen baris perintah; output pada output standar.

pegolf9338
sumber
1

ECMAScript 6 (131)

Hanya mengetik bersama dalam beberapa detik, jadi mungkin bisa bermain golf lebih jauh atau bahkan mendekati lebih baik. Saya mungkin akan mengunjungi lagi besok:

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

Sunting: Mengganti Stack dengan Array jauh lebih pendek

Sunting2: Mengganti ifs dengan ekspresi ternary

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

Python 2

Saya sudah mencoba beberapa pendekatan berbeda dengan yang diterbitkan sejauh ini. Tidak satu pun dari ini yang sesingkat solusi Python terbaik, tetapi mereka mungkin masih menarik bagi sebagian dari Anda.

Menggunakan rekursi, 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]

Menggunakan manipulasi daftar, 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]

Menggunakan 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]
gempa bumi
sumber
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}

Tidak Disatukan:

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
sumber
Anda dapat menyimpan 2 byte lebih banyak dengan meletakkan semuanya pada satu baris (atau menggunakan editor teks yang hanya menggunakan satu karakter untuk baris baru)
Hoki
@ Hoki Saya hanya menggunakan baris baru ketika tidak melanggar garis akan membutuhkan ;. Jadi saya pikir jumlah byte sama
Luis Mendo
tidak persis, sebagian besar editor teks jendela digunakan cr+lfuntuk baris baru, yaitu 2 karakter. Notepad saya ++ menghitung 230 karakter dalam versi 3 baris Anda, tetapi hanya 128 jika saya menempelkan semuanya dalam satu baris (dihapus 2 * 2 = 4 karakter dari 2 baris baru, dan menambahkan dua ;). Coba sendiri;)
Hoki
@ Hoki Kamu benar. Bahkan, jika saya menempelkan versi tiga baris pada mothereff.in/byte-counter (yang saya gunakan untuk menghitung byte teks), ia memberikan 228. Dan tentu saja itu juga yang saya dapatkan dari meletakkan semuanya dalam satu baris. Saya tidak tahu dari mana saya mendapatkan nomor 230. Terima kasih! Diperbaiki
Luis Mendo
1

K5, 70 byte

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

Saya tidak yakin kapan K5 dirilis, jadi ini mungkin tidak masuk hitungan. Masih mengagumkan!

kirbyfan64sos
sumber