Split up algorithms to several sub files

This commit is contained in:
2021-07-02 20:50:28 -04:00
parent eba3d9e1f8
commit 5cf20b539a
14 changed files with 1527 additions and 1442 deletions

View File

@@ -1,682 +0,0 @@
//myClasses/Algorithms.hpp
//Matthew Ellison
// Created: 11-08-18
//Modified: 06-29-21
//This file contains the declarations and implementations to several algoritms that I have found useful
/*
Copyright (C) 2021 Matthew Ellison
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef MEE_ALGORITHMS_HPP
#define MEE_ALGORITHMS_HPP
#include <vector>
#include <cinttypes>
#include <algorithm>
#include <string>
#include <sstream>
#include <cmath>
#include <unordered_map>
#include <map>
#include <bitset>
namespace mee{
//A list of functions in the file
//Also works as prototypes with general information
//This function determines whether the number passed into it is a prime
template <class T>
bool isPrime(T num);
//This is a function that returns all the primes <= goalNumber and returns a vector with those prime numbers
template <class T>
std::vector<T> getPrimes(T goalNumber);
//This function returns a vector with a specific number of primes
template <class T>
std::vector<T> getNumPrimes(T numberOfPrimes);
//This function returns all prime factors of a number
template <class T>
std::vector<T> getFactors(T goalNumber);
//This is a function that gets all the divisors of num and returns a vector containing the divisors
template <class T>
std::vector<T> getDivisors(T num);
//This is a function that returns the sum of all elements in a vector
template <class T>
T getSum(const std::vector<T>& numbers);
//This is a function that returns the product of all elements in a vector
template <class T>
T getProduct(const std::vector<T>& nums);
//This is a function that searches a vecter for an element. Returns true if the key is found in list
template <class T>
bool isFound(std::vector<T> ary, T key);
//This is a function that creates all permutations of a string and returns a vector of those permutations.
//It is meant to have only the string passed into it from the calling function. num is used for recursion purposes
//It can however be used with num if you want the first num characters to be stationary
std::vector<std::string> getPermutations(std::string master, int num = 0);
//These functions return the numth Fibonacci number
template <class T>
T getFib(const T num);
//This function returns a vector that includes all Fibonacci numbers <= num
template <class T>
std::vector<T> getAllFib(const T num);
//This is a function that performs a bubble sort on a vector
template <class T>
void bubbleSort(std::vector<T>& ary);
//This is a function that makes quick sort easier to start
template <class T>
void quickSort(std::vector<T>& ary);
//This is the function that actually performs the quick sort on the vector
template <class T>
void quickSort(std::vector<T>& ary, int64_t bottom, int64_t top);
//This is a helper function for quickSort. It chooses a pivot element and sorts everything to larger or smaller than the pivot. Returns location of pivot
template <class T>
int64_t partition(std::vector<T>& ary, int64_t bottom, int64_t top);
//This is a function that performs a search on a vector and returns the subscript of the item being searched for (-1 if not found)
template <class T>
int64_t search(const std::vector<T>& ary, T num);
//This function finds the smallest element in a vector
template <class T>
T findMin(const std::vector<T>& ary);
//This function finds the largest element in a vector
template <class T>
T findMax(const std::vector<T>& ary);
//This function returns the number of times the character occurs in the string
int findNumOccurrence(std::string str, char ch);
//This function returns true if the string passed in is a palindrome
bool isPalindrome(std::string str);
//This function converts a number to its binary equivalent
template <class T>
std::string toBin(T num);
template <class T>
class SieveOfEratosthenes{
private:
T possiblePrime; //The next number that could be a prime
std::unordered_map<T, std::vector<T>> compositeMap; //A map to keep track of all of the composite numbers
public:
SieveOfEratosthenes(){
possiblePrime = 2;
}
bool hasNext(){
return true;
}
T next(){
T prime;
if(possiblePrime > 2){
//Loop until you find a prime number
for(;compositeMap[possiblePrime].size() > 0;possiblePrime += 2){
//Create the next entry for all entries in the map
for(T num : compositeMap[possiblePrime]){
compositeMap[possiblePrime + num + num].push_back(num);
}
//Delete the current entry
compositeMap.erase(possiblePrime);
}
//Save that it is a prime
prime = possiblePrime;
//Add the next entry to the prime
compositeMap[prime * 3].push_back(prime);
//Move on to the next possible prime
possiblePrime += 2;
}
else{
//Return 2 and move to 3
prime = possiblePrime++;
}
return prime;
}
};
template <class T>
class SieveOfEratosthenesAlt{
private:
T possiblePrime; //The next number that could be a prime
std::map<T, std::vector<T>> compositeMap; //A map to keep track of all of the composite numbers
public:
SieveOfEratosthenesAlt(){
possiblePrime = 2;
}
bool hasNext(){
return true;
}
T next(){
T prime;
if(possiblePrime > 2){
//Loop until you find a prime number
for(;compositeMap[possiblePrime].size() > 0;possiblePrime += 2){
//Create the next entry for all entries in the map
for(T num : compositeMap[possiblePrime]){
compositeMap[possiblePrime + num + num].push_back(num);
}
//Delete the current entry
compositeMap.erase(possiblePrime);
}
//Save that it is a prime
prime = possiblePrime;
//Add the next entry to the prime
compositeMap[prime * 3].push_back(prime);
//Move on to the next possible prime
possiblePrime += 2;
}
else{
//Return 2 and move to 3
prime = possiblePrime++;
}
return prime;
}
};
//This is a function that returns all the primes <= goalNumber and returns a vector with those prime numbers
template <class T>
std::vector<T> getPrimes(T goalNumber){
std::vector<T> primes;
bool foundFactor = false;
//If the number is 1, 0, or a negative number return an empty vector
if(goalNumber <= 1){
return primes;
}
else{
primes.push_back(2);
}
//We can now start at 3 and skip all of the even numbers
for(T possiblePrime = 3;possiblePrime <= goalNumber;possiblePrime += 2){
//Step through every element in the current primes. If you don't find anything that divides it, it must be a prime itself
uint64_t topPossibleFactor = ceil(sqrt(possiblePrime));
for(uint64_t cnt = 0;(cnt < primes.size()) && (primes.at(cnt) <= topPossibleFactor);++cnt){
if((possiblePrime % primes.at(cnt)) == 0){
foundFactor = true;
break;
}
}
//If you didn't find a factor then it must be prime
if(!foundFactor){
primes.push_back(possiblePrime);
}
//If you did find a factor you need to reset the flag
else{
foundFactor = false;
}
}
std::sort(primes.begin(), primes.end());
return primes;
}
//This function returns a vector with a specific number of primes
template <class T>
std::vector<T> getNumPrimes(T numberOfPrimes){
std::vector<T> primes;
primes.reserve(numberOfPrimes); //Saves cycles later
bool foundFactor = false;
//If the number is 1, 0, or a negative number return an empty vector
if(numberOfPrimes <= 1){
return primes;
}
//Otherwise 2 is the first prime number
else{
primes.push_back(2);
}
//Loop through every odd number starting at 3 until we find the requisite number of primes
//Using possiblePrime >= 3 to make sure it doesn't loop back around in an overflow error and create an infinite loop
for(T possiblePrime = 3;(primes.size() < numberOfPrimes) && (possiblePrime >= 3);possiblePrime += 2){
//Step through every element in the current primes. If you don't find anything that divides it, it must be a prime itself
uint64_t topPossibleFactor = ceil(sqrt(possiblePrime));
for(uint64_t cnt = 0;(cnt < primes.size()) && (primes.at(cnt) <= topPossibleFactor);++cnt){
if((possiblePrime % primes.at(cnt)) == 0){
foundFactor = true;
break;
}
}
//If you didn't find a factor then it must be prime
if(!foundFactor){
primes.push_back(possiblePrime);
}
//If you did find a factor you need to reset the flag
else{
foundFactor = false;
}
}
//The numbers should be in order, but sort them anyway just in case
std::sort(primes.begin(), primes.end());
return primes;
}
//This function determines whether the number passed into it is a prime
template <class T>
bool isPrime(T possiblePrime){
if(possiblePrime <= 3){
return possiblePrime > 1;
}
else if(((possiblePrime % 2) == 0) || ((possiblePrime % 3) == 0)){
return false;
}
for(T cnt = 5;(cnt * cnt) <= possiblePrime;cnt += 6){
if(((possiblePrime % cnt) == 0) || ((possiblePrime % (cnt + 2)) == 0)){
return false;
}
}
return true;
}
//This function returns all prime factors of a number
template <class T>
std::vector<T> getFactors(T goalNumber){
//Get all the prime numbers up to sqrt(number). If there is a prime < goalNumber it will have to be <= sqrt(goalNumber)
std::vector<T> primes = getPrimes((T)ceil(sqrt(goalNumber))); //Make sure you are getting a vector of the correct type
std::vector<T> factors;
//Need to step through each prime and see if it is a factor of the number
for(int cnt = 0;cnt < primes.size();){
if((goalNumber % primes[cnt]) == 0){
factors.push_back(primes[cnt]);
goalNumber /= primes[cnt];
}
else{
++cnt;
}
}
//If it didn't find any factors in the primes the number itself must be prime
if(factors.size() == 0){
factors.push_back(goalNumber);
goalNumber /= goalNumber;
}
///Should add some kind of error throwing inc ase the number != 1 after searching for all prime factors
return factors;
}
//This is a function that gets all the divisors of num and returns a vector containing the divisors
template <class T>
std::vector<T> getDivisors(T num){
std::vector<T> divisors; //Holds the number of divisors
//Ensure the parameter is a valid number
if(num <= 0){
return divisors;
}
else if(num == 1){
divisors.push_back(1);
return divisors;
}
//You only need to check up to sqrt(num)
T topPossibleDivisor = ceil(sqrt(num));
for(uint64_t possibleDivisor = 1;possibleDivisor <= topPossibleDivisor;++possibleDivisor){
//Check if the counter evenly divides the number
//If it does the counter and the other number are both divisors
if((num % possibleDivisor) == 0){
//We don't need to check if the number already exists because we are only checking numbers <= sqrt(num), so there can be no duplicates
divisors.push_back(possibleDivisor);
//We still need to account for sqrt(num) being a divisor
if(possibleDivisor != topPossibleDivisor){
divisors.push_back(num / possibleDivisor);
}
//Take care of a few occations where a number was added twice
if(divisors.at(divisors.size() - 1) == (possibleDivisor + 1)){
++possibleDivisor;
}
}
}
//Sort the vector for neatness
std::sort(divisors.begin(), divisors.end());
//Return the vector of divisors
return divisors;
}
//This is a function that returns the sum of all elements in a vector
template <class T>
T getSum(const std::vector<T>& ary){
T sum = 0;
for(unsigned int cnt = 0;cnt < ary.size();++cnt){
sum += ary.at(cnt);
}
return sum;
}
//This is a function that returns the product of all elmements in a vector
template <class T>
T getProduct(const std::vector<T>& ary){
//Make sure there is something in the array
if(ary.size() == 0){
return 0;
}
//Multiply all elements in the array together
T prod = 1;
for(T cnt = 0;cnt < ary.size();++cnt){
prod *= ary.at(cnt);
}
return prod;
}
//This is a function that searches a vecter for an element. Returns true if they key is found in list
template <class T>
bool isFound(std::vector<T> ary, T key){
typename std::vector<T>::iterator location = std::find(ary.begin(), ary.end(), key);
if(location == ary.end()){
return false;
}
else{
return true;
}
}
//This is a function that creates all permutations of a string and returns a vector of those permutations.
std::vector<std::string> getPermutations(std::string master, int num){
std::vector<std::string> perms;
//Check if the number is out of bounds
if((num >= master.size()) || (num < 0)){
return perms;
}
//If this is the last possible recurse just return the current string
else if(num == (master.size() - 1)){
perms.push_back(master);
return perms;
}
//If there are more possible recurses, recurse with the current permutation
std::vector<std::string> temp;
temp = getPermutations(master, num + 1);
perms.insert(perms.end(), temp.begin(), temp.end());
//You need to swap the current letter with every possible letter after it
//The ones needed to swap before will happen automatically when the function recurses
for(int cnt = 1;(num + cnt) < master.size();++cnt){
std::swap(master[num], master[num + cnt]);
temp = getPermutations(master, num + 1);
perms.insert(perms.end(), temp.begin(), temp.end());
std::swap(master[num], master[num + cnt]);
}
//The array is not necessarily in alpha-numeric order. So if this is the full array sort it before returning
if(num == 0){
std::sort(perms.begin(), perms.end());
}
return perms;
}
//These functions return the numth Fibonacci number
template <class T>
T getFib(const T num){
//Make sure the number is within bounds
if(num <= 2){
return 1;
}
//Setup the variables
T fib = 0;
T tempNums[3];
tempNums[0] = tempNums[1] = 1;
//Do the calculation
unsigned int cnt;
for(cnt = 2;(cnt < num) && (tempNums[(cnt - 1) % 3] >= tempNums[(cnt - 2) % 3]);++cnt){
tempNums[cnt % 3] = tempNums[(cnt + 1) % 3] + tempNums[(cnt + 2) % 3];
}
fib = tempNums[(cnt - 1) % 3]; //Transfer the answer to permanent variable. -1 to account for the offset of starting at 0
return fib;
}
//This function returns a vector that includes all Fibonacci numbers <= num
template <class T>
std::vector<T> getAllFib(const T num){
std::vector<T> fibList;
//Make sure the number is within bounds
if(num <= 1){
fibList.push_back(1);
return fibList;
}
else{ //Make sure to add the first 2 elements
fibList.push_back(1);
fibList.push_back(1);
}
//Setup the variables
T fib = 0;
T tempNums[3];
tempNums[0] = tempNums[1] = 1;
//Do the calculation and add each number to the vector
for(T cnt = 2;(tempNums[(cnt - 1) % 3] <= num) && (tempNums[(cnt - 1) % 3] >= tempNums[(cnt - 2) % 3]);++cnt){
tempNums[cnt % 3] = tempNums[(cnt + 1) % 3] + tempNums[(cnt + 2) % 3];
fibList.push_back(tempNums[cnt % 3]);
}
//If you triggered the exit statement you have one more element than you need
fibList.pop_back();
//Return the vector that contains all of the Fibonacci numbers
return fibList;
}
//This is a function that performs a bubble sort on a vector
template <class T>
void bubbleSort(std::vector<T>& ary){
bool notFinished = true; //A flag to determine if the loop is finished
for(int numLoops = 0;numLoops < ary.size();++numLoops){ //Loop until you finish
notFinished = false; //Assume you are finished until you find an element out of order
//Loop through every element in the vector, moving the largest one to the end
for(int cnt = 1;cnt < (ary.size() - numLoops);++cnt){ //use size - 1 to make sure you don't go out of bounds
if(ary.at(cnt) < ary.at(cnt - 1)){
std::swap(ary.at(cnt), ary.at(cnt - 1));
notFinished = true;
}
}
}
}
//This is a function that makes quick sort easier to start
template <class T>
void quickSort(std::vector<T>& ary){
//Call the other quickSort function with all the necessary info
quickSort(ary, 0, ary.size() - 1);
}
//This is the function that actually performs the quick sort on the vector
template <class T>
void quickSort(std::vector<T>& ary, int64_t bottom, int64_t top){
//Make sure you have a valid slice of the vector
if(bottom < top){
//Get the pivot location
int64_t pivot = partition(ary, bottom, top);
//Sort all element less than the pivot
quickSort(ary, bottom, pivot - 1);
//Sort all element greater than the pivot
quickSort(ary, pivot + 1, top);
}
}
//This is a helper function for quickSort. It chooses a pivot element and sorts everything to larger or smaller than the pivot. Returns location of pivot
template <class T>
int64_t partition(std::vector<T>& ary, int64_t bottom, int64_t top){
int64_t pivot = ary.at(top); //Pick a pivot element
int64_t smaller = bottom - 1; //Keep track of where all elements are smaller than the pivot
//Loop through every element in the vector testing if it is smaller than pivot
for(int64_t cnt = bottom;cnt < top;++cnt){
//If the element is smaller than pivot move it to the correct location
if(ary.at(cnt) < pivot){
//Increment the tracker for elements smaller than pivot
++smaller;
//Swap the current element to the correct location for being smaller than the pivot
std::swap(ary.at(smaller), ary.at(cnt));
}
}
//Move the pivot element to the correct location
++smaller;
std::swap(ary.at(top), ary.at(smaller));
//Return the pivot element
return smaller;
}
//This is a function that performs a search on a vector and returns the subscript of the item being searched for
template <class T>
int64_t search(const std::vector<T>& ary, T num){
int64_t subscript = 0; //Start with the subscript at 0
//Step through every element in the vector and return the subscript if you find the correct element
while(subscript < ary.size()){
if(ary.at(subscript) == num){
return subscript;
}
else{
++subscript;
}
}
//If you cannot find the element return -1
return -1;
}
//This function finds the smallest element in a vector
template <class T>
T findMin(const std::vector<T>& ary){
T min; //For the smallest element
//Make sure the vector is not empty
if(ary.size() > 0){
//Use the first element as the smallest element
min = ary.at(0);
//Run through every element in the vector, checking it against the current minimum
for(int cnt = 1;cnt < ary.size();++cnt){
//If the current element is smaller than the minimum, make it the new minimum
if(ary.at(cnt) < min){
min = ary.at(cnt);
}
}
}
//Return the element
return min;
}
//This function finds the largest element in a vector
template <class T>
T findMax(const std::vector<T>& ary){
T max; //For the largest element
//Make sure the vector is not empty
if(ary.size() > 0){
//Use the first element as the largest element
max = ary.at(0);
//Run through every element in the vector, checking it against the current minimum
for(int cnt = 1;cnt < ary.size();++cnt){
//If the current element is larger than the maximum, make it the new maximum
if(ary.at(cnt) > max){
max = ary.at(cnt);
}
}
}
//Return the element
return max;
}
//This function returns the number of times the character occurs in the string
int findNumOccurrence(std::string str, char ch){
int num = 0; //Set the number of occurrences to 0 to start
//Loop through every character in the string and compare it to the character passed in
for(char strCh : str){
//If the character is the same as the one passed in increment the counter
if(strCh == ch){
++num;
}
}
//Return the number of times the character appeared in the string
return num;
}
//Return a vector of strings split on the delimiter
std::vector<std::string> split(std::string str, char delimiter){
std::vector<std::string> splitStrings;
int location = 0;
location = str.find(delimiter);
while(location != std::string::npos){
//Split the string
std::string firstString = str.substr(0, location);
str = str.substr(location + 1); //+1 to skip the delimiter itself
//Add the string to the vector
splitStrings.push_back(firstString);
//Get the location of the next delimiter
location = str.find(delimiter);
}
//Get the final string if it isn't empty
if(!str.empty()){
splitStrings.push_back(str);
}
//Return the vector of strings
return splitStrings;
}
//Return the factorial of the number passed in
template <class T>
T factorial(T num){
T fact = 1;
for(T cnt = 1;cnt <= num;++cnt){
fact *= cnt;
}
return fact;
}
//This function returns true if the string passed in is a palindrome
bool isPalindrome(std::string str){
std::string rev = str;
std::reverse(rev.begin(), rev.end());
if(str == rev){
return true;
}
else{
return false;
}
}
//This function converts a number to its binary equivalent
template <class T>
std::string toBin(T num){
//Convert the number to a binary string
std::string fullString = std::bitset<sizeof(T) * 8>(num).to_string();
//Remove leading zeros
int loc = 0;
for(loc = 0;(loc < fullString.size()) && (fullString[loc] == '0');++loc);
std::string trimmedString = fullString.substr(loc);
if(trimmedString == ""){
trimmedString = "0";
}
return trimmedString;
}
//Print a vector
template <class T>
std::string printVector(std::vector<T>& ary){
std::stringstream str;
str << "[";
for(int cnt = 0;cnt < ary.size();++cnt){
str << ary[cnt];
if(cnt < ary.size() - 1){
str << ", ";
}
}
str << "]";
return str.str();
}
}
#endif //MEE_ALGORITHMS_HPP

View File

@@ -0,0 +1,345 @@
//myClasses/headers/mee/numberAlgorithms.hpp
//Matthew Ellison
// Created: 07-02-21
//Modified: 07-02-21
//This file contains declarations of functions I have created to manipulate numbers
/*
Copyright (C) 2021 Matthew Ellison
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef MEE_NUMBER_ALGORITHMS_HPP
#define MEE_NUMBER_ALGORITHMS_HPP
#include <bitset>
#include <cinttypes>
#include <cmath>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
#include "Generator.hpp"
namespace mee{
//This function determines whether the number passed into it is a prime
template <class T>
bool isPrime(T possiblePrime){
if(possiblePrime <= 3){
return possiblePrime > 1;
}
else if(((possiblePrime % 2) == 0) || ((possiblePrime % 3) == 0)){
return false;
}
for(T cnt = 5;(cnt * cnt) <= possiblePrime;cnt += 6){
if(((possiblePrime % cnt) == 0) || ((possiblePrime % (cnt + 2)) == 0)){
return false;
}
}
return true;
}
//This is a function that returns all the primes <= goalNumber and returns a vector with those prime numbers
template <class T>
std::vector<T> getPrimes(T goalNumber){
std::vector<T> primes;
bool foundFactor = false;
//If the number is 1, 0, or a negative number return an empty vector
if(goalNumber <= 1){
return primes;
}
else{
primes.push_back(2);
}
//We can now start at 3 and skip all of the even numbers
for(T possiblePrime = 3;possiblePrime <= goalNumber;possiblePrime += 2){
//Step through every element in the current primes. If you don't find anything that divides it, it must be a prime itself
uint64_t topPossibleFactor = ceil(sqrt(possiblePrime));
for(uint64_t cnt = 0;(cnt < primes.size()) && (primes.at(cnt) <= topPossibleFactor);++cnt){
if((possiblePrime % primes.at(cnt)) == 0){
foundFactor = true;
break;
}
}
//If you didn't find a factor then it must be prime
if(!foundFactor){
primes.push_back(possiblePrime);
}
//If you did find a factor you need to reset the flag
else{
foundFactor = false;
}
}
std::sort(primes.begin(), primes.end());
return primes;
}
//This function returns a vector with a specific number of primes
template <class T>
std::vector<T> getNumPrimes(T numberOfPrimes){
std::vector<T> primes;
primes.reserve(numberOfPrimes); //Saves cycles later
bool foundFactor = false;
//If the number is 1, 0, or a negative number return an empty vector
if(numberOfPrimes <= 1){
return primes;
}
//Otherwise 2 is the first prime number
else{
primes.push_back(2);
}
//Loop through every odd number starting at 3 until we find the requisite number of primes
//Using possiblePrime >= 3 to make sure it doesn't loop back around in an overflow error and create an infinite loop
for(T possiblePrime = 3;(primes.size() < numberOfPrimes) && (possiblePrime >= 3);possiblePrime += 2){
//Step through every element in the current primes. If you don't find anything that divides it, it must be a prime itself
uint64_t topPossibleFactor = ceil(sqrt(possiblePrime));
for(uint64_t cnt = 0;(cnt < primes.size()) && (primes.at(cnt) <= topPossibleFactor);++cnt){
if((possiblePrime % primes.at(cnt)) == 0){
foundFactor = true;
break;
}
}
//If you didn't find a factor then it must be prime
if(!foundFactor){
primes.push_back(possiblePrime);
}
//If you did find a factor you need to reset the flag
else{
foundFactor = false;
}
}
//The numbers should be in order, but sort them anyway just in case
std::sort(primes.begin(), primes.end());
return primes;
}
//This function returns all prime factors of a number
template <class T>
std::vector<T> getFactors(T goalNumber){
//Get all the prime numbers up to sqrt(number). If there is a prime < goalNumber it will have to be <= sqrt(goalNumber)
std::vector<T> primes = getPrimes((T)ceil(sqrt(goalNumber))); //Make sure you are getting a vector of the correct type
std::vector<T> factors;
//Need to step through each prime and see if it is a factor of the number
for(int cnt = 0;cnt < primes.size();){
if((goalNumber % primes[cnt]) == 0){
factors.push_back(primes[cnt]);
goalNumber /= primes[cnt];
}
else{
++cnt;
}
}
//If it didn't find any factors in the primes the number itself must be prime
if(factors.size() == 0){
factors.push_back(goalNumber);
goalNumber /= goalNumber;
}
///Should add some kind of error throwing inc ase the number != 1 after searching for all prime factors
return factors;
}
//This is a function that gets all the divisors of num and returns a vector containing the divisors
template <class T>
std::vector<T> getDivisors(T num){
std::vector<T> divisors; //Holds the number of divisors
//Ensure the parameter is a valid number
if(num <= 0){
return divisors;
}
else if(num == 1){
divisors.push_back(1);
return divisors;
}
//You only need to check up to sqrt(num)
T topPossibleDivisor = ceil(sqrt(num));
for(uint64_t possibleDivisor = 1;possibleDivisor <= topPossibleDivisor;++possibleDivisor){
//Check if the counter evenly divides the number
//If it does the counter and the other number are both divisors
if((num % possibleDivisor) == 0){
//We don't need to check if the number already exists because we are only checking numbers <= sqrt(num), so there can be no duplicates
divisors.push_back(possibleDivisor);
//We still need to account for sqrt(num) being a divisor
if(possibleDivisor != topPossibleDivisor){
divisors.push_back(num / possibleDivisor);
}
//Take care of a few occations where a number was added twice
if(divisors.at(divisors.size() - 1) == (possibleDivisor + 1)){
++possibleDivisor;
}
}
}
//Sort the vector for neatness
std::sort(divisors.begin(), divisors.end());
//Return the vector of divisors
return divisors;
}
//These functions return the numth Fibonacci number
template <class T>
T getFib(const T num){
//Make sure the number is within bounds
if(num <= 2){
return 1;
}
//Setup the variables
T fib = 0;
T tempNums[3];
tempNums[0] = tempNums[1] = 1;
//Do the calculation
unsigned int cnt;
for(cnt = 2;(cnt < num) && (tempNums[(cnt - 1) % 3] >= tempNums[(cnt - 2) % 3]);++cnt){
tempNums[cnt % 3] = tempNums[(cnt + 1) % 3] + tempNums[(cnt + 2) % 3];
}
fib = tempNums[(cnt - 1) % 3]; //Transfer the answer to permanent variable. -1 to account for the offset of starting at 0
return fib;
}
//This function returns a vector that includes all Fibonacci numbers <= num
template <class T>
std::vector<T> getAllFib(const T num){
std::vector<T> fibList;
//Make sure the number is within bounds
if(num <= 1){
fibList.push_back(1);
return fibList;
}
else{ //Make sure to add the first 2 elements
fibList.push_back(1);
fibList.push_back(1);
}
//Setup the variables
T fib = 0;
T tempNums[3];
tempNums[0] = tempNums[1] = 1;
//Do the calculation and add each number to the vector
for(T cnt = 2;(tempNums[(cnt - 1) % 3] <= num) && (tempNums[(cnt - 1) % 3] >= tempNums[(cnt - 2) % 3]);++cnt){
tempNums[cnt % 3] = tempNums[(cnt + 1) % 3] + tempNums[(cnt + 2) % 3];
fibList.push_back(tempNums[cnt % 3]);
}
//If you triggered the exit statement you have one more element than you need
fibList.pop_back();
//Return the vector that contains all of the Fibonacci numbers
return fibList;
}
//This function converts a number to its binary equivalent
template <class T>
std::string toBin(T num){
//Convert the number to a binary string
std::string fullString = std::bitset<sizeof(T) * 8>(num).to_string();
//Remove leading zeros
int loc = 0;
for(loc = 0;(loc < fullString.size()) && (fullString[loc] == '0');++loc);
std::string trimmedString = fullString.substr(loc);
if(trimmedString == ""){
trimmedString = "0";
}
return trimmedString;
}
//Return the factorial of the number passed in
template <class T>
T factorial(T num){
T fact = 1;
for(T cnt = 1;cnt <= num;++cnt){
fact *= cnt;
}
return fact;
}
//A generator for prime numbers
template <class T>
mee::Generator<T> sieveOfEratosthenes(){
//Return 2 the first time, this lets us skip all even numbers later
co_yield 2;
int num = 0;
//Dictionary to hold the primes we have already found
std::unordered_map<T, std::vector<T>> dict;
//Start checking for primes with the number 3 and skip all even numbers
for(T possiblePrime = 3;true;possiblePrime += 2){
//If possiblePrime is in the dictionary it is a composite number
if(dict.contains(possiblePrime)){
//Move each number to its next odd multiple
for(T num : dict[possiblePrime]){
dict[possiblePrime + num + num].push_back(num);
}
//We no longer need this, free the memory
dict.erase(possiblePrime);
}
//If possiblePrime is not in the dictionary it is a new prime number
//Return it and mark its next multiple
else{
co_yield possiblePrime;
dict[possiblePrime * possiblePrime].push_back(possiblePrime);
}
}
}
//An alternate to sieveOfEratosthenes that uses map instead of unordered_map for greater compatibility but lower performance
template <class T>
mee::Generator<T> sieveOfEratosthenesAlt(){
//Return 2 the first time, this lets us skip all even numbers later
co_yield 2;
int num = 0;
//Dictionary to hold the primes we have already found
std::map<T, std::vector<T>> dict;
//Start checking for primes with the number 3 and skip all even numbers
for(T possiblePrime = 3;true;possiblePrime += 2){
//If possiblePrime is in the dictionary it is a composite number
if(dict.contains(possiblePrime)){
//Move each number to its next odd multiple
for(T num : dict[possiblePrime]){
dict[possiblePrime + num + num].push_back(num);
}
//We no longer need this, free the memory
dict.erase(possiblePrime);
}
//If possiblePrime is not in the dictionary it is a new prime number
//Return it and mark its next multiple
else{
co_yield possiblePrime;
dict[possiblePrime * possiblePrime].push_back(possiblePrime);
}
}
}
}
#endif //MEE_NUMBER_ALGORITHMS_HPP

View File

@@ -0,0 +1,117 @@
//myClasses/headers/mee/stringAlgorithms.hpp
//Matthew Ellison
// Created: 07-02-21
//Modified: 07-02-21
//This file contains declarations of functions I have created to manipulate strings
/*
Copyright (C) 2021 Matthew Ellison
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef MEE_STRING_ALGORITHMS_HPP
#define MEE_STRING_ALGORITHMS_HPP
#include <string>
#include <vector>
namespace mee{
//This is a function that creates all permutations of a string and returns a vector of those permutations.
std::vector<std::string> getPermutations(std::string master, int num = 0){
std::vector<std::string> perms;
//Check if the number is out of bounds
if((num >= master.size()) || (num < 0)){
return perms;
}
//If this is the last possible recurse just return the current string
else if(num == (master.size() - 1)){
perms.push_back(master);
return perms;
}
//If there are more possible recurses, recurse with the current permutation
std::vector<std::string> temp;
temp = getPermutations(master, num + 1);
perms.insert(perms.end(), temp.begin(), temp.end());
//You need to swap the current letter with every possible letter after it
//The ones needed to swap before will happen automatically when the function recurses
for(int cnt = 1;(num + cnt) < master.size();++cnt){
std::swap(master[num], master[num + cnt]);
temp = getPermutations(master, num + 1);
perms.insert(perms.end(), temp.begin(), temp.end());
std::swap(master[num], master[num + cnt]);
}
//The array is not necessarily in alpha-numeric order. So if this is the full array sort it before returning
if(num == 0){
std::sort(perms.begin(), perms.end());
}
return perms;
}
//This function returns the number of times the character occurs in the string
int findNumOccurrence(std::string str, char ch){
int num = 0; //Set the number of occurrences to 0 to start
//Loop through every character in the string and compare it to the character passed in
for(char strCh : str){
//If the character is the same as the one passed in increment the counter
if(strCh == ch){
++num;
}
}
//Return the number of times the character appeared in the string
return num;
}
//Return a vector of strings split on the delimiter
std::vector<std::string> split(std::string str, char delimiter){
std::vector<std::string> splitStrings;
int location = 0;
location = str.find(delimiter);
while(location != std::string::npos){
//Split the string
std::string firstString = str.substr(0, location);
str = str.substr(location + 1); //+1 to skip the delimiter itself
//Add the string to the vector
splitStrings.push_back(firstString);
//Get the location of the next delimiter
location = str.find(delimiter);
}
//Get the final string if it isn't empty
if(!str.empty()){
splitStrings.push_back(str);
}
//Return the vector of strings
return splitStrings;
}
//This function returns true if the string passed in is a palindrome
bool isPalindrome(std::string str){
std::string rev = str;
std::reverse(rev.begin(), rev.end());
if(str == rev){
return true;
}
else{
return false;
}
}
}
#endif //MEE_STRING_ALGORITHMS_HPP

View File

@@ -0,0 +1,213 @@
//myClasses/headers/mee/vectorAlgorithms.hpp
//Matthew Ellison
// Created: 07-02-21
//Modified: 07-02-21
//This file contains declarations of functions I have created to manipulate vectors and the data inside them
/*
Copyright (C) 2021 Matthew Ellison
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef MEE_VECTOR_ALGORITHMS_HPP
#define MEE_VECTOR_ALGORITHMS_HPP
#include <cinttypes>
#include <sstream>
#include <vector>
namespace mee{
//This is a function that returns the sum of all elements in a vector
template <class T>
T getSum(const std::vector<T>& ary){
T sum = 0;
for(unsigned int cnt = 0;cnt < ary.size();++cnt){
sum += ary.at(cnt);
}
return sum;
}
//This is a function that returns the product of all elmements in a vector
template <class T>
T getProduct(const std::vector<T>& ary){
//Make sure there is something in the array
if(ary.size() == 0){
return 0;
}
//Multiply all elements in the array together
T prod = 1;
for(T cnt = 0;cnt < ary.size();++cnt){
prod *= ary.at(cnt);
}
return prod;
}
//This is a function that searches a vecter for an element. Returns true if they key is found in list
template <class T>
bool isFound(std::vector<T> ary, T key){
typename std::vector<T>::iterator location = std::find(ary.begin(), ary.end(), key);
if(location == ary.end()){
return false;
}
else{
return true;
}
}
//This is a function that performs a bubble sort on a vector
template <class T>
void bubbleSort(std::vector<T>& ary){
bool notFinished = true; //A flag to determine if the loop is finished
for(int numLoops = 0;numLoops < ary.size();++numLoops){ //Loop until you finish
notFinished = false; //Assume you are finished until you find an element out of order
//Loop through every element in the vector, moving the largest one to the end
for(int cnt = 1;cnt < (ary.size() - numLoops);++cnt){ //use size - 1 to make sure you don't go out of bounds
if(ary.at(cnt) < ary.at(cnt - 1)){
std::swap(ary.at(cnt), ary.at(cnt - 1));
notFinished = true;
}
}
}
}
//This is a helper function for quickSort. It chooses a pivot element and sorts everything to larger or smaller than the pivot. Returns location of pivot
template <class T>
int64_t partition(std::vector<T>& ary, int64_t bottom, int64_t top){
int64_t pivot = ary.at(top); //Pick a pivot element
int64_t smaller = bottom - 1; //Keep track of where all elements are smaller than the pivot
//Loop through every element in the vector testing if it is smaller than pivot
for(int64_t cnt = bottom;cnt < top;++cnt){
//If the element is smaller than pivot move it to the correct location
if(ary.at(cnt) < pivot){
//Increment the tracker for elements smaller than pivot
++smaller;
//Swap the current element to the correct location for being smaller than the pivot
std::swap(ary.at(smaller), ary.at(cnt));
}
}
//Move the pivot element to the correct location
++smaller;
std::swap(ary.at(top), ary.at(smaller));
//Return the pivot element
return smaller;
}
//This is the function that actually performs the quick sort on the vector
template <class T>
void quickSort(std::vector<T>& ary, int64_t bottom, int64_t top){
//Make sure you have a valid slice of the vector
if(bottom < top){
//Get the pivot location
int64_t pivot = partition(ary, bottom, top);
//Sort all element less than the pivot
quickSort(ary, bottom, pivot - 1);
//Sort all element greater than the pivot
quickSort(ary, pivot + 1, top);
}
}
//This is a function that makes quick sort easier to start
template <class T>
void quickSort(std::vector<T>& ary){
//Call the other quickSort function with all the necessary info
quickSort(ary, 0, ary.size() - 1);
}
//This is a function that performs a search on a vector and returns the subscript of the item being searched for
template <class T>
int64_t search(const std::vector<T>& ary, T num){
int64_t subscript = 0; //Start with the subscript at 0
//Step through every element in the vector and return the subscript if you find the correct element
while(subscript < ary.size()){
if(ary.at(subscript) == num){
return subscript;
}
else{
++subscript;
}
}
//If you cannot find the element return -1
return -1;
}
//This function finds the smallest element in a vector
template <class T>
T findMin(const std::vector<T>& ary){
T min; //For the smallest element
//Make sure the vector is not empty
if(ary.size() > 0){
//Use the first element as the smallest element
min = ary.at(0);
//Run through every element in the vector, checking it against the current minimum
for(int cnt = 1;cnt < ary.size();++cnt){
//If the current element is smaller than the minimum, make it the new minimum
if(ary.at(cnt) < min){
min = ary.at(cnt);
}
}
}
//Return the element
return min;
}
//This function finds the largest element in a vector
template <class T>
T findMax(const std::vector<T>& ary){
T max; //For the largest element
//Make sure the vector is not empty
if(ary.size() > 0){
//Use the first element as the largest element
max = ary.at(0);
//Run through every element in the vector, checking it against the current minimum
for(int cnt = 1;cnt < ary.size();++cnt){
//If the current element is larger than the maximum, make it the new maximum
if(ary.at(cnt) > max){
max = ary.at(cnt);
}
}
}
//Return the element
return max;
}
//Print a vector
template <class T>
std::string printVector(std::vector<T>& ary){
std::stringstream str;
str << "[";
for(int cnt = 0;cnt < ary.size();++cnt){
str << ary[cnt];
if(cnt < ary.size() - 1){
str << ", ";
}
}
str << "]";
return str.str();
}
}
#endif //MEE_VECTOR_ALGORITHMS_HPP

View File

@@ -25,7 +25,7 @@
#include <cinttypes>
#include "Dice.hpp"
const int LENGTH_OF_TEST = 100; //How many times the dice will get rolled * the number of sides
const uint64_t LENGTH_OF_TEST = 100; //How many times the dice will get rolled * the number of sides
int main(){
@@ -58,12 +58,12 @@ int main(){
die1Rolls.push_back(0);
}
//A loop to roll the die and record the results
for(int cnt = 0;cnt < (LENGTH_OF_TEST * die1.getSides());++cnt){
int num = die1.roll();
for(uint64_t cnt = 0;cnt < (LENGTH_OF_TEST * die1.getSides());++cnt){
uint64_t num = die1.roll();
++die1Rolls[num - 1]; //num - 1 to account for dice starting at 1 and array starting at 0
}
//Print out the results
for(int cnt = 0;cnt < die1Rolls.size();++cnt){
for(size_t cnt = 0;cnt < die1Rolls.size();++cnt){
std::cout << cnt + 1 << ". " << die1Rolls[cnt] << '\n';
}
@@ -72,16 +72,16 @@ int main(){
//Setup an array to track how many times a number has been rolled
std::vector<unsigned int> die2Rolls;
die2Rolls.reserve(die2.getSides());
for(int cnt = 0;cnt < die2.getSides();++cnt){
for(uint64_t cnt = 0;cnt < die2.getSides();++cnt){
die2Rolls.push_back(0);
}
//A loop to roll the die and record the results
for(int cnt = 0;cnt < (LENGTH_OF_TEST * die2.getSides());++cnt){
for(uint64_t cnt = 0;cnt < (LENGTH_OF_TEST * die2.getSides());++cnt){
int num = die2.roll();
++die2Rolls[num - 1]; //num - 1 to account for dice starting at 1 and array starting at 0
}
//Print out the results
for(int cnt = 0;cnt < die2Rolls.size();++cnt){
for(uint64_t cnt = 0;cnt < die2Rolls.size();++cnt){
std::cout << cnt + 1 << ". " << die2Rolls[cnt] << '\n';
}

View File

@@ -0,0 +1,328 @@
//myClasses/test/mee/testNumberAlgorithms.cpp
//Matthew Ellison
// Created: 07-02-21
//Modified: 07-02-21
//This file contains tests for the functions in my numberAlgorithms library
/*
Copyright (C) 2021 Matthew Ellison
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cinttypes>
#include <iostream>
#include <gmpxx.h>
#include "mee/numberAlgorithms.hpp"
#include "mee/Stopwatch.hpp"
//Defines a type for functions so there can be an array of functions
typedef bool (*boolFn)();
//Prototypes for test functions
bool testIsPrime();
bool testGetPrimes();
bool testGetNumPrimes();
bool testGetFactors();
bool testGetDivisors();
bool testGetFib();
bool testGetAllFib();
bool testToBin();
bool testFactorial();
bool testSieveOfEratosthenes();
int main(){
mee::Stopwatch timer;
bool passedTest = false;
bool allPassed = true;
std::vector<boolFn> functions { testIsPrime, testGetPrimes, testGetNumPrimes, testGetFactors, testGetDivisors, testGetFib,
testGetAllFib, testToBin, testFactorial, testSieveOfEratosthenes };
std::vector<std::string> names { "isPrime", "getPrimes", "getNumPrimes", "getFactors", "getDivisors", "getFib",
"getAllFib", "toBin", "factorial", "sieveOfEratosthenes" };
//Start doing tests and print out the results of each
for(size_t cnt = 0;cnt < functions.size();++cnt){
timer.start();
passedTest = functions[cnt]();
timer.stop();
if(passedTest){
std::cout << "Function " << names[cnt] << "() passed the test\n";
}
else{
std::cout << "Function " << names[cnt] << "() failed the test\n";
allPassed = false;
}
std::cout << "The test took " << timer.getStr() << "\n\n" << std::endl;
}
if(allPassed){
return 0;
}
else{
return 1;
}
}
bool testIsPrime(){
//Test 1
int64_t num = 2;
bool correctAnswer = true;
bool answer = mee::isPrime(num);
if(correctAnswer != answer){
return false;
}
//Test 2
num = 97;
correctAnswer = true;
answer = mee::isPrime(num);
if(correctAnswer != answer){
return false;
}
//Test 3
num = 1000;
correctAnswer = false;
answer = mee::isPrime(num);
if(correctAnswer != answer){
return false;
}
//Test 4
num = 1;
correctAnswer = false;
answer = mee::isPrime(num);
if(correctAnswer != answer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetPrimes(){
std::vector<uint64_t> correctAnswer {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
uint64_t topNum = 100;
std::vector<uint64_t> answer = mee::getPrimes(topNum);
if(correctAnswer != answer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetNumPrimes(){
std::vector<uint64_t> correctAnswer {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
uint64_t numPrimes = 25;
std::vector<uint64_t> answer = mee::getNumPrimes(numPrimes);
if(correctAnswer != answer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetFactors(){
std::vector<uint64_t> correctAnswer {2, 2, 5, 5};
uint64_t number = 100;
std::vector<uint64_t> answer = mee::getFactors(number);
if(correctAnswer != answer){
return false;
}
correctAnswer = {2, 7, 7};
number = 98;
answer = mee::getFactors(number);
if(correctAnswer != answer){
return false;
}
//If a false was not triggered it must have passed all tests
return true;
}
bool testGetDivisors(){
std::vector<uint64_t> correctAnswer {1, 2, 4, 5, 10, 20, 25, 50, 100};
uint64_t topNum = 100;
std::vector<uint64_t> answer = mee::getDivisors(topNum);
if(correctAnswer != answer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetFib(){
//Test the imbeded type getFib function
uint64_t correctAnswer = 144;
uint64_t number = 12;
uint64_t answer = mee::getFib(number);
if(correctAnswer != answer){
std::cout << "getFit() failed at test 1" << std::endl;
return false;
}
number = 20;
correctAnswer = 6765;
answer = mee::getFib(number);
if(correctAnswer != answer){
std::cout << "getFit() failed at test 2" << std::endl;
return false;
}
//Test the gmp integer function
mpz_class mpzNumber = 12;
mpz_class longCorrectAnswer = 144;
mpz_class longAnswer = mee::getFib(mpzNumber);
if(longCorrectAnswer != longAnswer){
std::cout << "getFib() for mpz failed at test 3" << std::endl;
return false;
}
mpzNumber = 4782;
longCorrectAnswer = "1070066266382758936764980584457396885083683896632151665013235203375314520604694040621889147582489792657804694888177591957484336466672569959512996030461262748092482186144069433051234774442750273781753087579391666192149259186759553966422837148943113074699503439547001985432609723067290192870526447243726117715821825548491120525013201478612965931381792235559657452039506137551467837543229119602129934048260706175397706847068202895486902666185435124521900369480641357447470911707619766945691070098024393439617474103736912503231365532164773697023167755051595173518460579954919410967778373229665796581646513903488154256310184224190259846088000110186255550245493937113651657039447629584714548523425950428582425306083544435428212611008992863795048006894330309773217834864543113205765659868456288616808718693835297350643986297640660000723562917905207051164077614812491885830945940566688339109350944456576357666151619317753792891661581327159616877487983821820492520348473874384736771934512787029218636250627816";
longAnswer = mee::getFib(mpzNumber);
if(longCorrectAnswer != longAnswer){
std::cout << "getFib() for mpzfailed at test 4" << std::endl;
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetAllFib(){
std::vector<uint64_t> correctAnswer {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
uint64_t highestNumber = 100;
std::vector<uint64_t> answer = mee::getAllFib(highestNumber);
if(correctAnswer != answer){
return false;
}
correctAnswer = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987};
highestNumber = 1000;
answer = mee::getAllFib(highestNumber);
if(correctAnswer != answer){
return false;
}
//If a false was not triggered it must have passed all tests
return true;
}
bool testToBin(){
//Test 1
int num = 7;
std::string correctAnswer = "111";
std::string answer = mee::toBin(num);
if(correctAnswer != answer){
return false;
}
//Test 2
num = 0;
correctAnswer = "0";
answer = mee::toBin(num);
if(correctAnswer != answer){
return false;
}
//Test 3
num = 1000000;
correctAnswer = "11110100001001000000";
answer = mee::toBin(num);
if(correctAnswer != answer){
return false;
}
//Test 4
uint64_t num2 = 8;
correctAnswer = "1000";
answer = mee::toBin(num2);
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testFactorial(){
//Test 1
int num = 1;
int correctAnswer = 1;
int answer = mee::factorial(num);
if(correctAnswer != answer){
return false;
}
//Test 2
num = 10;
correctAnswer = 3628800;
answer = mee::factorial(num);
if(correctAnswer != answer){
return false;
}
//Test 3
num = -5;
correctAnswer = 1;
answer = mee::factorial(num);
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testSieveOfEratosthenes(){
//Test 1
mee::Generator<int> gen = mee::sieveOfEratosthenes<int>();
std::vector<int> correctAnswer{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
std::vector<int> answer;
for(int cnt = 0;cnt < 25;++cnt){
int prime = gen.next();
answer.push_back(prime);
}
if(correctAnswer != answer){
return false;
}
//Test 2
mee::Generator<mpz_class> mpzGen = mee::sieveOfEratosthenesAlt<mpz_class>();
std::vector<mpz_class> bigCorrectAnswer{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
std::vector<mpz_class> bigAnswer;
for(int cnt = 0;cnt < 25;++cnt){
mpz_class prime = mpzGen.next();
bigAnswer.push_back(prime);
}
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
/* Results:
*/

