Another coding problem
You're creating your own website for Harry Potter fans. As you all believe in magic, you're waiting for your personal letter from Hogwarts, that will definitely arrive to you some day with a magnificent owl. To be prepared for this exciting moment you decided to embed a calendar to your website on which you will mark the days when Hogwarts owls can bring letters.
Given a month and a year, return an HTML table representing the desired calendar. Follow the same format as provided in the example but omit all whitespace characters (i.e. tabs, newlines and whitespaces) where it is possible, because you care about space efficiency.
Example
For month = 11 and year = 2016, the output should be
solution(month, year) =
"<table border="0" cellpadding="0" cellspacing="0" class="month">
<tr>
<th colspan="7" class="month">November 2016</th>
</tr>
<tr>
<th class="mon">Mon</th>
<th class="tue">Tue</th>
<th class="wed">Wed</th>
<th class="thu">Thu</th>
<th class="fri">Fri</th>
<th class="sat">Sat</th>
<th class="sun">Sun</th>
</tr>
<tr>
<td class="noday"> </td>
<td class="tue">1</td>
<td class="wed">2</td>
<td class="thu">3</td>
<td class="fri">4</td>
<td class="sat">5</td>
<td class="sun">6</td>
</tr>
<tr>
<td class="mon">7</td>
<td class="tue">8</td>
<td class="wed">9</td>
<td class="thu">10</td>
<td class="fri">11</td>
<td class="sat">12</td>
<td class="sun">13</td>
</tr>
<tr>
<td class="mon">14</td>
<td class="tue">15</td>
<td class="wed">16</td>
<td class="thu">17</td>
<td class="fri">18</td>
<td class="sat">19</td>
<td class="sun">20</td>
</tr>
<tr>
<td class="mon">21</td>
<td class="tue">22</td>
<td class="wed">23</td>
<td class="thu">24</td>
<td class="fri">25</td>
<td class="sat">26</td>
<td class="sun">27</td>
</tr>
<tr>
<td class="mon">28</td>
<td class="tue">29</td>
<td class="wed">30</td>
<td class="noday"> </td>
<td class="noday"> </td>
<td class="noday"> </td>
<td class="noday"> </td>
</tr>
</table>"
Here is how this calendar would look on your website:
November 2016
Mon Tue Wed Thu Fri Sat Sun
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
I methodically worked through and learned some new things about the calendar
package.
def solution(month, year):
import calendar
from calendar import monthrange
import math
from datetime import datetime
days_in_week = 7
first_day, last_day = monthrange(year, month)
first_day = 1 # Always start at 1 intead of offset.
last_day += 1
get_date = lambda d: datetime.strptime(f"{month}-{d}-{year}", '%m-%d-%Y')
days_of_month = [(d, get_date(d).weekday(), calendar.day_name[get_date(d).weekday()][:3])
for d in range(first_day, last_day)]
days_in_month = len(days_of_month)
offset_days = days_in_week - days_of_month[0][1]
pad_start = [None for x in range(days_of_month[0][1])]
remaining_days = days_in_month % days_in_week # or days_in_month - 4*7
pad_end = [None for x in range(days_in_week - (remaining_days - offset_days))]
print(pad_start, pad_end, offset_days, remaining_days)
days_of_month = pad_start + days_of_month + pad_end
weeks = math.ceil(len(days_of_month) / days_in_week) if len(pad_end) < 7 else (days_in_month // days_in_week) + 1
print(days_of_month, days_in_month, weeks)
table_tag = f"<table border='0' cellpadding='0' cellspacing='0' class='month'>"
tr_start, tr_end = "<tr>", "</tr>"
header = f"<th colspan='7' class='month'>{calendar.month_name[month]} {year}</th>"
cell = lambda x, d, day: f"<t{x} class='{str(day).lower()}'>{d}</t{x}>"
calendar_month = []
for i in range(weeks):
c = i * 7
week = []
for dow in days_of_month[c:c+days_in_week]:
week.append(dow)
calendar_month.append(week)
res = table_tag + tr_start + header + tr_end
res += tr_start
for name in calendar.day_name: res += cell('h', name[:3], name[:3])
res += tr_end
for week in calendar_month:
res += tr_start
for d in week:
if d:
res += cell('d', d[0], d[2])
else:
res += cell('d', ' ', 'noday')
res += tr_end
res += "</table>"
return res.replace("'", '"')
All tests and hidden tests pass. Yay.
Top-ranked solution:
def solution_getta_outta_here(month, year):
import calendar
return calendar.HTMLCalendar().formatmonth(year, month).replace("\n", "")
Whelp, learned something else about calendar
package. (╯°□°)╯︵ ┻━┻