Last active
December 18, 2015 02:59
-
-
Save shukob/5715231 to your computer and use it in GitHub Desktop.
JS: Simple implementation of sum/sub, mult/divide calculation on input string.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var OperatorTokens = ['+','-','*','/']; //In priority ascending order | |
//class for a number | |
function Number(str){ | |
this.str = str;//string representation of the number | |
} | |
//parse and return as float | |
Number.prototype.to_f = function(){ | |
// alert(this.str); | |
return parseFloat(this.str); | |
} | |
//class for a tree node | |
function TreeNode(parent){ | |
this.parent = parent; | |
this.val = null;//operator of this node. | |
this.left = null;//left hand side of this node, eigher a number or a node. | |
this.right = null;//right hand side of this node, either a number or a node. | |
}; | |
//instance is a root node | |
TreeNode.prototype.isRoot = function(){ | |
return this.parent == null; | |
} | |
//instance does not have any operator | |
TreeNode.prototype.isEmpty = function(){ | |
return this.val == null; | |
} | |
//instance is a tree edge | |
TreeNode.prototype.isEdge = function(){ | |
return this.left == null && this.right == null; | |
} | |
//calculate a result for this node using those from all sub-nodes. | |
TreeNode.prototype.calc = function(){ | |
if(this.isEdge()){ | |
return this.val.to_f(); | |
}else{ | |
if(this.val=="+"){ | |
return this.left.calc() + this.right.calc(); | |
}else if(this.val=="-"){ | |
return this.left.calc() - this.right.calc(); | |
}else if(this.val=="*"){ | |
return this.left.calc() * this.right.calc(); | |
}else if(this.val=="/"){ | |
return this.left.calc() / this.right.calc(); | |
} | |
} | |
} | |
//construct an expression tree recursively. | |
function makeTree(root, tokens){ | |
// alert("input="+tokens); | |
var tokenParam = tokenize(tokens); | |
// alert("val="+tokenParam.val + " left="+tokenParam.left + " right="+tokenParam.right); | |
root.val = tokenParam.val; | |
if(!(tokenParam.right==null && tokenParam.left==null)){ | |
root.left = new TreeNode(root); | |
root.right = new TreeNode(root); | |
makeTree(root.left, tokenParam.left); | |
makeTree(root.right, tokenParam.right); | |
} | |
} | |
//separate characters in three parts, left hand side, operator and right hand side. | |
function tokenize(chars){ | |
var res=null; | |
if(chars[0]=='-'){ | |
chars[1]='-'+chars[1]; | |
chars.splice(0, 1); | |
} | |
for(var i = 0; i < OperatorTokens.length ; ++i){ | |
var index = chars.indexOf(OperatorTokens[i]); | |
if(index>0){ | |
res = {val: OperatorTokens[i], left: chars.slice(0, index), right: chars.slice(index+1, chars.length)}; | |
break; | |
} | |
} | |
if(res == null){ | |
res = {val: new Number(chars.join("")), left: null, right: null}; | |
} | |
return res; | |
} | |
//formalize the input so that we can easily construct an expression tree for it | |
function formalize(arg){ | |
//Bubble extracting minus sign in mult/devide operations (first argument with no sign) | |
while(arg.search(/^(((\d+)([\*\/]))+)-/)>=0){ | |
arg = arg.replace(/^(((\d+)([\*\/]))+)-/, "-$1"); | |
} | |
//Bubble extracting minus sign in mult/divide operations (other arguments) | |
while(arg.search(/([-\+]((\d+)([\*\/]))+)-/)>=0){ | |
arg = arg.replace(/([-\+]((\d+)([\*\/]))+)-/, "-$1"); | |
} | |
var index = -1; | |
//Summerizing contiguous signs | |
while((index =arg.search(/[\+-]{2,}/))>=0){ | |
// alert("arg:" + arg); | |
var last; | |
var minuses = 0; | |
for(last = index ; last < arg.length ; ++last){ | |
if(arg[last]=='-'){ | |
minuses+=1; | |
} | |
if(arg[last]!="-" && arg[last]!="+"){ | |
break; | |
} | |
} | |
var left = arg.substring(0, index); | |
var right = arg.substring(last, arg.length); | |
var sign = (minuses%2==1) ? '-' : '+'; | |
// alert("left:" + left + " right:" + right + " sign:" +sign); | |
//if left is blank, this position is the begining of the string | |
if(left==""){ | |
//therefor we dismiss the trailing plus | |
if(sign == "+"){ | |
arg = right; | |
}else{ | |
arg = sign + right; | |
} | |
}else{ | |
arg = left + sign + right; | |
} | |
} | |
return arg; | |
} | |
//main function | |
function solve(arg){ | |
var arg = formalize(arg) | |
var splitted = arg.match(/\d+|./g); | |
var root = new TreeNode(null); | |
makeTree(root, splitted); | |
return root.calc(); | |
} | |
return solve(arg); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment