Added a benchmark tool

This commit is contained in:
2020-07-08 20:38:37 -04:00
parent a7d960c3b1
commit 766af92f1a
68 changed files with 546 additions and 134 deletions

View File

@@ -7,7 +7,6 @@
#ifndef PROBLEM_HPP
#define PROBLEM_HPP
#include <string>
#include "Stopwatch.hpp"
@@ -35,8 +34,15 @@ public:
virtual std::string getTime(){
return timer.getStr();
}
virtual mee::Stopwatch getTimer(){
return timer;
}
virtual void solve() = 0;
virtual std::string getString() const = 0;
virtual void reset(){
timer.reset();
solved = false;
}
};
#endif //PROBLEM_HPP

View File

@@ -40,6 +40,7 @@ public:
Problem1();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the requested sum
uint64_t getSum() const;
};

View File

@@ -38,6 +38,7 @@ public:
Problem10();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the sum that was requested
uint64_t getSum() const;
};

View File

@@ -61,6 +61,7 @@ public:
Problem11();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the numbers that were being searched
std::vector<int> getNumbers() const;
//Returns the product that was requested

View File

@@ -40,6 +40,7 @@ public:
Problem12();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the triangular number
int64_t getTriangularNumber() const;
//Get the final number that was added to the triangular number

View File

@@ -140,13 +140,15 @@
class Problem13 : public Problem{
private:
//A vector to hold all of the numbers
static std::vector<mpz_class> nums;
std::vector<mpz_class> nums;
mpz_class sum;
void setNums();
void reserveVectors();
public:
Problem13();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the list 50-digit numbers
std::vector<mpz_class> getNumbers() const;
//Returns the sum of the 50-digit numbers

View File

@@ -46,6 +46,7 @@ public:
Problem14();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the length of the requested chain
uint64_t getLength() const;
//Returns the starting number of the requested chain

View File

@@ -42,6 +42,7 @@ public:
Problem15();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the number of routes found
uint64_t getNumberOfRoutes() const;
};

View File

@@ -43,6 +43,7 @@ public:
Problem16();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the number that was calculated
mpz_class getNumber() const;
//Return the sum of the digits of the number

View File

@@ -42,6 +42,7 @@ public:
Problem17();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the number of letters asked for
uint64_t getLetterCount() const;
};

View File

@@ -70,6 +70,7 @@ public:
Problem18();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the pyramid that was traversed as a string
std::string getPyramid();
//Returns the trail the algorithm took as a string

View File

@@ -58,6 +58,7 @@ public:
Problem19();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the total sundays that were asked for
uint64_t getTotalSundays() const;
};

View File

@@ -38,6 +38,7 @@ public:
Problem2();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the requested sum
uint64_t getSum() const;
};

View File

@@ -42,6 +42,7 @@ public:
Problem20();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the number 100!
mpz_class getNumber() const;
//Returns the number 100! in a string

View File

@@ -36,10 +36,12 @@ private:
static int LIMIT; //The top number that will be evaluated
std::vector<uint64_t> divisorSum; //Holds the sum of the divisors of the subscript number
std::vector<uint64_t> amicable; //Holds all amicable numbers
void reserveVectors();
public:
Problem21();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns a vector with all of the amicable numbers calculated
std::vector<uint64_t> getAmicable() const;
//Returns the sum of all of the amicable numbers

View File

@@ -36,10 +36,12 @@ private:
std::vector<uint64_t> sums; //Holds the score based on the sum of the characters in the name
std::vector<uint64_t> prod; //Holds the score based on the sum of the characters and the location in alphabetical order
static std::vector<std::string> names; //Holds the names that will be scored
void reserveVectors();
public:
Problem22();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the vector of the names being scored
std::vector<std::string> getNames() const;
//Returns the sum of the names scores

View File

@@ -38,10 +38,12 @@ private:
uint64_t sum; //The sum of all the numbers we are looking for
//A function that returns true if num can be created by adding two elements from abund and false if it cannot
bool isSum(const std::vector<int>& abund, int num);
void reserveVectors();
public:
Problem23();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the sum of the numbers asked for
uint64_t getSum() const;
};

View File

@@ -39,6 +39,7 @@ public:
Problem24();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns a vector with all of the permutations
std::vector<std::string> getPermutationsList() const;
//Returns the specific permutations you are looking for

View File

@@ -42,6 +42,7 @@ public:
Problem25();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
mpz_class getNumber() const; //Returns the Fibonacci number asked for
std::string getNumberString() const; //Returns the Fibonacci number asked for as a string
mpz_class getIndex() const; //Returns the index of the requested Fibonacci number

View File

@@ -39,6 +39,7 @@ public:
Problem26();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
unsigned int getLongestCycle() const; //Returns the length of the longest cycle
unsigned int getLongestNumber() const; //Returns the denominator that starts the longest cycle
};

View File

@@ -41,6 +41,7 @@ public:
Problem27();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
int64_t getTopA() const;
int64_t getTopB() const;
int64_t getTopN() const;

View File

@@ -36,12 +36,14 @@ class Problem28 : public Problem{
private:
std::vector<std::vector<int>> grid; //Holds the grid that we will be filling and searching
uint64_t sumOfDiagonals; //Holds the sum of the diagonals of the grid
void setupGrid(); //Sets up the grid
void setupGrid(); //This sets up the grid to hold the correct number of variables
void createGrid(); //Puts all of the numbers in the grid up the grid
void findSum(); //Finds the sum of the diagonals in the grid
public:
Problem28();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
std::vector<std::vector<int>> getGrid() const; //Returns the grid
uint64_t getSum() const; //Returns the sum of the diagonals
};

View File

@@ -47,6 +47,7 @@ public:
Problem29();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
unsigned int getBottomA() const;
unsigned int getTopA() const;
unsigned int getBottomB() const;

View File

@@ -39,6 +39,7 @@ public:
Problem3();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the list of factors of the number
std::vector<uint64_t> getFactors() const;
//Returns the largest factor of the number

View File

@@ -42,6 +42,7 @@ public:
Problem30();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
uint64_t getTopNum() const; //This returns the top number to be checked
std::vector<uint64_t> getListOfSumOfFifths() const; //This returns a copy of the vector holding all the numbers that are the sum of the fifth power of their digits
uint64_t getSumOfList() const; //This returns the sum of all entries in sumOfFifthNumbers

View File

@@ -38,6 +38,7 @@ public:
Problem31();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the number of correct permutations of the coins
int getPermutations() const;
};

View File

@@ -39,6 +39,7 @@ public:
Problem4();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the list of all palindromes
std::vector<uint64_t> getPalindromes() const;
//Returns the largest palindrome

View File

@@ -38,6 +38,7 @@ public:
Problem5();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the requested number
int getNumber() const;
};

View File

@@ -40,6 +40,7 @@ public:
Problem6();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the sum of all the squares
uint64_t getSumOfSquares() const;
//Returns the square of all of the sums

View File

@@ -143,8 +143,7 @@ private:
bool fromRight;
location(int x, int y, int t, bool r) : xLocation(x), yLocation(y), total(t), fromRight(r){ }
};
//This function takes every number in the vector and changes it to 100 - the number
void invert();
void invert(); //This function takes every number in the vector and changes it to 100 - the number
static const int NUM_ROWS = 100; //The number of rows in the list of numbers
std::list<location> foundPoints; //For the points that I have already found the shortest distance to
std::list<location> possiblePoints; //For the locations you are checking this round
@@ -155,6 +154,7 @@ public:
Problem67();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
std::string getPyramid() const; //Returns the pyramid that was traversed as a string
std::string getTrail(); //Returns the trail the algorithm took as a string
int getTotal() const; //Returns the total that was asked for

View File

@@ -39,6 +39,7 @@ public:
Problem7();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the requested prime number
uint64_t getPrime() const;
};

View File

@@ -62,6 +62,7 @@ public:
Problem8();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the string of numbers that produces the largest product
std::string getLargestNums() const;
//Returns the requested product

View File

@@ -40,6 +40,7 @@ public:
Problem9();
virtual void solve();
virtual std::string getString() const;
virtual void reset();
//Returns the length of the first side
int getSideA() const;
//Returns the length of the second side

95
ProblemSelection.hpp Normal file
View File

@@ -0,0 +1,95 @@
//ProjectEulerCPP/ProblemSelection.hpp
//Mattrixwv
// Created: 07-08-20
//Modified: 07-08-20
//This is a header file with a few functions to help select and run problems
#include <iostream>
#include "Problems.hpp"
#include "Algorithms.hpp"
//Setup the problem numbers
std::vector<unsigned int> PROBLEM_NUMBERS = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 67};
//This function returns a pointer to a problem of type number
Problem* getProblem(unsigned int problemNumber){
Problem* problem = nullptr; //Holds the problem we are about to create
//Decide which problem was asked for and create it
switch(problemNumber){
case 1 : problem = new Problem1; break;
case 2 : problem = new Problem2; break;
case 3 : problem = new Problem3; break;
case 4 : problem = new Problem4; break;
case 5 : problem = new Problem5; break;
case 6 : problem = new Problem6; break;
case 7 : problem = new Problem7; break;
case 8 : problem = new Problem8; break;
case 9 : problem = new Problem9; break;
case 10 : problem = new Problem10; break;
case 11 : problem = new Problem11; break;
case 12 : problem = new Problem12; break;
case 13 : problem = new Problem13; break;
case 14 : problem = new Problem14; break;
case 15 : problem = new Problem15; break;
case 16 : problem = new Problem16; break;
case 17 : problem = new Problem17; break;
case 18 : problem = new Problem18; break;
case 19 : problem = new Problem19; break;
case 20 : problem = new Problem20; break;
case 21 : problem = new Problem21; break;
case 22 : problem = new Problem22; break;
case 23 : problem = new Problem23; break;
case 24 : problem = new Problem24; break;
case 25 : problem = new Problem25; break;
case 26 : problem = new Problem26; break;
case 27 : problem = new Problem27; break;
case 28 : problem = new Problem28; break;
case 29 : problem = new Problem29; break;
case 30 : problem = new Problem30; break;
case 31 : problem = new Problem31; break;
case 67 : problem = new Problem67; break;
}
//Return the newly created problem
return problem;
}
void printDescription(Problem* problem){
std::cout << problem->getDescription() << '\n';
}
void solveProblem(Problem* problem){
//Print the problem description
printDescription(problem);
//Solve the problem
problem->solve();
//Print the results
std::cout << problem->getString()
<< "\nIt took " << problem->getTime() << " to solve this problem.\n\n" << std::endl;
}
unsigned int getProblemNumber(){
unsigned int problemNumber = 0;
std::cout << "Enter a problem number: ";
std::cin >> problemNumber;
while(!mee::isFound(PROBLEM_NUMBERS, problemNumber) || std::cin.fail()){
std::cout << "That is an invalid problem number!\nEnter a problem number: ";
std::cin.clear();
std::cin >> problemNumber;
}
return problemNumber;
}
void listProblems(){
std::cout << PROBLEM_NUMBERS[1];
for(unsigned int problemNumber = 2;problemNumber < PROBLEM_NUMBERS.size();++problemNumber){
std::cout << ", " << PROBLEM_NUMBERS[problemNumber];
}
std::cout << std::endl;
}

