Skip to content

Instantly share code, notes, and snippets.

@peterjaric
Forked from 140bytes/LICENSE.txt
Created October 10, 2011 20:33
Show Gist options
  • Save peterjaric/1276436 to your computer and use it in GitHub Desktop.
Save peterjaric/1276436 to your computer and use it in GitHub Desktop.
RPN

RPN

Evaluates well-formed reverse polish notation expressions (http://en.wikipedia.org/wiki/Reverse_Polish_notation).

Input

Strings with tokens separated by single spaces. Tokens are operators or operands. Operators are +, -, * or /. Operands are integers or floats (e.g. 7, 3.23, -1e9).

Output

The value of the evaluated expression.

Examples

"1 1 +" -> 2

"5 8 -" -> -3

"2 3 7 + -" -> -8

"5 3 * 5 +" -> 20

function(a, // The input string
b) { // Placeholder var that will become the stack
return (b = [])[ // Create an empty stack, and later return its 0th element (*)
a.replace(/\S+/g, // For each token (everything that does not
// contain spaces) in the string,
function(c) { // inspect and act on it:
b.push( // Something will always be pushed to the stack:
+c || // If it is a number (an operand), push the number itself.
eval( // Else it is an operator.
b.pop(a = b.pop()) + // Pop the topmost element and save it in a.
// Then pop the next element and
c + // apply the operator together with the
a)) // previously saved element.
}),
0] // (*) After going through all tokens, index the 0th element
// of the stack. This is the result of the expression.
}
function(a,b){return(b=[])[a.replace(/\S+/g,function(c){b.push(+c==c?c:eval(b.pop(a=b.pop())+c+a))}),0]}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 YOUR_NAME_HERE <YOUR_URL_HERE>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "rpn",
"description": "Reverse Polish Notation expression evaluator",
"keywords": [
"expression",
"parser",
"rpn",
"evaluator"
]
}
<!DOCTYPE html>
<title>RPN</title>
<div>Expected value: <b>3, -4, -8, 14</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
// write a small example that shows off the API for your example
// and tests it in one fell swoop.
var myFunction = function(a,b){return(b=[])[a.replace(/\S+/g,function(c){b.push(+c==c?c:eval(b.pop(a=b.pop())+c+a))}),0]}
document.getElementById( "ret" ).innerHTML = [myFunction('1 2 +'), myFunction('2 6 -'), myFunction('2 3 7 + -'), myFunction('5 1 2 + 4 * + 3 -')].join(', ');
</script>
@peterjaric
Copy link
Author

Yay! @tobeytailor got it to just under tweet-size! Then @subzey cut it down/reimplemented it to 108 bytes! I'll be updating.

@tsaniel
Copy link

tsaniel commented Oct 11, 2011

Save some bytes.

function(a,b){return(b=[])[a.replace(/\S+/g,function(c){b.push(+c==c?c:eval(b.pop(a=b.pop())+c+a))}),0]}

@peterjaric
Copy link
Author

Great! I will update later. (Edit: done)

If 0 wasn't allowed as an operand, we could shorten it to

function(a,b){return(b=[])[a.replace(/\S+/g,function(c){b.push(+c||eval(b.pop(a=b.pop())+c+a))}),0]}

But it is...

@peterjaric
Copy link
Author

Using the ideas outlined above, the eval-less version now is under 140 bytes too (138 bytes):

function(a,b){return(b=[])[a.replace(/\S+/g,function(c,d){b.push(+c==c?+c:(d=b.pop(a=b.pop()),c=='+'?d+a:c=='-'?d-a:c=='*'?d*a:d/a))}),0]}

Thanks everyone.

@tsaniel
Copy link

tsaniel commented Oct 12, 2011

Save 2 bytes.

function(a,b){return(b=[])[a.replace(/\S+/g,function(c,d){b.push(+c==c?+c:{'+':(d=b.pop(a=b.pop()))+a,'-':d-a,'*':d*a,'/':d/a}[c])}),0]}

or this

function(a,b){return(b=[])[a.replace(/\S+/g,function(c,d){b.push(+c==c?+c:[(d=b.pop(a=b.pop()))+a,d-a,d*a,d/a]['+-*/'.indexOf(c)])}),0]}

@peterjaric
Copy link
Author

I'm learning something in every comment. Great work, @tsaniel!

@jimmywarting
Copy link

With ES6 you can

  • Lift d variable to the top so you can ignore one (, )
    With the use of => function you can also remove all return and make one liner by omitting {} that makes it return the first thing
(a,b,d)=>(b=[])[a.replace(/\S+/g,c=>b.push(+c==c?+c:{'+':(d=b.pop(a=b.pop()))+a,'-':d-a,'*':d*a,'/':d/a}[c])),0]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment