Files
ProjectEulerLua/Problem17.lua

187 lines
6.0 KiB
Lua

--ProjectEuler/lua/Problem17.lua
--Matthew Ellison
-- Created: 02-07-19
--Modified: 06-19-20
--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) 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 <https://www.gnu.org/licenses/>.
]]
require "Stopwatch"
local 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
local 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
local 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
]]