Javascript add two numbers that are string without using parse - javascript

For non-negative integers num1 and num2, represented as strings, return the sum of num1 and num2.
My solution was to create a filter that has the indexOf with a value of the numbers.
const addStrings = function(num1, num2) {
let filter = "0123456789";
let x = 0;
for(let i=0; i<num1.length; i++) {
x = x + (filter.indexOf(num1[i]) * Math.pow(10, num1.length-1-i));
}
let y = 0;
for(i=0; i<num2.length; i++) {
y = y + (filter.indexOf(num2[i]) * Math.pow(10, num2.length-1-i));
}
return (x+y).toString();
};
It work in most of the cases. However, if the inputs are:
"9333852702227987"
"85731737104263"
It will return the wrong sum: "9419584439332252". I can't understand why it is converting the numbers wrongly.

I've created an object whose keys are digit1, digit2, and carry - all as strings.
The function takes two stringed numbers and adds them "digit by digit" (actually, character by character, as keys to object + carry).
The limit on the "numbers" is the limit on the length of string (minus 1 for the carry).
This could even be adapted to deal with decimals (I leave that to you).
Here's my code:
var sumObject={};
for(var i=0; i<=9; i++) {
for(var j=0; j<=9; j++) {
var sum, carry, digit, obj;
sum=i+j;
carry=sum>9?"1":"0";
digit=sum%10;
obj={sum:""+digit, carry:carry};
sumObject[""+i+j+"0"]=obj;
sum=i+j+1;
carry=sum>9?"1":"0";
digit=sum%10;
obj={sum:""+digit, carry:carry};
sumObject[""+i+j+"1"]=obj;
}
}
function sum2StringedNumbers(sn1, sn2) {
var answer="";
var maxLength=Math.max(sn1.length, sn2.length);
sn1=("0".repeat(maxLength)+sn1).slice(-maxLength);
sn2=("0".repeat(maxLength)+sn2).slice(-maxLength);
var carry="0";
for(var i=maxLength; i>0; i--) {
var key=""+sn1.charAt(i-1)+sn2.charAt(i-1)+carry;
var answer=sumObject[key].sum+answer;
carry=sumObject[key].carry;
}
if(carry=="1") answer="1"+answer;
return answer;
}

The sum of those numbers is larger than Number.MAX_SAFE_INTEGER. You need to use BigInts instead.
const addStrings = function(num1, num2) {
let filter = "0123456789";
let x = 0n;
for(let i=0; i<num1.length; i++) {
x = x + (BigInt(filter.indexOf(num1[i])) * 10n ** BigInt(num1.length-1-i));
}
let y = 0n;
for(i=0; i<num2.length; i++) {
y = y + (BigInt(filter.indexOf(num2[i])) * 10n ** BigInt(num2.length-1-i));
}
return (x+y).toString();
};
console.log(addStrings("9333852702227987","85731737104263"));

You can skip a lot of that code and convert your string directly to a BigInt and calculate from there. Then use toString() to bring it back to a string. Check it out:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
(BigInt("9333852702227987") + BigInt("85731737104263")).toString();
// 9419584439332250

Related

My function doesn't return the expected output

I wrote a fuction that must return if the sum of the first half of the digits is equal to the sum of the second half. What's wrong with my code?
thanks for helping me.
function isLucky(n) {
var digits = (n).toString(10).split("").map(Number)
var k = digits.length;
var a = 0;
var b = 0;
for(let x = 0; x<k/2; x++){
a+=n[x];
}
for(let x = k/2; x<k; x++){
b+=n[x];
}
return (a===b);
}
You can't access digits of a number like an array. First convert it to a String and then use spread syntax to convert it to an array of digits.
function isLucky(n) {
var digits = [...(n).toString(10)]
var k = digits.length;
var a = 0;
var b = 0;
for(let x = 0; x<k/2; x++){
a += +digits[x];
}
for(let x = Math.floor(k/2); x<k; x++){
b += +digits[x];
}
return (a===b);
}
Here is little code that does the comparison of the sums of digits of the 1st and 2nd halves of a number:
Try it. It will print the 2 halves and the result of the comparisons.
You can convert the code into a simple function.
let MyNumber = 1234.5678; // the Number
MyNumber = (""+MyNumber).split("."); // Split the number
let first_half=0, Second_half=0, a; // Some vars
a=[...MyNumber[0]].map(e => first_half+=+e); // Sum the first half
a=[...MyNumber[1]].map(e => Second_half+=+e) // Sum the 2nd half
console.log(first_half, Second_half) // Print 1st and 2nd halves
console.log(first_half == Second_half) // Test if equal

Fastest way to generate a lot of unique small random numbers in JavaScript

Wondering how to quickly generate lots of unique, small random numbers. When I implemented it like this it slows down exponentially it seems like, to the point where it never finishes, or will take hours to complete. Probably because it creates tons of duplicates toward the end.
var intsmap = {}
var intsarray = []
var i = 100000
while (i--) {
var int = randominteger(6)
if (intsmap[int]) i++
else {
intsmap[int] = true
intsarray.push(int)
}
}
// return intsarray
function randominteger(exp) {
var string = rand(exp)
return pad(string, exp)
}
function pad(num, size) {
var s = rand(9) + num
return s.substr(s.length - size)
}
function rand(exp) {
var integer = Math.random() * Math.pow(10, exp) << 0
var string = toString(integer, '0123456789')
return string
}
function toString(value, code) {
var digit
var radix = code.length
var result = ''
do {
digit = value % radix
result = code[digit] + result
value = Math.floor(value / radix)
} while (value)
return result
}
Wondering how to accomplish that but the code works within a few seconds if possible.
Update
I would like for the set of numbers to be distributed evenly over an arbitrary range (in this example 1000000 strings, not necessarily from 0-1000000, eg maybe 5050000 is in there).
I would like for the numbers to not necessarily be valid numbers, just a string of integers. So for example they can include 01010101 as a valid string, even though that's not a valid number.
You can use an object as a look up and only insert unique random number
var intsmap = {};
var i = 100000;
while (i--) {
var int = Math.random() * Math.pow(10, 6) << 0;
if(intsmap[int])
continue;
else
intsmap[int] = true;
}
console.log(Object.keys(intsmap));
You can use also use Durstenfeld shuffle after generating number in the given range.
var arr = Array.from({length:1000000}, (_,i) => (i+1));
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
shuffleArray(arr);
console.log(arr);
Just try to shuffle the array of numbers 1 to maxNum
First create an array
var maxNum = 1000000;
var arr = Array(maxNum).fill().map((e,i)=>i+1);
Now shuffle the array
arr.sort(function() {
return .5 - Math.random();
});
Now you have the array of unique random numbers
Demo
var startTime = new Date().getTime();
var maxNum = 1000000;
var arr = Array(maxNum).fill().map((e, i) => i + 1);
arr.sort(function() {
return .5 - Math.random();
});
var endTime = new Date().getTime();
console.log( "Time taken to get " + maxNum + " size random unique number is " + ( endTime - startTime ) + " ms");
I can propose this approach:
generate a random number
cast it to a string (0.1234567812345678)
and extract 6 substrings of length of 10
Code:
var res = {},
s = "";
for (let i=0; i<1000000; ++i) {
s = Math.random().toString();
for (let j=0; j<6; ++j) {
res[s.substring(2+j, 12+j)] = true; // extract 10 digits
}
}
After 1,000,000 iterations, you have computed 6,000,000 numbers with very little collisions (1,800 in average). So you have your 1,000,000 numbers and more in few seconds.
If you need unique big array try to think in other way. Just create range 0 ... 100000 and shuffle it and apply you function that you need for this array.
var acc = 0;
const result = [];
for(var i = 0; i < 100000; i++)
result.push(acc += Math.floor(Math.random() * 10) + 1);
I think the most expensive operation is the hashtable lookup/insertion, so simply do it without it.
One place where you might loose performances is in the Math.random call.
It's a quite expensive call, and you are calling it a huge number of times to generate your strings.
One solution to leverage it is to grab the whole string from a single result of Math.random().
var intsmap = {}
var intsarray = []
var i = 100000
while (i--) {
var int = randominteger(6)
if (intsmap[int]) {
i++
} else {
intsmap[int] = true
intsarray.push(int)
}
}
console.log(intsarray);
// It takes the whole string from a single call to 'random'.
// The maximum length is 16.
function randominteger(length){
return (Math.random() + '').substr(2,length);
}

Factorializing a number by creating an array and multiplying it

