Last Friday of each month: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 23: Line 23:


=={{header|C}}==
=={{header|C}}==
{{incorrect|C|<code>./last_fridays 2011</code> gives thursdays instead of fridays}}

<lang c>#define _XOPEN_SOURCE
<lang c>#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdio.h>
Line 49: Line 51:
return 0;
return 0;
}</lang>
}</lang>

=={{header|C++}}==
=={{header|C++}}==
called with <code>./last_fridays 2012</code>
called with <code>./last_fridays 2012</code>

Revision as of 21:00, 8 November 2011

Last Friday of each month is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Write a program or a script that returns the last Fridays of each months of a given year provided as argument on the command line.

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
Cf.

C

This example is incorrect. Please fix the code and remove this message.

Details: ./last_fridays 2011 gives thursdays instead of fridays

<lang c>#define _XOPEN_SOURCE

  1. include <stdio.h>
  2. include <time.h>

int main(int c, char *v[]) { int days[] = {31,29,31,30,31,30,31,31,30,31,30,31}; int m, y, w; struct tm tm; char buf[32];

if (c < 2 || !sscanf(v[1], "%d", &y)) return 1;

days[1] -= y % 4 || (y % 100 && ! (y % 400)); sprintf(buf, "%d-1-1", y); strptime(buf, "%Y-%m-%d", &tm); w = tm.tm_wday - 1; /* day of week for zeroth of Jan */

for(m = 0; m < 12; m++) { w = (w + days[m]) % 7; printf("%d-%02d-%d\n", y, m + 1, days[m] + (w < 5 ? -2 : 5) - w); }

return 0; }</lang>

C++

called with ./last_fridays 2012 <lang cpp>#include <boost/date_time/gregorian/gregorian.hpp>

  1. include <iostream>
  2. include <cstdlib>

int main( int argc , char* argv[ ] ) {

  using namespace boost::gregorian ;
  greg_month months[ ] = { Jan , Feb , Mar , Apr , May , Jun , Jul ,
     Aug , Sep , Oct , Nov , Dec } ;
  greg_year gy = atoi( argv[ 1 ] ) ;
  for ( int i = 0 ; i < 12 ; i++ ) {
     last_day_of_the_week_in_month lwdm ( Friday , months[ i ] ) ;
     date d = lwdm.get_date( gy ) ;
     std::cout << d << std::endl ;
  }
  return 0 ;

}</lang> Output:

2012-Jan-27
2012-Feb-24
2012-Mar-30
2012-Apr-27
2012-May-25
2012-Jun-29
2012-Jul-27
2012-Aug-31
2012-Sep-28
2012-Oct-26
2012-Nov-30
2012-Dec-28

Icon and Unicon

This will write the last fridays for every year given as an argument. There is no error checking on the year.

<lang Icon>procedure main(A) every write(lastfridays(!A)) end

procedure lastfridays(year) every m := 1 to 12 do {

  d := case m of {
     2        : if IsLeapYear(year) then 29 else 28
     4|6|9|11 : 30
     default  : 31
     }                          # last day of month
      
  z := 0  
  j := julian(m,d,year) + 1     # first day of next month
  until (j-:=1)%7 = 4 do z -:=1 # backup to last friday=4
  suspend sprintf("%d-%d-%d",year,m,d+z)
  }

end

link datetime, printf</lang>

printf.icn provides formatting datetime.icn provides julian and IsLeapYear

Output:

last_fridays.exe 2012
2012-1-27
2012-2-24
2012-3-30
2012-4-27
2012-5-25
2012-6-29
2012-7-27
2012-8-31
2012-9-28
2012-10-26
2012-11-30
2012-12-28

J