View File

@@ -34,7 +34,6 @@
uint64_t Problem1::MAX_NUMBER = 1000;
Problem1::Problem1() : Problem("What is the sum of all the multiples of 3 or 5 that are less than 1000?"), fullSum(0){
}
void Problem1::solve(){
@@ -84,3 +83,9 @@ uint64_t Problem1::getSum() const{
}
return fullSum;
}
void Problem1::reset(){
Problem::reset();
fullSum = 0;
numbers.clear();
}

View File

@@ -34,7 +34,6 @@
uint64_t Problem10::GOAL_NUMBER = 2000000;
Problem10::Problem10() : Problem("Find the sum of all the primes below two million"), sum(0){
}
void Problem10::solve(){
@@ -72,3 +71,8 @@ uint64_t Problem10::getSum() const{
}
return sum;
}
void Problem10::reset(){
Problem::reset();
sum = 0;
}

View File

@@ -75,7 +75,6 @@ std::vector<int> Problem11::grid[20] = {{ 8, 02, 22, 97, 38, 15, 00, 40, 00, 75,
{01, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 01, 89, 19, 67, 48}};
Problem11::Problem11() : Problem("What is the greatest product of four adjacent numbers in the same direction (up, down, left, right, or diagonally) in the 20x20 grid?"){
}
void Problem11::solve(){
@@ -202,3 +201,8 @@ int Problem11::getProduct() const{
}
return mee::getProduct(greatestProduct);
}
void Problem11::reset(){
Problem::reset();
greatestProduct.clear();
}

View File

@@ -33,7 +33,6 @@
uint64_t Problem12::GOAL_DIVISORS = 500;
Problem12::Problem12() : Problem("What is the value of the first triangle number to have over five hundred divisors?"), sum(1), counter(2){
}
void Problem12::solve(){
@@ -109,3 +108,10 @@ size_t Problem12::getNumberOfDivisors() const{
}
return divisors.size();
}
void Problem12::reset(){
Problem::reset();
divisors.clear();
sum = 1;
counter = 2;
}

View File

@@ -138,9 +138,11 @@
#include "../Headers/Problem13.hpp"
std::vector<mpz_class> Problem13::nums;
Problem13::Problem13() : Problem("Work out the first ten digits of the sum of the one-hundred 50-digit numbers"), sum(0){
reserveVectors();
}
void Problem13::reserveVectors(){
//Make sure the vector is the correct size
nums.reserve(100);
nums.resize(100);
@@ -299,3 +301,10 @@ mpz_class Problem13::getSum() const{
}
return sum;
}
void Problem13::reset(){
Problem::reset();
sum = 0;
nums.clear();
reserveVectors();
}

View File

@@ -54,7 +54,6 @@ uint64_t Problem14::checkSeries(uint64_t num){
}
Problem14::Problem14() : Problem("Which starting number, under one million, produces the longest chain using the itterative sequence?"), maxLength(0), maxNum(0){
}
void Problem14::solve(){
@@ -109,3 +108,9 @@ uint64_t Problem14::getStartingNumber() const{
}
return maxNum;
}
void Problem14::reset(){
Problem::reset();
maxLength = 0;
maxNum = 0;
}

View File

@@ -52,7 +52,6 @@ void Problem15::move(int currentX, int currentY, uint64_t& numOfRoutes){
}
Problem15::Problem15() : Problem("How many routes from the top left corner to the bottom right corner are there through a 20×20 grid if you can only move right and down?"), numOfRoutes(0){
}
void Problem15::solve(){
@@ -97,3 +96,8 @@ uint64_t Problem15::getNumberOfRoutes() const{
}
return numOfRoutes;
}
void Problem15::reset(){
Problem::reset();
numOfRoutes = 0;
}

View File

@@ -36,7 +36,6 @@ int Problem16::NUM_TO_POWER = 2; //The number that is going to be raised to a po
int Problem16::POWER = 1000; //The power that the number is going to be raised to
Problem16::Problem16() : Problem("What is the sum of the digits of the number 2^1000?"), num(0), sumOfElements(0){
}
void Problem16::solve(){
@@ -95,3 +94,9 @@ int Problem16::getSum() const{
}
return sumOfElements;
}
void Problem16::reset(){
Problem::reset();
num = 0;
sumOfElements = 0;
}

View File

@@ -33,7 +33,6 @@
int Problem17::TOP_NUM = 1000;
Problem17::Problem17() : Problem("If all the numbers from 1 to 1000 inclusive were written out in words, how many letters would be used?"), letterCount(0){
}
std::string Problem17::makeWord(int num){
@@ -210,3 +209,8 @@ uint64_t Problem17::getLetterCount() const{
}
return letterCount;
}
void Problem17::reset(){
Problem::reset();
letterCount = 0;
}

View File

@@ -66,14 +66,6 @@ std::vector<int> Problem18::list[NUM_ROWS] =
{04, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 04, 23}};
Problem18::Problem18() : Problem("Find the maximum total from the top to the bottom of the pyramid."), actualTotal(0){
//The method that I am using looks for the smallest numbers, so I need to invert the numbers in this list
invert();
//Now l[i][j] == 100 - l[i][j];
//Add the top point because that is already the only path
foundPoints.emplace_back(0, 0, list[0][0], false);
//Add the second row as possible points
possiblePoints.emplace_back(0, 1, (list[0][0] + list[1][0]), true);
possiblePoints.emplace_back(1, 1, (list[0][0] + list[1][1]), false);
}
void Problem18::invert(){
@@ -93,6 +85,15 @@ void Problem18::solve(){
//Start the timer
timer.start();
//The method that I am using looks for the smallest numbers, so I need to invert the numbers in this list
invert();
//Now l[i][j] == 100 - l[i][j];
//Add the top point because that is already the only path
foundPoints.emplace_back(0, 0, list[0][0], false);
//Add the second row as possible points
possiblePoints.emplace_back(0, 1, (list[0][0] + list[1][0]), true);
possiblePoints.emplace_back(1, 1, (list[0][0] + list[1][1]), false);
bool foundBottom = false; //Used when you find a point at the bottom
//Loop until you find the bottom
@@ -224,3 +225,10 @@ int Problem18::getTotal() const{
}
return actualTotal;
}
void Problem18::reset(){
Problem::reset();
foundPoints.clear();
possiblePoints.clear();
actualTotal = 0;
}

View File

@@ -44,7 +44,6 @@ unsigned int Problem19::START_YEAR = 1901; //The start year
unsigned int Problem19::END_YEAR = 2000; //The stop year
Problem19::Problem19() : Problem("How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?"), totalSundays(0){
}
Problem19::DAYS Problem19::getDay(unsigned int month, unsigned int day, unsigned int year){
@@ -189,3 +188,8 @@ uint64_t Problem19::getTotalSundays() const{
}
return totalSundays;
}
void Problem19::reset(){
Problem::reset();
totalSundays = 0;
}

View File

@@ -34,7 +34,6 @@
uint64_t Problem2::TOP_NUM = 4000000;
Problem2::Problem2() : Problem("What is the sum of the even Fibonacci numbers less than 4,000,000?"), fullSum(0){
}
void Problem2::solve(){
@@ -80,3 +79,8 @@ uint64_t Problem2::getSum() const{
}
return fullSum;
}
void Problem2::reset(){
Problem::reset();
fullSum = 0;
}

View File

@@ -101,3 +101,9 @@ uint64_t Problem20::getSum() const{
}
return sum;
}
void Problem20::reset(){
Problem::reset();
sum = 0;
num = 1;
}

