From 5cf20b539ad5cf47de7687386a7fb30658d1810e Mon Sep 17 00:00:00 2001 From: Mattrixwv Date: Fri, 2 Jul 2021 20:50:28 -0400 Subject: [PATCH] Split up algorithms to several sub files --- Algorithms.hpp | 682 ---------------- Dice.hpp => headers/mee/Dice.hpp | 0 Generator.hpp => headers/mee/Generator.hpp | 0 Stopwatch.hpp => headers/mee/Stopwatch.hpp | 0 headers/mee/numberAlgorithms.hpp | 345 ++++++++ headers/mee/stringAlgorithms.hpp | 117 +++ headers/mee/vectorAlgorithms.hpp | 213 +++++ testDice.cpp => test/mee/testDice.cpp | 14 +- test/mee/testNumberAlgorithms.cpp | 328 ++++++++ .../mee/testStopwatch.cpp | 3 +- test/mee/testStringAlgorithms.cpp | 169 ++++ test/mee/testVectorAlgorithms.cpp | 346 ++++++++ testAlgorithms.cpp | 750 ------------------ todo.txt | 2 - 14 files changed, 1527 insertions(+), 1442 deletions(-) delete mode 100644 Algorithms.hpp rename Dice.hpp => headers/mee/Dice.hpp (100%) rename Generator.hpp => headers/mee/Generator.hpp (100%) rename Stopwatch.hpp => headers/mee/Stopwatch.hpp (100%) create mode 100644 headers/mee/numberAlgorithms.hpp create mode 100644 headers/mee/stringAlgorithms.hpp create mode 100644 headers/mee/vectorAlgorithms.hpp rename testDice.cpp => test/mee/testDice.cpp (86%) create mode 100644 test/mee/testNumberAlgorithms.cpp rename testStopwatch.cpp => test/mee/testStopwatch.cpp (98%) create mode 100644 test/mee/testStringAlgorithms.cpp create mode 100644 test/mee/testVectorAlgorithms.cpp delete mode 100644 testAlgorithms.cpp diff --git a/Algorithms.hpp b/Algorithms.hpp deleted file mode 100644 index c158f8b..0000000 --- a/Algorithms.hpp +++ /dev/null @@ -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 . -*/ - -#ifndef MEE_ALGORITHMS_HPP -#define MEE_ALGORITHMS_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 -bool isPrime(T num); -//This is a function that returns all the primes <= goalNumber and returns a vector with those prime numbers -template -std::vector getPrimes(T goalNumber); -//This function returns a vector with a specific number of primes -template -std::vector getNumPrimes(T numberOfPrimes); -//This function returns all prime factors of a number -template -std::vector getFactors(T goalNumber); -//This is a function that gets all the divisors of num and returns a vector containing the divisors -template -std::vector getDivisors(T num); -//This is a function that returns the sum of all elements in a vector -template -T getSum(const std::vector& numbers); -//This is a function that returns the product of all elements in a vector -template -T getProduct(const std::vector& nums); -//This is a function that searches a vecter for an element. Returns true if the key is found in list -template -bool isFound(std::vector 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 getPermutations(std::string master, int num = 0); -//These functions return the numth Fibonacci number -template -T getFib(const T num); -//This function returns a vector that includes all Fibonacci numbers <= num -template -std::vector getAllFib(const T num); -//This is a function that performs a bubble sort on a vector -template -void bubbleSort(std::vector& ary); -//This is a function that makes quick sort easier to start -template -void quickSort(std::vector& ary); -//This is the function that actually performs the quick sort on the vector -template -void quickSort(std::vector& 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 -int64_t partition(std::vector& 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 -int64_t search(const std::vector& ary, T num); -//This function finds the smallest element in a vector -template -T findMin(const std::vector& ary); -//This function finds the largest element in a vector -template -T findMax(const std::vector& 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 -std::string toBin(T num); - - -template -class SieveOfEratosthenes{ -private: - T possiblePrime; //The next number that could be a prime - std::unordered_map> 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 SieveOfEratosthenesAlt{ -private: - T possiblePrime; //The next number that could be a prime - std::map> 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 -std::vector getPrimes(T goalNumber){ - std::vector 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 -std::vector getNumPrimes(T numberOfPrimes){ - std::vector 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 -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 -std::vector 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 primes = getPrimes((T)ceil(sqrt(goalNumber))); //Make sure you are getting a vector of the correct type - std::vector 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 -std::vector getDivisors(T num){ - std::vector 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 -T getSum(const std::vector& 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 -T getProduct(const std::vector& 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 -bool isFound(std::vector ary, T key){ - typename std::vector::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 getPermutations(std::string master, int num){ - std::vector 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 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 -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 -std::vector getAllFib(const T num){ - std::vector 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 -void bubbleSort(std::vector& 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 -void quickSort(std::vector& 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 -void quickSort(std::vector& 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 -int64_t partition(std::vector& 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 -int64_t search(const std::vector& 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 -T findMin(const std::vector& 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 -T findMax(const std::vector& 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 split(std::string str, char delimiter){ - std::vector 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 -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 -std::string toBin(T num){ - //Convert the number to a binary string - std::string fullString = std::bitset(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 -std::string printVector(std::vector& 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 diff --git a/Dice.hpp b/headers/mee/Dice.hpp similarity index 100% rename from Dice.hpp rename to headers/mee/Dice.hpp diff --git a/Generator.hpp b/headers/mee/Generator.hpp similarity index 100% rename from Generator.hpp rename to headers/mee/Generator.hpp diff --git a/Stopwatch.hpp b/headers/mee/Stopwatch.hpp similarity index 100% rename from Stopwatch.hpp rename to headers/mee/Stopwatch.hpp diff --git a/headers/mee/numberAlgorithms.hpp b/headers/mee/numberAlgorithms.hpp new file mode 100644 index 0000000..98d0833 --- /dev/null +++ b/headers/mee/numberAlgorithms.hpp @@ -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 . +*/ +#ifndef MEE_NUMBER_ALGORITHMS_HPP +#define MEE_NUMBER_ALGORITHMS_HPP + + +#include +#include +#include +#include +#include +#include +#include +#include "Generator.hpp" + + +namespace mee{ + + +//This function determines whether the number passed into it is a prime +template +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 +std::vector getPrimes(T goalNumber){ + std::vector 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 +std::vector getNumPrimes(T numberOfPrimes){ + std::vector 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 +std::vector 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 primes = getPrimes((T)ceil(sqrt(goalNumber))); //Make sure you are getting a vector of the correct type + std::vector 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 +std::vector getDivisors(T num){ + std::vector 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 +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 +std::vector getAllFib(const T num){ + std::vector 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 +std::string toBin(T num){ + //Convert the number to a binary string + std::string fullString = std::bitset(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 +T factorial(T num){ + T fact = 1; + for(T cnt = 1;cnt <= num;++cnt){ + fact *= cnt; + } + return fact; +} + +//A generator for prime numbers +template +mee::Generator 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> 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 +mee::Generator 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> 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 diff --git a/headers/mee/stringAlgorithms.hpp b/headers/mee/stringAlgorithms.hpp new file mode 100644 index 0000000..fa17ee3 --- /dev/null +++ b/headers/mee/stringAlgorithms.hpp @@ -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 . +*/ +#ifndef MEE_STRING_ALGORITHMS_HPP +#define MEE_STRING_ALGORITHMS_HPP + + +#include +#include + + +namespace mee{ + + +//This is a function that creates all permutations of a string and returns a vector of those permutations. +std::vector getPermutations(std::string master, int num = 0){ + std::vector 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 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 split(std::string str, char delimiter){ + std::vector 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 diff --git a/headers/mee/vectorAlgorithms.hpp b/headers/mee/vectorAlgorithms.hpp new file mode 100644 index 0000000..230058d --- /dev/null +++ b/headers/mee/vectorAlgorithms.hpp @@ -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 . +*/ +#ifndef MEE_VECTOR_ALGORITHMS_HPP +#define MEE_VECTOR_ALGORITHMS_HPP + + +#include +#include +#include + + +namespace mee{ + + +//This is a function that returns the sum of all elements in a vector +template +T getSum(const std::vector& 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 +T getProduct(const std::vector& 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 +bool isFound(std::vector ary, T key){ + typename std::vector::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 +void bubbleSort(std::vector& 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 +int64_t partition(std::vector& 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 +void quickSort(std::vector& 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 +void quickSort(std::vector& 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 +int64_t search(const std::vector& 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 +T findMin(const std::vector& 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 +T findMax(const std::vector& 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 +std::string printVector(std::vector& 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 diff --git a/testDice.cpp b/test/mee/testDice.cpp similarity index 86% rename from testDice.cpp rename to test/mee/testDice.cpp index 1bf794e..70edcb8 100644 --- a/testDice.cpp +++ b/test/mee/testDice.cpp @@ -25,7 +25,7 @@ #include #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 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'; } diff --git a/test/mee/testNumberAlgorithms.cpp b/test/mee/testNumberAlgorithms.cpp new file mode 100644 index 0000000..e294fef --- /dev/null +++ b/test/mee/testNumberAlgorithms.cpp @@ -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 . +*/ + + +#include +#include +#include +#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 functions { testIsPrime, testGetPrimes, testGetNumPrimes, testGetFactors, testGetDivisors, testGetFib, + testGetAllFib, testToBin, testFactorial, testSieveOfEratosthenes }; + std::vector 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 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 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 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 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 correctAnswer {2, 2, 5, 5}; + uint64_t number = 100; + std::vector 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 correctAnswer {1, 2, 4, 5, 10, 20, 25, 50, 100}; + uint64_t topNum = 100; + std::vector 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 correctAnswer {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89}; + uint64_t highestNumber = 100; + std::vector 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 gen = mee::sieveOfEratosthenes(); + std::vector 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 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 mpzGen = mee::sieveOfEratosthenesAlt(); + std::vector 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 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: + +*/ diff --git a/testStopwatch.cpp b/test/mee/testStopwatch.cpp similarity index 98% rename from testStopwatch.cpp rename to test/mee/testStopwatch.cpp index fd69202..52a50ab 100644 --- a/testStopwatch.cpp +++ b/test/mee/testStopwatch.cpp @@ -6,7 +6,7 @@ #include -#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"; diff --git a/test/mee/testStringAlgorithms.cpp b/test/mee/testStringAlgorithms.cpp new file mode 100644 index 0000000..a3859de --- /dev/null +++ b/test/mee/testStringAlgorithms.cpp @@ -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 . +*/ + + +#include +#include +#include +#include +#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 functions { testGetPermutations, testFindNumOccurrence, testSplit, testIsPalindrome}; + std::vector 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 correctAnswer {"012", "021", "102", "120", "201", "210"}; + std::vector 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 correctAnswer = {"abc", "def"}; + std::vector 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: + +*/ diff --git a/test/mee/testVectorAlgorithms.cpp b/test/mee/testVectorAlgorithms.cpp new file mode 100644 index 0000000..eceba8f --- /dev/null +++ b/test/mee/testVectorAlgorithms.cpp @@ -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 . +*/ + + +#include +#include +#include +#include +#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 functions {testGetSum, testGetProduct, testIsFound, testBubbleSort, testQuickSort, testSearch, + testFindMin, testFindMax, testPrintVector}; + std::vector 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 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 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 dist(1, INT_MAX); + std::vector 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 dist(1, INT_MAX); + std::vector 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 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 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 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 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 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: + +*/ diff --git a/testAlgorithms.cpp b/testAlgorithms.cpp deleted file mode 100644 index a7c2c03..0000000 --- a/testAlgorithms.cpp +++ /dev/null @@ -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 . -*/ - - -#include -#include -#include -#include -#include -#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 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 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 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 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 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 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 correctAnswer {2, 2, 5, 5}; - uint64_t number = 100; - std::vector 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 correctAnswer {1, 2, 4, 5, 10, 20, 25, 50, 100}; - uint64_t topNum = 100; - std::vector 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 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 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 correctAnswer {"012", "021", "102", "120", "201", "210"}; - std::vector 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 correctAnswer {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89}; - uint64_t highestNumber = 100; - std::vector 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 dist(1, INT_MAX); - std::vector 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 dist(1, INT_MAX); - std::vector 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 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 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 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 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 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 sieve; - std::vector 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 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 mpzSieve; - std::vector 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 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 -*/ diff --git a/todo.txt b/todo.txt index f931d5b..e69de29 100644 --- a/todo.txt +++ b/todo.txt @@ -1,2 +0,0 @@ -Move different types of algorithms to their own files -Keep an eye on gcc for generator<> implementation \ No newline at end of file