From 9a1896a9754b45946f25a06f422bd583588b21be Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Thu, 4 Apr 2024 21:26:13 +0700 Subject: [PATCH 01/10] chore: add `ParenthesesGenerator` to `DIRECTORY.md` --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index a75b521341fc..36989c416513 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -15,6 +15,7 @@ * [MazeRecursion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java) * [MColoring](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/backtracking/MColoring.java) * [NQueens](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/backtracking/NQueens.java) + * [ParenthesesGenerator](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java) * [Permutation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/backtracking/Permutation.java) * [PowerSum](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/backtracking/PowerSum.java) * [WordSearch](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/backtracking/WordSearch.java) From 55f218c2a8f8332eb6cb013b13118f46baa8229d Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Thu, 4 Apr 2024 21:26:39 +0700 Subject: [PATCH 02/10] feat: implement Parentheses Generator --- .../backtracking/ParenthesesGenerator.java | 43 ++++++++++++++++++ .../ParenthesesGeneratorTest.java | 44 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java create mode 100644 src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java diff --git a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java new file mode 100644 index 000000000000..9b7ac523fdb5 --- /dev/null +++ b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java @@ -0,0 +1,43 @@ +package com.thealgorithms.backtracking; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class generates all valid combinations of parentheses for a given number of pairs using backtracking. + */ +public class ParenthesesGenerator { + /** + * Generates all valid combinations of parentheses for a given number of pairs. + * + * @param n The number of pairs of parentheses. + * @return A list of strings representing valid combinations of parentheses. + */ + public List generateParentheses(int n) { + List result = new ArrayList<>(); + generateParenthesesHelper(result, "", 0, 0, n); + return result; + } + + /** + * Helper function for generating all valid combinations of parentheses recursively. + * + * @param result The list to store valid combinations. + * @param current The current combination being formed. + * @param open The number of open parentheses. + * @param close The number of closed parentheses. + * @param n The total number of pairs of parentheses. + */ + private void generateParenthesesHelper(List result, String current, int open, int close, int n) { + if (current.length() == n * 2) { + result.add(current); + return; + } + if (open < n) { + generateParenthesesHelper(result, current + "(", open + 1, close, n); + } + if (close < open) { + generateParenthesesHelper(result, current + ")", open, close + 1, n); + } + } +} diff --git a/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java b/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java new file mode 100644 index 000000000000..4ca1071765a7 --- /dev/null +++ b/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java @@ -0,0 +1,44 @@ +package com.thealgorithms.backtracking; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import org.junit.jupiter.api.Test; + +public class ParenthesesGeneratorTest { + + @Test + void testGenerateParenthesesWithZeroPairs() { + ParenthesesGenerator generator = new ParenthesesGenerator(); + List result = generator.generateParentheses(0); + assertEquals(List.of(""), result); + } + + @Test + void testGenerateParenthesesWithOnePair() { + ParenthesesGenerator generator = new ParenthesesGenerator(); + List result = generator.generateParentheses(1); + assertEquals(List.of("()"), result); + } + + @Test + void testGenerateParenthesesWithTwoPairs() { + ParenthesesGenerator generator = new ParenthesesGenerator(); + List result = generator.generateParentheses(2); + assertEquals(List.of("(())", "()()"), result); + } + + @Test + void testGenerateParenthesesWithThreePairs() { + ParenthesesGenerator generator = new ParenthesesGenerator(); + List result = generator.generateParentheses(3); + assertEquals(List.of("((()))", "(()())", "(())()", "()(())", "()()()"), result); + } + + @Test + void testGenerateParenthesesWithFourPairs() { + ParenthesesGenerator generator = new ParenthesesGenerator(); + List result = generator.generateParentheses(4); + assertEquals(List.of("(((())))", "((()()))", "((())())", "((()))()", "(()(()))", "(()()())", "(()())()", "(())(())", "(())()()", "()((()))", "()(()())", "()(())()", "()()(())", "()()()()"), result); + } +} From 88a34bcc277f5cb851db7ad0c60b6df540cbfb00 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Fri, 5 Apr 2024 08:54:32 +0700 Subject: [PATCH 03/10] ref: change `ParenthesesGenerator`s method to `static` --- .../com/thealgorithms/backtracking/ParenthesesGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java index 9b7ac523fdb5..4db7f586f0c6 100644 --- a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java +++ b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java @@ -13,7 +13,7 @@ public class ParenthesesGenerator { * @param n The number of pairs of parentheses. * @return A list of strings representing valid combinations of parentheses. */ - public List generateParentheses(int n) { + public static List generateParentheses(int n) { List result = new ArrayList<>(); generateParenthesesHelper(result, "", 0, 0, n); return result; @@ -28,7 +28,7 @@ public List generateParentheses(int n) { * @param close The number of closed parentheses. * @param n The total number of pairs of parentheses. */ - private void generateParenthesesHelper(List result, String current, int open, int close, int n) { + private static void generateParenthesesHelper(List result, String current, int open, int close, int n) { if (current.length() == n * 2) { result.add(current); return; From 1719cd5aaa100e6f85c829e5264fcad3be3f2551 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Fri, 5 Apr 2024 09:02:09 +0700 Subject: [PATCH 04/10] ref: use parametrized tests --- .../ParenthesesGeneratorTest.java | 47 +++++-------------- 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java b/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java index 4ca1071765a7..de67f2178f01 100644 --- a/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java +++ b/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java @@ -1,44 +1,19 @@ package com.thealgorithms.backtracking; - import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.List; -import org.junit.jupiter.api.Test; - +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; public class ParenthesesGeneratorTest { - - @Test - void testGenerateParenthesesWithZeroPairs() { - ParenthesesGenerator generator = new ParenthesesGenerator(); - List result = generator.generateParentheses(0); - assertEquals(List.of(""), result); - } - - @Test - void testGenerateParenthesesWithOnePair() { - ParenthesesGenerator generator = new ParenthesesGenerator(); - List result = generator.generateParentheses(1); - assertEquals(List.of("()"), result); + @ParameterizedTest + @MethodSource("tcStream") + void numberTests(int input, List expected) { + assertEquals(expected, ParenthesesGenerator.generateParentheses(input)); } - - @Test - void testGenerateParenthesesWithTwoPairs() { - ParenthesesGenerator generator = new ParenthesesGenerator(); - List result = generator.generateParentheses(2); - assertEquals(List.of("(())", "()()"), result); - } - - @Test - void testGenerateParenthesesWithThreePairs() { - ParenthesesGenerator generator = new ParenthesesGenerator(); - List result = generator.generateParentheses(3); - assertEquals(List.of("((()))", "(()())", "(())()", "()(())", "()()()"), result); - } - - @Test - void testGenerateParenthesesWithFourPairs() { - ParenthesesGenerator generator = new ParenthesesGenerator(); - List result = generator.generateParentheses(4); - assertEquals(List.of("(((())))", "((()()))", "((())())", "((()))()", "(()(()))", "(()()())", "(()())()", "(())(())", "(())()()", "()((()))", "()(()())", "()(())()", "()()(())", "()()()()"), result); + private static Stream tcStream() { + return Stream.of(Arguments.of(0, List.of("")), Arguments.of(1, List.of("()")), Arguments.of(2, List.of("(())", "()()")), Arguments.of(3, List.of("((()))", "(()())", "(())()", "()(())", "()()()")), + Arguments.of(4, List.of("(((())))", "((()()))", "((())())", "((()))()", "(()(()))", "(()()())", "(()())()", "(())(())", "(())()()", "()((()))", "()(()())", "()(())()", "()()(())", "()()()()"))); } } From 089c392387a525437163b899aa2efe953fe08830 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Fri, 5 Apr 2024 09:11:17 +0700 Subject: [PATCH 05/10] ref: handling exception when `n < 0` --- .../backtracking/ParenthesesGenerator.java | 3 +++ .../backtracking/ParenthesesGeneratorTest.java | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java index 4db7f586f0c6..e61ac91c9dcc 100644 --- a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java +++ b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java @@ -14,6 +14,9 @@ public class ParenthesesGenerator { * @return A list of strings representing valid combinations of parentheses. */ public static List generateParentheses(int n) { + if (n < 0) { + throw new IllegalArgumentException("The number of pairs of parentheses cannot be nagative"); + } List result = new ArrayList<>(); generateParenthesesHelper(result, "", 0, 0, n); return result; diff --git a/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java b/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java index de67f2178f01..735c46ba471c 100644 --- a/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java +++ b/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java @@ -1,19 +1,33 @@ package com.thealgorithms.backtracking; + import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.List; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; + public class ParenthesesGeneratorTest { @ParameterizedTest @MethodSource("tcStream") void numberTests(int input, List expected) { assertEquals(expected, ParenthesesGenerator.generateParentheses(input)); } + + @ParameterizedTest + @MethodSource("negativeInputStream") + void negativeInputTest(int input) { + assertThrows(IllegalArgumentException.class, () -> ParenthesesGenerator.generateParentheses(input)); + } + private static Stream tcStream() { return Stream.of(Arguments.of(0, List.of("")), Arguments.of(1, List.of("()")), Arguments.of(2, List.of("(())", "()()")), Arguments.of(3, List.of("((()))", "(()())", "(())()", "()(())", "()()()")), Arguments.of(4, List.of("(((())))", "((()()))", "((())())", "((()))()", "(()(()))", "(()()())", "(()())()", "(())(())", "(())()()", "()((()))", "()(()())", "()(())()", "()()(())", "()()()()"))); } + + private static Stream negativeInputStream() { + return Stream.of(Arguments.of(-1), Arguments.of(-5), Arguments.of(-10)); + } } From 5885bbb6e86781da0e4e77dfa0aab4ec5025fe63 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Fri, 5 Apr 2024 09:21:06 +0700 Subject: [PATCH 06/10] chore: update docstrings --- .../com/thealgorithms/backtracking/ParenthesesGenerator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java index e61ac91c9dcc..dd2e8908f681 100644 --- a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java +++ b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java @@ -12,6 +12,7 @@ public class ParenthesesGenerator { * * @param n The number of pairs of parentheses. * @return A list of strings representing valid combinations of parentheses. + * @throws IllegalArgumentException if n is less than 0. */ public static List generateParentheses(int n) { if (n < 0) { From 579941275f60e5f25ede172d196ac369b4fcae83 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Fri, 5 Apr 2024 19:06:44 +0700 Subject: [PATCH 07/10] ref: make `ParenthesesGenerator` to be a proper utility --- .../thealgorithms/backtracking/ParenthesesGenerator.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java index dd2e8908f681..8aabcbd4ff20 100644 --- a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java +++ b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java @@ -6,7 +6,10 @@ /** * This class generates all valid combinations of parentheses for a given number of pairs using backtracking. */ -public class ParenthesesGenerator { +public final class ParenthesesGenerator { + + private ParenthesesGenerator() { + } /** * Generates all valid combinations of parentheses for a given number of pairs. * @@ -14,7 +17,7 @@ public class ParenthesesGenerator { * @return A list of strings representing valid combinations of parentheses. * @throws IllegalArgumentException if n is less than 0. */ - public static List generateParentheses(int n) { + public static List generateParentheses(final int n) { if (n < 0) { throw new IllegalArgumentException("The number of pairs of parentheses cannot be nagative"); } @@ -32,7 +35,7 @@ public static List generateParentheses(int n) { * @param close The number of closed parentheses. * @param n The total number of pairs of parentheses. */ - private static void generateParenthesesHelper(List result, String current, int open, int close, int n) { + private static void generateParenthesesHelper(List result, final String current, final int open, final int close, final int n) { if (current.length() == n * 2) { result.add(current); return; From 6f197c77ec9849fd417d7cb25d4195b2fe7f15b0 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Fri, 5 Apr 2024 19:10:22 +0700 Subject: [PATCH 08/10] chore(docs): add private constructor docstring --- .../thealgorithms/backtracking/ParenthesesGenerator.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java index 8aabcbd4ff20..b492173b3d14 100644 --- a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java +++ b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java @@ -8,8 +8,14 @@ */ public final class ParenthesesGenerator { + /** + * Private constructor to prevent instantiation of this class. + * This class should be used only for its static methods and cannot be instantiated. + */ private ParenthesesGenerator() { + // Private constructor to prevent instantiation } + /** * Generates all valid combinations of parentheses for a given number of pairs. * From 884f5908863a6b83d52beafe936619177975734a Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Fri, 5 Apr 2024 19:16:01 +0700 Subject: [PATCH 09/10] ref(tests): move bad name suggestions --- .../backtracking/ParenthesesGeneratorTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java b/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java index 735c46ba471c..9da16061d8f4 100644 --- a/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java +++ b/src/test/java/com/thealgorithms/backtracking/ParenthesesGeneratorTest.java @@ -11,18 +11,18 @@ public class ParenthesesGeneratorTest { @ParameterizedTest - @MethodSource("tcStream") - void numberTests(int input, List expected) { + @MethodSource("regularInputStream") + void regularInputTests(int input, List expected) { assertEquals(expected, ParenthesesGenerator.generateParentheses(input)); } @ParameterizedTest @MethodSource("negativeInputStream") - void negativeInputTest(int input) { + void throwsForNegativeInputTests(int input) { assertThrows(IllegalArgumentException.class, () -> ParenthesesGenerator.generateParentheses(input)); } - private static Stream tcStream() { + private static Stream regularInputStream() { return Stream.of(Arguments.of(0, List.of("")), Arguments.of(1, List.of("()")), Arguments.of(2, List.of("(())", "()()")), Arguments.of(3, List.of("((()))", "(()())", "(())()", "()(())", "()()()")), Arguments.of(4, List.of("(((())))", "((()()))", "((())())", "((()))()", "(()(()))", "(()()())", "(()())()", "(())(())", "(())()()", "()((()))", "()(()())", "()(())()", "()()(())", "()()()()"))); } From d86cb331bed6903a41834345f051d3d75b1cc6c8 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:37:56 +0200 Subject: [PATCH 10/10] style: remove reduntant comments --- .../thealgorithms/backtracking/ParenthesesGenerator.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java index b492173b3d14..8bbed4106251 100644 --- a/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java +++ b/src/main/java/com/thealgorithms/backtracking/ParenthesesGenerator.java @@ -7,13 +7,7 @@ * This class generates all valid combinations of parentheses for a given number of pairs using backtracking. */ public final class ParenthesesGenerator { - - /** - * Private constructor to prevent instantiation of this class. - * This class should be used only for its static methods and cannot be instantiated. - */ private ParenthesesGenerator() { - // Private constructor to prevent instantiation } /**