Logging distinct array - javascript

I am trying to get just one distinct array populated under 'console.log(partial)', eg if the target = 5 and I have a set of numbers [1,1,1,1,1,2,2], the subset will give me just these 2 arrays: [1,1,1,2] or [1,2,2]. However, in my console log, the same 2 sets of arrays are populated multiple times. Is there something wrong with my code?
function subsetSum(numbers, target, partial) {
var s, n, remaining;
partial = partial || [];
// sum partial
s = partial.reduce(function (a, b){
return a + b;
}, 0);
// check if the partial sum is equals to target
if (s === target) {
console.log("%s=%s", partial.join("+"), target)
console.log(partial)
for(j = 0; j < partial.length; j++){
if (partial[j] == 1){
console.log("here")
}
}
}
if (s >= target) {
return; // if we reach the number why bother to continue
}
for (var i = 0; i < numbers.length; i++) {
n = numbers[i];
remaining = numbers.slice(i + 1);
subsetSum(remaining, target, partial.concat([n]));
}
return;
}

You get more than one result of
[1, 1, 1, 2, 2]
because you have more than one element with the same value.
For example, if you number the values and take only the integer value, you can see this happen.
For excluding same results, you need a search in the result set and avoid pusing the same set of numbers.
function subsetSum(numbers, target, partial = []) {
const
sum = partial.reduce((a, b) => a + parseInt(b, 10), 0),
result = [];
if (sum === target) return [partial];
if (sum > target) return [];
for (let i = 0; i < numbers.length; i++) {
const n = numbers[i];
result.push(...subsetSum(numbers.slice(i + 1), target, partial.concat(n)));
}
return result;
}
subsetSum(['1#1', '1#2', '1#3', '1#4', '1#5', '2#1', '2#2'], 5).forEach(a => console.log(...a));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Javascript - simple exercises

I have a task to write a function getEvenAverage, which should take only one argument - array. This function should return an average value of even numbers from this array. If in the array there aren't any even numbers the function should return null.
I'd really appreciate any feedback :-)
function getEvenAverage(tab) {
{
if (i % 2 === 0) {
for (var i = 0; i < tab.length; i++) {
sum += parseInt(tab[i], 10);
}
var avg = sum / tab.length;
} else
console.log('null');
}
}
You say you need to return something, so return it. Also move your if statement inside your for loop, and fix a few other syntax errors. And as pointed out in the comments, you should divide sum by the number of even numbers to get your avg:
function getEvenAverage(tab) {
var sum = 0;
var evens = 0;
for (var i = 0; i < tab.length; i++) {
if (i % 2 === 0) {
sum += parseInt(tab[i], 10);
evens++;
}
}
if (evens == 0) {
console.log("null");
return null;
} else {
var avg = sum / evens;
return avg;
}
}
console.log(getEvenAverage([1, 2, 3]));
You could also do it with the array reduce, with a single array traversal
const reducer = (acc, val) => {
let {
sum,
count
} = acc;
return (val % 2 === 0 ? {
sum: sum + val,
count: count + 1
} : acc);
};
const getEvenAverage = (input) => {
const initialValue = {
sum: 0,
count: 0
};
const output = input.reduce(reducer, initialValue);
if (output.count === 0) {
return null;
} else {
return output.sum / output.count;
}
};
console.log(getEvenAverage([1, 2, 3]));
Here is the correct function.
function getEvenAverage(tab) {
var sum = 0, count = 0;
for (var i = 0; i < tab.length; i++) {
if (i % 2 === 0) {
sum += parseInt(tab[i], 10);
count++;
}
}
if(sum > 0)
return (sum / count);
return null;
}
Wish You happy coding.
Other than using a for loop, you can utilize filter and reduce Array methods.
function getEvenAverage(arr) {
const newArr = arr.filter(number => number % 2 === 0);
return newArr.length > 0 ? newArr.reduce((acc, num) => acc + num) / newArr.length : null;
}
console.log(getEvenAverage([1, 2, 3, 4]));
console.log(getEvenAverage([1, 3, 5, 7]));
Try this function,
function getEvenAverage(tab) {
var numberOfEvens = 0;
var sum = 0;
for(var i=0;i<tab.length;i++){
if(tab[i]%2 == 0 ){
numberOfEvens++;
sum += tab[i];
}
}
if(numberOfEvens == 0)return null;
return sum/numberOfEvens;
}
console.log(getEvenAverage([0,1,2,3,4,5]))
console.log(getEvenAverage([1,2,3,4,5]))
console.log(getEvenAverage([0,1,11,3,4,5]))
console.log(getEvenAverage([1,5,3]))
You need only the even numbers, so first filter the array into a new array, then sum all the numbers (using reduce or a for loop) and divide by its length.
function getEvenAverage(array) {
if (!Array.isArray(array)) return null; // not a must if you're sure you pass an array
var evenArray = array.filter(function(value) {
return value % 2 === 0
});
if (evenArray.length === 0) return null;
var evenSum = evenArray.reduce(function(total, current) {
return total + current;
});
var evenAvg = evenSum / evenArray.length;
return evenAvg;
}
console.log(getEvenAverage("not an array"));
console.log(getEvenAverage([1,3,7])); // no even numbers
console.log(getEvenAverage([1,2,3])); // single even number
console.log(getEvenAverage([2,2,2])); // only even numbers
console.log(getEvenAverage([1,2,3,10,18])); // bigger array
console.log(getEvenAverage([0,1])); // 0 is also even
function getEvenAverage(arr){
var evenNumbers = []; // we use an array to hold all of our evenNumbers
for (var el of arr){ // we loop over the received array to check the received
if(el % 2 !=0){ // if the number is even
evenNumbers.push(el); // we add it to our evenNumbers array
}
}
if(evenNumbers.length == 0){ // when we have no even Number
return false; // we then return false
}
else{
// the next block of code calculates the average of the even values
return evenNumbers.reduce((pv,cv) => pv+cv,0)/evenNumbers.length;
}
}
var evenNumbers = [4,2,3,6,5,9];
getEvenAverage(evenNumbers); // returns 5.666666666666667
getEvenAverage([2,4,6,8]); // returns false

