Ký hiệu đảo ngược Ba Lan


41

Bạn phải đánh giá một chuỗi được viết bằng ký hiệu Reverse Ba Lan và đưa ra kết quả.

Chương trình phải chấp nhận đầu vào và trả lại đầu ra. Đối với các ngôn ngữ lập trình không có chức năng nhận đầu vào / đầu ra, bạn có thể đảm nhận các chức năng như readLine / print.

Bạn không được phép sử dụng bất kỳ loại "eval" nào trong chương trình.

Các số và toán tử được phân tách bằng một hoặc nhiều khoảng trắng.

Bạn phải hỗ trợ ít nhất các toán tử +, -, * và /.

Bạn cần thêm hỗ trợ cho các số âm (ví dụ: -4không giống như 0 4 -) và các số dấu phẩy động.

Bạn có thể giả sử đầu vào là hợp lệ và tuân theo các quy tắc trên


Các trường hợp thử nghiệm

Đầu vào:

-4 5 +

Đầu ra:

1

Đầu vào:

5 2 /

Đầu ra:

2.5

Đầu vào:

5 2.5 /

Đầu ra:

2

Đầu vào:

5 1 2 + 4 * 3 - +

Đầu ra:

14

Đầu vào:

4 2 5 * + 1 3 2 * + /

Đầu ra:

2

8
Thật xấu hổ khi không cho phép eval, nếu không thì giải pháp GolfScript là 1 ký tự : ~. :-P
Chris Jester-Young

5
Đó là lý do tại sao nó không được phép :-P, câu hỏi này trên StackOverflow đã nhận được câu trả lời 4 ký tự với dc.

1
@SHiNKiROU: Ngôn ngữ nào yêu cầu bạn sử dụng evalđể phân tích số? Nghe có vẻ khá vỡ. (GolfScript là một ngôn ngữ như vậy, theo như tôi biết. Tôi nghĩ nó cũng bị hỏng.)
Chris Jester-Young

3
Làm thế nào là -4 không giống với 0 4 -?
Keith Randall

1
Tôi nghĩ eval sẽ ổn nếu chỉ chuyển đổi chuỗi thành số. ví dụ. trong python eval(s)tốt hơnfloat(s)
gnibbler

Câu trả lời:


15

Ruby - 95 77 ký tự

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

Đưa đầu vào vào stdin.

Mã kiểm tra

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

cho

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

Không giống như phiên bản C, nó trả về kết quả hợp lệ cuối cùng nếu có thêm số được thêm vào đầu vào.


1
Bạn có thể cạo sạch một nhân vật bằng cách sử dụng bản đồ thay vì mỗi nhân vật
addison

10

Python - 124 ký tự

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 ký tự

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
Tôi thích các thao tác ngăn xếp.
Alexandru

2
Bạn không thể có 0toán hạng thứ hai ...
JBernardo

2
[a/b]nên được thay thế bằng b and[a/b]để bạn có thể có 0 là toán hạng thứ hai.
flornquake

10

Đề án, 162 ký tự

(Ngắt dòng được thêm vào cho rõ ràng. Tất cả đều là tùy chọn.)

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

Phiên bản được định dạng đầy đủ (chưa được chỉnh sửa):

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

Bình luận được chọn

`(,foo ,@bar)giống như (cons foo bar)(nghĩa là nó (có hiệu quả ) trả về một danh sách mới có foosẵn bar), ngoại trừ một ký tự ngắn hơn nếu bạn nén tất cả các khoảng trắng.

Do đó, bạn có thể đọc các mệnh đề lặp (loop (cons token stack))(loop (cons ((cadr ass) (cadr stack) (car stack)) (cddr stack)))nếu điều đó dễ dàng hơn trong mắt bạn.

`((+ ,+) (- ,-) (* ,*) (/ ,/))tạo một danh sách liên kết với ký hiệu + được ghép nối với thủ tục + và tương tự với các toán tử khác. Do đó, đây là một bảng tra cứu biểu tượng đơn giản (các từ trống (read)là các ký hiệu, đó là lý do tại sao không cần xử lý thêm token). Danh sách hiệp hội có tra cứu O (n) và do đó chỉ phù hợp với danh sách ngắn, như trường hợp ở đây. :-P

Điều này không chính xác về mặt kỹ thuật, nhưng, đối với các lập trình viên không phải là Lisp, nó có một ý tưởng đủ đúng.


Bạn có thể đọc nó không? Nghiêm túc?

1
@ M28: Phiên bản vô văn hóa, vâng. Tôi lập trình trong Đề án trên cơ sở bán định kỳ (đối với các chương trình thực tế, nghiêm túc).
Chris Jester-Young

Thật không may, Scheme là một ngôn ngữ dài dòng và nổi tiếng là khó chơi golf. Vì vậy, tôi sẽ không ngạc nhiên khi thấy một số đệ trình Perl đánh bại điều này.
Chris Jester-Young

7
Tôi thích bốn mặt cười trong phiên bản golf.
tomsmeding

2
lambda (ass)+1 cho lựa chọn tên biến: P
Downgoat

7

c - 424 ký tự cần thiết

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

Giả sử rằng bạn có một libc mới đủ để đưa getdelimvào stdio.h. Cách tiếp cận là thẳng về phía trước, toàn bộ đầu vào được đọc vào một bộ đệm, sau đó chúng tôi mã hóa strsepvà sử dụng độ dài và ký tự ban đầu để xác định lớp của mỗi loại. Không có bảo vệ chống lại đầu vào xấu. Cho nó ăn "+ - * / + - ...", và nó sẽ vui vẻ bật ra khỏi bộ nhớ "bên dưới" ngăn xếp cho đến khi nó bị lỗi. Tất cả những người không khai thác được hiểu là số float atofcó nghĩa là giá trị bằng 0 nếu chúng không giống như số.

Đọc và nhận xét:

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

Thẩm định:

 $ 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! Phải trích dẫn bất cứ điều gì với *nó ...

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

và trường hợp thử nghiệm của riêng tôi

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

Bạn có thể an toàn một số nhân vật bằng cách thay thế casebằng một 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

Bạn có thể xóa 9 ký tự bằng cách thay đổi "(s: _)! [] = S" thành "(s: _)! [] = Print s" và "main = getLine >> = putStrLn.show. ([]! ) .words "đến" main = getLine >> = ([]!). words "
Fors

Và sau đó loại bỏ thêm một vài ký tự khác bằng cách sử dụng câu lệnh tình huống một dòng.
Dành cho

s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!vsẽ lưu 14 ký tự.
Dành cho

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

(đầu vào được đọc từ đầu vào của người dùng, đầu ra được in ra).


Dưới đây là mã được chỉnh sửa và nhận xét, nó thực hiện khá nhiều thuật toán postfix được mô tả (với giả định rằng các biểu thức là hợp lệ):

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

Thêm:

Trong đoạn mã trên, chúng tôi giả định các nhà khai thác luôn nhị phân ( +, -, *, /). Chúng ta có thể khái quát hóa nó bằng cách sử dụng nargin(f)để xác định số lượng đối số mà toán hạng / hàm yêu cầu và bật đúng số lượng giá trị từ ngăn xếp tương ứng, như trong:

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

Bằng cách đó chúng ta có thể đánh giá các biểu thức như:

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

trong đó mean_of_threemột hàm do người dùng định nghĩa với ba đầu vào:

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

Lần tới, tôi sẽ sử dụng điều regrec đệ quy.

Ung dung:

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

Tôi mặc dù F # là ngôn ngữ lập trình mơ ước duy nhất của tôi ...


Tôi có một triển khai Perl 5 ngắn hơn.
heo

6

Windows PowerShell, 152 181 192

Ở dạng có thể đọc được, bởi vì bây giờ chỉ có hai dòng không có cơ hội phá vỡ chúng:

$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) - Nỗ lực đầu tiên.

2010-01-30 11:09 (170) - Biến hàm thành scriptblock giải quyết các vấn đề phạm vi. Chỉ cần làm cho mỗi lần gọi hai byte dài hơn.

2010-01-30 11:19 (188) - Không giải quyết được vấn đề phạm vi, trường hợp thử nghiệm chỉ che giấu nó. Mặc dù vậy, đã xóa chỉ mục khỏi đầu ra cuối cùng và loại bỏ một ngắt dòng không cần thiết. Và đổi gấp đôi thành float.

2010-01-30 11:19 (181) - Thậm chí không thể nhớ lời khuyên của riêng tôi. Đúc thành một kiểu số có thể được thực hiện trong một char.