View File

@@ -34,6 +34,10 @@
int Problem21::LIMIT = 10000; //The top number that will be evaluated
Problem21::Problem21() : Problem("Evaluate the sum of all the amicable numbers under 10000"){
reserveVectors();
}
void Problem21::reserveVectors(){
divisorSum.reserve(LIMIT); //Reserving it now makes it faster later
divisorSum.resize(LIMIT); //Make sure there are enough spaces
}
@@ -113,3 +117,10 @@ uint64_t Problem21::getSum() const{
}
return mee::getSum(amicable);
}
void Problem21::reset(){
Problem::reset();
divisorSum.clear();
amicable.clear();
reserveVectors();
}

View File

@@ -402,6 +402,10 @@ std::vector<std::string> Problem22::names = { "MARY","PATRICIA","LINDA","BARBARA
"HAI","ELDEN","DORSEY","DARELL","BRODERICK","ALONSO"};
Problem22::Problem22() : Problem("What is the total of all the name scores in the file?"){
reserveVectors();
}
void Problem22::reserveVectors(){
//Make sure the vector is the right size
sums.reserve(names.size());
sums.resize(names.size());
@@ -468,3 +472,10 @@ uint64_t Problem22::getNameScoreSum() const{
}
return mee::getSum(prod);
}
void Problem22::reset(){
Problem::reset();
sums.clear();
prod.clear();
reserveVectors();
}

View File

@@ -35,6 +35,10 @@
int Problem23::MAX_NUM = 28123;
Problem23::Problem23() : Problem("Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers"), sum(0){
reserveVectors();
}
void Problem23::reserveVectors(){
//This makes sure the vector is the correct size
divisorSums.reserve(MAX_NUM);
divisorSums.resize(MAX_NUM);
@@ -116,3 +120,10 @@ uint64_t Problem23::getSum() const{
}
return sum;
}
void Problem23::reset(){
Problem::reset();
sum = 0;
divisorSums.clear();
reserveVectors();
}

View File

@@ -84,3 +84,8 @@ std::string Problem24::getPermutation() const{
}
return permutations.at(NEEDED_PERM - 1);
}
void Problem24::reset(){
Problem::reset();
permutations.clear();
}

View File

@@ -36,7 +36,8 @@
unsigned int Problem25::NUM_DIGITS = 1000; //The number of digits to calculate up to
Problem25::Problem25() : Problem("What is the index of the first term in the Fibonacci sequence to contain 1000 digits?"), number(0), index(2){
number = 0;
index = 0;
}
void Problem25::solve(){
@@ -117,3 +118,9 @@ uint64_t Problem25::getIndexInt() const{
}
return index.get_ui();
}
void Problem25::reset(){
Problem::reset();
number = 0;
index = 2;
}

View File

@@ -32,7 +32,8 @@
unsigned int Problem26::TOP_NUMBER = 999;
Problem26::Problem26() : Problem("Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part."), longestCycle(0), longestNumber(1){
longestCycle = 0;
longestNumber = 0;
}
void Problem26::solve(){
@@ -117,3 +118,9 @@ unsigned int Problem26::getLongestNumber() const{
}
return longestNumber;
}
void Problem26::reset(){
Problem::reset();
longestCycle = 0;
longestNumber = 1;
}

View File

