Find the sum of the first n num [duplicate] - javascript

This question already has answers here:
Javascript - Counting array elements by reduce method until specific value occurs doesn't give a correct output
(4 answers)
Closed 2 years ago.
I have an array with numbers. Find the sum of the first N elements to the first zero. Task must be completed with
Example: - summarize the first 3 elements, because next is the element with the number 0.

You could do this as follows:
let arr = [10, 20, 3, 0, 16, 35, 1];
let sum = arr.slice(0, arr.indexOf(0)).reduce((sum, v) => sum + v);
console.log(sum);
I first extract the numbers in front of the first zero using Array.slice(). Then I use Array.reduce() to compute the sum of these numbers.

You can not break the iteration of reduce(). You can use a flag variable based on which you can add value to sum.
Try the following way:
let arr = [10, 20, 3, 0, 16, 35, 1];
let flag = true;
let sumNum = arr.reduce((sum, elem) => {
if (elem == 0) {
flag = false;
};
if(flag) return sum + elem;
else return sum + 0;
}, 0)
console.log(sumNum)

You can utilize an external variable stopCounting to flag if the counting should continue or not.
let arr = [10, 20, 3, 0, 16, 35, 1];
let stopCounting = false;
let sumNum = arr.reduce((sum, elem) => {
if (elem == 0) {
stopCounting = true;
}
return stopCounting ? sum : sum + elem;
}, 0);
console.log(sumNum);

You could iterate with a short circuit and check the value and add the value if not zero.
This approach does not search for zero in advance and needs only a single loop in the worst case.
var array = [10, 20, 3, 0, 16, 35, 1],
sum = 0;
array.every(v => (sum += v, v));
console.log(sum);

const arr = [10, 20, 3, 0, 16, 35, 1];
const zeroIndex = arr.indexOf(0);
const total = arr.slice(0, zeroIndex > 0 ? zeroIndex : arr.length)
.reduce(sum, n => sum+n, 0);
console.log(total);

Related

Removing values in a range from an array

I want to remove values in a range from an array. For example, removeVals([20, 30, 40, 50, 60, 70], 2, 4) should return the array [20, 30, 70]. How can I solve this problem?
This can be done in one-liner. If you're unfamiliar with arrow functions this might be a bit confusing but I'll put my solution out there anyway.
var removeVals = (array, start, end) => array.filter((item, index) => index < start || index > end);
console.log(removeVals([20, 30, 40, 50, 60, 70], 2, 4)) // [20, 30, 70]
JavaScript's built-in filter function iterates through an array, and passes each item (and the index of said item optionally) into the function that it's provided. If the return value of that function is true, then the item stays in the array, otherwise it is removed. The function that we pass into the filter function only returns true if the index of the current item in the array is less than the beginning of the range or more that the end of the range, therefore removing items that are in the range.
You can use Array#splice, which changes the input array. So you would need to return the modified array.
DEMO
const removeVals = (arr, start, end) => arr.splice(start, end-start+1) && arr;
console.log( removeVals([20, 30, 40, 50, 60, 70], 2, 4) );
This solution works like .filter() demonstrated in tybocopperkettle's answer, but with .flatMap() instead. Using a ternary in .flatMap() gives us an advantage of returning almost any value.
idx < a || idx > z ? num : []
JavaScript
Description
idx < a
If index is less than start...
||
...OR...
idx > z
...if index is greater than end...
? num
...return the value...
:[]
...otherwise return nothing🞾
🞾[] returns as nothing since .flatMap() applies .flat() to whatever it returns.
const arrayA = [20, 30, 40, 50, 60, 70];
const Aa = 2;
const Az = 4;
const arrayB = ['A', 'B', 'C', 'D', 'E', 'F'];
const Ba = 0;
const Bz = 7;
const remVal = (array, a, z) => array
.flatMap((num, idx) =>
idx < a || idx > z ?
num : []
);
console.log(remVal(arrayA, Aa, Az));
console.log(remVal(arrayB, Ba, Bz));
Method-1
This method removes the subset in the range Array[startIx, stopIx] from the source array using the Array.prototype.splice()method.
// INPUT → array[0, array.length - 1]
// OUTPUT → array[0, startIx - 1] U array[stopIx + 1, array.length - 1]
let removeVals = (array, startIx, stopIx) => {
array.splice(startIx, stopIx - startIx + 1);
return array;
}
let array= [20, 30, 40, 50, 60, 70]
console.log(`Result: ${removeVals(array, 2, 4)}`);
Method-2
Create a new array inside the function.
Add the values in the range array[0, startIx - 1] to the new array.
Add values from range array[stopIx+ 1, array.lenght - 1] to the new array.
// INPUT → array[0, array.length - 1]
// OUTPUT → array[0, startIx - 1] U array[stopIx + 1, array.length - 1]
let removeVals = (array, startIx, stopIx) => {
let resultArray = []
for(let i = 0; i < startIx ; ++i)
resultArray.push(array[i])
for(let i = stopIx + 1 ; i < array.length ; ++i)
resultArray.push(array[i])
return resultArray;
}
let array= [20, 30, 40, 50, 60, 70]
console.log(`Result: ${removeVals(array, 2, 4)}`);

