역 폴란드 표기법


41

Reverse Polish 표기법으로 작성된 문자열을 평가 하고 결과를 출력해야합니다.

프로그램은 입력을 승인하고 출력을 리턴해야합니다. 입력 / 출력을 수신하는 기능이없는 프로그래밍 언어의 경우 readLine / print와 같은 기능을 가정 할 수 있습니다.

프로그램에서 "eval"을 사용할 수 없습니다.

숫자와 연산자는 하나 이상의 공백으로 구분됩니다 .

최소한 +,-, * 및 / 연산자를 지원해야합니다.

음수 (예 : -4와 동일하지 않음 0 4 -) 및 부동 소수점 숫자에 대한 지원을 추가해야 합니다.

입력이 유효하다고 가정하고 위의 규칙을 따릅니다.


테스트 사례

입력:

-4 5 +

산출:

1

입력:

5 2 /

산출:

2.5

입력:

5 2.5 /

산출:

2

입력:

5 1 2 + 4 * 3 - +

산출:

14

입력:

4 2 5 * + 1 3 2 * + /

산출:

2

8
평가가 허용되는 것은 부끄러운 일이 아니며, 그렇지 않으면 GolfScript 솔루션은 1 자 ~입니다. :-P
Chris Jester-Young

5
그것이 허용되지 않는 이유입니다 :-P, StackOverflow에 대한이 질문은 dc로 4 개의 문자 응답을 받았습니다.

1
@SHiNKiROU : eval숫자를 파싱 하기 위해 어떤 언어를 사용해야 합니까? 꽤 깨진 것 같습니다. (GolfScript는 내가 아는 한 그러한 언어 중 하나입니다. 나도 깨진 것 같습니다.)
Chris Jester-Young

3
-4는 0 4-와 어떻게 다릅니 까?
Keith Randall

1
문자열을 숫자로 변환하는 것이라면 eval은 괜찮을 것이라고 생각합니다. 예. 파이썬 eval(s)에서보다 낫다float(s)
gnibbler

답변:


15

루비 -95 77 자

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

stdin에 입력을받습니다.

테스트 코드

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

C 버전과 달리 입력에 추가 숫자가 추가되면 마지막 유효한 결과를 반환합니다.


1
각각 대신 맵을 사용하여 캐릭터를 면도 할 수 있습니다
addison

10

파이썬-124 자

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]

파이썬-133 자

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
나는 스택 조작을 좋아한다.
Alexandru

2
당신은 0두 번째 피연산자로 가질 수 없습니다 ...
JBernardo

2
[a/b]b and[a/b]두 번째 피연산자로 0을 가질 수 있도록 로 바꿔야 합니다.
flornquake

10

구성표, 162 자

명확성을 위해 추가 된 줄 바꿈은 모두 선택 사항입니다.

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

완전한 형식의 (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)))))

선택된 논평

`(,foo ,@bar)모든 공백을 압축하면 한 문자보다 짧아진다는 점을 제외하고 는 (cons foo bar)(즉, 효과적으로 foo앞에 새 목록을 반환 함 bar)과 동일합니다.

따라서, 당신은 반복 절을 읽을 수 (loop (cons token stack))(loop (cons ((cadr ass) (cadr stack) (car stack)) (cddr stack)))그 당신의 눈에 쉽게합니다.

`((+ ,+) (- ,-) (* ,*) (/ ,/))프로 시저 와 쌍을 이루는 심볼 + 과 함께 다른 연산자와 연관 목록을 작성합니다 . 따라서 간단한 기호 조회 테이블입니다 (맨손은 기호로 표시되므로 더 이상 처리 할 필요가 없습니다 ). 연결 목록에는 O (n) 조회가 있으므로 여기에서와 같이 짧은 목록에만 적합합니다. :-피 +(read)token

† 이것은 기술적으로 정확하지는 않지만 Lisp가 아닌 프로그래머에게는 올바른 아이디어를 얻습니다.


당신은 그것을 읽을 수 있습니까? 진심이야?