2010-01-30 11:39 (152) - Giảm đáng kể bằng cách sử dụng kết hợp regex trong switch. Hoàn toàn giải quyết các vấn đề phạm vi trước đó với việc truy cập ngăn xếp để bật nó.


5

Vợt 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)]))

Ngắt dòng tùy chọn.

Dựa trên giải pháp của Chris Jester-Young cho Đề án.


4

Con trăn, 166 ký tự

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]

Sử dụng raw_input()mã không được chia thành nhiều dòng.
JPvdMerwe

Sau đó, bạn có thể thử: from operator import*và thay thế o.divbằng 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])

Đầu vào: 5 1 1 - -7 0 * + - 2 /

Đầu ra: 2.5

(Bạn có thể tìm thấy phiên bản Python 2 128 ký tự trong lịch sử chỉnh sửa.)


Khá thông minh :) Tôi thích cách bạn không cần /trong chuỗi.
Daniel Lubarov


@EriktheOutgolfer ngắt với a ZeroDivisionErrorkhi toán hạng thứ hai bằng 0 (ví dụ 5 0 +).
flornquake

Bạn có thể lưu 1 ký tự bằng cách sử dụng ord(x) - 42phương thức.
frederick99

@ frederick99 Tôi không thấy thế nào.
flornquake

3

JavaScript (157)

Mã này giả sử có hai chức năng: readLine và 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])

Ngắn hơn nếu bạn sử dụng prompt()thay vì readLine()(và có lẽ alert()thay vì print()để khớp prompt()).
nyuszika7h

3

Perl, 128

Điều này không thực sự cạnh tranh bên cạnh câu trả lời Perl khác, nhưng khám phá một con đường khác (tối ưu).

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

Các ký tự được tính là khác với một perl -e ''lời mời đơn giản .


2

Con trăn, 161 ký tự:

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 ký tự

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

Mã này nên hoạt động với stdin, mặc dù nó không được thử nghiệm với stdin.

Nó đã được thử nghiệm trên tất cả các trường hợp, đầu ra (và mã) cho cái cuối cùng ở đây:
http://codepad.viper-7.com/fGbnv6

Ungolfed, 314 330 326 ký tự

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

Trích dẫn từ mô tả nhiệm vụ: »Đối với các ngôn ngữ mà không có chức năng tiếp nhận đầu vào / đầu ra lập trình, bạn có thể giả định các chức năng như readLine / in« - được trình diễn PHP. chức năng để làm như vậy, do đó giả định là không chính xác.
Joey

Cập nhật nó để sử dụng stdin và đánh gôn thêm một chút.
Kevin Brown

2

uốn cong - 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);
.
%%

Nếu bạn không quen, hãy biên dịch với flex rpn.l && gcc -lfl lex.yy.c


2

Con trăn, 130 ký tự

Sẽ là 124 ký tự nếu chúng ta bỏ b and(một số câu trả lời Python bị thiếu). Và nó kết hợp 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]

Câu trả lời thực sự tốt đẹp. Nhưng tôi đếm được 130 ký tự. ;)
flornquake

@flornquake bạn nói đúng, cảm ơn vì đã sửa.
Daniel Lubarov

2

Python 3, 126 132 ký tự

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

Đã có những giải pháp tốt hơn, nhưng bây giờ tôi đã viết nó (tất nhiên là chưa đọc các bài nộp trước đó - mặc dù tôi phải thừa nhận rằng mã của tôi trông như thể tôi đã sao chép chúng cùng nhau), tôi muốn chia sẻ nó, quá.


b/anên được thay thế bằng a and b/a, nếu không giải pháp này sẽ không hoạt động nếu toán hạng thứ hai bằng 0 (ví dụ 4 0 -).
flornquake

@flornquake Đã sửa nó cho anh.
mbomb007

2

c99 gcc 235

Điều này làm việc cho tôi (với cảnh báo):

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

Nhưng nếu bạn đang biên dịch nó với mingw32, bạn cần tắt tính năng toàn cầu (xem https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ) bằng cách biên dịch như thế này:

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

Nếu bạn không * được tự động mở rộng bởi CRT mingw32.

Có ai biết làm thế nào để biến break;case'*':s[--d]*=s[d+1];thành một macro chấp nhận ký tự + làm tham số không vì sau đó cả bốn trường hợp sẽ chỉ làO(+)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