@@ -30,7 +30,6 @@
Problem27::Problem27() : Problem("Considering quadratics of the form n^2 + an + b, where |a| < 1000 and |b| <= 1000, find the product of the coefficients a and b that produce the maximum number of primes for consecutive values of n starting with n = 0."){
topA = topB = topN = 0;
primes = mee::getPrimes((int64_t)(12000));
}
void Problem27::solve(){
@@ -42,6 +41,8 @@ void Problem27::solve(){
//Start the timer
timer.start();
primes = mee::getPrimes((int64_t)(12000));
//Start with the lowest possible A and check all possibilities after that
for(int64_t a = -999;a <= 999;++a){
//Start with the lowest possible B and check all possibilities after that
@@ -108,3 +109,9 @@ int64_t Problem27::getTopN() const{
}
return topN;
}
void Problem27::reset(){
Problem::reset();
topA = topB = topN = 0;
primes.clear();
}

View File

@@ -30,6 +30,10 @@
Problem28::Problem28() : Problem("What is the sum of the number on the diagonals in a 1001 x 1001 spiral formed by starting with the number 1 and moving to the right in a clockwise direction?"){
setupGrid();
sumOfDiagonals = 0;
}
void Problem28::setupGrid(){
//Set the size of the grid to 1001 x 1001
for(int cnt = 0;cnt < 1001;++cnt){
grid.emplace_back();
@@ -37,11 +41,10 @@ Problem28::Problem28() : Problem("What is the sum of the number on the diagonals
grid.at(cnt).push_back(0);
}
}
sumOfDiagonals = 0;
}
//Sets up the grid
void Problem28::setupGrid(){
void Problem28::createGrid(){
bool finalLocation = false; //A flag to indicate if the final location to be filled has been reached
//Set the number that is going to be put at each location
int currentNum = 1;
@@ -117,7 +120,7 @@ void Problem28::solve(){
//Setup the grid
setupGrid();
createGrid();
//Find the sum of the diagonals in the grid
findSum();
@@ -158,3 +161,10 @@ uint64_t Problem28::getSum() const{
}
return sumOfDiagonals;
}
void Problem28::reset(){
Problem::reset();
sumOfDiagonals = 0;
grid.clear();
setupGrid();
}

View File

@@ -35,7 +35,6 @@
Problem29::Problem29() : Problem("How many distict terms are in the sequence generated by a^b for 2 <= a <= 100 and 2 <= b <= 100?"){
}
void Problem29::solve(){
@@ -118,3 +117,8 @@ std::vector<mpz_class> Problem29::getUnique() const{
}
return unique;
}
void Problem29::reset(){
Problem::reset();
unique.clear();
}

View File

@@ -34,8 +34,7 @@
uint64_t Problem3::GOAL_NUMBER = 600851475143;
Problem3::Problem3() : Problem("What is the largest prime factor of 600851475143?"){
Problem3::Problem3() : Problem("What is the largest prime factor of 600851475143?"){
}
void Problem3::solve(){
@@ -90,3 +89,8 @@ uint64_t Problem3::getGoalNumber() const{
}
return GOAL_NUMBER;
}
void Problem3::reset(){
Problem::reset();
factors.clear();
}

View File

@@ -31,7 +31,6 @@
Problem30::Problem30() : Problem("Find the sum of all the numbers that can be written as a sum of the fifth powers of their digits"){
}
//Returns a vector with the indivitual digits of the number passed into it
@@ -125,3 +124,8 @@ uint64_t Problem30::getSumOfList() const{
return sum;
}
void Problem30::reset(){
Problem::reset();
sumOfFifthNumbers.clear();
}

View File

@@ -84,3 +84,8 @@ std::string Problem31::getString() const{
int Problem31::getPermutations() const{
return permutations;
}
void Problem31::reset(){
Problem::reset();
permutations = 0;
}

View File

@@ -35,7 +35,6 @@ int Problem4::START_NUM = 100;
int Problem4::END_NUM = 999;
Problem4::Problem4() : Problem("Find the largest palindrome made from the product of two 3-digit numbers."){
}
void Problem4::solve(){
@@ -102,3 +101,8 @@ uint64_t Problem4::getLargestPalindrome() const{
}
return *(palindromes.end() - 1);
}
void Problem4::reset(){
Problem::reset();
palindromes.clear();
}

View File

@@ -32,7 +32,6 @@
Problem5::Problem5() : Problem("What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"), smallestNum(0){
}
void Problem5::solve(){
@@ -92,3 +91,8 @@ int Problem5::getNumber() const{
}
return smallestNum;
}
void Problem5::reset(){
Problem::reset();
smallestNum = 0;
}

View File

@@ -35,7 +35,6 @@ int Problem6::START_NUM = 1;
int Problem6::END_NUM = 100;
Problem6::Problem6() : Problem("Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum."), sumOfSquares(0), squareOfSum(0){
}
void Problem6::solve(){
@@ -94,3 +93,8 @@ uint64_t Problem6::getDifference() const{
}
return abs(sumOfSquares - squareOfSum);
}
void Problem6::reset(){
Problem::reset();
sumOfSquares = squareOfSum = 0;
}

View File

@@ -237,15 +237,6 @@ std::vector<int> Problem67::list[NUM_ROWS] = {
};
Problem67::Problem67() : Problem("Find the maximum total from the top to the bottom of the pyramid."){
//The method that I am using looks for the smallest numbers, so I need to invert the numbers in this list
invert();
//Now l[i][j] == 100 - l[i][j];
//Add the top point because that is already the only path
foundPoints.emplace_back(0, 0, list[0][0], false);
//Add the second row as possible points
possiblePoints.emplace_back(0, 1, (list[0][0] + list[1][0]), true);
possiblePoints.emplace_back(1, 1, list[0][0] + list[1][1], false);
}
void Problem67::invert(){
@@ -265,6 +256,16 @@ void Problem67::solve(){
//Start the timer
timer.start();
//The method that I am using looks for the smallest numbers, so I need to invert the numbers in this list
invert();
//Now l[i][j] == 100 - l[i][j];
//Add the top point because that is already the only path
foundPoints.emplace_back(0, 0, list[0][0], false);
//Add the second row as possible points
possiblePoints.emplace_back(0, 1, (list[0][0] + list[1][0]), true);
possiblePoints.emplace_back(1, 1, list[0][0] + list[1][1], false);
bool foundBottom = false; //Used when you find a point at the bottom
//Loop until you find the bottom
@@ -402,4 +403,12 @@ int Problem67::getTotal() const{
throw unsolved();
}
return actualTotal;
}
}
//Clears all of the variables so the problem can be run again
void Problem67::reset(){
Problem::reset();
foundPoints.clear();
possiblePoints.clear();
actualTotal = 0;
}

View File

@@ -35,7 +35,6 @@
uint64_t Problem7::NUMBER_OF_PRIMES = 10001;
Problem7::Problem7() : Problem("What is the 10001th prime number?"){
}
void Problem7::solve(){
@@ -73,3 +72,7 @@ uint64_t Problem7::getPrime() const{
}
return *primes.end();
}
void Problem7::reset(){
Problem::reset();
}

View File

@@ -56,7 +56,6 @@
std::string Problem8::number = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
Problem8::Problem8() : Problem("Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?"), maxProduct(0){
}
void Problem8::solve(){
@@ -112,3 +111,9 @@ uint64_t Problem8::getLargestProduct() const{
}
return maxProduct;
}
void Problem8::reset(){
Problem::reset();
maxNums = "";
maxProduct = 0;
}

View File

@@ -31,7 +31,6 @@
Problem9::Problem9() : Problem("There exists exactly one Pythagorean triplet for which a + b + c = 1000. Find the product of abc."), a(1), b(0), c(0), found(false){
}
void Problem9::solve(){
@@ -117,3 +116,11 @@ int Problem9::getProduct() const{
}
return a * b * (int)c;
}
void Problem9::reset(){
Problem::reset();
a = 1;
b = 0;
c = 0;
found = false;
}

167
benchmark.cpp Normal file
View File

@@ -0,0 +1,167 @@
//ProjectEulerCPP/benchmark.cpp
//Mattrixwv
// Created: 07-08-20
//Modified: 07-08-20
//This is a program that runs a problem several times to get the average time it takes to run
#include <iostream>
#include <vector>
#include "ProblemSelection.hpp"
void printMenu(); //Prints the menu to the screen
int getMenuSelection(); //Returns a valid menu option
bool isValidMenu(int selection); //Determines if a value is a valid menu option. Helper for getMenuSelection
void runSpecific(); //Determines which problem user wants to run and runs it
void runAllShort(); //Runs all problems except a few that are specified because of run length
void runAll(); //Runs all problems
unsigned int getNumberOfTimesToRun(); //Asks how many times a problem is supposed to run and returns the value
enum MENU_OPTIONS {RUN_SPECIFIC = 1, RUN_ALL_SHORT, RUN_ALL, EXIT, SIZE};
std::vector<unsigned int> tooLong = {15};
int main(){
int selection = 0;
do{
printMenu();
selection = getMenuSelection();
switch(selection){
case RUN_SPECIFIC: runSpecific(); break;
case RUN_ALL_SHORT: runAllShort(); break;
case RUN_ALL: runAll(); break;
case EXIT: break;
}
}while(selection != EXIT);
return 0;
}
void printMenu(){
std::cout << "1. Run a specific problem\n"
<< "2. Run all problems that have a reasonably short run time\n"
<< "3. Run all problems\n"
<< "4. Exit the program" << std::endl;
}
int getMenuSelection(){
int selection = 0;
std::cin >> selection;
while(std::cin.fail() || !isValidMenu(selection)){
std::cout << "That is an invalid option!\nPress Enter to continue" << std::endl;
std::cin.clear();
std::cin.get();
printMenu();
std::cin >> selection;
}
return selection;
}
bool isValidMenu(int selection){
if((selection > 0) && (selection < MENU_OPTIONS::SIZE)){
return true;
}
else{
return false;
}
}
void runSpecific(){
double totalTime = 0;
//Ask which problem the user wants to run
unsigned int problemNumber = getProblemNumber();
//Ask how many times to run the problem
unsigned int timesToRun = getNumberOfTimesToRun();
//Get the problem
Problem* problem = getProblem(problemNumber);
//Run the problem the specific number of times
std::cout << "Solving";
for(unsigned int cnt = 0;cnt < timesToRun;++cnt){
//Reset the data so you are actually counting the run time a second time
problem->reset();
std::cout << '.';
//Solve the problem
problem->solve();
//Get the time data
totalTime += problem->getTimer().getNano();
}
//Calculate the average run time
totalTime /= timesToRun;
std::string timeResults = mee::Stopwatch::getStr(totalTime);
//Print the results
std::cout << "\n\n" << problem->getString();
std::cout << "\nIt took an average of " << timeResults << " to run this problem over " << timesToRun << " iterations\n\n" << std::endl;
}
void runAllShort(){
//Ask how many times to run the problem
unsigned int timesToRun = getNumberOfTimesToRun();
//Run through all valid problem numbers, skipping a few that are in the tooLong vector
for(unsigned int cnt = 1;cnt < PROBLEM_NUMBERS.size();++cnt){
unsigned int problemNumber = PROBLEM_NUMBERS[cnt];
double totalTime = 0;
//If the problem number is contained the list of problems that take too long skip it
if(mee::isFound(tooLong, problemNumber)){
continue;
}
//Get the problem
Problem* problem = getProblem(problemNumber);
//Run each problem the specified number of times
std::cout << "Solving";
for(unsigned int cnt = 0;cnt < timesToRun;++cnt){
//Reset the data so you are actually counting the run time a second time
problem->reset();
std::cout << '.';
//Solve the problem
problem->solve();
//Get the time data
totalTime += (problem->getTimer()).getNano();
}
//Calculate the average run time of the problem
totalTime /= timesToRun;
std::string timeResults = mee::Stopwatch::getStr(totalTime);
//Print the results
std::cout << "\n\n" << problem->getString();
std::cout << "\nIt took an average of " << timeResults << " to run this problem over " << timesToRun << " iterations\n\n" << std::endl;
}
}
void runAll(){
//Ask how many times to run the problem
unsigned int timesToRun = getNumberOfTimesToRun();
//Run through all valid problem numbers, skipping a few that are in the tooLong vector
for(unsigned int cnt = 1;cnt < PROBLEM_NUMBERS.size();++cnt){
unsigned int problemNumber = PROBLEM_NUMBERS[cnt];
double totalTime = 0;
//Get the problem
Problem* problem = getProblem(problemNumber);
//Run each problem the specified number of times
std::cout << "Solving";
for(unsigned int cnt = 0;cnt < timesToRun;++cnt){
//Reset the data so you are actually counting the run time a second time
problem->reset();
std::cout << '.';
//Solve the problem
problem->solve();
//Get the time data
totalTime += (problem->getTimer()).getNano();
}
//Calculate the average run time of the problem
totalTime /= timesToRun;
std::string timeResults = mee::Stopwatch::getStr(totalTime);
//Print the results
std::cout << "\n\n" << problem->getString();
std::cout << "\nIt took an average of " << timeResults << " to run this problem over " << timesToRun << " iterations\n\n" << std::endl;
}
}
unsigned int getNumberOfTimesToRun(){
unsigned int numOfTimesToRun = 1;
std::cout << "How many times do you want to run this problem? ";
std::cin >> numOfTimesToRun;
while((std::cin.fail()) || (numOfTimesToRun < 1)){
std::cout << "That is an invalid number!\nHow many times do you want to run this problem? ";
std::cin.clear();
std::cin >> numOfTimesToRun;
}
return numOfTimesToRun;
}

View File

@@ -11,6 +11,7 @@
#include "Algorithms.hpp"
#include "Headers/Problem.hpp"
#include "Problems.hpp"
#include "ProblemSelection.hpp"
//Some helper functions to help with the menus
@@ -27,11 +28,6 @@ void listProblems(); //Lists the problem numbers that you can choose
//Setup the menu options
enum MenuOptions {SOLVE = 1, DESCRIPTION, LIST, EXIT, SIZE};
//Setup the problem numbers
std::vector<unsigned int> PROBLEM_NUMBERS = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 67};
int main(){
int selection = 0; //Holds the menu selection of the user
@@ -111,60 +107,6 @@ void solveMenu(){
}
}
//This function returns a pointer to a problem of type number
Problem* getProblem(unsigned int problemNumber){
Problem* problem = nullptr; //Holds the problem we are about to create
//Decide which problem was asked for and create it
switch(problemNumber){
case 1 : problem = new Problem1; break;
case 2 : problem = new Problem2; break;
case 3 : problem = new Problem3; break;
case 4 : problem = new Problem4; break;
case 5 : problem = new Problem5; break;
case 6 : problem = new Problem6; break;
case 7 : problem = new Problem7; break;
case 8 : problem = new Problem8; break;
case 9 : problem = new Problem9; break;
case 10 : problem = new Problem10; break;
case 11 : problem = new Problem11; break;
case 12 : problem = new Problem12; break;
case 13 : problem = new Problem13; break;
case 14 : problem = new Problem14; break;
case 15 : problem = new Problem15; break;
case 16 : problem = new Problem16; break;
case 17 : problem = new Problem17; break;
case 18 : problem = new Problem18; break;
case 19 : problem = new Problem19; break;
case 20 : problem = new Problem20; break;
case 21 : problem = new Problem21; break;
case 22 : problem = new Problem22; break;
case 23 : problem = new Problem23; break;
case 24 : problem = new Problem24; break;
case 25 : problem = new Problem25; break;
case 26 : problem = new Problem26; break;
case 27 : problem = new Problem27; break;
case 28 : problem = new Problem28; break;
case 29 : problem = new Problem29; break;
case 30 : problem = new Problem30; break;
case 31 : problem = new Problem31; break;
case 67 : problem = new Problem67; break;
}
//Return the newly created problem
return problem;
}
void solveProblem(Problem* problem){
//Print the problem description
printDescription(problem);
//Solve the problem
problem->solve();
//Print the results
std::cout << problem->getString()
<< "\nIt took " << problem->getTime() << " to solve this problem.\n\n" << std::endl;
}
void descriptionMenu(){
Problem* problem = nullptr; //Holds the problem that will be generated
std::cout << "\n\n"; //Give some extra space to print the description
@@ -200,27 +142,3 @@ void descriptionMenu(){
problem = nullptr;
}
}
void printDescription(Problem* problem){
std::cout << problem->getDescription() << '\n';
}
unsigned int getProblemNumber(){
unsigned int problemNumber = 0;
std::cout << "Enter a problem number: ";
std::cin >> problemNumber;
while(!mee::isFound(PROBLEM_NUMBERS, problemNumber) || std::cin.fail()){
std::cout << "That is an invalid problem number!\nEnter a problem number: ";
std::cin.clear();
std::cin >> problemNumber;
}
return problemNumber;
}
void listProblems(){
std::cout << PROBLEM_NUMBERS[1];
for(unsigned int problemNumber = 2;problemNumber < PROBLEM_NUMBERS.size();++problemNumber){
std::cout << ", " << PROBLEM_NUMBERS[problemNumber];
}
std::cout << std::endl;
}