Last active
May 21, 2017 14:07
-
-
Save ceautery/a7a6bf698333d7b9714c9b77ff99a308 to your computer and use it in GitHub Desktop.
Solution to the https://www.freecodecamp.com/challenges/pairwise with lengthy explanation
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
/* | |
* pairwise takes an array of numbers and a target number as arguments, and | |
* searches for pairs of array elements that sum to the target number. It sums | |
* the indices of each pair that add to the target, and returns that sum. | |
* | |
* Caveats: | |
* - Each index can only be used once | |
* - Given a choice between two indices that can pair to the target, the | |
* lowest index should be used. For example, passing ([5, 6, 6], 11) to | |
* pairwise, the resulting sum should be 1, since index 0 (the 5) and | |
* index 1 (the first 6) should be used. | |
* - If multiple pair matches are found, all the sums of their indices should | |
* be used. E.g., ([5, 6, 7, 4], 11) should return 6, since indices 0 and 1, | |
* as well as 2 and 3, both sum to 11 | |
*/ | |
function pairwise(arr, arg) { | |
// callback is the sumPairwiseIndices function with arg bound to "this". | |
// Since sumPairwiseIndices is not a closure (nested function) of pairwise, | |
// it would otherwise not have access to arg, which would not be in scope. | |
var callback = sumPairwiseIndices.bind(arg); | |
// Using slice() here will prevent the original values in arr from being | |
// altered, since our reduce callback will be setting array values to NaN | |
// when a match is found. | |
return arr.slice().reduce(callback, 0); | |
} | |
/* | |
* sumPairwiseIndices should be called in a reduce context with the second | |
* argument (initial accumulator value) set to 0. It's "this" variable should | |
* be bound to the target number that pairs will sum to. | |
* | |
* On each pass, it will search for the first index *after* the current array | |
* position that sums with the current element to make the target value. When | |
* a match is found, the current and counterpart element's indices are added | |
* to the accumulator, and the counterpart element's value is set to NaN (not | |
* a number) to prevent it from being used again in another match. | |
* | |
* NaN helps this function in two ways: | |
* - "this - NaN" will always return NaN | |
* - Array.prototype.indexOf(NaN) will never find a match | |
*/ | |
function sumPairwiseIndices(accumulator, element, index, array) { | |
var counterpart = array.indexOf(this - element, index + 1); | |
if (counterpart > -1) { | |
array[counterpart] = NaN; | |
accumulator += index + counterpart; | |
} | |
return accumulator; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment