From 26d9599d0afe9f760d1d72a8c9f8fe343b3e7140 Mon Sep 17 00:00:00 2001 From: vedas-dixit Date: Thu, 26 Oct 2023 15:08:59 +0530 Subject: [PATCH 01/17] Add Tug of War solution using backtracking --- Backtracking/TugOfWar.js | 49 +++++++++++++++++++++++++++++ Backtracking/tests/TugOfWar.test.js | 11 +++++++ 2 files changed, 60 insertions(+) create mode 100644 Backtracking/TugOfWar.js create mode 100644 Backtracking/tests/TugOfWar.test.js diff --git a/Backtracking/TugOfWar.js b/Backtracking/TugOfWar.js new file mode 100644 index 0000000000..e3eea5c198 --- /dev/null +++ b/Backtracking/TugOfWar.js @@ -0,0 +1,49 @@ +// Given an array of n integers, we need to divide them into two subsets such that +// the difference between their sums is minimized. + + +/** + * @param {number[]} arr - The array of integers. + * @returns {Array.} Two subsets with minimized sum difference. + */ + + +function tugOfWar(arr) { + const n = arr.length; + let totalSum = arr.reduce((a, b) => a + b, 0); + let minimumDiff = Number.MAX_VALUE; + let result = []; + + function isSafe(index, subset) { + return index < n; + } + + function backtrack(subset = [], index = 0) { + if (index === n) { + const currentSubsetSum = subset.reduce((a, b) => a + b, 0); + const otherSubsetSum = totalSum - currentSubsetSum; + const currentDiff = Math.abs(currentSubsetSum - otherSubsetSum); + + if (currentDiff < minimumDiff) { + minimumDiff = currentDiff; + result = [subset, arr.filter(x => !subset.includes(x))]; + } + return; + } + + // Include the current element. + if (isSafe(index, subset)) { + backtrack([...subset, arr[index]], index + 1); + } + + // Exclude the current element. + if (isSafe(index, subset)) { + backtrack([...subset], index + 1); + } + } + + backtrack(); + return result; +} + +export { tugOfWar }; diff --git a/Backtracking/tests/TugOfWar.test.js b/Backtracking/tests/TugOfWar.test.js new file mode 100644 index 0000000000..04e332e869 --- /dev/null +++ b/Backtracking/tests/TugOfWar.test.js @@ -0,0 +1,11 @@ +import { tugOfWar } from '../TugOfWar'; + +describe('tugOfWar', () => { + it('should divide array into two subsets with minimized sum difference', () => { + const arr = [3, 4, 5, -3, 100, 1, 89, 54, 23, 20]; + const [subset1, subset2] = tugOfWar(arr); + const diff = Math.abs(subset1.reduce((a, b) => a + b, 0) - subset2.reduce((a, b) => a + b, 0)); + + expect(diff).toBeLessThanOrEqual(1); // Here we assume that the difference could be 0 or 1 for this test case. + }); +}); From 35700346d87ff37f42de73dca32c89d492964219 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 26 Oct 2023 09:41:52 +0000 Subject: [PATCH 02/17] Updated Documentation in README.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 61fa501119..a91f9fc39f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -8,6 +8,7 @@ * [RatInAMaze](Backtracking/RatInAMaze.js) * [Sudoku](Backtracking/Sudoku.js) * [SumOfSubset](Backtracking/SumOfSubset.js) + * [TugOfWar](Backtracking/TugOfWar.js) * **Bit-Manipulation** * [BinaryCountSetBits](Bit-Manipulation/BinaryCountSetBits.js) * [GrayCodes](Bit-Manipulation/GrayCodes.js) From 786954bbbc829eba0c636f566d35490c86f7a2a8 Mon Sep 17 00:00:00 2001 From: vedas-dixit Date: Thu, 26 Oct 2023 15:16:34 +0530 Subject: [PATCH 03/17] Added Tug of war problem link --- Backtracking/TugOfWar.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Backtracking/TugOfWar.js b/Backtracking/TugOfWar.js index e3eea5c198..d3703c4c86 100644 --- a/Backtracking/TugOfWar.js +++ b/Backtracking/TugOfWar.js @@ -1,7 +1,8 @@ +// https://www.geeksforgeeks.org/tug-of-war/ + // Given an array of n integers, we need to divide them into two subsets such that // the difference between their sums is minimized. - /** * @param {number[]} arr - The array of integers. * @returns {Array.} Two subsets with minimized sum difference. From dcf5c2c994d8a80dbc31b2547fb9dc59b5f6816a Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Thu, 26 Oct 2023 15:05:02 +0000 Subject: [PATCH 04/17] Updated Documentation in README.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index a91f9fc39f..aa539befd0 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -11,6 +11,7 @@ * [TugOfWar](Backtracking/TugOfWar.js) * **Bit-Manipulation** * [BinaryCountSetBits](Bit-Manipulation/BinaryCountSetBits.js) + * [GenerateSubSets](Bit-Manipulation/GenerateSubSets.js) * [GrayCodes](Bit-Manipulation/GrayCodes.js) * [IsPowerofFour](Bit-Manipulation/IsPowerofFour.js) * [IsPowerOfTwo](Bit-Manipulation/IsPowerOfTwo.js) From 7c7c78e1d5c8afc6c222701c9c5817e570702fbc Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Mon, 30 Oct 2023 07:52:13 +0000 Subject: [PATCH 05/17] Updated Documentation in README.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index a8fdca4e09..12b00428b1 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -161,6 +161,7 @@ * [NumberOfIslands](Graphs/NumberOfIslands.js) * [PrimMST](Graphs/PrimMST.js) * **Hashes** + * [MD5](Hashes/MD5.js) * [SHA1](Hashes/SHA1.js) * [SHA256](Hashes/SHA256.js) * **Maths** From 93c54dd252f38adc41ae8cfd7dab5e0d055775f4 Mon Sep 17 00:00:00 2001 From: vedas-dixit Date: Mon, 30 Oct 2023 13:31:42 +0530 Subject: [PATCH 06/17] Refactor tugOfWar: remove unused vars, optimize initialization, and remove redundant checks --- {Backtracking => Recursive}/TugOfWar.js | 35 ++++++------------- .../tests => Recursive/test}/TugOfWar.test.js | 8 +++-- 2 files changed, 15 insertions(+), 28 deletions(-) rename {Backtracking => Recursive}/TugOfWar.js (53%) rename {Backtracking/tests => Recursive/test}/TugOfWar.test.js (64%) diff --git a/Backtracking/TugOfWar.js b/Recursive/TugOfWar.js similarity index 53% rename from Backtracking/TugOfWar.js rename to Recursive/TugOfWar.js index d3703c4c86..e3460f54c4 100644 --- a/Backtracking/TugOfWar.js +++ b/Recursive/TugOfWar.js @@ -1,26 +1,17 @@ -// https://www.geeksforgeeks.org/tug-of-war/ - -// Given an array of n integers, we need to divide them into two subsets such that -// the difference between their sums is minimized. - /** + * @see https://www.geeksforgeeks.org/tug-of-war/ + * Divides the given array into two subsets such that the difference between their sums is minimized. * @param {number[]} arr - The array of integers. * @returns {Array.} Two subsets with minimized sum difference. */ - function tugOfWar(arr) { - const n = arr.length; - let totalSum = arr.reduce((a, b) => a + b, 0); - let minimumDiff = Number.MAX_VALUE; - let result = []; - - function isSafe(index, subset) { - return index < n; - } + const totalSum = arr.reduce((a, b) => a + b, 0); + let minimumDiff = totalSum; + let result = [arr, []]; function backtrack(subset = [], index = 0) { - if (index === n) { + if (index === arr.length) { const currentSubsetSum = subset.reduce((a, b) => a + b, 0); const otherSubsetSum = totalSum - currentSubsetSum; const currentDiff = Math.abs(currentSubsetSum - otherSubsetSum); @@ -33,18 +24,12 @@ function tugOfWar(arr) { } // Include the current element. - if (isSafe(index, subset)) { - backtrack([...subset, arr[index]], index + 1); - } - + backtrack([...subset, arr[index]], index + 1); + // Exclude the current element. - if (isSafe(index, subset)) { - backtrack([...subset], index + 1); - } + backtrack([...subset], index + 1); } backtrack(); return result; -} - -export { tugOfWar }; +} \ No newline at end of file diff --git a/Backtracking/tests/TugOfWar.test.js b/Recursive/test/TugOfWar.test.js similarity index 64% rename from Backtracking/tests/TugOfWar.test.js rename to Recursive/test/TugOfWar.test.js index 04e332e869..cdc18bdbf1 100644 --- a/Backtracking/tests/TugOfWar.test.js +++ b/Recursive/test/TugOfWar.test.js @@ -1,4 +1,4 @@ -import { tugOfWar } from '../TugOfWar'; +import { tugOfWar } from './tugOfWar'; describe('tugOfWar', () => { it('should divide array into two subsets with minimized sum difference', () => { @@ -6,6 +6,8 @@ describe('tugOfWar', () => { const [subset1, subset2] = tugOfWar(arr); const diff = Math.abs(subset1.reduce((a, b) => a + b, 0) - subset2.reduce((a, b) => a + b, 0)); - expect(diff).toBeLessThanOrEqual(1); // Here we assume that the difference could be 0 or 1 for this test case. + expect(diff).toBeLessThanOrEqual(1); // Assume that the difference could be 0 or 1 for this test case. }); -}); + + // You can add more test cases +}); \ No newline at end of file From 08059d4fba39dba238ef15c6ec34c7bb7ccd51ee Mon Sep 17 00:00:00 2001 From: vedas-dixit Date: Mon, 30 Oct 2023 14:01:50 +0530 Subject: [PATCH 07/17] Added Function Export Statment --- DIRECTORY.md | 1 - {Backtracking => Recursive}/TugOfWar.js | 33 ++++++------------- .../tests => Recursive/test}/TugOfWar.test.js | 6 ++-- 3 files changed, 14 insertions(+), 26 deletions(-) rename {Backtracking => Recursive}/TugOfWar.js (54%) rename {Backtracking/tests => Recursive/test}/TugOfWar.test.js (71%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 12b00428b1..a7e2f04a2f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -8,7 +8,6 @@ * [RatInAMaze](Backtracking/RatInAMaze.js) * [Sudoku](Backtracking/Sudoku.js) * [SumOfSubset](Backtracking/SumOfSubset.js) - * [TugOfWar](Backtracking/TugOfWar.js) * **Bit-Manipulation** * [BinaryCountSetBits](Bit-Manipulation/BinaryCountSetBits.js) * [GenerateSubSets](Bit-Manipulation/GenerateSubSets.js) diff --git a/Backtracking/TugOfWar.js b/Recursive/TugOfWar.js similarity index 54% rename from Backtracking/TugOfWar.js rename to Recursive/TugOfWar.js index d3703c4c86..d36236667b 100644 --- a/Backtracking/TugOfWar.js +++ b/Recursive/TugOfWar.js @@ -1,26 +1,17 @@ -// https://www.geeksforgeeks.org/tug-of-war/ - -// Given an array of n integers, we need to divide them into two subsets such that -// the difference between their sums is minimized. - /** + * @see https://www.geeksforgeeks.org/tug-of-war/ + * Divides the given array into two subsets such that the difference between their sums is minimized. * @param {number[]} arr - The array of integers. * @returns {Array.} Two subsets with minimized sum difference. */ - function tugOfWar(arr) { - const n = arr.length; - let totalSum = arr.reduce((a, b) => a + b, 0); - let minimumDiff = Number.MAX_VALUE; - let result = []; - - function isSafe(index, subset) { - return index < n; - } + const totalSum = arr.reduce((a, b) => a + b, 0); + let minimumDiff = totalSum; + let result = [arr, []]; function backtrack(subset = [], index = 0) { - if (index === n) { + if (index === arr.length) { const currentSubsetSum = subset.reduce((a, b) => a + b, 0); const otherSubsetSum = totalSum - currentSubsetSum; const currentDiff = Math.abs(currentSubsetSum - otherSubsetSum); @@ -33,18 +24,14 @@ function tugOfWar(arr) { } // Include the current element. - if (isSafe(index, subset)) { - backtrack([...subset, arr[index]], index + 1); - } - + backtrack([...subset, arr[index]], index + 1); + // Exclude the current element. - if (isSafe(index, subset)) { - backtrack([...subset], index + 1); - } + backtrack([...subset], index + 1); } backtrack(); return result; } -export { tugOfWar }; +export { tugOfWar }; \ No newline at end of file diff --git a/Backtracking/tests/TugOfWar.test.js b/Recursive/test/TugOfWar.test.js similarity index 71% rename from Backtracking/tests/TugOfWar.test.js rename to Recursive/test/TugOfWar.test.js index 04e332e869..9f75173fe0 100644 --- a/Backtracking/tests/TugOfWar.test.js +++ b/Recursive/test/TugOfWar.test.js @@ -6,6 +6,8 @@ describe('tugOfWar', () => { const [subset1, subset2] = tugOfWar(arr); const diff = Math.abs(subset1.reduce((a, b) => a + b, 0) - subset2.reduce((a, b) => a + b, 0)); - expect(diff).toBeLessThanOrEqual(1); // Here we assume that the difference could be 0 or 1 for this test case. + expect(diff).toBeLessThanOrEqual(1); // Assume that the difference could be 0 or 1 for this test case. }); -}); + + // You can add more test cases +}); \ No newline at end of file From a48be6c0c4e903546ed30ea7474e44a273f71944 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Mon, 30 Oct 2023 08:36:41 +0000 Subject: [PATCH 08/17] Updated Documentation in README.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index a7e2f04a2f..a65d2eaf94 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -303,6 +303,7 @@ * [Palindrome](Recursive/Palindrome.js) * [SubsequenceRecursive](Recursive/SubsequenceRecursive.js) * [TowerOfHanoi](Recursive/TowerOfHanoi.js) + * [TugOfWar](Recursive/TugOfWar.js) * **Search** * [BinarySearch](Search/BinarySearch.js) * [ExponentialSearch](Search/ExponentialSearch.js) From 964239d84dad73984189de41f936fd925fab7381 Mon Sep 17 00:00:00 2001 From: vedas-dixit Date: Mon, 30 Oct 2023 14:18:11 +0530 Subject: [PATCH 09/17] Resolved Code Style --Prettier --- Recursive/TugOfWar.js | 46 ++++++++++++++++----------------- Recursive/test/TugOfWar.test.js | 22 +++++++++------- 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/Recursive/TugOfWar.js b/Recursive/TugOfWar.js index d36236667b..4932287da8 100644 --- a/Recursive/TugOfWar.js +++ b/Recursive/TugOfWar.js @@ -6,32 +6,32 @@ */ function tugOfWar(arr) { - const totalSum = arr.reduce((a, b) => a + b, 0); - let minimumDiff = totalSum; - let result = [arr, []]; + const totalSum = arr.reduce((a, b) => a + b, 0) + let minimumDiff = totalSum + let result = [arr, []] - function backtrack(subset = [], index = 0) { - if (index === arr.length) { - const currentSubsetSum = subset.reduce((a, b) => a + b, 0); - const otherSubsetSum = totalSum - currentSubsetSum; - const currentDiff = Math.abs(currentSubsetSum - otherSubsetSum); + function backtrack(subset = [], index = 0) { + if (index === arr.length) { + const currentSubsetSum = subset.reduce((a, b) => a + b, 0) + const otherSubsetSum = totalSum - currentSubsetSum + const currentDiff = Math.abs(currentSubsetSum - otherSubsetSum) - if (currentDiff < minimumDiff) { - minimumDiff = currentDiff; - result = [subset, arr.filter(x => !subset.includes(x))]; - } - return; - } - - // Include the current element. - backtrack([...subset, arr[index]], index + 1); - - // Exclude the current element. - backtrack([...subset], index + 1); + if (currentDiff < minimumDiff) { + minimumDiff = currentDiff + result = [subset, arr.filter((x) => !subset.includes(x))] + } + return } - backtrack(); - return result; + // Include the current element. + backtrack([...subset, arr[index]], index + 1) + + // Exclude the current element. + backtrack([...subset], index + 1) + } + + backtrack() + return result } -export { tugOfWar }; \ No newline at end of file +export { tugOfWar } diff --git a/Recursive/test/TugOfWar.test.js b/Recursive/test/TugOfWar.test.js index 9f75173fe0..10d9a4be43 100644 --- a/Recursive/test/TugOfWar.test.js +++ b/Recursive/test/TugOfWar.test.js @@ -1,13 +1,15 @@ -import { tugOfWar } from '../TugOfWar'; +import { tugOfWar } from '../TugOfWar' describe('tugOfWar', () => { - it('should divide array into two subsets with minimized sum difference', () => { - const arr = [3, 4, 5, -3, 100, 1, 89, 54, 23, 20]; - const [subset1, subset2] = tugOfWar(arr); - const diff = Math.abs(subset1.reduce((a, b) => a + b, 0) - subset2.reduce((a, b) => a + b, 0)); - - expect(diff).toBeLessThanOrEqual(1); // Assume that the difference could be 0 or 1 for this test case. - }); + it('should divide array into two subsets with minimized sum difference', () => { + const arr = [3, 4, 5, -3, 100, 1, 89, 54, 23, 20] + const [subset1, subset2] = tugOfWar(arr) + const diff = Math.abs( + subset1.reduce((a, b) => a + b, 0) - subset2.reduce((a, b) => a + b, 0) + ) - // You can add more test cases -}); \ No newline at end of file + expect(diff).toBeLessThanOrEqual(1) // Assume that the difference could be 0 or 1 for this test case. + }) + + // You can add more test cases +}) From d59715410e74a30dd72eb0a03e52498b38b7aea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20M=C3=BCller?= <34514239+appgurueu@users.noreply.github.com> Date: Sun, 5 Nov 2023 15:05:00 +0100 Subject: [PATCH 10/17] Rename "backtrack" to "recurse" --- Recursive/TugOfWar.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Recursive/TugOfWar.js b/Recursive/TugOfWar.js index 4932287da8..cdd605d023 100644 --- a/Recursive/TugOfWar.js +++ b/Recursive/TugOfWar.js @@ -10,7 +10,7 @@ function tugOfWar(arr) { let minimumDiff = totalSum let result = [arr, []] - function backtrack(subset = [], index = 0) { + function recurse(subset, index) { if (index === arr.length) { const currentSubsetSum = subset.reduce((a, b) => a + b, 0) const otherSubsetSum = totalSum - currentSubsetSum @@ -24,13 +24,13 @@ function tugOfWar(arr) { } // Include the current element. - backtrack([...subset, arr[index]], index + 1) + recurse([...subset, arr[index]], index + 1) // Exclude the current element. - backtrack([...subset], index + 1) + recurse([...subset], index + 1) } - backtrack() + recurse([], 0) return result } From cd460e91aa27555c9189996b4c7072233bf0eda8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20M=C3=BCller?= <34514239+appgurueu@users.noreply.github.com> Date: Sun, 5 Nov 2023 15:07:16 +0100 Subject: [PATCH 11/17] Fix test case: The difference needs to be exactly 1. --- Recursive/test/TugOfWar.test.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Recursive/test/TugOfWar.test.js b/Recursive/test/TugOfWar.test.js index 10d9a4be43..3c81808647 100644 --- a/Recursive/test/TugOfWar.test.js +++ b/Recursive/test/TugOfWar.test.js @@ -7,9 +7,6 @@ describe('tugOfWar', () => { const diff = Math.abs( subset1.reduce((a, b) => a + b, 0) - subset2.reduce((a, b) => a + b, 0) ) - - expect(diff).toBeLessThanOrEqual(1) // Assume that the difference could be 0 or 1 for this test case. + expect(diff).toBe(1) }) - - // You can add more test cases }) From 55307a06d935ab1879c43ea80e57ecf48bea5ac2 Mon Sep 17 00:00:00 2001 From: vedas-dixit Date: Sun, 5 Nov 2023 20:47:03 +0530 Subject: [PATCH 12/17] Code Modification: subsets should have sizes as close to n/2 as possible --- Recursive/TugOfWar.js | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/Recursive/TugOfWar.js b/Recursive/TugOfWar.js index cdd605d023..2c93d2c479 100644 --- a/Recursive/TugOfWar.js +++ b/Recursive/TugOfWar.js @@ -6,32 +6,34 @@ */ function tugOfWar(arr) { - const totalSum = arr.reduce((a, b) => a + b, 0) - let minimumDiff = totalSum - let result = [arr, []] + const totalSum = arr.reduce((a, b) => a + b, 0); + let minimumDiff = totalSum; + let result = [arr, []]; - function recurse(subset, index) { + function recurse(subset, index, size1, size2) { if (index === arr.length) { - const currentSubsetSum = subset.reduce((a, b) => a + b, 0) - const otherSubsetSum = totalSum - currentSubsetSum - const currentDiff = Math.abs(currentSubsetSum - otherSubsetSum) - - if (currentDiff < minimumDiff) { - minimumDiff = currentDiff - result = [subset, arr.filter((x) => !subset.includes(x))] + if (Math.abs(size1 - size2) < minimumDiff) { + minimumDiff = Math.abs(size1 - size2); + result = [subset.slice(), arr.filter((x) => !subset.includes(x))]; } - return + return; } - // Include the current element. - recurse([...subset, arr[index]], index + 1) + // Include the current element in the first subset if it doesn't exceed the other subset's size. + if (size1 + 1 <= size2 + (arr.length - index)) { + subset.push(arr[index]); + recurse(subset, index + 1, size1 + 1, size2); + subset.pop(); + } - // Exclude the current element. - recurse([...subset], index + 1) + // Include the current element in the second subset if it doesn't exceed the other subset's size. + if (size2 + 1 <= size1 + (arr.length - index)) { + recurse(subset, index + 1, size1, size2 + 1); + } } - recurse([], 0) - return result + recurse([], 0, 0, 0); + return result; } -export { tugOfWar } +export { tugOfWar }; From 9cfd3f224dbe2bb332be2c30748eaf3108f8a393 Mon Sep 17 00:00:00 2001 From: vedas-dixit Date: Sun, 5 Nov 2023 20:52:34 +0530 Subject: [PATCH 13/17] Updated test-case of TugOfWar --- Recursive/test/TugOfWar.test.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Recursive/test/TugOfWar.test.js b/Recursive/test/TugOfWar.test.js index 3c81808647..857faf6baa 100644 --- a/Recursive/test/TugOfWar.test.js +++ b/Recursive/test/TugOfWar.test.js @@ -1,12 +1,12 @@ -import { tugOfWar } from '../TugOfWar' +import { tugOfWar } from '../TugOfWar'; describe('tugOfWar', () => { it('should divide array into two subsets with minimized sum difference', () => { - const arr = [3, 4, 5, -3, 100, 1, 89, 54, 23, 20] - const [subset1, subset2] = tugOfWar(arr) + const arr = [3, 4, 5, -3, 100, 1, 89, 54, 23, 20]; + const [subset1, subset2] = tugOfWar(arr); const diff = Math.abs( subset1.reduce((a, b) => a + b, 0) - subset2.reduce((a, b) => a + b, 0) - ) - expect(diff).toBe(1) - }) -}) + ); + expect(diff).toBe(1); + }); +}); From f7c430abc7a6e4267b5af71a8e788a526578cc97 Mon Sep 17 00:00:00 2001 From: vedas-dixit Date: Sun, 5 Nov 2023 21:07:59 +0530 Subject: [PATCH 14/17] Changed TugOfWar problem to Partition --- DIRECTORY.md | 1 - Recursive/Partition.js | 40 +++++++++++++++++++ Recursive/TugOfWar.js | 39 ------------------ .../{TugOfWar.test.js => Partition.test.js} | 6 +-- 4 files changed, 43 insertions(+), 43 deletions(-) create mode 100644 Recursive/Partition.js delete mode 100644 Recursive/TugOfWar.js rename Recursive/test/{TugOfWar.test.js => Partition.test.js} (70%) diff --git a/DIRECTORY.md b/DIRECTORY.md index a65d2eaf94..a7e2f04a2f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -303,7 +303,6 @@ * [Palindrome](Recursive/Palindrome.js) * [SubsequenceRecursive](Recursive/SubsequenceRecursive.js) * [TowerOfHanoi](Recursive/TowerOfHanoi.js) - * [TugOfWar](Recursive/TugOfWar.js) * **Search** * [BinarySearch](Search/BinarySearch.js) * [ExponentialSearch](Search/ExponentialSearch.js) diff --git a/Recursive/Partition.js b/Recursive/Partition.js new file mode 100644 index 0000000000..8b74f76469 --- /dev/null +++ b/Recursive/Partition.js @@ -0,0 +1,40 @@ +/** + * @see https://www.geeksforgeeks.org/partition-problem-dp-18/ + * Divides the given array into two subsets such that the difference between their sums is minimized. + * @param {number[]} arr - The array of integers. + * @returns {Array.} Two subsets with minimized sum difference. + */ + +function partition(arr) { + const totalSum = arr.reduce((a, b) => a + b, 0); + const targetSum = totalSum / 2; // The target sum for each subset + let minimumDiff = totalSum; + let result = [[], []]; + + function recurse(subset = [], index = 0, currentSum = 0) { + if (index === arr.length) { + const otherSubsetSum = totalSum - currentSum; + const currentDiff = Math.abs(currentSum - otherSubsetSum); + + if (currentDiff < minimumDiff) { + minimumDiff = currentDiff; + result = [subset, arr.filter((x) => !subset.includes(x))]; + } + + return; + } + + // Include the current element if it doesn't exceed the target sum + if (currentSum + arr[index] <= targetSum) { + recurse([...subset, arr[index]], index + 1, currentSum + arr[index]); + } + + // Exclude the current element + recurse([...subset], index + 1, currentSum); + } + + recurse(); + return result; +} + +export default partition; \ No newline at end of file diff --git a/Recursive/TugOfWar.js b/Recursive/TugOfWar.js deleted file mode 100644 index 2c93d2c479..0000000000 --- a/Recursive/TugOfWar.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @see https://www.geeksforgeeks.org/tug-of-war/ - * Divides the given array into two subsets such that the difference between their sums is minimized. - * @param {number[]} arr - The array of integers. - * @returns {Array.} Two subsets with minimized sum difference. - */ - -function tugOfWar(arr) { - const totalSum = arr.reduce((a, b) => a + b, 0); - let minimumDiff = totalSum; - let result = [arr, []]; - - function recurse(subset, index, size1, size2) { - if (index === arr.length) { - if (Math.abs(size1 - size2) < minimumDiff) { - minimumDiff = Math.abs(size1 - size2); - result = [subset.slice(), arr.filter((x) => !subset.includes(x))]; - } - return; - } - - // Include the current element in the first subset if it doesn't exceed the other subset's size. - if (size1 + 1 <= size2 + (arr.length - index)) { - subset.push(arr[index]); - recurse(subset, index + 1, size1 + 1, size2); - subset.pop(); - } - - // Include the current element in the second subset if it doesn't exceed the other subset's size. - if (size2 + 1 <= size1 + (arr.length - index)) { - recurse(subset, index + 1, size1, size2 + 1); - } - } - - recurse([], 0, 0, 0); - return result; -} - -export { tugOfWar }; diff --git a/Recursive/test/TugOfWar.test.js b/Recursive/test/Partition.test.js similarity index 70% rename from Recursive/test/TugOfWar.test.js rename to Recursive/test/Partition.test.js index 857faf6baa..5629f25ea3 100644 --- a/Recursive/test/TugOfWar.test.js +++ b/Recursive/test/Partition.test.js @@ -1,9 +1,9 @@ -import { tugOfWar } from '../TugOfWar'; +import { partition } from '../Partition'; -describe('tugOfWar', () => { +describe('partition', () => { it('should divide array into two subsets with minimized sum difference', () => { const arr = [3, 4, 5, -3, 100, 1, 89, 54, 23, 20]; - const [subset1, subset2] = tugOfWar(arr); + const [subset1, subset2] = partition(arr); const diff = Math.abs( subset1.reduce((a, b) => a + b, 0) - subset2.reduce((a, b) => a + b, 0) ); From 7f0478c79c0cde1f2905e3e7987c035e7cd7d422 Mon Sep 17 00:00:00 2001 From: vedas-dixit Date: Sun, 5 Nov 2023 21:41:08 +0530 Subject: [PATCH 15/17] Modified partition problem --- Recursive/Partition.js | 59 ++++++++++++++++---------------- Recursive/test/Partition.test.js | 36 ++++++++++++------- 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/Recursive/Partition.js b/Recursive/Partition.js index 8b74f76469..2d86338fd4 100644 --- a/Recursive/Partition.js +++ b/Recursive/Partition.js @@ -1,40 +1,39 @@ /** - * @see https://www.geeksforgeeks.org/partition-problem-dp-18/ - * Divides the given array into two subsets such that the difference between their sums is minimized. - * @param {number[]} arr - The array of integers. - * @returns {Array.} Two subsets with minimized sum difference. + * @function canPartition + * @description Check whether it is possible to partition the given array into two equal sum subsets using recursion. + * @param {number[]} nums - The input array of numbers. + * @param {number} index - The current index in the array being considered. + * @param {number} target - The target sum for each subset. + * @return {boolean}. + * @see [Partition Problem](https://en.wikipedia.org/wiki/Partition_problem) */ -function partition(arr) { - const totalSum = arr.reduce((a, b) => a + b, 0); - const targetSum = totalSum / 2; // The target sum for each subset - let minimumDiff = totalSum; - let result = [[], []]; - - function recurse(subset = [], index = 0, currentSum = 0) { - if (index === arr.length) { - const otherSubsetSum = totalSum - currentSum; - const currentDiff = Math.abs(currentSum - otherSubsetSum); +const canPartition = (nums, index = 0, target = 0) => { + if (!Array.isArray(nums)) { + throw new TypeError('Invalid Input'); + } - if (currentDiff < minimumDiff) { - minimumDiff = currentDiff; - result = [subset, arr.filter((x) => !subset.includes(x))]; - } + const sum = nums.reduce((acc, num) => acc + num, 0); - return; - } + if (sum % 2 !== 0) { + return false; + } - // Include the current element if it doesn't exceed the target sum - if (currentSum + arr[index] <= targetSum) { - recurse([...subset, arr[index]], index + 1, currentSum + arr[index]); - } + if (target === sum / 2) { + return true; + } - // Exclude the current element - recurse([...subset], index + 1, currentSum); + if (index >= nums.length || target > sum / 2) { + return false; } - recurse(); - return result; -} + // Include the current number in the first subset and check if a solution is possible. + const withCurrent = canPartition(nums, index + 1, target + nums[index]); + + // Exclude the current number from the first subset and check if a solution is possible. + const withoutCurrent = canPartition(nums, index + 1, target); + + return withCurrent || withoutCurrent; +}; -export default partition; \ No newline at end of file +export { canPartition }; \ No newline at end of file diff --git a/Recursive/test/Partition.test.js b/Recursive/test/Partition.test.js index 5629f25ea3..5b6fda34a0 100644 --- a/Recursive/test/Partition.test.js +++ b/Recursive/test/Partition.test.js @@ -1,12 +1,24 @@ -import { partition } from '../Partition'; - -describe('partition', () => { - it('should divide array into two subsets with minimized sum difference', () => { - const arr = [3, 4, 5, -3, 100, 1, 89, 54, 23, 20]; - const [subset1, subset2] = partition(arr); - const diff = Math.abs( - subset1.reduce((a, b) => a + b, 0) - subset2.reduce((a, b) => a + b, 0) - ); - expect(diff).toBe(1); - }); -}); +import { canPartition } from '../Partition'; + +describe('Partition (Recursive)', () => { + it('expects to return true for an array that can be partitioned', () => { + const result = canPartition([1, 5, 11, 5]); + expect(result).toBe(true); + }); + + it('expects to return false for an array that cannot be partitioned', () => { + const result = canPartition([1, 2, 3, 5]); + expect(result).toBe(false); + }); + + it('expects to return true for an empty array (0 elements)', () => { + const result = canPartition([]); + expect(result).toBe(true); + }); + + it('Throw Error for Invalid Input', () => { + expect(() => canPartition(123)).toThrow('Invalid Input'); + expect(() => canPartition(null)).toThrow('Invalid Input'); + expect(() => canPartition(undefined)).toThrow('Invalid Input'); + }); +}); \ No newline at end of file From 67c5f728e91ea370f0924564b54fec1bb7936ebc Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sun, 5 Nov 2023 16:11:31 +0000 Subject: [PATCH 16/17] Updated Documentation in README.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index a7e2f04a2f..2ede552665 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -301,6 +301,7 @@ * [KochSnowflake](Recursive/KochSnowflake.js) * [LetterCombination](Recursive/LetterCombination.js) * [Palindrome](Recursive/Palindrome.js) + * [Partition](Recursive/Partition.js) * [SubsequenceRecursive](Recursive/SubsequenceRecursive.js) * [TowerOfHanoi](Recursive/TowerOfHanoi.js) * **Search** From 64cf5ae257a1866bda38b46d19bc3c0e7155d4aa Mon Sep 17 00:00:00 2001 From: vedas-dixit Date: Sun, 5 Nov 2023 21:55:16 +0530 Subject: [PATCH 17/17] fixed code style --- Recursive/Partition.js | 20 ++++++++++---------- Recursive/test/Partition.test.js | 30 +++++++++++++++--------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Recursive/Partition.js b/Recursive/Partition.js index 2d86338fd4..51465f8e93 100644 --- a/Recursive/Partition.js +++ b/Recursive/Partition.js @@ -10,30 +10,30 @@ const canPartition = (nums, index = 0, target = 0) => { if (!Array.isArray(nums)) { - throw new TypeError('Invalid Input'); + throw new TypeError('Invalid Input') } - const sum = nums.reduce((acc, num) => acc + num, 0); + const sum = nums.reduce((acc, num) => acc + num, 0) if (sum % 2 !== 0) { - return false; + return false } if (target === sum / 2) { - return true; + return true } if (index >= nums.length || target > sum / 2) { - return false; + return false } // Include the current number in the first subset and check if a solution is possible. - const withCurrent = canPartition(nums, index + 1, target + nums[index]); + const withCurrent = canPartition(nums, index + 1, target + nums[index]) // Exclude the current number from the first subset and check if a solution is possible. - const withoutCurrent = canPartition(nums, index + 1, target); + const withoutCurrent = canPartition(nums, index + 1, target) - return withCurrent || withoutCurrent; -}; + return withCurrent || withoutCurrent +} -export { canPartition }; \ No newline at end of file +export { canPartition } diff --git a/Recursive/test/Partition.test.js b/Recursive/test/Partition.test.js index 5b6fda34a0..929519999a 100644 --- a/Recursive/test/Partition.test.js +++ b/Recursive/test/Partition.test.js @@ -1,24 +1,24 @@ -import { canPartition } from '../Partition'; +import { canPartition } from '../Partition' describe('Partition (Recursive)', () => { it('expects to return true for an array that can be partitioned', () => { - const result = canPartition([1, 5, 11, 5]); - expect(result).toBe(true); - }); + const result = canPartition([1, 5, 11, 5]) + expect(result).toBe(true) + }) it('expects to return false for an array that cannot be partitioned', () => { - const result = canPartition([1, 2, 3, 5]); - expect(result).toBe(false); - }); + const result = canPartition([1, 2, 3, 5]) + expect(result).toBe(false) + }) it('expects to return true for an empty array (0 elements)', () => { - const result = canPartition([]); - expect(result).toBe(true); - }); + const result = canPartition([]) + expect(result).toBe(true) + }) it('Throw Error for Invalid Input', () => { - expect(() => canPartition(123)).toThrow('Invalid Input'); - expect(() => canPartition(null)).toThrow('Invalid Input'); - expect(() => canPartition(undefined)).toThrow('Invalid Input'); - }); -}); \ No newline at end of file + expect(() => canPartition(123)).toThrow('Invalid Input') + expect(() => canPartition(null)).toThrow('Invalid Input') + expect(() => canPartition(undefined)).toThrow('Invalid Input') + }) +})