Improve the speed of a JavaScript function

I have a task I found on CodeWars and I managed to solve it, however, after submitting is says:
Execution timed out: (12000 ms)
When I try to test the function is passed, but I guess it is too slow.
Before you condemn me for not finding the answer on my own. I don't really care about submitting that as a response, but I have no idea how to make it faster and that is why I am here.
Here is the function:
const ls = [0, 1, 3, 6, 10]
const partsSums = (ls) => {
const sum = []
for(let i = 0, len = ls.length; i < len + 1; i++) {
let result = ls.slice(i).reduce( (accumulator, currentValue) => accumulator + currentValue, 0)
sum.push(result)
}
return sum
}
Here are the instructions:
Let us consider this example (array written in general format):
ls = [0, 1, 3, 6, 10]
Its following parts:
ls = [0, 1, 3, 6, 10]
ls = [1, 3, 6, 10]
ls = [3, 6, 10]
ls = [6, 10]
ls = [10]
ls = []
The corresponding sums are (put together in a list): [20, 20, 19, 16,
10, 0]
The function parts_sums (or its variants in other languages) will take
as parameter a list ls and return a list of the sums of its parts as
defined above.
For this kind of array maipulations, you better not use build in methods, like slice or reduce, because they are slow in comparison to a for loop, or any other looping approaches.
This approach takes a sinlge loop and uses the index for getting a value of the given array and takes the last sum of the new array.
Some speed tests on Codewars: Sums of Parts:
5621 ms with sparse array sum = []; sum[i] = 0; (the first version of this answer),
3452 ms with Array(i + 1).fill(0) and without sum[i] = 0;,
1261 ms with Array(i + 1) and sum[i] = 0; (find below),
3733 ms with Icepickle's first attempt.
const
partsSums = (ls) => {
let i = ls.length;
const sum = Array(i + 1);
sum[i] = 0;
while (i--) sum[i] = sum[i + 1] + ls[i];
return sum;
},
ls = [0, 1, 3, 6, 10];
console.log(...partsSums(ls));
You can still take a more functional approach but optimise the way you're doing the calculations.
Here is the idea - since you're trying to sum all items, then sum all but the first, then sum all but the second, etc., mathematically equivalent to getting the sum then subtracting from it each number in order and keeping the total.
[sum([41, 42, 43]), sum([42, 43]), sum([43]), sum([])]
is the same as:
total = sum([41, 42, 43])
[total - 0, total - 0 - 41, total - 0 - 41 - 42, total - 0 - 41 - 42- 43]
is the same as:
total = sum([41, 42, 43])
[total -= 0, total -= 41, total -= 42, total -= 43]
Generalised, this looks like:
total = sum([a1, a2, ..., aN])
[total -= 0, total -= a1, total -= a2, ..., total -= aN]
Using the trusty Array#reduce we can derive the sum once. Then we can derive the new array using Array.map using ls.map(num => total -= num).
The only problem here is that we get one less item - we don't calculate the initial total -= 0 which has to exist for all items. One way to do it is to append it to the start [0].concat(ls) will create the correct array to map over. However, since we already know what the value there would be, we can skip this step and directly substitute with total (after all the result of total -= 0 is total and leaves total unchanged). So, we can directly use [total].concat(ls.map(num => total -= num)) to start with total and add the rest of the items. to the end.
const ls = [0, 1, 3, 6, 10]
const partsSums = (ls) => {
let total = ls.reduce((a, b) => a + b, 0);
return [total]
.concat(
ls.map(num => total -= num)
);
}
console.log(partsSums(ls));
Personally, I would just use the previous sum to calculate the next, I don't see any need to re-iterate all the previous sums, so, I would probably go for a basic loop and then reverse the results, like so
function partsSums(ls) {
const result = [0];
if (ls.length === 0) {
return result;
}
for (let i = ls.length, q = 0; i--; q++) {
result.push(result[q] + ls[i]);
}
return result.reverse();
}
or, without reversing, look more like Nina's solution (except for predefining the length of the array)
function partsSums(ls) {
const len = ls.length;
const result = new Array(len+1);
result[len] = 0;
for (let i = len; i--;) {
result[i] = result[i+1] + ls[i];
}
return result;
}
Both also seem to run faster than Nina's on codewars nodejs engine, in the first part probably because of push, in the second one, probably because the array's length is defined from the start, for more information see this question
A solution using normal for loop along the time of execution .
var arr = [0, 1, 3, 6, 10];
function giveList(array){
var sum=0;
for(let i=0;i<array.length;i++){
sum=sum+array[i];
}
var result = [];
result.push(sum);
var temp;
for(let i=0;i<array.length;i++){
temp=sum-array[i];
result.push(temp);
sum=sum-array[i];
}
return result;
}
console.time();
console.log(giveList(arr));
console.timeEnd();
const partsSums = (ls, sum = 0) =>
[...ls, 0].reverse().map(x => sum = x + sum).reverse();
Takes around 1100 ms when I run it on CodeWars, which is slightly faster than other answers.
The repeated operation is too more. e.g: when you compute sum of [3, 6, 10], the up step [1, 3, 6, 10] already compute。 So you can think in another direction, back to end compute the sum of array
const ls = [0, 1, 3, 6, 10];
function partSums(ls) {
const len = ls.length;
const dp = [];
if(len === 0) { return [0] }
dp[len] = 0;
dp[len - 1] = ls[len - 1];
for (let i = len - 2; i >= 0; i--) {
dp[i] = dp[i + 1] + ls[i];
}
return dp;
}

check if values in array have common difference

I have a sample array as
const arr=[0,2,4,6]
I want to check if they have a common difference in them, which is 2 and yes in above array.
There could be more efficient way to do this. I tried using a simple for loop as:
const arr = [0,2,4,6];
for(let i=0;i<arr.length-1;i++){
if(arr[i]+2==arr[i+1]){
console.log(true);
}
else{
console.log(false);
}
}
This could give me result as true,true,true and push all values to a new array then check if all are true and finally I would get true
It would be helpful if there is a more efficient way to do this; any help appreciated.
Assuming the array is sorted, you can do it pretty simply with .every().
const arr = [0,2,4,6];
const itvl = arr[1] - arr[0];
const result = arr.slice(0, -1).every((n, i) =>
itvl === arr[i + 1] - n
)
console.log(result);
This starts off by calculating the first interval, then it iterates the array (except the last index) using .every() to test that the next index minus the current one is equal to that pre-calculated index.
You can do this. It's better to stop as soon as you find a false rather than testing all the values.
const arr=[0,2,4,6]
var r = true
for (var i=1; i<arr.length-1 && r; i++) {
r = ((arr[i+1] - arr[i]) == (arr[i] - arr[i-1]))
}
console.log(r)
I assume what you mean by difference is the step value. For that, first find the difference between the first two elements ; then check whether the same difference holds for all consecutive values.
const arr = [0, 2, 4, 6];
let flag = true;
diff = arr[1] - arr[0];
for(let i = 1; i < arr.length-1; i++){
if(arr[i+1] - arr[i] != diff ){
flag = false;
break;
}
}
console.log(flag)
The code assumes the array size is atleast 2. Add an if guard if this is not always guaranteed.
Checks if numbers sum up to desired sum and if rest of numbers have same difference as desired in comments. (This should be a separate question.)
add up until s >= sum. return false if s isn't equal to set sum
if numbers left <= 2 return true
get difference of first 2 numbers
check difference of numbers, if not same difference return false
differences all same, return true
let arr = [0, 1, 3, 4, 6, 8, 10, 12];
const sum = 4
check = arr => {
let s = 0,
idx = arr.findIndex(x => (s+=x) >= sum ) + 1
if(s !== sum) return false
if(arr.length - idx < 3) return true
const diff = arr[idx+1] - arr[idx]
while(++idx<arr.length-1)
if(arr[idx+1] - arr[idx] !== diff) return false
return true
}
arr = [0, 1, 3, 4, 6, 8, 10, 12]
console.log(
check(arr)
)
arr = [0, 1, 3]
console.log(
check(arr)
)
arr = [0, 1, 3, 4, 6, 8, 10, 12, 11]
console.log(
check(arr)
)

Count pairs in an array in JavaScript

I'm still a junior at web dev and I am trying to solve this problem.
I have to find the number of matching pairs in these arrays:
var ar1 = [10, 20, 20, 10, 10, 30, 50, 10, 20] // return 3 (2 pairs of 10 and 1 pair of 20)
var ar2 = [1, 1, 3, 1, 2, 1, 3, 3, 3, 3] // return 4 (2 pairs of 1 and 2 pairs of 3)
// I started to write my logic below but I'm stuck, could you please help me to solve this problem ?
// The last result I am returning is a filtered array with all the nbs that are superior to 1 and then can't figure out how to get the result of matching pairs :-(
function countPairs(n, ar) {
const count = {};
ar.forEach((nb) => (count[nb] = (count[nb] || 0) + 1));
const values = Object.values(count);
const filter = values.filter((value) => value > 1);
return filter;
}
// 9 and 10 are the length of the arrays
console.log(countPairs(9, ar1))
console.log(countPairs(10, ar2))
Thank you very much for your help!
Perhaps there is a faster/better way to calculate this than this O(2n) solution, but it's something:
var ar1 = [10, 20, 20, 10, 10, 30, 50, 10, 20] // return 3 (2 pairs of 10 and 1 pair of 20)
var ar2 = [1, 1, 3, 1, 2, 1, 3, 3, 3, 3] // return 4 (2 pairs of 1 and 2 pairs of 3)
function countPairs(ar) {
var obj = {};
ar.forEach(item => {
obj[item] = obj[item] ? obj[item] + 1 : 1;
});
return Object.values(obj).reduce((acc, curr) => {
acc += Math.floor(curr / 2)
return acc;
}, 0);
}
console.log(countPairs(ar1))
console.log(countPairs(ar2))
This first calculates the number of occurences for each number and stores them in an Object. Once that is done, we reduce over the values and return the quotient from the division with 2 (to get the number of pairs in total).
Note: I removed the first argument from your function, because the array length is not needed as an argument. It can be obtained from the array you pass directly.
We can achieve this in O(n) time. Maintain an object which keeps track whether a number have been found before, if it was found before, then it makes up a pair, so we increment the pairs count. If not we make the entry of that number in the object 1
function countPairs(arr) {
let pairs = 0;
const obj = {};
arr.forEach(i => {
if (obj[i]) {
pairs += 1;
obj[i] = 0;
} else {
obj[i] = 1;
}
});
return pairs;
}
Simplest solution I can find:
create empty dictionary var t = {}; and use it to count each item in array arr.forEach (i => t[i] = (t[i] || 0) + 1);. After that take all keys Object.values(t) and sum .reduce((acc, p) => acc + ..., 0) each item counts divided by 2 p/2 with Int semantics of course Math.floor(...).
function countPairs(arr) {
var t = {};
arr.forEach (i => t[i] = (t[i] || 0) + 1);
return Object.values(t).reduce((acc, p) => acc + Math.floor(p/2), 0);
}
console.dir(countPairs([1,2,2,2,2,3]));
console.dir(countPairs([1,2,2,2,2,2,3]));
console.dir(countPairs([1,2,2,2,2,2,2,3]));
console.dir(countPairs([10, 20, 20, 10, 10, 30, 50, 10, 20]));
console.dir(countPairs([1, 1, 3, 1, 2, 1, 3, 3, 3, 3]));
First argument in your implementation is not necessary.
Please up-vote if answer was helpful
Concise approach with reduce method
const countPairs = arr => (pairs = [], arr.reduce((p, c) => (p[c] ? (pairs.push([p[c], c]), delete p[c]) : p[c] = c, p), {}), pairs.length)
console.log(countPairs([10, 20, 20, 10, 10, 30, 50, 10, 20]));
So, I wanted a more simpler solution to this problem since I'm just starting to learn to code and I'm teaching my self. I found this solution works perfectly for what you want. I didn't created this solution I found it on the internet(https://www.geeksforgeeks.org/count-equal-element-pairs-in-the-given-array/) I just translated it to JavaScript.
function countDuplicates(n, arr) {
var count = 0;
arr.sort();
for (var i = 0; i < n;) {
if (arr[i] === arr[i + 1]) {
count++;
i = i + 2;
} else {
i++;
}
}
return count;
}
console.log(countDuplicates(9, [10, 20, 20, 10, 10, 30, 50, 10, 20]));
There are some more concise answers here, but here's the solution I have for you:
function countDuplicates(arr) {
var counts = {}, sum = 0;
for (var i = 0; i < arr.length; i++) {
counts[arr[i].toString()] = (counts[arr[i].toString()] || 0) + 1;
}
for (var count in counts) {
if (Object.prototype.hasOwnProperty.call(counts, count)) sum += Math.floor(counts[count] / 2);
}
return sum;
}
console.log(countDuplicates([10, 20, 20, 10, 10, 30, 50, 10, 20]));
I hope I have helped
function numberOfPairs(array) {
let arr = [...array].sort();
let result = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] == arr[i + 1]) {
result++;
arr.shift();
}
}
console.log(result);
}
numberOfPairs(['blue', 'blue', 'blue', 1, 2, 5, 2, 1]);

