Addition of number string in javascript with leading zeros - javascript

Following is my code, which is working fine in most scenarios except in case of leading Zeros. It should preserve trailing zeros like -001 + 1 = 002
Code -
function incrementString (str) {
if(str === '') return "1";
if(!str.slice(-1).match(/\d/)) return `${str}1`;
const replacer = x => {
// Check if number
return (parseInt(x) + 1).toString();
}
return str.replace(/\d+/g, replacer )
}
// Return foobar2 which is correct
console.log(incrementString("foobar1"))
// Return foobar100 which is correct
console.log(incrementString("foobar099"))
// Return foobar2 which is incorrect, is should be foobar002
console.log(incrementString("foobar001"))
// Return foobar1 which is incorrect, is should be foobar001
console.log(incrementString("foobar000"))
// Return foobar101 which is incorrect, is should be foobar0101
console.log(incrementString("foobar0100"))

You may use this regex soluton:
function incrementString (str) {
if(str === '') return "1";
if(!str.slice(-1).match(/\d/)) return `${str}1`;
const replacer = (m, g1, g2) => {
// Check if number
var nn = (g1?g1:"") + (parseInt(g2) + 1).toString()
return nn.slice(-1 * m.length)
}
return str.replace(/(0*)(\d+)/g, replacer )
}
// Return foobar2
console.log(incrementString("foobar1"))
// Return foobar100
console.log(incrementString("foobar099"))
// Return foobar002
console.log(incrementString("foobar001"))
// Return foobar001
console.log(incrementString("foobar000"))
// Return foobar0101
console.log(incrementString("foobar0100"))
// Return foobar01000
console.log(incrementString("foobar00999"))
// Return foobar010
console.log(incrementString("foobar009"))

Everything seems to be perfect, you need to only handle the regex part of the leading zeroes in your replacer function.Below is the updated code for the same.
function incrementString(str) {
if (str === '')
return "1";
if (!str.slice(-1).match(/\d/)) {
return `${str}1`;
}
const replacer = x => {
var leadingZerosMatched = x.match(/^0+/);
var incrementedNumber = (parseInt(x) + 1).toString();
var leadingZeroes;
if (leadingZerosMatched && incrementedNumber.length < x.length) {
leadingZeroes = leadingZerosMatched[0];
if(leadingZeroes.length === x.length) {
leadingZeroes = leadingZeroes.slice(0, leadingZeroes.length-1)
}
}
return leadingZeroes ? leadingZeroes + incrementedNumber : incrementedNumber;
}
return str.replace(/\d+/g, replacer)
}

You could split your string from digits and use padStart after increment to preserve leading 0:
const incrementString = (str) => {
const [chars, nums] = str.split(/(\d+)/)
return [
...chars,
String(Number(nums) + 1)
.padStart(nums.length, '0')
].join('')
}
console.log(incrementString("foobar1"))
console.log(incrementString("foobar099"))
console.log(incrementString("foobar001"))
console.log(incrementString("foobar000"))
console.log(incrementString("foobar0100"))

function incrementString (str) {
let [
openingPartial,
terminatingInt
] = str.split(/(\d*)$/);
if (terminatingInt) {
const incrementedInt = String(parseInt(terminatingInt, 10) + 1);
const leadingZeroCount = (terminatingInt.length - incrementedInt.length);
if (leadingZeroCount >= 1) {
terminatingInt = Array(leadingZeroCount).fill("0").concat(incrementedInt).join('');
} else {
terminatingInt = incrementedInt;
}
} else {
terminatingInt = '1';
}
return `${ (openingPartial || '') }${ terminatingInt }`;
}
// Should return 'foo_003_bar1'.
console.log(incrementString("foo_003_bar"));
// Should return 'foo_003_bar_01'.
console.log(incrementString("foo_003_bar_00"));
// Should return 'foobar1'.
console.log(incrementString("foobar"));
// Should return 'foobar2'.
console.log(incrementString("foobar1"));
// Should return 'foobar100'.
console.log(incrementString("foobar099"));
// Should return 'foobar002'.
console.log(incrementString("foobar001"));
// Should return 'foobar001'.
console.log(incrementString("foobar000"));
// Should return 'foobar0101'.
console.log(incrementString("foobar0100"));
.as-console-wrapper { max-height: 100%!important; top: 0; }

Related

Convert array to pipe separated

How to convert array EX-["lat","long","abc","def","abcc","deef",]
into [lat,long | abc,def | abcc,deef] in javascript.
I am facing issue with distance matrix Api...
Below is my code
export async function getStoreDistance(locationDetails) {
destinationRequest = [];
let destinationRequest = locationDetails.destinations.map(location => {
console.log('destreqlocation', location);
return `${location.lat},${location.long} `;
});
return await axios
.get(
`https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial
&origins=${locationDetails.origins.map(function(locationDetail) {
return locationDetail;
})}
&destinations=${destinationRequest}&key=**********`,
)
.then(function(response) {
// handle success
// return response;
})
.catch(function(error) {
// handle error
return error;
});
}
My solution to the problem.
const so1 = ["lat","long","abc","def","abcc","deef"]
let result = so1
.map((item, id, array) => ((id % 2) !== 0 && id !== (array.length - 1)) ? item + '|' : (id !== (array.length - 1)) ? item + '&' : item)
.join('')
.replace(/&/g, ',')
console.log( result )
console.log( `[${result}]` )
Try something like below
input = ["lat", "long", "abc", "def", "abcc", "deef"];
const [lat, long, ...rest] = input;
res = rest.reduce((acc, val, index) => {
if(index % 2 === 0) acc.push([]);
acc[acc.length -1].push(val);
return acc;
}, []);
resFinal = [[lat, long], ...res];
console.log(resFinal);
resFinalStr = resFinal.reduce((acc, val, index)=> {
if(index !== resFinal.length -1){
acc+=(val.join(",")) + "|";
}else{
acc += val.join(",")
}
return acc;
}, "")
console.log(resFinalStr)
console.log(`[${resFinalStr}]`)
An old-fashioned for loop should do the job fine:
function getStoreDistance(locationDetails) {
destinationRequest = locationDetails[0] || "";
for (let i = 1; i < locationDetails.length; i++) {
destinationRequest += (i % 2 ? "," : " | ") + locationDetails[i];
}
return destinationRequest;
}
// Demo
let response = ["lat","long","abc","def","abcc","deef"];
console.log(getStoreDistance(response));

