Skip to content

Instantly share code, notes, and snippets.

@shukob
Last active December 18, 2015 02:59
Show Gist options
  • Save shukob/5715231 to your computer and use it in GitHub Desktop.
Save shukob/5715231 to your computer and use it in GitHub Desktop.
JS: Simple implementation of sum/sub, mult/divide calculation on input string.
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