Five weekends
You are encouraged to solve this task according to the task description, using any language you may know.
The month of October in 2010 has five Fridays, five Saturdays, and five Sundays.
The task
- Write a program to show all months that have this same characteristic of five full weekends from the year 1900 through 2100 (Gregorian calendar).
- Show the number of months with this property (there should be 201).
- Show at least the first and last five dates, in order.
Algorithm suggestions
- Count the number of Fridays, Saturdays, and Sundays in every month.
- Find all of the 31-day months that begin on Friday.
Extra credit
Count and/or show all of the years which do not have at least one five-weekend month (there should be 29).
Ada
<lang Ada> with Ada.Text_IO; use Ada.Text_IO; with Ada.Calendar.Formatting; use Ada.Calendar;
use Ada.Calendar.Formatting;
procedure Five_Weekends is
Months : Natural := 0;
begin
for Year in Year_Number range 1901..2100 loop for Month in Month_Number range 1..12 loop begin if Day_Of_Week (Formatting.Time_Of (Year, Month, 31)) = Sunday then Put_Line (Year_Number'Image (Year) & Month_Number'Image (Month)); Months := Months + 1; end if; exception when Time_Error => null; end; end loop; end loop; Put_Line ("Number of months:" & Integer'Image (Months));
end Five_Weekends; </lang> Sample output:
1901 3 1902 8 1903 5 1904 1 1904 7 1905 12 1907 3 1908 5 1909 1 1909 10 1910 7 1911 12 1912 3 1913 8 1914 5 1915 1 1915 10 1916 12 1918 3 1919 8 1920 10 1921 7 1922 12 1924 8 1925 5 1926 1 1926 10 1927 7 1929 3 1930 8 1931 5 1932 1 1932 7 1933 12 1935 3 1936 5 1937 1 1937 10 1938 7 1939 12 1940 3 1941 8 1942 5 1943 1 1943 10 1944 12 1946 3 1947 8 1948 10 1949 7 1950 12 1952 8 1953 5 1954 1 1954 10 1955 7 1957 3 1958 8 1959 5 1960 1 1960 7 1961 12 1963 3 1964 5 1965 1 1965 10 1966 7 1967 12 1968 3 1969 8 1970 5 1971 1 1971 10 1972 12 1974 3 1975 8 1976 10 1977 7 1978 12 1980 8 1981 5 1982 1 1982 10 1983 7 1985 3 1986 8 1987 5 1988 1 1988 7 1989 12 1991 3 1992 5 1993 1 1993 10 1994 7 1995 12 1996 3 1997 8 1998 5 1999 1 1999 10 2000 12 2002 3 2003 8 2004 10 2005 7 2006 12 2008 8 2009 5 2010 1 2010 10 2011 7 2013 3 2014 8 2015 5 2016 1 2016 7 2017 12 2019 3 2020 5 2021 1 2021 10 2022 7 2023 12 2024 3 2025 8 2026 5 2027 1 2027 10 2028 12 2030 3 2031 8 2032 10 2033 7 2034 12 2036 8 2037 5 2038 1 2038 10 2039 7 2041 3 2042 8 2043 5 2044 1 2044 7 2045 12 2047 3 2048 5 2049 1 2049 10 2050 7 2051 12 2052 3 2053 8 2054 5 2055 1 2055 10 2056 12 2058 3 2059 8 2060 10 2061 7 2062 12 2064 8 2065 5 2066 1 2066 10 2067 7 2069 3 2070 8 2071 5 2072 1 2072 7 2073 12 2075 3 2076 5 2077 1 2077 10 2078 7 2079 12 2080 3 2081 8 2082 5 2083 1 2083 10 2084 12 2086 3 2087 8 2088 10 2089 7 2090 12 2092 8 2093 5 2094 1 2094 10 2095 7 2097 3 2098 8 2099 5 2100 1 2100 10 Number of months: 201
AppleScript
<lang AppleScript>set fiveWeekendMonths to {} set noFiveWeekendYears to {}
set someDate to current date set day of someDate to 1
repeat with someYear from 1900 to 2100
set year of someDate to someYear set foundOne to false repeat with someMonth in {January, March, May, July, ¬ August, October, December} set month of someDate to someMonth if weekday of someDate is Friday then set foundOne to true set end of fiveWeekendMonths to ¬ (someYear as text) & "-" & (someMonth as text) end end repeat if not foundOne then set end of noFiveWeekendYears to someYear end
end repeat
set text item delimiters to ", " set monthList to ¬
(items 1 thru 5 of fiveWeekendMonths as text) & ", ..." & linefeed & ¬ " ..., " & (items -5 thru end of fiveWeekendMonths as text)
set monthCount to count fiveWeekendMonths set yearCount to count noFiveWeekendYears
set resultText to ¬
"Months with five weekends (" & monthCount & "): " & linefeed & ¬ " " & monthList & linefeed & linefeed & ¬ "Years with no such months (" & yearCount & "): "
set y to 1 repeat while y < yearCount
set final to y+11 if final > yearCount then set final to yearCount end set resultText to ¬ resultText & linefeed & ¬ " " & (items y through final of noFiveWeekendYears as text) set y to y + 12
end resultText</lang>
Output (can always add "display dialog resultText" for GUI output):
Months with five weekends (201): 1901-March, 1902-August, 1903-May, 1904-January, 1904-July, ... ..., 2097-March, 2098-August, 2099-May, 2100-January, 2100-October Years with no such months (29): 1900, 1906, 1917, 1923, 1928, 1934, 1945, 1951, 1956, 1962, 1973, 1979 1984, 1990, 2001, 2007, 2012, 2018, 2029, 2035, 2040, 2046, 2057, 2063 2068, 2074, 2085, 2091, 2096
AutoHotkey
<lang AutoHotkey> Year := 1900 End_Year := 2100 31_Day_Months = 01,03,05,07,08,10,12
While Year <= End_Year { Loop, Parse, 31_Day_Months, CSV { FormatTime, Day, %Year%%A_LoopField%01, dddd IfEqual, Day, Friday { All_Months_With_5_Weekends .= A_LoopField . "/" . Year ", " 5_Weekend_Count++ Year_Has_5_Weekend_Month := 1 } } IfEqual, Year_Has_5_Weekend_Month, 0 { All_Years_Without_5_Weekend .= Year ", " No_5_Weekend_Count ++ } Year ++ Year_Has_5_Weekend_Month := 0 } StringTrimRight, All_Months_With_5_Weekends, All_Months_With_5_Weekends, 5 ; trim the spaces and comma off the last item StringTrimRight, All_Years_Without_5_Weekend, All_Years_Without_5_Weekend, 4 MsgBox, Months with 5 day weekends between 1900 and 2100 : %5_Weekend_Count%`r`n %All_Months_With_5_Weekends% MsgBox, Years with no 5 day weekends between 1900 and 2100 : %No_5_Weekend_Count% `r`n %All_Years_Without_5_Weekend%</lang>
ALGOL 68
Note: This specimen retains the original Fortran coding style. diff
<lang algol68>five_weekends: BEGIN
INT m, year, nfives := 0, not5 := 0; BOOL no5weekend; MODE MONTH = STRUCT( INT n, [3]CHAR name ) # MODE MONTH #; []MONTH month = ( MONTH(13, "Jan"), MONTH(3, "Mar"), MONTH(5, "May"), MONTH(7, "Jul"), MONTH(8, "Aug"), MONTH(10, "Oct"), MONTH(12, "Dec") ); FOR year FROM 1900 TO 2100 DO IF year = 1905 THEN printf($"..."l$) FI; no5weekend := TRUE; FOR m TO UPB month DO IF n OF month(m) = 13 THEN IF day_of_week(1, n OF month(m), year-1) = 6 THEN IF year<1905 OR year > 2096 THEN printf(($g, 5zl$, name OF month(m), year)) FI; nfives +:= 1; no5weekend := FALSE FI ELSE IF day_of_week(1, n OF month(m), year) = 6 THEN IF year<1905 OR year > 2096 THEN printf(($g, 5zl$, name OF month(m), year)) FI; nfives +:= 1; no5weekend := FALSE FI FI OD; IF no5weekend THEN not5 +:= 1 FI OD; printf(($g, g(0)l$, "Number of months with five weekends between 1900 and 2100 = ", nfives)); printf(($g, g(0)l$, "Number of years between 1900 and 2100 with no five weekend months = ", not5));
- contains #
PROC day_of_week = (INT d, m, y)INT: BEGIN INT j, k; j := y OVER 100; k := y MOD 100; (d + (m+1)*26 OVER 10 + k + k OVER 4 + j OVER 4 + 5*j) MOD 7 END # function day_of_week #; SKIP
END # program five_weekends #</lang> Output:
Mar 1901 Aug 1902 May 1903 Jan 1904 Jul 1904 ... Mar 2097 Aug 2098 May 2099 Jan 2100 Oct 2100 Number of months with five weekends between 1900 and 2100 = 201 Number of years between 1900 and 2100 with no five weekend months = 29
C
Not your typical method. Requires ncal
.
<lang c>#include <stdio.h>
- include <string.h>
int check_month(int y, int m) { char buf[1024], *ptr; int bytes, *a = &m;
sprintf(buf, "ncal -m %d -M %d", m, y); FILE *fp = popen(buf, "r"); if (!fp) return -1;
bytes = fread(buf, 1, 1024, fp); fclose(fp); buf[bytes] = 0;
- define check_day(x) \
ptr = strstr(buf, x);\ if (5 != sscanf(ptr, x" %d %d %d %d %d", a, a, a, a, a)) return 0
check_day("Fr"); check_day("Sa"); check_day("Su"); return 1; }
int main() { int y, m, cnt = 0; for (y = 1900; y <= 2100; y++) { for (m = 1; m <= 12; m++) { if (check_month(y, m) <= 0) continue; printf("%d-%02d ", y, m); if (++cnt % 16 == 0) printf("\n"); } } printf("\nTotal: %d\n", cnt);
return 0; }</lang>output<lang>1901-03 1902-08 1903-05 1904-01 1904-07 1905-12 1907-03 1908-05 1909-01 1909-10 1910-07 1911-12 1912-03 1913-08 1914-05 1915-01 . . . 2093-05 2094-01 2094-10 2095-07 2097-03 2098-08 2099-05 2100-01 2100-10 Total: 201</lang>
C++
<lang cpp>#include <vector>
- include <boost/date_time/gregorian/gregorian.hpp>
- include <algorithm>
- include <iostream>
- include <iterator>
using namespace boost::gregorian ;
void print( const date &d ) {
std::cout << d.year( ) << "-" << d.month( ) << "\n" ;
}
int main( ) {
greg_month longmonths[ ] = {Jan, Mar , May , Jul , Aug , Oct , Dec } ; int monthssize = sizeof ( longmonths ) / sizeof (greg_month ) ; typedef std::vector<date> DateVector ; DateVector weekendmonster ; std::vector<unsigned short> years_without_5we_months ; for ( unsigned short i = 1900 ; i < 2101 ; i++ ) { bool months_found = false ; //does a given year have 5 weekend months ? for ( int j = 0 ; j < monthssize ; j++ ) {
date d ( i , longmonths[ j ] , 1 ) ; if ( d.day_of_week( ) == Friday ) { //for the month to have 5 weekends weekendmonster.push_back( d ) ; if ( months_found == false ) months_found = true ;
} } if ( months_found == false ) {
years_without_5we_months.push_back( i ) ;
} } std::cout << "Between 1900 and 2100 , there are " << weekendmonster.size( ) << " months with 5 complete weekends!\n" ; std::cout << "Months with 5 complete weekends are:\n" ; std::for_each( weekendmonster.begin( ) , weekendmonster.end( ) , print ) ; std::cout << years_without_5we_months.size( ) << " years had no months with 5 complete weekends!\n" ; std::cout << "These are:\n" ; std::copy( years_without_5we_months.begin( ) , years_without_5we_months.end( ) ,
std::ostream_iterator<unsigned short>( std::cout , "\n" ) ) ;
std::cout << std::endl ; return 0 ;
}</lang> sample output:
Between 1900 and 2100 , there are 201 months with 5 complete weekends! Months with 5 complete weekends are: 1901-Mar 1902-Aug 1903-May 1904-Jan 1904-Jul 1905-Dec 1907-Mar 1908-May 1909-Jan 1909-Oct 1910-Jul 1911-Dec 1912-Mar 1913-Aug 1914-May 1915-Jan 1915-Oct 1916-Dec 1918-Mar 1919-Aug 1920-Oct 1921-Jul 1922-Dec 1924-Aug 1925-May 1926-Jan 1926-Oct 1927-Jul 1929-Mar 1930-Aug 1931-May 1932-Jan 1932-Jul 1933-Dec 1935-Mar 1936-May 1937-Jan 1937-Oct 1938-Jul 1939-Dec 1940-Mar 1941-Aug 1942-May 1943-Jan 1943-Oct 1944-Dec 1946-Mar 1947-Aug 1948-Oct 1949-Jul 1950-Dec 1952-Aug 1953-May 1954-Jan 1954-Oct 1955-Jul 1957-Mar 1958-Aug 1959-May 1960-Jan 1960-Jul 1961-Dec 1963-Mar 1964-May 1965-Jan 1965-Oct 1966-Jul 1967-Dec 1968-Mar 1969-Aug 1970-May 1971-Jan 1971-Oct 1972-Dec 1974-Mar 1975-Aug 1976-Oct 1977-Jul 1978-Dec 1980-Aug 1981-May 1982-Jan 1982-Oct 1983-Jul 1985-Mar 1986-Aug 1987-May 1988-Jan 1988-Jul 1989-Dec 1991-Mar 1992-May 1993-Jan 1993-Oct 1994-Jul 1995-Dec 1996-Mar 1997-Aug 1998-May 1999-Jan 1999-Oct 2000-Dec 2002-Mar 2003-Aug 2004-Oct 2005-Jul 2006-Dec 2008-Aug 2009-May 2010-Jan 2010-Oct 2011-Jul 2013-Mar 2014-Aug 2015-May 2016-Jan 2016-Jul 2017-Dec 2019-Mar 2020-May 2021-Jan 2021-Oct 2022-Jul 2023-Dec 2024-Mar 2025-Aug 2026-May 2027-Jan 2027-Oct 2028-Dec 2030-Mar 2031-Aug 2032-Oct 2033-Jul 2034-Dec 2036-Aug 2037-May 2038-Jan 2038-Oct 2039-Jul 2041-Mar 2042-Aug 2043-May 2044-Jan 2044-Jul 2045-Dec 2047-Mar 2048-May 2049-Jan 2049-Oct 2050-Jul 2051-Dec 2052-Mar 2053-Aug 2054-May 2055-Jan 2055-Oct 2056-Dec 2058-Mar 2059-Aug 2060-Oct 2061-Jul 2062-Dec 2064-Aug 2065-May 2066-Jan 2066-Oct 2067-Jul 2069-Mar 2070-Aug 2071-May 2072-Jan 2072-Jul 2073-Dec 2075-Mar 2076-May 2077-Jan 2077-Oct 2078-Jul 2079-Dec 2080-Mar 2081-Aug 2082-May 2083-Jan 2083-Oct 2084-Dec 2086-Mar 2087-Aug 2088-Oct 2089-Jul 2090-Dec 2092-Aug 2093-May 2094-Jan 2094-Oct 2095-Jul 2097-Mar 2098-Aug 2099-May 2100-Jan 2100-Oct 29 years had no months with 5 complete weekends! These are: 1900 1906 1917 1923 1928 1934 1945 1951 1956 1962 1973 1979 1984 1990 2001 2007 2012 2018 2029 2035 2040 2046 2057 2063 2068 2074 2085 2091 2096
C#
<lang csharp>using System;
namespace _5_Weekends {
class Program { const int FIRST_YEAR = 1900; const int LAST_YEAR = 2100; static int[] _31_MONTHS = { 1, 3, 5, 7, 8, 10, 12 };
static void Main(string[] args) { int totalNum = 0; int totalNo5Weekends = 0;
for (int year = FIRST_YEAR; year <= LAST_YEAR; year++) { bool has5Weekends = false;
foreach (int month in _31_MONTHS) { DateTime firstDay = new DateTime(year, month, 1); if (firstDay.DayOfWeek == DayOfWeek.Friday) { totalNum++; has5Weekends = true; Console.WriteLine(firstDay.ToString("yyyy - MMMM")); } }
if (!has5Weekends) totalNo5Weekends++; } Console.WriteLine("Total 5-weekend months between {0} and {1}: {2}", FIRST_YEAR, LAST_YEAR, totalNum); Console.WriteLine("Total number of years with no 5-weekend months {0}", totalNo5Weekends); } }
}</lang> Output
1901 - March 1902 - August 1903 - May 1904 - January 1904 - July 1905 - December ... 2095 - July 2097 - March 2098 - August 2099 - May 2100 - January 2100 - October Total 5-weekend months between 1900 and 2100: 201 Total number of years with no 5-weekend months 29
Clojure
<lang Clojure>(import java.util.GregorianCalendar java.text.DateFormatSymbols)
(->> (for [year (range 1900 2101) month [0 2 4 6 7 9 11] ;; 31 day months :let [cal (GregorianCalendar. year month 1) day (.get cal GregorianCalendar/DAY_OF_WEEK)] :when (= day GregorianCalendar/FRIDAY)]
(println month "-" year)) count (println "Total Months: " ,))</lang>
D
<lang d>import std.stdio, std.datetime, std.algorithm, std.range;
auto m5w(Date start=Date(1900,1,1), Date end=Date(2100,12,31)) {
Date[] res; // adjust to 1st day for (Date when = Date(start.year, start.month, 1); when < end; when.add!"months"(1)) {
if (when.endOfMonthDay == 31 && // Such month must have 3+4*7 when.dayOfWeek == 5) // days and start at friday res ~= when; // for 5 FULL weekends. } return res;
}
bool noM5wByYear(int year) {
return m5w(Date(year, 1, 1), Date(year, 12, 31)).length == 0;
}
void main() {
auto m = m5w(); // use default input writeln("There are ", m.length, " months of which the first and last five are:"); foreach (d; m[0 .. 5] ~ m[$ - 5 .. $]) writeln(d.toSimpleString[0 .. $-2]);
auto noM5w = filter!noM5wByYear(iota(1900, 2101)); writeln("There are ", walkLength(noM5w), " years in the ", "range that do not have months with five weekends");
}</lang> Output:
There are 201 months of which the first and last five are: 1901-Mar- 1902-Aug- 1903-May- 1904-Jan- 1904-Jul- 2097-Mar- 2098-Aug- 2099-May- 2100-Jan- 2100-Oct- There are 29 years in the range that do not have months with five weekends
Delphi
<lang delphi>program FiveWeekends;
{$APPTYPE CONSOLE}
uses SysUtils, DateUtils;
var
lMonth, lYear: Integer; lDate: TDateTime; lFiveWeekendCount: Integer; lYearsWithout: Integer; lFiveWeekendFound: Boolean;
begin
for lYear := 1900 to 2100 do begin lFiveWeekendFound := False; for lMonth := 1 to 12 do begin lDate := EncodeDate(lYear, lMonth, 1); if (DaysInMonth(lDate) = 31) and (DayOfTheWeek(lDate) = DayFriday) then begin Writeln(FormatDateTime('mmm yyyy', lDate)); Inc(lFiveWeekendCount); lFiveWeekendFound := True; end; end; if not lFiveWeekendFound then Inc(lYearsWithout); end;
Writeln; Writeln(Format('Months with 5 weekends: %d', [lFiveWeekendCount])); Writeln(Format('Years with no 5 weekend months: %d', [lYearsWithout]));
end.</lang>
Erlang
Two examples, both based on first building a nested list-of-lists like [Year1, Year2, ..., YearN], where each year is a sublist of year and month tuples, like [{YearN, 1}, {YearN, 2}, ..., {YearN, 12}].
First, a pretty compact example intended for use with escript:
<lang erlang>
- !/usr/bin/env escript
%% %% Calculate number of months with five weekends between years 1900-2100 %% main(_) ->
Years = [ [{Y,M} || M <- lists:seq(1,12)] || Y <- lists:seq(1900,2100) ], {CountedYears, {Has5W, TotM5W}} = lists:mapfoldl( fun(Months, {Has5W, Tot}) -> WithFive = [M || M <- Months, has_five(M)], CountM5W = length(WithFive), {{Months,CountM5W}, {Has5W++WithFive, Tot+CountM5W}} end, {[], 0}, Years), io:format("There are ~p months with five full weekends.~n" "Showing top and bottom 5:~n", [TotM5W]), lists:map(fun({Y,M}) -> io:format("~p-~p~n", [Y,M]) end, lists:sublist(Has5W,1,5) ++ lists:nthtail(TotM5W-5, Has5W)), No5W = [Y || {[{Y,_M}|_], 0} <- CountedYears], io:format("The following ~p years do NOT have any five-weekend months:~n", [length(No5W)]), lists:map(fun(Y) -> io:format("~p~n", [Y]) end, No5W).
has_five({Year, Month}) ->
has_five({Year, Month}, calendar:last_day_of_the_month(Year, Month)).
has_five({Year, Month}, Days) when Days =:= 31 ->
calendar:day_of_the_week({Year, Month, 1}) =:= 5;
has_five({_Year, _Month}, _DaysNot31) ->
false.
</lang> Second, a more verbose Erlang module: <lang erlang> -module(five_weekends).
-export([report/0, print_5w_month/1, print_year_with_no_5w_month/1]).
report() ->
Years = make_nested_period_list(1900, 2100), {CountedYears, {All5WMonths, CountOf5WMonths}} = lists:mapfoldl( fun(SingleYearSublist, {All5WMonths, CountOf5WMonths}) -> MonthsWith5W = [Month || Month <- SingleYearSublist, if_has_5w(Month)], CountOf5WMonthsFor1Year = length(MonthsWith5W), { % Result of map for this year sublist: {SingleYearSublist,CountOf5WMonthsFor1Year}, % Accumulate total result for our fold: {All5WMonths ++ MonthsWith5W, CountOf5WMonths + CountOf5WMonthsFor1Year} } end, {[], 0}, Years), io:format("There are ~p months with five full weekends.~n" "Showing top and bottom 5:~n", [CountOf5WMonths]), lists:map(fun print_5w_month/1, take_nth_first_and_last(5, All5WMonths)), YearsWithout5WMonths = find_years_without_5w_months(CountedYears), io:format("The following ~p years do NOT have any five-weekend months:~n", [length(YearsWithout5WMonths)]), lists:map(fun print_year_with_no_5w_month/1, YearsWithout5WMonths).
make_nested_period_list(FromYear, ToYear) ->
[ make_monthtuple_sublist_for_year(Year) || Year <- lists:seq(FromYear, ToYear) ].
make_monthtuple_sublist_for_year(Year) ->
[ {Year, Month} || Month <- lists:seq(1,12) ].
if_has_5w({Year, Month}) ->
if_has_5w({Year, Month}, calendar:last_day_of_the_month(Year, Month)).
if_has_5w({Year, Month}, Days) when Days =:= 31 ->
calendar:day_of_the_week({Year, Month, 1}) =:= 5;
if_has_5w({_Year, _Month}, _DaysNot31) ->
false.
print_5w_month({Year, Month}) ->
io:format("~p-~p~n", [Year, Month]).
print_year_with_no_5w_month(Year) ->
io:format("~p~n", [Year]).
take_nth_first_and_last(N, List) ->
Len = length(List), lists:sublist(List, 1, N) ++ lists:nthtail(Len - N, List).
find_years_without_5w_months(List) ->
[Y || {[{Y,_M}|_], 0} <- List].
</lang> Output
There are 201 months with five full weekends. Showing top and bottom 5: 1901-3 1902-8 1903-5 1904-1 1904-7 2097-3 2098-8 2099-5 2100-1 2100-10 The following 29 years do NOT have any five-weekend months: 1900 1906 1917 1923 1928 1934 1945 1951 1956 1962 1973 1979 1984 1990 2001 2007 2012 2018 2029 2035 2040 2046 2057 2063 2068 2074 2085 2091 2096
Fortran
Using Zeller's congruence <lang fortran>program Five_weekends
implicit none
integer :: m, year, nfives = 0, not5 = 0 logical :: no5weekend
type month integer :: n character(3) :: name end type month
type(month) :: month31(7) month31(1) = month(13, "Jan") month31(2) = month(3, "Mar") month31(3) = month(5, "May") month31(4) = month(7, "Jul") month31(5) = month(8, "Aug") month31(6) = month(10, "Oct") month31(7) = month(12, "Dec")
do year = 1900, 2100 no5weekend = .true. do m = 1, size(month31) if(month31(m)%n == 13) then if(Day_of_week(1, month31(m)%n, year-1) == 6) then write(*, "(a3, i5)") month31(m)%name, year nfives = nfives + 1 no5weekend = .false. end if else if(Day_of_week(1, month31(m)%n, year) == 6) then write(*,"(a3, i5)") month31(m)%name, year nfives = nfives + 1 no5weekend = .false. end if end if end do if(no5weekend) not5 = not5 + 1 end do write(*, "(a, i0)") "Number of months with five weekends between 1900 and 2100 = ", nfives write(*, "(a, i0)") "Number of years between 1900 and 2100 with no five weekend months = ", not5
contains
function Day_of_week(d, m, y)
integer :: Day_of_week integer, intent(in) :: d, m, y integer :: j, k j = y / 100 k = mod(y, 100) Day_of_week = mod(d + (m+1)*26/10 + k + k/4 + j/4 + 5*j, 7)
end function Day_of_week end program Five_weekends</lang> Output
Mar 1901 Aug 1902 May 1903 Jan 1904 Jul 1904 ... Mar 2097 Aug 2098 May 2099 Jan 2100 Oct 2100 Number of months with five weekends between 1900 and 2100 = 201 Number of years between 1900 and 2100 with no five weekend months = 29
GAP
<lang gap># return a list of two lists :
- first is the list of months with five weekends between years y1 and y2 (included)
- second is the list of years without such months, in the same interval
FiveWeekends := function(y1, y2)
local L, yL, badL, d, m, y; L := [ ]; badL := [ ]; for y in [y1 .. y2] do yL := [ ]; for m in [1, 3, 5, 7, 8, 10, 12] do if WeekDay([1, m, y]) = "Fri" then d := StringDate([1, m, y]); Add(yL, d{[4 .. 11]}); fi; od; if Length(yL) = 0 then Add(badL, y); else Append(L, yL); fi; od; return [ L, badL ];
end;
r := FiveWeekends(1900, 2100);; n := Length(r[1]);
- 201
Length(r[2]);
- 29
r[1]{[1 .. 5]};
- [ "Mar-1901", "Aug-1902", "May-1903", "Jan-1904", "Jul-1904" ]
r[1]{[n-4 .. n]};
- [ "Mar-2097", "Aug-2098", "May-2099", "Jan-2100", "Oct-2100" ]</lang>
Go
<lang go>package main
import (
"fmt" "time"
)
func main() {
var n int var haveNone []int64 fmt.Println("Months with five weekends:") for y := int64(1900); y <= 2100; y++ { var hasOne bool // for the extra credit for _, m := range []int{1, 3, 5, 7, 8, 10, 12} { t := &time.Time{Year: y, Month: m, Day: 1} t = time.SecondsToUTC(t.Seconds()) // computes weekday if t.Weekday == time.Friday { fmt.Println(" ", t.Format("2006 January")) n++ hasOne = true } } if !hasOne { haveNone = append(haveNone, y) } } fmt.Println(n, "total\n") fmt.Println("Extra credit: years with no months with five weekends:") for _, y := range haveNone { fmt.Println(" ", y) } fmt.Println(len(haveNone), "total")
}</lang> Output:
Months with five weekends: 1901 March 1902 August 1903 May 1904 January 1904 July ... 2097 March 2098 August 2099 May 2100 January 2100 October 201 total Extra credit: years with no months with five weekends: 1900 1906 1917 1923 1928 ... 2068 2074 2085 2091 2096 29 total
Inform 7
Inform 7 has no built-in date functions, so this solution implements date types and a day-of-week function.
<lang inform7>Calendar is a room.
When play begins: let happy month count be 0; let sad year count be 0; repeat with Y running from Y1900 to Y2100: if Y is a sad year, increment the sad year count; repeat with M running through months: if M of Y is a happy month: say "[M] [year number of Y]."; increment the happy month count; say "Found [happy month count] month[s] with five weekends and [sad year count] year[s] with no such months."; end the story.
Section - Years
A year is a kind of value. Y1 specifies a year.
To decide which number is year number of (Y - year): decide on Y / Y1.
To decide if (N - number) is divisible by (M - number): decide on whether or not the remainder after dividing N by M is zero.
Definition: a year (called Y) is a leap year: let YN be the year number of Y; if YN is divisible by 400, yes; if YN is divisible by 100, no; if YN is divisible by 4, yes; no.
Section - Months
A month is a kind of value. The months are defined by the Table of Months.
Table of Months month month number January 1 February 2 March 3 April 4 May 5 June 6 July 7 August 8 September 9 October 10 November 11 December 12
A month has a number called length. The length of a month is usually 31. September, April, June, and November have length 30. February has length 28.
To decide which number is number of days in (M - month) of (Y - year): let L be the length of M; if M is February and Y is a leap year, decide on L + 1; otherwise decide on L.
Section - Weekdays
A weekday is a kind of value. The weekdays are defined by the Table of Weekdays.
Table of Weekdays weekday weekday number Saturday 0 Sunday 1 Monday 2 Tuesday 3 Wednesday 4 Thursday 5 Friday 6
To decide which weekday is weekday of the/-- (N - number) of (M - month) of (Y - year): let MN be the month number of M; let YN be the year number of Y; if MN is less than 3: increase MN by 12; decrease YN by 1; let h be given by Zeller's Congruence; let WDN be the remainder after dividing h by 7; decide on the weekday corresponding to a weekday number of WDN in the Table of Weekdays.
Equation - Zeller's Congruence h = N + ((MN + 1)*26)/10 + YN + YN/4 + 6*(YN/100) + YN/400 where h is a number, N is a number, MN is a number, and YN is a number.
To decide which number is number of (W - weekday) days in (M - month) of (Y - year): let count be 0; repeat with N running from 1 to the number of days in M of Y: if W is the weekday of the N of M of Y, increment count; decide on count.
Section - Happy Months and Sad Years
To decide if (M - month) of (Y - year) is a happy month: if the number of days in M of Y is 31 and the weekday of the 1st of M of Y is Friday, decide yes; decide no.
To decide if (Y - year) is a sad year: repeat with M running through months: if M of Y is a happy month, decide no; decide yes.</lang>
Output:
March 1901. August 1902. May 1903. January 1904. July 1904. ... March 2097. August 2098. May 2099. January 2100. October 2100. Found 201 months with five weekends and 29 years with no such months.
J
<lang j>require 'types/datetime numeric' find5wkdMonths=: verb define
years=. range 2{. y months=. 1 3 5 7 8 10 12 m5w=. (#~ 0 = weekday) >,{years;months;31 NB. 5 full weekends iff 31st is Sunday(0) >'MMM YYYY' fmtDate toDayNo m5w
)</lang> Usage: <lang j> # find5wkdMonths 1900 2100 NB. number of months found 201
(5&{. , '...' , _5&{.) find5wkdMonths 1900 2100 NB. First and last 5 months found
Mar 1901 Aug 1902 May 1903 Jan 1904 Jul 1904 ... Mar 2097 Aug 2098 May 2099 Jan 2100 Oct 2100
# (range -. {:"1@(_ ". find5wkdMonths)) 1900 2100 NB. number of years without 5 weekend months
29</lang>
Java
In Java 1.5+ you can add import static java.util.Calendar.*;
to the list of imports and remove all other occurrences of Calendar.
from the rest of the code (e.g. Calendar.FRIDAY
would simply become FRIDAY
). It's more portable (and probably more clear) to leave the Calendar.
's in.
<lang java>import java.util.Calendar;
import java.util.GregorianCalendar;
public class FiveFSS {
private static boolean[] years = new boolean[201]; //dreizig tage habt september... private static int[] month31 = {Calendar.JANUARY, Calendar.MARCH, Calendar.MAY, Calendar.JULY, Calendar.AUGUST, Calendar.OCTOBER, Calendar.DECEMBER};
public static void main(String[] args) { StringBuilder months = new StringBuilder(); int numMonths = 0; for (int year = 1900; year <= 2100; year++) { for (int month : month31) { Calendar date = new GregorianCalendar(year, month, 1); if (date.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) { years[year - 1900] = true; numMonths++; //months are 0-indexed in Calendar months.append((date.get(Calendar.MONTH) + 1) + "-" + year +"\n"); } } } System.out.println("There are "+numMonths+" months with five weekends from 1900 through 2100:"); System.out.println(months); System.out.println("Years with no five-weekend months:"); for (int year = 1900; year <= 2100; year++) { if(!years[year - 1900]){ System.out.println(year); } } }
}</lang> Output (middle results cut out):
There are 201 months with five weekends from 1900 through 2100: 3-1901 8-1902 5-1903 1-1904 7-1904 12-1905 3-1907 5-1908 1-1909 10-1909 7-1910 ... 12-2090 8-2092 5-2093 1-2094 10-2094 7-2095 3-2097 8-2098 5-2099 1-2100 10-2100 Years with no five-weekend months: 1900 1906 1917 1923 1928 1934 1945 1951 1956 1962 1973 1979 1984 1990 2001 2007 2012 2018 2029 2035 2040 2046 2057 2063 2068 2074 2085 2091 2096
JavaScript
<lang javascript>function startsOnFriday(month, year) {
// 0 is Sunday, 1 is Monday, ... 5 is Friday, 6 is Saturday return new Date(year, month, 1).getDay() === 5;
} function has31Days(month, year) {
return new Date(year, month, 31).getDate() === 31;
} function checkMonths(year) {
var month, count = 0; for (month = 0; month < 12; month += 1) { if (startsOnFriday(month, year) && has31Days(month, year)) { count += 1; document.write(year + ' ' + month + '
'); } } return count;
} function fiveWeekends() {
var startYear = 1900, endYear = 2100, year, monthTotal = 0, yearsWithoutFiveWeekends = [], total = 0; for (year = startYear; year <= endYear; year += 1) { monthTotal = checkMonths(year); total += monthTotal; // extra credit if (monthTotal === 0) yearsWithoutFiveWeekends.push(year); } document.write('Total number of months: ' + total + '
'); document.write('
'); document.write(yearsWithoutFiveWeekends + '
'); document.write('Years with no five-weekend months: ' + yearsWithoutFiveWeekends.length + '
');
} fiveWeekends();</lang>
Sample output:
1901 2 1902 7 1903 4 1904 0 1904 6 ... 2097 2 2098 7 2099 4 2100 0 2100 9 Total number of months: 201 1900,1906,1917,1923,1928,1934,1945,1951,1956,1962,1973,1979,1984,1990,2001,2007,2012,2018,2029,2035,2040,2046,2057,2063,2068,2074,2085,2091,2096 Years with no five-weekend months: 29
k
<lang k> cal_j:(_jd[19000101]+!(-/_jd 21010101 19000101)) / enumerate the calendar is_we:(cal_j!7) _lin 4 5 6 / identify friday saturdays and sundays m:__dj[cal_j]%100 / label the months mi:&15=+/'is_we[=m] / group by month and sum the weekend days `0:,"There are ",($#mi)," months with five weekends" m5:(?m)[mi] `0:$5#m5 `0:,"..." `0:$-5#m5 y:1900+!201 / enumerate the years in the range y5:?_ m5%100 / label the years of the months yn5:y@&~y _lin y5 / find any years not in the 5 weekend month list `0:,"There are ",($#yn5)," years without any five-weekend months" `0:,1_,/",",/:$yn5</lang> Output:
There are 201 months with five weekends 190103 190208 190305 190401 190407 ... 209703 209808 209905 210001 210010 There are 29 years without any five-weekend months 1900,1906,1917,1923,1928,1934,1945,1951,1956,1962,1973,1979,1984,1990,2001,2007,2012,2018,2029,2035,2040,2046,2057,2063,2068,2074,2085,2091,2096
MUMPS
<lang MUMPS> FIVE
;List and count the months between 1/1900 and 12/2100 that have 5 full weekends ;Extra credit - list and count years with no months with five full weekends ;Using the test that the 31st of a month is on a Sunday ;Uses the VA's public domain routine %DTC (Part of the Kernel) named here DIDTC NEW YEAR,MONTH,X,Y,CNTMON,NOT,NOTLIST ; YEAR is the year we're testing ; MONTH is the month we're testing ; X is the date in "internal" format, as an input to DOW^DIDTC ; Y is the day of the week (0=Sunday, 1=Monday...) output from DOW^DIDTC ; CNTMON is a count of the months that have 5 full weekends ; NOT is a flag if there were no months with 5 full weekends yet that year ; NOTLIST is a list of years that do not have any months with 5 full weekends SET CNTMON=0,NOTLIST="" WRITE !!,"The following months have five full weekends:" FOR YEAR=200:1:400 DO ;years since 12/31/1700 epoch . SET NOT=0 . FOR MONTH="01","03","05","07","08","10","12" DO . . SET X=YEAR_MONTH_"31" . . DO DOW^DIDTC . . IF (Y=0) DO . . . SET NOT=NOT+1,CNTMON=CNTMON+1 . . . WRITE !,MONTH_"-"_(YEAR+1700) . SET:(NOT=0) NOTLIST=NOTLIST_$SELECT($LENGTH(NOTLIST)>1:",",1:"")_(YEAR+1700) WRITE !,"For a total of "_CNTMON_" months." WRITE !!,"There are "_$LENGTH(NOTLIST,",")_" years with no five full weekends in any month." WRITE !,"They are: "_NOTLIST KILL YEAR,MONTH,X,Y,CNTMON,NOT,NOTLIST QUIT
F ;Same logic as the main entry point, shortened format
N R,M,X,Y,C,N,L S C=0,L="" W !!,"The following months have five full weekends:" F R=200:1:400 D . S N=0 F M="01","03","05","07","08","10","12" S X=R_M_"31" D DOW^DIDTC I 'Y S N=N+1,C=C+1 W !,M_"-"_(R+1700) . S:'N L=L_$S($L(L):",",1:"")_(R+1700) W !,"For a total of "_C_" months.",!!,"There are "_$L(L,",")_" years with no five full weekends in any month.",!,"They are: "_L
Q</lang>Usage:
USER>d ^FIVE The following months have five full weekends: 03-1901 08-1902 05-1903 01-1904 07-1904 12-1905 . . . . . . 01-2094 10-2094 07-2095 03-2097 08-2098 05-2099 01-2100 10-2100 For a total of 201 months. There are 29 years with no five full weekends in any month. They are: 1900,1906,1917,1923,1928,1934,1945,1951,1956,1962,1973,1979,1984,1990,2001,2007,2012,2018,2029,2035,2040,2046,2057,2063,2068,2074,2085,2091,2096
Pascal
See Delphi
Perl
<lang perl>#!/usr/bin/perl -w use DateTime ;
my @happymonths ; my @workhardyears ; my @longmonths = ( 1 , 3 , 5 , 7 , 8 , 10 , 12 ) ; my @years = 1900..2100 ; foreach my $year ( @years ) {
my $countmonths = 0 ; foreach my $month ( @longmonths ) { my $dt = DateTime->new( year => $year ,
month => $month , day => 1 ) ;
if ( $dt->day_of_week == 5 ) {
$countmonths++ ; my $yearfound = $dt->year ; my $monthfound = $dt->month_name ; push ( @happymonths , "$yearfound $monthfound" ) ;
} } if ( $countmonths == 0 ) { push ( @workhardyears, $year ) ; }
} print "There are " . @happymonths . " months with 5 full weekends!\n" ; print "The first 5 and the last 5 of them are:\n" ; foreach my $i ( 0..4 ) {
print "$happymonths[ $i ]\n" ;
} foreach my $i ( -5..-1 ) {
print "$happymonths[ $i ]\n" ;
} print "No long weekends in the following " . @workhardyears . " years:\n" ; map { print "$_\n" } @workhardyears ;</lang> Output:
There are 201 months with 5 full weekends! The first 5 and the last 5 of them are: 1901 March 1902 August 1903 May 1904 January 1904 July 2097 March 2098 August 2099 May 2100 January 2100 October No 5 weekends per month in the following 29 years: 1900 1906 1917 1923 1928 1934 1945 1951 1956 1962 1973 1979 1984 1990 2001 2007 2012 2018 2029 2035 2040 2046 2057 2063 2068 2074 2085 2091 2096
Perl 6
<lang perl6># A month has 5 weekends iff it has 31 days and starts on Friday.
my @years = 1900 .. 2100; my @ym = @years X 1, 3, 5, 7, 8, 10, 12; # Months with 31 days
my @happy = @ym.map({ Date.new: $^a, $^b, 1 }).grep: { .day-of-week == 5 };
say 'Happy month count: ', +@happy; say 'First happy months: ' ~ @happy[^5]; say 'Last happy months: ' ~ @happy[*-5 .. *]; say 'Dreary years count: ', @years - @happy».year.uniq;</lang>
Output:
Happy month count: 201 First happy months: 1901-03-01 1902-08-01 1903-05-01 1904-01-01 1904-07-01 Last happy months: 2097-03-01 2098-08-01 2099-05-01 2100-01-01 2100-10-01 Dreary years count: 29
PicoLisp
<lang PicoLisp>(setq Lst
(make (for Y (range 1900 2100) (for M (range 1 12) (and (date Y M 31) (= "Friday" (day (date Y M 1))) (link (list (get *Mon M) Y)) ) ) ) ) )
(prinl "There are " (length Lst) " months with five weekends:") (mapc println (head 5 Lst)) (prinl "...") (mapc println (tail 5 Lst)) (prinl) (setq Lst (diff (range 1900 2100) (uniq (mapcar cadr Lst)))) (prinl "There are " (length Lst) " years with no five-weekend months:") (println Lst)</lang> Output:
There are 201 months with five weekends: (Mar 1901) (Aug 1902) (May 1903) (Jan 1904) (Jul 1904) ... (Mar 2097) (Aug 2098) (May 2099) (Jan 2100) (Oct 2100) There are 29 years with no five-weekend months: (1900 1906 1917 1923 1928 1934 1945 1951 1956 1962 1973 1979 1984 1990 2001 2007 2012 2018 2029 2035 2040 2046 2057 2063 2068 2074 2085 2091 2096)
PureBasic
<lang PureBasic>Procedure DateG(year.w, month.b, day)
;Returns the number of days before or after the earliest reference date ;in PureBasic's Date Library (1 Jan 1970) based on an assumed Gregorian calendar calculation Protected days days = (year) * 365 + (month - 1) * 31 + day - 1 - 719527 ;DAYS_UNTIL_1970_01_01 = 719527 If month >= 3 days - Int(0.4 * month + 2.3) Else year - 1 EndIf days + Int(year/4) - Int(year/100) + Int(year/400) ProcedureReturn days
EndProcedure
Procedure startsOnFriday(year, month)
;0 is Sunday, 1 is Monday, ... 5 is Friday, 6 is Saturday Protected referenceDay = DayOfWeek(Date(1970, 1, 1, 0, 0, 0)) ;link to the first day in the PureBasic's date library Protected resultDay = (((DateG(year, month, 1) + referenceDay) % 7) + 7) % 7 If resultDay = 5 ProcedureReturn #True EndIf
EndProcedure
Procedure has31Days(month)
Select month Case 1, 3, 5, 7 To 8, 10, 12 ProcedureReturn #True EndSelect
EndProcedure
Procedure checkMonths(year)
Protected month, count For month = 1 To 12 If startsOnFriday(year, month) And has31Days(month) count + 1 PrintN(Str(year) + " " + Str(month)) EndIf Next ProcedureReturn count
EndProcedure
Procedure fiveWeekends()
Protected startYear = 1900, endYear = 2100, year, monthTotal, total NewList yearsWithoutFiveWeekends() For year = startYear To endYear monthTotal = checkMonths(year) total + monthTotal ;extra credit If monthTotal = 0 AddElement(yearsWithoutFiveWeekends()) yearsWithoutFiveWeekends() = year EndIf Next PrintN("Total number of months: " + Str(total) + #CRLF$) PrintN("Years with no five-weekend months: " + Str(ListSize(yearsWithoutFiveWeekends())) )
EndProcedure
If OpenConsole()
fiveWeekends() Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input() CloseConsole()
EndIf</lang> Sample output:
1901 3 1902 8 1903 5 1904 1 1904 7 . .(output clipped) . 2097 3 2098 8 2099 5 2100 1 2100 10 Total number of months: 201 Years with no five-weekend months: 29
Python
<lang python>from datetime import timedelta, date
DAY = timedelta(days=1) START, STOP = date(1900, 1, 1), date(2101, 1, 1) WEEKEND = {6, 5, 4} # Sunday is day 6 FMT = '%Y %m(%B)'
def fiveweekendspermonth(start=START, stop=STOP):
'Compute months with five weekends between dates' when = start lastmonth = weekenddays = 0 fiveweekends = [] while when < stop: year, mon, _mday, _h, _m, _s, wday, _yday, _isdst = when.timetuple() if mon != lastmonth: if weekenddays >= 15: fiveweekends.append(when - DAY) weekenddays = 0 lastmonth = mon if wday in WEEKEND: weekenddays += 1 when += DAY return fiveweekends
dates = fiveweekendspermonth() indent = ' ' print('There are %s months of which the first and last five are:' % len(dates)) print(indent +('\n'+indent).join(d.strftime(FMT) for d in dates[:5])) print(indent +'...') print(indent +('\n'+indent).join(d.strftime(FMT) for d in dates[-5:]))
print('\nThere are %i years in the range that do not have months with five weekends'
% len(set(range(START.year, STOP.year)) - {d.year for d in dates}))</lang>
Alternate Algorithm
The condition is equivalent to having a thirty-one day month in which the last day of the month is a Sunday. <lang python>LONGMONTHS = (1, 3, 5, 7, 8, 10, 12) # Jan Mar May Jul Aug Oct Dec def fiveweekendspermonth2(start=START, stop=STOP):
return [date(yr, month, 31) for yr in range(START.year, STOP.year) for month in LONGMONTHS if date(yr, month, 31).timetuple()[6] == 6 # Sunday ]
dates2 = fiveweekendspermonth2() assert dates2 == dates</lang>
Sample Output
There are 201 months of which the first and last five are: 1901 03(March) 1902 08(August) 1903 05(May) 1904 01(January) 1904 07(July) ... 2097 03(March) 2098 08(August) 2099 05(May) 2100 01(January) 2100 10(October) There are 29 years in the range that do not have months with five weekends
REXX
version 1
This version uses the latest enhancements to the DATE built-in function.
Not all REXX interpreters support this feature.
Programming justification note: the inclusion of leapyear checking is present even though it wasn't needed as
February can be excluded from the criteria of having five weekends. Having the leapyear routine included
allows for a general-purpose strategem of solving these types of problems without taking shortcuts to the
solution (although shortcuts are generaly desireable). If there is a change in the criteria, the
support for more (or less) checks can be supported easily, as well as supporting more criterium.
<lang rexx>
/*REXX program finds months with 5 weekends in them (given a date range)*/
parse arg yStart yStop . if yStart== then yStart=1900 if yStop == then yStop =2100 years=ystop-yStart+1 month. =31 /*month days, Feb. is done later.*/ month.4 =30 month.6 =30 month.9 =30 month.11=30 haps=0 /*num of five weekends happenings*/ yr5.=0 /*if a year has any five-weekends*/
do y=yStart to yStop /*process the years specified. */ do m=1 for 12; mm=right(m,2,0) /*process each month in each year*/ if m==2 then month.2=28+leapyear(y) /*handle num of days in Feb*/ wd.=0 do d=1 for month.m; dd=right(d,2,0) dat_=y"-"mm'-'dd _=left(date('W',dat_,"I"),2); upper _ wd._=wd._+1 /* _ is first 2 chars of weekday.*/ end /*d*/ if wd.su\==5 | wd.fr\==5 | wd.sa\==5 then iterate /*5 weekends ?*/ haps=haps+1 /*bump counter*/ say 'There are five weekends in' y date('M',dat_,"I") yr5.y=1 /*indicate this year has one. */ end /*m*/ end /*y*/
say say 'There were' haps "occurance"s(haps) 'of five-weekend months in',
"year"s(years) yStart'-->'yStop
say no5s=0
do y=yStart to yStop if yr5.y then iterate no5s=no5s+1 say y "doesn't have any five-weekend months." end
say say "There are" no5s 'year's(no5s),
"that haven't any five-weekend months in year"s(years) yStart'-->'yStop
exit
/*─────────────────────────────────────LEAPYEAR subroutine──────────────*/
leapyear: procedure; arg y /*year could be: Y, YY, YYY, YYYY*/
if length(y)==2 then y=left(right(date(),4),2)y /*adjust for YY year.*/
if y//4\==0 then return 0 /* not ≈ by 4? Not a leapyear.*/
return y//100\==0 | y//400==0 /*apply 100 and 400 year rule. */
/*─────────────────────────────────────S subroutine (for plurals)───────*/
s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1)
</lang>
Output:
There are five weekends in 1901 March There are five weekends in 1902 August There are five weekends in 1903 May There are five weekends in 1904 January There are five weekends in 1904 July There are five weekends in 1905 December There are five weekends in 1907 March There are five weekends in 1908 May There are five weekends in 1909 January There are five weekends in 1909 October There are five weekends in 1910 July There are five weekends in 1911 December There are five weekends in 1912 March There are five weekends in 1913 August There are five weekends in 1914 May There are five weekends in 1915 January There are five weekends in 1915 October There are five weekends in 1916 December There are five weekends in 1918 March There are five weekends in 1919 August There are five weekends in 1920 October There are five weekends in 1921 July There are five weekends in 1922 December There are five weekends in 1924 August There are five weekends in 1925 May There are five weekends in 1926 January There are five weekends in 1926 October There are five weekends in 1927 July There are five weekends in 1929 March There are five weekends in 1930 August There are five weekends in 1931 May There are five weekends in 1932 January There are five weekends in 1932 July There are five weekends in 1933 December There are five weekends in 1935 March There are five weekends in 1936 May There are five weekends in 1937 January There are five weekends in 1937 October There are five weekends in 1938 July There are five weekends in 1939 December There are five weekends in 1940 March There are five weekends in 1941 August There are five weekends in 1942 May There are five weekends in 1943 January There are five weekends in 1943 October There are five weekends in 1944 December There are five weekends in 1946 March There are five weekends in 1947 August There are five weekends in 1948 October There are five weekends in 1949 July There are five weekends in 1950 December There are five weekends in 1952 August There are five weekends in 1953 May There are five weekends in 1954 January There are five weekends in 1954 October There are five weekends in 1955 July There are five weekends in 1957 March There are five weekends in 1958 August There are five weekends in 1959 May There are five weekends in 1960 January There are five weekends in 1960 July There are five weekends in 1961 December There are five weekends in 1963 March There are five weekends in 1964 May There are five weekends in 1965 January There are five weekends in 1965 October There are five weekends in 1966 July There are five weekends in 1967 December There are five weekends in 1968 March There are five weekends in 1969 August There are five weekends in 1970 May There are five weekends in 1971 January There are five weekends in 1971 October There are five weekends in 1972 December There are five weekends in 1974 March There are five weekends in 1975 August There are five weekends in 1976 October There are five weekends in 1977 July There are five weekends in 1978 December There are five weekends in 1980 August There are five weekends in 1981 May There are five weekends in 1982 January There are five weekends in 1982 October There are five weekends in 1983 July There are five weekends in 1985 March There are five weekends in 1986 August There are five weekends in 1987 May There are five weekends in 1988 January There are five weekends in 1988 July There are five weekends in 1989 December There are five weekends in 1991 March There are five weekends in 1992 May There are five weekends in 1993 January There are five weekends in 1993 October There are five weekends in 1994 July There are five weekends in 1995 December There are five weekends in 1996 March There are five weekends in 1997 August There are five weekends in 1998 May There are five weekends in 1999 January There are five weekends in 1999 October There are five weekends in 2000 December There are five weekends in 2002 March There are five weekends in 2003 August There are five weekends in 2004 October There are five weekends in 2005 July There are five weekends in 2006 December There are five weekends in 2008 August There are five weekends in 2009 May There are five weekends in 2010 January There are five weekends in 2010 October There are five weekends in 2011 July There are five weekends in 2013 March There are five weekends in 2014 August There are five weekends in 2015 May There are five weekends in 2016 January There are five weekends in 2016 July There are five weekends in 2017 December There are five weekends in 2019 March There are five weekends in 2020 May There are five weekends in 2021 January There are five weekends in 2021 October There are five weekends in 2022 July There are five weekends in 2023 December There are five weekends in 2024 March There are five weekends in 2025 August There are five weekends in 2026 May There are five weekends in 2027 January There are five weekends in 2027 October There are five weekends in 2028 December There are five weekends in 2030 March There are five weekends in 2031 August There are five weekends in 2032 October There are five weekends in 2033 July There are five weekends in 2034 December There are five weekends in 2036 August There are five weekends in 2037 May There are five weekends in 2038 January There are five weekends in 2038 October There are five weekends in 2039 July There are five weekends in 2041 March There are five weekends in 2042 August There are five weekends in 2043 May There are five weekends in 2044 January There are five weekends in 2044 July There are five weekends in 2045 December There are five weekends in 2047 March There are five weekends in 2048 May There are five weekends in 2049 January There are five weekends in 2049 October There are five weekends in 2050 July There are five weekends in 2051 December There are five weekends in 2052 March There are five weekends in 2053 August There are five weekends in 2054 May There are five weekends in 2055 January There are five weekends in 2055 October There are five weekends in 2056 December There are five weekends in 2058 March There are five weekends in 2059 August There are five weekends in 2060 October There are five weekends in 2061 July There are five weekends in 2062 December There are five weekends in 2064 August There are five weekends in 2065 May There are five weekends in 2066 January There are five weekends in 2066 October There are five weekends in 2067 July There are five weekends in 2069 March There are five weekends in 2070 August There are five weekends in 2071 May There are five weekends in 2072 January There are five weekends in 2072 July There are five weekends in 2073 December There are five weekends in 2075 March There are five weekends in 2076 May There are five weekends in 2077 January There are five weekends in 2077 October There are five weekends in 2078 July There are five weekends in 2079 December There are five weekends in 2080 March There are five weekends in 2081 August There are five weekends in 2082 May There are five weekends in 2083 January There are five weekends in 2083 October There are five weekends in 2084 December There are five weekends in 2086 March There are five weekends in 2087 August There are five weekends in 2088 October There are five weekends in 2089 July There are five weekends in 2090 December There are five weekends in 2092 August There are five weekends in 2093 May There are five weekends in 2094 January There are five weekends in 2094 October There are five weekends in 2095 July There are five weekends in 2097 March There are five weekends in 2098 August There are five weekends in 2099 May There are five weekends in 2100 January There are five weekends in 2100 October There were 201 occurances of five-weekend months in years 1900-->2100 1900 doesn't have any five-weekend months. 1906 doesn't have any five-weekend months. 1917 doesn't have any five-weekend months. 1923 doesn't have any five-weekend months. 1928 doesn't have any five-weekend months. 1934 doesn't have any five-weekend months. 1945 doesn't have any five-weekend months. 1951 doesn't have any five-weekend months. 1956 doesn't have any five-weekend months. 1962 doesn't have any five-weekend months. 1973 doesn't have any five-weekend months. 1979 doesn't have any five-weekend months. 1984 doesn't have any five-weekend months. 1990 doesn't have any five-weekend months. 2001 doesn't have any five-weekend months. 2007 doesn't have any five-weekend months. 2012 doesn't have any five-weekend months. 2018 doesn't have any five-weekend months. 2029 doesn't have any five-weekend months. 2035 doesn't have any five-weekend months. 2040 doesn't have any five-weekend months. 2046 doesn't have any five-weekend months. 2057 doesn't have any five-weekend months. 2063 doesn't have any five-weekend months. 2068 doesn't have any five-weekend months. 2074 doesn't have any five-weekend months. 2085 doesn't have any five-weekend months. 2091 doesn't have any five-weekend months. 2096 doesn't have any five-weekend months. There are 29 years that haven't any five-weekend months in years 1900-->2100
version 2
This version will work with any version of a REXX interpreter. <lang rexx> /*REXX program finds months with 5 weekends in them (given a date range)*/
parse arg yStart yStop . if yStart== then yStart=1900 if yStop == then yStop =2100 years=ystop-yStart+1 month. =31 /*month days, Feb. is done later.*/ month.4 =30 month.6 =30 month.9 =30 month.11=30 haps=0 /*num of five weekends happenings*/ yr5.=0 /*if a year has any five-weekends*/ @months='January February March April May June July',
'August September October November December'
do y=yStart to yStop /*process the years specified. */ do m=1 for 12 /*process each month in each year*/ wd.=0 if m==2 then month.2=28+leapyear(y) /*handle num of days in Feb*/ do d=1 for month.m _=dow(m,d,y) /*get day-of-week for mm/dd/yyyy.*/ wd._=wd._+1 /*_: 1 (Sunday), 2 (Monday) ...*/ end /*d*/ if wd.1\==5 | wd.6\==5 | wd.7\==5 then iterate /*5 weekends ?*/ haps=haps+1 /*bump counter*/ say 'There are five weekends in' y word(@months,m) yr5.y=1 /*indicate this year has one. */ end /*m*/ end /*y*/
say say 'There were' haps "occurance"s(haps) 'of five-weekend months in',
"year"s(years) yStart'-->'yStop
say no5s=0
do y=yStart to yStop if yr5.y then iterate no5s=no5s+1 say y "doesn't have any five-weekend months." end
say say "There are" no5s 'year's(no5s),
"that haven't any five-weekend months in year"s(years) yStart'-->'yStop
exit
/*─────────────────────────────────────DOW (day of week) subroutine─────*/
dow: procedure; arg m,d,y; if m<3 then do; m=m+12; y=y-1; end
yL=left(y,2); yr=right(y,2); w=(d+(m+1)*26%10+yr+yr%4+yL%4+5*yL)//7
if w==0 then w=7; return w /*Sunday=1, Monday=2, ... Saturday=7*/
/*─────────────────────────────────────LEAPYEAR subroutine──────────────*/
leapyear: procedure; arg y /*year could be: Y, YY, YYY, YYYY*/
if length(y)==2 then y=left(right(date(),4),2)y /*adjust for YY year.*/
if y//4\==0 then return 0 /* not ≈ by 4? Not a leapyear.*/
return y//100\==0 | y//400==0 /*apply 100 and 400 year rule. */
/*─────────────────────────────────────S subroutine (for plurals)───────*/
s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1)
</lang>
Ruby
<lang ruby>require 'date'
- if the last day of the month falls on a Sunday and the month has 31 days,
- this is the only case where the month has 5 weekends.
start = Date.parse("1900-01-01") stop = Date.parse("2100-12-31") dates = (start..stop).find_all do |day|
day.mday == 31 and day.wday == 0
end
puts "There are #{dates.size} months with 5 weekends from 1900 to 2100:" puts dates[0, 5].map { |d| d.strftime("%b %Y") }.join("\n") puts "..." puts dates[-5, 5].map { |d| d.strftime("%b %Y") }.join("\n")
years_with_5w = dates.map(&:year)
years = (1900..2100).to_a - years_with_5w
puts "There are #{years.size} years without months with 5 weekends:" puts years.join(", ")</lang>
Output
There are 201 months with 5 weekends from 1900 to 2100: Mar 1901 Aug 1902 May 1903 Jan 1904 Jul 1904 ... Mar 2097 Aug 2098 May 2099 Jan 2100 Oct 2100 There are 29 years without months with 5 weekends: 1900, 1906, 1917, 1923, 1928, 1934, 1945, 1951, 1956, 1962, 1973, 1979, 1984, 1990, 2001, 2007, 2012, 2018, 2029, 2035, 2040, 2046, 2057, 2063, 2068, 2074, 2085, 2091, 2096
Seed7
<lang seed7>$ include "seed7_05.s7i";
include "time.s7i";
const proc: main is func
local var integer: months is 0; var time: firstDayInMonth is time.value; begin for firstDayInMonth.year range 1900 to 2100 do for firstDayInMonth.month range 1 to 12 do if daysInMonth(firstDayInMonth) = 31 and dayOfWeek(firstDayInMonth) = 5 then writeln(firstDayInMonth.year <& "-" <& firstDayInMonth.month lpad0 2); incr(months); end if; end for; end for; writeln("Number of months:" <& months); end func;</lang>
Output:
1901-03 1902-08 1903-05 1904-01 1904-07 1905-12 ... 2095-07 2097-03 2098-08 2099-05 2100-01 2100-10 Number of months:201
Tcl
<lang tcl>package require Tcl 8.5
set months {} set years {} for {set year 1900} {$year <= 2100} {incr year} {
set count [llength $months] foreach month {Jan Mar May Jul Aug Oct Dec} {
set date [clock scan "$month/01/$year" -format "%b/%d/%Y" -locale en_US] if {[clock format $date -format %u] == 5} { # Month with 31 days that starts on a Friday => has 5 weekends lappend months "$month $year" }
} if {$count == [llength $months]} {
# No change to number of months; year must've been without lappend years $year
}
} puts "There are [llength $months] months with five weekends" puts [join [list {*}[lrange $months 0 4] ... {*}[lrange $months end-4 end]] \n] puts "There are [llength $years] years without any five-weekend months" puts [join $years ","]</lang> Output:
There are 201 months with five weekends Mar 1901 Aug 1902 May 1903 Jan 1904 Jul 1904 ... Mar 2097 Aug 2098 May 2099 Jan 2100 Oct 2100 There are 29 years without any five-weekend months 1900,1906,1917,1923,1928,1934,1945,1951,1956,1962,1973,1979,1984,1990,2001,2007,2012,2018,2029,2035,2040,2046,2057,2063,2068,2074,2085,2091,2096
TUSCRIPT
<lang tuscript> $$ MODE TUSCRIPT LOOP year=1900,2100
LOOP month="1'3'5'7'8'10'12" SET dayofweek=DATE (number,1,month,year,nummer) IF (dayofweek==5) PRINT year,"-",month ENDLOOP
ENDLOOP </lang> Output:
1901-3 1902-8 1903-5 1904-1 1904-7 1905-12 1907-3 1908-5 1909-1 1909-10 1910-7 1911-12 1912-3 1913-8 1914-5 1915-1 1915-10 1916-12 1918-3 1919-8 1920-10 1921-7 1922-12 1924-8 1925-5 1926-1 1926-10 1927-7 1929-3 1930-8 1931-5 1932-1 1932-7 1933-12 1935-3 1936-5 1937-1 1937-10 1938-7 1939-12 1940-3 1941-8 1942-5 1943-1 1943-10 1944-12 1946-3 1947-8 1948-10 1949-7 1950-12 1952-8 1953-5 1954-1 1954-10 1955-7 1957-3 1958-8 1959-5 1960-1 1960-7 1961-12 1963-3 1964-5 1965-1 1965-10 1966-7 1967-12 1968-3 1969-8 1970-5 1971-1 1971-10 1972-12 1974-3 1975-8 1976-10 1977-7 1978-12 1980-8 1981-5 1982-1 1982-10 1983-7 1985-3 1986-8 1987-5 1988-1 1988-7 1989-12 1991-3 1992-5 1993-1 1993-10 1994-7 1995-12 1996-3 1997-8 1998-5 1999-1 1999-10 2000-12 2002-3 2003-8 2004-10 2005-7 2006-12 2008-8 2009-5 2010-1 2010-10 2011-7 2013-3 2014-8 2015-5 2016-1 2016-7 2017-12 2019-3 2020-5 2021-1 2021-10 2022-7 2023-12 2024-3 2025-8 2026-5 2027-1 2027-10 2028-12 2030-3 2031-8 2032-10 2033-7 2034-12 2036-8 2037-5 2038-1 2038-10 2039-7 2041-3 2042-8 2043-5 2044-1 2044-7 2045-12 2047-3 2048-5 2049-1 2049-10 2050-7 2051-12 2052-3 2053-8 2054-5 2055-1 2055-10 2056-12 2058-3 2059-8 2060-10 2061-7 2062-12 2064-8 2065-5 2066-1 2066-10 2067-7 2069-3 2070-8 2071-5 2072-1 2072-7 2073-12 2075-3 2076-5 2077-1 2077-10 2078-7 2079-12 2080-3 2081-8 2082-5 2083-1 2083-10 2084-12 2086-3 2087-8 2088-10 2089-7 2090-12 2092-8 2093-5 2094-1 2094-10 2095-7 2097-3 2098-8 2099-5 2100-1 2100-10