//ProjectEuler/ProjectEulerCPP/Source/Problem17.cpp //Matthew Ellison // Created: 10-05-18 //Modified: 07-09-20 //If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used? //Unless otherwise listed all non-standard includes are my own creation and available from https://bibucket.org/Mattrixwv/myClasses /* Copyright (C) 2020 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 "Stopwatch.hpp" #include "../Headers/Problem.hpp" #include "../Headers/Problem17.hpp" //This is the largest number to get the words of int Problem17::START_NUM = 1; int Problem17::STOP_NUM = 1000; //This function makes a word out of the number passed into it std::string Problem17::makeWord(int num){ int currentDivider = 1000; int currentNum; bool teen = false; std::string word = ""; std::string currentWord = ""; //Start at thousands currentNum = num / currentDivider; if(currentNum > 0 && num != 0){ num -= currentNum * currentDivider; currentWord = wordHelper(currentNum); word += currentWord + " thousand "; currentWord = ""; } //Check for hundreds currentDivider /= 10; currentNum = num / currentDivider; if(currentNum > 0 && num != 0){ num -= currentNum * currentDivider; currentWord = wordHelper(currentNum); word += currentWord + " hundred "; currentWord = ""; } //Insert an and if there is a reason if(word != "" && num > 0){ word += " and "; } //Check for double digits currentDivider /= 10; currentNum = num / currentDivider; if(currentNum > 0 && num != 0){ num -= currentNum * currentDivider; currentWord = wordHelper(currentNum); } if(currentWord != ""){ //For specialty numbers if(currentNum == 8){ word += "eighty "; } else if(currentNum == 5){ word += "fifty "; } else if(currentNum == 4){ word += "forty "; } else if(currentNum == 3){ word += "thirty "; } else if(currentNum == 2){ word += "twenty "; } //For teens else if(currentNum == 1){ if(num == 8){ word += "eighteen"; num = 0; } else if(num == 5){ word += "fifteen"; num = 0; } else if(num == 3){ word += "thirteen"; num = 0; } else if(num == 2){ word += "twelve"; num = 0; } else if(num == 1){ word += "eleven"; num = 0; } else if(num == 0){ word += "ten"; num = 0; } else{ teen = true; } } //For all other numbers > 30 else{ word += currentWord + "ty "; } currentWord = ""; } //Check for single digits currentDivider /= 10; currentNum = num / currentDivider; if(currentNum > 0 && num != 0){ num -= currentNum * currentDivider; currentWord = wordHelper(currentNum); word += currentWord; if(teen){ word += "teen"; } } return word; } //This function helps makeWord() by returning the words for the numbers 1-9 std::string Problem17::wordHelper(int num){ std::string tempString; switch(num){ case 9: tempString += "nine"; break; case 8: tempString += "eight"; break; case 7: tempString += "seven"; break; case 6: tempString += "six"; break; case 5: tempString += "five"; break; case 4: tempString += "four"; break; case 3: tempString += "three"; break; case 2: tempString += "two"; break; case 1: tempString += "one"; break; default: tempString += "ERROR"; break; } return tempString; } //This counts the number of letters in the string that is passed in (ignoring numbers and punctuation) uint64_t Problem17::countLetters(std::string str){ uint64_t letterCount = 0; //Step through every character in the string and count how many letters there are for(unsigned int cnt = 0;cnt < str.size();++cnt){ if(isalpha(str.at(cnt))){ ++letterCount; } } return letterCount; } //Constructor 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){ } //Solve the problem void Problem17::solve(){ //If the problem has already been solved do nothing and end the function if(solved){ return; } //Start the timer timer.start(); //Step through every element in nums and get the word representations of the numbers for(int cnt = START_NUM;cnt <= STOP_NUM;++cnt){ std::string words = makeWord(cnt); //Get the words of each number in turn letterCount += countLetters(words); //Add the number of letters to the running tally } //Stop the timer timer.stop(); //Throw a flag to show the problem is solved solved = true; } //Reset the problem so it can be run again void Problem17::reset(){ Problem::reset(); letterCount = 0; } //Return a string with the solution to the problem std::string Problem17::getString() const{ //If the problem hasn't been solved throw an exception if(!solved){ throw Unsolved(); } std::stringstream results; results << "The number of letters is " << letterCount; return results.str(); } //Returns the number of letters asked for uint64_t Problem17::getLetterCount() const{ //If the problem hasn't been solved throw an exception if(!solved){ throw Unsolved(); } return letterCount; }