//myClasses/Algorithms.hpp //Matthew Ellison // Created: 11-8-18 //Modified: 11-8-18 //This file contains the declarations to several algoritms that I have found useful #ifndef MEE_ALGORITHMS_HPP #define MEE_ALGORITHMS_HPP #include #include #include #include #include //This is necessary for the getFib 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 a declaration //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); void getFib(mpz_t fibNum, uint64_t num); 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; } //1 divides everything primes.push_back(1); //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(int 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[2] = 1; //Do the calculation uint64_t cnt = 2; uint64_t location = 1; while(cnt < num){ tempNums[location] = tempNums[(location + 1) % 3] + tempNums[(location + 2) % 3]; location = (location + 1) % 3; ++cnt; } fib = tempNums[(num + 1) % 3]; //Transfer the answer to permanent variable return fib; } void getFib(mpz_t fibNum, uint64_t num){ //Make sure the number is within bounds if(num <= 0){ mpz_set_ui(fibNum, 0); return; } else if(num <= 2){ mpz_set_ui(fibNum, 1); return; } mpz_t tempNums[3]; //Initialize the variables mpz_init(tempNums[0]); mpz_init(tempNums[1]); mpz_init(tempNums[2]); //Set the variables correctly mpz_set_ui(tempNums[0], 1); mpz_set_ui(tempNums[2], 1); //Do the calculation uint64_t cnt = 2; uint64_t location = 1; while(cnt < num){ mpz_add(tempNums[location], tempNums[(location + 1) % 3], tempNums[(location + 2) % 3]); location = (location + 1) % 3; ++cnt; } mpz_set(fibNum, tempNums[(num + 1) % 3]); //Transfer the answer to the permanent variable //Clear the variables mpz_clear(tempNums[0]); mpz_clear(tempNums[1]); mpz_clear(tempNums[2]); } } #endif //MEE_ALGORITHMS_HPP