I want to create simple addition of array with carryover. Also need carryover and result value for display.
Something like this:-
e.g var input = [[0,0,9],[0,9,9]];
var carryover = [];
var result = [];
Thanks...
The two parts you might have been struggling with, I assume would be how you get the carry, and how you get the result..
result [diget] = t % 10;
The % 10 part is what is called modulus, here I'm doing a modulus by 10, so that gets you the 10's unit value.
carryover [diget] = Math.trunc(t / 10);
For the carryover, you just then divide by 10, and then we strip the decimals,. That's what Math.trunc does.
var input = [[0,0,0,9],[0,9,9]];
var carryover = [];
var result = [];
var digetlength = Math.max(input[0].length, input[1].length);
//lets padd inputs to be same size
input[0].unshift(
...new Array(digetlength - input[0].length).fill(0));
input[1].unshift(
...new Array(digetlength - input[1].length).fill(0));
for (var diget = digetlength - 1; diget >= 0; diget -= 1) {
var t = input[0][diget] + input[1][diget];
if (diget < digetlength - 1)
t += carryover[diget + 1];
result [diget] = t % 10;
carryover [diget] = Math.trunc(t / 10);
}
result.unshift(carryover[0]);
console.log('result: ' + result.join(', '));
console.log('carry: ' + carryover.join(', '));
1.turn both numbers into array of digits, reverse them.
2.determine the end index of the for-loop with max length of above 2 arrays.
3.create the 3rd carryover digits array of zeros (don't forget the extra digit).
4.Add the respective digits from step1 and step3,
as you iterate through each of digits from right to left,
4.1 if the sum is greater than 9 then add 1 into next carryover slot.
5. you should have array of carried over digits when the for-loop is done
count the number of 1s you have in them.
function numberOfCarryOperations(num1, num2) {
const dd1 = [...num1.toString()].reverse()
const dd2 = [...num2.toString()].reverse()
const end = Math.max(dd1.length, dd2.length)
const carry = Array(end+1).fill(0)
for (let i = 0; i < end; i++) {
//console.log(i,(Number(dd1[i]?dd1[i]:0)),Number(dd2[i]?dd2[i]:0),carry)
if (((Number(dd1[i]?dd1[i]:0)) + Number(dd2[i]?dd2[i]:0) + carry[i]) > 9) {
carry[i+1] = 1
}
//console.log('-----',carry)
}
//console.log(num1, num2,carry)
return carry.reduce((sum,curr)=>sum+curr)
}
Here is my attempt. It will accept the following as input:
Any number of input arrays
The input arrays don't all need to have the same number of items
I've added code comments to explain what goes on, I hope they're informative enough to explain the answer.
const
input = [
[0,0,9],
[0,9,9],
[1,0,9,9]
];
function getMaxArrayLength(values) {
// Determine the number of items in the longest array. Initialize the reduce with 0.
return values.reduce((maxLength, array) => {
// Return the largets number between the last largest number and the
// length of the current array.
return Math.max(maxLength, array.length);
}, 0);
}
function sumValues(values) {
const
// Determine the number of items in the longest array.
maxLength = getMaxArrayLength(values),
result = [],
carry = [];
// Loop over the length of the longest array. The value of index will be substracted from
// the length of the input arrays. Therefore it is easier to start at 1 as this will
// return a proper array index without needing to correct it.
for (let index = 1; index <= maxLength; index++) {
const
// Get the carryover value from the last sum or 0 in case there is no previous value.
carryValue = (carry.length === 0) ? 0 : carry[carry.length-1],
// Sum up all the values at the current index of all the input arrays. After summing up
// all the values, also add the carry over from the last sum.
sum = values.reduce((sum, array) => {
// Determine the index for the current array. Start at the end and substract the
// current index. This way the values in the array are processed last to first.
const
arrayIndex = array.length - index;
// It could be the current array doesn't have as many items as the longest array,
// when the arrayIndex is less than 0 just return the current result.
if (arrayIndex < 0) {
return sum;
}
// Return the accumulated value plus the value at the current index of the
// current source array.
return sum + array[arrayIndex];
}, 0) + carryValue;
// The carry over value is the number of times 10 fits into the sum. This should be rounded
// down so for instance 5/10=.5 becomes 0.
carry.push(Math.floor(sum / 10));
// Push the remainder of the sum divided by 10 into the result so 15 % 10 = 5.
result.push(sum % 10);
}
// Return the carry over and the result, reverse the arrays before returning them.
return {
carryOver: carry.reverse(),
result: result.reverse()
};
}
const
result = sumValues(input);
console.log(`Carry over: ${result.carryOver}`);
console.log(`Result: ${result.result}`);
Related
Goal
I am at the final stage of scripting a Luhn algorithm.
Problem
Let's say I have a final calculation of 73
How can I round it up to the next 0? So the final value is 80.
And lastly, how can I get the value that made the addition? e.g. 7 is the final answer.
Current code
function validateCred(array) {
// Array to return the result of the algorithm
const algorithmValue = [];
// Create a [2, 1, 2] Pattern
const pattern = array.map((x, y) => {
return 2 - (y % 2);
});
// From given array, multiply each element by it's pattern
const multiplyByPattern = array.map((n, i) => {
return n * pattern[i];
});
// From the new array, split the numbers with length of 2 e.g. 12 and add them together e.g. 1 + 2 = 3
multiplyByPattern.forEach(el => {
// Check for lenght of 2
if(el.toString().length == 2) {
// Split the number
const splitNum = el.toString().split('');
// Add the 2 numbers together
const addSplitNum = splitNum.map(Number).reduce(add, 0);
// Function to add number together
function add(accumalator, a) {
return accumalator + a;
}
algorithmValue.push(addSplitNum);
}
// Check for lenght of 1
else if(el.toString().length == 1){
algorithmValue.push(el);
}
});
// Sum up the algorithmValue together
const additionOfAlgorithmValue = algorithmValue.reduce((a, b) => {
return a + b;
});
// Mod the final value by 10
if((additionOfAlgorithmValue % 10) == 0) {
return true;
}
else{
return false;
}
}
// Output is False
console.log(validateCred([2,7,6,9,1,4,8,3,0,4,0,5,9,9,8]));
Summary of the code above
The output should be True. This is because, I have given the total length of 15 digits in the array. Whereas it should be 16. I know the 16th value is 7, because the total value of the array given is 73, and rounding it up to the next 0 is 80, meaning the check digit is 7.
Question
How can I get the check number if given array length is less than 15?
You could do something like this:
let x = [73,81,92,101,423];
let y = x.map((v) => {
let remainder = v % 10;
let nextRounded = v + (10-remainder);
/* or you could use
let nextRounded = (parseInt(v/10)+1)*10;
*/
let amountToNextRounded = 10 - remainder;
return [nextRounded,amountToNextRounded];
});
console.log(y);
EDIT
As noticed by #pilchard you could find nextRounded using this more simplified way:
let nextRounded = v + (10-remainder);
https://stackoverflow.com/users/13762301/pilchard
I think what you need is this:
var oldNum = 73
var newNum = Math.ceil((oldNum+1) / 10) * 10;;
Then check the difference using this:
Math.abs(newNum - oldNum);
I implemented the way to generate a list of items with iterable counts with prefix 0. What is the best way to generate such kind of list?
Current behaviour:
const generateList = (length, n, i) => {
let b = n+i
return b.toString().padStart(length.toString().length + n.toString.length, 0)
}
Array(10).fill(null).map((x, i) => generateList(10,2, i))
Output result:
["002", "003", "004", "005", "006", "007", "008", "009", "010", "011"]
Do u have any idea to make it another way?
You could determine the number of characters needed at the start and used the predetermined value to format the output for the array.
function createList(startValue, endValue) {
let
// The minimum output length, for a single digit number, is 2 chars.
outputLength = 2,
testValue = 10,
// Create an empty array which has as many items as numbers we need to
// generate for the output. Add 1 to the end value as this is to be
// inclusive of the range to create. If the +1 is not done the resulting
// array is 1 item too small.
emptyArray = Array(endValue - startValue + 1);
// As long as test value is less than the end value, keep increasing the
// output size by 1 and continue to the next multiple of 10.
while (testValue <= endValue) {
outputLength++;
testValue = testValue * 10;
}
// Create a new array, with the same length as the empty array created
// earlier. For each position place a padded number into the output array.
return Array.from(emptyArray, (currentValue, index) => {
// Pad the current value to the determined max length.
return (startValue + index).toString().padStart(outputLength, '0');
});
}
function createListWithLength(length, startValue = 0) {
return createList(startValue, startValue + length);
}
console.log(createList(2,10));
console.log(createListWithLength(30));
console.log(createListWithLength(10, 995));
Have a look at generators:
function* range(from, to) {
for (var i=from; i<to; i++)
yield i;
}
function* paddedRange(from, to) {
const length = (to-1).toString(10) + 1 /* at least one pad */;
for (const i of range(from, to))
yield i.padStart(length, '0');
}
console.log(Array.from(paddedRange(2, 12)));
You can also inline the loop from range into paddedRange, or you can make it return an array directly:
function paddedRange(from, to) {
const length = (to-1).toString(10) + 1 /* at least one pad */;
return Array.from(range(from, to), i => i.padStart(length, '0'));
}
console.log(paddedRange(2, 12));
The main simplification is that you should compute the padding length only once and give it a denotative name, instead of computing it for every number again. Also ranges are usually given by their lower and upper end instead of their begin and a length, but you can easily switch back if you need the latter for some reason.
Not sure, but maybe something like this
const generateList = length => Array(length).fill('0').map((item, index) => item + index);
console.log(generateList(20));
Watson gives Sherlock an array A of length N. Then he asks him to
determine if there exists an element in the array such that the sum of
the elements on its left is equal to the sum of the elements on its
right. If there are no elements to the left/right, then the sum is
considered to be zero. Formally, find an i, such that,
Input Format
The first line contains T, the number of test cases. For each test
case, the first line contains N, the number of elements in the array
A. The second line for each test case contains N space-separated
integers, denoting the array A.
Constraints
1<=T<=10
1<=N<=10^5
1<=Ai<=2*10^4
1<=i<=N
Output Format
For each test case print YES if there exists an element in the array,
such that the sum of the elements on its left is equal to the sum of
the elements on its right; otherwise print NO.
Sample Input
2
3
1 2 3
4
1 2 3 3
Sample Output
NO
YES
Explanation
For the first test case, no such index exists. For the second test
case,
therefore index 3 satisfies the given conditions.
I'm having timeout issues on 3 of the test cases
function check(input) {
var result = "NO";
var sum=0;
input.map(function(data){
sum=sum+(+data);
})
sumLeft=0;
sumRight=sum-(+input[0]);
for(var i=1;i<input.length;i++){
sumLeft=sumLeft+(+input[i-1]);
sumRight=sumRight-(+input[i])
if(sumLeft==sumRight)
{
console.log("YES");
return;
}
}
console.log("NO");
}
function processData(input) {
//Enter your code here
var lines = input.split("\r\n");
for (var m = 2; m < lines.length; m = m + 2) {
check(lines[m].split(" "));
}
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function(input) {
_input += input;
});
process.stdin.on("end", function() {
processData(_input);
});
Loop over the array once to find the sum. Declare two variables: sumLeft and sumRight. sumLeft should have an initial value of 0 and sumRight should be totalSum-arr[0].
Iterate over the array again and increment sumLeft by the (n-1) element and decrement sumRight by the nth element. Keep comparing the two variables to check if they equal each other. You cut your time complexity down to O(n)
The below code passed the test on https://www.hackerrank.com/challenges/sherlock-and-array . The tricky part was setting up default responses for when the array length was 1. I will admit that #trincot 's answer was more efficient (n as opposed to 2n) for arrays containing only positive integers.
function check(input) {
var result = "NO";
var sum=0;
if(input.length == 1){
console.log("YES");
return;
}
input.map(function(data){
sum=sum+(+data);
})
sumLeft=0;
sumRight=sum-(+input[0]);
for(var i=1;i<input.length-1;i++){
sumLeft=sumLeft+(+input[i-1]);
sumRight=sumRight-(+input[i])
if(sumLeft==sumRight)
{
console.log("YES");
return;
}else if (sumLeft>sumRight) { ///worked both with and without this optimization
console.log("NO");
return;
}
}
console.log("NO");
}
function processData(input) {
//var lines = input.split("\r\n");
var lines = input.split(/\r|\n/)
for (var m = 2; m < lines.length; m = m + 2) {
check(lines[m].split(" "));
}
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function(input) {
_input += input;
});
process.stdin.on("end", function() {
processData(_input);
});
You could go through the array from both ends in inwards direction using two pointers (indices). Keep a balance, starting with 0, as follows:
When the balance is negative move the left pointer one step to the right while increasing the balance with the value you leave behind. When the balance is positive, move the right pointer one step to the left while decreasing the balance with the value you leave behind.
When the two pointers meet each other, check the balance. If it is zero, you have success.
Here is the algorithm in ES6 code, together with a text area where you can adapt the input according to the required input format:
function hasMiddle(a) {
var balance = 0, i = 0, j = a.length-1;
while (i < j) balance += balance > 0 ? -a[j--] : a[i++];
return !balance;
}
// I/O: event handling, parsing input, formatting output
var input = document.querySelector('textarea');
var output = document.querySelector('pre');
input.oninput = function() {
var lines = this.value.trim().split(/[\r\n]+/).filter(s => s.trim().length);
// Strip the case count and array element counts:
lines = lines.slice(1).filter( (s, i) => i % 2 );
// Call function for each test case, returning array of booleans:
var results = lines.map( line => hasMiddle(line.match(/\d+/g).map(Number)) );
// Output results
output.textContent = results.map( pos => pos ? 'YES' : 'NO' ).join('\n');
}
// Evaluate input immediately
input.oninput();
Input:<br>
<textarea style="width:100%; height:120px">2
3
1 2 3
4
1 2 3 3
</textarea>
<pre></pre>
This algorithm requires your input array to consist of non-negative numbers.
If you need to support negative numbers in your array, then the algorithm needs to go through the array first to calculate the sum, and then go through the array again to find the point where the balance reaches 0:
function hasMiddle(a) {
var balance = a.reduce( (sum, v) => sum + v );
return !a.every ( (v, i) => balance -= v + (i ? a[i-1] : 0) );
}
// I/O for snippet
var input = document.querySelector('textarea');
var output = document.querySelector('pre');
input.oninput = function() {
var lines = this.value.trim().split(/[\r\n]+/).filter(s => s.trim().length);
// Strip the case count and array element counts:
lines = lines.slice(1).filter( (s, i) => i % 2 );
// Call function for each test case, returning array of booleans:
var results = lines.map( line => hasMiddle(line.match(/[\d-]+/g).map(Number)));
// Output results
output.textContent = results.map( pos => pos ? 'YES' : 'NO' ).join('\n');
}
// Evaluate input immediately
input.oninput();
Input:<br>
<textarea style="width:100%; height:120px">2
3
1 2 3
4
1 2 3 3
</textarea>
<pre></pre>
Given that we have a proper array one might do as follows
var arr = [...Array(35)].map(_ => ~~(Math.random()*10)+1),
sum = arr.reduce((p,c) => p+c),
half = Math.floor(sum/2),
ix;
console.log(JSON.stringify(arr));
midix = arr.reduce((p,c,i,a) => { (p+=c) < half ? p : !ix && (ix = i);
return i < a.length - 1 ? p : ix;
},0);
console.log("best possible item in the middle # index", midix,": with value:",arr[midix]);
console.log("sums around midix:",
arr.slice(0,midix)
.reduce((p,c) => p+c),
":",
arr.slice(midix+1)
.reduce((p,c) => p+c));
Of course for randomly populated arrays as above, we can not always get a perfect middle index.
I am working on prime numbers algorithm, and I almost finished it.. I think output array is updated every time loop finishes, so if I call function with prime number: e.g primes(7), I get [7] instead of [2,3,5,7]. If its called with non prime, output arr is empty.
Here is code:
function rimes(num){
var outputArr = [];
for(var i=1; i<=num; i++){
function range(start, count) {
return Array.apply(0, Array(count))
.map(function (element, index) {
return index + start;
});
}
var rangeArr = range(1,num);
var current = i;
function rangeFiltering(value){
return value !== 1 && value < current;
}
var filteredRange = rangeArr.filter(rangeFiltering);
function dividingByEachRangeElement(rangeElement){
return current % rangeElement !== 0;
}
var divided = filteredRange.filter(dividingByEachRangeElement);
if(divided.length === num - 2){ //current is prime if there are all numbers from 1 to current in divided array.(if there are zeros after modulo) i.e. when current is 5(prime), divided array is [2,3,4]. When current is 6(non prime), divided arr is [4,5] - 2,3 are missing because 6%2 = 0 and 6%3 = 0.
outputArr.push(current);
}
}
console.log(outputArr);
}
sumPrimes(47);
//sumPrimes(6) -> [];
//sumPrimes(7) -> [7];
//sumPrimes(11) -> [11];
How can i fix this?
Your problem is on the line:
if(divided.length === num - 2)
which means the current number is only added to outputArr if the length of divided happens to equal num - 2 which is only true when i or current is equal to 7 in your example case.
Changing it to:
if(divided.length === current - 2)
should do the trick.
"A positive number of whatever length is represented as an array of numerical characters, ergo between '0's and '9's. We know that the most significant cypher is in position of index 0 of the array.
Example:
- Number is 10282
- Array will be number = [1,0,2,8,2]
This considered, create a function of 2 arrays representing two positive numbers that calculates the SUM\ADDITION\SUMMATION of both of them and set it in a third array, containing the sum of the first 2."
This is how the exercise is translated from my own language, italian.
This is my solution but it doesnt entirely work. I have tried with basic stuff like
A=[1,4] and B=[4,7]. The results should be C=[6,1] but it gives me [5,1] as it considers the line where I use the modular but not the one where I say that the -1 index position should take a ++.
Help <3
alert('Insert A length');
var k=asknum();
alert('Insert B length');
var h=asknum();
var A = new Array(k);
var B = new Array(h);
// asknum() is only defined in this particular environment we are
// using at the university. I guess the turnaround would be -prompt-
function readVet(vet){//inserts values in index positions
for(i=0;i<vet.length;i++)
vet[i]=asknum();
}
readVet(A);//fills array
readVet(B);//fills array
function sumArray(vet1,vet2){
var C = new Array();
for(i=vet1.length-1;i>(-1);i--){
for(n=vet2.length-1;n>(-1);n--){
C[i]=vet1[i]+vet2[i];
if(C[i]>9){
C[i]=C[i]%10;
C[i-1]=C[i-1]++;
}
}
}
return C;
}
print(sumArray(A,B));
I'm not sure what you're doing with a nested for loop here. You just need one. Also, to make said loop really simple, normalize the arrays first so that both are the length of the larger array + 1 element (in case of carry). Then correct the result on the way out of the function.
function normalizeArray(array, digits) {
var zeroCnt = digits - array.length,
zeroes = [];
while (zeroCnt--) {
zeroes.push(0);
}
return zeroes.concat(array);
}
function sumArrays(a1, a2) {
var maxResultLength = Math.max(a1.length, a2.length) + 1;
a1 = normalizeArray(a1, maxResultLength);
a2 = normalizeArray(a2, maxResultLength);
var result = normalizeArray([], maxResultLength);
var i = maxResultLength - 1, // working index
digit = 0, // working result digit
c = 0; // carry (0 or 1)
while (i >= 0) {
digit = a1[i] + a2[i] + c;
if (digit > 9) {
c = 1;
digit -= 10;
} else {
c = 0;
}
result[i--] = digit;
}
/* If there was no carry into the most significant digit, chop off the extra 0 */
/* If the caller gave us arrays with a bunch of leading zeroes, chop those off */
/* but don't be an idiot and slice for every digit like sqykly =D */
for (i = 0 ; i < result.length && result[i] === 0 ; i++) {
/* result = result.slice(1); don't do that, or anything */
}
return result.slice(i);
}
That gives the expected output.
I may be missing something because the other answers look much more complicated, but here's my attempt at providing an answer based on the question:
// Takes an array and generates the sum of the elements
function addArrayNumbers(arr) {
return arr.reduce(function (p, c) {
return String(p) + String(c);
});
}
// Sums two numbers and returns an array based on that sum
function addCombinedNumbers(a, b) {
return String(Number(a) + Number(b)).split('');
}
var arrone = [1, 4];
var arrtwo = [4, 7];
var one = addArrayNumbers(arrone);
var two = addArrayNumbers(arrtwo);
var c = addCombinedNumbers(one, two); // [6,1]
Fiddle
I followed a different approach that may very well be less efficient than yours, but i consider it to be much clearer. One important thing is that i reverse the arrays so the least significant bit is first. Comments are in the code.
function sum(a,b){
// ensure a is the largest of the two arrays
if (a.length < b.length)
return sum(b,a);
// flip the arrays so the least significant digit is first
a = a.reverse();
b = b.reverse();
// c will hold the result (reversed at first)
var c = [];
// add each number individually
var carry = a.reduce(function(carry,digitA,index){
// digitA is guaranteed to be a number, digit from b is not!
var sum = digitA + (b[index] || 0) + carry;
c.push(sum%10);
return Math.floor(sum/10); // this is carried to the next step of the addition
},0); // initial carry is 0
if (carry) c.push(1); // resolve if carry exists after all digits have been added
return c.reverse();
}
// Usage:
console.log(sum([1,0,8,3],[1,3,5])); // [1, 2, 1, 8]
console.log(sum([8,3],[7,9])); // [1, 6, 2]
PS: There are many problems with your code. For one, you cannot use two nested loops:
var a = [0,1];
var b = [2,3];
for (var i=0; i<a.length; i++) {
for (var j=0; j<b.length; j++) {
console.log(a[i] + ' ' + b[i]);
}
}
// will output: 0 2, 0 3, 1 2, 1 3
// you want something along the lines of: 0 2, 1 3
What you want is a single loop that iterates over both arrays simultaneously.
My attempt at an efficient solution:
function efficientSum(a,b){
var i = a.length, j = b.length;
if (i<j) return efficientSum(j,i);
var q = 0, c = [];
c.length = i;
while (i) {
c[--i] = a[i] + (b[--j] || 0) + q;
q = c[i] > 9 ? ((c[i]-=10),1) : 0; // comma operator, ugly!
}
if (q) c.unshift(1);
return c;
}