Merge branch 'master' into fixgraph

This commit is contained in:
Ayaan Khan 2020-07-25 07:57:05 +05:30 committed by GitHub
commit c107f99db9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 996 additions and 24 deletions

View File

@ -5,5 +5,7 @@ RUN sudo apt-get update \
doxygen \
graphviz \
ninja-build \
freeglut3 \
freeglut3-dev \
&& pip install cpplint \
&& sudo rm -rf /var/lib/apt/lists/*

View File

@ -11,7 +11,10 @@
* [Sudoku Solve](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/sudoku_solve.cpp)
## 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)
* [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)
## Data Structures
* [Avltree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/avltree.cpp)
@ -33,6 +36,7 @@
* [Queue Using Array2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_array2.cpp)
* [Queue Using Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_linked_list.cpp)
* [Queue Using Linkedlist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_linkedlist.cpp)
* [Queue Using Two Stacks](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_two_stacks.cpp)
* [Skip List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/skip_list.cpp)
* [Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/stack.h)
* [Stack Using Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/stack_using_array.cpp)
@ -215,12 +219,14 @@
## Sorting
* [Bead Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bead_sort.cpp)
* [Bitonic Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bitonic_sort.cpp)
* [Bogo Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bogo_sort.cpp)
* [Bubble Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bubble_sort.cpp)
* [Bucket Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bucket_sort.cpp)
* [Cocktail Selection Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/cocktail_selection_sort.cpp)
* [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)
* [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)
* [Library Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/library_sort.cpp)
@ -229,6 +235,7 @@
* [Numeric String Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/numeric_string_sort.cpp)
* [Odd Even Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/odd_even_sort.cpp)
* [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)
* [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)

124
ciphers/caesar_cipher.cpp Normal file
View File

@ -0,0 +1,124 @@
/**
* @file caesar_cipher.cpp
* @brief Implementation of [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher) algorithm.
*
* @details
* In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher,
* Caesar's code or Caesar shift, is one of the simplest and most widely known encryption
* techniques. It is a type of substitution cipher in which each letter in the plaintext
* is replaced by a letter some fixed number of positions down the alphabet. For example,
* with a left shift of 3, D would be replaced by A, E would become B, and so on.
* The method is named after Julius Caesar, who used it in his private correspondence.
*
* ### Algorithm
* The encryption can also be represented using modular arithmetic by first transforming
* the letters into numbers, according to the scheme, A 0, B 1, ..., Z 25.
* Encryption of a letter x by a shift n can be described mathematically as,
* \f[ E(x) = (x + n)\;\mbox{mod}\; 26\f]
* while decryption can be described as,
* \f[ D(x) = (x - n) \;\mbox{mod}\; 26\f]
*
* \note This program implements caesar cipher for only uppercase English alphabet characters (i.e. A-Z).
*
* @author [Deep Raval](https://github.com/imdeep2905)
*/
#include <iostream>
#include <string>
#include <cassert>
/** \namespace ciphers
* \brief Algorithms for encryption and decryption
*/
namespace ciphers {
/** \namespace caesar
* \brief Functions for [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher) algorithm.
*/
namespace caesar {
namespace {
/**
* This function finds character for given value (i.e.A-Z)
* @param x value for which we want character
* @returns corresponding character for perticular value
*/
inline char get_char(const int x) {
// By adding 65 we are scaling 0-25 to 65-90.
// Which are in fact ASCII values of A-Z.
return char(x + 65);
}
/**
* This function finds value for given character (i.e.0-25)
* @param c character for which we want value
* @returns returns corresponding value for perticular character
*/
inline int get_value(const char c) {
// A-Z have ASCII values in range 65-90.
// Hence subtracting 65 will scale them to 0-25.
return int(c - 65);
}
} // Unnamed namespace
/**
* Encrypt given text using caesar cipher.
* @param text text to be encrypted
* @param shift number of shifts to be applied
* @returns new encrypted text
*/
std::string encrypt (const std::string &text, const int &shift) {
std::string encrypted_text = ""; // Empty string to store encrypted text
for (char c : text) { // Going through each character
int place_value = get_value(c); // Getting value of character (i.e. 0-25)
place_value = (place_value + shift) % 26; // Applying encryption formula
char new_char = get_char(place_value); // Getting new character from new value (i.e. A-Z)
encrypted_text += new_char; // Appending encrypted character
}
return encrypted_text; // Returning encrypted text
}
/**
* Decrypt given text using caesar cipher.
* @param text text to be decrypted
* @param shift number of shifts to be applied
* @returns new decrypted text
*/
std::string decrypt (const std::string &text, const int &shift) {
std::string decrypted_text = ""; // Empty string to store decrypted text
for (char c : text) { // Going through each character
int place_value = get_value(c); // Getting value of character (i.e. 0-25)
place_value = (place_value - shift) % 26;// Applying decryption formula
if(place_value < 0) { // Handling case where remainder is negative
place_value = place_value + 26;
}
char new_char = get_char(place_value); // Getting original character from decrypted value (i.e. A-Z)
decrypted_text += new_char; // Appending decrypted character
}
return decrypted_text; // Returning decrypted text
}
} // namespace caesar
} // namespace ciphers
/**
* Function to test above algorithm
*/
void test() {
// Test 1
std::string text1 = "ALANTURING";
std::string encrypted1 = ciphers::caesar::encrypt(text1, 17);
std::string decrypted1 = ciphers::caesar::decrypt(encrypted1, 17);
assert(text1 == decrypted1);
std::cout << "Original text : " << text1;
std::cout << " , Encrypted text (with shift = 21) : " << encrypted1;
std::cout << " , Decrypted text : "<< decrypted1 << std::endl;
// Test 2
std::string text2 = "HELLOWORLD";
std::string encrypted2 = ciphers::caesar::encrypt(text2, 1729);
std::string decrypted2 = ciphers::caesar::decrypt(encrypted2, 1729);
assert(text2 == decrypted2);
std::cout << "Original text : " << text2;
std::cout << " , Encrypted text (with shift = 1729) : " << encrypted2;
std::cout << " , Decrypted text : "<< decrypted2 << std::endl;
}
/** Driver Code */
int main() {
// Testing
test();
return 0;
}

