--ProjectEuler/lua/Problem19.lua --Matthew Ellison -- Created: 03-13-19 --Modified: 06-19-20 --How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)? --[[ You are given the following information, but you may prefer to do some research for yourself. 1 Jan 1900 was a Monday. Thirty days has September, April, June and November. All the rest have thirty-one, Saving February alone, Which has twenty-eight, rain or shine. And on leap years, twenty-nine. A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400. ]] --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 . ]] require "Stopwatch" DAYS = { SUNDAY = 0, MONDAY = 1, TUESDAY = 2, WEDNESDAY = 3, THURSDAY = 4, FRIDAY = 5, SATURDAY = 6, NUMBER_OF_DAYS = 7, ERROR = 8; } local START_YEAR = 1901; local END_YEAR = 2000; local function isLeapYear(year) local answer; if(year < 1) then answer = false; elseif((year % 100) == 0) then --This rule only applies at and after 1800 if(year <= 1700) then answer = true; elseif((year % 400) == 0) then answer = true; else answer = false; end elseif((year % 4) == 0) then answer = true; else answer = false; end return answer; end --Return the day of the week that the date you pass into it is on local function getDay(month, day, year) --Make sure the numbers are within propper bounds if((month < 1) or (month > 12) or (day < 1) or (day > 31) or (year < 1)) then return DAYS.ERROR; end local numDays = 0; local currentYear = 1; local currentMonth = 1; local currentDay = DAYS.SATURDAY; day = day - 1; --Add the correct number of days for every year while(currentYear < year) do if(isLeapYear(currentYear)) then numDays = numDays + 366; else numDays = numDays + 365; end currentYear = currentYear + 1; end --Add the correct number of days for every month while(currentMonth < month) do --February if(currentMonth == 2) then if(isLeapYear(currentYear)) then numDays = numDays + 29; else numDays = numDays + 28; end --31 day months elseif((currentMonth == 1) or (currentMonth == 3) or (currentMonth == 5) or (currentMonth == 7) or (currentMonth == 8) or (currentMonth == 10) or (currentMonth == 12)) then numDays = numDays + 31; --30 day months else numDays = numDays + 30; end currentMonth = currentMonth + 1; end --Account for the weird year of 1752 if(year > 1752) then numDays = numDays - 11; elseif(year == 1752) then if(month > 9) then numDays = numDays - 11; elseif(month == 9) then if(day >= 14) then numDays = numDays - 11; --Days 3-13 were skipped that year elseif((day > 2) and (day < 14)) then return DAYS.ERROR; end end end --Add the correct number of days for every day numDays = numDays + day; currentDay = currentDay + numDays; currentDay = currentDay % DAYS.NUMBER_OF_DAYS; if(currentDay == DAYS.SUNDAY) then day = DAYS.SUNDAY; elseif(currentDay == DAYS.MONDAY) then day = DAYS.MONDAY; elseif(currentDay == DAYS.TUESDAY) then day = DAYS.TUESDAY; elseif(currentDay == DAYS.WEDNESDAY) then day = DAYS.WEDNESDAY; elseif(currentDay == DAYS.THURSDAY) then day = DAYS.THURSDAY; elseif(currentDay == DAYS.FRIDAY) then day = DAYS.FRIDAY; elseif(currentDay == DAYS.SATURDAY) then day = DAYS.SATURDAY; else day = DAYS.ERROR; end --Return the day generated return day; end --Setup the variables local timer = Stopwatch:create(); local totalSundays = 0; --Start the timer timer:start(); --Run for all years up to 2000 for year=START_YEAR,END_YEAR do --Run for all months in the year for month=1,12 do local day = getDay(month, 1, year); if(day == DAYS.ERROR) then io.output("There was an error with the day\n"); os.exit(); elseif(day == DAYS.SUNDAY) then totalSundays = totalSundays + 1; end end end --Stop the timer timer:stop() --Print the results io.write("There are " .. totalSundays .. " Sundays that landed on the first of the months from " .. START_YEAR .. " to " .. END_YEAR .. '\n'); io.write("It took " .. timer:getMilliseconds() .. " milliseconds to run this algorithm\n"); --[[ Results: There are 171 Sundays that landed on the first of the months from 1901 to 2000 It took 390.0 milliseconds to run this algorithm ]]