Last active
August 23, 2021 17:16
-
-
Save kopiro/5db16bbfd19346452fd4d7bcd4f13173 to your computer and use it in GitHub Desktop.
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
/** | |
* Helper to sum an array | |
*/ | |
function sum(array) { | |
return array.reduce((carry, e) => (carry += e), 0); | |
} | |
/** | |
* This procedure will build all possible combinations of K elements by making sure we never go into the | |
* branches where the sum of the sub-list is greater than T. | |
*/ | |
function procedureIterate(combinations, list, t, k, carry = [], currentIndex) { | |
// If by adding this new element (+1) we have more than K elements, this means this entire function should not run | |
if (carry.length + 1 > k) { | |
return; | |
} | |
// We built our new sub-list by combining our incoming list and the element at the currentIndex | |
carry = [...carry, list[currentIndex]]; | |
const s = sum(carry); | |
// Note that the built sub-list can be at any size, we discard it no matter when sum has reached the end. | |
if (s > t) { | |
return; | |
} | |
// At this point, 2 things can happen: we either reached the maximum length of the sublist | |
// or we should continue building it | |
if (carry.length === k) { | |
// This combinations will only contain valid values | |
combinations.push([carry, s]); | |
} | |
// This is the core of the recursive function: what you want to do is try all possible "increments" starting from a | |
// point in the sublist; For example, in the list [1,2,3,4,5]; when the sublist contains [1] with k=3, you wanna | |
// try the "increments" (1, 2, 3) that gives you the sublist [1,2,3], [1,3,4], [1,2,5] | |
// therefore, all possible increments (note: for this sublist) | |
// are from 1 to list.length - our current index in the main list | |
for (let increment = 1; increment < list.length - currentIndex; increment++) { | |
// And here we just pass all the variables, the MODIFIED carry containing the NEW sublist and... | |
// the new element to process, that it will be at: currentIndex + increment | |
procedureIterate(combinations, list, t, k, carry, currentIndex + increment); | |
} | |
} | |
function chooseBestSum(t, k, ls) { | |
// This array will contain all possible VALID combs | |
const combinations = []; | |
// We loop the entire list and chose a start point by selecting the (i) item in the list | |
for (let currentIndex = 0; currentIndex < ls.length + 1 - k; currentIndex++) { | |
procedureIterate(combinations, ls, t, k, [], currentIndex); | |
} | |
// We sort the valid combinations based on the total distance and that will give us the candidate | |
combinations.sort((a, b) => b[1] - a[1]); | |
return combinations.length ? combinations[0][1] : null; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment