50
\$\begingroup\$

You must evaluate a string written in Reverse Polish notation and output the result.

The program must accept an input and return the output. For programming languages that do not have functions to receive input/output, you can assume functions like readLine/print.

You are not allowed to use any kind of "eval" in the program.

Numbers and operators are separated by one or more spaces.

You must support at least the +, -, * and / operators.

You need to add support to negative numbers (for example, -4 is not the same thing as 0 4 -) and floating point numbers.

You can assume the input is valid and follows the rules above


Test Cases

Input:

-4 5 +

Output:

1

Input:

5 2 /

Output:

2.5

Input:

5 2.5 /

Output:

2

Input:

5 1 2 + 4 * 3 - +

Output:

14

Input:

4 2 5 * + 1 3 2 * + /

Output:

2
\$\endgroup\$
12
  • 10
    \$\begingroup\$ It's a shame no eval is allowed, otherwise the GolfScript solution is 1 character: ~. :-P \$\endgroup\$ Commented Jan 30, 2011 at 1:49
  • 7
    \$\begingroup\$ That's why it's not allowed :-P, this question on StackOverflow received a 4 chars answer with dc. \$\endgroup\$
    – user11
    Commented Jan 30, 2011 at 1:51
  • 1
    \$\begingroup\$ @SHiNKiROU: Which language requires you to use eval to parse numbers? It sounds quite broken. (GolfScript is one such language, as far as I'm aware. I think it's broken too.) \$\endgroup\$ Commented Jan 30, 2011 at 5:08
  • 4
    \$\begingroup\$ How is -4 not the same as 0 4 - ? \$\endgroup\$ Commented Jan 30, 2011 at 5:18
  • 1
    \$\begingroup\$ @Chris: Floating-point numbers are required as well, which rules out Golfscript too. And batch files. And Brainfuck. Unless you reimplement fp support in those which is probably not suitable for a golf task :-) \$\endgroup\$
    – Joey
    Commented Jan 30, 2011 at 9:44

48 Answers 48

16
\$\begingroup\$

Ruby - 95 77 characters

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

Takes input on stdin.

Testing code

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

gives

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

Unlike the C version this returns the last valid result if there are extra numbers appended to the input it seems.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ You could shave off a character by using map instead of each \$\endgroup\$
    – addison
    Commented Jun 21, 2015 at 2:31
12
\$\begingroup\$

Python - 124 chars

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 chars

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]
\$\endgroup\$
3
  • 1
    \$\begingroup\$ I like the stack manipulation. \$\endgroup\$
    – Alexandru
    Commented Jan 30, 2011 at 12:55
  • 2
    \$\begingroup\$ You can't have 0 as second operand... \$\endgroup\$
    – JBernardo
    Commented Dec 22, 2011 at 8:36
  • 2
    \$\begingroup\$ [a/b] should be replaced with b and[a/b] so that you can have 0 as second operand. \$\endgroup\$
    – flornquake
    Commented Apr 14, 2013 at 21:44
11
\$\begingroup\$

Scheme, 162 chars

(Line breaks added for clarity—all are optional.)

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

Fully-formatted (ungolfed) version:

