Merge branch 'master' into fix-1323

This commit is contained in:
Kaustubh Damania
2020-11-20 14:16:55 +05:30
committed by GitHub
25 changed files with 2493 additions and 414 deletions

View File

@@ -1,13 +1,17 @@
# CONTRIBUTION GUIDELINES
## Before contributing
Welcome to [TheAlgorithms/C-Plus-Plus](https://github.com/TheAlgorithms/C-Plus-Plus)! Before submitting pull requests, please make sure that you have **read the whole guidelines**. If you have any doubts about this contribution guide, please open [an issue](https://github.com/TheAlgorithms/C-Plus-Plus/issues/new/choose) and clearly state your concerns.
## Contributing
### Contributor
We are very happy that you consider implementing algorithms and data structures for others! This repository is referred to and used by learners from around the globe. Being one of our contributors, you agree and confirm that:
- You did your own work.
- No plagiarism allowed. Any plagiarized work will not be merged.
- No plagiarism allowed. Any plagiarized work will not be merged.
- Your work will be distributed under [MIT License](License) once your pull request has been merged.
- You submitted work fulfils or mostly fulfils our styles and standards.
@@ -20,36 +24,40 @@ We are very happy that you consider implementing algorithms and data structures
### Making Changes
#### Code
- Please use the directory structure of the repository.
- File extension for code should be *.h *.cpp.
- File extension for code should be `*.hpp`, `*.h` or `*.cpp`.
- Don't use **bits/stdc++.h** because this is quite Linux specific and slows down the compilation process.
- Organize your code using **`struct`**, **`class`** and/or **`namespace`** keywords
- If an implementation of the algorithm already exists, please refer to the [file-name section below](#new-file-name-guidelines).
- You can suggest reasonable changes to existing algorithms.
- Strictly use snake_case (underscore_separated) in filenames.
- If you have added or modified code, please make sure the code compiles before submitting.
- Our automated testing runs [__cpplint__](https://github.com/cpplint/cpplint) on all pull requests so please be sure that your code passes before submitting.
- Our automated testing runs [__CMake__](https://cmake.org/) on all pull requests so please be sure that your code passes before submitting.
- Please conform to [doxygen](https://www.doxygen.nl/manual/docblocks.html) standard and document the code as much as possible. This not only facilitates the readers but also generates the correct info on website.
- **Be consistent in use of these guidelines.**
#### Documentation
- Make sure you put useful comments in your code. Do not comment things that are obvious.
- Please avoid creating new directories if at all possible. Try to fit your work into the existing directory structure. If you want to create a new directory, then please check if a similar category has been recently suggested or created by other pull requests.
- If you have modified/added documentation, please ensure that your language is concise and contains no grammar errors.
- Do not update README.md along with other changes, first create an issue and then link to that issue in your pull request to suggest specific changes required to README.md
- The repository follows [Doxygen](https://www.doxygen.nl/manual/docblocks.html) standards and auto-generates the [repo website](https://thealgorithms.github.io/C-Plus-Plus). Please ensure the code is documented in this structure. Sample implementation is given below.
- Do not update [`README.md`](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/README.md) along with other changes. First create an issue and then link to that issue in your pull request to suggest specific changes required to [`README.md`](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/README.md).
- The repository follows [Doxygen](https://www.doxygen.nl/manual/docblocks.html) standards and auto-generates the [repository website](https://thealgorithms.github.io/C-Plus-Plus). Please ensure the code is documented in this structure. Sample implementation is given below.
#### Test
- Make sure to add examples and test cases in your main() function.
- If you find any algorithm or document without tests, please feel free to create a pull request or issue describing suggested changes.
- Please try to add one or more `test()` functions that will invoke the algorithm implementation on random test data with expected output. Use `assert()` function to confirm that the tests will pass.
- Please try to add one or more `test()` functions that will invoke the algorithm implementation on random test data with expected output. Use `assert()` function to confirm that the tests will pass. Requires including the `cassert` header.
#### Typical structure of a program
#### Typical structure of a program:
```cpp
/**
* @file
* @file
* @brief Add one line description here
* @details
* @details
* This is a multi line
* description containing links, references,
* math equations, etc
@@ -57,7 +65,8 @@ We are very happy that you consider implementing algorithms and data structures
* @see related_file.cpp, another_file.cpp
*/
#include
#include <cassert>
#include
/**
* @namespace <check from other files in this repo>
@@ -93,8 +102,12 @@ bool func(int param1, T param2) {
return true;
}
} // namespace name
/** Test function */
/**
* @brief Test implementations
* @returns void
*/
static void test() {
/* desciptions of the following test */
assert(func(...) == ...); // this ensures that the algorithm works as expected
@@ -102,7 +115,12 @@ static void test() {
// can have multiple checks
}
/** Main function */
/**
* @brief Main function
* @param argc commandline argument count (ignored)
* @param argv commandline array of arguments (ignored)
* @returns 0 on exit
*/
int main(int argc, char *argv[]) {
test(); // execute the tests
// code here
@@ -111,76 +129,102 @@ int main(int argc, char *argv[]) {
```
#### New File Name guidelines
- Use lowercase words with ``"_"`` as separator
- For instance
```
```markdown
MyNewCppClass.CPP is incorrect
my_new_cpp_class.cpp is correct format
```
- It will be used to dynamically create a directory of files and implementation.
- File name validation will run on docker to ensure the validity.
- If an implementation of the algorithm already exists and your version is different from that implemented, please use incremental numeric digit as a suffix. For example, if `median_search.cpp` already exists in the `search` folder and you are contributing a new implementation, the filename should be `median_search2.cpp` and for a third implementation, `median_search3.cpp`.
#### New Directory guidelines
- We recommend adding files to existing directories as much as possible.
- Use lowercase words with ``"_"`` as separator ( no spaces or ```"-"``` allowed )
- For instance
```
```markdown
SomeNew Fancy-Category is incorrect
some_new_fancy_category is correct
```
- Filepaths will be used to dynamically create a directory of our algorithms.
- Filepath validation will run on GitHub Actions to ensure compliance.
#### Commit Guidelines
- It is recommended to keep your changes grouped logically within individual commits. Maintainers find it easier to understand changes that are logically spilt across multiple commits. Try to modify just one or two files in the same directory. Pull requests that span multiple directories are often rejected.
```
```bash
git add file_xyz.cpp
git commit -m "your message"
```
Examples of commit messages with semantic prefixes:
```
```markdown
fix: xyz algorithm bug
feat: add xyx algorithm, class xyz
test: add test for xyz algorithm
docs: add comments and explanation to xyz algorithm
```
Common prefixes:
- fix: A bug fix
- feat: A new feature
- docs: Documentation changes
- test: Correct existing tests or add new ones
### Pull Requests
- Checkout our [pull request template](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/.github/pull_request_template.md)
#### Building Locally
Before submitting a pull request, build the code locally or using the convenient [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/TheAlgorithms/C-Plus-Plus) service.
```
Before submitting a pull request,
build the code locally or using the convenient [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/TheAlgorithms/C-Plus-Plus) service.
```bash
cmake -B build -S .
```
#### Static Code Analyzer
We use [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) as a static code analyzer with a configuration in [.clang-tidy](.clang-tidy).
```
```bash
clang-tidy --fix --quiet -p build subfolder/file_to_check.cpp --
```
#### Code Formatter
[__clang-format__](https://clang.llvm.org/docs/ClangFormat.html) is used for code forrmating.
* Installation (Only needs to be installed once.)
* Mac (using home-brew): `brew install clang-format`
* Mac (using macports): `sudo port install clang-10 +analyzer`
* Windows (MSYS2 64-bit): `pacman -S mingw-w64-x86_64-clang-tools-extra`
* Linux (Debian): `sudo apt-get install clang-format-10 clang-tidy-10`
* Running (all platforms): `clang-format -i -style="file" my_file.cpp`
- Installation (only needs to be installed once.)
- Mac (using home-brew): `brew install clang-format`
- Mac (using macports): `sudo port install clang-10 +analyzer`
- Windows (MSYS2 64-bit): `pacman -S mingw-w64-x86_64-clang-tools-extra`
- Linux (Debian): `sudo apt-get install clang-format-10 clang-tidy-10`
- Running (all platforms): `clang-format -i -style="file" my_file.cpp`
#### GitHub Actions
Enable GitHub Actions on your fork of the repository.
After enabling it will execute `clang-tidy` and `clang-format` after every a push (not a commit).
The result can create another commit if the actions made any changes on your behalf.
Hence, it is better to wait and check the results of GitHub Actions after every push.
Run `git pull` in your local clone if these actions made many changes in order to avoid merge conflicts.
- Enable GitHub Actions on your fork of the repository.
After enabling it will execute `clang-tidy` and `clang-format` after every push (not a commit).
- Click on the tab "Actions", then click on the big green button to enable it.
![GitHub Actions](https://user-images.githubusercontent.com/51391473/94609466-6e925100-0264-11eb-9d6f-3706190eab2b.png)
- The result can create another commit if the actions made any changes on your behalf.
- Hence, it is better to wait and check the results of GitHub Actions after every push.
- Run `git pull` in your local clone if these actions made many changes in order to avoid merge conflicts.
Most importantly,
- Happy coding!

View File

@@ -13,6 +13,7 @@
## Ciphers
* [Caesar Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/caesar_cipher.cpp)
* [Hill Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/hill_cipher.cpp)
* [Morse Code](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/morse_code.cpp)
* [Vigenere Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/vigenere_cipher.cpp)
* [Xor Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/xor_cipher.cpp)
@@ -54,6 +55,7 @@
* [Bellman Ford](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/bellman_ford.cpp)
* [Catalan Numbers](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/catalan_numbers.cpp)
* [Coin Change](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/coin_change.cpp)
* [Coin Change Topdown](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/coin_change_topdown.cpp)
* [Cut Rod](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/cut_rod.cpp)
* [Edit Distance](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/edit_distance.cpp)
* [Egg Dropping Puzzle](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/egg_dropping_puzzle.cpp)
@@ -66,6 +68,7 @@
* [Longest Increasing Subsequence](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/longest_increasing_subsequence.cpp)
* [Longest Increasing Subsequence (Nlogn)](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/longest_increasing_subsequence_(nlogn).cpp)
* [Matrix Chain Multiplication](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/matrix_chain_multiplication.cpp)
* [Palindrome Partitioning](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/palindrome_partitioning.cpp)
* [Searching Of Element In Dynamic Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/searching_of_element_in_dynamic_array.cpp)
* [Shortest Common Supersequence](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/shortest_common_supersequence.cpp)
* [Tree Height](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/tree_height.cpp)
@@ -112,6 +115,9 @@
* [Linear Probing Hash Table](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/hashing/linear_probing_hash_table.cpp)
* [Quadratic Probing Hash Table](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/hashing/quadratic_probing_hash_table.cpp)
## Linear Algebra
* [Gram Schmidt](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/linear_algebra/gram_schmidt.cpp)
## Machine Learning
* [Adaline Learning](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/machine_learning/adaline_learning.cpp)
* [Kohonen Som Topology](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/machine_learning/kohonen_som_topology.cpp)
@@ -135,15 +141,20 @@
* [Fibonacci](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/fibonacci.cpp)
* [Fibonacci Fast](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/fibonacci_fast.cpp)
* [Fibonacci Large](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/fibonacci_large.cpp)
* [Fibonacci Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/fibonacci_sum.cpp)
* [Gcd Iterative Euclidean](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/gcd_iterative_euclidean.cpp)
* [Gcd Of N Numbers](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/gcd_of_n_numbers.cpp)
* [Gcd Recursive Euclidean](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/gcd_recursive_euclidean.cpp)
* [Large Factorial](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/large_factorial.cpp)
* [Large Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/large_number.h)
* [Lcm Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/lcm_sum.cpp)
* [Least Common Multiple](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/least_common_multiple.cpp)
* [Magic Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/magic_number.cpp)
* [Miller Rabin](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/miller_rabin.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)
* [Ncr Modulo P](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/ncr_modulo_p.cpp)
* [N Choose R](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/n_choose_r.cpp)
* [Number Of Positive Divisors](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/number_of_positive_divisors.cpp)
* [Power For Huge Numbers](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/power_for_huge_numbers.cpp)
* [Prime Factorization](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/prime_factorization.cpp)
@@ -153,6 +164,7 @@
* [Sieve Of Eratosthenes](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/sieve_of_eratosthenes.cpp)
* [Sqrt Double](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/sqrt_double.cpp)
* [String Fibonacci](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/string_fibonacci.cpp)
* [Sum Of Binomial Coefficient](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/sum_of_binomial_coefficient.cpp)
* [Sum Of Digits](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/sum_of_digits.cpp)
## Numerical Methods
@@ -171,6 +183,7 @@
* [Qr Decompose](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/qr_decompose.h)
* [Qr Decomposition](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/qr_decomposition.cpp)
* [Qr Eigen Values](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/qr_eigen_values.cpp)
* [Rungekutta](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/rungekutta.cpp)
* [Successive Approximation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/numerical_methods/successive_approximation.cpp)
## Operations On Datastructures
@@ -240,6 +253,7 @@
* [Comb Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/comb_sort.cpp)
* [Counting Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/counting_sort.cpp)
* [Counting Sort String](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/counting_sort_string.cpp)
* [Cycle Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/cycle_sort.cpp)
* [Gnome Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/gnome_sort.cpp)
* [Heap Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/heap_sort.cpp)
* [Insertion Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/insertion_sort.cpp)
@@ -254,6 +268,7 @@
* [Quick Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/quick_sort.cpp)
* [Quick Sort 3](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/quick_sort_3.cpp)
* [Radix Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/radix_sort.cpp)
* [Radix Sort2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/radix_sort2.cpp)
* [Selection Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/selection_sort.cpp)
* [Shell Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/shell_sort.cpp)
* [Shell Sort2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/shell_sort2.cpp)
@@ -261,6 +276,7 @@
* [Strand Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/strand_sort.cpp)
* [Swap Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/swap_sort.cpp)
* [Tim Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/tim_sort.cpp)
* [Wiggle Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/wiggle_sort.cpp)
## Strings
* [Brute Force String Searching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/strings/brute_force_string_searching.cpp)

View File

@@ -1,71 +1,129 @@
/**
* @file
* @brief [N queens](https://en.wikipedia.org/wiki/Eight_queens_puzzle) all
* optimized
*
* @author [Sombit Bose](https://github.com/deadshotsb)
* @author [David Leal](https://github.com/Panquesito7)
*/
#include <array>
#include <iostream>
#define n 4
#define inc_loop(var, start, stop) for (int var = start; var <= stop; var++)
#define dec_loop(var, start, stop) for (int var = start; var >= stop; var--)
void PrintSol(int Board[n][n]) {
inc_loop(i, 0, n - 1) {
inc_loop(j, 0, n - 1) std::cout << Board[i][j] << " ";
/**
* @namespace backtracking
* @brief Backtracking algorithms
*/
namespace backtracking {
/**
* @namespace n_queens_optimized
* @brief Functions for [Eight
* Queens](https://en.wikipedia.org/wiki/Eight_queens_puzzle) puzzle optimized.
*/
namespace n_queens_optimized {
/**
* Utility function to print matrix
* @tparam n number of matrix size
* @param board matrix where numbers are saved
*/
template <size_t n>
void PrintSol(const std::array<std::array<int, n>, n> &board) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
std::cout << board[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
if (n % 2 == 0 || (n % 2 == 1 && Board[n / 2 + 1][0] != 1)) {
inc_loop(i, 0, n - 1) {
dec_loop(j, n - 1, 0) std::cout << Board[i][j] << " ";
if (n % 2 == 0 || (n % 2 == 1 && board[n / 2 + 1][0] != 1)) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
std::cout << board[j][i] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
}
bool CanIMove(int Board[n][n], int row, int col) {
/**
* Check if a queen can be placed on matrix
* @tparam n number of matrix size
* @param board matrix where numbers are saved
* @param row current index in rows
* @param col current index in columns
* @returns `true` if queen can be placed on matrix
* @returns `false` if queen can't be placed on matrix
*/
template <size_t n>
bool CanIMove(const std::array<std::array<int, n>, n> &board, int row,
int col) {
/// check in the row
inc_loop(i, 0, col - 1) {
if (Board[row][i] == 1)
for (int i = 0; i <= col; i++) {
if (board[row][i] == 1) {
return false;
}
}
/// check the first diagonal
for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
if (Board[i][j] == 1)
if (board[i][j] == 1) {
return false;
}
}
/// check the second diagonal
for (int i = row, j = col; i <= n - 1 && j >= 0; i++, j--) {
if (Board[i][j] == 1)
if (board[i][j] == 1) {
return false;
}
}
return true;
}
void NQueenSol(int Board[n][n], int col) {
/**
* Solve n queens problem
* @tparam n number of matrix size
* @param board matrix where numbers are saved
* @param col current index in columns
*/
template <size_t n>
void NQueenSol(std::array<std::array<int, n>, n> board, int col) {
if (col >= n) {
PrintSol(Board);
PrintSol<n>(board);
return;
}
inc_loop(i, 0, n - 1) {
if (CanIMove(Board, i, col)) {
Board[i][col] = 1;
NQueenSol(Board, col + 1);
Board[i][col] = 0;
for (int i = 0; i < n; i++) {
if (CanIMove<n>(board, i, col)) {
board[i][col] = 1;
NQueenSol<n>(board, col + 1);
board[i][col] = 0;
}
}
}
} // namespace n_queens_optimized
} // namespace backtracking
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
int Board[n][n] = {0};
const int n = 4;
std::array<std::array<int, n>, n> board{};
if (n % 2 == 0) {
inc_loop(i, 0, n / 2 - 1) {
if (CanIMove(Board, i, 0)) {
Board[i][0] = 1;
NQueenSol(Board, 1);
Board[i][0] = 0;
for (int i = 0; i <= n / 2 - 1; i++) { // 😎
if (backtracking::n_queens_optimized::CanIMove(board, i, 0)) {
board[i][0] = 1;
backtracking::n_queens_optimized::NQueenSol(board, 1);
board[i][0] = 0;
}
}
} else {
inc_loop(i, 0, n / 2) {
if (CanIMove(Board, i, 0)) {
Board[i][0] = 1;
NQueenSol(Board, 1);
Board[i][0] = 0;
for (int i = 0; i <= n / 2; i++) { // 😏
if (backtracking::n_queens_optimized::CanIMove(board, i, 0)) {
board[i][0] = 1;
backtracking::n_queens_optimized::NQueenSol(board, 1);
board[i][0] = 0;
}
}
}

272
ciphers/morse_code.cpp Normal file
View File

@@ -0,0 +1,272 @@
/**
* @file
* @author [Deep Raval](https://github.com/imdeep2905)
*
* @brief Implementation of [Morse Code]
* (https://en.wikipedia.org/wiki/Morse_code).
*
* @details
* Morse code is a method used in telecommunication to encode text characters
* as standardized sequences of two different signal durations, called dots
* and dashes or dits and dahs. Morse code is named after Samuel Morse, an
* inventor of the telegraph.
*/
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
/** \namespace ciphers
* \brief Algorithms for encryption and decryption
*/
namespace ciphers {
/** \namespace morse
* \brief Functions for [Morse Code]
* (https://en.wikipedia.org/wiki/Morse_code).
*/
namespace morse {
/**
* Get the morse representation for given character.
* @param c Character
* @returns morse representation string of character
*/
std::string char_to_morse(const char &c) {
// return corresponding morse code
switch (c) {
case 'a':
return ".-";
case 'b':
return "-...";
case 'c':
return "-.-.";
case 'd':
return "-..";
case 'e':
return ".";
case 'f':
return "..-.";
case 'g':
return "--.";
case 'h':
return "....";
case 'i':
return "..";
case 'j':
return ".---";
case 'k':
return "-.-";
case 'l':
return ".-..";
case 'm':
return "--";
case 'n':
return "-.";
case 'o':
return "---";
case 'p':
return ".--.";
case 'q':
return "--.-";
case 'r':
return ".-.";
case 's':
return "...";
case 't':
return "-";
case 'u':
return "..-";
case 'v':
return "...-";
case 'w':
return ".--";
case 'x':
return "-..-";
case 'y':
return "-.--";
case 'z':
return "--..";
case '1':
return ".----";
case '2':
return "..---";
case '3':
return "...--";
case '4':
return "....-";
case '5':
return ".....";
case '6':
return "-....";
case '7':
return "--...";
case '8':
return "---..";
case '9':
return "----.";
case '0':
return "-----";
default:
std::cerr << "Found invalid character: " << c << ' ' << std::endl;
std::exit(0);
}
}
/**
* Get character from the morse representation.
* @param s Morse representation
* @returns corresponding character
*/
char morse_to_char(const std::string &s) {
// return corresponding character
if (s == ".-") {
return 'a';
} else if (s == "-...") {
return 'b';
} else if (s == "-.-.") {
return 'c';
} else if (s == "-..") {
return 'd';
} else if (s == ".") {
return 'e';
} else if (s == "..-.") {
return 'f';
} else if (s == "--.") {
return 'g';
} else if (s == "....") {
return 'h';
} else if (s == "..") {
return 'i';
} else if (s == ".---") {
return 'j';
} else if (s == "-.-") {
return 'k';
} else if (s == ".-..") {
return 'l';
} else if (s == "--") {
return 'm';
} else if (s == "-.") {
return 'n';
} else if (s == "---") {
return 'o';
} else if (s == ".--.") {
return 'p';
} else if (s == "--.-") {
return 'q';
} else if (s == ".-.") {
return 'r';
} else if (s == "...") {
return 's';
} else if (s == "-") {
return 't';
} else if (s == "..-") {
return 'u';
} else if (s == "...-") {
return 'v';
} else if (s == ".--") {
return 'w';
} else if (s == "-..-") {
return 'x';
} else if (s == "-.--") {
return 'y';
} else if (s == "--..") {
return 'z';
} else if (s == ".----") {
return '1';
} else if (s == "..---") {
return '2';
} else if (s == "...--") {
return '3';
} else if (s == "....-") {
return '4';
} else if (s == ".....") {
return '5';
} else if (s == "-....") {
return '6';
} else if (s == "--...") {
return '7';
} else if (s == "---..") {
return '8';
} else if (s == "----.") {
return '9';
} else if (s == "-----") {
return '0';
} else {
std::cerr << "Found invalid Morse code: " << s << ' ' << std::endl;
std::exit(0);
}
}
/**
* Encrypt given text using morse code.
* @param text text to be encrypted
* @returns new encrypted text
*/
std::string encrypt(const std::string &text) {
std::string encrypted_text = ""; // Empty string to store encrypted text
// Going through each character of text and converting it
// to morse representation
for (const char &c : text) {
encrypted_text += ciphers::morse::char_to_morse(c) + " ";
}
return encrypted_text; // Returning encrypted text
}
/**
* Decrypt given morse coded text.
* @param text text to be decrypted
* @returns new decrypted text
*/
std::string decrypt(const std::string &text) {
// Going through each character of text and converting it
// back to normal representation.
std::string decrypted_text = ""; // Empty string to store decrypted text
// Spliting string (with delimiter = " ") and storing it
// in vector
std::size_t pos_start = 0, pos_end = 0, delim_len = 1;
std::vector<std::string> splits;
while ((pos_end = text.find(' ', pos_start)) != std::string::npos) {
std::string token = text.substr(pos_start, pos_end - pos_start);
pos_start = pos_end + delim_len;
splits.push_back(token);
}
// Traversing through each morse code string
for (const std::string &s : splits) {
// Add corresponding character
decrypted_text += ciphers::morse::morse_to_char(s);
}
return decrypted_text; // Returning decrypted text
}
} // namespace morse
} // namespace ciphers
/**
* @brief Function to test above algorithm
* @returns void
*/
static void test() {
// Test 1
std::string text1 = "01234567890";
std::string encrypted1 = ciphers::morse::encrypt(text1);
std::string decrypted1 = ciphers::morse::decrypt(encrypted1);
assert(text1 == decrypted1);
std::cout << "Original text : " << text1 << std::endl;
std::cout << "Encrypted text : " << encrypted1 << std::endl;
std::cout << "Decrypted text : " << decrypted1 << std::endl;
// Test 2
std::string text2 = "abcdefghijklmnopqrstuvwxyz";
std::string encrypted2 = ciphers::morse::encrypt(text2);
std::string decrypted2 = ciphers::morse::decrypt(encrypted2);
assert(text2 == decrypted2);
std::cout << "Original text : " << text2 << std::endl;
std::cout << "Encrypted text : " << encrypted2 << std::endl;
std::cout << "Decrypted text : " << decrypted2 << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
// Testing
test();
return 0;
}

View File

@@ -4,31 +4,32 @@
* @warning The sorting algorithm is erroneous
*/
#include <iostream>
#include <array>
struct list {
int data[50];
std::array<int, 50> data{};
int top = 0;
bool isSorted = false;
int BinarySearch(int *array, int first, int last, int x) {
int BinarySearch(const std::array<int, 50>& dataArr, int first, int last, int x) {
if (last < first) {
return -1;
}
int mid = (first + last) / 2;
if (array[mid] == x)
if (dataArr[mid] == x)
return mid;
else if (x < array[mid])
return (BinarySearch(array, first, mid - 1, x));
else if (x > array[mid])
return (BinarySearch(array, mid + 1, last, x));
else if (x < dataArr[mid])
return (BinarySearch(dataArr, first, mid - 1, x));
else if (x > dataArr[mid])
return (BinarySearch(dataArr, mid + 1, last, x));
std::cerr << __func__ << ":" << __LINE__ << ": Undefined condition\n";
return -1;
}
int LinarSearch(int *array, int x) {
int LinearSearch(const std::array<int, 50>& dataArr, int x) const {
for (int i = 0; i < top; i++) {
if (array[i] == x) {
if (dataArr[i] == x) {
return i;
}
}
@@ -37,12 +38,12 @@ struct list {
}
int Search(int x) {
int pos = -1;
int pos;
if (isSorted) {
pos = BinarySearch(data, 0, top - 1, x);
} else {
pos = LinarSearch(data, x);
pos = LinearSearch(data, x);
}
if (pos != -1) {
@@ -54,7 +55,7 @@ struct list {
}
void Sort() {
int i, j, pos;
int i, j, pos=0;
for (i = 0; i < top; i++) {
int min = data[i];
for (j = i + 1; j < top; j++) {
@@ -121,6 +122,8 @@ int main() {
int choice;
int x;
do {
// Choices for operations on the list_array.
std::cout << "\n0.Exit";
std::cout << "\n1.Insert";
std::cout << "\n2.Delete";
std::cout << "\n3.Search";
@@ -129,27 +132,31 @@ int main() {
std::cout << "\n\nEnter Your Choice : ";
std::cin >> choice;
switch (choice) {
case 1:
std::cout << "\nEnter the element to be inserted : ";
std::cin >> x;
L.insert(x);
break;
case 2:
std::cout << "\nEnter the element to be removed : ";
std::cin >> x;
L.Remove(x);
break;
case 3:
std::cout << "\nEnter the element to be searched : ";
std::cin >> x;
L.Search(x);
break;
case 4:
L.Sort();
break;
case 5:
L.Show();
break;
case 0:
break;
case 1:
std::cout << "\nEnter the element to be inserted : ";
std::cin >> x;
L.insert(x);
break;
case 2:
std::cout << "\nEnter the element to be removed : ";
std::cin >> x;
L.Remove(x);
break;
case 3:
std::cout << "\nEnter the element to be searched : ";
std::cin >> x;
L.Search(x);
break;
case 4:
L.Sort();
break;
case 5:
L.Show();
break;
default:
std::cout << "\nplease enter valid option.";
}
} while (choice != 0);
return 0;

View File

@@ -1,77 +1,120 @@
/*
Write a program to implement Linear Queue using array.
/**
* @file
* @brief Implementation of Linear [Queue using array]
* (https://www.geeksforgeeks.org/array-implementation-of-queue-simple/).
* @details
* The Linear Queue is a data structure used for holding a sequence of
* values, which can be added to the end line (enqueue), removed from
* head of line (dequeue) and displayed.
* ### Algorithm
* Values can be added by increasing the `rear` variable by 1 (which points to
* the end of the array), then assigning new value to `rear`'s element of the array.
*
* Values can be removed by increasing the `front` variable by 1 (which points to
* the first of the array), so it cannot reached any more.
*
* @author [Pooja](https://github.com/pooja-git11)
* @author [Farbod Ahmadian](https://github.com/farbodahm)
*/
#include <iostream> /// for io operations
#include <array> /// for std::array
Functions to implement
Enqueue (Insertion)
Dequeue (Deletion)
constexpr uint16_t max_size{10}; ///< Maximum size of the queue
*/
#include <iostream>
/**
* @namespace data_structures
* @brief Algorithms with data structures
*/
namespace data_structures {
#define MAXSIZE 10
/**
* @namespace queue_using_array
* @brief Functions for [Queue using Array]
* (https://www.geeksforgeeks.org/array-implementation-of-queue-simple/) implementation.
*/
namespace queue_using_array {
/**
* @brief Queue_Array class containing the main data and also index of head and tail of the array.
*/
class Queue_Array {
int front;
int rear;
int size;
public:
Queue_Array() {
front = -1;
rear = -1;
size = MAXSIZE;
}
int *arr = new int[size];
void enqueue(int);
int dequeue();
void display();
public:
void enqueue(const int16_t&); ///< Add element to the first of the queue
int dequeue(); ///< Delete element from back of the queue
void display() const; ///< Show all saved data
private:
int8_t front{-1}; ///< Index of head of the array
int8_t rear{-1}; ///< Index of tail of the array
std::array<int16_t, max_size> arr; ///< All stored data
};
void Queue_Array::enqueue(int ele) {
if (rear == size - 1) {
/**
* @brief Adds new element to the end of the queue
* @param ele to be added to the end of the queue
*/
void Queue_Array::enqueue(const int16_t& ele ) {
if (rear == arr.size() - 1) {
std::cout << "\nStack is full";
} else if (front == -1 && rear == -1) {
front = rear = 0;
front = 0;
rear = 0;
arr[rear] = ele;
} else if (rear < size) {
rear++;
} else if (rear < arr.size()) {
++rear;
arr[rear] = ele;
}
}
/**
* @brief Remove element that is located at the first of the queue
* @returns data that is deleted if queue is not empty
*/
int Queue_Array::dequeue() {
int d;
int8_t d{0};
if (front == -1) {
std::cout << "\nstack is empty ";
return 0;
} else if (front == rear) {
d = arr[front];
d = arr.at(front);
front = rear = -1;
} else {
d = arr[front++];
d = arr.at(front++);
}
return d;
}
void Queue_Array::display() {
/**
* @brief Utility function to show all elements in the queue
*/
void Queue_Array::display() const {
if (front == -1) {
std::cout << "\nStack is empty";
} else {
for (int i = front; i <= rear; i++) std::cout << arr[i] << " ";
for (int16_t i{front}; i <= rear; ++i) std::cout << arr.at(i) << " ";
}
}
int main() {
int op, data;
} // namespace queue_using_array
} // namespace data_structures
Queue_Array ob;
/**
* @brief Main function
* @details
* Allows the user to add and delete values from the queue.
* Also allows user to display values in the queue.
* @returns 0 on exit
*/
int main() {
int op{0}, data{0};
data_structures::queue_using_array::Queue_Array ob;
std::cout << "\n1. enqueue(Insertion) ";
std::cout << "\n2. dequeue(Deletion)";
std::cout << "\n3. Display";
std::cout << "\n4. Exit";
while (1) {
while (true) {
std::cout << "\nEnter your choice ";
std::cin >> op;
if (op == 1) {
@@ -89,4 +132,6 @@ int main() {
std::cout << "\nWrong choice ";
}
}
return 0;
}

View File

@@ -1,66 +1,129 @@
// 0-1 Knapsack problem - Dynamic programming
//#include <bits/stdc++.h>
/**
* @file
* @brief Implementation of [0-1 Knapsack Problem]
* (https://en.wikipedia.org/wiki/Knapsack_problem)
*
* @details
* Given weights and values of n items, put these items in a knapsack of
* capacity `W` to get the maximum total value in the knapsack. In other words,
* given two integer arrays `val[0..n-1]` and `wt[0..n-1]` which represent
* values and weights associated with n items respectively. Also given an
* integer W which represents knapsack capacity, find out the maximum value
* subset of `val[]` such that sum of the weights of this subset is smaller than
* or equal to W. You cannot break an item, either pick the complete item or
* dont pick it (0-1 property)
*
* ### Algorithm
* The idea is to consider all subsets of items and calculate the total weight
* and value of all subsets. Consider the only subsets whose total weight is
* smaller than `W`. From all such subsets, pick the maximum value subset.
*
* @author [Anmol](https://github.com/Anmol3299)
* @author [Pardeep](https://github.com/Pardeep009)
*/
#include <array>
#include <cassert>
#include <iostream>
using namespace std;
#include <vector>
// void Print(int res[20][20], int i, int j, int capacity)
//{
// if(i==0 || j==0)
// {
// return;
// }
// if(res[i-1][j]==res[i][j-1])
// {
// if(i<=capacity)
// {
// cout<<i<<" ";
// }
//
// Print(res, i-1, j-1, capacity-i);
// }
// else if(res[i-1][j]>res[i][j-1])
// {
// Print(res, i-1,j, capacity);
// }
// else if(res[i][j-1]>res[i-1][j])
// {
// Print(res, i,j-1, capacity);
// }
//}
/**
* @namespace dynamic_programming
* @brief Dynamic Programming algorithms
*/
namespace dynamic_programming {
/**
* @namespace Knapsack
* @brief Implementation of 0-1 Knapsack problem
*/
namespace knapsack {
/**
* @brief Picking up all those items whose combined weight is below
* given capacity and calculating value of those picked items.Trying all
* possible combinations will yield the maximum knapsack value.
* @tparam n size of the weight and value array
* @param capacity capacity of the carrying bag
* @param weight array representing weight of items
* @param value array representing value of items
* @return maximum value obtainable with given capacity.
*/
template <size_t n>
int maxKnapsackValue(const int capacity, const std::array<int, n> &weight,
const std::array<int, n> &value) {
std::vector<std::vector<int> > maxValue(n + 1,
std::vector<int>(capacity + 1, 0));
// outer loop will select no of items allowed
// inner loop will select capcity of knapsack bag
int items = sizeof(weight) / sizeof(weight[0]);
for (size_t i = 0; i < items + 1; ++i) {
for (size_t j = 0; j < capacity + 1; ++j) {
if (i == 0 || j == 0) {
// if no of items is zero or capacity is zero, then maxValue
// will be zero
maxValue[i][j] = 0;
} else if (weight[i - 1] <= j) {
// if the ith item's weight(in actual array it will be at i-1)
// is less than or equal to the allowed weight i.e. j then we
// can pick that item for our knapsack. maxValue will be the
// obtained either by picking the current item or by not picking
// current item
int Knapsack(int capacity, int n, int weight[], int value[]) {
int res[20][20];
for (int i = 0; i < n + 1; ++i) {
for (int j = 0; j < capacity + 1; ++j) {
if (i == 0 || j == 0)
res[i][j] = 0;
else if (weight[i - 1] <= j)
res[i][j] = max(value[i - 1] + res[i - 1][j - weight[i - 1]],
res[i - 1][j]);
else
res[i][j] = res[i - 1][j];
// picking current item
int profit1 = value[i - 1] + maxValue[i - 1][j - weight[i - 1]];
// not picking current item
int profit2 = maxValue[i - 1][j];
maxValue[i][j] = std::max(profit1, profit2);
} else
// as weight of current item is greater than allowed weight, so
// maxProfit will be profit obtained by excluding current item.
maxValue[i][j] = maxValue[i - 1][j];
}
}
// Print(res, n, capacity, capacity);
// cout<<"\n";
return res[n][capacity];
// returning maximum value
return maxValue[items][capacity];
}
} // namespace knapsack
} // namespace dynamic_programming
/**
* @brief Function to test above algorithm
* @returns void
*/
static void test() {
// Test 1
const int n1 = 3; // number of items
std::array<int, n1> weight1 = {10, 20, 30}; // weight of each item
std::array<int, n1> value1 = {60, 100, 120}; // value of each item
const int capacity1 = 50; // capacity of carrying bag
const int max_value1 = dynamic_programming::knapsack::maxKnapsackValue(
capacity1, weight1, value1);
const int expected_max_value1 = 220;
assert(max_value1 == expected_max_value1);
std::cout << "Maximum Knapsack value with " << n1 << " items is "
<< max_value1 << std::endl;
// Test 2
const int n2 = 4; // number of items
std::array<int, n2> weight2 = {24, 10, 10, 7}; // weight of each item
std::array<int, n2> value2 = {24, 18, 18, 10}; // value of each item
const int capacity2 = 25; // capacity of carrying bag
const int max_value2 = dynamic_programming::knapsack::maxKnapsackValue(
capacity2, weight2, value2);
const int expected_max_value2 = 36;
assert(max_value2 == expected_max_value2);
std::cout << "Maximum Knapsack value with " << n2 << " items is "
<< max_value2 << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
int n;
cout << "Enter number of items: ";
cin >> n;
int weight[n], value[n];
cout << "Enter weights: ";
for (int i = 0; i < n; ++i) {
cin >> weight[i];
}
cout << "Enter values: ";
for (int i = 0; i < n; ++i) {
cin >> value[i];
}
int capacity;
cout << "Enter capacity: ";
cin >> capacity;
cout << Knapsack(capacity, n, weight, value);
// Testing
test();
return 0;
}

View File

@@ -0,0 +1,89 @@
/**
* @file
* @brief [Minimum coins](https://leetcode.com/problems/coin-change/) change problem is a problem used to find the minimum number of
* coins required to completely reach a target amount.
*
* @details
* This problem can be solved using 2 methods:
* 1. Top down approach
* 2. Bottom up appraoch
* Top down approach involves a vector with all elements initialised to 0.
* It is based on optimal substructure and overlapping subproblems.
* Overall time complexity of coin change problem is O(n*t)
* For example: example 1:-
* Coins: {1,7,10}
* Target:15
* Therfore minimum number of coins required = 3 of denomination 1,7 and 7.
* @author [Divyansh Kushwaha](https://github.com/webdesignbydivyansh)
*/
#include <iostream> // for io operations
#include <vector> // for std::vector
#include <cassert> // for assert
#include <climits> // for INT_MAX
/**
* @namespace dynamic_programming
* @brief Dynamic Programming algorithm
*/
namespace dynamic_programming {
/**
* @namespace mincoins_topdown
* @brief Functions for [minimum coin exchange](https://leetcode.com/problems/coin-change/) problem
*/
namespace mincoins_topdown {
/**
* @brief This implementation is for finding minimum number of coins .
* @param T template-type to use any kind of value
* @param n amount to be reached
* @param coins vector of coins
* @param t deontes the number of coins
* @param dp initilised to 0
* @returns minimum number of coins
*/
template<typename T>
int64_t mincoins(const T &n, const std::vector<T> &coins, const int16_t &t, std::vector<T> dp){
if(n==0){
return 0;
}
if(dp[n]!=0){
return dp[n];
}
int ans=INT_MAX; //variable to store min coins
for(int i=0;i<t;i++){
if(n-coins[i]>=0){ //if after subtracting the current denomination is it greater than 0 or not
int sub=mincoins(n-coins[i],coins,t,dp);
ans=std::min(ans,sub+1);
}
}
dp[n]=ans;
return dp[n]; //returns minimum number of coins
}
} // namespace mincoins_topdown
} // namespace dynamic_programming
/**
* @brief Test implementations
* @returns void
*/
static void test() {
// example 1: number of coins=3 and minimum coins required=3(7,7,1)
const int64_t n1 = 15;
const int8_t t1=3, a1=0;
std::cout << "\nTest 1...";
std::vector<int64_t> arr1 {1,7,10};
std::vector<int64_t> dp1 (n1+1);
fill(dp1.begin(),dp1.end(),a1);
assert(dynamic_programming::mincoins_topdown::mincoins(n1, arr1, t1, dp1)==3);
std::cout << "Passed\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the test
return 0;
}

View File

@@ -0,0 +1,123 @@
/**
* @file
* @brief Implements [Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/) algorithm, giving you the minimum number of partitions you need to make
*
* @details
* palindrome partitioning uses dynamic programming and goes to all the possible partitions to find the minimum
* you are given a string and you need to give minimum number of partitions needed to divide it into a number of palindromes
* [Palindrome Partitioning] (https://www.geeksforgeeks.org/palindrome-partitioning-dp-17/)
* overall time complexity O(n^2)
* For example: example 1:-
* String : "nitik"
* Output : 2 => "n | iti | k"
* For example: example 2:-
* String : "ababbbabbababa"
* Output : 3 => "aba | b | bbabb | ababa"
* @author [Sujay Kaushik] (https://github.com/sujaykaushik008)
*/
#include <iostream> // for io operations
#include <vector> // for std::vector
#include <algorithm> // for std::min
#include <cassert> // for std::assert
#include <climits> // for INT_MAX
/**
* @namespace dynamic_programming
* @brief Dynamic Programming algorithms
*/
namespace dynamic_programming {
/**
* @namespace palindrome_partitioning
* @brief Functions for [Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/) algorithm
*/
namespace palindrome_partitioning {
/**
* Function implementing palindrome partitioning algorithm using lookup table method.
* @param str input string
* @returns minimum number of partitions
*/
int pal_part(const std::string &str) {
int n = str.size();
// creating lookup table for minimum number of cuts
std::vector<std::vector<int> > cuts(n, std::vector<int>(n, 0));
// creating lookup table for palindrome checking
std::vector<std::vector<bool> > is_palindrome(n, std::vector<bool>(n, false));
// initialization
for (int i = 0; i < n; i++) {
is_palindrome[i][i] = true;
cuts[i][i] = 0;
}
for (int len = 2; len <= n; len++) {
for (int start_index = 0; start_index < n - len + 1; start_index++) {
int end_index = start_index + len - 1;
if (len == 2) {
is_palindrome[start_index][end_index] = (str[start_index] == str[end_index]);
} else {
is_palindrome[start_index][end_index] =
(str[start_index] == str[end_index]) && is_palindrome[start_index + 1][end_index - 1];
}
if (is_palindrome[start_index][end_index]) {
cuts[start_index][end_index] = 0;
} else {
cuts[start_index][end_index] = INT_MAX;
for (int partition = start_index; partition <= end_index - 1; partition++) {
cuts[start_index][end_index] = std::min(cuts[start_index][end_index],
cuts[start_index][partition] +
cuts[partition + 1][end_index] + 1);
}
}
}
}
return cuts[0][n - 1];
}
} // namespace palindrome_partitioning
} // namespace dynamic_programming
/**
* @brief Test Function
* @return void
*/
static void test() {
// custom input vector
std::vector<std::string> custom_input{"nitik", "ababbbabbababa", "abdc"};
// calculated output vector by pal_part Function
std::vector<int> calculated_output(3);
for (int i = 0; i < 3; i++) {
calculated_output[i] = dynamic_programming::palindrome_partitioning::pal_part(custom_input[i]);
}
// expected output vector
std::vector<int> expected_output{2, 3, 3};
// Testing implementation via assert function
// It will throw error if any of the expected test fails
// Else it will give nothing
for (int i = 0; i < 3; i++) {
assert(expected_output[i] == calculated_output[i]);
}
std::cout << "All tests passed successfully!\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the test
return 0;
}

View File

@@ -4,7 +4,9 @@
* \brief [Breadth First Search Algorithm
* (Breadth First Search)](https://en.wikipedia.org/wiki/Breadth-first_search)
*
* \author [Ayaan Khan](http://github.com/ayaankhan98)
* \author [Ayaan Khan](https://github.com/ayaankhan98)
* \author [Aman Kumar Pandey](https://github.com/gpamangkp)
*
*
* \details
* Breadth First Search also quoted as BFS is a Graph Traversal Algorithm.
@@ -48,150 +50,153 @@
#include <iostream>
#include <queue>
#include <vector>
#include <map>
#include <list>
#include <string>
/**
* \namespace graph
* \brief Graph algorithms
*/
namespace graph {
/**
* \brief Representation of the graph as an adjacency list.
*
* For every vertex, there is a list of its neighbors in the order in which
* they were added to the graph. By default, the edges are directed, but
* an undirected graph can be represented simply by storing each each as
* two directed edges in both directions.
*/
using adjacency_list = std::vector<std::vector<int>>;
/**
* \brief
* Adds a directed edge from vertex u to vertex v.
*
* @param graph Adjacency list representation of graph
* @param u first vertex
* @param v second vertex
*
*/
void add_directed_edge(adjacency_list *graph, int u, int v) {
(*graph)[u].push_back(v);
}
/**
* \brief
* Adds an undirected edge from vertex u to vertex v.
* Essentially adds too directed edges to the adjacency list reprsentation
* of the graph.
*
* @param graph Adjacency list representation of graph
* @param u first vertex
* @param v second vertex
*
*/
void add_undirected_edge(adjacency_list *graph, int u, int v) {
add_directed_edge(graph, u, v);
add_directed_edge(graph, v, u);
}
/**
* \brief
* Function performs the breadth first search algorithm over the graph
*
* @param graph Adjacency list representation of graph
* @param start vertex from where traversing starts
* @returns a binary vector indicating which vertices were visited during the
* search.
*
*/
std::vector<bool> breadth_first_search(const adjacency_list &graph, int start) {
/// vector to keep track of visited vertices
std::vector<bool> visited(graph.size(), false);
/// queue that stores vertices that need to be further explored
std::queue<int> tracker;
/// mark the starting vertex as visited
visited[start] = true;
tracker.push(start);
while (!tracker.empty()) {
size_t vertex = tracker.front();
tracker.pop();
for (auto x : graph[vertex]) {
/// if the vertex is not visited then mark it as visited
/// and push it to the queue
if (!visited[x]) {
visited[x] = true;
tracker.push(x);
}
namespace graph{
/* Class Graph definition */
template<typename T>
class Graph{
/**
* adjacency_list maps every vertex to the list of its neighbours in the order
* in which they are added.
*/
std::map<T,std::list<T> > adjacency_list;
public:
Graph(){};
void add_edge(T u,T v, bool bidir=true){
/**
* add_edge(u,v,bidir) is used to add an edge between node u and node v
* by default , bidir is made true , i.e graph is bidirectional .
* It means if edge(u,v) is added then u-->v and v-->u both edges exist.
*
* to make the graph unidirectional pass the third parameter of add_edge as
* false which will
*/
adjacency_list[u].push_back(v); // u-->v edge added
if(bidir==true){
// if graph is bidirectional
adjacency_list[v].push_back(u); // v-->u edge added
}
}
return visited;
}
/**
* this function performs the breadth first search on graph and return a
* mapping which maps the nodes to a boolean value representing whether the
* node was traversed or not.
*/
std::map<T,bool> breadth_first_search(T src){
/// mapping to keep track of all visited nodes
std::map<T,bool> visited;
/// initialise every possible vertex to map to false
/// initially none of the vertices are unvisited
for(auto const &adjlist: adjacency_list){
visited[adjlist.first]=false;
for(auto const &node:adjacency_list[adjlist.first]){
visited[node]=false;
}
}
/// queue to store the nodes which are yet to be traversed
std::queue<T> tracker;
/// push the source vertex to queue to begin traversing
tracker.push(src);
///mark the source vertex as visited
visited[src]=true;
while(!tracker.empty()){
/// traverse the graph till no connected vertex are left
/// extract a node from queue for further traversal
T node = tracker.front();
/// remove the node from the queue
tracker.pop();
for(T const &neighbour : adjacency_list[node]){
/// check every vertex connected to the node which are still unvisited
if(!visited[neighbour]){
/// if the neighbour is unvisited , push it into the queue
tracker.push(neighbour);
/// mark the neighbour as visited
visited[neighbour]=true;
}
}
}
return visited;
}
};
/* Class definition ends */
}
} // namespace graph
/** Test function */
static void tests() {
/// Test 1 Begin
graph::adjacency_list graph(4, std::vector<int>());
graph::add_undirected_edge(&graph, 0, 1);
graph::add_undirected_edge(&graph, 1, 2);
graph::add_undirected_edge(&graph, 2, 3);
graph::Graph<int> g;
std::map<int,bool> correct_result;
g.add_edge(0,1);
g.add_edge(1,2);
g.add_edge(2,3);
correct_result[0]=true;
correct_result[1]=true;
correct_result[2]=true;
correct_result[3]=true;
std::vector<bool> returned_result = graph::breadth_first_search(graph, 2);
std::vector<bool> correct_result = {true, true, true, true};
std::map<int,bool> returned_result = g.breadth_first_search(2);
assert(std::equal(correct_result.begin(), correct_result.end(),
returned_result.begin()));
assert(returned_result==correct_result);
std::cout << "Test 1 Passed..." << std::endl;
/// Test 2 Begin
returned_result = graph::breadth_first_search(graph, 0);
assert(std::equal(correct_result.begin(), correct_result.end(),
returned_result.begin()));
returned_result = g.breadth_first_search(0);
assert(returned_result==correct_result);
std::cout << "Test 2 Passed..." << std::endl;
/// Test 3 Begins
graph.clear();
graph.resize(6);
graph::add_directed_edge(&graph, 0, 1);
graph::add_directed_edge(&graph, 0, 2);
graph::add_directed_edge(&graph, 1, 3);
graph::add_directed_edge(&graph, 2, 3);
graph::add_directed_edge(&graph, 1, 4);
graph::add_directed_edge(&graph, 3, 5);
graph::Graph<std::string> g2;
returned_result = graph::breadth_first_search(graph, 2);
correct_result = {false, false, true, true, false, true};
g2.add_edge("Gorakhpur","Lucknow",false);
g2.add_edge("Gorakhpur","Kanpur",false);
g2.add_edge("Lucknow","Agra",false);
g2.add_edge("Kanpur","Agra",false);
g2.add_edge("Lucknow","Prayagraj",false);
g2.add_edge("Agra","Noida",false);
assert(std::equal(correct_result.begin(), correct_result.end(),
returned_result.begin()));
std::map<std::string,bool> correct_res;
std::map<std::string,bool> returned_res=g2.breadth_first_search("Kanpur");
correct_res["Gorakhpur"]=false;
correct_res["Lucknow"]=false;
correct_res["Kanpur"]=true;
correct_res["Agra"]=true;
correct_res["Prayagraj"]=false;
correct_res["Noida"]=true;
assert(correct_res==returned_res);
std::cout << "Test 3 Passed..." << std::endl;
}
/** Main function */
int main() {
tests();
size_t vertices = 0, edges = 0;
std::cout << "Enter the number of vertices: ";
std::cin >> vertices;
size_t edges = 0;
std::cout << "Enter the number of edges: ";
std::cin >> edges;
graph::adjacency_list graph(vertices);
graph::Graph<int> g;
std::cout << "Enter space-separated pairs of vertices that form edges: "
<< std::endl;
while (edges--) {
int u = 0, v = 0;
std::cin >> u >> v;
// Decrement the vertex index so that we can read more convenint
// 1-based indexing from the user input.
graph::add_directed_edge(&graph, u - 1, v - 1);
g.add_edge(u,v);
}
graph::breadth_first_search(graph, 0);
g.breadth_first_search(0);
return 0;
}

View File

@@ -1,31 +1,30 @@
#include <iostream>
using namespace std;
#include <array>
#define V 6
#define INFINITY 99999
int graph[V][V] = {{0, 4, 1, 4, INFINITY, INFINITY},
{4, 0, 3, 8, 3, INFINITY},
{1, 3, 0, INFINITY, 1, INFINITY},
{4, 8, INFINITY, 0, 5, 7},
{INFINITY, 3, 1, 5, 0, INFINITY},
{INFINITY, INFINITY, INFINITY, 7, INFINITY, 0}};
void findMinimumEdge() {
for (int i = 0; i < V; i++) {
void findMinimumEdge(int INFINITY, std::array< std::array< int ,6 >,6 > graph) {
for (int i = 0; i < graph.size(); i++) {
int min = INFINITY;
int minIndex = 0;
for (int j = 0; j < V; j++) {
for (int j = 0; j < graph.size(); j++) {
if (graph[i][j] != 0 && graph[i][j] < min) {
min = graph[i][j];
minIndex = j;
}
}
cout << i << " - " << minIndex << "\t" << graph[i][minIndex] << "\n";
std::cout << i << " - " << minIndex << "\t" << graph[i][minIndex] << std::endl;
}
}
int main() {
findMinimumEdge();
constexpr int INFINITY = 99999;
std::array< std::array< int ,6 >,6 >graph
{0, 4, 1, 4, INFINITY, INFINITY,
4, 0, 3, 8, 3, INFINITY,
1, 3, 0, INFINITY, 1, INFINITY,
4, 8, INFINITY, 0, 5, 7,
INFINITY, 3, 1, 5, 0, INFINITY,
INFINITY, INFINITY, INFINITY, 7, INFINITY, 0};
findMinimumEdge(INFINITY,graph);
return 0;
}

View File

@@ -0,0 +1,251 @@
/**
* @file
* @brief [Gram Schmidt Orthogonalisation Process](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process)
*
* @details
* Takes the input of Linearly Independent Vectors,
* returns vectors orthogonal to each other.
*
* ### Algorithm
* Take the first vector of given LI vectors as first vector of Orthogonal vectors.
* Take projection of second input vector on the first vector of Orthogonal vector
* and subtract it from the 2nd LI vector.
* Take projection of third vector on the second vector of Othogonal vectors and subtract it from the 3rd LI vector.
* Keep repeating the above process until all the vectors in the given input array are exhausted.
*
* For Example:
* In R2,
* Input LI Vectors={(3,1),(2,2)}
* then Orthogonal Vectors= {(3, 1),(-0.4, 1.2)}
*
* Have defined maximum dimension of vectors to be 10 and number of vectors
* taken is 20.
* Please do not give linearly dependent vectors
*
*
* @author [Akanksha Gupta](https://github.com/Akanksha-Gupta920)
*/
#include <iostream> /// for io operations
#include <cassert> /// for assert
#include <cmath> /// for fabs
#include <array> /// for std::array
/**
* @namespace linear_algebra
* @brief Linear Algebra algorithms
*/
namespace linear_algebra {
/**
* @namespace gram_schmidt
* @brief Functions for [Gram Schmidt Orthogonalisation Process](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process)
*/
namespace gram_schmidt {
/**
* Dot product function.
* Takes 2 vectors along with their dimension as input and returns the dot product.
* @param x vector 1
* @param y vector 2
* @param c dimension of the vectors
*
* @returns sum
*/
double dot_product(const std::array<double, 10>& x, const std::array<double, 10>& y, const int& c) {
double sum = 0;
for (int i = 0; i < c; ++i) {
sum += x[i] * y[i];
}
return sum;
}
/**
* Projection Function
* Takes input of 2 vectors along with their dimension and evaluates their projection in temp
*
* @param x Vector 1
* @param y Vector 2
* @param c dimension of each vector
*
* @returns factor
*/
double projection(const std::array<double, 10>& x,const std::array<double, 10>& y,
const int& c) {
double dot = dot_product(x, y, c); ///The dot product of two vectors is taken
double anorm = dot_product(y, y, c); ///The norm of the second vector is taken.
double factor = dot / anorm; ///multiply that factor with every element in a 3rd vector, whose initial values are same as the 2nd vector.
return factor;
}
/**
* Function to print the orthogonalised vector
*
* @param r number of vectors
* @param c dimenaion of vectors
* @param B stores orthogonalised vectors
*
* @returns void
*/
void display(const int& r,const int& c,const std::array<std::array<double, 10>, 20>& B) {
for (int i = 0; i < r; ++i) {
std::cout << "Vector " << i + 1 << ": ";
for (int j = 0; j < c; ++j) {
std::cout << B[i][j] << " ";
}
std::cout << '\n';
}
}
/**
* Function for the process of Gram Schimdt Process
* @param r number of vectors
* @param c dimension of vectors
* @param A stores input of given LI vectors
* @param B stores orthogonalised vectors
*
* @returns void
*/
void gram_schmidt(int r,const int& c,const std::array<std::array<double, 10>, 20>& A,
std::array<std::array<double, 10>, 20> B) {
if (c < r) { /// we check whether appropriate dimensions are given or not.
std::cout
<< "Dimension of vector is less than number of vector, hence \n first "
<< c << " vectors are orthogonalised\n";
r = c;
}
int k = 1;
while (k <= r) {
if (k == 1) {
for (int j = 0; j < c; j++) B[0][j] = A[0][j]; ///First vector is copied as it is.
}
else {
std::array<double, 10> all_projection{}; ///array to store projections
for (int i = 0; i < c; ++i) {
all_projection[i] = 0; ///First initialised to zero
}
int l = 1;
while (l < k) {
std::array<double, 10> temp{}; ///to store previous projected array
double factor; ///to store the factor by which the previous array will change
factor = projection(A[k - 1], B[l - 1], c);
for(int i = 0; i < c; ++i)
temp[i] = B[l - 1][i] * factor; ///projected array created
for (int j = 0; j < c; ++j) {
all_projection[j] = all_projection[j] + temp[j]; ///we take the projection with all the previous vector and add them.
}
l++;
}
for (int i = 0; i < c; ++i) {
B[k - 1][i] = A[k - 1][i] - all_projection[i]; ///subtract total projection vector from the input vector
}
}
k++;
}
display(r, c, B); //for displaying orthogoanlised vectors
}
} // namespace gram_schmidt
} // namespace linear_algebra
/**
* Test Function. Process has been tested for 3 Sample Inputs
* @returns void
*/
static void test() {
std::array<std::array<double, 10>, 20> a1 = {
{{1, 0, 1, 0}, {1, 1, 1, 1}, {0, 1, 2, 1}}};
std::array<std::array<double, 10>, 20> b1 = {{0}};
double dot1 = 0;
linear_algebra::gram_schmidt::gram_schmidt(3, 4, a1, b1);
int flag = 1;
for (int i = 0; i < 2; ++i)
for (int j = i + 1; j < 3; ++j) {
dot1 = fabs(linear_algebra::gram_schmidt::dot_product(b1[i], b1[j], 4));
if (dot1 > 0.1) {
flag = 0;
break;
}
}
if (flag == 0) std::cout << "Vectors are linearly dependent\n";
assert(flag == 1);
std::cout << "Passed Test Case 1\n ";
std::array<std::array<double, 10>, 20> a2 = {{{3, 1}, {2, 2}}};
std::array<std::array<double, 10>, 20> b2 = {{0}};
double dot2 = 0;
linear_algebra::gram_schmidt::gram_schmidt(2, 2, a2, b2);
flag = 1;
for (int i = 0; i < 1; ++i)
for (int j = i + 1; j < 2; ++j) {
dot2 = fabs(linear_algebra::gram_schmidt::dot_product(b2[i], b2[j], 2));
if (dot2 > 0.1) {
flag = 0;
break;
}
}
if (flag == 0) std::cout << "Vectors are linearly dependent\n";
assert(flag == 1);
std::cout << "Passed Test Case 2\n";
std::array<std::array<double, 10>, 20> a3 = {{{1, 2, 2}, {-4, 3, 2}}};
std::array<std::array<double, 10>, 20> b3 = {{0}};
double dot3 = 0;
linear_algebra::gram_schmidt::gram_schmidt(2, 3, a3, b3);
flag = 1;
for (int i = 0; i < 1; ++i)
for (int j = i + 1; j < 2; ++j) {
dot3 = fabs(linear_algebra::gram_schmidt::dot_product(b3[i], b3[j], 3));
if (dot3 > 0.1) {
flag = 0;
break;
}
}
if (flag == 0) std::cout << "Vectors are linearly dependent\n" ;
assert(flag == 1);
std::cout << "Passed Test Case 3\n";
}
/**
* @brief Main Function
* @return 0 on exit
*/
int main() {
int r=0, c=0;
test(); // perform self tests
std::cout << "Enter the dimension of your vectors\n";
std::cin >> c;
std::cout << "Enter the number of vectors you will enter\n";
std::cin >> r;
std::array<std::array<double, 10>, 20>
A{}; ///a 2-D array for storing all vectors
std::array<std::array<double, 10>, 20> B = {
{0}}; /// a 2-D array for storing orthogonalised vectors
/// storing vectors in array A
for (int i = 0; i < r; ++i) {
std::cout << "Enter vector " << i + 1 <<'\n'; ///Input of vectors is taken
for (int j = 0; j < c; ++j) {
std::cout << "Value " << j + 1 << "th of vector: ";
std::cin >> A[i][j];
}
std::cout <<'\n';
}
linear_algebra::gram_schmidt::gram_schmidt(r, c, A, B);
double dot = 0;
int flag = 1; ///To check whether vectors are orthogonal or not
for (int i = 0; i < r - 1; ++i) {
for (int j = i + 1; j < r; ++j) {
dot = fabs(linear_algebra::gram_schmidt::dot_product(B[i], B[j], c));
if (dot > 0.1) /// take make the process numerically stable, upper bound for the dot product take 0.1
{
flag = 0;
break;
}
}
}
if (flag == 0) std::cout << "Vectors are linearly dependent\n";
return 0;
}

View File

@@ -826,7 +826,10 @@ static void test() {
return;
}
/** Driver Code */
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
// Testing
test();

138
math/fibonacci_sum.cpp Normal file
View File

@@ -0,0 +1,138 @@
/**
* @file
* @brief An algorithm to calculate the sum of [Fibonacci
* Sequence](https://en.wikipedia.org/wiki/Fibonacci_number): \f$\mathrm{F}(n) +
* \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$
* @details An algorithm to calculate the sum of Fibonacci Sequence:
* \f$\mathrm{F}(n) + \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$ where
* \f$\mathrm{F}(i)\f$ denotes the i-th Fibonacci Number . Note that F(0) = 0
* and F(1) = 1. The value of the sum is calculated using matrix exponentiation.
* Reference source:
* https://stackoverflow.com/questions/4357223/finding-the-sum-of-fibonacci-numbers
* @author [Sarthak Sahu](https://github.com/SarthakSahu1009)
*/
#include <cassert> /// for assert
#include <iostream> /// for std::cin and std::cout
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @namespace fibonacci_sum
* @brief Functions for the sum of the Fibonacci Sequence: \f$\mathrm{F}(n) +
* \mathrm{F}(n+1) + .. + \mathrm{F}(m)\f$
*/
namespace fibonacci_sum {
using matrix = std::vector<std::vector<uint64_t> >;
/**
* Function to multiply two matrices
* @param T matrix 1
* @param A martix 2
* @returns resultant matrix
*/
math::fibonacci_sum::matrix multiply(const math::fibonacci_sum::matrix &T, const math::fibonacci_sum::matrix &A) {
math::fibonacci_sum::matrix result(2, std::vector<uint64_t>(2, 0));
// multiplying matrices
result[0][0] = T[0][0]*A[0][0] + T[0][1]*A[1][0];
result[0][1] = T[0][0]*A[0][1] + T[0][1]*A[1][1];
result[1][0] = T[1][0]*A[0][0] + T[1][1]*A[1][0];
result[1][1] = T[1][0]*A[0][1] + T[1][1]*A[1][1];
return result;
}
/**
* Function to compute A^n where A is a matrix.
* @param T matrix
* @param ex power
* @returns resultant matrix
*/
math::fibonacci_sum::matrix power(math::fibonacci_sum::matrix T, uint64_t ex) {
math::fibonacci_sum::matrix A{{1, 1}, {1, 0}};
if (ex == 0 || ex == 1) {
return T;
}
T = power(T, ex / 2);
T = multiply(T, T);
if (ex & 1) {
T = multiply(T, A);
}
return T;
}
/**
* Function to compute sum of fibonacci sequence from 0 to n.
* @param n number
* @returns uint64_t ans, the sum of sequence
*/
uint64_t result(uint64_t n) {
math::fibonacci_sum::matrix T{{1, 1}, {1, 0}};
T = power(T, n);
uint64_t ans = T[0][1];
ans = (ans - 1);
return ans;
}
/**
* Function to compute sum of fibonacci sequence from n to m.
* @param n start of sequence
* @param m end of sequence
* @returns uint64_t the sum of sequence
*/
uint64_t fiboSum(uint64_t n, uint64_t m) {
return (result(m + 2) - result(n + 1));
}
} // namespace fibonacci_sum
} // namespace math
/**
* Function for testing fiboSum function.
* test cases and assert statement.
* @returns `void`
*/
static void test() {
uint64_t n = 0, m = 3;
uint64_t test_1 = math::fibonacci_sum::fiboSum(n, m);
assert(test_1 == 4);
std::cout << "Passed Test 1!" << std::endl;
n = 3;
m = 5;
uint64_t test_2 = math::fibonacci_sum::fiboSum(n, m);
assert(test_2 == 10);
std::cout << "Passed Test 2!" << std::endl;
n = 5;
m = 7;
uint64_t test_3 = math::fibonacci_sum::fiboSum(n, m);
assert(test_3 == 26);
std::cout << "Passed Test 3!" << std::endl;
n = 7;
m = 10;
uint64_t test_4 = math::fibonacci_sum::fiboSum(n, m);
assert(test_4 == 123);
std::cout << "Passed Test 4!" << std::endl;
n = 9;
m = 12;
uint64_t test_5 = math::fibonacci_sum::fiboSum(n, m);
assert(test_5 == 322);
std::cout << "Passed Test 5!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the tests
return 0;
}

99
math/lcm_sum.cpp Normal file
View File

@@ -0,0 +1,99 @@
/**
* @file
* @brief An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) + \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$
* @details An algorithm to calculate the sum of LCM: \f$\mathrm{LCM}(1,n) + \mathrm{LCM}(2,n) + \ldots + \mathrm{LCM}(n,n)\f$ where \f$\mathrm{LCM}(i,n)\f$
* denotes the Least Common Multiple of the integers i and n. For n greater than or equal to 1.
* The value of the sum is calculated by formula:
* \f[
* \sum\mathrm{LCM}(i, n) = \frac{1}{2} \left[\left(\sum (d * \mathrm{ETF}(d)) + 1\right) * n\right]
* \f]
* where \mathrm{ETF}(i) represents Euler totient function of i.
* @author [Chesta Mittal](https://github.com/chestamittal)
*/
#include <iostream> /// for std::cin and std::cout
#include <cassert> /// for assert
#include <vector> /// for std::vector
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* Function to compute sum of euler totients in sumOfEulerTotient vector
* @param num input number
* @returns int Sum of LCMs, i.e. ∑LCM(i, num) from i = 1 to num
*/
uint64_t lcmSum(const uint16_t& num) {
uint64_t i=0, j=0;
std::vector <uint64_t> eulerTotient(num+1);
std::vector <uint64_t> sumOfEulerTotient(num+1);
// storing initial values in eulerTotient vector
for(i=1; i<=num; i++) {
eulerTotient[i] = i;
}
// applying totient sieve
for(i=2; i<=num; i++) {
if(eulerTotient[i] == i) {
for(j=i; j<=num; j+=i) {
eulerTotient[j] = eulerTotient[j]/i;
eulerTotient[j] = eulerTotient[j]*(i-1);
}
}
}
// computing sum of euler totients
for(i=1; i<=num; i++) {
for(j=i; j <=num; j+=i) {
sumOfEulerTotient[j] += eulerTotient[i]*i;
}
}
return ((sumOfEulerTotient[num] + 1 ) * num) / 2;
}
} // namespace math
/**
* Function for testing lcmSum function.
* test cases and assert statement.
* @returns `void`
*/
static void test() {
uint64_t n = 2;
uint64_t test_1 = math::lcmSum(n);
assert(test_1 == 4);
std::cout << "Passed Test 1!" << std::endl;
n = 5;
uint64_t test_2 = math::lcmSum(n);
assert(test_2 == 55);
std::cout << "Passed Test 2!" << std::endl;
n = 10;
uint64_t test_3 = math::lcmSum(n);
assert(test_3 == 320);
std::cout << "Passed Test 3!" << std::endl;
n = 11;
uint64_t test_4 = math::lcmSum(n);
assert(test_4 == 616);
std::cout << "Passed Test 4!" << std::endl;
n = 15;
uint64_t test_5 = math::lcmSum(n);
assert(test_5 == 1110);
std::cout << "Passed Test 5!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the tests
return 0;
}

80
math/magic_number.cpp Normal file
View File

@@ -0,0 +1,80 @@
/**
* @file
* @brief A simple program to check if the given number is a magic number or
* not. A number is said to be a magic number, if the sum of its digits are
* calculated till a single digit recursively by adding the sum of the digits
* after every addition. If the single digit comes out to be 1,then the number
* is a magic number.
*
* This is a shortcut method to verify Magic Number.
* On dividing the input by 9, if the remainder is 1 then the number is a magic
* number else not. The divisibility rule of 9 says that a number is divisible
* by 9 if the sum of its digits are also divisible by 9. Therefore, if a number
* is divisible by 9, then, recursively, all the digit sums are also divisible
* by 9. The final digit sum is always 9. An increase of 1 in the original
* number will increase the ultimate value by 1, making it 10 and the ultimate
* sum will be 1, thus verifying that it is a magic number.
* @author [Neha Hasija](https://github.com/neha-hasija17)
*/
#include <cassert> /// for assert
#include <iostream> /// for io operations
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* Function to check if the given number is magic number or not.
* @param n number to be checked.
* @return if number is a magic number, returns true, else false.
*/
bool magic_number(const uint64_t &n) {
if (n <= 0) {
return false;
}
// result stores the modulus of @param n with 9
uint64_t result = n % 9;
// if result is 1 then the number is a magic number else not
if (result == 1) {
return true;
} else {
return false;
}
}
} // namespace math
/**
* @brief Test function
* @returns void
*/
static void tests() {
std::cout << "Test 1:\t n=60\n";
assert(math::magic_number(60) == false);
std::cout << "passed\n";
std::cout << "Test 2:\t n=730\n";
assert(math::magic_number(730) == true);
std::cout << "passed\n";
std::cout << "Test 3:\t n=0\n";
assert(math::magic_number(0) == false);
std::cout << "passed\n";
std::cout << "Test 4:\t n=479001600\n";
assert(math::magic_number(479001600) == false);
std::cout << "passed\n";
std::cout << "Test 5:\t n=-35\n";
assert(math::magic_number(-35) == false);
std::cout << "passed\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // execute the tests
return 0;
}

View File

@@ -0,0 +1,89 @@
/**
* @file
* @brief C++ Program for Modular Exponentiation Iteratively.
* @details The task is to calculate the value of an integer a raised to an
* integer exponent b under modulo c.
* @note The time complexity of this approach is O(log b).
*
* Example:
* (4^3) % 5 (where ^ stands for exponentiation and % for modulo)
* (4*4*4) % 5
* (4 % 5) * ( (4*4) % 5 )
* 4 * (16 % 5)
* 4 * 1
* 4
* We can also verify the result as 4^3 is 64 and 64 modulo 5 is 4
*
* @author [Shri2206](https://github.com/Shri2206)
*/
#include <cassert> /// for assert
#include <iostream> /// for io operations
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief This function calculates a raised to exponent b under modulo c using
* modular exponentiation.
* @param a integer base
* @param b unsigned integer exponent
* @param c integer modulo
* @return a raised to power b modulo c
*/
uint64_t power(uint64_t a, uint64_t b, uint64_t c) {
uint64_t ans = 1; /// Initialize the answer to be returned
a = a % c; /// Update a if it is more than or equal to c
if (a == 0) {
return 0; /// In case a is divisible by c;
}
while (b > 0) {
/// If b is odd, multiply a with answer
if (b & 1) {
ans = ((ans % c) * (a % c)) % c;
}
/// b must be even now
b = b >> 1; /// b = b/2
a = ((a % c) * (a % c)) % c;
}
return ans;
}
} // namespace math
/**
* Function for testing power function.
* test cases and assert statement.
* @returns `void`
*/
static void test() {
uint32_t test_case_1 = math::power(2, 5, 13);
assert(test_case_1 == 6);
std::cout << "Test 1 Passed!" << std::endl;
uint32_t test_case_2 = math::power(14, 7, 15);
assert(test_case_2 == 14);
std::cout << "Test 2 Passed!" << std::endl;
uint64_t test_case_3 = math::power(8, 15, 41);
assert(test_case_3 == 32);
std::cout << "Test 3 Passed!" << std::endl;
uint64_t test_case_4 = math::power(27, 2, 5);
assert(test_case_4 == 4);
std::cout << "Test 4 Passed!" << std::endl;
uint16_t test_case_5 = math::power(7, 3, 6);
assert(test_case_5 == 1);
std::cout << "Test 5 Passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the tests
return 0;
}

81
math/n_choose_r.cpp Normal file
View File

@@ -0,0 +1,81 @@
/**
* @file
* @brief [Combinations](https://en.wikipedia.org/wiki/Combination) n choose r function implementation
* @details
* A very basic and efficient method of calculating
* choosing r from n different choices.
* \f$ \binom{n}{r} = \frac{n!}{r! (n-r)!} \f$
*
* @author [Tajmeet Singh](https://github.com/tjgurwara99)
*/
#include <iostream> /// for io operations
#include <cassert> /// for assert
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* @brief This is the function implementation of \f$ \binom{n}{r} \f$
* @details
* We are calculating the ans with iterations
* instead of calculating three different factorials.
* Also, we are using the fact that
* \f$ \frac{n!}{r! (n-r)!} = \frac{(n - r + 1) \times \cdots \times n}{1 \times \cdots \times r} \f$
* @tparam T Only for integer types such as long, int_64 etc
* @param n \f$ n \f$ in \f$ \binom{n}{r} \f$
* @param r \f$ r \f$ in \f$ \binom{n}{r} \f$
* @returns ans \f$ \binom{n}{r} \f$
*/
template <class T>
T n_choose_r(T n, T r) {
if(r > n / 2)
r = n - r; // Because of the fact that nCr(n, r) == nCr(n, n - r)
T ans = 1;
for(int i = 1; i <= r; i++) {
ans *= n - r + i;
ans /= i;
}
return ans;
}
} // namespace math
/**
* @brief Test implementations
* @returns void
*/
static void test() {
// First test on 5 choose 2
uint8_t t = math::n_choose_r(5, 2);
assert(((void)"10 is the answer but function says otherwise.\n",
t == 10));
std::cout << "First test passes." << std::endl;
// Second test on 5 choose 3
t = math::n_choose_r(5, 3);
assert(((void)"10 is the answer but the function says otherwise.\n",
t == 10));
std::cout << "Second test passes." << std::endl;
// Third test on 3 choose 2
t = math::n_choose_r(3, 2);
assert(((void)"3 is the answer but the function says otherwise.\n",
t == 3));
std::cout << "Third test passes." << std::endl;
// Fourth test on 10 choose 4
t = math::n_choose_r(10, 4);
assert(((void)"210 is the answer but the function says otherwise.\n",
t == 210));
std::cout << "Fourth test passes." << std::endl;
}
/**
* @brief Main function
* @param argc commandline argument count (ignored)
* @param argv commandline array of arguments (ignored)
* @returns 0 on exit
*/
int main(int argc, char *argv[]) {
test(); // executing tests
return 0;
}

View File

@@ -0,0 +1,67 @@
/**
* @file
* @brief Algorithm to find sum of binomial coefficients of a given positive integer.
* @details Given a positive integer n, the task is to find the sum of binomial coefficient i.e
* nC0 + nC1 + nC2 + ... + nCn-1 + nCn
* By induction, we can prove that the sum is equal to 2^n
* @see more on https://en.wikipedia.org/wiki/Binomial_coefficient#Sums_of_the_binomial_coefficients
* @author [muskan0719](https://github.com/muskan0719)
*/
#include <iostream> /// for std::cin and std::cout
#include <cassert> /// for assert
/**
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {
/**
* Function to calculate sum of binomial coefficients
* @param n number
* @return Sum of binomial coefficients of number
*/
uint64_t binomialCoeffSum(uint64_t n)
{
// Calculating 2^n
return (1 << n);
}
} // namespace math
/**
* Function for testing binomialCoeffSum function.
* test cases and assert statement.
* @returns `void`
*/
static void test()
{
int test_case_1 = math::binomialCoeffSum(2);
assert(test_case_1==4);
std::cout<<"Test_case_1 Passed!"<<std::endl;
int test_case_2 = math::binomialCoeffSum(3);
assert(test_case_2==8);
std::cout<<"Test_case_2 Passed!"<<std::endl;
int test_case_3 = math::binomialCoeffSum(4);
assert(test_case_3==16);
std::cout<<"Test_case_3 Passed!"<<std::endl;
int test_case_4 = math::binomialCoeffSum(5);
assert(test_case_4==32);
std::cout<<"Test_case_4 Passed!"<<std::endl;
int test_case_5 = math::binomialCoeffSum(7);
assert(test_case_5==128);
std::cout<<"Test_case_5 Passed!"<<std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main()
{
test(); // execute the tests
return 0;
}

View File

@@ -4,7 +4,12 @@
* method](https://en.wikipedia.org/wiki/Regula_falsi), also known as the Secant
* method
*
* Given two points \f$a\f$ and \f$b\f$ such that \f$f(a)<0\f$ and
* \details
* First, multiple intervals are selected with the interval gap provided.
* Separate recursive function called for every root.
* Roots are printed Separatelt.
*
* For an interval [a,b] \f$a\f$ and \f$b\f$ such that \f$f(a)<0\f$ and
* \f$f(b)>0\f$, then the \f$(i+1)^\text{th}\f$ approximation is given by: \f[
* x_{i+1} = \frac{a_i\cdot f(b_i) - b_i\cdot f(a_i)}{f(b_i) - f(a_i)}
* \f]
@@ -13,62 +18,112 @@
* continued till a close enough approximation is achieved.
*
* \see newton_raphson_method.cpp, bisection_method.cpp
*
* \author Unknown author
* \author [Samruddha Patil](https://github.com/sampatil578)
*/
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <limits>
#include <cmath> /// for math operations
#include <iostream> /// for io operations
#define EPSILON \
1e-6 // std::numeric_limits<double>::epsilon() ///< system accuracy limit
#define MAX_ITERATIONS 50000 ///< Maximum number of iterations to check
/** define \f$f(x)\f$ to find root for
/**
* @namespace numerical_methods
* @brief Numerical methods
*/
static double eq(double i) {
return (std::pow(i, 3) - (4 * i) - 9); // origial equation
namespace numerical_methods {
/**
* @namespace false_position
* @brief Functions for [False Position]
* (https://en.wikipedia.org/wiki/Regula_falsi) method.
*/
namespace false_position {
/**
* @brief This function gives the value of f(x) for given x.
* @param x value for which we have to find value of f(x).
* @return value of f(x) for given x.
*/
static float eq(float x) {
return (x*x-x); // original equation
}
/** get the sign of any given number */
template <typename T>
int sgn(T val) {
return (T(0) < val) - (val < T(0));
/**
* @brief This function finds root of the equation in given interval i.e. (x1,x2).
* @param x1,x2 values for an interval in which root is present.
@param y1,y2 values of function at x1, x2 espectively.
* @return root of the equation in the given interval.
*/
static float regula_falsi(float x1,float x2,float y1,float y2){
float diff = x1-x2;
if(diff<0){
diff= (-1)*diff;
}
if(diff<0.00001){
if (y1<0) {
y1=-y1;
}
if (y2<0) {
y2=-y2;
}
if (y1<y2) {
return x1;
}
else {
return x2;
}
}
float x3=0,y3=0;
x3 = x1 - (x1-x2)*(y1)/(y1-y2);
y3 = eq(x3);
return regula_falsi(x2,x3,y2,y3);
}
/** main function */
/**
* @brief This function prints roots of the equation.
* @param root which we have to print.
* @param count which is count of the root in an interval [-range,range].
*/
void printRoot(float root, const int16_t &count){
if(count==1){
std::cout << "Your 1st root is : " << root << std::endl;
}
else if(count==2){
std::cout << "Your 2nd root is : " << root << std::endl;
}
else if(count==3){
std::cout << "Your 3rd root is : " << root << std::endl;
}
else{
std::cout << "Your "<<count<<"th root is : " << root << std::endl;
}
}
} // namespace false_position
} // namespace numerical_methods
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
double a = -1, b = 1, x, z, m, n, c;
int i;
// loop to find initial intervals a, b
for (int i = 0; i < MAX_ITERATIONS; i++) {
z = eq(a);
x = eq(b);
if (sgn(z) == sgn(x)) { // same signs, increase interval
b++;
a--;
} else { // if opposite signs, we got our interval
break;
float a=0, b=0,i=0,root=0;
int16_t count=0;
float range = 100000; //Range in which we have to find the root. (-range,range)
float gap = 0.5; // interval gap. lesser the gap more the accuracy
a = numerical_methods::false_position::eq((-1)*range);
i=((-1)*range + gap);
//while loop for selecting proper interval in provided range and with provided interval gap.
while(i<=range){
b = numerical_methods::false_position::eq(i);
if(b==0){
count++;
numerical_methods::false_position::printRoot(i,count);
}
}
std::cout << "\nFirst initial: " << a;
std::cout << "\nSecond initial: " << b;
for (i = 0; i < MAX_ITERATIONS; i++) {
m = eq(a);
n = eq(b);
c = ((a * n) - (b * m)) / (n - m);
a = c;
z = eq(c);
if (std::abs(z) < EPSILON) { // stoping criteria
break;
if(a*b<0){
root = numerical_methods::false_position::regula_falsi(i-gap,i,a,b);
count++;
numerical_methods::false_position::printRoot(root,count);
}
a=b;
i+=gap;
}
std::cout << "\n\nRoot: " << c << "\t\tSteps: " << i << std::endl;
return 0;
}

View File

@@ -0,0 +1,135 @@
/**
* @{
* \file
* \brief [Runge Kutta fourth order](https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods) method implementation
*
* \author [Rudra Prasad Das](http://github.com/rudra697)
*
* \details
* It solves the unknown value of y
* for a given value of x
* only first order differential equations
* can be solved
* \example
* it solves \frac{\mathrm{d} y}{\mathrm{d} x}= \frac{\left ( x-y \right )}{2}
* given x for given initial
* conditions
* There can be many such equations
*/
#include <iostream> /// for io operations
#include <vector> /// for using the vector container
#include <cassert> /// asserting the test functions
/**
* @brief The change() function is used
* to return the updated iterative value corresponding
* to the given function
* @param x is the value corresponding to the x coordinate
* @param y is the value corresponding to the y coordinate
* @returns the computed function value at that call
*/
static double change(double x, double y)
{
return ((x - y)/2.0);
}
/**
* @namespace numerical_methods
* @brief Numerical Methods
*/
namespace numerical_methods {
/**
* @namespace runge_kutta
* @brief Functions for [Runge Kutta fourth order](https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods) method
*/
namespace runge_kutta {
/**
* @brief the Runge Kutta method finds the value of integration of a function in the given limits.
* the lower limit of integration as the initial value and the upper limit is the given x
* @param init_x is the value of initial x and is updated after each call
* @param init_y is the value of initial x and is updated after each call
* @param x is current iteration at which the function needs to be evaluated
* @param h is the step value
* @returns the value of y at thr required value of x from the initial conditions
*/
double rungeKutta(double init_x, const double &init_y, const double &x, const double &h)
{
// Count number of iterations
// using step size or
// step height h
// n calucates the number of iterations
// k1, k2, k3, k4 are the Runge Kutta variables
// used for calculation of y at each iteration
auto n = static_cast<uint64_t>((x - init_x) / h);
// used a vector container for the variables
std::vector<double> k(4,0.0);
// Iterate for number of iterations
double y = init_y;
for (int i=1; i<=n; ++i)
{
// Apply Runge Kutta Formulas
// to find next value of y
k[0] = h*change(init_x, y);
k[1] = h*change(init_x + 0.5*h, y + 0.5*k[0]);
k[2] = h*change(init_x + 0.5*h, y + 0.5*k[1]);
k[3] = h*change(init_x + h, y + k[2]);
// Update next value of y
y += (1.0/6.0)*(k[0] + 2*k[1] + 2*k[2] + k[3]);
// Update next value of x
init_x += h;
}
return y;
}
} // namespace runge_kutta
} // namespace numerical_methods
/**
* @brief Tests to check algorithm implementation.
* @returns void
*/
static void test()
{
std::cout << "The Runge Kutta function will be tested on the basis of precomputed values\n";
std::cout << "Test 1...." << "\n";
double valfirst=numerical_methods::runge_kutta::rungeKutta(2,3,4,0.2); // Tests the function with pre calculated values
assert(valfirst==3.10363932323749570);
std::cout << "Passed Test 1\n";
std::cout << "Test 2...." << "\n";
double valsec=numerical_methods::runge_kutta::rungeKutta(1,2,5,0.1); // The value of step changed
assert(valsec==3.40600589380261409);
std::cout << "Passed Test 2\n";
std::cout << "Test 3...." << "\n";
double valthird=numerical_methods::runge_kutta::rungeKutta(-1,3,4,0.1); // Tested with negative value
assert(valthird==2.49251005860244268);
std::cout << "Passed Test 3\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main()
{
test(); // Execute the tests
return 0;
}

104
sorting/cycle_sort.cpp Normal file
View File

@@ -0,0 +1,104 @@
/**
* @file
* @brief Implementation of [Cycle sort](https://en.wikipedia.org/wiki/Cycle_sort) algorithm
*
* @details
* Cycle Sort is a sorting algorithm that works in \f$O(n^2)\f$ time in best cas and works in \f$O(n^2)\f$ in worst case.
* If a element is already at its correct position, do nothing.
* If a element is not at its correct position, we then need to move it to its correct position by computing the correct positions.Therefore, we should make sure the duplicate elements.
*
* @author [TsungHan Ho](https://github.com/dalaoqi)
*/
#include <algorithm> /// for std::is_sorted, std::swap
#include <cassert> /// for assert
#include <iostream> /// for io operations
#include <vector> /// for std::vector
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace cycle_sort
* @brief Functions for [Cycle sort](https://en.wikipedia.org/wiki/Cycle_sort) algorithm
*/
namespace cycle_sort {
/**
* @brief The main function implements cycleSort
* @tparam T type of array
* @param in_arr array to be sorted
* @returns void
*/
template <typename T>
std::vector<T> cycleSort(const std::vector<T> &in_arr) {
std::vector<T> arr(in_arr);
for (size_t cycle_start = 0; cycle_start <= arr.size() - 1; cycle_start++) {
// initialize item
T item = arr[cycle_start];
// Count the number of elements smaller than item, this number is the correct index of item.
int pos = cycle_start;
for (size_t i = cycle_start + 1; i < arr.size(); i++) {
if (arr[i] < item) {
pos++;
}
}
// item is already in correct position
if (pos == cycle_start) {
continue;
}
// duplicate elements
while (item == arr[pos]) pos += 1;
std::swap(item, arr[pos]);
// Rest of the elements
while (pos != cycle_start) {
pos = cycle_start;
// Find position where we put the element
for (size_t i = cycle_start + 1; i < arr.size(); i++) {
if (arr[i] < item) {
pos += 1;
}
}
// duplicate elements
while (item == arr[pos]) pos += 1;
std::swap(item, arr[pos]);
}
}
return arr;
}
} // namespace cycle_sort
} // namespace sorting
/**
* @brief Test implementations
* @returns void
*/
static void test() {
// [506, 48, 123, 79, 0, 362, 951, 500, 0] return [0, 0, 48, 79, 123, 362, 500, 506, 951]
std::vector<int> array1 = {506, 48, 123, 79, 0, 362, 951, 500, 0};
std::cout << "Test 1... ";
std::vector<int> arr1 = sorting::cycle_sort::cycleSort(array1);
assert(std::is_sorted(std::begin(arr1), std::end(arr1)));
std::cout << "passed" << std::endl;
// [4.3, -6.5, -7.4, 0, 2.7, 1.8] return [-7.4, -6.5, 0, 1.8, 2.7, 4.3]
std::vector<double> array2 = {4.3, -6.5, -7.4, 0, 2.7, 1.8};
std::cout << "Test 2... ";
std::vector<double> arr2 = sorting::cycle_sort::cycleSort(array2);
assert(std::is_sorted(std::begin(arr2), std::end(arr2)));
std::cout << "passed" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the test
return 0;
}

View File

@@ -1,26 +1,25 @@
/**
* @file
* @brief pancake sort sorts a disordered stack of pancakes by flipping any number of pancakes using a spatula using minimum number of flips.
* @brief pancake sort sorts a disordered stack of pancakes by flipping any
* number of pancakes using a spatula using minimum number of flips.
*
* @details
* Unlike a traditional sorting algorithm, which attempts to sort with the fewest comparisons possible,
* the goal is to sort the sequence in as few reversals as possible.
* Overall time complexity of pancake sort is O(n^2)
* For example: example 1:-
* Disordered pancake sizes: {2,5,3,7,8}
* Sorted: {2,3,5,7,8}
* For example: example 2:-
* Disordered pancake sizes: {22,51,37,73,81}
* Sorted: {22,37,51,73,81}
* Unlike a traditional sorting algorithm, which attempts to sort with the
* fewest comparisons possible, the goal is to sort the sequence in as few
* reversals as possible. Overall time complexity of pancake sort is O(n^2) For
* example: example 1:- Disordered pancake sizes: {2,5,3,7,8} Sorted:
* {2,3,5,7,8} For example: example 2:- Disordered pancake sizes:
* {22,51,37,73,81} Sorted: {22,37,51,73,81}
* @author [Divyansh Gupta](https://github.com/divyansh12323)
* @see more on [Pancake sort](https://en.wikipedia.org/wiki/Pancake_sorting)
* @see related problem at [Leetcode](https://leetcode.com/problems/pancake-sorting/)
*/
* @see related problem at
* [Leetcode](https://leetcode.com/problems/pancake-sorting/)
*/
#include <iostream> // for io operations
#include <vector> // for std::vector
#include <algorithm> // for std::is_sorted
#include <cassert> // for std::assert
#include <iostream> // for io operations
#include <vector> // for std::vector
/**
* @namespace sorting
@@ -29,52 +28,54 @@
namespace sorting {
/**
* @namespace pancake_sort
* @brief Functions for [Pancake sort](https://en.wikipedia.org/wiki/Pancake_sorting) algorithm
* @brief Functions for [Pancake
* sort](https://en.wikipedia.org/wiki/Pancake_sorting) algorithm
*/
namespace pancake_sort {
/**
* @brief This implementation is for reversing elements in a a C-style array .
* @param [start,end] arr our vector of elements.
* @param start starting index of array
* @param end ending index of array
* @returns void
*/
template<typename T>
void reverse(std::vector<T> &arr, int start, int end) {
T temp; //Temporary variable
while (start <= end) {
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
/**
* @brief This implementation is for reversing elements in a a C-style array .
* @param [start,end] arr our vector of elements.
* @param start starting index of array
* @param end ending index of array
* @returns void
*/
template <typename T>
void reverse(std::vector<T> &arr, int start, int end) {
T temp; // Temporary variable
while (start <= end) {
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
/**
* @brief This implementation is for a C-style array input that gets modified in place.
* @param [start,end] arr our vector of elements.
* @param size size of given array
* @returns 0 on exit
*/
template<typename T>
int pancakeSort(std::vector<T> &arr, int size) {
for (int i = size; i > 1; --i) {
int max_index = 0, j; //intialize some variables.
T max_value = 0;
for (j = 0; j < i; j++) {
if (arr[j] >= max_value) {
max_value = arr[j];
max_index = j;
}
}
if (max_index != i - 1) //check for reversing
{
reverse(arr, 0, max_index);
reverse(arr, 0, i - 1);
}
/**
* @brief This implementation is for a C-style array input that gets modified in
* place.
* @param [start,end] arr our vector of elements.
* @param size size of given array
* @returns 0 on exit
*/
template <typename T>
int pancakeSort(std::vector<T> &arr, int size) {
for (int i = size; i > 1; --i) {
int max_index = 0, j = 0; // intialize some variables.
T max_value = 0;
for (j = 0; j < i; j++) {
if (arr[j] >= max_value) {
max_value = arr[j];
max_index = j;
}
}
return 0;
if (max_index != i - 1) // check for reversing
{
reverse(arr, 0, max_index);
reverse(arr, 0, i - 1);
}
}
return 0;
}
} // namespace pancake_sort
} // namespace sorting
@@ -98,7 +99,8 @@ static void test() {
// example 2: vector of double
const int size2 = 8;
std::cout << "\nTest 2- as std::vector<double>...";
std::vector<double> arr2 = {23.56, 10.62, 200.78, 111.484, 3.9, 1.2, 61.77, 79.6};
std::vector<double> arr2 = {23.56, 10.62, 200.78, 111.484,
3.9, 1.2, 61.77, 79.6};
sorting::pancake_sort::pancakeSort(arr2, size2);
assert(std::is_sorted(arr2.begin(), arr2.end()));
std::cout << "Passed\n";

118
sorting/radix_sort2.cpp Normal file
View File

@@ -0,0 +1,118 @@
/**
* @file
* @brief Algorithm of [Radix sort](https://en.wikipedia.org/wiki/Radix_sort)
* @author [Suyash Jaiswal](https://github.com/Suyashjaiswal)
* @details
* Sort the vector of unsigned integers using radix sort i.e. sorting digit by digit
* using [Counting Sort](https://en.wikipedia.org/wiki/Counting_sort) as subroutine.
* Running time of radix sort is O(d*(n+b)) where b is the base for representing
* numbers and d in the max digits in input integers and n is number of unsigned integers.
* consider example for n = 5, aray elements = 432,234,143,332,123
* sorting digit by digit
* sorting according to
* 1) 1st digit place
* => 432, 332, 143, 123, 234
*
* 2) 2nd digit place
* => 123, 432, 332, 234, 143
*
* 3) 3rd digit place
* => 123, 143, 234, 332, 432
*
* using count sort at each step, which is stable.
* stable => already sorted according to previous digits.
*/
/// header files
#include <iostream> /// for io operations
#include <vector> /// for std::vector
#include <algorithm> /// for collection of functions
#include <cassert> /// for a macro called assert which can be used to verify assumptions
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace radix_sort
* @brief Functions for [Radix sort](https://en.wikipedia.org/wiki/Radix_sort)
* algorithm
*/
namespace radix_sort {
/**
* @brief Function to sort vector according to current digit using stable
* sorting.
* @param cur_digit - sort according to the cur_digit
* @param ar - vector to be sorted
* @returns std::vector sorted till ith digit
*/
std::vector<uint64_t> step_ith(uint16_t cur_digit, const std::vector<uint64_t>& ar) { // sorting according to current digit.
int n = ar.size();
std::vector<uint32_t> position(10, 0);
for (int i = 0; i < n; ++i) {
position[(ar[i] / cur_digit) %
10]++; // counting frequency of 0-9 at cur_digit.
}
int cur = 0;
for (int i = 0; i < 10; ++i) {
int a = position[i];
position[i] = cur; // assingning starting position of 0-9.
cur += a;
}
std::vector<uint64_t> temp(n);
for (int i = 0; i < n; ++i) {
temp[position[(ar[i] / cur_digit) % 10]] =
ar[i]; // storing ar[i] in ar[i]'s cur_digit expected position of
// this step.
position[(ar[i] / cur_digit) %
10]++; // incrementing ar[i]'s cur_digit position by 1, as
// current place used by ar[i].
}
return temp;
}
/**
* @brief Function to sort vector digit by digit.
* @param ar - vector to be sorted
* @returns sorted vector
*/
std::vector<uint64_t> radix(const std::vector<uint64_t>& ar) {
uint64_t max_ele = *max_element(ar.begin(), ar.end()); // returns the max element.
std::vector<uint64_t> temp = ar;
for (int i = 1; max_ele / i > 0;
i *= 10) { // loop breaks when i > max_ele because no further digits
// left to makes changes in aray.
temp = step_ith(i,temp);
}
for (uint64_t i : temp) {
std::cout << i << " ";
}
std::cout << "\n";
return temp;
}
} // namespace radix_sort
} // namespace sorting
/**
* @brief Function to test the above algorithm
* @returns none
*/
static void tests() {
/// Test 1
std::vector<uint64_t> ar1 = {432, 234, 143, 332, 123};
ar1 = sorting::radix_sort::radix(ar1);
assert(std::is_sorted(ar1.begin(), ar1.end()));
/// Test 2
std::vector<uint64_t> ar2 = {213, 3214, 123, 111, 112, 142,
133, 132, 32, 12, 113};
ar2 = sorting::radix_sort::radix(ar2);
assert(std::is_sorted(ar2.begin(), ar2.end()));
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // execute the tests
return 0;
}

136
sorting/wiggle_sort.cpp Normal file
View File

@@ -0,0 +1,136 @@
/**
* \addtogroup sorting Sorting Algorithms
* @{
* \file
* \brief [Wiggle Sort Algorithm]
* (https://leetcode.com/problems/wiggle-sort-ii/) Implementation
*
* \author [Roshan Kanwar](http://github.com/roshan0708)
*
* \details
* Wiggle Sort sorts the array into a wave like array.
* An array arr[0..n-1] is sorted in wave form,
* if arr[0] >= arr[1] <= arr[2] >= arr[3] <= arr[4] >= …..
*
* \example
* arr = [1,1,5,6,1,4], after wiggle sort arr will become equal to [1,1,6,1,5,4]
* arr = [2,8,9,1,7], after wiggle sort arr will become equal to [8,2,9,1,7]
*/
#include <iostream> /// for io operations
#include <algorithm>
#include <vector>
#include <cassert>
#include <ctime>
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace wiggle_sort
* @brief Functions for [Wiggle Sort](https://leetcode.com/problems/wiggle-sort-ii/) algorithm
*/
namespace wiggle_sort {
/**
*
* @brief Function used for sorting the elements in wave form.
* @details
* Checking whether the even indexed elements are greater than
* their adjacent odd elements.
* Traversing all even indexed elements of the input arr.
* If current element is smaller than the previous odd element, swap them.
* If current element is smaller than the next odd element, swap them.
*
* @param arr input array (unsorted elements)
*
*/
template<typename T> // this allows to have vectors of ints, double, float, etc
std::vector<T> wiggleSort(const std::vector<T>& arr) {
uint32_t size = arr.size();
std::vector<T> out(arr); // create a copy of input vector. this way, the original input vector does not get modified. a sorted array is is returned.
for(int i = 0; i < size ; i +=2) {
if(i > 0 && out[i-1] > out[i]) {
std::swap(out[i],out[i-1]); //swapping the two values
}
if(i < size - 1 && out[i] < out[i+1]) {
std::swap(out[i],out[i+1]); //swapping the two values
}
}
return out; //returns the sorted vector
}
} // namespace wiggle_sort
} // namespace sorting
/**
*
* @brief Utility function used for printing the elements.
* Prints elements of the array after they're sorted using wiggle sort algorithm.
*
* @param arr array containing the sorted elements
*
*/
template<typename T>
static void displayElements(const std::vector<T> &arr) {
uint32_t size = arr.size();
std::cout << "Sorted elements are as follows: ";
std::cout << "[";
for(int i = 0 ; i < size ; i++ ) {
std::cout << arr[i] ;
if(i != size - 1) {
std::cout << ", " ;
}
}
std::cout << "]"<<std::endl;
}
/**
* Test function
* @returns void
*/
static void test() {
std::srand(std::time(nullptr)); // initialize random number generator
std::vector<float> data1(100);
for (auto &d: data1) { // generate random numbers between -5.0 and 4.99
d = float(std::rand() % 1000 - 500) / 100.f;
}
std::vector<float> sorted = sorting::wiggle_sort::wiggleSort<float>(data1);
displayElements(sorted);
for(uint32_t j = 0; j < data1.size(); j+=2) {
assert(data1[j] <= data1[j+1] && data1[j+1] >= data1[j+2]); // check the validation condition
}
std::cout << "Test 1 passed\n";
}
/** Driver Code */
int main() {
test();
return 0;
}
/** @} */