Related
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;
}
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);
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]);
My function should return the missing element in a given array range.
So i first sorted the array and checked if the difference between i and i+1 is not equal to 1, i'm returning the missing element.
// Given an array A such that:
// A[0] = 2
// A[1] = 3
// A[2] = 1
// A[3] = 5
// the function should return 4, as it is the missing element.
function solution(A) {
A.sort((a,b) => {
return b<a;
})
var len = A.length;
var missing;
for( var i = 0; i< len; i++){
if( A[i+1] - A[i] >1){
missing = A[i]+1;
}
}
return missing;
}
I did like above, but how to write it more efficiently??
You could use a single loop approach by using a set for missing values.
In the loop, delete each number from the missing set.
If a new minimum value is found, all numbers who are missing are added to the set of missing numbers, except the minimum, as well as for a new maximum numbers.
The missing numbers set contains at the end the result.
function getMissing(array) {
var min = array[0],
max = array[0],
missing = new Set;
array.forEach(v => {
if (missing.delete(v)) return; // if value found for delete return
if (v < min) while (v < --min) missing.add(min); // add missing min values
if (v > max) while (v > ++max) missing.add(max); // add missing max values
});
return missing.values().next().value; // take the first missing value
}
console.log(getMissing([2, 3, 1, 5]));
console.log(getMissing([2, 3, 1, 5, 4, 6, 7, 9, 10]));
console.log(getMissing([3, 4, 5, 6, 8]));
Well, from the question (as it's supposed to return a single number) and all the existing solution (examples at least), it looks like list is unique. For that case I think we can sumthe entire array and then subtracting with the expected sum between those numbers will generate the output.
sum of the N natural numbers
1 + 2 + ....... + i + ... + n we can evaluate by n * (n+1) / 2
now assume, in our array min is i and max is n
so to evaluate i + (i+1) + ..... + n we can
A = 1 + 2 + ..... + (i-1) + i + (i+1) + .... n (i.e. n*(n+1)/2)
B = 1 + 2 + ..... + (i-1)
and
C = A - B will give us the sum of (i + (i+1) + ... + n)
Now, we can iterate the array once and evaluate the actual sum (assume D), and C - D will give us the missing number.
Let's create the same with each step at first (not optimal for performance, but more readable) then we will try to do in a single iteration
let input1 = [2, 3, 1, 5],
input2 = [2, 3, 1, 5, 4, 6, 7, 9, 10],
input3 = [3, 4, 5, 6, 8];
let sumNatural = n => n * (n + 1) / 2;
function findMissing(array) {
let min = Math.min(...array),
max = Math.max(...array),
sum = array.reduce((a,b) => a+b),
expectedSum = sumNatural(max) - sumNatural(min - 1);
return expectedSum - sum;
}
console.log('Missing in Input1: ', findMissing(input1));
console.log('Missing in Input2: ', findMissing(input2));
console.log('Missing in Input3: ', findMissing(input3));
Now, lets try doing all in a single iteration (as we were iterating 3 times for max, min and sum)
let input1 = [2, 3, 1, 5],
input2 = [2, 3, 1, 5, 4, 6, 7, 9, 10],
input3 = [3, 4, 5, 6, 8];
let sumNatural = n => n * (n + 1) / 2;
function findMissing(array) {
let min = array[0],
max = min,
sum = min,
expectedSum;
// assuming the array length will be minimum 2
// in order to have a missing number
for(let idx = 1;idx < array.length; idx++) {
let each = array[idx];
min = Math.min(each, min); // or each < min ? each : min;
max = Math.max(each, max); // or each > max ? each : max;
sum+=each;
}
expectedSum = sumNatural(max) - sumNatural(min - 1);
return expectedSum - sum;
}
console.log('Missing in Input1: ', findMissing(input1));
console.log('Missing in Input2: ', findMissing(input2));
console.log('Missing in Input3: ', findMissing(input3));
Instead of sorting, you could put each value into a Set, find the minimum, and then iterate starting from the minimum, checking if the set has the number in question, O(N). (Sets have guaranteed O(1) lookup time)
const input1 = [2, 3, 1, 5];
const input2 = [2, 3, 1, 5, 4, 6, 7, 9, 10];
const input3 = [3, 4, 5, 6, 8];
function findMissing(arr) {
const min = Math.min(...arr);
const set = new Set(arr);
return Array.from(
{ length: set.size },
(_, i) => i + min
).find(numToFind => !set.has(numToFind));
}
console.log(findMissing(input1));
console.log(findMissing(input2));
console.log(findMissing(input3));
If the array is items and the difference between missing and present diff is 1:
const missingItem = items => [Math.min(...items)].map(min => items.filter(x =>
items.indexOf(x-diff) === -1 && x !== min)[0]-diff)[0]
would give complexity of O(n^2).
It translates to: find the minimum value and check if there isn't a n-diff value member for every value n in the array, which is also not the minimum value. It should be true for any missing items of size diff.
To find more than 1 missing element:
([Math.min(...items)].map(min => items.filter(x =>
items.indexOf(x-diff) === -1 && x !== min))[0]).map(x => x-diff)
would give O((m^2)(n^2)) where m is the number of missing members.
Found this old question and wanted to take a stab at it. I had a similar thought to https://stackoverflow.com/users/2398764/koushik-chatterjee in that I think you can optimize this by knowing that there's always only going to be one missing element. Using similar methodology but not using a max will result in this:
function getMissing(arr) {
var sum = arr.reduce((a, b) => a + b, 0);
var lowest = Math.min(...arr);
var realSum = (arr.length) * (arr.length + 1) / 2 + lowest * arr.length;
return realSum - sum + lowest;
}
With the same inputs as above. I ran it in jsperf on a few browsers and it is faster then the other answers.
https://jsperf.com/do-calculation-instead-of-adding-or-removing.
First sum everything, then calculate the lowest and calculate what the sum would be for integers if that happened to be the lowest. So for instance if we have 2,3,4,5 and want to sum them that's the same as summing 0,1,2,3 and then adding the lowest number + the amount of numbers in this case 2 * 4 since (0+2),(1+2),(2+2),(3+2) turns it back into the original. After that we can calculate the difference but then have to increase it once again by the lowest. To offset the shift we did.
You can use while loop as well, like below -
function getMissing(array) {
var tempMin = Math.min(...array);
var tempMax = tempMin + array.length;
var missingNumber = 0;
while(tempMin <= tempMax){
if(array.indexOf(tempMin) === -1) {
missingNumber = tempMin;
}
tempMin++;
}
return missingNumber;
}
console.log(getMissing([2, 3, 1, 5]));
console.log(getMissing([2, 3, 1, 5, 4, 6, 7, 9, 10]));
console.log(getMissing([3, 4, 5, 6, 8]));
My approach is based on in place sorting of the array which is O(N) and without using any other data structure.
Find the min element in the array.
Sort in place.
Again loop the array and check if any element is misplaced, that is the answer!
function getMissing(ar) {
var mn = Math.min(...ar);
var size = ar.length;
for(let i=0;i<size;i++){
let cur = ar[i];
// this ensures each element is in its right place
while(cur != mn +i && (cur - mn < size) && cur != ar[cur- mn]) {
// swap
var tmp = cur;
ar[i] = ar[cur-mn];
ar[cur-mn] = tmp;
}
}
for(let i=0; i<size; i++) {
if(ar[i] != i+mn) return i+mn;
}
}
console.log(getMissing([2, 3, 1, 5]));
console.log(getMissing([2, 3, 1, 5, 4, 6, 7, 9, 10]));
console.log(getMissing([3, 4, 5, 6, 8]));
I am newbie in programming and try to find out how to multiply
[1,1,0]
to
[4,9,7,2,1,6]
for the next result output
[4,9,7,2,0,0]
As you see I want to multiply each value of [1,1,0] array to each two of second array by shifting in them
[1..] * [4,9..] = [4,9]
[.1.] * [.7,2.] = [7,2]
[..0] * [..1,6] = [0,0]
As example in js i writed something like
var firstArray = [1,1,0];
var secondArray = [4,9,7,2,1,6];
var shift = secondArray / firstArray;
var startpos = 0;
var outArray = [];
for(i=0; i< firstArray.length; i++){
for(z=i; z< shift+i; z++){
outArray.push(firstArray[i] * secondArray[z]);
}
}
console.log(outArray);
It may be in python
You can abuse zip and list slicing:
a = [1, 1, 0]
b = [4, 9, 7, 2, 1, 6]
shift = len(b) // len(a) # use / in Python 2
li = []
for num_a, num_b1, num_b2 in zip(a, b[::shift], b[1::shift]):
li.extend([num_a * num_b1, num_a * num_b2])
print(li)
# [4, 9, 7, 2, 0, 0]
You can express this as a standard matrix multiplication by making your inputs 2D arrays.
I got the multiplication algorithm from here: https://stackoverflow.com/a/27205510/5710637
The calculation would now look like:
[1,0,0] [4,9] [4,9]
[0,1,0] * [7,2] = [7,2]
[0,0,0] [1,6] [0,0]
function multiplyMatrices(m1, m2) {
var result = [];
for (var i = 0; i < m1.length; i++) {
result[i] = [];
for (var j = 0; j < m2[0].length; j++) {
var sum = 0;
for (var k = 0; k < m1[0].length; k++) {
sum += m1[i][k] * m2[k][j];
}
result[i][j] = sum;
}
}
return result;
}
var in1 = [[1, 0, 0], [0, 1, 0], [0, 0, 0]];
var in2 = [[4, 9], [7, 2], [1, 6]]
console.log(multiplyMatrices(in1, in2))
In Javascript, you could use a more functional approach by using
Array#reduce for iterating the factors and returning a new array,
Array#concat for adding a part result after multiplying to the result set,
Array#slice, for getting only two elements of the values array,
Array#map for multiplying the part array with the given factor,
at least use an array as start value for reduce.
var factors = [1, 1, 0],
values = [4, 9, 7, 2, 1, 6],
result = factors.reduce(
(r, f, i) => r.concat(
values
.slice(i * 2, (i + 1) * 2)
.map(v => f * v)
),
[]
);
console.log(result);
You can do this:
Iterate over first array so that you get a number to multiply.
Then extract two elements from the target array and multiply, store the result in res array.
var mul = [1,1,0];
var target = [4,9,7,2,1,6];
var start = 0;
var res = [];
mul.forEach(function(v,i) {
var arr = target.slice(start, start+2);//from start index extract two
//elements
arr.forEach(function(val,i) {
res.push(v * val);
});
start += 2;
});
console.log(res);
You can use map() on array2 and use one var for incrementing index of array1 for each two elements and then multiply current element of array1 with element from array2 that has index as that var.
var a1 = [1,1,0];
var a2 = [4,9,7,2,1,6];
var j = 0;
var result = a2.map(function(e, i) {
if(i % 2 == 0 && i != 0) j++
return e * a1[j];
})
console.log(result)
In python you can use the following code. I'm assuming the length of the second array is larger and it is divisible by the length of the shorter array
def multiply(a, b):
x, y = len(a), len(b) # Find lengths
assert x % y == 0
n = x / y
result = [a[i] * b[i / n] for i in range(x)] # For each index in a, calculate the appropriate element in output by multiplying with relevant part
print result