<lang j>require'dates' last_fridays=: 12 {. [:({:/.~ }:"1)@(#~ 5 = weekday)@todate (i.366) + todayno@,&1 1</lang>

In other words, start from January 1 of the given year, and count forward for 366 days, keeping the fridays. Then pick the last friday within each represented month. Then pick the first 12 (since on a non-leap year which ends on a thursday we would get an extra friday).

Example use:

<lang j> last_fridays 2012 2012 1 27 2012 2 24 2012 3 30 2012 4 27 2012 5 25 2012 6 29 2012 7 27 2012 8 31 2012 9 28 2012 10 26 2012 11 30 2012 12 28</lang>

Java

Works with: Java version 1.5+

<lang java5>import java.util.Calendar; import java.util.GregorianCalendar;

public class LastFriday { private static int[] months = {Calendar.JANUARY, Calendar.FEBRUARY, Calendar.MARCH, Calendar.APRIL, Calendar.MAY, Calendar.JUNE, Calendar.JULY, Calendar.AUGUST, Calendar.SEPTEMBER, Calendar.OCTOBER, Calendar.NOVEMBER, Calendar.DECEMBER}; public static void main(String[] args){ int year = Integer.parseInt(args[0]); boolean leapYear = new GregorianCalendar().isLeapYear(year); for(int month:months){ int days = 31; switch(month){ case Calendar.SEPTEMBER: case Calendar.APRIL: case Calendar.JUNE: case Calendar.NOVEMBER: days = 30; break; case Calendar.FEBRUARY: days = leapYear ? 29 : 28; default: } GregorianCalendar date = new GregorianCalendar(year, month, days); while(date.get(Calendar.DAY_OF_WEEK) != Calendar.FRIDAY){ date.add(Calendar.DAY_OF_MONTH, -1); } System.out.println((date.get(Calendar.MONTH) + 1) + "-" + date.get(Calendar.DAY_OF_MONTH)); } } }</lang> Output (for java LastFriday 2012):

1-27
2-24
3-30
4-27
5-25
6-29
7-27
8-31
9-28
10-26
11-30
12-28

OCaml

<lang ocaml>#load "unix.cma" open Unix

let usage() =

 Printf.eprintf "%s <year>\n" Sys.argv.(0);
 exit 1

let print_date t =

 Printf.printf "%d-%02d-%02d\n" (t.tm_year + 1900) (t.tm_mon + 1) t.tm_mday

let is_date_ok tm t =

 (tm.tm_year = t.tm_year &&
  tm.tm_mon  = t.tm_mon  &&
  tm.tm_mday = t.tm_mday)

let () =

 let _year =
   try int_of_string Sys.argv.(1)
   with _ -> usage()
 in
 let year = _year - 1900 in
 let fridays = Array.make 12 (Unix.gmtime 0.0) in
 for month = 0 to 11 do
   for day_of_month = 1 to 31 do
     let tm = { (Unix.gmtime 0.0) with 
       tm_year = year;
       tm_mon = month;
       tm_mday = day_of_month;
     } in
     let _, t = Unix.mktime tm in
     if is_date_ok tm t  (* check for months that have less than 31 days *)
     && t.tm_wday = 5  (* is a friday *)
     then fridays.(month) <- t
   done;
 done;
 Array.iter print_date fridays</lang>

Output:

$ ocaml last_fridays.ml 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

Perl

<lang Perl>#!/usr/bin/perl -w use strict ; use DateTime ; use feature qw( say ) ;

foreach my $month ( 1..12 ) {

  my $dt = DateTime->last_day_of_month( year => $ARGV[ 0 ] , month => $month ) ;
  while ( $dt->day_of_week != 5 ) {
     $dt->subtract( days => 1 ) ;
  }
  say $dt->ymd ;

}</lang> Output:

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

Pike

<lang Pike>int(0..1) last_friday(object day) {

  return day->week_day() == 5 && 
         day->month_day() > day->month()->number_of_days()-7; 

}

int main(int argc, array argv) {

   array days = filter(Calendar.Year((int)argv[1])->months()->days()[*], last_friday);
   write("%{%s\n%}", days->format_ymd());
   return 0;

}</lang>

Ruby

<lang ruby>require 'date'

def last_friday(year, month)

 if month == 12
   d = Date.new(year+1, 1, 1)
 else
   d = Date.new(year, month+1, 1)
 end
 begin
   d -= 1
 end until d.wday == 5 # Ruby 1.9: d.friday?
 d

end

year = Integer(ARGV.shift) (1..12).each {|month| puts last_friday(year, month)}</lang>

Library: ActiveSupport

Using the ActiveSupport library for some convenience methods

<lang ruby>require 'rubygems' require 'activesupport'

def last_friday(year, month)

 d = Date.new(year, month, 1).end_of_month
 until d.wday == 5
   d = d.yesterday
 end
 d

end</lang>

Tcl

<lang tcl>package require Tcl 8.5 set year [lindex $argv 0] foreach dm {02/1 03/1 04/1 05/1 06/1 07/1 08/1 09/1 10/1 11/1 12/1 12/32} {

   # The [clock scan] code is unhealthily clever; use it for our own evil purposes
   set t [clock scan "last friday" -base [clock scan $dm/$year -gmt 1] -gmt 1]
   # Print the interesting part
   puts [clock format $t -format "%Y-%m-%d" -gmt 1]

}</lang> Sample execution:

$ tclsh8.5 lastfri.tcl 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