Five weekends: Difference between revisions
(→{{header|Python}}: Add extra credit answer.) |
(→{{header|Python}}: Alternate algorithm) |
||
Line 194: | Line 194: | ||
print('\nThere are %i years in the range that do not have months with five weekends' |
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> |
% 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''' |
'''Sample Output''' |
Revision as of 20:49, 23 October 2010
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 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+" 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
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
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