Expansion of algebraic term

I am trying to expand an algebraic term.
(x+1)(x+1)/x => x + 2 + x^-1
(x+1)^3 => x^3 + 3x^2 + 3x + 1
(x^2*x)(x^2) => x^5
This is my attempt at it. I have tried a lot of ways trying to fix the problems below.
Problems:
Like terms should be added together
(x+1)(x+1)(x+1) should be valid.
(x+1)^2 should be equal to (x+1)(x+1)
x(x+1) should be valid
1x^n should just be x^n
There should be no 0x^n terms.
nx^0 terms should just be n
Code Snippet:
function split(input) {
return ((((input.split(")(")).toString()).replace(/\)/g, "")).replace(/\(/g, "")).split(','); }
function strVali(str) {
str = str.replace(/\s+/g, "");
var parts = str.match(/[+\-]?[^+\-]+/g);
// accumulate the results
return parts.reduce(function(res, part) {
var coef = parseFloat(part) || +(part[0] + "1") || 1;
var x = part.indexOf('x');
var power = x === -1 ?
0:
part[x + 1] === "^" ?
+part.slice(x + 2) :
1;
res[power] = (res[power] || 0) + coef;
return res;
}, {});
}
function getCoeff(coeff) {
var powers = Object.keys(strVali(coeff));
var max = Math.max.apply(null, powers);
var result = [];
for(var i = max; i >= 0; i--)
result.push(strVali(coeff)[i] || 0);
return result; }
function evaluate(expression) {
var term1 = getCoeff(expression[0]);
var term2 = getCoeff(expression[1]);
var expand = "";
for ( var j = 0; j < term1.length; j++ ) {
for ( var i = 0; i < term2.length; i++ ) {
expand += Number(term1[j] * term2[i]) + 'x^ ' + (Number(term1.length) - 1 - j + Number(term2.length) - 1 - i) + ' + ';
}}
var final = "";
for ( var Z = 0; Z < getCoeff(expand).length; Z++) {
final += ' ' + getCoeff(expand)[Z] + 'x^ {' + (getCoeff(expand).length - Z - 1) + '} +';
}
final = "$$" + ((((((final.replace(/\+[^\d]0x\^ \{[\d]+\}/g,'')).replace(/x\^ \{0}/g,'')).replace(/x\^ \{1}/g,'x')).replace(/[^\d]1x\^ /g,'+ x^')).replace(/\+ -/g,' - ')).slice(0, -1)).substring(1,(final.length)) + "$$";
document.getElementById('result').innerHTML = final;
MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]);
}
function caller() {
var input = document.getElementById('input').value;
evaluate(split(input)); }
div.wrapper {
width: 100%;
height:100%;
border:0px solid black;
}
input[type="text"] {
display: block;
margin : 0 auto;
padding: 10px;
font-size:20px;
}
button{
margin:auto;
display:block;
background-color: white;
color: black;
border: 2px solid #555555;
padding-left: 20px;
padding-right: 20px;
font-size: 20px;
margin-top:10px;
}
button:hover {
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19);
}
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<div class='wrapper'><input id="input" title="Enter Expression" type="text" value="(x^2+x+1)(x^2+x+1)"></div>
<div> <button onclick="caller()">Click</button></div>
<div id="result">$$x^4 + 2x^3 + 3x^2 + 2x + 1$$</div>
Reference:
How to calculate coefficients of polynomial expansion in javascript
Getting coefficients of algebraic term
How to get a term before a character?
Edit: I have re-written my original answer from when the question did not include the - and / operators). My new answer supports - and /.
Since you have not defined a precise grammar, I have made some assumptions. I support the +, -, /, ^ operators and the implicit multiply. These can operate on numbers, x and (...) expressions, except that right hand side of the ^ operator must be a number. I allow spaces between tokens.
Limitations: The -is a binary not unary - operator, So x-2 if OK, -2 on its own is a syntax error. The / is limited. You may divide by a value with a single coefficient such as 2, 'x', 2x^2, but not by cannot have 1/(x^2+1), which would evaluate to an infinite series.
It first takes the string and wraps it in a 'tokenizer' which lets you look it one token at a time, where a token is a number, x, ( ) or operator.
It then calls evaluateSum() which evaluates things separated by + or -, where each thing is a product evaluated by evaluateProduct(). This in turn uses evaluatePower() to evalue the ^. Finally evaluateTerm() looks for x, numbers and bracketed sub-expressions which are evaluates recursively with evaluateSum(). This hierarchy creates the correct operator precedence and evaluation order.
Each layer of the evaluation returns a 'coefficients' object which s array-like, but may contain megative indexes. For example [1,0,1] means 1+x^2.
It can cope with any number of nested brackets and a lot of other case such as xx(x) is x^3, 2^3 is 8. I have added a few throws for syntax errors, for example 2^x is illegal.
function makeTokenizer(source) {
var c, i, tokenizer;
i = 0; // The index of the current character.
c = source.charAt(i); // The current character.
function consumeChar() { // Move to next c, return previous c.
var prevC = c;
i += 1;
c = source.charAt(i);
return prevC;
}
tokenizer = {
next : function () {
var str;
while (c === ' ') { // Skip spaces
consumeChar();
}
if (!c) {
tokenizer.token = undefined; // End of source
} else if (c >= '0' && c <= '9') { // number
str = consumeChar(); // First digit
while (c >= '0' && c <= '9') { // Look for more digits.
str += consumeChar();
}
tokenizer.token = Number(str);
} else if (c === "x") {
tokenizer.token = consumeChar();
} else { // single-character operator
tokenizer.token = consumeChar();
}
}
};
tokenizer.next(); // Load first token.
return tokenizer;
}
function makeCoefficients() { // Make like an array but can have -ve indexes
var min = 0, max = 0, c = {};
return {
get: function (i) {
return c[i] || 0;
},
set: function (i, value) {
c[i] = value;
min = Math.min(i, min);
max = Math.max(i + 1, max);
return this; // for chaining
},
forEach: function (callback) {
var i;
for (i = min; i < max; i += 1) {
if (this.get(i)) {
callback(this.get(i), i);
}
}
},
toString: function () {
var result = "", first = true;
this.forEach(function (val, power) {
result += (val < 0 || first) ? "" : "+";
first = false;
result += (val === 1 && power !== 0) ? "" : val;
if (power) {
result += "x";
if (power !== 1) {
result += "^" + power;
}
}
});
return result;
},
toPowerOf: function (power) {
if (power === 0) {
return makeCoefficients().set(0, 1); // Anything ^0 = 1
}
if (power === 1) {
return this;
}
if (power < 0) {
throw "cannot raise to negative powers";
}
return this.multiply(this.toPowerOf(power - 1));
},
multiply: function (coefficients) {
var result = makeCoefficients();
this.forEach(function (a, i) {
coefficients.forEach(function (b, j) {
result.set(i + j, result.get(i + j) + a * b);
});
});
return result;
},
divide: function (coefficients) {
// Division is hard, for example we cannot do infinite series like:
// 1/(1 + x^2) = sum_(n=0 to infinity) 1/2 x^n ((-i)^n + i^n)
// So we do a few easy cases only.
var that = this, result = makeCoefficients(), done;
coefficients.forEach(function (value, pow) {
that.forEach(function (value2, pow2) {
result.set(pow2 - pow, value2 / value);
});
if (done) {
throw "cannot divide by " + coefficients.toString();
}
done = true;
});
return result;
},
add: function (coefficients, op) {
var result = makeCoefficients();
this.forEach(function (value, i) {
result.set(value, i);
});
op = (op === "-" ? -1 : 1);
coefficients.forEach(function (value, i) {
result.set(i, result.get(i) + value * op);
});
return result;
}
};
}
var evaluateSum; // Called recursively
function evaluateTerm(tokenizer) {
var result;
if (tokenizer.token === "(") {
tokenizer.next();
result = evaluateSum(tokenizer);
if (tokenizer.token !== ")") {
throw ") missing";
}
tokenizer.next();
} else if (typeof tokenizer.token === "number") {
result = makeCoefficients().set(0, tokenizer.token);
tokenizer.next();
} else if (tokenizer.token === "x") {
tokenizer.next();
result = makeCoefficients().set(1, 1); // x^1
} else {
return false; // Not a 'term'
}
return result;
}
function evaluatePower(tokenizer) {
var result;
result = evaluateTerm(tokenizer);
if (tokenizer.token === "^") {
tokenizer.next();
if (typeof tokenizer.token !== "number") {
throw "number expected after ^";
}
result = result.toPowerOf(tokenizer.token);
tokenizer.next();
}
return result;
}
function evaluateProduct(tokenizer) {
var result, term, divOp;
result = evaluatePower(tokenizer);
if (!result) {
throw "Term not found";
}
while (true) {
divOp = (tokenizer.token === "/");
if (divOp) {
tokenizer.next();
term = evaluatePower(tokenizer);
result = result.divide(term);
} else {
term = evaluatePower(tokenizer);
if (!term) {
break;
}
result = result.multiply(term);
}
}
return result;
}
function evaluateSum(tokenizer) {
var result, op;
result = evaluateProduct(tokenizer);
while (tokenizer.token === "+" || tokenizer.token === "-") {
op = tokenizer.token;
tokenizer.next();
result = result.add(evaluateProduct(tokenizer), op);
}
return result;
}
function evaluate(source) {
var tokenizer = makeTokenizer(source),
coefficients = evaluateSum(tokenizer);
if (tokenizer.token) {
throw "Unexpected token " + tokenizer.token;
}
console.log(source + " => " + coefficients.toString());
}
// Examples:
evaluate("(x+1)(x+1)"); // => 1+2x+x^2
evaluate("(x+1)^2"); // => 1+2x+x^2
evaluate("(x+1)(x+1)(x+1)"); // => 1+3x+3x^2+x^3
evaluate("(x+1)^3"); // => 1+3x+3x^2+x^3
evaluate("(x)(x+1)"); // => x+x^2
evaluate("(x+1)(x)"); // => x+x^2
evaluate("3x^0"); // => 3
evaluate("2^3"); // => 8
evaluate("(x+2x(x+2(x+1)x))"); // => x+6x^2+4x^3
evaluate("(x+1)(x-1)"); // => -1+x^2
evaluate("(x+1)(x+1)/x"); // x^-1+2+x
//evaluate("(x+1)/(x^2 + 1)"); //throws cannot divide by 1+2x
It can handle +, -, / and implicit multiplication. It expands the parenthesis accordingly and adds them to the original expression while removing the parenthesised version. It collects like terms accordingly. Limitations: It cannot divide by a polynomial and it does not support the * operator.
function strVali(str) {
str = str.replace(/\s+/g, "");
var parts = str.match(/[+\-]?[^+\-]+/g);
return parts.reduce(function(res, part) {
var coef = parseFloat(part) || +(part[0] + "1") || 1;
var x = part.indexOf('x');
var power = x === -1 ?
0:
part[x + 1] === "^" ?
+part.slice(x + 2) :
1;
res[power] = (res[power] || 0) + coef;
return res;
}, {});
}
function getCoeff(coeff) {
var powers = Object.keys(strVali(coeff));
var max = Math.max.apply(null, powers);
var result = [];
for(var i = max; i >= 0; i--)
result.push(strVali(coeff)[i] || 0);
return result; }
function format(str) {
str = ' ' + str;
str = str.replace(/-/g,'+-').replace(/x(?!\^)/g,'x^1').replace(/([+\/*)(])(\d+)([+\/*)(])/g,'$1$2x^0$3').replace(/([^\d])(x\^-?\d+)/g,'$11$2').replace(/(-?\d+x\^\d+)(?=\()/g,'($1)').replace(/(\))(-?\d+x\^\d+)/g,'$1($2)').replace(/([^\)\/])(\()([^\*\/\(\)]+?)(\))(?![(^\/])/g,'$1$3');
str = str.replace(/(\([^\(\)]+?\))\/(\d+x\^-?\d+)/g,'$1/($2)').replace(/(\d+x\^-?\d+)\/(\d+x\^-?\d+)/g,'($1)/($2)').replace(/(\d+x\^-?\d+)\/(\(\d+x\^-?\d+\))/g,'($1)/$2');
return str;
}
function expBrackets(str) {
var repeats = str.match(/\([^\(\)]+?\)\^\d+/g);
if ( repeats === null ) { return str; } else { var totalRepeat = '';
for ( var t = 0; t < repeats.length; t++ ) { var repeat = repeats[t].match(/\d+$/); for ( var u = 0; u < Number(repeat); u++ ) { totalRepeat += repeats[t].replace(/\^\d+$/,''); }
str = str.replace(/\([^\(\)]+?\)\^\d+/, totalRepeat); totalRepeat = ''; }
return str; }
}
function multiply(str) {
var pairs = str.match(/\([^\(\)]+?\)\([^\(\)]+?\)/g);
if ( pairs !== null ) { while ( pairs !== null ) { var output = '';
for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].slice(1).slice(0, -1).split(')('); var firstCoeff = getCoeff(pair[0]); var secondCoeff = getCoeff(pair[1]);
for (var j = 0; j < firstCoeff.length; j++) {
for (var k = 0; k < secondCoeff.length; k++) { output += firstCoeff[j] * secondCoeff[k] + 'x^' + Number(firstCoeff.length - 1 - j + secondCoeff.length - 1 - k) + '+'; } }
var regexp = new RegExp(pairs[i].replace(/\(/g,'\\(').replace(/\+/g,'\\+').replace(/\)/g,'\\)').replace(/\^/g,'\\^').replace(/\-/g,'\\-'));
str = str.replace(regexp, '(' + (output.slice(0, -1).replace(/[^\d]0x\^\d+/g,'')) + ')');
output = ''; }
pairs = str.match(/\([^\(\)]+?\)\([^\(\)]+?\)/g); } }
else { }
str = str.replace(/\+/g,' + ');
return str;
}
function divide(str) {
if ( str.match(/\/(\(-?\d+x\^-?\d+.+?\))/g) === null && str.match(/\//g) !== null ) {
while ( pairs !== null ) {
var pairs = str.match(/\([^\(\)]+?\)\/\([^\(\)]+?\)/g);
var output = '';
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].slice(1).slice(0, -1).split(')/(');
var firstCoeff = getCoeff(pair[0]);
var secondCoeff = getCoeff(pair[1]);
for (var j = 0; j < firstCoeff.length; j++) {
for (var k = 0; k < secondCoeff.length; k++) {
output += firstCoeff[j] / secondCoeff[k] + 'x^' + Number(firstCoeff.length - 1 - j - secondCoeff.length + 1 + k) + '+';
output = output.replace(/([+-])Infinityx\^\-?\d+/g,'').replace(/([+-])NaNx\^\-?\d+/g,'');
} }
var regexp = new RegExp(pairs[i].replace(/\(/g,'\\(').replace(/\+/g,'\\+').replace(/\)/g,'\\)').replace(/\^/g,'\\^').replace(/\-/g,'\\-'));
str = str.replace(regexp, '(' + (output.slice(0, -1).replace(/[^\d]0x\^-?\d+/g,'')) + ')');
output = ''; }
pairs = str.match(/\([^\(\)]+?\)\/\([^\(\)]+?\)/g); } }
else { }
return str;
}
function evaluate(str) {
var result = format(divide(format(multiply(expBrackets(format((str)))))));
var resultCollect = '';
result = result.replace(/\s+/g, "").replace(/[^\d]0x\^-?\d+/g,'').replace(/\+/g,' + ');
if ( result === '') {
document.getElementById('result').innerHTML = '$$' + str + '$$' + '$$ = 0 $$';
MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]);
} else if ( result.match(/-?\d+x\^-\d+/g) === null && str.match(/\/(\(-?\d+x\^-?\d+.+?\))/g) === null) {
for ( var i = 0; i < getCoeff(result).length; i++ ) {
resultCollect += getCoeff(result)[i] + 'x^' + Number(getCoeff(result).length - 1 - i) + '+' ; }
if ( resultCollect !== '')
resultCollect = '$$ = ' + resultCollect.slice(0,-1).replace(/[^\d]0x\^-?\d+/g,'').replace(/\+/g,' + ').replace(/x\^0/g,'').replace(/x\^1(?!\d+)/g,'x').replace(/\^(-?\d+)/g,'\^\{$1\}').replace(/\+ -/g,' - ') + '$$';
else
resultCollect = 'Error: Trying to divide by a polynomial ';
document.getElementById('result').innerHTML = '$$' + str.replace(/\^(-?\d+)/g,'\^\{$1\}') + '$$' + resultCollect;
MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]);
} else {
resultCollect = '$$ = ' + result.replace(/\^(-?\d+)/g,'\^\{$1\}') + '$$';
document.getElementById('result').innerHTML = '$$' + str.replace(/\^(-?\d+)/g,'\^\{$1\}').replace(/\+ -/g,' - ') + '$$' + resultCollect;
MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]);
}
}
function caller() {
var input = document.getElementById('input').value;
evaluate(input);
}
div.wrapper {
width: 100%;
height:100%;
border:0 solid black;
}
input[type="text"] {
display: block;
margin : 0 auto;
padding: 10px;
font-size:20px;
}
button{
margin:auto;
display:block;
background-color: white;
color: black;
border: 2px solid #555555;
padding-left: 20px;
padding-right: 20px;
font-size: 20px;
margin-top:10px;
}
button:hover {
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19);
}
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<input id="input" type="text" title="Enter Expression: ">
<button onclick="caller()">Click</button>
<div id="result"></div>
<div id="errors"></div>
My approach utilizes two helper classes:
-Term: This stores a coefficient and an object, the keys of which are variables and the values of which are the exponents. It has methods for determining whether terms are the "same" (i.e. whether they have the same variables with the same exponents, thus allowing them to be added), adding terms, and multiplying terms.
-Polynomial: This stores an array of terms. It has methods for adding two polynomials, multiplying two polynomials, and simplifying polynomials (eliminating terms with 0 coefficients and combining like terms).
It has two substantial helper functions:
-findOuterParens - Given a string, this function returns the indices of the first outermost pair of left and right parentheses.
-parseExpressionStr - This function uses a regular expression to split a string into three types of substrings: 1) a number, 2) a symbol (i.e. a variable, like 'x' or 'y'), or 3) an operator (*, -, +, ^, /). It creates Polynomial objects for the first two types and leaves the operators as strings.
The expand function runs the show. It takes in a string and returns a Polynomial object representing the expanded form of the polynomial in the string. It does this as follows:
1) It deals with parentheses by recursion. It uses findOuterParens to find all outermost parenthsized substrings. So for "3x*(x+4)+(2(y+1))*t", for instance, it would find "x+4" and "2(y+1)" as parenthsized substrings. It then passes these to itself for further parsing. For "2(y+1)", it would identify "y+1" as a parenthesized substring, and pass this to itself, for three levels of recursion for this example.
2) It deals with other parts of the string using parseExpressionStr. After steps 1 and 2, it has an array containing Polynomial objects and operators (stored as strings). It then proceeds to simplifying and expanding.
3) It converts subtraction subproblems to addition subproblems by replacing all -'s with +'s and multiplying all polynomials following -'s by -1.
4) It converts division subproblems to multiplication subproblems by replacing /'s with *'s and inverting the Polynomial following the /. If the polynomial following the / has more than one term, it throws an error.
5) It converts power subproblems to multiplication subproblems by replacing ^'s with a series of multiplications.
6) It adds in implicit *'s. I.e. if two Polynomial elements are right next to each other in the array, then it's inferred that they are being multiplied, so, e.g. '2*x' == '2x'.
7) Now the array has polynomial objects alternating with either '+' or '*'. It first performs all polynomial multiplications and then performs all additions.
8) It performs a final simplification step and returns the resulting expanded polynomial.
<html>
<head></head>
<body></body>
<script>
function findOuterParens(str) {
var leftIndex = str.indexOf('('), leftNum = 1, rightNum = 0;
if (leftIndex === -1)
return
for (var i=leftIndex+1; i<str.length; i++) {
if (str[i] === '(')
leftNum++;
else if (str[i] === ')')
rightNum++, rightIndex=i;
if (leftNum === rightNum)
return {start: leftIndex, end: rightIndex}
}
throw Error('Parenthesis at position ' + leftIndex + ' of "' + str + '" is unpaired.');
}
function parseExpressionStr(inputString) {
var result = [], str = inputString;
while (str) {
var nextPart = str.match(/([\d]+)|([\+\-\^\*\/])|([a-zA-z])/);
if (!nextPart)
return result;
if (nextPart.length === 0)
throw Error('Unable to parse expression string "' + inputString + '". Remainder "' + str + '" could not be parsed.');
else if (nextPart[1]) // First group (digits) matched
result.push(new Polynomial(parseFloat(nextPart[0])));
else if (nextPart[3]) // Third group (symbol) matched
result.push(new Polynomial(nextPart[0]));
else // Second group (operator) matched
result.push(nextPart[0]);
str = str.substring(nextPart.index+nextPart[0].length);
}
return result
}
function isOperator(char) {
return char === '*' || char === '/' || char === '^' || char === '+' || char === '-';
}
function Polynomial(value) {
this.terms = (value!==undefined) ? [new Term(value)] : [];
}
Polynomial.prototype.simplify = function() {
for (var i=0; i<this.terms.length-1; i++) {
if (this.terms[i].coeff === 0) {
this.terms.splice(i--, 1);
continue;
}
for (var j=i+1; j<this.terms.length; j++) {
if (Term.same(this.terms[i], this.terms[j])) {
this.terms[i] = Term.add(this.terms[i], this.terms[j]);
this.terms.splice(j--, 1);
}
}
}
}
Polynomial.add = function(a, b) {
var result = new Polynomial();
result.terms = a.terms.concat(b.terms);
result.simplify();
return result
}
Polynomial.multiply = function(a, b) {
var result = new Polynomial();
a.terms.forEach(function(aTerm) {
b.terms.forEach(function (bTerm) {
result.terms.push(Term.multiply(aTerm, bTerm));
});
});
result.simplify();
return result
}
Polynomial.prototype.toHtml = function() {
var html = ''
for (var i=0; i<this.terms.length; i++) {
var term = this.terms[i];
if (i !== 0)
html += (term.coeff < 0) ? ' - ' : ' + ';
else
html += (term.coeff < 0) ? '-' : '';
var coeff = Math.abs(term.coeff);
html += (coeff === 1 && Object.keys(term.symbols).length > 0) ? '' : coeff;
for (var symbol in term.symbols) {
var exp = term.symbols[symbol];
exp = (exp !== 1) ? exp : '';
html += symbol + '<sup>' + exp + '</sup>';
}
}
return html;
}
function Term(value) {
this.symbols = {};
if (typeof value==='string') { // Symbol
this.symbols[value] = 1;
this.coeff = 1;
} else if (typeof value==='number') { // Number
this.coeff = value;
} else {
this.coeff = 1;
}
}
Term.same = function(a, b) {
if (Object.keys(a.symbols).length != Object.keys(b.symbols).length)
return false
else
for (var aSymbol in a.symbols)
if (a.symbols[aSymbol] != b.symbols[aSymbol]) return false
return true
}
Term.add = function(a, b) {
var result = new Term();
Object.assign(result.symbols, a.symbols);
result.coeff = a.coeff + b.coeff;
return result
}
Term.multiply = function(a, b) {
var result = new Term();
Object.assign(result.symbols, a.symbols);
for (var symbol in b.symbols) {
if (!(symbol in result.symbols))
result.symbols[symbol] = 0;
result.symbols[symbol] += b.symbols[symbol];
if (result.symbols[symbol] === 0)
delete result.symbols[symbol];
}
result.coeff = a.coeff * b.coeff;
return result
}
function expand(str) {
var result = [];
var parens = findOuterParens(str);
while (parens) {
result = result.concat(parseExpressionStr(str.slice(0,parens.start)));
result.push(expand(str.slice(parens.start+1, parens.end)))
str = str.slice(parens.end+1);
parens = findOuterParens(str);
}
result = result.concat(parseExpressionStr(str));
// Move -s to coefficients
var minus = result.indexOf('-'), minusPoly = new Polynomial(-1);
while (minus !== -1) {
result[minus] = '+';
result[minus+1] = Polynomial.multiply(minusPoly, result[minus+1]);
minus = result.indexOf('-');
}
// Get rid of +s that follow another operator
var plus = result.indexOf('+');
while (plus !== -1) {
if (plus===0 || isOperator(result[plus-1])) {
result.splice(plus--, 1);
}
plus = result.indexOf('+', plus+1);
}
// Convert /s to *s
var divide = result.indexOf('/');
while (divide !== -1) {
result[divide] = '*';
var termsToInvert = result[divide+1].terms;
if (termsToInvert.length > 1)
throw Error('Attempt to divide by a polynomial with more than one term.');
var termToInvert = termsToInvert[0];
for (var symbol in termToInvert.symbols) {
termToInvert.symbols[symbol] = -termToInvert.symbols[symbol];
}
termToInvert.coeff = 1/termToInvert.coeff;
divide = result.indexOf('/');
}
// Convert ^s to *s
var power = result.indexOf('^');
while (power !== -1) {
var exp = result[power+1];
if (exp.terms.length > 1 || Object.keys(exp.terms[0].symbols).length != 0)
throw Error('Attempt to use non-number as an exponent');
exp = exp.terms[0].coeff;
var base = result[power-1];
var expanded = [power-1, 3, base];
for (var i=0; i<exp-1; i++) {
expanded.push('*');
expanded.push(base);
}
result.splice.apply(result, expanded);
power = result.indexOf('^');
}
// Add implicit *s
for (var i=0; i<result.length-1; i++)
if (!isOperator(result[i]) && !(isOperator(result[i+1])))
result.splice(i+1, 0, '*');
// Multiply
var mult = result.indexOf('*');
while (mult !== -1) {
var product = Polynomial.multiply(result[mult-1], result[mult+1]);
result.splice(mult-1, 3, product);
mult = result.indexOf('*');
}
// Add
var add = result.indexOf('+');
while (add !== -1) {
var sum = Polynomial.add(result[add-1], result[add+1]);
result.splice(add-1, 3, sum);
add = result.indexOf('+');
}
result[0].simplify();
return result[0];
}
var problems = ['(x+1)(x+1)/x', '(x+1)^3', '(x^2*x)(x^2)', '(x+1)(x+1)(x+1)',
'(x+1)^2', 'x(x+1)', '1x^4', '(x + (x+2))(x+5)', '3x^0', '2^3',
'(x+2x(x+2(x+1)x))', '(x+1)(x-1)', '(x+1)(y+1)', '(x+y+t)(q+x+7)'];
var solutionHTML = '';
for (var i = 0; i<problems.length; i++) {
solutionHTML += problems[i] + ' => ' + expand(problems[i]).toHtml() + '<br>';
}
document.body.innerHTML = solutionHTML;
</script>
</html>
It outputs:

Add Comma Function in JavaScript is Too Greedy

How can I modify the function below to make it stop adding commas once we hit the decimal marker?
addCommas = function(number) {
if(number === undefined) {
return '';
}
while(/(\d+)(\d{3})/.test(number.toString())) {
number = number.toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2');
}
return number;
}
addCommas(0.123456); // Outputs 0.123,456, should output 0.123456
My method is to split the number into fractional and integer parts...
addCommas = function(number)
{
if (number === undefined)
return '';
var parts = number.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
document.write( addCommas(0.123456) + "<br />" );
document.write( addCommas(123456.123456) + "<br />" );
document.write( addCommas(123456) + "<br />" );
Just add ^[^.]* to the front of the pattern:
addCommas = function(number) {
if(number === undefined) {
return '';
}
while(/^[^.]*(\d+)(\d{3})/.test(number.toString())) {
number = number.toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2');
}
return number;
}
You only have to do that for the .test() call.
I would break the string in two prior to using the regular expression. Such as:
RenanCommas = function(number) {
if(number === undefined) {
return '';
}
var parts = (number + "").split(".");
var integerPart = parts[0];
var decimalPart = parts.length > 1 ? parts[1] : "0";
while(/(\d+)(\d{3})/.test(integerPart.toString())) {
integerPart = integerPart.replace(/(\d+)(\d{3})/, '$1'+','+'$2');
}
return integerPart + "." + decimalPart;
}
Notice that you could also have decimalPart as an empty string. In that case, you could check whether or not it is empty before using it. If you use an empty string instead of "0", the last line would be something like:
return integerPart + (decimalPart ? ("." + decimalPart) : "");
And when you run it:
RenanCommas(12121241243.1123131232); // outputs "12,121,241,243.112312"
This seems to be working:
addCommas = function(number) {
return number.replace(/(\.\d+$)|(?!^)(?=(?:\d{3})+(?=\.|$))/g, function($0, $1) {
return ($1)?$1:','; });
}
Examples:
addCommas('0.123456');
"0.123456"
addCommas('987654.123456');
"987,654.123456"
addCommas('987654321');
"987,654,321"

Phone mask for text field with regex

I'm using this function to phone mask and works almost perfectly.
function mask(o, f)
{
v_obj = o;
v_fun = f;
setTimeout("execmask()", 1)
};
function execmask()
{
v_obj.value = v_fun(v_obj.value)
};
function mphone(v){
v=v.replace(/\D/g,"");
v=v.substring(0, 11);
v=v.replace(/^(\d{2})(\d)/g,"(OXX$1) $2");
v=v.replace(/(\d)(\d{4})$/,"$1-$2");
return v;
}
Here I run the mask in the text field:
<input type="text" id="phone" name="phone" onkeypress="mask(this, mphone);" onblur="mask(this, mphone);" />
The problem is that I need to change this part of the code (OXX$1) to (0XX$1).
Current situation:
No. Of Digits
Input Field
9 digit
(OXX99) 99999-9999
8 digit
(OXX99) 9999-9999
The correct formatting that I need:
No. Of Digits
Input Field
9 digit
(0XX99) 99999-9999
8 digit
(0XX99) 9999-9999
The amount of 8 or 9 digits is the choice of the user.
Changing O to 0, causes an error in the mask.
function mask(o, f) {
setTimeout(function () {
var v = f(o.value);
if (v != o.value) {
o.value = v;
}
}, 1);
}
function mphone(v) {
var r = v.replace(/\D/g,"");
r = r.replace(/^0/,"");
if (r.length > 10) {
// 11+ digits. Format as 5+4.
r = r.replace(/^(\d\d)(\d{5})(\d{4}).*/,"(0XX$1) $2-$3");
}
else if (r.length > 5) {
// 6..10 digits. Format as 4+4
r = r.replace(/^(\d\d)(\d{4})(\d{0,4}).*/,"(0XX$1) $2-$3");
}
else if (r.length > 2) {
// 3..5 digits. Add (0XX..)
r = r.replace(/^(\d\d)(\d{0,5})/,"(0XX$1) $2");
}
else {
// 0..2 digits. Just add (0XX
r = r.replace(/^(\d*)/, "(0XX$1");
}
return r;
}
http://jsfiddle.net/BBeWN/
In this project you can see the use of several methods below, including the phone mask and applying them to an input:
Repository: react-text-field-mask
Demo sandbox: https://codesandbox.io/s/eager-monad-qzod32
Regex masks:
// (00) 00000-0000
const phoneMask = (value: string | number) => {
const stringValue = value.toString();
return stringValue
.replace(/\D/g, '')
.replace(/(\d{2})(\d)/, '($1) $2')
.replace(/(\d{5})(\d{4})/, '$1-$2');
};
// (00) 0000-0000
const landlineTelephoneMask = (value: string | number) => {
const stringValue = value.toString();
return stringValue
.replace(/\D/g, '')
.replace(/(\d{2})(\d)/, '($1) $2')
.replace(/(\d{4})(\d{4})/, '$1-$2');
};
// 10.000,00 -> 10000.00
const removeMoneyMask = (value: string | number) => {
const originalNumber = Number(value);
const numberIsWithMask = Number.isNaN(originalNumber);
if (numberIsWithMask) {
const stringValue = value.toString();
const splitedMoneyMask = stringValue
.split('.')
.join('')
.split(',')
.join('.');
return splitedMoneyMask.replace(/[^0-9.-]+/g, '');
}
return value.toString();
};
type BehaviorMode = 'standard' | 'typing';
const moneyMaskCustomization = {
/**
* typingMode - The value is typed from right to left:
* - '1' -> '0.01'
* - '10' -> '0.10'
*
* defaultMode - Simple conversion:
* - '1' -> '1.00'
* - '10' -> '10.00'
*/
maskBehaviorMode: (behaviorMode: BehaviorMode, value: string | number) => {
const numberWithoutMask = removeMoneyMask(value);
const normalizedMoneyValue = moneyMaskCustomization.normalizeMoneyValue(
numberWithoutMask.toString(),
);
const integerWithoutDecimalPlaces = normalizedMoneyValue.length === 1;
if (behaviorMode === 'typing' && integerWithoutDecimalPlaces) {
const newNumberFormat = Number(normalizedMoneyValue) / 100;
return Number(newNumberFormat).toFixed(2);
}
if (behaviorMode === 'standard' && integerWithoutDecimalPlaces) {
return Number(normalizedMoneyValue).toFixed(2);
}
return normalizedMoneyValue;
},
normalizeMoneyValue: (numberToNormalized: string) => {
const [stringInteger, stringDecimal] = numberToNormalized.split('.');
if (stringDecimal && stringDecimal.length === 1) {
const lastPositionOfTheInteger = stringInteger.length - 1;
const lastToIntegerPlace = stringInteger[lastPositionOfTheInteger];
if (lastPositionOfTheInteger !== 0) {
const firstIntegerPlace = stringInteger.substring(
0,
lastPositionOfTheInteger,
);
return `${firstIntegerPlace}.${lastToIntegerPlace}${stringDecimal}`;
}
return `${0}.${lastToIntegerPlace}${stringDecimal}`;
}
if (stringDecimal && stringDecimal.length === 3) {
const firstDecimalPlace = stringDecimal.substring(0, 1);
const lastTwoDecimalPlaces = stringDecimal.substring(1, 3);
const integerIsZero = Number(stringInteger) === 0;
if (integerIsZero) {
return `${firstDecimalPlace}.${lastTwoDecimalPlaces}`;
}
return `${stringInteger}${firstDecimalPlace}.${lastTwoDecimalPlaces}`;
}
return numberToNormalized;
},
};
// 10.000,00
const moneyMask = (
value: string | number,
maskBehaviorMode: BehaviorMode = 'standard',
) => {
if (value || Number.isInteger(value)) {
const moneyValue = moneyMaskCustomization.maskBehaviorMode(
maskBehaviorMode,
value,
);
return moneyValue
.replace(/\D/g, '')
.replace(/\D/g, '.')
.replace(/(\d)(\d{2})$/, '$1,$2')
.replace(/(?=(\d{3})+(\D))\B/g, '.');
}
return '';
};
// 000.000.000-00
const cpfMask = (value: string | number) => {
const stringValue = value.toString();
return stringValue
.replace(/\D/g, '')
.replace(/(\d{3})(\d)/, '$1.$2')
.replace(/(\d{3})(\d)/, '$1.$2')
.replace(/(\d{3})(\d{1,2})/, '$1-$2')
.replace(/(-\d{2})\d+?$/, '$1');
};
// 00.000.000/0000-000
const cnpjMask = (value: string | number) => {
const stringValue = value.toString();
return stringValue
.replace(/\D/g, '')
.replace(/(\d{2})(\d)/, '$1.$2')
.replace(/(\d{3})(\d)/, '$1.$2')
.replace(/(\d{3})(\d)/, '$1/$2')
.replace(/(\d{4})(\d{2})/, '$1-$2');
};
// 000.000.000-00 or 00.000.000/0000-000
const cpfOrCnpjMask = (value: string | number) => {
const stringValue = value.toString();
if (stringValue.length >= 15) {
return cnpjMask(value);
}
return cpfMask(value);
};
// 00000-000
const cepMask = (value: string | number) => {
const stringValue = value.toString();
return stringValue.replace(/\D/g, '').replace(/^(\d{5})(\d{3})+?$/, '$1-$2');
};
// 00/00/0000
const dateMask = (value: string | number) => {
const stringValue = value.toString();
return stringValue
.replace(/\D/g, '')
.replace(/(\d{2})(\d)/, '$1/$2')
.replace(/(\d{2})(\d)/, '$1/$2')
.replace(/(\d{4})(\d)/, '$1');
};
const onlyLettersMask = (value: string | number) => {
const stringValue = value.toString();
return stringValue.replace(/[0-9!##¨$%^&*)(+=._-]+/g, '');
};
const onlyNumbersMask = (value: string | number) => {
const stringValue = value.toString();
return stringValue.replace(/\D/g, '');
};
I have made some changes:
I changed the event to keyup (besides the fact that keypress has been deprecated) because keypress always takes the string with one less character and to work I also needed onblur, something that doesn't happen with keyup. Code adjustments were needed to resolve this
and the issue of the "-", that when tried to remove it with backspace it kept always coming back.
fiddle
function mascaraFone(event) {
var valor = document.getElementById("telefone").attributes[0].ownerElement['value'];
var retorno = valor.replace(/\D/g, "");
retorno = retorno.replace(/^0/, "");
if (retorno.length > 10) {
retorno = retorno.replace(/^(\d\d)(\d{5})(\d{4}).*/, "($1) $2-$3");
} else if (retorno.length > 5) {
if (retorno.length == 6 && event.code == "Backspace") {
// necessário pois senão o "-" fica sempre voltando ao dar backspace
return;
}
retorno = retorno.replace(/^(\d\d)(\d{4})(\d{0,4}).*/, "($1) $2-$3");
} else if (retorno.length > 2) {
retorno = retorno.replace(/^(\d\d)(\d{0,5})/, "($1) $2");
} else {
if (retorno.length != 0) {
retorno = retorno.replace(/^(\d*)/, "($1");
}
}
document.getElementById("telefone").attributes[0].ownerElement['value'] = retorno;
}
<input id="telefone" onkeyup="mascaraFone(event)" />
I love this function and I use it all the time. I've added 2 other masks if anyone needs them. I understand that they don't directly answer the question, but they are super useful.
//Social Security Number for USA
function mssn(v) {
var r = v.replace(/\D/g,"");
r = r.replace(/^0/,"");
if (r.length > 9) {
r = r.replace(/^(\d\d\d)(\d{2})(\d{0,4}).*/,"$1-$2-$3");
return r;
}
else if (r.length > 4) {
r = r.replace(/^(\d\d\d)(\d{2})(\d{0,4}).*/,"$1-$2-$3");
}
else if (r.length > 2) {
r = r.replace(/^(\d\d\d)(\d{0,3})/,"$1-$2");
}
else {
r = r.replace(/^(\d*)/, "$1");
}
return r;
}
//USA date
function mdate(v) {
var r = v.replace(/\D/g,"");
if (r.length > 4) {
r = r.replace(/^(\d\d)(\d{2})(\d{0,4}).*/,"$1/$2/$3");
}
else if (r.length > 2) {
r = r.replace(/^(\d\d)(\d{0,2})/,"$1/$2");
}
else if (r.length > 0){
if (r > 12) {
r = "";
}
}
return r;
}

custom rules parser

I have a set of masks.
The masks look like this
'09{2,9}n(6)'
//read as 09
//[a number between 2 and 9]
//[a random number][repeat expression 6 times]
'029n(7,10)'
//read as 029
//[a random number][repeat expression between 7 and 10 times]
'029n(2,5){8,15}(7,10)n'
//read as 029
//[a random number][repeat expression between 2 and 5 times]
//[a random number between 8 and 15][repeat expression between 7 and 10 times]
//[a random number]
as an example expession 3 would work out as
'029n(4){4,9}(7)n'
'029nnnn{4,9}{4,9}{4,9}{4,9}{4,9}{4,9}{4,9}n
'029nnnn{5}{9}{4}{8}{5}{9}{9}n
'029nnnn5948599n'
'029023559485999'
I need to write a parser in javascript that can generate a string based on those rules.
Note that this is not validation, it is string generation.
Whats the best way to do this?
Trying out a custom parser. Use as,
var generator = new PatternGenerator('09{2,9}n(6)');
generator.generate(); // 096555555
generator.generate(); // 095000000
Checkout this example.
And the constructor function,
function PatternGenerator(pattern) {
var tokens = null;
this.generate = function() {
var stack = [];
tokens = pattern.split('');
// Read each token and add
while (tokens.length) {
var token = lookahead();
if (isDigit(token)) {
stack.push(consumeNumber());
}
else if (token == "n") {
stack.push(consumeVariableNumber());
}
else if (token == "(") {
var topObject = stack.pop();
stack.push(consumeRepetition(topObject));
}
else if (token == "{") {
stack.push(consumeVariableRangeNumber());
}
else {
throw new Error("Invalid input");
}
}
return stack.join('');
}
// [0-9]+
function consumeNumber() {
var number = "";
while (isDigit(lookahead())) {
number += consume();
}
return number;
}
// "n"
function VariableNumber() {
var number = generateRandomNumber();
this.toString = function() {
return Number(number);
};
}
function consumeVariableNumber() {
consume();
return new VariableNumber();
}
// {x, y}
function VariableRangeNumber(start, end) {
var number = generateRandomNumberBetween(start, end);
this.toString = function() {
return Number(number);
};
}
function consumeVariableRangeNumber() {
consume(); // {
var firstNumber = consumeNumber();
consume(); // ,
var secondNumber = consumeNumber();
consume(); // }
return new VariableRangeNumber(firstNumber, secondNumber);
}
// <expression>(x)
function Repeat(object, times) {
this.toString = function() {
var string = "";
for (var i = 0; i < times; i++) {
string += object;
}
return string;
};
}
// <expression>(x, y)
function RepeatWithRange(object, start, end) {
var times = generateRandomNumberBetween(start, end);
this.toString = function() {
return new Repeat(object, times).toString();
};
}
function consumeRepetition(object) {
consume(); // (
var firstNumber, secondNumber;
var firstNumber = consumeNumber();
if (lookahead() == ",") {
consume(); // ,
secondNumber = consumeNumber();
}
consume(); // )
if (typeof secondNumber == 'undefined') {
return new Repeat(objectToRepeat, firstNumber);
}
else {
return new RepeatWithRange(object, firstNumber, secondNumber);
}
}
// Helpers to generate random integers
function generateRandomNumber() {
var MAX = Math.pow(2, 52);
return generateRandomNumberBetween(0, MAX);
}
function generateRandomNumberBetween(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function lookahead() {
return tokens[0];
}
function consume() {
return tokens.shift();
}
function isDigit(character) {
return /\d/.test(character);
}
}

Categories

Resources