Convert an array into cumulative% array

I have an array like this one:
[30, 10, 4, 3, 3]
And I need to transform this to a cumulative% array in such a way that each value is the sum of all values upto there divided by sum of all values in the array.
In this case, the total is 50. So, the first value will be 30/50, i.e., 0.6 or 60%. The 2nd value will be (30+10)/50, i.e., 0.8 or 80% and so on.
The final array in this will be:
[60%, 80%, 88%, 94%, 100%]
How can I do this transformation with JavaScript? What would be the most efficient way to do so?
Try,
var x = [30, 10, 4, 3, 3];
var y = x.reduce(function(a,b){ return a+b; }, 0)
x = x.map(function(itm, index){
for(var i=0;i<index;i++) itm += x[i];
return (itm/y * 100);
});
x; //[60, 80, 88, 94, 100]
And this will look more elegant,
var x = [30, 10, 4, 3, 3];
var y = x.reduce(function(a,b){ return a+b; }, 0), sum = 0;
x = x.map(function(itm) { return sum += itm, (sum / y) * 100; });
Try
let nums = [30, 10, 4, 3, 3];
let sum = nums.reduce((prev,curr) => prev + curr);
let result = nums.map((num,i) => Math.round(nums.slice(0,i + 1).reduce((prev,curr) => prev + curr) / sum * 100) + '%');
You first need to compute the sum to get the denominator (50).
Then you need to apply the treatment for each element (new_value=value/denominator)
To do so you can use simple for loops, or even cleaner with arrays specific functions, to avoid any error:
var array = [30, 10, 4, 3, 3];
// Compute the denominator
var sum = array.reduce(function(pv, cv) { return pv + cv; }, 0);
// Duplicate the array
var arrayResult = array;
// Apply the function to each given "myArray[ind]" element
arrayResult.forEach( function(cv,ind,myArray) {
myArray[ind] = cv/sum;
// Add the previous accumulator if any
if( ind>0 ) {myArray[ind] += myArray[ind-1];}
} );
See it running on JSFiddle
edited to add the accumulator
Combine two maps, one to create an array with cumulative sums, the second to divide by the sum.
function cumulative_ratio(array) {
var x = 0;
return array .
map(v => x += v) .
map(v => v / x);
}

Categories

Resources