1
@ M28 : 언 골프 버전입니다. 나는 Scheme에서 반 정기적으로 (실제, 심각한 프로그램을 위해) 프로그램합니다.
Chris Jester-Young

불행하게도, Scheme은 장황한 언어이며 골프를 잘하기에는 악명 높습니다. 그래서 나는 Perl 제출이 이것을이기는 것을보고 놀라지 않을 것입니다.
Chris Jester-Young

7
나는 골프 버전에서 네 스마일을 좋아한다.
tomsmeding

2
lambda (ass)변수 이름 선택의 경우 +1 : P
Downgoat

7

c-424 필요한 캐릭터

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

getdelimstdio.h 에 포함시킬만큼 충분한 libc가 있다고 가정합니다 . 접근 방식은 곧바로 전체 입력을 버퍼로 읽은 다음 strsep길이와 초기 문자로 토큰 화 하고 사용하여 각 클래스를 결정합니다. 잘못된 입력에 대한 보호는 없습니다. "+-* / +-..."를 공급하면 결함을 세분화 할 때까지 스택 아래 "메모리"에서 메모리에있는 물건을 행복하게 튀어 나옵니다. 모든 비 연산자는 부동 소수점으로 해석되어 atof숫자처럼 보이지 않으면 0 값을 의미합니다.

읽고 주석을 달았습니다 :

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

확인, 검증:

 $ 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

응! 그 *안에 무엇이든 인용해야 합니다 ...

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

그리고 내 자신의 테스트 사례

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

case마크로 로 교체 하여 일부 캐릭터를 보호 할 수 있습니다 .
FUZxxl

7

하스켈 (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

"(s : _)! [] = s"를 "(s : _)! [] = print s"및 "main = getLine >> = putStrLn.show. ([]!로 변경하면 9자를 제거 할 수 있습니다. ) .words "에서"main = getLine >> = ([]!). words "
Fors

그리고 한 줄의 case-statement를 사용하여 몇 가지 다른 문자를 추가로 제거하십시오.
Fors

s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!v14자를 절약 할 수 있습니다.
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

(사용자 입력에서 입력을 읽고 출력을 출력합니다).


아래는 코드화되고 주석이 달린 코드이며 설명 된 접미사 알고리즘 (표현식이 유효한 것으로 가정)을 거의 구현합니다 .

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

보너스:

위의 코드에서 우리는 운영자가 항상 바이너리 가정 ( +, -, *, /). nargin(f)피연산자 / 함수에 필요한 인수의 수를 결정하기 위해 이를 사용하여 일반화 할 수 있으며 다음과 같이 스택에서 올바른 양의 값을 표시 할 수 있습니다.

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

그렇게하면 다음과 같은 표현식을 평가할 수 있습니다.

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

mean_of_three세 개의 입력을 가진 사용자 정의 함수는 어디에 있습니까?

function d = mean_of_three(a,b,c)
    d = (a+b+c)/3;
end

6

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

다음에는 재귀 정규 표현식을 사용하겠습니다.

언 골프 드 :

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

F #이 유일한 꿈의 프로그래밍 언어이지만 ...


Perl 5 구현이 더 짧습니다.
고인돌

6

Windows PowerShell을, (152) 181 (192)

읽을 수있는 형식으로되어 있기 때문에 지금은 두 줄로 나뉘어 질 가능성이 없습니다.

$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) – 첫 번째 시도.

2010-01-30 11:09 (170) – 함수를 스크립트 블록으로 바꾸면 범위 문제가 해결됩니다. 각 호출을 2 바이트 더 길게 만듭니다.

2010-01-30 11:19 (188) – 스코프 문제를 해결하지 못했지만 테스트 사례가이를 마스킹했습니다. 그러나 최종 출력에서 ​​색인을 제거하고 불필요한 줄 바꿈을 제거했습니다. 그리고 double을로 변경했습니다 float.

2010-01-30 11:19 (181) – 내 자신의 충고도 기억할 수 없습니다. 단일 문자로 숫자 유형으로 캐스트 할 수 있습니다.

