//ProjectEuler/C++/Source/Problem19.cpp //Matthew Ellison // Created: 09-28-18 //Modified: 07-14-19 //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. */ //Unless otherwise listed all non-standard includes are my own creation and available from https://bibucket.org/Mattrixwv/myClasses /* 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 . */ #include #include #include #include "Stopwatch.hpp" #include "../Headers/Problem19.hpp" unsigned int Problem19::START_YEAR = 1901; //The start year unsigned int Problem19::END_YEAR = 2000; //The stop year Problem19::Problem19() : Problem("How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?"), totalSundays(0){ } Problem19::DAYS Problem19::getDay(unsigned int month, unsigned int day, unsigned int year){ //Make sure the numbers are within propper bounds if((month < 1) || (month > 12) || (day < 1) || (day > 31) || (year < 1)){ return ERROR; } uint64_t numDays = 0; //The number of days between 01-01-0001 and the date given (Saturday) unsigned int currentYear, currentMonth, currentDay; currentYear = 1; currentMonth = 1; currentDay = SATURDAY; --day; //Add the correct number of days for every year while(currentYear < year){ if(isLeapYear(currentYear)){ numDays += 366; } else{ numDays += 365; } ++currentYear; } //Add the correct number of days for every month while(currentMonth < month){ //31 day months if(currentMonth == 2){ if(isLeapYear(currentYear)){ numDays += 29; } else{ numDays += 28; } } else if((currentMonth == 1) || (currentMonth == 3) || (currentMonth == 5) || (currentMonth == 7) || (currentMonth == 8) || (currentMonth == 10) || (currentMonth == 12)){ numDays += 31; } else{ numDays += 30; } ++currentMonth; } //Account for the weird year of 1752 if(year > 1752){ numDays -= 11; } else if(year == 1752){ if(month > 9){ numDays -= 11; } else if(month == 9){ if(day >= 14){ numDays -= 11; } //Days 3-13 were skipped that year else if((day > 2) && (day < 14)){ return ERROR; } } } //Add the correct number of days for every day numDays += day; currentDay += numDays; currentDay = currentDay % NUMBER_OF_DAYS; switch(currentDay){ case SUNDAY: return SUNDAY; case MONDAY: return MONDAY; case TUESDAY: return TUESDAY; case WEDNESDAY: return WEDNESDAY; case THURSDAY: return THURSDAY; case FRIDAY: return FRIDAY; case SATURDAY: return SATURDAY; default: return ERROR; } } bool Problem19::isLeapYear(unsigned int year){ if(year < 1){ return false; } else if((year % 100) == 0){ //This rule only applies at and after 1800 if(year <= 1700){ return true; } else if((year % 400) == 0){ return true; } } else if((year % 4) == 0){ return true; } return false; } void Problem19::solve(){ //If the problem has already been solved do nothing and end the function if(solved){ return; } //Start the timer timer.start(); //Run for all years up to 2000 for(unsigned int year = START_YEAR;year <= END_YEAR;++year){ //Run for all months in the year for(unsigned int month = 1;month <= 12;++month){ DAYS day = getDay(month, 1, year); if(day == ERROR){ exit(1); } else if(day == SUNDAY){ ++totalSundays; } } } //Stop the timer timer.stop(); //Throw a flag to show the problem is solved solved = true; } std::string Problem19::getString() const{ //If the problem hasn't been solved throw an exception if(!solved){ throw unsolved(); } std::stringstream results; results << "There are " << totalSundays << " Sundays that landed on the first of the months from " << START_YEAR << " to " << END_YEAR; return results.str(); } uint64_t Problem19::getTotalSundays() const{ //If the problem hasn't been solved throw an exception if(!solved){ throw unsolved(); } return totalSundays; }