Find the largest subarray length with delimiter

I'm trying to solve this problem:
Given two parameters: an array a and integer i, find the largest array length where the sum of all elements is <= i.
For example, having the following array: [3, 1, 2, 1], and i = 4, all the combinations that are <= i are: [3], [1], [2], [3, 1], [1, 2], [1, 2, 1]. The largest subarray is [1, 2, 1], so the return of the function should be 3 (the array length).
What would be a an efficient approach to solve this problem?
This is my algorithm until now, but I know that I'm missing something:
function sumArray(a) {
return a.reduce((a, b) => a + b, 0)
}
function maxLength(a, i) {
let max = 0
let array = [a[0]]
a.splice(1, a.length).forEach(number => {
array.push(number)
if (sumArray(array) <= k) max = array.length
else array.splice(array.indexOf(Math.max.apply(null, array)), 1)
})
return max
}
Here's how I would do it.
First, we'll get the longest sub-array by taking only the smallest elements out of the original, because that way the sum will be smallest possible as we go along. So:
const original = [3, 1, 2, 1];
const maxsum = 4;
// To make sure we take only the smallest, let's just
// sort the array straight away. That way the smallest
// element will always be the first.
// The .slice call is to make a copy, so we don't change
// the original:
const sorted = original.slice().sort();
// Here's your sum function. Looks legit.
function sumArray(a) {
return a.reduce((a, b) => a + b, 0)
}
// Now take items from the front of the sorted array and
// put them in the new array until either the original is
// empty or the max is reached.
let subarray = [];
while (sorted.length) {
// Get the next smallest element. It's always the
// first one because of the sort.
const smallest = sorted.shift();
// If the sum of what we have plus this new element
// is bigger than the max, our work is done:
if (sumArray(subarray) + smallest > maxsum) break;
// Otherwise, add it to our sub array and continue.
subarray.push(smallest)
}
// Once that loop has run, either we ran out of elements,
// or we hit the max. Either way, our job is done.
console.log("Original array:", original);
console.log("Maximal subset:", subarray);
console.log("Maximal subset length:", subarray.length);
Finally, if you want to get fancy, you can even do this with a single .reduce call:
const original = [3, 1, 2, 1];
const maxsum = 4;
const maximalSubset = original.slice().sort().reduce((subset, current) => {
if (subset.reduce((s, c) => s + c, 0) + current <= maxsum) subset.push(current);
return subset;
}, []);
console.log("Orignal:", original);
console.log("Maximal subset:", maximalSubset);
console.log("Maximal subset length:", maximalSubset.length);
Although while shorter, that second snippet has the downside that we have to iterate the entire array before we get the result, whereas the first one will stop once the maximum is reached.
EDIT:
It turns out that the subarray needs to be a continuous piece of the original, so changing the order of the original won't work since we need to make sure the result is a continuous slice of the original.
To do that, instead, just check each subslice of the array, and keep the best one:
let original = [74,659,931,273,545,879,924,710,441,166,493,43,988,504,328,730,841,613,304,170,710,158,561,934,100,279,817,336,98,827,513,268,811,634,980,150,580,822,968,673,394,337,486,746,229,92,195,358,2,154,709,945,669,491,125,197,531,904,723,667,550];
const maxsum = 22337;
function arraySum(arr) {
return arr.reduce((p, c) => p + c, 0);
}
// Double for loop will do the trick.
let bestSoFar = [];
for (let i = 0; i < original.length; i++) {
for (let j = i+1; j < original.length; j++) {
if (j-i > bestSoFar.length && arraySum(original.slice(i, j)) < maxsum) {
bestSoFar = original.slice(i, j);
}
}
}
console.log("Longest continuous subarray is:", bestSoFar.length);
A brute force approach is likely the best solution to this problem. Start at each entry and see how far you can go before arriving at a sum > i and if it's better than the best you've seen so far save it. I provided a sample Java solution below, I haven't actually run it so one or two of my indices may be off but I think you can get the gist. Runtime is O(n^2), memory is O(n) (both occurring with, for example, #getMaxSubArray(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 1000000))
private int[] getMaxSubArray(int[] a, int i) {
int minIndex = 0;
int maxIndex = -1;
for (int j = 0; j < a.length; j+=1) {
if (a[j] > i) {
continue;
}
int sum = a[j];
for (int k = j + 1; k < a.length; k++) {
if (sum + a[k] > i) {
if ((k - 1) - j > maxIndex - minIndex) {
maxIndex = k - 1;
minIndex = j;
}
break;
}
sum += a[k];
}
}
if (maxIndex - minIndex < 0) {
return null;
}
int[] result = new int[maxIndex - minIndex + 1];
for (int p = minIndex; p <= maxIndex; p += 1) {
result[p - minIndex] = a[p];
}
return result;
}
This is my solution. It will return the max length of the subarray. Can you please take a look, guys?
function maxLength(a, k) {
const sortedArray = a.sort((i,j) => i - j);
let sum = 0;
let length = 0;
const subArray = [];
for (let i=0; i < sortedArray.length; i++) {
sum = sum + sortedArray[i];
if (sum <= k) {
length++;
subArray.push(sortedArray[i]);
} else {
return length;
}
}
return length;
}