View File

@@ -6,7 +6,7 @@
#include <iostream>
#include "Stopwatch.hpp"
#include "mee/Stopwatch.hpp"
int main(){
mee::Stopwatch timer;
@@ -54,6 +54,7 @@ int main(){
timer.start();
for(int cnt = 0;cnt < 1000000;++cnt){
int num = cnt;
cnt = num;
}
timer.stop();
std::cout << "It took " << timer.getStr() << " to complete this loop\n";

View File

@@ -0,0 +1,169 @@
//myClasses/test/mee/testStringAlgorithms.cpp
//Matthew Ellison
// Created: 07-02-21
//Modified: 07-02-21
//This file contains tests for the functions in my stringAlgorithms library
/*
Copyright (C) 2021 Matthew Ellison
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include "mee/Stopwatch.hpp"
#include "mee/stringAlgorithms.hpp"
#include "mee/vectorAlgorithms.hpp"
//Defines a type for functions so there can be an array of functions
typedef bool (*boolFn)();
//Prototypes for test functions
bool testGetPermutations();
bool testFindNumOccurrence();
bool testSplit();
bool testIsPalindrome();
int main(){
mee::Stopwatch timer;
bool passedTest = false;
bool allPassed = true;
std::vector<boolFn> functions { testGetPermutations, testFindNumOccurrence, testSplit, testIsPalindrome};
std::vector<std::string> names { "getPermutations", "findNumOccurrence", "split", "isPalindrome"};
//Start doing tests and print out the results of each
for(size_t cnt = 0;cnt < functions.size();++cnt){
timer.start();
passedTest = functions[cnt]();
timer.stop();
if(passedTest){
std::cout << "Function " << names[cnt] << "() passed the test\n";
}
else{
std::cout << "Function " << names[cnt] << "() failed the test\n";
allPassed = false;
}
std::cout << "The test took " << timer.getStr() << "\n\n" << std::endl;
}
if(allPassed){
return 0;
}
else{
return 1;
}
}
bool testGetPermutations(){
std::string permString = "012";
std::vector<std::string> correctAnswer {"012", "021", "102", "120", "201", "210"};
std::vector<std::string> answer = mee::getPermutations(permString);
if(answer != correctAnswer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testFindNumOccurrence(){
//Test 1
std::string testString = "abcdefgdd";
char testChar = 'a';
int correctAnswer = 1;
int answer = mee::findNumOccurrence(testString, testChar);
if(correctAnswer != answer){
return false;
}
//Test 2
testChar = 'd';
correctAnswer = 3;
answer = mee::findNumOccurrence(testString, testChar);
if(correctAnswer != answer){
return false;
}
//Test 3
testChar = 'h';
correctAnswer = 0;
answer = mee::findNumOccurrence(testString, testChar);
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testSplit(){
//Test 1
std::string str = "abc0def";
std::vector<std::string> correctAnswer = {"abc", "def"};
std::vector<std::string> answer = mee::split(str, '0');
if(correctAnswer != answer){
return false;
}
//Test 2
str = "abc0def";
correctAnswer = {"abc0def"};
answer = mee::split(str, '1');
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testIsPalindrome(){
//Test 1
std::string str = "101";
bool correctAnswer = true;
bool answer = mee::isPalindrome(str);
if(correctAnswer != answer){
return false;
}
//Test 2
str = "100";
correctAnswer = false;
answer = mee::isPalindrome(str);
if(correctAnswer != answer){
return false;
}
//Test 3
str = "";
correctAnswer = true;
answer = mee::isPalindrome(str);
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
/* Results:
*/

View File

@@ -0,0 +1,346 @@
//myClasses/test/mee/testVectorAlgorithms.cpp
//Matthew Ellison
// Created: 07-02-21
//Modified: 07-02-21
//This file contains tests for the functions in my vetorAlgorithms library
/*
Copyright (C) 2021 Matthew Ellison
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cinttypes>
#include <iostream>
#include <random>
#include <vector>
#include "mee/numberAlgorithms.hpp"
#include "mee/Stopwatch.hpp"
#include "mee/vectorAlgorithms.hpp"
//Defines a type for functions so there can be an array of functions
typedef bool (*boolFn)();
//Prototypes for test functions
bool testGetSum();
bool testGetProduct();
bool testIsFound();
bool testBubbleSort();
bool testQuickSort();
bool testSearch();
bool testFindMin();
bool testFindMax();
bool testPrintVector();
int main(){
mee::Stopwatch timer;
bool passedTest = false;
bool allPassed = true;
std::vector<boolFn> functions {testGetSum, testGetProduct, testIsFound, testBubbleSort, testQuickSort, testSearch,
testFindMin, testFindMax, testPrintVector};
std::vector<std::string> names { "getSum", "getProduct", "isFound", "bubbleSort", "quickSort", "search",
"findMin", "findMax", "printVector"};
//Start doing tests and print out the results of each
for(size_t cnt = 0;cnt < functions.size();++cnt){
timer.start();
passedTest = functions[cnt]();
timer.stop();
if(passedTest){
std::cout << "Function " << names[cnt] << "() passed the test\n";
}
else{
std::cout << "Function " << names[cnt] << "() failed the test\n";
allPassed = false;
}
std::cout << "The test took " << timer.getStr() << "\n\n" << std::endl;
}
if(allPassed){
return 0;
}
else{
return 1;
}
}
bool testGetSum(){
uint64_t correctAnswer = 1060;
uint64_t topNum = 100;
uint64_t answer = mee::getSum(mee::getPrimes(topNum));
if(correctAnswer != answer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetProduct(){
uint64_t correctAnswer = 0;
std::vector<uint64_t> numbers = {};
uint64_t answer = mee::getProduct(numbers);
if(correctAnswer != answer){
return false;
}
correctAnswer = 57600;
numbers = {2, 2, 3, 3, 4, 4, 100};
answer = mee::getProduct(numbers);
if(correctAnswer != answer){
return false;
}
//If a false was not triggered it must have passed all tests
return true;
}
bool testIsFound(){
bool correctAnswer = true;
std::vector<uint64_t> testVector = mee::getPrimes((uint64_t)100);
uint64_t searchFor = 79;
bool answer = mee::isFound(testVector, searchFor);
if(answer != correctAnswer){
std::cout << "isFound() is failed at test 1" << std::endl;
return false;
}
searchFor = 97;
answer = mee::isFound(testVector, searchFor);
if(answer != correctAnswer){
std::cout << "isFound() is failed at test 2" << std::endl;
return false;
}
searchFor = 88;
correctAnswer = false;
answer = mee::isFound(testVector, searchFor);
if(answer != correctAnswer){
std::cout << "isFound() is failed at test 3" << std::endl;
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testBubbleSort(){
unsigned int NUM_TO_GENERATE = 10000;
std::default_random_engine generator(std::random_device{}());
std::uniform_int_distribution<int> dist(1, INT_MAX);
std::vector<int> nums;
//Run through the appropriate number of numbers to generate and add them to the vector
for(unsigned int cnt = 0;cnt < NUM_TO_GENERATE;++cnt){
nums.push_back(dist(generator));
}
//Sort the numbers with my algorithm
mee::bubbleSort(nums);
//Make sure each number is not < the one in behind it
for(size_t cnt = 1;cnt < nums.size();++cnt){
if(nums.at(cnt) < nums.at(cnt - 1)){
return false;
std::cout << "nums.size() " << nums.size() << "\ncnt " << cnt << std::endl;
}
}
//If the false was not triggered then everything must have been sorted correctly
return true;
}
bool testQuickSort(){
unsigned int NUM_TO_GENERATE = 10000;
std::default_random_engine generator(std::random_device{}());
std::uniform_int_distribution<int> dist(1, INT_MAX);
std::vector<int> nums;
//Run through the appropriate number of numbers to generate and add them to the vector
for(unsigned int cnt = 0;cnt < NUM_TO_GENERATE;++cnt){
nums.push_back(dist(generator));
}
//Sort the numbers with my algorithm
mee::quickSort(nums);
//Make sure each number is not < the one in behind it
for(size_t cnt = 1;cnt < nums.size();++cnt){
if(nums.at(cnt) < nums.at(cnt - 1)){
return false;
}
}
//If the false was not triggered then everything must have been sorted correctly
return true;
}
bool testSearch(){
int64_t found = -1;
//Create a vector of numbers
std::vector<int> nums {1, 20, 3, 40, 5, 60, 7, 80, 9};
//Search for one that is in the vector
found = mee::search(nums, 1);
if(found != 0){ //This number is in the vector, if it was not found in the vector there is a problem
return false;
}
//Search for another that is in the vector
found = mee::search(nums, 9);
if(found != 8){ //This number is in the vector, if it was not found in the vector there is a problem
return false;
}
//Search for another that is in the vector
found = mee::search(nums, 60);
if(found != 5){ //This number is in the vector, if it was not found in the vector there is a problem
return false;
}
//Search for a number that is not in the vector
found = mee::search(nums, 6);
if(found != -1){
return false;
}
//If it didn't trigger a false then everything went through correctly
return true;
}
bool testFindMin(){
std::vector<int> arr {1, 2, 3, 4, 5, 6, 7, 8, 9};
int answer = 0;
//Test first
answer = mee::findMin(arr);
if(answer != 1){
return false;
}
//Test last
answer = 0;
arr = {9, 8, 7, 6, 5, 4, 3, 2, 1};
answer = mee::findMin(arr);
if(answer != 1){
return false;
}
//Test middle
answer = 0;
arr = {9, 5, 3, 6, 8, 1, 7, 2, 4};
answer = mee::findMin(arr);
if(answer != 1){
return false;
}
//Test negative
answer = 0;
arr = {-1, -2, -3, -4, -5, -6, -7, -8, -9};
answer = mee::findMin(arr);
if(answer != -9){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testFindMax(){
std::vector<int> arr {1, 2, 3, 4, 5, 6, 7, 8, 9};
int answer = 0;
//Test last
answer = mee::findMax(arr);
if(answer != 9){
return false;
}
//Test first
answer = 0;
arr = {9, 8, 7, 6, 5, 4, 3, 2, 1};
answer = mee::findMax(arr);
if(answer != 9){
return false;
}
//Test middle
answer = 0;
arr = {9, 5, 3, 6, 8, 1, 7, 2, 4};
answer = mee::findMax(arr);
if(answer != 9){
return false;
}
//Test negative
answer = 0;
arr = {-1, -2, -3, -4, -5, -6, -7, -8, -9};
answer = mee::findMax(arr);
if(answer != -1){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testPrintVector(){
//Test 1
std::vector<int> nums;
std::string correctAnswer = "[]";
std::string answer = mee::printVector(nums);
if(correctAnswer != answer){
return false;
}
//Test 2
nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
correctAnswer = "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]";
answer = mee::printVector(nums);
if(correctAnswer != answer){
return false;
}
//Test 3
nums = {-3, -2, -1, 0, 1, 2, 3};
correctAnswer = "[-3, -2, -1, 0, 1, 2, 3]";
answer = mee::printVector(nums);
if(correctAnswer != answer){
return false;
}
//Test 4
std::vector<std::string> strings = {"A", "B", "C"};
correctAnswer = "[A, B, C]";
answer = mee::printVector(strings);
if(correctAnswer != answer){
return false;
}
//Test 5
strings = {"abc", "def", "ghi"};
correctAnswer = "[abc, def, ghi]";
answer = mee::printVector(strings);
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
/* Results:
*/

View File

@@ -1,750 +0,0 @@
//myClasses/Algorithms.cpp
//Matthew Ellison
// Created: 11-14-18
//Modified: 06-29-21
//This is the file that tests all my algorithms, both for speed and accuracy
/*
Copyright (C) 2021 Matthew Ellison
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <vector>
#include <string>
#include <random>
#include <gmpxx.h>
#include "Algorithms.hpp"
#include "Stopwatch.hpp"
//Defines a type for functions so there can be an array of functions
typedef bool (*boolFn)();
//A function to test every set of funtions in Algorithms.hpp
//Some of the functions are overloaded, so I test all overloaded functions in each function
bool testGetPrimes();
bool testGetNumPrimes();
bool testIsPrime();
bool testGetFactors();
bool tetsGetDivisors();
bool testGetSum();
bool testGetProduct();
bool testIsFound();
bool testGetPermutations();
bool testGetFib();
bool testGetAllFib();
bool testBubbleSort();
bool testQuickSort();
bool testSearch();
bool testFindMin();
bool testFindMax();
bool testFindNumOccurrence();
bool testFactorial();
bool testIsPalindrome();
bool testToBin();
bool testPrintVector();
bool testSieveOfEratosthenes();
int main(){
mee::Stopwatch timer;
bool passedTest = false;
std::vector<boolFn> functions {testGetPrimes, testGetNumPrimes, testIsPrime, testGetFactors, tetsGetDivisors, testGetSum, testGetProduct, testIsFound, testGetPermutations,
testGetFib, testGetAllFib, testBubbleSort, testQuickSort, testSearch, testFindMin, testFindMax, testFindNumOccurrence, testFactorial, testIsPalindrome, testToBin,
testPrintVector, testSieveOfEratosthenes};
std::vector<std::string> names {"getPrimes", "getNumPrimes", "isPrime", "getFactors", "getDivisors", "getSum", "getProduct", "isFound", "getPermutations",
"getFib", "getAllFib", "bubbleSort", "quickSort", "search", "findMin", "findMax", "findNumOccurrence", "factorial", "isPalindrome", "toBin",
"testPrintVector", "testSieveOfEratosthenes"};
//Start doing tests and print out the results of each
for(int cnt = 0;cnt < functions.size();++cnt){
timer.start();
passedTest = functions[cnt]();
timer.stop();
if(passedTest){
std::cout << "Function " << names.at(cnt) << "() passed the test\n";
}
else{
std::cout << "Function " << names.at(cnt) << "() failed the test\n";
}
std::cout << "The test took " << timer.getStr() << "\n\n" << std::endl;
}
return 0;
}
bool testGetPrimes(){
std::vector<uint64_t> correctAnswer {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
uint64_t topNum = 100;
std::vector<uint64_t> answer = mee::getPrimes(topNum);
if(correctAnswer != answer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetNumPrimes(){
std::vector<uint64_t> correctAnswer {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
uint64_t numPrimes = 25;
std::vector<uint64_t> answer = mee::getNumPrimes(numPrimes);
if(correctAnswer != answer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testIsPrime(){
//Test 1
int64_t num = 2;
bool correctAnswer = true;
bool answer = mee::isPrime(num);
if(correctAnswer != answer){
return false;
}
//Test 2
num = 97;
correctAnswer = true;
answer = mee::isPrime(num);
if(correctAnswer != answer){
return false;
}
//Test 3
num = 1000;
correctAnswer = false;
answer = mee::isPrime(num);
if(correctAnswer != answer){
return false;
}
//Test 4
num = 1;
correctAnswer = false;
answer = mee::isPrime(num);
if(correctAnswer != answer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetFactors(){
std::vector<uint64_t> correctAnswer {2, 2, 5, 5};
uint64_t number = 100;
std::vector<uint64_t> answer = mee::getFactors(number);
if(correctAnswer != answer){
return false;
}
correctAnswer = {2, 7, 7};
number = 98;
answer = mee::getFactors(number);
if(correctAnswer != answer){
return false;
}
//If a false was not triggered it must have passed all tests
return true;
}
bool tetsGetDivisors(){
std::vector<uint64_t> correctAnswer {1, 2, 4, 5, 10, 20, 25, 50, 100};
uint64_t topNum = 100;
std::vector<uint64_t> answer = mee::getDivisors(topNum);
if(correctAnswer != answer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetSum(){
uint64_t correctAnswer = 1060;
uint64_t topNum = 100;
uint64_t answer = mee::getSum(mee::getPrimes(topNum));
if(correctAnswer != answer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetProduct(){
uint64_t correctAnswer = 0;
std::vector<uint64_t> numbers = {};
uint64_t answer = mee::getProduct(numbers);
if(correctAnswer != answer){
return false;
}
correctAnswer = 57600;
numbers = {2, 2, 3, 3, 4, 4, 100};
answer = mee::getProduct(numbers);
if(correctAnswer != answer){
return false;
}
//If a false was not triggered it must have passed all tests
return true;
}
bool testIsFound(){
bool correctAnswer = true;
std::vector<uint64_t> testVector = mee::getPrimes((uint64_t)100);
uint64_t searchFor = 79;
bool answer = mee::isFound(testVector, searchFor);
if(answer != correctAnswer){
std::cout << "isFound() is failed at test 1" << std::endl;
return false;
}
searchFor = 97;
answer = mee::isFound(testVector, searchFor);
if(answer != correctAnswer){
std::cout << "isFound() is failed at test 2" << std::endl;
return false;
}
searchFor = 88;
correctAnswer = false;
answer = mee::isFound(testVector, searchFor);
if(answer != correctAnswer){
std::cout << "isFound() is failed at test 3" << std::endl;
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetPermutations(){
std::string permString = "012";
std::vector<std::string> correctAnswer {"012", "021", "102", "120", "201", "210"};
std::vector<std::string> answer = mee::getPermutations(permString);
if(answer != correctAnswer){
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetFib(){
//Test the imbeded type getFib function
uint64_t correctAnswer = 144;
uint64_t number = 12;
uint64_t answer = mee::getFib(number);
if(correctAnswer != answer){
std::cout << "getFit() failed at test 1" << std::endl;
return false;
}
number = 20;
correctAnswer = 6765;
answer = mee::getFib(number);
if(correctAnswer != answer){
std::cout << "getFit() failed at test 2" << std::endl;
return false;
}
//Test the gmp integer function
mpz_class mpzNumber = 12;
mpz_class longCorrectAnswer = 144;
mpz_class longAnswer = mee::getFib(mpzNumber);
if(longCorrectAnswer != longAnswer){
std::cout << "getFib() for mpz failed at test 3" << std::endl;
return false;
}
mpzNumber = 4782;
longCorrectAnswer = "1070066266382758936764980584457396885083683896632151665013235203375314520604694040621889147582489792657804694888177591957484336466672569959512996030461262748092482186144069433051234774442750273781753087579391666192149259186759553966422837148943113074699503439547001985432609723067290192870526447243726117715821825548491120525013201478612965931381792235559657452039506137551467837543229119602129934048260706175397706847068202895486902666185435124521900369480641357447470911707619766945691070098024393439617474103736912503231365532164773697023167755051595173518460579954919410967778373229665796581646513903488154256310184224190259846088000110186255550245493937113651657039447629584714548523425950428582425306083544435428212611008992863795048006894330309773217834864543113205765659868456288616808718693835297350643986297640660000723562917905207051164077614812491885830945940566688339109350944456576357666151619317753792891661581327159616877487983821820492520348473874384736771934512787029218636250627816";
longAnswer = mee::getFib(mpzNumber);
if(longCorrectAnswer != longAnswer){
std::cout << "getFib() for mpzfailed at test 4" << std::endl;
return false;
}
//If the false was not triggered it must have passed all tests
return true;
}
bool testGetAllFib(){
std::vector<uint64_t> correctAnswer {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};
uint64_t highestNumber = 100;
std::vector<uint64_t> answer = mee::getAllFib(highestNumber);
if(correctAnswer != answer){
return false;
}
correctAnswer = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987};
highestNumber = 1000;
answer = mee::getAllFib(highestNumber);
if(correctAnswer != answer){
return false;
}
//If a false was not triggered it must have passed all tests
return true;
}
bool testBubbleSort(){
unsigned int NUM_TO_GENERATE = 10000;
std::default_random_engine generator(std::random_device{}());
std::uniform_int_distribution<int> dist(1, INT_MAX);
std::vector<int> nums;
//Run through the appropriate number of numbers to generate and add them to the vector
for(int cnt = 0;cnt < NUM_TO_GENERATE;++cnt){
nums.push_back(dist(generator));
}
//Sort the numbers with my algorithm
mee::bubbleSort(nums);
//Make sure each number is not < the one in behind it
for(int cnt = 1;cnt < nums.size();++cnt){
if(nums.at(cnt) < nums.at(cnt - 1)){
return false;
std::cout << "nums.size() " << nums.size() << "\ncnt " << cnt << std::endl;
}
}
//If the false was not triggered then everything must have been sorted correctly
return true;
}
bool testQuickSort(){
unsigned int NUM_TO_GENERATE = 10000;
std::default_random_engine generator(std::random_device{}());
std::uniform_int_distribution<int> dist(1, INT_MAX);
std::vector<int> nums;
//Run through the appropriate number of numbers to generate and add them to the vector
for(int cnt = 0;cnt < NUM_TO_GENERATE;++cnt){
nums.push_back(dist(generator));
}
//Sort the numbers with my algorithm
mee::quickSort(nums);
//Make sure each number is not < the one in behind it
for(int cnt = 1;cnt < nums.size();++cnt){
if(nums.at(cnt) < nums.at(cnt - 1)){
return false;
}
}
//If the false was not triggered then everything must have been sorted correctly
return true;
}
bool testSearch(){
int64_t found = -1;
//Create a vector of numbers
std::vector<int> nums {1, 20, 3, 40, 5, 60, 7, 80, 9};
//Search for one that is in the vector
found = mee::search(nums, 1);
if(found != 0){ //This number is in the vector, if it was not found in the vector there is a problem
return false;
}
//Search for another that is in the vector
found = mee::search(nums, 9);
if(found != 8){ //This number is in the vector, if it was not found in the vector there is a problem
return false;
}
//Search for another that is in the vector
found = mee::search(nums, 60);
if(found != 5){ //This number is in the vector, if it was not found in the vector there is a problem
return false;
}
//Search for a number that is not in the vector
found = mee::search(nums, 6);
if(found != -1){
return false;
}
//If it didn't trigger a false then everything went through correctly
return true;
}
bool testFindMin(){
std::vector<int> arr {1, 2, 3, 4, 5, 6, 7, 8, 9};
int answer = 0;
//Test first
answer = mee::findMin(arr);
if(answer != 1){
return false;
}
//Test last
answer = 0;
arr = {9, 8, 7, 6, 5, 4, 3, 2, 1};
answer = mee::findMin(arr);
if(answer != 1){
return false;
}
//Test middle
answer = 0;
arr = {9, 5, 3, 6, 8, 1, 7, 2, 4};
answer = mee::findMin(arr);
if(answer != 1){
return false;
}
//Test negative
answer = 0;
arr = {-1, -2, -3, -4, -5, -6, -7, -8, -9};
answer = mee::findMin(arr);
if(answer != -9){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testFindMax(){
std::vector<int> arr {1, 2, 3, 4, 5, 6, 7, 8, 9};
int answer = 0;
//Test last
answer = mee::findMax(arr);
if(answer != 9){
return false;
}
//Test first
answer = 0;
arr = {9, 8, 7, 6, 5, 4, 3, 2, 1};
answer = mee::findMax(arr);
if(answer != 9){
return false;
}
//Test middle
answer = 0;
arr = {9, 5, 3, 6, 8, 1, 7, 2, 4};
answer = mee::findMax(arr);
if(answer != 9){
return false;
}
//Test negative
answer = 0;
arr = {-1, -2, -3, -4, -5, -6, -7, -8, -9};
answer = mee::findMax(arr);
if(answer != -1){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testFindNumOccurrence(){
//Test 1
std::string testString = "abcdefgdd";
char testChar = 'a';
int correctAnswer = 1;
int answer = mee::findNumOccurrence(testString, testChar);
if(correctAnswer != answer){
return false;
}
//Test 2
testChar = 'd';
correctAnswer = 3;
answer = mee::findNumOccurrence(testString, testChar);
if(correctAnswer != answer){
return false;
}
//Test 3
testChar = 'h';
correctAnswer = 0;
answer = mee::findNumOccurrence(testString, testChar);
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testFactorial(){
//Test 1
int num = 1;
int correctAnswer = 1;
int answer = mee::factorial(num);
if(correctAnswer != answer){
return false;
}
//Test 2
num = 10;
correctAnswer = 3628800;
answer = mee::factorial(num);
if(correctAnswer != answer){
return false;
}
//Test 3
num = -5;
correctAnswer = 1;
answer = mee::factorial(num);
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testIsPalindrome(){
//Test 1
std::string str = "101";
bool correctAnswer = true;
bool answer = mee::isPalindrome(str);
if(correctAnswer != answer){
return false;
}
//Test 2
str = "100";
correctAnswer = false;
answer = mee::isPalindrome(str);
if(correctAnswer != answer){
return false;
}
//Test 3
str = "";
correctAnswer = true;
answer = mee::isPalindrome(str);
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testToBin(){
//Test 1
int num = 7;
std::string correctAnswer = "111";
std::string answer = mee::toBin(num);
if(correctAnswer != answer){
return false;
}
//Test 2
num = 0;
correctAnswer = "0";
answer = mee::toBin(num);
if(correctAnswer != answer){
return false;
}
//Test 3
num = 1000000;
correctAnswer = "11110100001001000000";
answer = mee::toBin(num);
if(correctAnswer != answer){
return false;
}
//Test 4
uint64_t num2 = 8;
correctAnswer = "1000";
answer = mee::toBin(num2);
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testPrintVector(){
//Test 1
std::vector<int> nums;
std::string correctAnswer = "[]";
std::string answer = mee::printVector(nums);
if(correctAnswer != answer){
return false;
}
//Test 2
nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
correctAnswer = "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]";
answer = mee::printVector(nums);
if(correctAnswer != answer){
return false;
}
//Test 3
nums = {-3, -2, -1, 0, 1, 2, 3};
correctAnswer = "[-3, -2, -1, 0, 1, 2, 3]";
answer = mee::printVector(nums);
if(correctAnswer != answer){
return false;
}
//Test 4
std::vector<std::string> strings = {"A", "B", "C"};
correctAnswer = "[A, B, C]";
answer = mee::printVector(strings);
if(correctAnswer != answer){
return false;
}
//Test 5
strings = {"abc", "def", "ghi"};
correctAnswer = "[abc, def, ghi]";
answer = mee::printVector(strings);
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
bool testSieveOfEratosthenes(){
//Test 1
mee::SieveOfEratosthenes<int> sieve;
std::vector<int> correctAnswer{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
std::vector<int> answer;
for(int cnt = 0;cnt < 25;++cnt){
int prime = sieve.next();
answer.push_back(prime);
}
if(correctAnswer != answer){
return false;
}
//Test 2
mee::SieveOfEratosthenesAlt<mpz_class> mpzSieve;
std::vector<mpz_class> bigCorrectAnswer{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
std::vector<mpz_class> bigAnswer;
for(int cnt = 0;cnt < 25;++cnt){
mpz_class prime = mpzSieve.next();
bigAnswer.push_back(prime);
}
if(correctAnswer != answer){
return false;
}
//If it hasn't failed a test then return true for passing all the tests
return true;
}
/* Results:
Function getPrimes() passed the test
The test took 9.400 microseconds
Function getNumPrimes() passed the test
The test took 6.400 microseconds
Function isPrime() passed the test
The test took 200.000 nanoseconds
Function getFactors() passed the test
The test took 5.400 microseconds
Function getDivisors() passed the test
The test took 2.000 microseconds
Function getSum() passed the test
The test took 8.500 microseconds
Function getProduct() passed the test
The test took 1.200 microseconds
Function isFound() passed the test
The test took 7.100 microseconds
Function getPermutations() passed the test
The test took 8.800 microseconds
Function getFib() passed the test
The test took 221.400 microseconds
Function getAllFib() passed the test
The test took 4.100 microseconds
Function bubbleSort() passed the test
The test took 1.186 seconds
Function quickSort() passed the test
The test took 3.580 milliseconds
Function search() passed the test
The test took 1.300 microseconds
Function findMin() passed the test
The test took 1.700 microseconds
Function findMax() passed the test
The test took 1.600 microseconds
Function findNumOccurrence() passed the test
The test took 1.400 microseconds
Function factorial() passed the test
The test took 200.000 nanoseconds
Function isPalindrome() passed the test
The test took 1.400 microseconds
Function toBin() passed the test
The test took 9.300 microseconds
Function testPrintVector() passed the test
The test took 9.900 microseconds
*/

View File

@@ -1,2 +0,0 @@
Move different types of algorithms to their own files
Keep an eye on gcc for generator<> implementation