135
ciphers/vigenere_cipher.cpp Normal file
View File

@ -0,0 +1,135 @@
/**
* @file vigenere_cipher.cpp
* @brief Implementation of [Vigenère cipher](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) algorithm.
*
* @details
* The Vigenère cipher is a method of encrypting alphabetic text by using a series of interwoven vigenere
* ciphers, based on the letters of a keyword. It employs a form of polyalphabetic substitution.
*
* ### Algorithm
* The encryption can also be represented using modular arithmetic by first transforming
* the letters into numbers, according to the scheme, A 0, B 1, ..., Z 25.
* Encryption of \f$i^{th}\f$ character in Message M by key K can be described mathematically as,
*
* \f[ E_{K}(M_{i}) = (M_{i} + K_{i})\;\mbox{mod}\; 26\f]
*
* while decryption of \f$i^{th}\f$ character in Cipher C by key K can be described mathematically as,
*
* \f[ D_{k}(C_{i}) = (C_{i} - K_{i} + 26)\;\mbox{mod}\; 26\f]
*
* Where \f$K_{i}\f$ denotes corresponding character in key. If \f$|key| < |text|\f$ than
* same key is repeated untill their lengths are equal.
*
* For Example,
* If M = "ATTACKATDAWN" and K = "LEMON" than K becomes "LEMONLEMONLE".
*
* \note Rather than creating new key of equal length this program does this by using modular index for key
* (i.e. \f$(j + 1) \;\mbox{mod}\; |\mbox{key}|\f$)
*
* \note This program implements Vigenère cipher for only uppercase English alphabet characters (i.e. A-Z).
*
* @author [Deep Raval](https://github.com/imdeep2905)
*/
#include <iostream>
#include <string>
#include <cassert>
/** \namespace ciphers
* \brief Algorithms for encryption and decryption
*/
namespace ciphers {
/** \namespace vigenere
* \brief Functions for [vigenère cipher](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) algorithm.
*/
namespace vigenere {
namespace {
/**
* This function finds character for given value (i.e.A-Z)
* @param x value for which we want character
* @return corresponding character for perticular value
*/
inline char get_char(const int x) {
// By adding 65 we are scaling 0-25 to 65-90.
// Which are in fact ASCII values of A-Z.
return char(x + 65);
}
/**
* This function finds value for given character (i.e.0-25)
* @param c character for which we want value
* @return returns corresponding value for perticular character
*/
inline int get_value(const char c) {
// A-Z have ASCII values in range 65-90.
// Hence subtracting 65 will scale them to 0-25.
return int(c - 65);
}
} // Unnamed namespace
/**
* Encrypt given text using vigenere cipher.
* @param text text to be encrypted
* @param key to be used for encryption
* @return new encrypted text
*/
std::string encrypt (const std::string &text, const std::string &key) {
std::string encrypted_text = ""; // Empty string to store encrypted text
// Going through each character of text and key
// Note that key is visited in circular way hence j = (j + 1) % |key|
for(size_t i = 0, j = 0; i < text.length(); i++, j = (j + 1) % key.length()) {
int place_value_text = get_value(text[i]); // Getting value of character in text
int place_value_key = get_value(key[j]); // Getting value of character in key
place_value_text = (place_value_text + place_value_key) % 26; // Applying encryption
char encrypted_char = get_char(place_value_text); // Getting new character from encrypted value
encrypted_text += encrypted_char; // Appending encrypted character
}
return encrypted_text; // Returning encrypted text
}
/**
* Decrypt given text using vigenere cipher.
* @param text text to be decrypted
* @param key key to be used for decryption
* @return new decrypted text
*/
std::string decrypt (const std::string &text, const std::string &key) {
// Going through each character of text and key
// Note that key is visited in circular way hence j = (j + 1) % |key|
std::string decrypted_text = ""; // Empty string to store decrypted text
for(size_t i = 0, j = 0; i < text.length(); i++, j = (j + 1) % key.length()) {
int place_value_text = get_value(text[i]); // Getting value of character in text
int place_value_key = get_value(key[j]); // Getting value of character in key
place_value_text = (place_value_text - place_value_key + 26) % 26; // Applying decryption
char decrypted_char = get_char(place_value_text); // Getting new character from decrypted value
decrypted_text += decrypted_char; // Appending decrypted character
}
return decrypted_text; // Returning decrypted text
}
} // namespace vigenere
} // namespace ciphers
/**
* Function to test above algorithm
*/
void test() {
// Test 1
std::string text1 = "NIKOLATESLA";
std::string encrypted1 = ciphers::vigenere::encrypt(text1, "TESLA");
std::string decrypted1 = ciphers::vigenere::decrypt(encrypted1, "TESLA");
assert(text1 == decrypted1);
std::cout << "Original text : " << text1;
std::cout << " , Encrypted text (with key = TESLA) : " << encrypted1;
std::cout << " , Decrypted text : "<< decrypted1 << std::endl;
// Test 2
std::string text2 = "GOOGLEIT";
std::string encrypted2 = ciphers::vigenere::encrypt(text2, "REALLY");
std::string decrypted2 = ciphers::vigenere::decrypt(encrypted2, "REALLY");
assert(text2 == decrypted2);
std::cout << "Original text : " << text2;
std::cout << " , Encrypted text (with key = REALLY) : " << encrypted2;
std::cout << " , Decrypted text : "<< decrypted2 << std::endl;
}
/** Driver Code */
int main() {
// Testing
test();
return 0;
}

