Most jigsaw puzzles can only be solved once and then you're done. But the Daily Calendar Puzzle1 is a very fun and addictive puzzle that each day provides a new challenge. All you have to do is put the ten puzzle pieces in the calendar frame so that the three uncovered squares are labeled with a weekday, a day and a month.

Daily Calendar Puzzle
The Daily Calendar Puzzle is a very fun and addictive puzzle that each day provides a new challenge.
Daily Calendar Puzzle
The Daily Calendar Puzzle is a very fun and addictive puzzle that each day provides a new challenge.

It would be a lie to say that all date are easy to form, but there is at least one solution for every day. Can you make today's date? Your birthday? A historical event?

Assignment

The calendar frame of a Daily Calendar Puzzle consists of a $$8 \times 7$$ grid with 8 rows and 7 columns. Each of the 56 squares in the grid is assigned a number from 0 to 55 (int) by going through the grid from left to right and from top to bottom. Six squares cannot be covered by puzzle pieces: 6, 13, 49, 50, 51 and 52 (marked with a darker background color in the image below). All other squares have a unique label: in order by increasing number the English three-letter abbreviations for the twelve months of the year (JanDec), the day numbers (131) and the English three-letter abbreviations for the seven weekdays (SunSat).

calendar frame
Calendar frame of a Daily Calendar Puzzle whose the squares have been numbered from 055 by going through the grid from left to right and from top to bottom.

Each puzzle piece is assigned a unique uppercase letter (str) as a label to distinguish it from other pieces. We represent the place where a piece is put down in the frame as a collection (list, tuple or set) with the numbers of the squares covered by the piece. At the same time, this also describes the shape of the piece. Here we have put down, for example, a straight orange puzzle piece in place (0, 1, 2, 3), covering the four squares on the left side of the top row.

puzzle piece
The orange puzzle piece covers the squares with numbers 0, 1, 2 and 3.

Define a class Calendar to represent frames of a Daily Calendar Puzzle in which puzzle pieces may be put down and removed. No arguments must be passed when creating a new frame (Calendar): each frame has the same dimensions and no puzzle pieces have been put down in the frame initially. A frame $$f$$ (Calendar) must at least support the following methods:

If a frame $$f$$ (Calendar) is passed to the built-in function str, a string representation (str) of the frame must be returned. Each row of the frame is a separate line in the string representation, listing the string representations of the squares on that row from left to right, separated by spaces.

Example

>>> frame = Calendar()
>>> frame.square(0)
'Jan'
>>> frame.square(39)
' 26'
>>> frame.square(48)
'Wed'
>>> frame.square(52)
'###'
>>> print(frame)
Jan Feb Mar Apr May Jun ###
Jul Aug Sep Oct Nov Dec ###
  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  31 Sun Mon Tue Wed
### ### ### ### Thu Fri Sat
>>> frame.piece('A')
Traceback (most recent call last):
AssertionError: no piece A in the frame
>>> print(frame.put('A', (0, 1, 2, 3)))
#A# #A# #A# #A# May Jun ###
Jul Aug Sep Oct Nov Dec ###
  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  31 Sun Mon Tue Wed
### ### ### ### Thu Fri Sat
>>> frame.piece('A')
{0, 1, 2, 3}
>>> print(frame.put('B', (4, 5, 9, 10, 11)))
#A# #A# #A# #A# #B# #B# ###
Jul Aug #B# #B# #B# Dec ###
  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  31 Sun Mon Tue Wed
### ### ### ### Thu Fri Sat
>>> frame.put('B', (7, 8, 14, 21, 28))
Traceback (most recent call last):
AssertionError: piece B already in the frame
>>> frame.put('C', (13, 14, 15))
Traceback (most recent call last):
AssertionError: can't put piece C in the frame
>>> frame.put('C', (0, 1, 7, 8))
Traceback (most recent call last):
AssertionError: can't put piece C in the frame
>>> print(frame.put('C', [7, 8, 14, 21, 28]).put('D', [15, 16, 22, 23, 29]))
#A# #A# #A# #A# #B# #B# ###
#C# #C# #B# #B# #B# Dec ###
#C# #D# #D#   4   5   6   7
#C# #D# #D#  11  12  13  14
#C# #D#  17  18  19  20  21
 22  23  24  25  26  27  28
 29  30  31 Sun Mon Tue Wed