Vui với đệ quy.

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

Ung dung:

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

Các trường hợp thử nghiệm:

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

Tôi đang gặp một lỗi với sự hiểu biết mảng nên tôi đã sử dụng .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)

Dùng thử trực tuyến tại ESFiddle


Có phiên dịch ES7 không?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ này sẽ hoạt động trên Firefox. Bạn có thể dùng thử babeljs.io/repl
Downgoat

Ồ, tôi hiểu rồi. ^ _ ^ Cảm ơn!
Conor O'Brien

1

PHP - 259 ký tự

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

Giả sử đầu vào trong biến POST i .


2
Trích dẫn từ mô tả ban đầu »Đối với các ngôn ngữ lập trình không có chức năng nhận đầu vào / đầu ra, bạn có thể đảm nhận các chức năng như readLine / print.« PHP có một cách để đưa stdin qua các luồng.
Kevin Brown

1

C # - 392 ký tự

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

Tuy nhiên, nếu các đối số có thể được sử dụng thay vì đầu vào tiêu chuẩn, chúng ta có thể đưa nó xuống

C # - 366 ký tự

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

Bạn có thể lưu 23 ký tự với một chút tối ưu hóa: 1. xóa thủ thuật không gian tên, đủ điều kiện rõ ràng hai loại cần nó. Bạn lưu từ khóa "không gian tên" và dấu ngoặc tương ứng. 2. Xóa khoảng trắng giữa chuỗi [] và i, từ khóa trường hợp và nhãn, chuyển đổi và parens của nó. 3. Loại bỏ float o và chỉ cần sử dụng toán học để có kết quả đúng (ví dụ: -k.Pop () + k.Pop () cho dấu trừ và 1 / k.Pop () * k.Pop () để chia .
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

Con trăn - 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())

Phiên bản bị đánh cắp:

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

Nhập từ đối số dòng lệnh; đầu ra trên đầu ra tiêu chuẩn.


1

ECMAScript 6 (131)

Chỉ cần gõ cùng nhau trong một vài giây, vì vậy nó có thể được đánh gôn xa hơn hoặc thậm chí có thể tiếp cận tốt hơn. Tôi có thể xem lại vào ngày mai:

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

Chỉnh sửa: Thay thế Stack bằng Array là cách ngắn hơn

Edit2: Đã thay thế ifs bằng biểu thức ternary


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

1

Con trăn 2

Tôi đã thử một số cách tiếp cận khác nhau cho những phương pháp được công bố cho đến nay. Không có cái nào trong số này ngắn như các giải pháp Python tốt nhất, nhưng chúng vẫn có thể thú vị với một số bạn.

Sử dụng đệ quy, 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]

Sử dụng thao tác danh sách, 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]

Sử dụng 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}

Ung dung:

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

Bạn có thể tiết kiệm thêm 2 byte bằng cách đặt mọi thứ vào một dòng (hoặc sử dụng trình soạn thảo văn bản chỉ sử dụng một ký tự cho dòng mới)
Hoki

@Hoki Tôi chỉ sử dụng các dòng mới khi không ngắt dòng sẽ yêu cầu a ;. Vì vậy, tôi nghĩ rằng số byte là như nhau
Luis Mendo

không chính xác, hầu hết các trình soạn thảo văn bản cửa sổ sử dụng cr+lfcho một dòng mới, có 2 ký tự. Sổ ghi chép của tôi ++ đã đếm được 230 ký tự trong phiên bản 3 dòng của bạn, nhưng chỉ 128 nếu tôi dán mọi thứ trong một dòng (đã xóa 2 * 2 = 4 ký tự khỏi 2 dòng mới và thêm hai ký tự ;). Hãy tự thử;)
Hoki

@Hoki Bạn nói đúng. Trên thực tế, nếu tôi dán phiên bản ba dòng trên Mothereff.in/byte-count (đó là những gì tôi đã sử dụng để đếm byte văn bản), nó sẽ cho 228. Và tất nhiên đó cũng là những gì tôi nhận được từ việc đưa tất cả vào một hàng. Tôi không biết tôi lấy số 230 từ đâu. Cảm ơn! Đã sửa
Luis Mendo

1

K5, 70 byte

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

Tôi không chắc chắn khi K5 được phát hành, vì vậy điều này có thể không được tính. Vẫn tuyệt vời!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.