99
ciphers/xor_cipher.cpp Normal file
View File

@ -0,0 +1,99 @@
/**
* @file xor_cipher.cpp
* @brief Implementation of [XOR cipher](https://en.wikipedia.org/wiki/XOR_cipher) algorithm.
*
* @details
* In cryptography, the simple XOR cipher is a type of additive cipher, an encryption
* algorithm that operates according to the principles:
*
* * \f$A {\oplus} 0 = A\f$
* * \f$A {\oplus} A = 0\f$
* * \f$ (A {\oplus} B) {\oplus} C = A {\oplus} (B {\oplus} C)\f$
* * \f$ (B {\oplus} A) {\oplus} B = B {\oplus} 0 = B \f$
*
*
* where \f$\oplus\f$ symbol denotes the exclusive disjunction (XOR) operation.
* This operation is sometimes called modulus 2 addition (or subtraction, which is identical).
* With this logic, a string of text can be encrypted by applying the bitwise XOR operator to
* every character using a given key. To decrypt the output, merely reapplying the XOR function
* with the key will remove the cipher.
*
* ### Algorithm
* Choose the key for encryption and apply XOR operation to each character of a string.
* Reapplying XOR operation to each character of encrypted string will give original string back.
*
* \note This program implements XOR Cipher for string with ASCII characters.
*
* @author [Deep Raval](https://github.com/imdeep2905)
*/
#include <iostream>
#include <string>
#include <cassert>
/** \namespace ciphers
* \brief Algorithms for encryption and decryption
*/
namespace ciphers {
/** \namespace XOR
* \brief Functions for [XOR cipher](https://en.wikipedia.org/wiki/XOR_cipher) algorithm.
*/
namespace XOR {
/**
* Encrypt given text using XOR cipher.
* @param text text to be encrypted
* @param key to be used for encyption
* @return new encrypted text
*/
std::string encrypt (const std::string &text, const int &key) {
std::string encrypted_text = ""; // Empty string to store encrypted text
for (auto &c: text) { // Going through each character
char encrypted_char = char(c ^ key); // Applying encyption
encrypted_text += encrypted_char; // Appending encrypted character
}
return encrypted_text; // Returning encrypted text
}
/**
* Decrypt given text using XOR cipher.
* @param text text to be encrypted
* @param key to be used for decryption
* @return new decrypted text
*/
std::string decrypt (const std::string &text, const int &key) {
std::string decrypted_text = ""; // Empty string to store decrypted text
for (auto &c : text) { // Going through each character
char decrypted_char = char(c ^ key); // Applying decryption
decrypted_text += decrypted_char; // Appending decrypted character
}
return decrypted_text; // Returning decrypted text
}
} // namespace XOR
} // namespace ciphers
/**
* Function to test above algorithm
*/
void test() {
// Test 1
std::string text1 = "Whipalsh! : Do watch this movie...";
std::string encrypted1 = ciphers::XOR::encrypt(text1, 17);
std::string decrypted1 = ciphers::XOR::decrypt(encrypted1, 17);
assert(text1 == decrypted1);
std::cout << "Original text : " << text1;
std::cout << " , Encrypted text (with key = 17) : " << encrypted1;
std::cout << " , Decrypted text : "<< decrypted1 << std::endl;
// Test 2
std::string text2 = "->Valar M0rghulis<-";
std::string encrypted2 = ciphers::XOR::encrypt(text2, 29);
std::string decrypted2 = ciphers::XOR::decrypt(encrypted2, 29);
assert(text2 == decrypted2);
std::cout << "Original text : " << text2;
std::cout << " , Encrypted text (with key = 29) : " << encrypted2;
std::cout << " , Decrypted text : "<< decrypted2 << std::endl;
}
/** Driver Code */
int main() {
// Testing
test();
return 0;
}

View File

@ -0,0 +1,144 @@
/**
* @author [shoniavika](https://github.com/shoniavika)
* @file
*
* Implementation of a Queue using two Stacks.
*/
#include <cassert>
#include <iostream>
#include <stack>
namespace {
/**
* @brief Queue data structure. Stores elements in FIFO
* (first-in-first-out) manner.
* @tparam T datatype to store in the queue
*/
template <typename T>
class MyQueue {
private:
std::stack<T> s1, s2;
public:
/**
* Constructor for queue.
*/
MyQueue() = default;
/**
* Pushes x to the back of queue.
*/
void push(T x);
/**
* Removes an element from the front of the queue.
*/
const T& pop();
/**
* Returns first element, without removing it.
*/
const T& peek() const;
/**
* Returns whether the queue is empty.
*/
bool empty() const;
};
/**
* Appends element to the end of the queue
*/
template <typename T>
void MyQueue<T>::push(T x) {
while (!s2.empty()) {
s1.push(s2.top());
s2.pop();
}
s2.push(x);
while (!s1.empty()) {
s2.push(s1.top());
s1.pop();
}
}
/**
* Removes element from the front of the queue
*/
template <typename T>
const T& MyQueue<T>::pop() {
const T& temp = MyQueue::peek();
s2.pop();
return temp;
}
/**
* Returns element in the front.
* Does not remove it.
*/
template <typename T>
const T& MyQueue<T>::peek() const {
if (!empty()) {
return s2.top();
}
std::cerr << "Queue is empty" << std::endl;
exit(0);
}
/**
* Checks whether a queue is empty
*/
template <typename T>
bool MyQueue<T>::empty() const {
return s2.empty() && s1.empty();
}
} // namespace
/**
* Testing function
*/
void queue_test() {
MyQueue<int> que;
std::cout << "Test #1\n";
que.push(2);
que.push(5);
que.push(0);
assert(que.peek() == 2);
assert(que.pop() == 2);
assert(que.peek() == 5);
assert(que.pop() == 5);
assert(que.peek() == 0);
assert(que.pop() == 0);
assert(que.empty() == true);
std::cout << "PASSED\n";
std::cout << "Test #2\n";
que.push(-1);
assert(que.empty() == false);
assert(que.peek() == -1);
assert(que.pop() == -1);
std::cout << "PASSED\n";
MyQueue<double> que2;
std::cout << "Test #3\n";
que2.push(2.31223);
que2.push(3.1415926);
que2.push(2.92);
assert(que2.peek() == 2.31223);
assert(que2.pop() == 2.31223);
assert(que2.peek() == 3.1415926);
assert(que2.pop() == 3.1415926);
assert(que2.peek() == 2.92);
assert(que2.pop() == 2.92);
std::cout << "PASSED\n";
}
/**
* Main function, calls testing function
*/
int main() {
queue_test();
return 0;
}

View File

@ -26,12 +26,12 @@ unsigned int gcd(unsigned int x, unsigned int y) {
if (x > y) {
// The following is valid because we have checked whether y == 0
int temp = x / y;
unsigned int temp = x / y;
return gcd(y, x - temp * y);
}
// Again the following is valid because we have checked whether x == 0
int temp = y / x;
unsigned int temp = y / x;
return gcd(x, y - temp * x);
}
@ -40,7 +40,9 @@ unsigned int gcd(unsigned int x, unsigned int y) {
* @params integer x and y whose lcm we want to find.
* @return lcm of x and y using the relation x * y = gcd(x, y) * lcm(x, y)
*/
unsigned int lcm(unsigned int x, unsigned int y) { return x * y / gcd(x, y); }
unsigned int lcm(unsigned int x, unsigned int y) {
return x / gcd(x, y) * y;
}
/**
* Function for testing the lcm() functions with some assert statements.
@ -59,6 +61,15 @@ void tests() {
lcm(2, 3) == 6));
std::cout << "Second assertion passes: LCM of 2 and 3 is " << lcm(2, 3)
<< std::endl;
// Testing an integer overflow.
// The algorithm should work as long as the result fits into integer.
assert(((void)"LCM of 987654321 and 987654321 is 987654321 but lcm function"
" gives a different result.\n",
lcm(987654321, 987654321) == 987654321));
std::cout << "Third assertion passes: LCM of 987654321 and 987654321 is "
<< lcm(987654321, 987654321)
<< std::endl;
}
/**

View File

@ -1,58 +1,72 @@
/**
* @file
* @brief Get list of prime numbers using Sieve of Eratosthenes
* Sieve of Eratosthenes is an algorithm to find the primes
* that is between 2 to N (as defined in main).
* @details
* Sieve of Eratosthenes is an algorithm that finds all the primes
* between 2 and N.
*
* Time Complexity : \f$O(N \cdot\log N)\f$
* Time Complexity : \f$O(N \cdot\log \log N)\f$
* <br/>Space Complexity : \f$O(N)\f$
*
* @see primes_up_to_billion.cpp prime_numbers.cpp
*/
#include <iostream> // for io operations
#include <cassert>
#include <iostream>
#include <vector>
/**
* This is the function that finds the primes and eliminates
* the multiples.
* This is the function that finds the primes and eliminates the multiples.
* Contains a common optimization to start eliminating multiples of
* a prime p starting from p * p since all of the lower multiples
* have been already eliminated.
* @param N number of primes to check
* @param [out] isprime a boolean array of size `N` identifying if `i`^th number is prime or not
* @return is_prime a vector of `N + 1` booleans identifying if `i`^th number is a prime or not
*/
void sieve(uint32_t N, bool *isprime) {
isprime[0] = true;
isprime[1] = true;
std::vector<bool> sieve(uint32_t N) {
std::vector<bool> is_prime(N + 1, true);
is_prime[0] = is_prime[1] = false;
for (uint32_t i = 2; i * i <= N; i++) {
if (!isprime[i]) {
for (uint32_t j = (i << 1); j <= N; j = j + i) {
isprime[j] = true;
if (is_prime[i]) {
for (uint32_t j = i * i; j <= N; j += i) {
is_prime[j] = false;
}
}
}
return is_prime;
}
/**
* This function prints out the primes to STDOUT
* @param N number of primes to check
* @param [in] isprime a boolean array of size `N` identifying if `i`^th number is prime or not
* @param is_prime a vector of `N + 1` booleans identifying if `i`^th number is a prime or not
*/
void print(uint32_t N, const bool *isprime) {
void print(uint32_t N, const std::vector<bool> &is_prime) {
for (uint32_t i = 2; i <= N; i++) {
if (!isprime[i]) {
if (is_prime[i]) {
std::cout << i << ' ';
}
}
std::cout << std::endl;
}
/**
* Test implementations
*/
void tests() {
// 0 1 2 3 4 5 6 7 8 9 10
std::vector<bool> ans{false, false, true, true, false, true, false, true, false, false, false};
assert(sieve(10) == ans);
}
/**
* Main function
*/
int main() {
uint32_t N = 100;
bool *isprime = new bool[N];
sieve(N, isprime);
print(N, isprime);
delete[] isprime;
tests();
uint32_t N = 100;
std::vector<bool> is_prime = sieve(N);
print(N, is_prime);
return 0;
}

115
sorting/bogo_sort.cpp Normal file
View File

@ -0,0 +1,115 @@
/**
* @file
* @brief Implementation of [Bogosort algorithm](https://en.wikipedia.org/wiki/Bogosort)
*
* @details
* In computer science, bogosort (also known as permutation sort, stupid sort, slowsort,
* shotgun sort, random sort, monkey sort, bobosort or shuffle sort) is a highly inefficient
* sorting algorithm based on the generate and test paradigm. Two versions of this algorithm
* exist: a deterministic version that enumerates all permutations until it hits a sorted one,
* and a randomized version that randomly permutes its input.Randomized version is implemented here.
*
* ### Algorithm
* Shuffle the array untill array is sorted.
*
* @author [Deep Raval](https://github.com/imdeep2905)
*/
#include <iostream>
#include <algorithm>
#include <array>
#include <cassert>
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* Function to shuffle the elements of an array. (for reference)
* @tparam T typename of the array
* @tparam N length of array
* @param arr array to shuffle
* @returns new array with elements shuffled from a given array
*/
template <typename T, size_t N>
std::array <T, N> shuffle (std::array <T, N> arr) {
for (int i = 0; i < N; i++) {
// Swaps i'th index with random index (less than array size)
std::swap(arr[i], arr[std::rand() % N]);
}
return arr;
}
/**
* Implement randomized Bogosort algorithm and sort the elements of a given array.
* @tparam T typename of the array
* @tparam N length of array
* @param arr array to sort
* @returns new array with elements sorted from a given array
*/
template <typename T, size_t N>
std::array <T, N> randomized_bogosort (std::array <T, N> arr) {
// Untill array is not sorted
while (!std::is_sorted(arr.begin(), arr.end())) {
std::random_shuffle(arr.begin(), arr.end());// Shuffle the array
}
return arr;
}
} // namespace sorting
/**
* Function to display array on screen
* @tparam T typename of the array
* @tparam N length of array
* @param arr array to display
*/
template <typename T, size_t N>
void show_array (const std::array <T, N> &arr) {
for (int x : arr) {
std::cout << x << ' ';
}
std::cout << '\n';
}
/**
* Function to test above algorithm
*/
void test() {
// Test 1
std::array <int, 5> arr1;
for (int &x : arr1) {
x = std::rand() % 100;
}
std::cout << "Original Array : ";
show_array(arr1);
arr1 = sorting::randomized_bogosort(arr1);
std::cout << "Sorted Array : ";
show_array(arr1);
assert(std::is_sorted(arr1.begin(), arr1.end()));
// Test 2
std::array <int, 5> arr2;
for (int &x : arr2) {
x = std::rand() % 100;
}
std::cout << "Original Array : ";
show_array(arr2);
arr2 = sorting::randomized_bogosort(arr2);
std::cout << "Sorted Array : ";
show_array(arr2);
assert(std::is_sorted(arr2.begin(), arr2.end()));
}
/** Driver Code */
int main() {
// Testing
test();
// Example Usage
std::array <int, 5> arr = {3, 7, 10, 4, 1}; // Defining array which we want to sort
std::cout << "Original Array : ";
show_array(arr);
arr = sorting::randomized_bogosort(arr); // Callling bogo sort on it
std::cout << "Sorted Array : ";
show_array(arr); // Printing sorted array
return 0;
}

133
sorting/gnome_sort.cpp Normal file
View File

@ -0,0 +1,133 @@
/**
* @file
* @brief Implementation of [gnome
* sort](https://en.wikipedia.org/wiki/Gnome_sort) algorithm.
* @author [beqakd](https://github.com/beqakd)
* @author [Krishna Vedala](https://github.com/kvedala)
* @details
* Gnome sort algorithm is not the best one but it is widely used.
* The algorithm iteratively checks the order of pairs in the array. If they are
* on right order it moves to the next successive pair, otherwise it swaps
* elements. This operation is repeated until no more swaps are made thus
* indicating the values to be in ascending order.
*
* The time Complexity of the algorithm is \f$O(n^2)\f$ and in some cases it
* can be \f$O(n)\f$.
*/
#include <algorithm> // for std::swap
#include <array> // for std::array
#include <cassert> // for assertions
#include <iostream> // for io operations
/**
* @namespace sorting
* Sorting algorithms
*/
namespace sorting {
/**
* This implementation is for a C-style array input that gets modified in place.
* @param [in,out] arr our array of elements.
* @param size size of given array
*/
template <typename T>
void gnomeSort(T *arr, int size) {
// few easy cases
if (size <= 1) {
return;
}
int index = 0; // initialize some variables.
while (index < size) {
// check for swap
if ((index == 0) || (arr[index] >= arr[index - 1])) {
index++;
} else {
std::swap(arr[index], arr[index - 1]); // swap
index--;
}
}
}
/**
* This implementation is for a C++-style array input. The function argument is
* a pass-by-value and hence a copy of the array gets created which is then
* modified by the function and returned.
* @tparam T type of data variables in the array
* @tparam size size of the array
* @param [in] arr our array of elements.
* @return array with elements sorted
*/
template <typename T, size_t size>
std::array<T, size> gnomeSort(std::array<T, size> arr) {
// few easy cases
if (size <= 1) {
return arr;
}
int index = 0; // initialize loop index
while (index < size) {
// check for swap
if ((index == 0) || (arr[index] >= arr[index - 1])) {
index++;
} else {
std::swap(arr[index], arr[index - 1]); // swap
index--;
}
}
return arr;
}
} // namespace sorting
/**
* Test function
*/
static void test() {
// Example 1. Creating array of int,
std::cout << "Test 1 - as a C-array...";
const int size = 6;
std::array<int, size> arr = {-22, 100, 150, 35, -10, 99};
sorting::gnomeSort(arr.data(),
size); // pass array data as a C-style array pointer
assert(std::is_sorted(std::begin(arr), std::end(arr)));
std::cout << " Passed\n";
for (int i = 0; i < size; i++) {
std::cout << arr[i] << ", ";
}
std::cout << std::endl;
// Example 2. Creating array of doubles.
std::cout << "\nTest 2 - as a std::array...";
std::array<double, size> double_arr = {-100.2, 10.2, 20.0, 9.0, 7.5, 7.2};
std::array<double, size> sorted_arr = sorting::gnomeSort(double_arr);
assert(std::is_sorted(std::begin(sorted_arr), std::end(sorted_arr)));
std::cout << " Passed\n";
for (int i = 0; i < size; i++) {
std::cout << double_arr[i] << ", ";
}
std::cout << std::endl;
// Example 3. Creating random array of float.
std::cout << "\nTest 3 - 200 random numbers as a std::array...";
const int size2 = 200;
std::array<float, size2> rand_arr{};
for (auto &a : rand_arr) {
// generate random numbers between -5.0 and 4.99
a = float(std::rand() % 1000 - 500) / 100.f;
}
std::array<float, size2> float_arr = sorting::gnomeSort(rand_arr);
assert(std::is_sorted(std::begin(float_arr), std::end(float_arr)));
std::cout << " Passed\n";
// for (int i = 0; i < size; i++) std::cout << double_arr[i] << ", ";
std::cout << std::endl;
}
/**
* Our main function with example of sort method.
*/
int main() {
test();
return 0;
}

188
sorting/quick_sort_3.cpp Normal file
View File

@ -0,0 +1,188 @@
/**
* @file
* @brief Implementation Details
* @details Quick sort 3 works on Dutch National Flag Algorithm
* The major difference between simple quicksort and quick sort 3 comes in the
* function partition3 In quick_sort_partition3 we divide the vector/array into
* 3 parts. quick sort 3 works faster in some cases as compared to simple
* quicksort.
* @author immortal-j
* @author [Krishna Vedala](https://github/kvedala)
*/
#include <algorithm>
#include <cassert>
#include <ctime>
#include <iostream>
#include <vector>
namespace {
/**
* Operator to print the array.
* @param out std::ostream object to write to
* @param arr array to write
*/
template <typename T>
std::ostream &operator<<(std::ostream &out, const std::vector<T> &arr) {
for (size_t i = 0; i < arr.size(); ++i) {
out << arr[i];
if (i < arr.size() - 1) {
out << ", ";
}
}
return out;
}
} // namespace
/**
* @namespace sorting
* @brief Sorting Algorithms
*/
namespace sorting {
namespace { // using un-named namespace here to prevent partition function
// being visible to end-users
/** This function partitions `arr[]` in three parts
* 1. \f$arr[l\ldots i]\f$ contains all elements smaller than pivot
* 2. \f$arr[(i+1)\ldots (j-1)]\f$ contains all occurrences of pivot
* 3. \f$arr[j\ldots r]\f$ contains all elements greater than pivot
* @tparam T type of data in the vector array
* @param [in,out] arr vector array being partitioned
* @param [in] low lower limit of window to partition
* @param [in] high upper limit of window to partition
* @param [out] i updated lower limit of partition
* @param [out] j updated upper limit of partition
*/
template <typename T>
void partition3(std::vector<T> *arr, int32_t low, int32_t high, int32_t *i,
int32_t *j) {
// To handle 2 elements
if (high - low <= 1) {
if ((*arr)[high] < (*arr)[low]) {
std::swap((*arr)[high], (*arr)[low]);
}
*i = low;
*j = high;
return;
}
int32_t mid = low;
T pivot = (*arr)[high];
while (mid <= high) {
if ((*arr)[mid] < pivot) {
std::swap((*arr)[low++], (*arr)[mid++]);
} else if ((*arr)[mid] == pivot) {
mid++;
} else if ((*arr)[mid] > pivot) {
std::swap((*arr)[mid], (*arr)[high--]);
}
}
// update i and j
*i = low - 1;
*j = mid; // or high-1
}
} // namespace
/** 3-way partition based quick sort. This function accepts array pointer and
* modified the input array.
* @tparam T type of data in the vector array
* @param [in,out] arr vector array to sort
* @param [in] low lower limit of window to partition
* @param [in] high upper limit of window to partition
*/
template <typename T>
void quicksort(std::vector<T> *arr, int32_t low, int32_t high) {
if (low >= high) { // 1 or 0 elements
return;
}
int32_t i = 0, j = 0;
// i and j are passed as reference
partition3(arr, low, high, &i, &j);
// Recur two halves
quicksort(arr, low, i);
quicksort(arr, j, high);
}
/** 3-way partition based quick sort. This function accepts array by value and
* creates a copy of it. The array copy gets sorted and returned by the
* function.
* @tparam T type of data in the vector array
* @param [in] arr vector array to sort
* @param [in] low lower limit of window to partition
* @param [in] high upper limit of window to partition
* @returns sorted array vector
*/
template <typename T>
std::vector<T> quicksort(std::vector<T> arr, int32_t low, int32_t high) {
if (low >= high) { // 1 or 0 elements
return arr;
}
int32_t i = 0, j = 0;
// i and j are passed as reference
partition3(&arr, low, high, &i, &j);
// Recur two halves
quicksort(&arr, low, i);
quicksort(&arr, j, high);
return arr;
}
} // namespace sorting
/** Test function for integer type arrays */
static void test_int() {
std::cout << "\nTesting integer type arrays\n";
for (int num_tests = 1; num_tests < 21; num_tests++) {
size_t size = std::rand() % 500;
std::vector<int> arr(size);
for (auto &a : arr) {
a = std::rand() % 500 - 250; // random numbers between -250, 249
}
std::cout << "Test " << num_tests << "\t Array size:" << size << "\t ";
std::vector<int> sorted = sorting::quicksort(arr, 0, size - 1);
if (size < 20) {
std::cout << "\t Sorted Array is:\n\t";
std::cout << sorted << "\n";
}
assert(std::is_sorted(std::begin(sorted), std::end(sorted)));
std::cout << "\t Passed\n";
}
}
/** Test function for double type arrays */
static void test_double() {
std::cout << "\nTesting Double type arrays\n";
for (int num_tests = 1; num_tests < 21; num_tests++) {
size_t size = std::rand() % 500;
std::vector<double> arr(size);
for (auto &a : arr) {
a = double(std::rand() % 500) -
250.f; // random numbers between -250, 249
a /= 100.f; // convert to -2.5 to 2.49
}
std::cout << "Test " << num_tests << "\t Array size:" << size << "\t ";
std::vector<double> sorted = sorting::quicksort(arr, 0, size - 1);
if (size < 20) {
std::cout << "\t Sorted Array is:\n\t";
std::cout << sorted << "\n";
}
assert(std::is_sorted(std::begin(sorted), std::end(sorted)));
std::cout << "\t Passed\n";
}
}
/** Driver program for above functions */
int main() {
std::srand(std::time(nullptr));
test_int();
test_double();
return 0;
}