2010-01-30 11:39 (152) –에서 정규식 일치를 사용하여 크게 줄어 듭니다 switch. 스택에 액세스하여 스택으로 접근하여 이전 범위 문제를 완전히 해결합니다.


5

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

줄 바꿈은 선택 사항입니다.

Chris Jester-Young의 Scheme 솔루션을 기반으로합니다.


4

파이썬, 166 자

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]

사용 raw_input()코드는 여러 줄로 나뉘 지 않습니다.
JPvdMerwe

그럼 당신은 시도 할 수 : from operator import*및 교체 o.div와 함께 div.
JPvdMerwe

4

파이썬 3, 119 바이트

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

입력: 5 1 1 - -7 0 * + - 2 /

산출: 2.5

편집 기록에서 128 자 Python 2 버전을 찾을 수 있습니다.


꽤 영리합니다 :) 나는 당신이 /문자열에 필요하지 않은 방법을 좋아합니다 .
Daniel Lubarov


ZeroDivisionError두 번째 피연산자가 0 일 때 @로 끝나는 @EriktheOutgolfer (예 :) 5 0 +.
flornquake

ord(x) - 42방법 을 사용하여 한 문자를 저장할 수 있습니다 .
frederick99

@ frederick99 어떻게 보지 못합니다.
flornquake

3

자바 스크립트 (157)

이 코드는 readLine과 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])

당신이 사용하는 경우 짧은 prompt()대신에 readLine()(아마 alert()대신 print()경기에 prompt()).
nyuszika7h

3

펄, 128

이것은 다른 Perl 답변 옆에 실제로 경쟁적이지는 않지만 다른 (최적) 경로를 탐색합니다.

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

문자는 간단한 perl -e ''호출의 차이로 계산 됩니다.


2

파이썬, 161 자 :

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 자

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

이 코드는 stdin으로 테스트되지는 않지만 stdin과 함께 작동해야합니다.

모든 경우에 대해 테스트되었으며 마지막 경우의 출력 및 코드는 다음과 같습니다.
http://codepad.viper-7.com/fGbnv6

Ungolfed, 314 (330) 326 자

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

작업 설명에서 인용 :»입력 / 출력을 수신하는 기능이없는 프로그래밍 언어의 경우 readLine / print와 같은 기능을 가정 할 수 있습니다.«– 명백히 PHP 에는 그렇게하는 기능이 있으므로 가정이 잘못되었습니다.
조이

stdin을 사용하도록 업데이트하고 조금 더 골프를 쳤습니다.
Kevin Brown

2

플렉스-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);
.
%%

익숙하지 않다면 flex rpn.l && gcc -lfl lex.yy.c


2

파이썬, 130 자

우리가 떨어 뜨리면 124자가 될 것입니다 b and(파이썬 답변 중 일부가 누락되었습니다). 그리고 그것은 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]

정말 좋은 답변입니다. 그러나 나는 130자를 셉니다. ;)
flornquake

@flornquake 당신이 맞아요, 수정 주셔서 감사합니다.
Daniel Lubarov

2

파이썬 3 126 개 132 문자

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

더 나은 해결책이 이미 있었지만 이제는 (이전의 제출물을 읽지 않고서도 코드를 복사하여 붙여 넣은 것처럼 보이는 것을 인정해야하지만) 작성 했으므로 공유하고 싶었습니다. 너무.


b/a로 대체해야합니다 a and b/a. 그렇지 않으면 두 번째 피연산자가 0 (예 :)이면이 솔루션이 작동하지 않습니다 4 0 -.
flornquake

@flornquake 그를 위해 고쳤다.
mbomb007

2

c99 gcc 235

이것은 (경고와 함께) 저에게 효과적입니다.

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

그러나 mingw32로 컴파일하는 경우 다음과 같이 컴파일하여 globbing을 비활성화해야합니다 ( https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ).

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

그렇지 않으면 *는 mingw32 CRT에 의해 자동으로 확장됩니다.

