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 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'] + }) diff --git a/DIRECTORY.md b/DIRECTORY.md index b937b4c82..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) 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; +} diff --git a/dynamic_programming/longest_palindromic_subsequence.cpp b/dynamic_programming/longest_palindromic_subsequence.cpp index 9505dcc10..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 @@ -13,26 +13,33 @@ * @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 + * @namespace + * @brief Dynamic Programming algorithms */ -std::string lps(std::string a) { - std::string b = a; - reverse(b.begin(), b.end()); - int m = a.length(); - std::vector > res(m + 1); +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()); + 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 +50,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 @@ -70,19 +77,22 @@ std::string lps(std::string a) { return ans; } +} // namespace dynamic_programming -/** 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"); +/** + * @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 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; }