From 6027480643fb01e5e7bb080345eee027b6c2c300 Mon Sep 17 00:00:00 2001 From: WoWS17 <76009241+WoWS17@users.noreply.github.com> Date: Tue, 16 May 2023 21:32:47 +0200 Subject: [PATCH 1/6] feat: add well-formed parentheses generator (#2445) * feat: add well-formed parentheses generator * updating DIRECTORY.md * changes made * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * Update backtracking/generate_parentheses.cpp Co-authored-by: David Leal * chore: apply suggestions from code review * Update backtracking/generate_parentheses.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * updating DIRECTORY.md --------- Co-authored-by: github-actions[bot] Co-authored-by: David Leal Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- DIRECTORY.md | 3 + backtracking/generate_parentheses.cpp | 113 ++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 backtracking/generate_parentheses.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index 86d2835bc..817fdd89b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1,5 +1,6 @@ ## Backtracking + * [Generate Parentheses](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/generate_parentheses.cpp) * [Graph Coloring](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/graph_coloring.cpp) * [Knight Tour](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/knight_tour.cpp) * [Magic Sequence](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/magic_sequence.cpp) @@ -67,6 +68,7 @@ * [Queue Using Two Stacks](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/queue_using_two_stacks.cpp) * [Rb Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/rb_tree.cpp) * [Reverse A Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/reverse_a_linked_list.cpp) + * [Segment Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/segment_tree.cpp) * [Skip List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/skip_list.cpp) * [Sparse Table](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/sparse_table.cpp) * [Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/data_structures/stack.hpp) @@ -228,6 +230,7 @@ * [Prime Factorization](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/prime_factorization.cpp) * [Prime Numbers](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/prime_numbers.cpp) * [Primes Up To Billion](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/primes_up_to_billion.cpp) + * [Quadratic Equations Complex Numbers](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/quadratic_equations_complex_numbers.cpp) * [Realtime Stats](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/realtime_stats.cpp) * [Sieve Of Eratosthenes](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/sieve_of_eratosthenes.cpp) * [Sqrt Double](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/math/sqrt_double.cpp) diff --git a/backtracking/generate_parentheses.cpp b/backtracking/generate_parentheses.cpp new file mode 100644 index 000000000..8a9e3b330 --- /dev/null +++ b/backtracking/generate_parentheses.cpp @@ -0,0 +1,113 @@ +/** + * @file + * @brief Well-formed [Generated + * Parentheses](https://leetcode.com/explore/interview/card/top-interview-questions-medium/109/backtracking/794/) with all combinations. + * + * @details a sequence of parentheses is well-formed if each opening parentheses + * has a corresponding closing parenthesis + * and the closing parentheses are correctly ordered + * + * @author [Giuseppe Coco](https://github.com/WoWS17) + + */ + +#include /// for assert +#include /// for I/O operation +#include /// for vector container + +/** + * @brief Backtracking algorithms + * @namespace backtracking + */ +namespace backtracking { +/** + * @brief generate_parentheses class + */ +class generate_parentheses { + private: + std::vector res; ///< Contains all possible valid patterns + + void makeStrings(std::string str, int n, int closed, int open); + + public: + std::vector generate(int n); +}; + +/** + * @brief function that adds parenthesis to the string. + * + * @param str string build during backtracking + * @param n number of pairs of parentheses + * @param closed number of closed parentheses + * @param open number of open parentheses + */ + +void generate_parentheses::makeStrings(std::string str, int n, + int closed, int open) { + if (closed > open) // We can never have more closed than open + return; + + if ((str.length() == 2 * n) && + (closed != open)) { // closed and open must be the same + return; + } + + if (str.length() == 2 * n) { + res.push_back(str); + return; + } + + makeStrings(str + ')', n, closed + 1, open); + makeStrings(str + '(', n, closed, open + 1); +} + +/** + * @brief wrapper interface + * + * @param n number of pairs of parentheses + * @return all well-formed pattern of parentheses + */ +std::vector generate_parentheses::generate(int n) { + backtracking::generate_parentheses::res.clear(); + std::string str = "("; + generate_parentheses::makeStrings(str, n, 0, 1); + return res; +} +} // namespace backtracking + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + int n = 0; + std::vector patterns; + backtracking::generate_parentheses p; + + n = 1; + patterns = {{"()"}}; + assert(p.generate(n) == patterns); + + n = 3; + patterns = {{"()()()"}, {"()(())"}, {"(())()"}, {"(()())"}, {"((()))"}}; + + assert(p.generate(n) == patterns); + + n = 4; + patterns = {{"()()()()"}, {"()()(())"}, {"()(())()"}, {"()(()())"}, + {"()((()))"}, {"(())()()"}, {"(())(())"}, {"(()())()"}, + {"(()()())"}, {"(()(()))"}, {"((()))()"}, {"((())())"}, + {"((()()))"}, {"(((())))"}}; + assert(p.generate(n) == patterns); + + std::cout << "All tests passed\n"; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} From 4fc14710b60c265f265bd4d7c526207a5d477421 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Thu, 18 May 2023 19:26:06 +0200 Subject: [PATCH 2/6] fix: segv in `longest_palindromic_subsequence.cpp` (#2461) * fix: initialise properly res, set properly size of ans * test: add check with empty input * style: use const reference as input type * refactor: add ind_type * style: use reverse interators to b * style: use auto in definition of idx * updating DIRECTORY.md * style: clean-up includes * style: use std::string::size_type in definition of ind_type --------- Co-authored-by: github-actions[bot] Co-authored-by: David Leal --- .../longest_palindromic_subsequence.cpp | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/dynamic_programming/longest_palindromic_subsequence.cpp b/dynamic_programming/longest_palindromic_subsequence.cpp index 9505dcc10..870c43b9c 100644 --- a/dynamic_programming/longest_palindromic_subsequence.cpp +++ b/dynamic_programming/longest_palindromic_subsequence.cpp @@ -13,26 +13,26 @@ * @author [Anjali Jha](https://github.com/anjali1903) */ -#include -#include -#include -#include +#include /// for assert +#include /// for std::string +#include /// for std::vector /** * Function that returns the longest palindromic * subsequence of a string */ -std::string lps(std::string a) { - std::string b = a; - reverse(b.begin(), b.end()); - int m = a.length(); - std::vector > res(m + 1); +std::string lps(const std::string& a) { + const auto b = std::string(a.rbegin(), a.rend()); + const auto m = a.length(); + using ind_type = std::string::size_type; + std::vector > res(m + 1, + std::vector(m + 1)); // Finding the length of the longest // palindromic subsequence and storing // in a 2D array in bottoms-up manner - for (int i = 0; i <= m; i++) { - for (int j = 0; j <= m; j++) { + for (ind_type i = 0; i <= m; i++) { + for (ind_type j = 0; j <= m; j++) { if (i == 0 || j == 0) { res[i][j] = 0; } else if (a[i - 1] == b[j - 1]) { @@ -43,10 +43,10 @@ std::string lps(std::string a) { } } // Length of longest palindromic subsequence - int idx = res[m][m]; + auto idx = res[m][m]; // Creating string of index+1 length - std::string ans(idx + 1, '\0'); - int i = m, j = m; + std::string ans(idx, '\0'); + ind_type i = m, j = m; // starting from right-most bottom-most corner // and storing them one by one in ans @@ -73,12 +73,10 @@ std::string lps(std::string a) { /** Test function */ void test() { - // lps("radar") return "radar" assert(lps("radar") == "radar"); - // lps("abbcbaa") return "abcba" assert(lps("abbcbaa") == "abcba"); - // lps("bbbab") return "bbbb" assert(lps("bbbab") == "bbbb"); + assert(lps("") == ""); } /** From 4f4585d4c1e64251a5dd28a03ce330ae85ce8c2c Mon Sep 17 00:00:00 2001 From: David Leal Date: Fri, 19 May 2023 19:22:54 -0600 Subject: [PATCH 3/6] docs: improve `longest_palindromic_subsequence.cpp` (#2467) --- .../longest_palindromic_subsequence.cpp | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/dynamic_programming/longest_palindromic_subsequence.cpp b/dynamic_programming/longest_palindromic_subsequence.cpp index 870c43b9c..51fc028cf 100644 --- a/dynamic_programming/longest_palindromic_subsequence.cpp +++ b/dynamic_programming/longest_palindromic_subsequence.cpp @@ -1,7 +1,7 @@ /** * @file - * @brief Program to find the Longest Palindormic - * Subsequence of a string + * @brief Program to find the [Longest Palindormic + * Subsequence](https://www.geeksforgeeks.org/longest-palindromic-subsequence-dp-12/) of a string * * @details * [Palindrome](https://en.wikipedia.org/wiki/Palindrome) string sequence of @@ -18,8 +18,15 @@ #include /// for std::vector /** - * Function that returns the longest palindromic + * @namespace + * @brief Dynamic Programming algorithms + */ +namespace dynamic_programming { +/** + * @brief Function that returns the longest palindromic * subsequence of a string + * @param a string whose longest palindromic subsequence is to be found + * @returns longest palindromic subsequence of the string */ std::string lps(const std::string& a) { const auto b = std::string(a.rbegin(), a.rend()); @@ -70,17 +77,22 @@ std::string lps(const std::string& a) { return ans; } +} // namespace dynamic_programming -/** Test function */ -void test() { - assert(lps("radar") == "radar"); - assert(lps("abbcbaa") == "abcba"); - assert(lps("bbbab") == "bbbb"); - assert(lps("") == ""); +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + assert(dynamic_programming::lps("radar") == "radar"); + assert(dynamic_programming::lps("abbcbaa") == "abcba"); + assert(dynamic_programming::lps("bbbab") == "bbbb"); + assert(dynamic_programming::lps("") == ""); } /** - * Main Function + * @brief Main Function + * @returns 0 on exit */ int main() { test(); // execute the tests From 0934ec4a8a0c58143776b9e8e0faf1ccc2ea88ed Mon Sep 17 00:00:00 2001 From: David Leal Date: Fri, 19 May 2023 19:23:40 -0600 Subject: [PATCH 4/6] feat: label PR on CI fail (WIP) (#2455) * feat: label PR on CI fail * updating DIRECTORY.md --------- Co-authored-by: github-actions[bot] --- .github/workflows/awesome_workflow.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/awesome_workflow.yml b/.github/workflows/awesome_workflow.yml index 315629c98..c4c398cd9 100644 --- a/.github/workflows/awesome_workflow.yml +++ b/.github/workflows/awesome_workflow.yml @@ -94,6 +94,8 @@ jobs: name: Compile checks runs-on: ${{ matrix.os }} needs: [MainSequence] + permissions: + pull-requests: write strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] @@ -101,5 +103,17 @@ jobs: - uses: actions/checkout@v3 with: submodules: true - - run: cmake -B ./build -S . - - run: cmake --build build + - run: | + cmake -B ./build -S . + cmake --build build + - name: Label on PR fail + uses: actions/github-script@v6 + if: ${{ failure() && matrix.os == 'ubuntu-latest' && github.event_name == 'pull_request' }} + with: + script: | + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['automated tests are failing'] + }) From 33750ec1f89bfdf0d24b9aec7cb247d5c8a9414a Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Wed, 31 May 2023 04:48:05 +0200 Subject: [PATCH 5/6] fix: cover the cases `n == 0` and `m < n` in `N_bonacci` (#2468) * fix: make N_bonacci return an array of size m * tests: simplify test, add new test cases * style: remove unused include, update include justifications * fix: cover the case n == 0 --- math/n_bonacci.cpp | 90 +++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 53 deletions(-) diff --git a/math/n_bonacci.cpp b/math/n_bonacci.cpp index 845cad734..c34dab7a1 100644 --- a/math/n_bonacci.cpp +++ b/math/n_bonacci.cpp @@ -15,10 +15,9 @@ * @author [Swastika Gupta](https://github.com/Swastyy) */ -#include /// for std::is_equal, std::swap -#include /// for assert -#include /// for IO operations -#include /// for std::vector +#include /// for assert +#include /// for std::cout +#include /// for std::vector /** * @namespace math @@ -39,10 +38,17 @@ namespace n_bonacci { * @returns the n-bonacci sequence as vector array */ std::vector N_bonacci(const uint64_t &n, const uint64_t &m) { - std::vector a(m, 0); // we create an empty array of size m + std::vector a( + m, 0); // we create an array of size m filled with zeros + if (m < n || n == 0) { + return a; + } a[n - 1] = 1; /// we initialise the (n-1)th term as 1 which is the sum of /// preceding N zeros + if (n == m) { + return a; + } a[n] = 1; /// similarily the sum of preceding N zeros and the (N+1)th 1 is /// also 1 for (uint64_t i = n + 1; i < m; i++) { @@ -61,55 +67,33 @@ std::vector N_bonacci(const uint64_t &n, const uint64_t &m) { * @returns void */ static void test() { - // n = 1 m = 1 return [1, 1] - std::cout << "1st test"; - std::vector arr1 = math::n_bonacci::N_bonacci( - 1, 1); // first input is the param n and second one is the param m for - // N-bonacci func - std::vector output_array1 = { - 1, 1}; // It is the expected output series of length m - assert(std::equal(std::begin(arr1), std::end(arr1), - std::begin(output_array1))); - std::cout << "passed" << std::endl; + struct TestCase { + const uint64_t n; + const uint64_t m; + const std::vector expected; + TestCase(const uint64_t in_n, const uint64_t in_m, + std::initializer_list data) + : n(in_n), m(in_m), expected(data) { + assert(data.size() == m); + } + }; + const std::vector test_cases = { + TestCase(0, 0, {}), + TestCase(0, 1, {0}), + TestCase(0, 2, {0, 0}), + TestCase(1, 0, {}), + TestCase(1, 1, {1}), + TestCase(1, 2, {1, 1}), + TestCase(1, 3, {1, 1, 1}), + TestCase(5, 15, {0, 0, 0, 0, 1, 1, 2, 4, 8, 16, 31, 61, 120, 236, 464}), + TestCase( + 6, 17, + {0, 0, 0, 0, 0, 1, 1, 2, 4, 8, 16, 32, 63, 125, 248, 492, 976}), + TestCase(56, 15, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})}; - // n = 5 m = 15 return [0, 0, 0, 0, 1, 1, 2, 4, 8, 16, 31, 61, 120, 236, - // 464] - std::cout << "2nd test"; - std::vector arr2 = math::n_bonacci::N_bonacci( - 5, 15); // first input is the param n and second one is the param m for - // N-bonacci func - std::vector output_array2 = { - 0, 0, 0, 0, 1, 1, 2, 4, - 8, 16, 31, 61, 120, 236, 464}; // It is the expected output series of - // length m - assert(std::equal(std::begin(arr2), std::end(arr2), - std::begin(output_array2))); - std::cout << "passed" << std::endl; - - // n = 6 m = 17 return [0, 0, 0, 0, 0, 1, 1, 2, 4, 8, 16, 32, 63, 125, 248, - // 492, 976] - std::cout << "3rd test"; - std::vector arr3 = math::n_bonacci::N_bonacci( - 6, 17); // first input is the param n and second one is the param m for - // N-bonacci func - std::vector output_array3 = { - 0, 0, 0, 0, 0, 1, 1, 2, 4, - 8, 16, 32, 63, 125, 248, 492, 976}; // It is the expected output series - // of length m - assert(std::equal(std::begin(arr3), std::end(arr3), - std::begin(output_array3))); - std::cout << "passed" << std::endl; - - // n = 56 m = 15 return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - std::cout << "4th test"; - std::vector arr4 = math::n_bonacci::N_bonacci( - 56, 15); // first input is the param n and second one is the param m - // for N-bonacci func - std::vector output_array4 = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0}; // It is the expected output series of length m - assert(std::equal(std::begin(arr4), std::end(arr4), - std::begin(output_array4))); + for (const auto &tc : test_cases) { + assert(math::n_bonacci::N_bonacci(tc.n, tc.m) == tc.expected); + } std::cout << "passed" << std::endl; } From ea4100e394b7783a36a776fe3b26c11375b78f75 Mon Sep 17 00:00:00 2001 From: David Leal Date: Wed, 31 May 2023 11:51:36 -0600 Subject: [PATCH 6/6] chore: add codeowners (#2474) --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..b35b4a61e --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @Panquesito7 @tjgurwara99 @realstealthninja