# Project Euler in PL/SQL: Problem 19

Solving the riddle from problem 19 for Project Euler in PL/SQL.

## Problem 19:

### Counting Sundays

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.

How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

It took me a couple re-reads of the problem to understand what they were asking for here. I needed to check for the following conditions – for every month in every year of 1901 to 2000, check to see if the 1st day is a Sunday.

I came up with the below solution without using any of the Oracle date functions so the code could stand on its own. I think it’s pretty self explanatory, though the first_day_of_month code might take a couple read-throughs to understand how or why it works.

DECLARE
day_of_week INTEGER := 2; --1901 starts on a Tuesday
answer INTEGER := 0;
FUNCTION first_day_of_month(month_days_in INTEGER, curr_day_in INTEGER) RETURN INTEGER
AS
day_tracker INTEGER;
BEGIN
--takes weekday of the first of the previous month and return
--what the first of the next month will be
-- 1 = Mon, 2 = Tues, 3 = Wed, 4 = Thurs, 5 = Fri, 6 = Sat, 7 = Sun

day_tracker := curr_day_in + MOD(month_days_in, 7);

IF day_tracker > 7 THEN
day_tracker := day_tracker - 7;
END IF;

RETURN day_tracker;
END;
BEGIN
FOR i_year IN 1901..2000 LOOP
FOR i_month IN 1..12 LOOP
--check if it's Sunday at the start of each month
IF day_of_week = 7 THEN
END IF;

--calculate what day of the week if will be at the start of next month
IF i_month IN (4,6,9,11) THEN
--thirty days
day_of_week := first_day_of_month(30, day_of_week);
ELSIF i_month IN (2) THEN
--feb 28/29
IF (REMAINDER(i_year,4) = 0 AND REMAINDER(i_year,100) != 0) OR REMAINDER(i_year, 400) = 0 THEN
--leap year
day_of_week := first_day_of_month(29, day_of_week);
ELSE
day_of_week := first_day_of_month(28, day_of_week);
END IF;
ELSE
--thirty-one days
day_of_week := first_day_of_month(31, day_of_week);
END IF;
END LOOP;
END LOOP;
END;

--output: 171

I decided to see how much easier it would be to use built-in Oracle functions, and the result was much, much simpler…

DECLARE
answer INTEGER := 0;
BEGIN
FOR i_year IN 1901..2000 LOOP
FOR i_month IN 1..12 LOOP
--check if it's Sunday at the start of each month
IF TRIM(TO_CHAR(TO_DATE(i_month||'/1/'||i_year,'MM/DD/YYYY'), 'DAY')) = 'SUNDAY' THEN