//ProjectEulerTS/Problems/Problem18.ts //Matthew Ellison // Created: 04-06-21 //Modified: 07-14-21 //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/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 { Problem } from "./Problem"; //An easier way to signal day of the week enum DAYS {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FIRDAY, SATURDAY, NUMBER_OF_DAYS, ERROR}; export class Problem19 extends Problem{ //Variables //Static variables private static START_YEAR: number = 1901; //The first year we are going to test private static END_YEAR: number = 2000; //The last year we are going to test //Instance variables private totalSundays: number; //Keep track of the number of sundays //Functions //Constructor public constructor(){ super(`How many Sundays fell on the first of the month during the twentieth century (1 Jan ${Problem19.START_YEAR} to 31 Dec ${Problem19.END_YEAR})?`); this.totalSundays = 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(); //Run for all years 1901-2000 for(let year = Problem19.START_YEAR;year <= Problem19.END_YEAR;++year){ //Run for all months in the year for(let month = 1;month <= 12;++month){ let day: DAYS = this.getDay(month, 1, year); if(day == DAYS.ERROR){ console.log("There was an error with the day"); } else if(day == DAYS.SUNDAY){ ++this.totalSundays; } } } //Stop the timer this.timer.stop(); //Throw a flag to show the problem is solved this.solved = true; } //Return the day of the week that the data you pass into it is on private getDay(month: number, day: number, year: number): DAYS{ //Make sure the numbers are within propper bounds if((month < 1) || (month > 12) || (day < 1) || (day > 31) || (year < 1)){ return DAYS.ERROR; } let numDays: number = 0; let currentYear: number = 1; let currentMonth: number = 1; let currentDay: number = DAYS.SATURDAY; --day; //Add the correct number of days for every year while(currentYear < year){ if(this.isLeapYear(currentYear)){ numDays += 366; } else{ numDays += 365; } ++currentYear; } //Add the correct number of days for every month while(currentMonth < month){ switch(currentMonth){ case 1: case 3: case 5: case 7: case 8: case 10: case 12: numDays += 31; break; case 4: case 6: case 9: case 11: numDays += 30; break; case 2: if(this.isLeapYear(currentYear)){ numDays += 29; } else{ numDays += 28; } break; } ++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; } else if((day > 2) && (day < 14)){ console.log("Hit 1752 error"); return DAYS.ERROR; } } } //Add the correct number of days for every day numDays += day; currentDay += numDays; currentDay = currentDay % DAYS.NUMBER_OF_DAYS; switch(currentDay){ case DAYS.SUNDAY: return DAYS.SUNDAY; case DAYS.MONDAY: return DAYS.MONDAY; case DAYS.TUESDAY: return DAYS.TUESDAY; case DAYS.WEDNESDAY: return DAYS.WEDNESDAY; case DAYS.THURSDAY: return DAYS.THURSDAY; case DAYS.FIRDAY: return DAYS.FIRDAY; case DAYS.SATURDAY: return DAYS.SATURDAY; default: console.log("Hit default error"); return DAYS.ERROR; } } //Returns true if the year passed to it is a leap year private isLeapYear(year: number): boolean{ 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; } //Reset the problem so it can be run again public reset(): void{ super.reset(); this.totalSundays = 0; } //Gets //Returns the result of solving the problem public getResult(): string{ this.solvedCheck("result"); return `There are ${this.totalSundays} Sundays that landed on the first of the months from ${Problem19.START_YEAR} to ${Problem19.END_YEAR}`; } //Returns the total sundays that were asked for public getTotalSundays(): number{ this.solvedCheck("total number of sundays"); return this.totalSundays; } } /* Results: There are 171 Sundays that landed on the first of the months from 1901 to 2000 It took an average of 4.314 milliseconds to run this problem through 100 iterations */