아무도 break;case'*':s[--d]*=s[d+1];문자 +를 매개 변수로 허용하는 매크로 로 바꾸는 방법을 알고 있습니까? 네 가지 경우 모두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 바이트

재귀와 재미.

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

언 골프 드 :

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

테스트 사례 :

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

자바 스크립트 ES7, 119 바이트

배열 이해력에 버그가 생겨서 사용했습니다. .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)

ESFiddle에서 온라인으로 사용해보십시오


ES7 통역사가 있습니까?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Firefox에서 작동합니다. babeljs.io/repl
Downgoat

아, 알겠습니다 ^ _ ^ 감사합니다!
Conor O'Brien

1

PHP-259 자

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

POST 변수 i에 입력이 있다고 가정합니다 .


2
원본 설명에서 인용»입력 / 출력을 수신하는 기능이없는 프로그래밍 언어의 경우 readLine / print와 같은 기능을 가정 할 수 있습니다.«PHP는 스트림을 통해 stdin을 얻는 방법이 있습니다.
Kevin Brown

1

C #-392 자

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

그러나 표준 입력 대신 인수를 사용할 수 있다면

C #-366 자

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

약간의 최적화로 23자를 저장할 수 있습니다. 1. 네임 스페이스 트릭을 제거하고 필요한 두 가지 유형을 명시 적으로 규정하십시오. "네임 스페이스"키워드와 해당 괄호를 저장합니다. 2. string []과 i, 케이스 키워드 및 레이블, 스위치 및 해당 구획 사이의 공백을 제거하십시오. 3. float o를 제거하고 간단히 math를 사용하여 올바른 결과를 얻습니다 (예 : -k.Pop () + k.Pop () 빼기, 1 / k.Pop () * k.Pop () 나누기 .
MikeP

1

스칼라 412 37649335312 :

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

파이썬-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())

언 골프 버전 :

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

명령 행 인수에서 입력; 표준 출력으로 출력.


1

ECMAScript 6 (131)

몇 초 안에 함께 입력하기 때문에 골프를 치고 골프를 칠 수 있습니다. 내일 다시 방문 할 수도 있습니다.

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

편집 : 스택을 배열로 교체하는 것이 훨씬 짧습니다.

편집 2 : if를 삼항 식으로 대체


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

1

파이썬 2

나는 지금까지 출판 된 방법에 대한 몇 가지 다른 접근법을 시도했습니다. 이 중 최고의 Python 솔루션만큼 짧은 것은 아니지만 여전히 일부 사용자에게는 흥미로울 수 있습니다.

재귀 사용, 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]

리스트 조작 사용하기, 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]

사용하기 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}

언 골프 드 :

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

모든 것을 한 줄에 넣음으로써 2 바이트를 더 절약 할 수 있습니다 (또는 개행에 한 문자 만 사용하는 텍스트 편집기 사용)
Hoki

@Hoki 줄을 끊지 않을 때 새 줄만 사용하고 ;있습니다. 바이트 수는 같다고 생각합니다
Luis Mendo

정확하게 말하면, 대부분의 창 텍스트 편집기 cr+lf는 개행 (2 자)에 사용합니다. 내 메모장 ++은 3 줄 버전에서 230 문자를 계산했지만 모든 줄을 한 줄에 넣으면 128 개만 사용합니다 (2 줄 바꿈에서 2 * 2 = 4 문자를 제거하고 두 개를 추가했습니다 ;). 직접 시도해보십시오.)
Hoki

@ 호키 당신이 맞아요. 사실, 내가 3 줄 버전을 mothereff.in/byte-counter (텍스트 바이트를 계산하는 데 사용 된 것) 에 붙여 넣으면 228이됩니다. 선. 230을 어디서 얻었는지 모르겠습니다. 감사! 수정
Luis Mendo

1

K5, 70 바이트

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

K5가 출시되었을 때이 그래서 나는 확실하지 않다 힘이 계산되지. 여전히 굉장합니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.