//ProjectEulerTS/Problems/Problem17.ts //Matthew Ellison // Created: 03-29-21 //Modified: 03-29-21 //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/typescriptClasses /* Copyright (C) 2021 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 . */ import { Unsolved } from "../Unsolved"; import { Problem } from "./Problem"; export class Problem17 extends Problem{ //Variables //Static variables private static START_NUM: number = 1; //This is the smallest number to get the words of private static STOP_NUM: number = 1000; //This is the largest number to get the words of //Instance variables private letterCount: number; //This is the cumulative number of letters in the words of the numbers //Functions //Constructor public constructor(){ super(`If all of teh numbers from ${Problem17.START_NUM} to ${Problem17.STOP_NUM} inclusive were written out in words, how many letters would be used?`); this.letterCount = 0; } //Operational functions //Solve the problem public solve(): void{ //If the problem has already been solved do nothing and end the function if(this.solved){ return; } //Start the timer this.timer.start(); //Start with 1 and increment for(let num: number = Problem17.START_NUM;num <= Problem17.STOP_NUM;++num){ //Pass the number to a function that will create a string for the number let currentNumString: string = this.makeWordFromNum(num); //Pass the string to the function that will count the number of letters in it, ignoring whitespace and punctuation and add that number to the running tally this.letterCount += this.getNumberChars(currentNumString); } //Stop the timer this.timer.stop(); //Throw a flag to show the problem is solved this.solved = true; } //Reset the problem so it can be run again public reset(): void{ super.reset(); this.letterCount = 0; } //This function makes a word out of the number passed into it private makeWordFromNum(orgNum: number): string{ let num: number = orgNum; let numberString: string = ""; //Starting with the largest digit create a string based on the number passed in //Check for negative if(num < 0){ numberString += "negative "; } //Check if the number is zero if(num == 0){ numberString += "zero"; } //Start with the thousands place if((num / 1000) >= 1){ numberString += this.makeWordFromNum(Math.floor(num / 1000)); numberString += " thousand"; num -= (Math.floor(num / 1000) * 1000); } //Check the hundreds place if((num / 100) >= 1){ numberString += this.makeWordFromNum(Math.floor(num / 100)); numberString += " hundred"; num -= (Math.floor(num / 100) * 100); } //Insert an and if there is need if((numberString.trim().length > 0) && (num > 0)){ numberString += " and "; } //Check for tens place if((num / 10) >= 2){ //For the tens you need to do something special let tensPlace: number = Math.floor(num / 10); switch(tensPlace){ case 9: numberString += "ninety"; break; case 8: numberString += "eighty"; break; case 7: numberString += "seventy"; break; case 6: numberString += "sixty"; break; case 5: numberString += "fifty"; break; case 4: numberString += "forty"; break; case 3: numberString += "thirty"; break; case 2: numberString += "twenty"; break; } num -= (tensPlace * 10); //If there is something left in the number you will need a dash to separate the tens and ones place if(num > 0){ numberString += "-"; } } //Check for teens else if((num / 10) >= 1){ let onesPlace: number = (num % 10); switch(onesPlace){ case 9: numberString += "nineteen"; break; case 8: numberString += "eighteen"; break; case 7: numberString += "seventeen"; break; case 6: numberString += "sixteen"; break; case 5: numberString += "fifteen"; break; case 4: numberString += "fourteen"; break; case 3: numberString += "thirteen"; break; case 2: numberString += "twelve"; break; case 1: numberString += "eleven"; break; case 0: numberString += "ten"; break; } //If this was hit the number was completed num = 0; } //Check for the ones place if(num >= 1){ switch(num){ case 9: numberString += "nine"; break; case 8: numberString += "eight"; break; case 7: numberString += "seven"; break; case 6: numberString += "six"; break; case 5: numberString += "five"; break; case 4: numberString += "four"; break; case 3: numberString += "three"; break; case 2: numberString += "two"; break; case 1: numberString += "one"; break; } //If this was hit the number was completed num = 0; } //If the number is not 0 there was a problem if(num != 0){ throw new Unsolved("The number " + orgNum + " was not completely reduced!\nRemainder is " + num); } //Return the string return numberString; } //This counts the number of letters in the string that is passed in (ignoring numbers and puctuation) private getNumberChars(num: string): number{ let sumOfLetters: number = 0; //Start at location 0 and count the number of letters, ignoring punctuation and whitespace for(let location: number = 0;location < num.length;++location){ let char = num.charAt(location).toLowerCase(); if((char >= "a") && (char <= "z")){ sumOfLetters += 1; } } //Returns the number of letters return sumOfLetters; } //Gets //Returns the result of solving the problem public getResult(): string{ if(!this.solved){ throw new Unsolved(); } return `The sum of all the letters in all the numbers ${Problem17.START_NUM}-${Problem17.STOP_NUM} is ${this.letterCount}`; } //Returns the number of letters asked for public getLetterCount(): number{ if(!this.solved){ throw new Unsolved(); } return this.letterCount; } } /* Results: The sum of all the letters in all the numbers 1-1000 is 21124 It took an average of 485.744 microseconds to run this problem through 100 iterations */