Find the last Sunday of each month: Difference between revisions
(→Tcl: Added implementation) |
|||
Line 432: | Line 432: | ||
2013-09-29 |
2013-09-29 |
||
2013-10-27 |
2013-10-27 |
||
2013-11-24 |
|||
2013-12-29 |
|||
</pre> |
|||
=={{header|Tcl}}== |
|||
<lang tcl>proc lastSundays {{year ""}} { |
|||
if {$year eq ""} { |
|||
set year [clock format [clock seconds] -gmt 1 -format "%Y"] |
|||
} |
|||
foreach month {2 3 4 5 6 7 8 9 10 11 12 13} { |
|||
set d [clock add [clock scan "$month/1/$year" -gmt 1] -1 day] |
|||
while {[clock format $d -gmt 1 -format "%u"] != 7} { |
|||
set d [clock add $d -1 day] |
|||
} |
|||
lappend result [clock format $d -gmt 1 -format "%Y-%m-%d"] |
|||
} |
|||
return $result |
|||
} |
|||
puts [join [lastSundays {*}$argv] "\n"]</lang> |
|||
{{out}} |
|||
When called as: “<code>tclsh lastSundays.tcl 2013</code>” (or with the year argument omitted during 2013) |
|||
<pre> |
|||
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-20 |
|||
2013-11-24 |
2013-11-24 |
||
2013-12-29 |
2013-12-29 |
Revision as of 11:34, 27 April 2013
You are encouraged to solve this task according to the task description, using any language you may know.
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
- Cf.
Ada
The program from [[1]] solves this task, as well.
- Output:
>./last_weekday_in_month sunday 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
BBC BASIC
<lang bbcbasic> INSTALL @lib$+"DATELIB"
INPUT "What year to calculate (YYYY)? " Year%
PRINT '"Last Sundays in ";Year%;" are on:" FOR Month%=1 TO 12
PRINT Year% "-" RIGHT$("0"+STR$Month%,2) "-";FN_dim(Month%,Year%)-FN_dow(FN_mjd(FN_dim(Month%,Year%),Month%,Year%))
NEXT END </lang> Output:
What year to calculate (YYYY)? 2013 Last Sundays in 2013 are on: 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
C++
<lang cpp>
- include <windows.h>
- include <iostream>
- include <string>
//-------------------------------------------------------------------------------------------------- using namespace std;
//-------------------------------------------------------------------------------------------------- class lastSunday { public:
lastSunday() {
m[0] = "JANUARY: "; m[1] = "FEBRUARY: "; m[2] = "MARCH: "; m[3] = "APRIL: "; m[4] = "MAY: "; m[5] = "JUNE: "; m[6] = "JULY: "; m[7] = "AUGUST: "; m[8] = "SEPTEMBER: "; m[9] = "OCTOBER: "; m[10] = "NOVEMBER: "; m[11] = "DECEMBER: ";
}
void findLastSunday( int y ) {
year = y; isleapyear();
int days[] = { 31, isleap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, d; for( int i = 0; i < 12; i++ ) { d = days[i]; while( true ) { if( !getWeekDay( i, d ) ) break; d--; } lastDay[i] = d; }
display();
}
private:
void isleapyear() {
isleap = false; if( !( year % 4 ) ) { if( year % 100 ) isleap = true; else if( !( year % 400 ) ) isleap = true; }
}
void display() {
system( "cls" ); cout << " YEAR " << year << endl << "=============" << endl; for( int x = 0; x < 12; x++ ) cout << m[x] << lastDay[x] << endl;
cout << endl << endl;
}
int getWeekDay( int m, int d ) {
int y = year;
int f = y + d + 3 * m - 1; m++; if( m < 3 ) y--; else f -= int( .4 * m + 2.3 );
f += int( y / 4 ) - int( ( y / 100 + 1 ) * 0.75 ); f %= 7;
return f;
}
int lastDay[12], year; string m[12]; bool isleap;
}; //-------------------------------------------------------------------------------------------------- int main( int argc, char* argv[] ) {
int y; lastSunday ls;
while( true ) {
system( "cls" ); cout << "Enter the year( yyyy ) --- ( 0 to quit ): "; cin >> y; if( !y ) return 0;
ls.findLastSunday( y );
system( "pause" );
} return 0;
} //-------------------------------------------------------------------------------------------------- </lang> Output:
YEAR 2013 ============= JANUARY: 27 FEBRUARY: 24 MARCH: 31 APRIL: 28 MAY: 26 JUNE: 30 JULY: 28 AUGUST: 25 SEPTEMBER: 29 OCTOBER: 27 NOVEMBER: 24 DECEMBER: 29
FBSL
<lang qbasic>#APPTYPE CONSOLE
DIM date AS INTEGER, dayname AS STRING FOR DIM i = 1 TO 12
FOR DIM j = 31 DOWNTO 1 date = 20130000 + (i * 100) + j IF CHECKDATE(i, j, 2013) THEN dayname = DATECONV(date, "dddd") IF dayname = "Sunday" THEN PRINT 2013, " ", i, " ", j EXIT FOR END IF END IF NEXT
NEXT
PAUSE </lang> Output <lang text>2013-1-27 2013-2-24 2013-3-31 2013-4-28 2013-5-26 2013-6-30 2013-7-28 2013-8-25 2013-9-29 2013-10-27 2013-11-24 2013-12-29
Press any key to continue... </lang>
Perl
<lang Perl>#!/usr/bin/perl use strict ; use warnings ; use DateTime ;
for my $i( 1..12 ) {
my $date = DateTime->last_day_of_month( year => $ARGV[ 0 ] ,
month => $i ) ;
while ( $date->dow != 7 ) { $date = $date->subtract( days => 1 ) ; } my $ymd = $date->ymd ; print "$ymd\n" ;
}</lang> Output:
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
Perl 6
<lang Perl6>for (1..12) -> $i {
my $lastDay = Date.days-in-month( @*ARGS[ 0 ].Int , $i ) ; my $lastDate = Date.new( @*ARGS[ 0 ].Int , $i , $lastDay ) ; while $lastDate.day-of-week != 7 { $lastDate -= 1 ; } $lastDate.say ;
}</lang> Output:
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
REXX
This REXX example is an exact replication of the Rosetta Code
- find last Fridays of each month for any year
except for the innards of the first DO loop.
The lastDOW subroutine can be used for any day-of-the-week for any month for any year.
<lang rexx>/*REXX program displays dates of last Sundays of each month for any year*/
parse arg yyyy
do j=1 for 12 _ = lastDOW('Sunday', j, yyyy) say right(_,4)'-'right(j,2,0)"-"left(word(_,2),2) end /*j*/
exit /*stick a fork in it, we're done.*/ /*┌────────────────────────────────────────────────────────────────────┐
│ lastDOW: procedure to return the date of the last day-of-week of │ │ any particular month of any particular year. │ │ │ │ The day-of-week must be specified (it can be in any case, │ │ (lower-/mixed-/upper-case) as an English name of the spelled day │ │ of the week, with a minimum length that causes no ambiguity. │ │ I.E.: W for Wednesday, Sa for Saturday, Su for Sunday ... │ │ │ │ The month can be specified as an integer 1 ──► 12 │ │ 1=January 2=February 3=March ... 12=December │ │ or the English name of the month, with a minimum length that │ │ causes no ambiguity. I.E.: Jun for June, D for December. │ │ If omitted [or an asterisk(*)], the current month is used. │ │ │ │ The year is specified as an integer or just the last two digits │ │ (two digit years are assumed to be in the current century, and │ │ there is no windowing for a two-digit year). │ │ If omitted [or an asterisk(*)], the current year is used. │ │ Years < 100 must be specified with (at least 2) leading zeroes.│ │ │ │ Method used: find the "day number" of the 1st of the next month, │ │ then subtract one (this gives the "day number" of the last day of │ │ the month, bypassing the leapday mess). The last day-of-week is │ │ then obtained straightforwardly, or via subtraction. │ └────────────────────────────────────────────────────────────────────┘*/
lastdow: procedure; arg dow .,mm .,yy . /*DOW = day of week*/ parse arg a.1,a.2,a.3 /*orig args, errmsg*/ if mm== | mm=='*' then mm=left(date('U'),2) /*use default month*/ if yy== | yy=='*' then yy=left(date('S'),4) /*use default year */ if length(yy)==2 then yy=left(date('S'),2)yy /*append century. */
/*Note mandatory leading blank in strings below.*/
$=" Monday TUesday Wednesday THursday Friday SAturday SUnday" !=" JAnuary February MARch APril MAY JUNe JULy AUgust September",
" October November December"
upper $ ! /*uppercase strings*/ if dow== then call .er "wasn't specified",1 if arg()>3 then call .er 'arguments specified',4
do j=1 for 3 /*any plural args ?*/ if words(arg(j))>1 then call .er 'is illegal:',j end
dw=pos(' 'dow,$) /*find day-of-week*/ if dw==0 then call .er 'is invalid:',1 if dw\==lastpos(' 'dow,$) then call .er 'is ambigious:',1
if datatype(mm,'month') then /*if MM is alpha...*/
do m=pos(' 'mm,!) /*maybe its good...*/ if m==0 then call .er 'is invalid:',1 if m\==lastpos(' 'mm,!) then call .er 'is ambigious:',2 mm=wordpos(word(substr(!,m),1),!)-1 /*now, use true Mon*/ end
if \datatype(mm,'W') then call .er "isn't an integer:",2 if \datatype(yy,'W') then call .er "isn't an integer:",3 if mm<1 | mm>12 then call .er "isn't in range 1──►12:",2 if yy=0 then call .er "can't be 0 (zero):",3 if yy<0 then call .er "can't be negative:",3 if yy>9999 then call .er "can't be > 9999:",3
tdow=wordpos(word(substr($,dw),1),$)-1 /*target DOW, 0──►6*/
/*day# of last dom.*/
_=date('B',right(yy+(mm=12),4)right(mm//12+1,2,0)"01",'S')-1 ?=_//7 /*calc. DOW, 0──►6*/ if ?\==tdow then _=_-?-7+tdow+7*(?>tdow) /*not DOW? Adjust.*/ return date('weekday',_,"B") date(,_,'B') /*return the answer*/
.er: arg ,_;say; say '***error!*** (in LASTDOW)';say /*tell error, and */
say word('day-of-week month year excess',arg(2)) arg(1) a._ say; exit 13 /*... then exit. */</lang>
output when using the default input (the current year, 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
Seed7
Uses the libraries time.s7i and duration.s7i. Applicable to any day of the week, cf. [[2]].
<lang seed7>$ include "seed7_05.s7i";
include "time.s7i"; include "duration.s7i";
const proc: main is func
local var integer: weekday is 1; # 1 for monday, 2 for tuesday, and so on up to 7 for sunday. var integer: year is 0; var integer: month is 1; var time: aDate is time.value; var time: selected is time.value; begin if length(argv(PROGRAM)) <> 2 then writeln("usage: lastWeekdayInMonth weekday year"); writeln(" weekday: 1 for monday, 2 for tuesday, and so on up to 7 for sunday."); else weekday := integer parse (argv(PROGRAM)[1]); year := integer parse (argv(PROGRAM)[2]); for month range 1 to 12 do aDate := date(year, month, 1); while aDate.month = month do if dayOfWeek(aDate) = weekday then selected := aDate; end if; aDate +:= 1 . DAYS; end while; writeln(strDate(selected)); end for; end if; end func;</lang>
Output when called with s7 rosetta/lastWeekdayInMonth 7 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
Tcl
<lang tcl>proc lastSundays Template:Year "" {
if {$year eq ""} {
set year [clock format [clock seconds] -gmt 1 -format "%Y"]
} foreach month {2 3 4 5 6 7 8 9 10 11 12 13} {
set d [clock add [clock scan "$month/1/$year" -gmt 1] -1 day] while {[clock format $d -gmt 1 -format "%u"] != 7} { set d [clock add $d -1 day] } lappend result [clock format $d -gmt 1 -format "%Y-%m-%d"]
} return $result
} puts [join [lastSundays {*}$argv] "\n"]</lang>
- Output:
When called as: “tclsh lastSundays.tcl 2013
” (or with the year argument omitted during 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-20 2013-11-24 2013-12-29