Number Formatting for large integer numbers in Javascript - javascript
I know there are in-build function in javascript like toLocalString() to achieve number formatting. But this question is purely for learning and logic understanding.
I have a function in javascript that formats given number in Indian Number formatting standards (eg: 1,234 | 12,21,123 | etc)
Code
function formatter(input) {
var inputStr = input.toString(), l = inputStr.length;
var c = 1, f = 0;
console.log(l);
for (var x=l-1; x>=0; x--) {
if (x === 0) {
continue;
}
if (c === 3 && f === 0) {
inputStr = inputStr.substring(0, x) + ',' + inputStr.substring(x);
f = 1;
c = 0;
} else if (c % 2 === 0 && f === 1) {
inputStr = inputStr.substring(0, x) + ',' + inputStr.substring(x);
c = 0;
}
c++;
}
return inputStr;
}
Now this works for most part (as far as I have test, do point out bugs if you spot any). But my question is how do I handle large number in this, i.e. how do I handle values greater than 9007199254740991.
Hope this now fixes the issue:
function formatter(inputStr) {
inputStr+="";
let c = 1, f = 0;
for (let x=inputStr.length-1; x>=0; x--) {
if (x === 0) continue;
if (c === 3 && f === 0) {
inputStr = inputStr.substring(0, x) + ',' + inputStr.substring(x);
f = 1;
c = 0;
} else if (c % 2 === 0 && f === 1) {
inputStr = inputStr.substring(0, x) + ',' + inputStr.substring(x);
c = 0;
}
c++;
}
return inputStr;
}
//========= Tests =======
console.log(formatter(9007199254740991));
console.log(formatter("900719925474093454549341"));
console.log(formatter("123456678890987665443221112345667676766545434243"));
Related
Efficient way to get longest palindrome subsequence in a string
I'm trying to implement a function that takes a string as input and returns the longest palindrome subsequence in the string. I've tried using dynamic programming and have come up with the following code: function longestPalindromicSubsequence(str) { let n = str.length; let dp = Array(n); for (let i = 0; i < n; i++) { dp[i] = Array(n); dp[i][i] = 1; } for (let cl = 2; cl <= n; cl++) { for (let i = 0; i < n - cl + 1; i++) { let j = i + cl - 1; if (str[i] === str[j] && cl === 2) dp[i][j] = 2; else if (str[i] === str[j]) dp[i][j] = dp[i + 1][j - 1] + 2; else dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]); } } return dp[0][n - 1]; } However, this code doesn't seem to be giving me efficient and better results for all test cases. The Time and Space Complexity is also be reduced. I've been struggling with this for days and can't seem to find the issue. Can someone help me figure out what's going wrong and how to fix it?
Oh, I think Dynamic Programming does not work with this sort of problem, because it does not break down recursively, i.e. to find the longest palindrome in a string, you don't need all second-largest palindromes. You can just check at each position and see if it is the center of a palindrome longer than any before. This can be solved with a greedy algorithm: const pals = "asd1234321fghjkl1234567887654321qwertzu1234321" function palindromeAtPos(str, pos, checkEven = false){ let ix = 0 const off = checkEven ? 2 : 1 while(pos-ix-1 >= 0 && pos+ix+1+off < str.length && str[pos-ix-1] === str[pos+ix+off]){ ix++ } return ix === 0 ? str[pos] : str.substring(pos-ix, pos+ix+off) } function longestPalindrome(str){ let longest = '' for(let i = 1; i < str.length; i++){ const odd = palindromeAtPos(str, i) longest = odd.length > longest.length ? odd : longest const even = palindromeAtPos(str, i, true) longest = even.length > longest.length ? even : longest } return longest } console.log(longestPalindrome(pals)) On paper (and for a string like aaaaaaaaaa), this has quadratic complexity, but for most strings, it will be almost linear.
/* * s => string * return [] of strings witch have the max lenth */ function maxLenPalindromes(s) { const l = s.length let c, z, zz, a, b, a1, b1, maxl = 0, result = [] if (l < 2) return result for (c = 0; c < l - 1; c++) { a = -1 if (maxl>(l-c)*2+1) return result if (c > 0 && s[c - 1] == s[c + 1]) { zz = Math.min(c, l - c - 1) for (z = 1; z <= zz; z++) { if (s[c - z] != s[c + z]) { a = c - z + 1; b = c + z break } else if (z == zz) { a = c - z; b = c + z + 1 break } } if (a >= 0) { if (b-a > maxl) { result = [s.slice(a, b)] maxl = b-a } else if (b-a == maxl) { result.push(s.slice(a, b)) } } } a=-1 if (s[c] == s[c + 1]) { if (c == 0 || c == l - 2) { a = c; b = c + 2 } else { zz = Math.min(c, l - c - 2) for (z = 1; z <= zz; z++) { if (s[c - z] != s[c + z + 1]) { a = c - z + 1; b = c + z + 1 break } else if (z == zz) { a = c - z; b = c + z + 2 break } } } if (a >= 0) { if (b-a > maxl) { result = [s.slice(a, b)] maxl = b-a } else if (b-a == maxl) { result.push(s.slice(a, b)) } } } } return result } const s1="112233111222333" const s2="11_22_33_111_222_333" const s3="12345_54321xqazws_swzaq_qwertytrewq" const s4="sdfgsdfg1qqqqqAAAAA_123456789o o987654321_AAAAAqqqqq;lakdjvbafgfhfhfghfh" console.log(maxLenPalindromes(s1)) console.log(maxLenPalindromes(s2)) console.log(maxLenPalindromes(s3)) console.log(maxLenPalindromes(s4))
Function in Javascript that inserts dashes or asterisks between each two odd or even numbers
I want to write a function that inserts dashes (' - ') between each two odd numbers and inserts asterisks (' * ') between each two even numbers. For instance: Input: 99946 Output: 9-9-94*6 Input: 24877 Output: 2*4*87-7 My try function dashAst (para) { let stringArray = para.toString().split(''); let numbArray = stringArray.map(Number); for (let i = 0; i<numbArray.length; i++) { if (numbArray[i] %2 === 0 && numbArray[i+1] % 2 === 0) { numbArray.splice(numbArray.indexOf(numbArray[i]), 0, '*') } else if (numbArray[i] %2 !== 0 && numbArray[i+1] %2 !== 0) { numbArray.splice(numbArray.indexOf(numbArray[i]), 0, '-') } } return numbArray } When I try to invoke the function it returns nothing. For instance, I tested the splice-command separately and it seems to be correct which makes it even more confusing to me. Thanks to everyone reading, or even helping a beginner out.
Looping through an Array that changes its length during the loop can be very messy (i needs to be adjusted every time you splice). It's easier to create a new result variable: function dashAst(para) { const stringArray = para.toString().split(''); const numbArray = stringArray.map(Number); let result = ""; for (let i = 0; i < numbArray.length; i++) { const n = numbArray[i], next = numbArray[i + 1]; result += n; if (n % 2 == next % 2) { result += n % 2 ? '-' : '*'; } } return result; } console.log(dashAst(99946)); // "9-9-94*6" console.log(dashAst(24877)); // "2*4*87-7"
You could map the values by checking if the item and next item have the same modulo and take a separator which is defined by the modulo. function dashAst(value) { return [...value.toString()] .map((v, i, a) => v % 2 === a[i + 1] % 2 ? v + '*-'[v % 2] : v) .join(''); } console.log(dashAst(99946)); // 9-9-94*6 console.log(dashAst(24877)); // 2*4*87-7
I hope this helps var str = '24877'; function dashAst (para) { let stringArray = para.toString().split(''); let numbArray = stringArray.map(x => parseInt(x)); console.log(numbArray); var out=[]; for(let i = 0; i < numbArray.length; i++) { if(numbArray[i] % 2 == 0){ out.push(numbArray[i]); numbArray[i + 1] % 2 == 0 ? out.push('*') : 0; }else if(numbArray[i] % 2 != 0) { out.push(numbArray[i]); numbArray[i + 1] != undefined ? out.push('-') : 0; } } console.log(out.join('')); return out; } dashAst(str);
Compare 3 values - Show the highest
Doing a survey where a user picks : A B or C I then need to know if the user has picked Mostly A's, B's or C's. I'm trying a few jQuery logics' but not having much luck, Due to expression expected error. Is there a neater / better way to show purely which variable is the highest? My current jQuery : var count = 0; var count_a = 0; var count_b = 0; var count_c = 0; $('.radio-select').click(function() { var chosen_option = $(this).val(); if(chosen_option == 'a') { count++; count_a ++; } if(chosen_option == 'b') { count++; count_b ++; } if(chosen_option == 'c') { count++; count_c ++; } check_numbers(count, count_a, count_b, count_c); }) function check_numbers(count, a, b, c) { parseInt(a); parseInt(b); parseInt(c); if(count == '8') { if ((a > b ) && (a > c)) { alert("A is Highest"); } if ((b > a ) && (b > c)) { alert("B is Highest"); } if(c > b) && (c > a)) { alert("C is highest!"); } } } jsFiddle Example
If you wanted a smaller way of doing it you could use inline if statements. Up to you if this is a better way, I like it though. a = 5 b = 11 c = 6 console.log((a > b && a > c? a : (b > c ? b : c)))
Firstly you do not need to use parseInt() on a, b, c as they are already integers. And again count is an integer while you are comparing it to a string. This should work. if(count == 8) { if ((a > b ) && (a > c)) { alert("A is Highest"); } else if ((b > a ) && (b > c)) { alert("B is Highest"); } else { alert("C is highest!"); }
You need to fetch the value returned by parseInt. Use it like: a = parseInt(a); and same for the other variables before comparing them in the if...else.
function check_numbers(count, a, b, c) { var x = parseInt(a), y = parseInt(b), z = parseInt(c); if(count == 8) { var result = (x > y ? (x > z ? x : z) : (y > z ? y : z)); } }
#StuBlackett you can consider adding the values and labels to an array then sorting Descending and returning the lable at the top. function CompareIndexZero(a, b) { if (a[0] < b[0]) return 1; if (a[0] > b[0]) return -1; return 0; } function myFunction() { var count_a = 2; var count_b = 5; var count_c = 4; var arrHighest = []; arrHighest.push([count_a, "A"]); arrHighest.push([count_b, "B"]); arrHighest.push([count_c, "C"]); arrHighest.sort(CompareIndexZero); alert(arrHighest[0][1] + " is the highest"); }
Here is a modified version of check_numbers() that works as intended if I got you right. The point I want to make is the use of Math.max() to find the highest number from a selection of numbers. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max function check_numbers(count, a, b, c) { if(count === 8) { var numArray = [a, b, c]; var highest = Math.max.apply(null, numArray); console.log(highest); if (highest === a) { console.log('a is highest'); } else if (highest === b) { console.log('b is highest'); } else if (highest === c) { console.log('c is highest'); } } } check_numbers(8, 1 , 2, 5); check_numbers(8, 5, 2, 1); check_numbers(8, 1 , 5, 2);
Have you also taken into account that multiple answers could share the highest count? My 2 cents on that: var count = count_a = count_b = count_c = 0; $('.radio-select').on('click', function() { var chosen_option = $(this).val(); if (chosen_option == 'a') { count_a++; } else if (chosen_option == 'b') { count_b++; } else if (chosen_option == 'c') { count_c++; } if (++count == 8) { check_numbers(count_a, count_b, count_c); } }); function check_numbers(a, b, c) { var highest = ((a > b && a > c) ? a : (b > c)? b : c), multiple = false, alertText = ''; if (a == highest) { alertText += 'A'; } if (b == highest) { if (alertText != '') { multiple = true; alertText += ' and '; } alertText += 'B'; } if (c == highest) { if (alertText != '') { multiple = true; alertText += ' and '; } alertText += 'C'; } alert(alertText + ' ' + (multiple ? 'are' : 'is') + ' highest!'); }
While loop runs forever in JavaScript
I've writen a function in JavaScript that checks through all the combinations of three digits between 1 and 9 and gives me the number of combinations that follow this pattern √(x^2 + y^2 + z^2) = a natural number (a full number like 24 or 34 but not 2.54) √ = square root , ^2 = to the power of 2, My problem is that whenever I run the function the computer gets stuck and the function never ends so it doesn't return an answer. I would very much appreciate if someone could tell me whats wrong with it (I'm running my programs on the chrome browser console) function mmd() { var chk = false; var a = 1; var b = 1; var c = 1; var d = 1; var e = 0; while(chk != true) { d = Math.sqrt(Math.pow(a, 2)+Math.pow(b, 2)+Math.pow(c, 2)); if( d == d.toFixed(0)) { e++; } else { if((b == 9) && (a == 9) && (c == 9)) {chk = true;} else if((a == 9) && (b == 9)) {c++;} else if(b == 9) {b = 1; a++;} else if(c == 9) {c = 1; b++;} else if(c < 9) {c++;} } } return e }
This part of the code is causing it to never end: if (d == d.toFixed(0)){} else {} If the result of the formula is an integer, you add 1 to e, but you don't increment the other variables, because of the else. It keeps doing e++ for ever. So you need to remove that else. I also took the liberty or removing that chk variable, and instead used while(true), which will be ended by a return of the final result: function mmd() { var a = 1, b = 1, c = 1, d, e = 0; while(true) { d = Math.sqrt(Math.pow(a, 2)+Math.pow(b, 2)+Math.pow(c, 2)); if( d == parseInt(d, 10)) { e++; } if((b == 9) && (a == 9) && (c == 9)) {return e;} else if((a == 9) && (b == 9)) {c++;} else if(b == 9) {b = 1; a++;} else if(c == 9) {c = 1; b++;} else {c++;} } } alert(mmd());
It gets stuck once it hits the e++ block and never increases a, b, or c. function mmd() { var keepGoing = true; var a = 1, b = 1, c = 1, d, e = 0; while(keepGoing) { // calculate d d = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2) + Math.pow(c, 2)); // check if it is a whole number if(d == d.toFixed(0)) e++; // if we're done then stop if(a == 9 && b == 9 && c == 9){ keepGoing = false; } // if c is less than 9 then increase it else if(c < 9){ c++; } // if c is 9 and b is less than 9 then set c back to 1 and increase b else if(b < 9){ c = 1; b++; } // if c is 9 and b is 9 then set both back to 1 and increase a else if(a < 9){ c = b = 1; a++; } } return e; }
Most effecient way to solve a formula in javascript
Say I have the following formula a + (13 * (b/c)) + d + (12 * e) - f - 11 + (g * (h/i)) - 10 = 66; Now the letters a-i can represent a number from 1-9. However, each number can only be used once. What would be the most efficient way to solve this? The way I have at the moment is to generate an array of random numbers e.g. array[2,5,1,7,8,6,9,3,4] I then fit this into the formula to check if it equals 66. If not, I generate a new array of numbers. I was thinking there should be a better way to do this though, maybe using recursion? Just wanted to get some input in how you would tackle this? Thanks
I think there's no smarter algorithm than just trying with each permutation of the numbers in the set for equality. Which I think will be easier for you, than creating everytime an unique array, that was not already generated. In the code bellow I have used very primitive check for equality between numbers. There might be an easier way from the standard javascript library (e.g. if number is found in the predefined set...) var solutions = []; for (var a = 1; a <= 9; a++) { for (var b = 1; b <= 9; b++) { if ( b == a ) continue; for (var c = 1; c <= 9; c++) { if ( c == b || c == a ) continue; for (var d = 1; d <= 9; d++) { if ( d == c || d == b || d == a ) continue; for (var e = 1; e <= 9; e++) { if ( e == d || e == c || e == b || e == a ) continue; for (var f = 1; f <= 9; f++) { if ( f == e || f == d || f == c || f == b || f == a ) continue; for (var g = 1; g <= 9; g++) { if ( g == f || g == e || g == d || g == c || g == b || g == a ) continue; for (var h = 1; h <= 9; h++) { if ( h == g || h == f || h == e || h == d || h == c || h == b || h == a ) continue; for (var i = 1; i <= 9; i++) { if ( i == h || i == g || i == f || i == e || i == d || i == c || i == b || i == a ) continue; if ((a + (13 * (b/c)) + d + (12 * e) - f - 11 + (g * (h/i)) - 10) == 66) { solutions.push(a + "," + b + "," + c + "," + d + "," + e + "," + f + "," + g + "," + h + "," + i); } } } } } } } } } } console.log(solutions); Which results into a lot of solutions ["1,2,6,4,7,8,3,5,9", "1,2,6,4,7,8,5,3,9", "1,3,2,4,5,8,7,9,6", "1,3,2,4,5,8,9,7,6", "1,3,2,9,5,6,4,7,8", "1,3,2,9,5,6,7,4,8", "1,3,4,7,6,5,2,9,8", "1,3,4,7,6,5,9,2,8", "1,3,6,2,7,9,4,5,8", "1,3,6,2,7,9,5,4,8", "1,3,9,4,7,8,2,5,6", "1,3,9,4,7,8,5,2,6", "1,4,8,2,7,9,3,5,6", "1,4,8,2,7,9,5,3,6", "1,5,2,3,4,8,7,9,6", "1,5,2,3,4,8,9,7,6", "1,5,2,8,4,7,3,9,6", "1,5,2,8,4,7,9,3,6", "1,5,3,9,4,2,7,8,6", "1,5,3,9,4,2,8,7,6", "1,9,6,4,5,8,3,7,2", "1,9,6,4,5,8,7,3,2", "1,9,6,7,5,2,3,4,8", "1,9,6,7,5,2,4,3,8", "2,1,4,3,7,9,5,6,8", "2,1,4,3,7,9,6,5,8", "2,3,6,1,7,9,4,5,8", "2,3,6,1,7,9,5,4,8", "2,4,8,1,7,9,3,5,6", "2,4,8,1,7,9,5,3,6", "2,8,6,9,4,1,5,7,3", "2,8,6,9,4,1,7,5,3", "2,9,6,3,5,1,4,7,8", "2,9,6,3,5,1,7,4,8", "3,1,4,2,7,9,5,6,8", "3,1,4,2,7,9,6,5,8", "3,2,1,5,4,7,8,9,6", "3,2,1,5,4,7,9,8,6", "3,2,4,8,5,1,7,9,6", "3,2,4,8,5,1,9,7,6", "3,2,8,6,5,1,7,9,4", "3,2,8,6,5,1,9,7,4", "3,5,2,1,4,8,7,9,6", "3,5,2,1,4,8,9,7,6", "3,6,4,9,5,8,1,7,2", "3,6,4,9,5,8,7,1,2", "3,9,2,8,1,5,6,7,4", "3,9,2,8,1,5,7,6,4", "3,9,6,2,5,1,4,7,8", "3,9,6,2,5,1,7,4,8", "4,2,6,1,7,8,3,5,9", "4,2,6,1,7,8,5,3,9", "4,3,2,1,5,8,7,9,6", "4,3,2,1,5,8,9,7,6", "4,3,9,1,7,8,2,5,6", "4,3,9,1,7,8,5,2,6", "4,9,6,1,5,8,3,7,2", "4,9,6,1,5,8,7,3,2", "5,1,2,9,6,7,3,4,8", "5,1,2,9,6,7,4,3,8", "5,2,1,3,4,7,8,9,6", "5,2,1,3,4,7,9,8,6", "5,3,1,7,2,6,8,9,4", "5,3,1,7,2,6,9,8,4", "5,4,1,9,2,7,3,8,6", "5,4,1,9,2,7,8,3,6", "5,4,8,9,6,7,1,3,2", "5,4,8,9,6,7,3,1,2", "5,7,2,8,3,9,1,6,4", "5,7,2,8,3,9,6,1,4", "5,9,3,6,2,1,7,8,4", "5,9,3,6,2,1,8,7,4", "6,2,8,3,5,1,7,9,4", "6,2,8,3,5,1,9,7,4", "6,3,1,9,2,5,7,8,4", "6,3,1,9,2,5,8,7,4", "6,9,3,5,2,1,7,8,4", "6,9,3,5,2,1,8,7,4", "7,1,4,9,6,5,2,3,8", "7,1,4,9,6,5,3,2,8", "7,2,8,9,6,5,1,3,4", "7,2,8,9,6,5,3,1,4", "7,3,1,5,2,6,8,9,4", "7,3,1,5,2,6,9,8,4", "7,3,2,8,5,9,1,6,4", "7,3,2,8,5,9,6,1,4", "7,3,4,1,6,5,2,9,8", "7,3,4,1,6,5,9,2,8", "7,5,2,8,4,9,1,3,6", "7,5,2,8,4,9,3,1,6", "7,6,4,8,5,9,1,3,2", "7,6,4,8,5,9,3,1,2", "7,9,6,1,5,2,3,4,8", "7,9,6,1,5,2,4,3,8", "8,2,4,3,5,1,7,9,6", "8,2,4,3,5,1,9,7,6", "8,3,2,7,5,9,1,6,4", "8,3,2,7,5,9,6,1,4", "8,5,2,1,4,7,3,9,6", "8,5,2,1,4,7,9,3,6", "8,5,2,7,4,9,1,3,6", "8,5,2,7,4,9,3,1,6", "8,6,4,7,5,9,1,3,2", "8,6,4,7,5,9,3,1,2", "8,7,2,5,3,9,1,6,4", "8,7,2,5,3,9,6,1,4", "8,9,2,3,1,5,6,7,4", "8,9,2,3,1,5,7,6,4", "9,1,2,5,6,7,3,4,8", "9,1,2,5,6,7,4,3,8", "9,1,4,7,6,5,2,3,8", "9,1,4,7,6,5,3,2,8", "9,2,8,7,6,5,1,3,4", "9,2,8,7,6,5,3,1,4", "9,3,1,6,2,5,7,8,4", "9,3,1,6,2,5,8,7,4", "9,3,2,1,5,6,4,7,8", "9,3,2,1,5,6,7,4,8", "9,4,1,5,2,7,3,8,6", "9,4,1,5,2,7,8,3,6", "9,4,8,5,6,7,1,3,2", "9,4,8,5,6,7,3,1,2", "9,5,3,1,4,2,7,8,6", "9,5,3,1,4,2,8,7,6", "9,6,4,3,5,8,1,7,2", "9,6,4,3,5,8,7,1,2", "9,8,6,2,4,1,5,7,3", "9,8,6,2,4,1,7,5,3"] If the formula is only this, and will not change, you might try to think if there are ranges that are not included in the result set per definition. For example, if you find that some of the numbers cannot be 9, you should not iterate to 9. E.g. the multiplications in the formula might exceed a number that even added to the minimal values in the other variables to exceed 66.
Brute force method: function findSolution() { for (var a = 1; a <= 9; a++) { for (var b = 1; b <= 9; b++) { for (var c = 1; c <= 9; c++) { for (var d = 1; d <= 9; d++) { for (var e = 1; e <= 9; e++) { for (var f = 1; f <= 9; f++) { for (var g = 1; g <= 9; g++) { for (var h = 1; h <= 9; h++) { for (var i = 1; i <= 9; i++) { if ( [b,c,d,e,f,g,h,i].indexOf(a) >= 0 || [a,c,d,e,f,g,h,i].indexOf(b) >= 0 || [a,b,d,e,f,g,h,i].indexOf(c) >= 0 || [a,b,c,e,f,g,h,i].indexOf(d) >= 0 || [a,b,c,d,f,g,h,i].indexOf(e) >= 0 || [a,b,c,d,e,g,h,i].indexOf(f) >= 0 || [a,b,c,d,e,f,h,i].indexOf(g) >= 0 || [a,b,c,d,e,f,g,i].indexOf(h) >= 0 || [a,b,c,d,e,f,g,h].indexOf(i) >= 0 ) { continue; } if (a + (13 * (b/c)) + d + (12 * e) - f - 11 + (g * (h/i)) - 10 === 66) { return [a,b,c,d,e,f,g,h,i]; } } } } } } } } } } } document.getElementById('result').innerText = findSolution().join(', ') <span id="result"></span>