Five weekends
The month of October in 2010 has five Fridays, five Saturdays, and five Sundays.
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
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 Show all of the years which do not have at least one five-weekend month (there should be 29).
D
<lang d>import std.stdio ; import std.gregorian ; // this module currently work in progress
Date[] m5w(Date start = Date(1900,1,1), Date end = Date(2100,12,31) ) {
Date[] res ; for(Date when = Date(start.year, start.month, 1) ; // adjust to 1st day when < end ; when = Date(when.year, 1 + when.month, 1)) { if(when.endOfMonthDay == 31) // Such month must has 3 + 4*7 if(when.dayOfWeek == 5 ) // days and start at friday res ~= when ; // for 5 FULL weekends. } return res ;
}
void main() {
auto m = m5w() ; // use default input writefln("There are %d months of which the first and last five are:", m.length) ; foreach(d;m[0..5]~m[$-5..$]) writefln("%s", d.toSimpleString[0..$-2]) ;
}</lang>
output match python one.
J
<lang j>require 'types/datetime' find5wkdMonths=: verb define
years=. 1900 + i. >: 1900 -~ 2100 months=. 1 3 5 7 8 10 12 dates=. 31 m5w=. (#~ 0 = weekday) >,{years;months;dates NB. 5 full weekends iff 31st is Sunday(0) >'MMM YYYY' fmtDate toDayNo m5w
)</lang> Usage: <lang j> # find5wkdMonths NB. number of months found 201
(5&{. , '...' , _5&{.) find5wkdMonths 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</lang>
Java
<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+" 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 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
Python
<lang python>from datetime import timedelta, date
DAY = timedelta(days=1) WEEKEND = {6, 5, 4} # Sunday is day 6 FMT = '%Y %m(%B)'
def fiveweekendspermonth(start=date(1900, 1, 1), stop=date(2101, 1, 1)):
'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:]))</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)
Ruby
<lang ruby># 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")</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
Tcl
<lang tcl>package require Tcl 8.5
for {set year 1900} {$year <= 2100} {incr year} {
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" }
}
} puts "There are [llength $months] with five weekends" puts [join [list {*}[lrange $months 0 4] ... {*}[lrange $months end-4 end]] \n]</lang> Output:
There are 201 with five weekends Mar 1901 Aug 1902 May 1903 Jan 1904 Jul 1904 ... Mar 2097 Aug 2098 May 2099 Jan 2100 Oct 2100