Task

Write a program or a script that returns the date of the last Fridays 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_fridays 2012
2012-01-27
2012-02-24
2012-03-30
2012-04-27
2012-05-25
2012-06-29
2012-07-27
2012-08-31
2012-09-28
2012-10-26
2012-11-30
2012-12-28



Related tasks
 Five weekends
 Day of the week
 Find the last Sunday of each month


% for command line argument 
main(ARGV) =>
  if ARGV.length > 0 then
    Year = ARGV[1].to_integer(),
    show_year(Year),
    nl
  end.
 
% Without command line argument
main => go.
 
go =>
  show_year(2022),
  nl.
 
% Show the months
show_year(Year) =>
  foreach(Date in get_months(Year)) 
    println(format_date(Date))
  end,
  nl.
 
% Format date to YYYY-DD-MM
format_date(Date) = to_fstring("%4d-%02d-%02d",Date[1],Date[2],Date[3]).
 
 
% Return the last Fridays of each month for year Year
get_months(Year) = 
  [ [ [Year,Month,Day] : Day in 1..max_days_in_month(Year,Month),
                         dow(Year, Month, Day) == 5].last() : Month in 1..12].
 
 
% Day of week, Sakamoto's method
dow(Y, M, D) = R =>
  T = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4],
  if M < 3 then
     Y := Y - 1
  end,
  R = (Y + Y // 4 - Y // 100 + Y // 400 + T[M] + D) mod 7.
 
% Maximum days in month
max_days_in_month(Year,Month) = Days => 
  if member(Month, [1,3,5,7,8,10,12]) then 
    Days = 31
  elseif member(Month,[4,6,9,11]) then
    Days = 30
  else
    if leap_year(Year) then
     Days = 29
   else
     Days = 28
   end
  end.
 
% Is Year a leap year?
leap_year(Year) => 
  (Year mod 4 == 0, Year mod 100 != 0) 
  ; 
  Year mod 400 == 0. 