Skip to content

Instantly share code, notes, and snippets.

@ceautery
Last active May 21, 2017 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ceautery/a7a6bf698333d7b9714c9b77ff99a308 to your computer and use it in GitHub Desktop.
Save ceautery/a7a6bf698333d7b9714c9b77ff99a308 to your computer and use it in GitHub Desktop.
Solution to the https://www.freecodecamp.com/challenges/pairwise with lengthy explanation
/*
* 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