I am going through one of the FreeCodeCamp challenges.
" Return the factorial of the provided integer.
If the integer is represented with the letter n, a factorial is the
product of all positive integers less than or equal to n.
Factorials are often represented with the shorthand notation n!
For example: 5! = 1 * 2 * 3 * 4 * 5 = 120 "
I already know that the easiest way is to use recursion but by the moment I've discovered this fact I was already trying to solve the problem by creating an array, pushing numbers in it and multiplying them. However I got stuck on this step. I have created an array with the number of digits depending on the function factorialize argument, but I can't get the product of those digits. What did I do wrong:
function factorialize(num) {
var array = [];
var product;
for(i = 0; i<=num;i++) {
array.push(i);
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
}
factorialize(5);
I think the easiest way would be to create a range and reduce that:
var n = 5;
function factorize(max) {
return [...Array(max).keys()].reduce((a,b) => a * (b + 1), 1);
}
console.log(factorize(n));
It looks like you missed a close parenthesis
function factorialize(num) {
var array = [];
var product = 1;
for(i = 0; i<=num;i++) {
array.push(i);
} //right here!!! <----
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
factorialize(5);
but as stated in the comments, you should change i = 0 to i = 1 not just because it would change the final result(which it does for all num ) but because it also doesn't follow the factorial algorithm.
1) You need initial value 'product' variable
2) You should change i = 0 to 1. You multiply by 0 in the loop
3) You don't need nested loop
function factorialize(num) {
var array = [];
var product = 1;
for(var i = 1; i <= num; i++) {
array.push(i);
}
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
You only need one loop for that,
from 1 to the maximum number, then you multiply them up,
just a little clean up from your code
fact variable will contain the string version of the individual numbers making up the sum
if m is 5 you'll fact will be 1*2*3*4*5
function factorialize(num) {
var product = 1;
var fact = ""
for (i = 1; i <= num; i++) {
product *= i;
fact += i + "*"
}
fact = fact.substring(0, fact.length - 1)
console.log(fact)
return product;
}
console.log(factorialize(5));

Generate random string with capital letters and numbers without O and 0

I'm wanting to generate a random string with a length of 12 with capital letters only and numbers with no letter O or the number 0 in javascript. here is what I have:
Math.random().toString(36).substr(2, 12)
but the problem is that it is not all capital and i don't want the letter O or the number 0. thanks
function rand_str_without_O0() {
const list = "ABCDEFGHIJKLMNPQRSTUVWXYZ123456789";
var res = "";
for(var i = 0; i < 12; i++) {
var rnd = Math.floor(Math.random() * list.length);
res = res + list.charAt(rnd);
}
return res;
}
Usage:
var randomString = rand_str_without_O0();
let foo = function(length) { //length should be <= 7
return Math.random().toString(36).toUpperCase().replace(/[0-9O]/g, '').substring(1,length+1)
}
response = foo(6) + foo(6)
This will first generate random string convert to uppercase, then remove the un-needed values and then create substring of required length. As far as I have seen, this will generate a string of at-least 7 characters so you can use it twice to generate string of length 12.
This is a quick solution and probably not optimal.
var myString = function(len, excluded) {
var included = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
// remove the excluded chars from the included string
for (var i = 0; i < excluded.length; i++) {
included = included.split(excluded[i]).join('');
}
// add len random chars form whatever is left.
var output = '';
for (var i = 0; i < len; i++) {
output += included.charAt(Math.random() * included.length);
}
return output;
}
And you call it with the desired length and an array of characters to exclude:
console.log(myString(12, ['0', 'O']));
EDIT: This solution allows the output length and the chars to be excluded to be passed on as parameters.
var all_chars_without_O0 = 'ABCDEFGHIJKLMNPQRSTUVWXYZ123456789'.split('');
// Returns a random integer between min (included) and max (excluded)
// Using Math.round() will give you a non-uniform distribution!
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
}
function pickRandom(arr) {
return arr[getRandomInt(0, arr.length)];
}
function randomString(length = 12, chars = all_chars_without_O0) {
var s = '';
while (length--)
s += pickRandom(chars);
return s;
}
https://jsfiddle.net/MrQubo/fusb1746/1/
Or using lodash:
var all_chars_without_O0 = 'ABCDEFGHIJKLMNPQRSTUVWXYZ123456789'.split('');
function randomString(length = 12, chars = all_chars_without_O0) {
return _.sampleSize(chars, length).join('');
}
However, you should be warned, that Math.random() doesn't provide cryptographically secure random numbers. See Math.random() for more information.

Javascript Loop Performance: Counting occurrences of a number in a finite series

What is the most efficient way to write a javascript loop to calculate the number of occurrences of 7's (as an example number) that will be encountered in counting from 1 to 100?
Example:
function numberOccurences(targetNumber, minNumber, maxNumber) {
var count = 0;
for (i = minNumber; i < maxNumber; i++) {
count = count + (i.toString().split(targetNumber).length - 1);
}
return count;
}
var result = numberOccurences(7,1,100);
This will do it without looking at the actual numbers. Sorry, no loop, but you did ask for effeciency. If you really want to use a loop, make the recursion an iteration.
function digitOccurences(digit, min, max, base) {
if (typeof base != "number") base = 10;
return digitOccurencesPlus(digit, max, base, 1, 0) - digitOccurencesPlus(digit, min, base, 1, 0);
function digitOccurencesPlus(digit, N, base, pow, rest) {
if (N == 0) return 0;
var lastDigit = N%base,
prevDigits = (N-lastDigit)/base;
var occsInLastDigit = pow*(prevDigits+(lastDigit>digit));
var occsOfLastInRest = rest * (lastDigit==digit);
// console.log(prevDigits+" "+lastDigit, rest, occsInLastDigit, occsOfLastInRest);
return occsInLastDigit + occsOfLastInRest + digitOccurencesPlus(digit, prevDigits, base, pow*base, pow*lastDigit+rest);
}
}
This is an interesting problem, and already has similar answers for other languages. Maybe you could try to make this one in javascript: Count the number of Ks between 0 and N
That solution is for occurences from 0 to n, but you could easily use it to calculate from a to b this way:
occurences(a,b)= occurences(0,b)-occurences(0,a)
This is much faster (x6) than my original function...JSPERF
function numberOccurences2(targetNumber, minNumber, maxNumber) {
var strMe = "";
for (i = minNumber; i < maxNumber; i++) {
strMe = strMe.concat(i);
}
var re = new RegExp(targetNumber,"g");
var num1 = strMe.length;
var num2 = strMe.replace(re, "").length;
num2 = num1- num2;
return (num2);
}
There has to be a faster way still...

Categories

Resources