--ProjectEuler/lua/Problem17.lua --Matthew Ellison -- Created: 02-07-19 --Modified: 03-28-19 --If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used? --All of my requires, unless otherwise listed, can be found at https://bitbucket.org/Mattrixwv/luaClasses --[[ Copyright (C) 2019 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 . ]] require "Stopwatch" timer = Stopwatch:create(); timer:start(); --This function takes a number and returns it as a string in english --This function only works for numbers -1,000,000 < num < 1,000,000 function getStringFromNum(number) local numberString = ""; --Starting with the largest digit create a string based on the number passed in --Check for negative if(number < 0) then numberString = numberString .. "negative "; --Check if the number is zero elseif(number == 0) then numberString = numberString .. "zero"; end --Start with the thousands place if((number / 1000) >= 1) then numberString = numberString .. getStringFromNum(math.floor(number / 1000)); numberString = numberString .. " thousand"; number = number - (math.floor(number / 1000) * 1000); end --Check for hundreds place if((number / 100) >= 1) then numberString = numberString .. getStringFromNum(math.floor(number / 100)); numberString = numberString .. " hundred"; number = number - (math.floor(number / 100) * 100); end --Insert an and if there is need if((numberString ~= "") and (number > 0)) then numberString = numberString .. " and "; end --Check for tens place if((number / 10) >= 2) then --For the tens you need to do something special local tensPlace = math.floor(number / 10); if(tensPlace == 9) then numberString = numberString .. "ninety"; elseif(tensPlace == 8) then numberString = numberString .. "eighty"; elseif(tensPlace == 7) then numberString = numberString .. "seventy"; elseif(tensPlace == 6) then numberString = numberString .. "sixty"; elseif(tensPlace == 5) then numberString = numberString .. "fifty"; elseif(tensPlace == 4) then numberString = numberString .. "forty"; elseif(tensPlace == 3) then numberString = numberString .. "thrity"; elseif(tensPlace == 2) then numberString = numberString .. "twenty"; end number = number - (tensPlace * 10); --If there is something left in the number you will need a space to separate it if(number > 0) then numberString = numberString .. ' '; end --Check for teens elseif((number / 10) >= 1) then local onesPlace = (number % 10); if(onesPlace == 9) then numberString = numberString .. "nineteen"; elseif(onesPlace == 8) then numberString = numberString .. "eighteen"; elseif(onesPlace == 7) then numberString = numberString .. "seventeen"; elseif(onesPlace == 6) then numberString = numberString .. "sixteen"; elseif(onesPlace == 5) then numberString = numberString .. "fifteen"; elseif(onesPlace == 4) then numberString = numberString .. "fourteen"; elseif(onesPlace == 3) then numberString = numberString .. "thirteen"; elseif(onesPlace == 2) then numberString = numberString .. "twelve"; elseif(onesPlace == 1) then numberString = numberString .. "eleven"; elseif(onesPlace == 0) then numberString = numberString .. "ten"; end --If this if was hit number was used up number = 0; end --Check for ones place if(number >= 1) then if(number == 9) then numberString = numberString .. "nine"; elseif(number == 8) then numberString = numberString .. "eight"; elseif(number == 7) then numberString = numberString .. "seven"; elseif(number == 6) then numberString = numberString .. "six"; elseif(number == 5) then numberString = numberString .. "five"; elseif(number == 4) then numberString = numberString .. "four"; elseif(number == 3) then numberString = numberString .. "three"; elseif(number == 2) then numberString = numberString .. "two"; elseif(number == 1) then numberString = numberString .. "one"; end --If this if was hit number was used up number = 0; end --Return the string return numberString; end --This function returns the number of letters in a string, ignoring punctuation, whitespace, and numbers function getNumberChars(number) local sumOfLetters = 0; --Start at location 1 and count the number of letters, ignoring punctuation and whitespace for location=1,string.len(number) do local tempString = string.sub(number, location, location); if(string.match(tempString, "%w")) then sumOfLetters = sumOfLetters + 1; end end --Return the number of letters return sumOfLetters; end timer = Stopwatch:create(); timer:start(); START_NUM = 1; STOP_NUM = 1000; local sumOfLetters = 0; --Start with 1 and increment for num=START_NUM,STOP_NUM do --Pass the number to a function that will create a string for the number local currentNumString = getStringFromNum(num); --Pass the string to a function that will count the number of letters in a string, ignoring whitespace, punctuation, and numbers and add the amount tot he running tally sumOfLetters = sumOfLetters + getNumberChars(currentNumString); end timer:stop(); --Print the results print("The sum of all the letters in all the numbers " .. START_NUM .. '-' .. STOP_NUM .. " is " .. sumOfLetters); print("It took " .. timer:getMilliseconds() .. " milliseconds to run this algorithm"); --[[Results: The sum of all the letters in all the numbers 1-1000 is 21124 It took 4.0 milliseconds to run this algorithm ]]