diff --git a/DIRECTORY.md b/DIRECTORY.md index e89e9c7af..f2cb78cba 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -11,9 +11,11 @@ * [Subarray Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/subarray_sum.cpp) * [Subset Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/subset_sum.cpp) * [Sudoku Solve](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/sudoku_solve.cpp) + * [Wildcard Matching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/wildcard_matching.cpp) ## Bit Manipulation * [Count Of Set Bits](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/bit_manipulation/count_of_set_bits.cpp) + * [Count Of Trailing Ciphers In Factorial N](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp) * [Hamming Distance](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/bit_manipulation/hamming_distance.cpp) ## Ciphers @@ -64,6 +66,9 @@ * [Trie Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/trie_tree.cpp) * [Trie Using Hashmap](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/trie_using_hashmap.cpp) +## Divide And Conquer + * [Karatsuba Algorithm For Fast Multiplication](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp) + ## Dynamic Programming * [0 1 Knapsack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/0_1_knapsack.cpp) * [Abbreviation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/abbreviation.cpp) @@ -180,6 +185,7 @@ * [Modular Division](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_division.cpp) * [Modular Exponentiation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_exponentiation.cpp) * [Modular Inverse Fermat Little Theorem](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_inverse_fermat_little_theorem.cpp) + * [N Bonacci](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/n_bonacci.cpp) * [N Choose R](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/n_choose_r.cpp) * [Ncr Modulo P](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/ncr_modulo_p.cpp) * [Number Of Positive Divisors](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/number_of_positive_divisors.cpp) diff --git a/backtracking/wildcard_matching.cpp b/backtracking/wildcard_matching.cpp new file mode 100644 index 000000000..d9163a41b --- /dev/null +++ b/backtracking/wildcard_matching.cpp @@ -0,0 +1,155 @@ +/** + * @file + * @brief Implementation of the [Wildcard + * Matching](https://www.geeksforgeeks.org/wildcard-pattern-matching/) problem. + * @details + * Given a matching string and a pattern, implement wildcard pattern + * matching with support for `?` and `*`. `?` matches any single character. + * `*` matches any sequence of characters (including the empty sequence). + * The matching should cover the entire matching string (not partial). The task + * is to determine if the pattern matches with the matching string + * @author [Swastika Gupta](https://github.com/Swastyy) + */ + +#include /// for assert +#include /// for IO operations +#include /// for std::vector + +/** + * @namespace backtracking + * @brief Backtracking algorithms + */ +namespace backtracking { +/** + * @namespace wildcard_matching + * @brief Functions for the [Wildcard + * Matching](https://www.geeksforgeeks.org/wildcard-pattern-matching/) problem. + */ +namespace wildcard_matching { +/** + * @brief The main function implements if pattern can be matched with given + * string + * @param s is the given matching string + * @param p is the given pattern + * @param pos1 is the starting index + * @param pos2 is the last index + * @returns 1 if pattern matches with matching string otherwise 0 + */ +std::vector> dpTable(1000, std::vector(1000, -1)); +bool wildcard_matching(std::string s, std::string p, uint32_t pos1, + uint32_t pos2) { + uint32_t n = s.length(); + uint32_t m = p.length(); + // matching is successfull if both strings are done + if (pos1 == n && pos2 == m) { + return true; + } + + // matching is unsuccessfull if pattern is not finished but matching string + // is + if (pos1 != n && pos2 == m) { + return false; + } + + // all the remaining characters of patterns must be * inorder to match with + // finished string + if (pos1 == n && pos2 != m) { + while (pos2 < m && p[pos2] == '*') { + pos2++; + } + + return pos2 == m; + } + + // if already calculted for these positions + if (dpTable[pos1][pos2] != -1) { + return dpTable[pos1][pos2]; + } + + // if the characters are same just go ahead in both the string + if (s[pos1] == p[pos2]) { + return dpTable[pos1][pos2] = + wildcard_matching(s, p, pos1 + 1, pos2 + 1); + } + + else { + // can only single character + if (p[pos2] == '?') { + return dpTable[pos1][pos2] = + wildcard_matching(s, p, pos1 + 1, pos2 + 1); + } + // have choice either to match one or more charcters + else if (p[pos2] == '*') { + return dpTable[pos1][pos2] = + wildcard_matching(s, p, pos1, pos2 + 1) || + wildcard_matching(s, p, pos1 + 1, pos2); + } + // not possible to match + else { + return dpTable[pos1][pos2] = 0; + } + } +} + +} // namespace wildcard_matching +} // namespace backtracking + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + // 1st test + std::cout << "1st test "; + std::string matching1 = "baaabab"; + std::string pattern1 = "*****ba*****ab"; + assert(backtracking::wildcard_matching::wildcard_matching(matching1, + pattern1, 0, 0) == + 1); // here the pattern matches with given string + std::cout << "passed" << std::endl; + + // 2nd test + std::cout << "2nd test "; + std::string matching2 = "baaabab"; + std::string pattern2 = "ba*****ab"; + assert(backtracking::wildcard_matching::wildcard_matching(matching2, + pattern2, 0, 0) == + 1); // here the pattern matches with given string + std::cout << "passed" << std::endl; + + // 3rd test + std::cout << "3rd test "; + std::string matching3 = "baaabab"; + std::string pattern3 = "ba*ab"; + assert(backtracking::wildcard_matching::wildcard_matching(matching3, + pattern3, 0, 0) == + 1); // here the pattern matches with given string + std::cout << "passed" << std::endl; + + // 4th test + std::cout << "4th test "; + std::string matching4 = "baaabab"; + std::string pattern4 = "a*ab"; + assert(backtracking::wildcard_matching::wildcard_matching(matching4, + pattern4, 0, 0) == + 1); // here the pattern matches with given string + std::cout << "passed" << std::endl; + + // 5th test + std::cout << "5th test "; + std::string matching5 = "baaabab"; + std::string pattern5 = "aa?ab"; + assert(backtracking::wildcard_matching::wildcard_matching(matching5, + pattern5, 0, 0) == + 1); // here the pattern matches with given string + std::cout << "passed" << std::endl; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} diff --git a/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp b/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp new file mode 100644 index 000000000..aa2ceb3dd --- /dev/null +++ b/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp @@ -0,0 +1,98 @@ +/** + * @file + * @brief [Count the number of + * ciphers](https://www.tutorialspoint.com/count-trailing-zeros-in-factorial-of-a-number-in-cplusplus) in `n!` implementation + * @details + * Given an integer number as input. The goal is to find the number of trailing + zeroes in the factorial calculated for + * that number. A factorial of a number N is a product of all numbers in the + range [1, N]. + + * We know that we get a trailing zero only if the number is multiple of 10 or + has a factor pair (2,5). In all factorials of + * any number greater than 5, we have many 2s more than 5s in the prime + factorization of that number. Dividing a + * number by powers of 5 will give us the count of 5s in its factors. So, the + number of 5s will tell us the number of trailing zeroes. + * @author [Swastika Gupta](https://github.com/Swastyy) + */ + +#include /// for assert +#include /// for IO operations + +/** + * @namespace bit_manipulation + * @brief Bit manipulation algorithms + */ +namespace bit_manipulation { +/** + * @namespace count_of_trailing_ciphers_in_factorial_n + * @brief Functions for the [Count the number of + * ciphers](https://www.tutorialspoint.com/count-trailing-zeros-in-factorial-of-a-number-in-cplusplus) + * in `n!` implementation + */ +namespace count_of_trailing_ciphers_in_factorial_n { +/** + * @brief Function to count the number of the trailing ciphers + * @param n number for which `n!` ciphers are returned + * @return count, Number of ciphers in `n!`. + */ +uint64_t numberOfCiphersInFactorialN(uint64_t n) { + // count is to store the number of 5's in factorial(n) + uint64_t count = 0; + + // Keep dividing n by powers of + // 5 and update count + for (uint64_t i = 5; n / i >= 1; i *= 5) { + count += static_cast(n) / i; + } + + return count; +} +} // namespace count_of_trailing_ciphers_in_factorial_n +} // namespace bit_manipulation + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + // 1st test + std::cout << "1st test "; + assert(bit_manipulation::count_of_trailing_ciphers_in_factorial_n:: + numberOfCiphersInFactorialN(395) == 97); + std::cout << "passed" << std::endl; + + // 2nd test + std::cout << "2nd test "; + assert(bit_manipulation::count_of_trailing_ciphers_in_factorial_n:: + numberOfCiphersInFactorialN(977) == 242); + std::cout << "passed" << std::endl; + + // 3rd test + std::cout << "3rd test "; + assert(bit_manipulation::count_of_trailing_ciphers_in_factorial_n:: + numberOfCiphersInFactorialN(871) == 215); + std::cout << "passed" << std::endl; + + // 4th test + std::cout << "4th test "; + assert(bit_manipulation::count_of_trailing_ciphers_in_factorial_n:: + numberOfCiphersInFactorialN(239) == 57); + std::cout << "passed" << std::endl; + + // 5th test + std::cout << "5th test "; + assert(bit_manipulation::count_of_trailing_ciphers_in_factorial_n:: + numberOfCiphersInFactorialN(0) == 0); + std::cout << "passed" << std::endl; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} diff --git a/divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp b/divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp new file mode 100644 index 000000000..1782d0a45 --- /dev/null +++ b/divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp @@ -0,0 +1,167 @@ +/** + * @file + * @brief Implementation of the [Karatsuba algorithm for fast + * multiplication](https://en.wikipedia.org/wiki/Karatsuba_algorithm) + * @details + * Given two strings in binary notation we want to multiply them and return the + * value Simple approach is to multiply bits one by one which will give the time + * complexity of around O(n^2). To make it more efficient we will be using + * Karatsuba' algorithm to find the product which will solve the problem + * O(nlogn) of time. + * @author [Swastika Gupta](https://github.com/Swastyy) + */ + +#include /// for assert +#include /// for string +#include /// for IO operations +#include /// for std::vector + +/** + * @namespace divide_and_conquer + * @brief Divide and Conquer algorithms + */ +namespace divide_and_conquer { +/** + * @namespace karatsuba_algorithm + * @brief Functions for the [Karatsuba algorithm for fast + * multiplication](https://en.wikipedia.org/wiki/Karatsuba_algorithm) + */ +namespace karatsuba_algorithm { +/** + * @brief Helper function for the main function, that implements Karatsuba's + * algorithm for fast multiplication + * @param first the input string 1 + * @param second the input string 2 + * @returns the concatenated string + */ +std::string addStrings(std::string first, std::string second) { + std::string result; // To store the resulting sum bits + + int64_t len1 = first.size(); + int64_t len2 = second.size(); + int64_t length = std::max(len1, len2); + std::string zero = "0"; + if (len1 < len2) // make the string lengths equal + { + for (int64_t i = 0; i < len2 - len1; i++) { + zero += first; + first = zero; + } + } else if (len1 > len2) { + zero = "0"; + for (int64_t i = 0; i < len1 - len2; i++) { + zero += second; + second = zero; + } + } + int64_t carry = 0; + for (int64_t i = length - 1; i >= 0; i--) { + int64_t firstBit = first.at(i) - '0'; + int64_t secondBit = second.at(i) - '0'; + + int64_t sum = (firstBit ^ secondBit ^ carry) + '0'; // sum of 3 bits + std::string temp; + temp = std::to_string(sum); + temp += result; + result = temp; + + carry = (firstBit & secondBit) | (secondBit & carry) | + (firstBit & carry); // sum of 3 bits + } + + if (carry) { + result = '1' + result; // adding 1 incase of overflow + } + return result; +} +/** + * @brief The main function implements Karatsuba's algorithm for fast + * multiplication + * @param str1 the input string 1 + * @param str2 the input string 2 + * @returns the multiplicative number value + */ +int64_t karatsuba_algorithm(std::string str1, std::string str2) { + int64_t len1 = str1.size(); + int64_t len2 = str2.size(); + int64_t n = std::max(len1, len2); + std::string zero = "0"; + if (len1 < len2) { + for (int64_t i = 0; i < len2 - len1; i++) { + zero += str1; + str1 = zero; + } + } else if (len1 > len2) { + zero = "0"; + for (int64_t i = 0; i < len1 - len2; i++) { + zero += str2; + str2 = zero; + } + } + if (n == 0) { + return 0; + } + if (n == 1) { + return (str1[0] - '0') * (str2[0] - '0'); + } + int64_t fh = n / 2; // first half of string + int64_t sh = (n - fh); // second half of string + + std::string Xl = str1.substr(0, fh); // first half of first string + std::string Xr = str1.substr(fh, sh); // second half of first string + + std::string Yl = str2.substr(0, fh); // first half of second string + std::string Yr = str2.substr(fh, sh); // second half of second string + + // Calculating the three products of inputs of size n/2 recursively + int64_t product1 = karatsuba_algorithm(Xl, Yl); + int64_t product2 = karatsuba_algorithm(Xr, Yr); + int64_t product3 = karatsuba_algorithm( + divide_and_conquer::karatsuba_algorithm::addStrings(Xl, Xr), + divide_and_conquer::karatsuba_algorithm::addStrings(Yl, Yr)); + + return product1 * (1 << (2 * sh)) + + (product3 - product1 - product2) * (1 << sh) + + product2; // combining the three products to get the final result. +} +} // namespace karatsuba_algorithm +} // namespace divide_and_conquer + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + // 1st test + std::string s11 = "1"; + std::string s12 = "1010"; + std::cout << "1st test... "; + assert(divide_and_conquer::karatsuba_algorithm::karatsuba_algorithm( + s11, s12) == 10); // here the multiplication is 10 + std::cout << "passed" << std::endl; + + // 2nd test + std::string s21 = "11"; + std::string s22 = "1010"; + std::cout << "2nd test... "; + assert(divide_and_conquer::karatsuba_algorithm::karatsuba_algorithm( + s21, s22) == 30); // here the multiplication is 30 + std::cout << "passed" << std::endl; + + // 3rd test + std::string s31 = "110"; + std::string s32 = "1010"; + std::cout << "3rd test... "; + assert(divide_and_conquer::karatsuba_algorithm::karatsuba_algorithm( + s31, s32) == 60); // here the multiplication is 60 + std::cout << "passed" << std::endl; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} diff --git a/math/check_prime.cpp b/math/check_prime.cpp index d68325d56..3c3ff2b62 100644 --- a/math/check_prime.cpp +++ b/math/check_prime.cpp @@ -22,11 +22,11 @@ template bool is_prime(T num) { bool result = true; if (num <= 1) { - return 0; + return false; } else if (num == 2) { - return 1; + return true; } else if ((num & 1) == 0) { - return 0; + return false; } if (num >= 3) { for (T i = 3; (i * i) <= (num); i = (i + 2)) { @@ -47,7 +47,7 @@ int main() { assert(is_prime(50) == false); assert(is_prime(115249) == true); - int num; + int num = 0; std::cout << "Enter the number to check if it is prime or not" << std::endl; std::cin >> num; bool result = is_prime(num); diff --git a/math/n_bonacci.cpp b/math/n_bonacci.cpp new file mode 100644 index 000000000..845cad734 --- /dev/null +++ b/math/n_bonacci.cpp @@ -0,0 +1,123 @@ +/** + * @file + * @brief Implementation of the + * [N-bonacci](http://oeis.org/wiki/N-bonacci_numbers) series + * + * @details + * In general, in N-bonacci sequence, + * we generate sum of preceding N numbers from the next term. + * + * For example, a 3-bonacci sequence is the following: + * 0, 0, 1, 1, 2, 4, 7, 13, 24, 44, 81 + * In this code we take N and M as input where M is the number of terms + * to be printed of the N-bonacci series + * + * @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 + +/** + * @namespace math + * @brief Mathematical algorithms + */ +namespace math { +/** + * @namespace n_bonacci + * @brief Functions for the [N-bonacci](http://oeis.org/wiki/N-bonacci_numbers) + * implementation + */ +namespace n_bonacci { +/** + * @brief Finds the N-Bonacci series for the `n` parameter value and `m` + * parameter terms + * @param n is in the N-Bonacci series + * @param m is the number of terms in the N-Bonacci sequence + * @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 + + a[n - 1] = 1; /// we initialise the (n-1)th term as 1 which is the sum of + /// preceding N zeros + 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++) { + // this is an optimized solution that works in O(M) time and takes O(M) + // extra space here we use the concept of the sliding window the current + // term can be computed using the given formula + a[i] = 2 * a[i - 1] - a[i - 1 - n]; + } + return a; +} +} // namespace n_bonacci +} // namespace math + +/** + * @brief Self-test implementations + * @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; + + // 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))); + std::cout << "passed" << std::endl; +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +}