Last active
December 19, 2015 14:59
-
-
Save istro/5973617 to your computer and use it in GitHub Desktop.
The challenge: Given an array of integers, find the largest possible sum of consecutive elements of that array. Example: For array [3, -4, 8, -2, -1, 20] the output should be 25, because 8+(-2)+(-1)+20 Live version can be found on codepen - http://codepen.io/istro/pen/qEesB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// To break down the problem for myself better, I like to write some tests. | |
var test = function(){ | |
// Array contains only negative integers -> result is the single largest element | |
if(findSum([-14, -5, -22]) != -5 && findSum([-3, -23, -1]) != -1){ | |
alert('First test case fails.'); | |
return false; | |
} | |
// Array contains only positive integers -> result is the sum of all elements | |
if(findSum([1, 2, 3]) != 6 && findSum([5, 6]) != 11){ | |
alert('Second test case fails.'); | |
return false; | |
} | |
// Array contains a mixture of both. | |
if(findSum([-1, 3, -2, -20, 4]) != 4 && findSum([3, -2, 6, 4, -6]) != 11){ | |
alert('Third test case fails.'); | |
return false; | |
} | |
alert('Yay! tests pass!'); | |
return true; | |
}; | |
var findSum = function(array){ | |
// For the first test case, I have to ensure the array only has negative numbers. | |
// Why not sort it, non-destructively. | |
var arrCopy = array.slice(); | |
arrCopy.sort(function(a, b){ return b-a }); | |
if(arrCopy[0]<0) | |
return arrCopy[0]; | |
// Sorted array comes handy for the second test case, too: | |
var sum = 0; | |
if(arrCopy[arrCopy.length-1]>0){ | |
$.each(array, function(index, value){ | |
sum += value; | |
}); | |
return sum; | |
}; | |
// Cool. For the third case, I don't care about consecutive positives or consecutive negatives - | |
// they're just as good as the sum of them. So I'll make sure I don't have any repetition going on. | |
// start the short array with first element of the input array | |
var shortie = [array[0]]; | |
for(i=1; i<array.length; i++){ | |
var shortiesLast = shortie[shortie.length-1]; | |
// compare next element's sign (positive/negative), if they match - just add it to last element, | |
// if not - add as a new element | |
if(array[i]>0 && shortiesLast>0 || array[i]<0 && shortiesLast<0){ | |
shortie[shortie.length-1] = shortiesLast+array[i]; | |
}else{ | |
shortie.push(array[i]); | |
} | |
} | |
// also, if my shortened array starts or ends with the negative number - i don't care about it: | |
if(shortie[shortie.length-1]<0) | |
shortie.pop(); | |
if(shortie[0]<0) | |
shortie.shift(); | |
// Cool, shortie is now an array with alternating signs. It only makes sense to include negative | |
// numbers in the sum if both positive numbers are larger than the one they surround, | |
// e.g. [2, -10, 400] shouldn't get summed up while [20, -19, 21] should. | |
// I can iterate over that array in bigger steps - and create sums of all | |
// reasonable 'chunks' of the array, like so: | |
var sums = [shortie[0]]; | |
for(i=1; i<shortie.length; i+=2){ | |
var ohSoNegative = Math.abs(shortie[i]); | |
if(ohSoNegative<shortie[i-1] && ohSoNegative<shortie[i+1]){ | |
sums[sums.length-1] += (shortie[i] + shortie[i+1]); | |
}else{ | |
sums.push(shortie[i+1]); | |
}; | |
} | |
// All that's left is return the largest sum. | |
sums.sort(function(a, b){ return b-a }); | |
return sums[0]; | |
} | |
test(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment