From d8acfbd56b85237db64f7a9581e6991dabf7df34 Mon Sep 17 00:00:00 2001 From: Suaze9 Date: Thu, 30 Sep 2021 21:49:50 -0600 Subject: [PATCH 1/5] sum of subset algorithm --- Backtracking/SumOfSubset.js | 75 +++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Backtracking/SumOfSubset.js diff --git a/Backtracking/SumOfSubset.js b/Backtracking/SumOfSubset.js new file mode 100644 index 0000000000..58b60ad0d4 --- /dev/null +++ b/Backtracking/SumOfSubset.js @@ -0,0 +1,75 @@ +/* + * + * Sum of Subset problem + * + * Given an ordered set W of non-negative integers and a value K, + * determine all possible subsets from the given set W whose sum + * of its elemets equals to the given value K. + * + */ + +/* + * @param {number[]} set Original set of numbers + * @param {number[]} subset Subset being evaluated + * @param {number} setIndex Index from set of last element in subset + * @param {sum} Sum of elements from subset + * @param {targetSum} The target sum on which the subset sum is compared to + */ +const subsetSum = (set, subset, setindex, sum, targetSum) => { + // Base case where the subset sum is equal to target sum + // Evaluation of following subsets on this path will always add up to + // greater than targetSum, so no need to continue + if (sum === targetSum) return [subset]; + + // This and following subsets on this path will always add up to + // greater than targetSum, so no need to continue + if (sum > targetSum) return []; + + // Initialize results array. Will contain only valid subsets + let results = []; + + // Slice gets from the set all the elements at the right of the last element + // to be evaluated (last element of subset) + // forEach iterated on the resulting array + set.slice(setindex).forEach((num, index) => { + // The next subset to be evaluated, current subset plus next element + const nextSubset = [...subset, num]; + + // Next index from the set. Current set index plus iteration index + // index starts at 0, so a + 1 is required + const nextSetIndex = setindex + index + 1; + + // Sum of elements from the next subset to be evaluated + const nextSum = sum + num; + + // Call recursively the subsetSum for the nextSubset + const subsetResult = subsetSum( + set, + nextSubset, + nextSetIndex, + nextSum, + targetSum + ); + + // Concat the recursive result with current result arary + results = [...results, ...subsetResult]; + }); + + //Return results + return results; + }; + + /* + * Example with ordered array + * W = [2, 5, 7, 8, 12, 16, 23, 40] + * K = 25 + * + * resulting subsets = [ 2, 7, 16 ], [ 2, 23 ], [ 5, 8, 12 ] + */ + + const nums = [2, 5, 7, 8, 12, 16, 23, 40]; + + const subsets = subsetSum(nums, [], 0, 0, 25); + + console.log(subsets); + \ No newline at end of file From 6f966bcad431f2d47e20a74e8505340daf7b8187 Mon Sep 17 00:00:00 2001 From: Suaze9 Date: Thu, 30 Sep 2021 21:54:37 -0600 Subject: [PATCH 2/5] set returns comment --- Backtracking/SumOfSubset.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Backtracking/SumOfSubset.js b/Backtracking/SumOfSubset.js index 58b60ad0d4..5dea80dc1b 100644 --- a/Backtracking/SumOfSubset.js +++ b/Backtracking/SumOfSubset.js @@ -14,6 +14,7 @@ * @param {number} setIndex Index from set of last element in subset * @param {sum} Sum of elements from subset * @param {targetSum} The target sum on which the subset sum is compared to + * @returns {number[][]} Subsets whose elements add up to targetSum */ const subsetSum = (set, subset, setindex, sum, targetSum) => { // Base case where the subset sum is equal to target sum From c3a92143b6bc71b913c0bb0e6d95c3143687b033 Mon Sep 17 00:00:00 2001 From: Suaze9 Date: Thu, 30 Sep 2021 21:55:39 -0600 Subject: [PATCH 3/5] fix comment --- Backtracking/SumOfSubset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Backtracking/SumOfSubset.js b/Backtracking/SumOfSubset.js index 5dea80dc1b..66d3219f0b 100644 --- a/Backtracking/SumOfSubset.js +++ b/Backtracking/SumOfSubset.js @@ -12,7 +12,7 @@ * @param {number[]} set Original set of numbers * @param {number[]} subset Subset being evaluated * @param {number} setIndex Index from set of last element in subset - * @param {sum} Sum of elements from subset + * @param {number} Sum of elements from subset * @param {targetSum} The target sum on which the subset sum is compared to * @returns {number[][]} Subsets whose elements add up to targetSum */ From 9d9ccd3483f02981097e3f66ed790fe14263ebbc Mon Sep 17 00:00:00 2001 From: Suaze9 Date: Thu, 30 Sep 2021 21:58:33 -0600 Subject: [PATCH 4/5] add resource url to comments --- Backtracking/SumOfSubset.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Backtracking/SumOfSubset.js b/Backtracking/SumOfSubset.js index 66d3219f0b..3ab8720064 100644 --- a/Backtracking/SumOfSubset.js +++ b/Backtracking/SumOfSubset.js @@ -6,6 +6,7 @@ * determine all possible subsets from the given set W whose sum * of its elemets equals to the given value K. * + * More info: https://www.geeksforgeeks.org/subset-sum-backtracking-4/ */ /* From c77b646fbde0174d5b13e985bba39f61611edc8d Mon Sep 17 00:00:00 2001 From: Suaze9 Date: Thu, 30 Sep 2021 22:42:50 -0600 Subject: [PATCH 5/5] separate test to different file and format --- Backtracking/SumOfSubset.js | 103 +++++++++++-------------- Backtracking/tests/SumOfSubset.test.js | 18 +++++ 2 files changed, 63 insertions(+), 58 deletions(-) create mode 100644 Backtracking/tests/SumOfSubset.test.js diff --git a/Backtracking/SumOfSubset.js b/Backtracking/SumOfSubset.js index 3ab8720064..16573e5fab 100644 --- a/Backtracking/SumOfSubset.js +++ b/Backtracking/SumOfSubset.js @@ -17,61 +17,48 @@ * @param {targetSum} The target sum on which the subset sum is compared to * @returns {number[][]} Subsets whose elements add up to targetSum */ -const subsetSum = (set, subset, setindex, sum, targetSum) => { - // Base case where the subset sum is equal to target sum - // Evaluation of following subsets on this path will always add up to - // greater than targetSum, so no need to continue - if (sum === targetSum) return [subset]; - - // This and following subsets on this path will always add up to - // greater than targetSum, so no need to continue - if (sum > targetSum) return []; - - // Initialize results array. Will contain only valid subsets - let results = []; - - // Slice gets from the set all the elements at the right of the last element - // to be evaluated (last element of subset) - // forEach iterated on the resulting array - set.slice(setindex).forEach((num, index) => { - // The next subset to be evaluated, current subset plus next element - const nextSubset = [...subset, num]; - - // Next index from the set. Current set index plus iteration index - // index starts at 0, so a + 1 is required - const nextSetIndex = setindex + index + 1; - - // Sum of elements from the next subset to be evaluated - const nextSum = sum + num; - - // Call recursively the subsetSum for the nextSubset - const subsetResult = subsetSum( - set, - nextSubset, - nextSetIndex, - nextSum, - targetSum - ); - - // Concat the recursive result with current result arary - results = [...results, ...subsetResult]; - }); - - //Return results - return results; - }; - - /* - * Example with ordered array - * W = [2, 5, 7, 8, 12, 16, 23, 40] - * K = 25 - * - * resulting subsets = [ 2, 7, 16 ], [ 2, 23 ], [ 5, 8, 12 ] - */ - - const nums = [2, 5, 7, 8, 12, 16, 23, 40]; - - const subsets = subsetSum(nums, [], 0, 0, 25); - - console.log(subsets); - \ No newline at end of file +const sumOfSubset = (set, subset, setindex, sum, targetSum) => { + // Base case where the subset sum is equal to target sum + // Evaluation of following subsets on this path will always add up to + // greater than targetSum, so no need to continue + if (sum === targetSum) return [subset] + + // This and following subsets on this path will always add up to + // greater than targetSum, so no need to continue + if (sum > targetSum) return [] + + // Initialize results array. Will contain only valid subsets + let results = [] + + // Slice gets from the set all the elements at the right of the last element + // to be evaluated (last element of subset) + // forEach iterated on the resulting array + set.slice(setindex).forEach((num, index) => { + // The next subset to be evaluated, current subset plus next element + const nextSubset = [...subset, num] + + // Next index from the set. Current set index plus iteration index + // index starts at 0, so a + 1 is required + const nextSetIndex = setindex + index + 1 + + // Sum of elements from the next subset to be evaluated + const nextSum = sum + num + + // Call recursively the sumOfSubset for the nextSubset + const subsetResult = sumOfSubset( + set, + nextSubset, + nextSetIndex, + nextSum, + targetSum + ) + + // Concat the recursive result with current result arary + results = [...results, ...subsetResult] + }) + + // Return results + return results +} + +export { sumOfSubset } diff --git a/Backtracking/tests/SumOfSubset.test.js b/Backtracking/tests/SumOfSubset.test.js new file mode 100644 index 0000000000..07a70c704b --- /dev/null +++ b/Backtracking/tests/SumOfSubset.test.js @@ -0,0 +1,18 @@ +import { sumOfSubset } from '../SumOfSubset' + +describe('SumOfSubset', () => { + it('should return the subsets that add up to the given number', () => { + // W = [2, 5, 7, 8, 12, 16, 23, 40] + // K = 25 + + const nums = [2, 5, 7, 8, 12, 16, 23, 40] + + const subsets = sumOfSubset(nums, [], 0, 0, 25) + + expect(subsets).toEqual([ + [2, 7, 16], + [2, 23], + [5, 8, 12] + ]) + }) +})