what should be the correct Algorithm to Get Array B from Array A

Array A= [1,0,1,1,1,1,0,1,1]];
And the result will be B B=[1,0,4,3,2,1,0,2,1];
the elements of A is given and the result will be B.
Elements in A can only be 0 and 1.
we need to count backward from the last element in A, if there are consecutive 1's then the element in A and B will be 1 but for the 2nd consecutive 1 in A it will be 2 in be and for the 3rd one in A the element will be 3 in B
but for 0 it will be 0. I have tried the following way but I am not getting the output.
<script>
var A= [1,0,1,1,1,1,0,1,1]];
var B =[];
//var B= A.length;
var lastValueOne;
var consecutiveOnes = 0;
for (i = A.Length - 1; i >= 0; i--)
{
if ( lastValueOne== false)
{
consecutiveOnes = 0;
B[i] = 0;
}
else
{
consecutiveOnes++;
B[i] = consecutiveOnes;
}
if (A[i] == 1)
{
lastValueOne = true;
}
else
{
lastValueOne = false;
}
}
//console.log(B[i]);
document.getElementById("demo").innerHTML = B;
You could iterate the given array and map the value of the count if a truthy value is given at the actual index. Then iterate until a falsy value is found and return the count.
var array = [1, 0, 1, 1, 1, 1, 0, 1, 1],
result = array.map(function (_, i, a) { // take only index and array as parameter
var count = 0; // declare and initialize counter with zero
while(a[i++]) { // check value at actual index and inc index
count++; // increment counter while true/truthy
}
return count; // return count
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Moving the idea of le_m's answer a bit ahead without using a sum variable and using the first element of the result array r[0] for keeping the cumulative sum.
var array = [1, 0, 1, 1, 1, 1, 0, 1, 1],
result = array.reduceRight(function (r, a) {
return [a && (r[0] || 0) + a].concat(r);
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The more descriptive Array.reduceRight lends itself well to your task of computing cumulative sums from right to left.
// Return cumulative sums from right, reset on zero:
function cumSumRight(array, sum = 0) {
return array.reduceRight((result, a) => {
sum = a > 0 ? sum + a : 0;
result.unshift(sum);
return result;
}, []);
}
// Example:
console.log(cumSumRight([1,0,1,1,1,1,0,1,1])); // [1,0,4,3,2,1,0,2,1]
To fix your current solution, write A.length instead of A.Length. You can then simplify to:
let sum = 0;
for (let i = A.length - 1; i >= 0; i--) {
sum += A[i];
if (A[i] === 0) {
sum = 0;
}
B.unshift(sum);
}
You should only increment consecutiveOnes if last value was 1 AND the current value is also 1.
But the logic can be simplier, because when the last value is false, your consecutive value should also be 0.
var A= [1,0,1,1,1,1,0,1,1];
var B = [];
var consecutiveOnes = 0;
for (i = A.length - 1; i >= 0; i--)
{
if (A[i] == 1)
{
consecutiveOnes += 1;
}
else
{
consecutiveOnes = 0;
}
B[i] = consecutiveOnes;
}
console.log(B);

Pair of elements from a specified array whose sum equals a specific target number

I am in mid of my JavaScript session. Find this code in my coding exercise. I understand the logic but I didn't get this map[nums[x]] condition.
function twoSum(nums, target_num) {
var map = [];
var indexnum = [];
for (var x = 0; x < nums.length; x++)
{
if (map[nums[x]] != null)
// what they meant by map[nums[x]]
{
index = map[nums[x]];
indexnum[0] = index+1;
indexnum[1] = x+1;
break;
}
else
{
map[target_num - nums[x]] = x;
}
}
return indexnum;
}
console.log(twoSum([10,20,10,40,50,60,70],50));
I am trying to get the Pair of elements from a specified array whose sum equals a specific target number. I have written below code.
function arraypair(array,sum){
for (i = 0;i < array.length;i++) {
var first = array[i];
for (j = i + 1;j < array.length;j++) {
var second = array[j];
if ((first + second) == sum) {
alert('First: ' + first + ' Second ' + second + ' SUM ' + sum);
console.log('First: ' + first + ' Second ' + second);
}
}
}
}
var a = [2, 4, 3, 5, 6, -2, 4, 7, 8, 9];
arraypair(a,7);
Is there any optimized way than above two solutions? Can some one explain the first solution what exactly map[nums[x]] this condition points to?
Using HashMap approach using time complexity approx O(n),below is the following code:
let twoSum = (array, sum) => {
let hashMap = {},
results = []
for (let i = 0; i < array.length; i++){
if (hashMap[array[i]]){
results.push([hashMap[array[i]], array[i]])
}else{
hashMap[sum - array[i]] = array[i];
}
}
return results;
}
console.log(twoSum([10,20,10,40,50,60,70,30],50));
result:
{[10, 40],[20, 30]}
I think the code is self explanatory ,even if you want help to understand it,let me know.I will be happy enough to for its explanation.
Hope it helps..
that map value you're seeing is a lookup table and that twoSum method has implemented what's called Dynamic Programming
In Dynamic Programming, you store values of your computations which you can re-use later on to find the solution.
Lets investigate how it works to better understand it:
twoSum([10,20,40,50,60,70], 50)
//I removed one of the duplicate 10s to make the example simpler
In iteration 0:
value is 10. Our target number is 50. When I see the number 10 in index 0, I make a note that if I ever find a 40 (50 - 10 = 40) in this list, then I can find its pair in index 0.
So in our map, 40 points to 0.
In iteration 2:
value is 40. I look at map my map to see I previously found a pair for 40.
map[nums[x]] (which is the same as map[40]) will return 0.
That means I have a pair for 40 at index 0.
0 and 2 make a pair.
Does that make any sense now?
Unlike in your solution where you have 2 nested loops, you can store previously computed values. This will save you processing time, but waste more space in the memory (because the lookup table will be needing the memory)
Also since you're writing this in javascript, your map can be an object instead of an array. It'll also make debugging a lot easier ;)
function twoSum(arr, S) {
const sum = [];
for(let i = 0; i< arr.length; i++) {
for(let j = i+1; j < arr.length; j++) {
if(S == arr[i] + arr[j]) sum.push([arr[i],arr[j]])
}
}
return sum
}
Brute Force not best way to solve but it works.
Please try the below code. It will give you all the unique pairs whose sum will be equal to the targetSum. It performs the binary search so will be better in performance. The time complexity of this solution is O(NLogN)
((arr,targetSum) => {
if ((arr && arr.length === 0) || targetSum === undefined) {
return false;
} else {
for (let x = 0; x <=arr.length -1; x++) {
let partnerInPair = targetSum - arr[x];
let start = x+1;
let end = (arr.length) - 2;
while(start <= end) {
let mid = parseInt(((start + end)/2));
if (arr[mid] === partnerInPair) {
console.log(`Pairs are ${arr[x]} and ${arr[mid]} `);
break;
} else if(partnerInPair < arr[mid]) {
end = mid - 1;
} else if(partnerInPair > arr[mid]) {
start = mid + 1;
}
}
};
};
})([0,1,2,3,4,5,6,7,8,9], 10)
function twoSum(arr, target) {
let res = [];
let indexes = [];
for (let i = 0; i < arr.length - 1; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (target === arr[i] + arr[j] && !indexes.includes(i) && !indexes.includes(j)) {
res.push([arr[i], arr[j]]);
indexes.push(i);
indexes.push(j);
}
}
}
return res;
}
console.log('Result - ',
twoSum([1,2,3,4,5,6,6,6,6,6,6,6,6,6,7,8,9,10], 12)
);
Brute force.
const findTwoNum = ((arr, value) => {
let result = [];
for(let i= 0; i< arr.length-1; i++) {
if(arr[i] > value) {
continue;
}
if(arr.includes(value-arr[i])) {
result.push(arr[i]);
result.push(value-arr[i]);
break;;
}
}
return result;
});
let arr = [20,10,40,50,60,70,30];
const value = 120;
console.log(findTwoNum(arr, value));
OUTPUT : Array [50, 70]
function twoSum(arr){
let constant = 17;
for(let i=0;i<arr.length-2;i++){
for(let j=i+1;j<arr.length;j++){
if(arr[i]+arr[j] === constant){
console.log(arr[i],arr[j]);
}
}
}
}
let myArr = [2, 4, 3, 5, 7, 8, 9];
function getPair(arr, targetNum) {
for (let i = 0; i < arr.length; i++) {
let cNum = arr[i]; //my current number
for (let j = i; j < arr.length; j++) {
if (cNum !== arr[j] && cNum + arr[j] === targetNum) {
let pair = {};
pair.key1 = cNum;
pair.key2 = arr[j];
console.log(pair);
}
}
}
}
getPair(myArr, 7)
let sumArray = (arr,target) => {
let ar = []
arr.forEach((element,index) => {
console.log(index);
arr.forEach((element2, index2) => {
if( (index2 > index) && (element + element2 == target)){
ar.push({element, element2})
}
});
});
return ar
}
console.log(sumArray([8, 7, 2, 5, 3, 1],10))
Use {} hash object for storing and fast lookups.
Use simple for loop so you can return as soon as you find the right combo; array methods like .forEach() have to finish iterating no matter what.
And make sure you handle edges cases like this: twoSum([1,2,3,4], 8)---that should return undefined, but if you don't check for !== i (see below), you would erroneously return [4,4]. Think about why that is...
function twoSum(nums, target) {
const lookup = {};
for (let i = 0; i < nums.length; i++) {
const n = nums[i];
if (lookup[n] === undefined) {//lookup n; seen it before?
lookup[n] = i; //no, so add to dictionary with index as value
}
//seen target - n before? if so, is it different than n?
if (lookup[target - n] !== undefined && lookup[target - n] !== i) {
return [target - n, n];//yep, so we return our answer!
}
}
return undefined;//didn't find anything, so return undefined
}
We can fix this with simple JS object as well.
const twoSum = (arr, num) => {
let obj = {};
let res = [];
arr.map(item => {
let com = num - item;
if (obj[com]) {
res.push([obj[com], item]);
} else {
obj[item] = item;
}
});
return res;
};
console.log(twoSum([2, 3, 2, 5, 4, 9, 6, 8, 8, 7], 10));
// Output: [ [ 4, 6 ], [ 2, 8 ], [ 2, 8 ], [ 3, 7 ] ]
Solution In Java
Solution 1
public static int[] twoNumberSum(int[] array, int targetSum) {
for(int i=0;i<array.length;i++){
int first=array[i];
for(int j=i+1;j<array.length;j++){
int second=array[j];
if(first+second==targetSum){
return new int[]{first,second};
}
}
}
return new int[0];
}
Solution 2
public static int[] twoNumberSum(int[] array, int targetSum) {
Set<Integer> nums=new HashSet<Integer>();
for(int num:array){
int pmatch=targetSum-num;
if(nums.contains(pmatch)){
return new int[]{pmatch,num};
}else{
nums.add(num);
}
}
return new int[0];
}
Solution 3
public static int[] twoNumberSum(int[] array, int targetSum) {
Arrays.sort(array);
int left=0;
int right=array.length-1;
while(left<right){
int currentSum=array[left]+array[right];
if(currentSum==targetSum){
return new int[]{array[left],array[right]};
}else if(currentSum<targetSum){
left++;
}else if(currentSum>targetSum){
right--;
}
}
return new int[0];
}
function findPairOfNumbers(arr, targetSum) {
var low = 0, high = arr.length - 1, sum, result = [];
while(low < high) {
sum = arr[low] + arr[high];
if(sum < targetSum)
low++;
else if(sum > targetSum)
high--;
else if(sum === targetSum) {
result.push({val1: arr[low], val2: arr[high]});
high--;
}
}
return (result || false);
}
var pairs = findPairOfNumbers([1,2,3,4,4,5], 8);
if(pairs.length) {
console.log(pairs);
} else {
console.log("No pair of numbers found that sums to " + 8);
}
Simple Solution would be in javascript is:
var arr = [7,5,10,-5,9,14,45,77,5,3];
var arrLen = arr.length;
var sum = 15;
function findSumOfArrayInGiven (arr, arrLen, sum){
var left = 0;
var right = arrLen - 1;
// Sort Array in Ascending Order
arr = arr.sort(function(a, b) {
return a - b;
})
// Iterate Over
while(left < right){
if(arr[left] + arr[right] === sum){
return {
res : true,
matchNum: arr[left] + ' + ' + arr[right]
};
}else if(arr[left] + arr[right] < sum){
left++;
}else{
right--;
}
}
return 0;
}
var resp = findSumOfArrayInGiven (arr, arrLen, sum);
// Display Desired output
if(resp.res === true){
console.log('Matching Numbers are: ' + resp.matchNum +' = '+ sum);
}else{
console.log('There are no matching numbers of given sum');
}
Runtime test JSBin: https://jsbin.com/vuhitudebi/edit?js,console
Runtime test JSFiddle: https://jsfiddle.net/arbaazshaikh919/de0amjxt/4/
function sumOfTwo(array, sumNumber) {
for (i of array) {
for (j of array) {
if (i + j === sumNumber) {
console.log([i, j])
}
}
}
}
sumOfTwo([1, 2, 3], 4)
function twoSum(args , total) {
let obj = [];
let a = args.length;
for(let i = 0 ; i < a ; i++){
for(let j = 0; j < a ; j++){
if(args[i] + args[j] == total) {
obj.push([args[i] , args[j]])
}
}
}
console.log(obj)}
twoSum([10,20,10,40,50,60,70,30],60);
/* */

JavaScript recursive loop to sum all integers from nested array

arr will be an array, containing integers, strings and/or arrays like itself. Sum all the integers you find, anywhere in the nest of arrays.
This is what I came up with, but still not right yet
function arraySum(arr) {
var sum = 0;
var sum1 = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] === Math.round(arr[i])) { //check if its an integar
sum += arr[i];
}
if (arr[i] instanceof Array) {
for (var n = 0; n < arr[i].length; n++) {
sum1 += arr[i][n];
}
}
}
console.log(sum + sum1);
}
var sumArr = [[[[[[[[[1]]]]]]]], 1]; // => 101. SHOULD BE 2
arraySum(sumArr);
function arraySum(arr) {
var sum = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] instanceof Array) { sum += arraySum(arr[i]);}
if (arr[i] === Math.round(arr[i])) {sum += arr[i];}
}
return sum;
}
What about using reduce recursively?
function arrSum(arr) {
return arr.reduce(function fn(a, b) {
if (Array.isArray(b)) {
return b.reduce(fn, a);
} else if (b === Math.round(b)) {
return a + b;
}
return a;
}, 0);
}
The reduce() method applies a function against an accumulator and each
value of the array (from left-to-right) has to reduce it to a single
value.
function add(array){
return(array+"").match(/-?\d+(?:\.\d+)?/g).reduce(function(a,b) {
return +a+ +b;
});
}
That uses regex to parse a stringified array but it should work just fine.
So then there'll be an array with only the numbers. Those get parsed into a .reduce() which adds them. The best I could think of :)
help from: mdn
function add(n){return JSON.stringify(n).match(/[^\D]+/g).reduce(function(n,r){return 1*n+1*r})} is what came out of http://jscompress.com
SPEED: 0.04395800351630896s
Either 11% faster than other answers, or my Math's terrible
A more supported answer:
function add (array) {
var nums = JSON.stringify(array).match(/[\d\-]+/g),
i,
sum = 0;
for (i = 0; i < nums.length; i += 1) {
sum += parseInt(nums[i], 10);
}
return sum;
}
You can solve this using recursive functions, try with something like this:
function arraySum(arr) {
var sum = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] === Math.round(arr[i])) {
sum += arr[i];
}
if (arr[i] instanceof Array) {
sum += arraySum(arr[i]); //This will apply the same function to the current Array element which is an Array
}
}
return sum; //To have the sum of the actual Array
}
var sumArr = [[[[[[[[[1]]]]]]]], 1];
console.log(arraySum(sumArr)); //now it returns 2
Try this :
function arraySum(arr) {
return arr.reduce(function(s, n) {
return s + ((n instanceof Array) ? arraySum(n) : +n || 0);
}, 0);
}
+n attempts to convert strings to integers, defaulting to zero if +n yields NaN.
http://jsfiddle.net/3z7pakfx/
Here is a solution that doesn't rely on iteration:
var arraySum = function(array) {
if (array.length === 0) {
return 0;
}
var rest = array.slice();
var next = rest.pop();
if (next instanceof Array) {
return arraySum(next) + arraySum(rest);
} else {
return next + arraySum(rest);
}
};
The sum of any value, v, and more values is -
If we do not have a value, v, return the empty sum, 0
By induction, we have a value, v. If the value is an array, return the sum of v plus the sum of more
By induction, we have a value v that is not an array. Return the numeric value of v plus the sum of more
const sum = ([ v, ...more ]) =>
v === undefined
? 0 // 1
: Array.isArray(v)
? sum(v) + sum(more) // 2
: Number(v) + sum(more) // 3
const result =
sum([[[[[[[[[1]]]]]]]], 1])
console.log(result)
// 2

Categories

Resources