Skip to content

Instantly share code, notes, and snippets.

@kopiro
Last active August 23, 2021 17:16
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 kopiro/5db16bbfd19346452fd4d7bcd4f13173 to your computer and use it in GitHub Desktop.
Save kopiro/5db16bbfd19346452fd4d7bcd4f13173 to your computer and use it in GitHub Desktop.
/**
* 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