//myClasses/Algorithms.hpp //Matthew Ellison // Created: 11-8-18 //Modified: 12-10-18 //This file contains the declarations and implementations to several algoritms that I have found useful /* Copyright (C) 2018 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 //This library is licensed under lgplv3 //You can find more information at gmplib.org #include //This is necessary for the getGmpFib function for numbers larger than a normal int can hold. It can be commented out if needed namespace mee{ //A list of functions in the file //Also works as prototypes with general information //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 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 gets the sum of all elements in a vector and returns the number template T getSum(std::vector numbers); //This is a function that searches a vecter for an element. Returns true if num is found in list template bool isFound(T num, std::vector list); //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 uint64_t getFib(uint64_t num); mpz_class getMpzFib(uint64_t num); //This is a function that performs a bubble sort on a vector template bool bubbleSort(std::vector nums); //This is a function that perfomrs a quick sort on a vector template bool quickSort(std::vector nums); //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(std::vector nums, T num); //This function finds the smallest element in a vector template T findMin(std::vector arr); //This function finds the largest element in a vector template T findMax(std::vector arr); template std::vector getPrimes(T goalNumber){ std::vector primes; bool foundFactor = false; //If the number is 0 or a negative number return an empty vector if(goalNumber < 1){ return primes; } //If the number is even 2 is a factor if((goalNumber % 2) == 0){ 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 for(uint64_t cnt = 0;(cnt < primes.size()) && ((primes.at(cnt) * primes.at(cnt)) < goalNumber);++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; } template std::vector getDivisors(T num){ std::vector divisors; //Holds the number of divisors //You only need to go to sqrt(number). cnt * cnt is faster than sqrt() for(uint64_t cnt = 1;cnt * cnt <= num;++cnt){ //Check if the counter evenly divides the number //If it does the counter and the other number are both divisors if((num % cnt) == 0){ if(!isFound(cnt, divisors)){ divisors.push_back(cnt); } if(!isFound(num/cnt, divisors)){ divisors.push_back(num / cnt); } } } std::sort(divisors.begin(), divisors.end()); return divisors; } template T getSum(std::vector numbers){ T sum = 0; for(unsigned int cnt = 0;cnt < numbers.size();++cnt){ sum += numbers.at(cnt); } return sum; } template bool isFound(T num, std::vector list){ for(int cnt = 0;cnt < list.size();++cnt){ if(list.at(cnt) == num){ return true; } } return false; } 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; } uint64_t getFib(uint64_t num){ //Make sure the number is within bounds if(num <= 2){ return 1; } //Setup the variables uint64_t fib = 0; uint64_t tempNums[3]; tempNums[0] = tempNums[1] = 1; //Do the calculation for(uint64_t cnt = 2;cnt < num;++cnt){ tempNums[cnt % 3] = tempNums[(cnt + 1) % 3] + tempNums[(cnt + 2) % 3]; } fib = tempNums[(num - 1) % 3]; //Transfer the answer to permanent variable. -1 to account for the offset of starting at 0 return fib; } mpz_class getMpzFib(uint64_t num){ //Make sure the number is within bounds if(num <= 0){ return 0; } else if(num <= 2){ return 1; } mpz_class fibNum = 0; mpz_class tempNums[3]; //Initialize the variables tempNums[0] = 1; tempNums[1] = 1; //Do the calculation for(uint64_t cnt = 2;cnt < num;++cnt){ tempNums[cnt % 3] = tempNums[(cnt + 1) % 3] + tempNums[(cnt + 2) % 3]; } return tempNums[(num - 1) % 3]; //Return the answer } //This is a function that performs a bubble sort on a vector template bool bubbleSort(std::vector nums){ bool notFinished = true; //A flag to determine if the loop is finished for(int numLoops = 0;notFinished;++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 = 0;cnt < ((nums.size() - 1) - numLoops);++cnt){ //use size - 1 to make sure you don't go out of bounds if(nums.at(cnt) > nums.at(cnt + 1)){ std::swap(nums.at(cnt), nums.at(cnt + 1)); notFinished = true; } } } } //This is a function that perfomrs a quick sort on a vector template bool quickSort(std::vector nums){ } //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(std::vector nums, 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 < nums.size()){ if(nums.at(subscript) == num){ return subscript; } } //If you cannot find the element return -1 return -1; } //This function finds the smallest element in a vector template T findMin(std::vector arr){ T min; //For the smallest element //Make sure the vector is not empty if(arr.size() > 0){ //Use the first element as the smallest element min = arr.at(0); //Run through every element in the vector, checking it against the current minimum for(int cnt = 1;cnt < arr.size();++cnt){ //If the current element is smaller than the minimum, make it the new minimum if(arr.at(cnt) < min){ min = arr.at(cnt); } } } //Return the element return min; } //This function finds the largest element in a vector template T findMax(std::vector arr){ T max; //For the largest element //Make sure the vector is not empty if(arr.size() > 0){ //Use the first element as the largest element max = arr.at(0); //Run through every element in the vector, checking it against the current minimum for(int cnt = 1;cnt < arr.size();++cnt){ //If the current element is larger than the maximum, make it the new maximum if(arr.at(cnt) > max){ max = arr.at(cnt); } } } //Return the element return max; } } #endif //MEE_ALGORITHMS_HPP