//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);
void getFib(mpz_t fibNum, 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