(let loop ((stack '()))
  (let ((token (read)))
    (cond ((number? token) (loop `(,token ,@stack)))
          ((assq token `((+ ,+) (- ,-) (* ,*) (/ ,/)))
           => (lambda (ass) (loop `(,((cadr ass) (cadr stack) (car stack))
                                    ,@(cddr stack)))))
          (else (car stack)))))

Selected commentary

`(,foo ,@bar) is the same as (cons foo bar) (i.e., it (effectively) returns a new list with foo prepended to bar), except it's one character shorter if you compress all the spaces out.

Thus, you can read the iteration clauses as (loop (cons token stack)) and (loop (cons ((cadr ass) (cadr stack) (car stack)) (cddr stack))) if that's easier on your eyes.

`((+ ,+) (- ,-) (* ,*) (/ ,/)) creates an association list with the symbol + paired with the procedure +, and likewise with the other operators. Thus it's a simple symbol lookup table (bare words are (read) in as symbols, which is why no further processing on token is necessary). Association lists have O(n) lookup, and thus are only suitable for short lists, as is the case here. :-P

† This is not technically accurate, but, for non-Lisp programmers, it gets a right-enough idea across.

\$\endgroup\$
5
  • \$\begingroup\$ Can you read that? Seriously? \$\endgroup\$
    – user11
    Commented Jan 30, 2011 at 3:14
  • 1
    \$\begingroup\$ @M28: The ungolfed version, yes. I program in Scheme on a semi-regular basis (for real, serious programs). \$\endgroup\$ Commented Jan 30, 2011 at 3:16
  • \$\begingroup\$ Unfortunately, Scheme is a verbose language and notoriously difficult to golf well. So I wouldn't be surprised to see some Perl submission beat this one. \$\endgroup\$ Commented Jan 30, 2011 at 3:18
  • 7
    \$\begingroup\$ I like the four smileys in the golfed version. \$\endgroup\$
    – tomsmeding
    Commented Oct 28, 2013 at 7:34
  • 3
    \$\begingroup\$ lambda (ass) +1 for variable name choice :P \$\endgroup\$
    – Downgoat
    Commented Apr 24, 2016 at 2:50
8
\$\begingroup\$

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 is read from user input, output printed out).


Below is the code prettified and commented, it pretty much implements the postfix algorithm described (with the assumption that expressions are 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:

In the code above, we assume operators are always binary (+, -, *, /). We can generalize it by using nargin(f) to determine the number of arguments the operand/function requires, and pop the right amount of values from the stack accordingly, as in:

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

That way we can evaluate expressions like:

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

where mean_of_three is a user-defined function with three inputs:

function d = mean_of_three(a,b,c)
    d = (a+b+c)/3;
end
\$\endgroup\$
0
7
\$\begingroup\$

c -- 424 necessary character

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

Assumes that you have a new enough libc to include getdelim in stdio.h. The approach is straight ahead, the whole input is read into a buffer, then we tokenize with strsep and use length and initial character to determine the class of each. There is no protection against bad input. Feed it "+ - * / + - ...", and it will happily pop stuff off the memory "below" the stack until it seg faults. All non-operators are interpreted as floats by atof which means zero value if they don't look like numbers.

Readable and commented:

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

Validation:

 $ 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! Gotta quote anything with * in it...

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

and my own test case

 $ echo "12 8 3 * 6 / - 2 + -20.5 " | ./a.out
-20.500000
\$\endgroup\$
1
  • \$\begingroup\$ You can safe some characters by replacing case with a makro. \$\endgroup\$
    – FUZxxl
    Commented Jan 30, 2011 at 14:24
7
\$\begingroup\$

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
\$\endgroup\$
3
  • \$\begingroup\$ You can get remove 9 characters by changing "(s:_)![]=s" to "(s:_)![]=print s" and "main=getLine>>=putStrLn.show.([]!).words" to "main=getLine>>=([]!).words" \$\endgroup\$
    – Fors
    Commented Apr 19, 2013 at 16:25
  • \$\begingroup\$ And then further remove a few other characters by using a one-line case-statement. \$\endgroup\$
    – Fors
    Commented Apr 19, 2013 at 18:29
  • \$\begingroup\$ s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!v would save 14 characters. \$\endgroup\$
    – Fors
    Commented Apr 20, 2013 at 12:38
6
\$\begingroup\$

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

Next time, I'm going to use the recursive regexp thing.

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

I though F# is my only dream programming language...

\$\endgroup\$
1
  • \$\begingroup\$ I have a shorter Perl 5 implementation. \$\endgroup\$
    – dolmen
    Commented Jan 3, 2019 at 0:48
6
\$\begingroup\$

Windows PowerShell, 152 181 192

In readable form, because by now it's only two lines with no chance of breaking them up:

$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) – First attempt.

2010-01-30 11:09 (170) – Turning the function into a scriptblock solves the scope issues. Just makes each invocation two bytes longer.

2010-01-30 11:19 (188) – Didn't solve the scope issue, the test case just masked it. Removed the index from the final output and removed a superfluous line break, though. And changed double to float.

2010-01-30 11:19 (181) – Can't even remember my own advice. Casting to a numeric type can be done in a single char.

2010-01-30 11:39 (152) – Greatly reduced by using regex matching in the switch. Completely solves the previous scope issues with accessing the stack to pop it.

\$\endgroup\$
5
\$\begingroup\$

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

Line breaks optional.

Based on Chris Jester-Young's solution for Scheme.

\$\endgroup\$
4
\$\begingroup\$

Python, 166 characters

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]
\$\endgroup\$
2
  • \$\begingroup\$ Use raw_input() code isn't split over multiple lines. \$\endgroup\$
    – JPvdMerwe
    Commented Jan 30, 2011 at 6:23
  • \$\begingroup\$ Then you could try: from operator import* and replace o.div with div. \$\endgroup\$
    – JPvdMerwe
    Commented Jan 30, 2011 at 10:37
4
\$\begingroup\$

Python 3, 119 bytes

s=[]
for x in input().split():
 try:s+=float(x),
 except:o='-*+'.find(x);*s,a,b=s;s+=(a+b*~-o,a*b**o)[o%2],
print(s[0])

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

Output: 2.5

(You can find a 128-character Python 2 version in the edit history.)

\$\endgroup\$
10
  • \$\begingroup\$ Pretty clever :) I like how you don't need / in the string. \$\endgroup\$ Commented Oct 20, 2013 at 19:12
  • \$\begingroup\$ 114 bytes \$\endgroup\$ Commented Oct 26, 2017 at 18:46
  • \$\begingroup\$ @EriktheOutgolfer that breaks with a ZeroDivisionError when the second operand is 0 (e.g. 5 0 +). \$\endgroup\$
    – flornquake
    Commented Nov 1, 2017 at 16:54
  • \$\begingroup\$ You can save 1 character by using the ord(x) - 42 method. \$\endgroup\$ Commented May 26, 2019 at 4:54
  • \$\begingroup\$ @frederick99 I don't see how. \$\endgroup\$
    – flornquake
    Commented Jul 22, 2019 at 21:07
3
\$\begingroup\$

JavaScript (157)

This code assumes there are these two functions: readLine and 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])
\$\endgroup\$
1
  • \$\begingroup\$ Shorter if you use prompt() instead of readLine() (and perhaps alert() instead of print() to match prompt()). \$\endgroup\$
    – user344
    Commented Aug 21, 2014 at 19:00
3
\$\begingroup\$

Perl, 128

This isn't really competitive next to the other Perl answer, but explores a different (suboptimal) path.

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

Characters counted as diff to a simple perl -e '' invocation.

\$\endgroup\$
3
\$\begingroup\$

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

If you aren't familiar, compile with flex rpn.l && gcc -lfl lex.yy.c

\$\endgroup\$
2
\$\begingroup\$

Python, 161 characters:

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])
\$\endgroup\$
2
\$\begingroup\$

PHP, 439 265 263 262 244 240 characters

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

This code should work with stdin, though it is not tested with stdin.

It has been tested on all of the cases, the output (and code) for the last one is here:
http://codepad.viper-7.com/fGbnv6

Ungolfed, 314 330 326 characters

<?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];
\$\endgroup\$
2
  • \$\begingroup\$ Quote from the task description: »For programming languages that do not have functions to receive input/output, you can assume functions like readLine/print.« – demonstrably PHP has functions to do so, therefore the assumption is incorrect. \$\endgroup\$
    – Joey
    Commented Jan 30, 2011 at 10:11
  • \$\begingroup\$ Updated it to use stdin and golfed it a little more. \$\endgroup\$ Commented Jan 30, 2011 at 19:21
2
\$\begingroup\$

Python, 130 characters

Would be 124 characters if we dropped b and (which some of the Python answers are missing). And it incorporates 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]
\$\endgroup\$
2
  • \$\begingroup\$ Really nice answer. But I count 130 characters. ;) \$\endgroup\$
    – flornquake
    Commented Sep 15, 2014 at 10:02
  • \$\begingroup\$ @flornquake you're right, thanks for the correction. \$\endgroup\$ Commented Sep 15, 2014 at 19:44
2
\$\begingroup\$

Python 3, 126 132 chars

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

There have been better solutions already, but now that I had written it (without having read the prior submissions, of course - even though I have to admit that my code looks as if I had copypasted them together), I wanted to share it, too.

\$\endgroup\$
2
  • \$\begingroup\$ b/a should be replaced with a and b/a, otherwise this solution won't work if the second operand is 0 (e.g. 4 0 -). \$\endgroup\$
    – flornquake
    Commented Apr 20, 2013 at 10:51
  • \$\begingroup\$ @flornquake Fixed it for him. \$\endgroup\$
    – mbomb007
    Commented Jul 28, 2015 at 20:17
2
\$\begingroup\$

C, 232 229 bytes

Fun with recursion.

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

Test Cases:

$ ./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
\$\endgroup\$
2
\$\begingroup\$

JavaScript ES7, 119 bytes

I'm getting a bug with array comprehensions so I've used .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)

Try it online at ESFiddle

\$\endgroup\$
4
  • \$\begingroup\$ Is there an ES7 interpreter available? \$\endgroup\$ Commented Dec 3, 2015 at 18:12
  • \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ this should work on Firefox. You could try babeljs.io/repl \$\endgroup\$
    – Downgoat
    Commented Dec 3, 2015 at 18:28
  • \$\begingroup\$ Oh, I see. ^_^ Thanks! \$\endgroup\$ Commented Dec 3, 2015 at 18:36
  • \$\begingroup\$ Fail with input 0 \$\endgroup\$
    – l4m2
    Commented Dec 18, 2022 at 11:28
2
\$\begingroup\$

C 153

Sometimes a program can be made a bit shorter with more golfing and sometimes you just take completely the wrong route and the much better version is found by someone else.

Thanks to @ceilingcat for finding a much better (and shorter) version

double atof(),s[99],*p=s;y,z;main(c,v)char**v;{for(;--c;*p=z?z-2?~z?z-4?p+=2,atof(*v):*p/y:*p*y:*p-y:*p+y)z=1[*++v]?9:**v-43,y=*p--;printf("%f\n",s[1]);}

Try it online!

My original version:

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

If you are compiling it with mingw32 you need to turn off globbing (see https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html) by compiling like this:

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

If you don't * is automatically expanded by the mingw32 CRT into filenames.

\$\endgroup\$
3
  • \$\begingroup\$ @ceilingcat Your version is very different to mine (and a lot more impressive) - it is more like a whole new answer than a gold of mine. Are you sure you don't want to post it as a completely different answer? \$\endgroup\$ Commented Feb 6, 2020 at 21:01
  • \$\begingroup\$ @ceilingcat Thanks for all the golfs - I have actually learned a lot of tricks from your updates. \$\endgroup\$ Commented Feb 7, 2020 at 0:23
  • \$\begingroup\$ @ceilingcat Getting rid of the import is really clever. That would probably save bytes on the other ones too. \$\endgroup\$ Commented Mar 30, 2020 at 8:18
1
\$\begingroup\$

PHP - 259 characters

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

Assuming input in POST variable i.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Quoted from the original description »For programming languages that do not have functions to receive input/output, you can assume functions like readLine/print.« PHP has a way to get stdin through streams. \$\endgroup\$ Commented Jan 30, 2011 at 19:02
1
\$\begingroup\$

C# - 392 characters

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

However, if arguments can be used instead of standard input, we can bring it down to

C# - 366 characters

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());}}}
\$\endgroup\$
1
  • \$\begingroup\$ You can save 23 characters with a little optimization: 1. remove the namespace trick, explicitly qualify the two types that need it. You save the "namespace" keyword and corresponding brackets. 2. Remove spaces between string[] and i, case keywords and labels, switch and its parens. 3. Get rid of float o and simply use math to get the right results (ie. -k.Pop()+k.Pop() for minus, and 1/k.Pop()*k.Pop() for divide. \$\endgroup\$
    – MikeP
    Commented May 5, 2011 at 3:33
1
\$\begingroup\$

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))}
\$\endgroup\$
1
\$\begingroup\$

Python - 206

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

Ungolfed version:

# RPN

import sys

input = sys.argv[1].split()
stack = []

# Eval postfix notation
for tkn in input:
    if tkn == "+":
        stack.append(stack.pop() + stack.pop())
    elif tkn == "-":
        tmp = stack.pop()
        stack.append(stack.pop() - tmp)
    elif tkn == "*":
        stack.append(stack.pop() * stack.pop())
    elif tkn == "/":
        tmp = stack.pop()
        stack.append(stack.pop()/tmp)
    else:
        stack.append(float(tkn))

print(stack.pop())

Input from command-line argument; output on standard output.

\$\endgroup\$
1
\$\begingroup\$

ECMAScript 6 (131)

Just typed together in a few seconds, so it can probably be golfed further or maybe even approached better. I might revisit it tomorrow:

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())
\$\endgroup\$
1
\$\begingroup\$

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

Edit: Replacing the Stack with an Array is way shorter

Edit2: Replaced the ifs with a ternary expression

\$\endgroup\$
1
  • \$\begingroup\$ string[] i=>string[]i. \$\endgroup\$
    – Adalynn
    Commented Jul 27, 2017 at 18:06
1
\$\begingroup\$

Python 2

I've tried out some different approaches to the ones published so far. None of these is quite as short as the best Python solutions, but they might still be interesting to some of you.

Using recursion, 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]

Using list manipulation, 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]

Using 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]
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
4
  • \$\begingroup\$ You can save 2 more bytes by putting everything onto one line (or use a text editor which only uses one character for newline) \$\endgroup\$
    – Hoki
    Commented Jul 29, 2015 at 13:28
  • \$\begingroup\$ @Hoki I'm only using new lines when not breaking the line would require a ;. So I think the byte count is the same \$\endgroup\$
    – Luis Mendo
    Commented Jul 29, 2015 at 13:50
  • \$\begingroup\$ not exactly, most window text editors use cr+lf for a newline, which is 2 characters. My notepad++ counted 230 characters in your 3 lines version, but only 128 if I stick everything in one line (removed 2*2=4 characters from the 2 newlines, and added two ;). Try it yourself ;) \$\endgroup\$
    – Hoki
    Commented Jul 29, 2015 at 14:06
  • \$\begingroup\$ @Hoki You are right. In fact, if I paste the three-line version on mothereff.in/byte-counter (which is what I used for counting text bytes), it gives 228. And of course that's also what I get from putting it all in a single line. I don't know where I got the number 230 from. Thanks! Corrected \$\endgroup\$
    – Luis Mendo
    Commented Jul 29, 2015 at 14:29
1
\$\begingroup\$

K5, 70 bytes

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

I'm not sure when K5 was released, so this might not count. Still awesome!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.