### ### ### ### Thu Fri Sat
>>> print(frame.remove('A'))
Jan Feb Mar Apr #B# #B# ###
#C# #C# #B# #B# #B# Dec ###
#C# #D# #D#   4   5   6   7
#C# #D# #D#  11  12  13  14
#C# #D#  17  18  19  20  21
 22  23  24  25  26  27  28
 29  30  31 Sun Mon Tue Wed
### ### ### ### Thu Fri Sat
>>> frame.remove('Z')
Traceback (most recent call last):
AssertionError: no piece Z in the frame
>>> print(frame.put('A', (0, 1, 2, 3)))
#A# #A# #A# #A# #B# #B# ###
#C# #C# #B# #B# #B# Dec ###
#C# #D# #D#   4   5   6   7
#C# #D# #D#  11  12  13  14
#C# #D#  17  18  19  20  21
 22  23  24  25  26  27  28
 29  30  31 Sun Mon Tue Wed
### ### ### ### Thu Fri Sat
>>> print(frame.put('E', {17, 24, 25, 26, 33}).put('F', {18, 19, 20, 27, 34}))
#A# #A# #A# #A# #B# #B# ###
#C# #C# #B# #B# #B# Dec ###
#C# #D# #D# #E# #F# #F# #F#
#C# #D# #D# #E# #E# #E# #F#
#C# #D#  17  18  19 #E# #F#
 22  23  24  25  26  27  28
 29  30  31 Sun Mon Tue Wed
### ### ### ### Thu Fri Sat
>>> print(frame.put('G', (30, 31, 32, 38, 45)).put('H', (35, 36, 37, 42, 44)))
#A# #A# #A# #A# #B# #B# ###
#C# #C# #B# #B# #B# Dec ###
#C# #D# #D# #E# #F# #F# #F#
#C# #D# #D# #E# #E# #E# #F#
#C# #D# #G# #G# #G# #E# #F#
#H# #H# #H# #G#  26  27  28
#H#  30 #H# #G# Mon Tue Wed
### ### ### ### Thu Fri Sat
>>> frame.read()
Traceback (most recent call last):
AssertionError: invalid date
>>> print(frame.put('I', (39, 40, 41, 48)).put('J', (46, 47, 54, 55)))
#A# #A# #A# #A# #B# #B# ###
#C# #C# #B# #B# #B# Dec ###
#C# #D# #D# #E# #F# #F# #F#
#C# #D# #D# #E# #E# #E# #F#
#C# #D# #G# #G# #G# #E# #F#
#H# #H# #H# #G# #I# #I# #I#
#H#  30 #H# #G# #J# #J# #I#
### ### ### ### Thu #J# #J#
>>> frame.read()
'Thu, 30 Dec'

Epilogue

There are 28 972 628 different ways the 10 puzzle pieces can be put in the grid. Of these, 4 937 780 (17.04 %) leave a month, a day and a weekday open, and 4 864 096 (16.79 %) if also discard invalid dates such as February 30 or November 31. The easiest date is Tuesday, June 7 (Tue, 7 Jun) that can be formed in 10 374 different ways. The most difficult date is Monday, April 6 (Mon, 6 Apr) that can be formed in only 97 different ways.

Spoiler alert

In case you would become addicted to this puzzle: this is an overview2 with a randomly selected solution for each of the $$12 \times 31 \times 7$$ different days of the year. This may help putting your frustrations away on days where you can't find the solution yourself.

There's also a version of the puzzle called "dageraat3" with hexagonal cells.

hexagonal puzzle (empty)
Version of the Daily Calendar Puzzle with hexagonal cells.
hexagonal puzzle (ongoing)
Version of the Daily Calendar Puzzle with hexagonal cells.
hexagonal puzzle (solved)
Version of the Daily Calendar Puzzle with hexagonal cells.