Write a program or a script that returns the last Sundays of each month of a given year. The year may be given through any simple input method in your language (command line, std in, etc).

Example of an expected output:

./last_sundays 2013
2013-01-27
2013-02-24
2013-03-31
2013-04-28
2013-05-26
2013-06-30
2013-07-28
2013-08-25
2013-09-29
2013-10-27
2013-11-24
2013-12-29


Related tasks
 Day of the week
 Five weekends
 Last Friday of each month


 
BEGIN
 
% CALCULATE P MOD Q %
INTEGER FUNCTION MOD(P, Q);
INTEGER P, Q;
BEGIN
   MOD := P - Q * (P / Q);
END;
 
COMMENT
  RETURN DAY OF WEEK (SUN=0, MON=1, ETC.) FOR A GIVEN
  GREGORIAN CALENDAR DATE USING ZELLER'S CONGRUENCE;
INTEGER FUNCTION DAYOFWEEK(MO, DA, YR);
INTEGER MO, DA, YR;
BEGIN
  INTEGER Y, C, Z;
  IF MO < 3 THEN
    BEGIN
      MO := MO + 10;
      YR := YR - 1;
    END
  ELSE MO := MO - 2;
  Y := MOD(YR, 100);
  C := YR / 100;
  Z := (26 * MO - 2) / 10;
  Z := Z + DA + Y + (Y / 4) + (C / 4) - 2 * C + 777;
  DAYOFWEEK := MOD(Z, 7);
END;
 
% RETURN 1 IF Y IS A LEAP YEAR, OTHERWISE 0 %
INTEGER FUNCTION ISLEAPYR(Y);
INTEGER Y;
BEGIN
  IF MOD(Y,4) <> 0 THEN  % QUICK EXIT IN MOST COMMON CASE %
    ISLEAPYR := 0
  ELSE IF MOD(Y,400) = 0 THEN
    ISLEAPYR := 1
  ELSE IF MOD(Y,100) = 0 THEN
    ISLEAPYR := 0
  ELSE                   % NON-CENTURY AND DIVISIBLE BY 4 %
    ISLEAPYR := 1;
END;
 
% RETURN THE NUMBER OF DAYS IN THE SPECIFIED MONTH %
INTEGER FUNCTION MONTHDAYS(MO, YR);
INTEGER MO, YR;
BEGIN
  IF MO = 2 THEN
    BEGIN
      IF ISLEAPYR(YR) = 1 THEN
        MONTHDAYS := 29
      ELSE
        MONTHDAYS := 28;
    END
  ELSE IF (MO = 4) OR (MO = 6) OR (MO = 9) OR (MO = 11) THEN
    MONTHDAYS := 30
  ELSE
    MONTHDAYS := 31;
END;
 
COMMENT
  RETURN THE DAY OF THE MONTH CORRESPONDING TO LAST OCCURRENCE
  OF WEEKDAY K (SUN=0, MON=1, ETC.) FOR A GIVEN MONTH AND YEAR;
INTEGER FUNCTION LASTKDAY(K, M, Y);
INTEGER K, M, Y;
BEGIN
  INTEGER D, W;
  % DETERMINE WEEKDAY FOR THE LAST DAY OF THE MONTH %
  D := MONTHDAYS(M, Y);
  W := DAYOFWEEK(M, D, Y);
  % BACK UP AS NEEDED TO DESIRED WEEKDAY %
  IF W >= K THEN
    D := D - (W - K)
  ELSE
    D := D - (7 - K - W);
  LASTKDAY := D;
END;
 
STRING FUNCTION MONTHNAME(N);
INTEGER N;
BEGIN
  CASE (N - 1) OF
    BEGIN
      MONTHNAME := "JAN";
      MONTHNAME := "FEB";
      MONTHNAME := "MAR";
      MONTHNAME := "APR";
      MONTHNAME := "MAY";
      MONTHNAME := "JUN";
      MONTHNAME := "JUL";
      MONTHNAME := "AUG";
      MONTHNAME := "SEP";
      MONTHNAME := "OCT";
      MONTHNAME := "NOV";
      MONTHNAME := "DEC";
    END;
END;
 
% EXERCISE THE ROUTINE %
INTEGER M, Y, SUNDAY;
SUNDAY := 0;
WRITE("DISPLAY LAST SUNDAYS FOR WHAT YEAR?");
READ(Y);
FOR M:=1 STEP 1 UNTIL 12 DO
  WRITE(MONTHNAME(M), LASTKDAY(SUNDAY,M,Y));
 
END
 