In 1975 Phoebe Winch discovered that the 100 standard Scrabble tiles reveal a hidden message:

I AM DIETING. I EAT QUINCE JELLY. LOTS OF GROUND MAIZE GIVES VARIETY. I COOK RHUBARB AND SODA, WEEP ANEW, OR PUT ON EXTRA FLESH.

The question is how well this Scrabble diet works …

Scrabble gameboard
A game of Scrabble in progress.

Scrabble is a word game in which two to four players score points by placing tiles — each bearing a single letter — onto a game board. The tiles must form words which, in crossword fashion, flow left to right in rows or downwards in columns. The words must be defined in a standard dictionary, or be present in specified reference works that provide a list of officially permissible words.

The game is played by two to four players on a square board with a $$15 \times 15 = 225$$ grid of squares, each of which accommodates a single letter tile. The board is marked with "premium" squares, which multiply the number of points awarded: eight dark red "triple-word" squares, 17 pink "double-word" squares, of which one, the center square, is marked with a star or other symbol; 12 dark blue "triple-letter" squares, and 24 light blue "double-letter" squares.

In an English-language set, the game contains 100 tiles, 98 of which are marked with a letter and a point value ranging from 1 to 10. The number of points of each lettered tile is based on the letter's frequency in standard English writing. Commonly used letters such as vowels are worth one point, while less common letters score higher, with Q and Z each worth 10 points. The game also has two blank tiles that are unmarked and carry no point value. The blank tiles can be used as substitutes for any letter. Once laid on the board, however, the choice is fixed. Other language sets use different letter set distributions with different point values.

Before the game, a resource (either a word list or a dictionary) is selected for the purpose of adjudicating any challenges during the game. The letter tiles are put in an opaque bag. Next, players decide the order in which they play. The normal approach is for players to each draw one tile: the player who picks the letter closest to the beginning of the alphabet goes first, with the blank tiles taking precedence over A's. At the beginning of the game, each player draws a fixed number of tiles from the bag and places them on his or her rack, concealed from the other player(s). On each turn, the player has three options:

A proper play uses one or more of the player's tiles to form a continuous string of letters that make a word (the play's "main word") on the board, reading either left-to-right or top-to-bottom. The main word must either use the letters of one or more previously played words or else have at least one of its tiles horizontally or vertically adjacent to an already played word. If any words other than the main word are formed by the play, they are scored as well, and are subject to the same criteria of acceptability.

A blank tile may represent any letter, and scores zero points, regardless of its placement or what letter it represents. But its placement on a double-word or triple-word square does cause the corresponding premium to be applied to the word(s) in which it is used. Once a blank tile is placed, it remains that letter for the rest of the game. The player then draws tiles from the bag to replenish his or her rack. If there are not enough tiles in the bag to do so, the player takes all the remaining tiles. The game ends when either one player plays every tile on his or her rack and there are no tiles remaining in the bag (regardless of the tiles on his or her opponent's rack) or at least six successive scoreless turns have occurred and either player decides to end the game.

opaque bag
In the game of Scrabble, letters are drawn blindly from an opaque bag.

Assignment

In this assignment we represent a couple of letters as a string, a list, a tuple or a set containing uppercase letters and underscores (_), where the underscores represent blanks in the game of Scrabble. Letters and underscores may occur several times.

The contents of a bag of letters are represented as a dictionary, whose keys are uppercase letters and possibly also an underscore (again representing a blank). Each key is associated with a strictly positive integer that indicates the number of occurrences of the letter (or blank) in the bag. Note that it is not allowed to associate the value zero with a letter or a blank. If a letter does not occur in the bag, there is no corresponding key/value pair in the dictionary that represents the bag.

Implement a class Bag that can be used to represent bags as used in the Scrabble game. It must be possible to fill the bag with letters at the start of a game, and to remove letters from the bag during the game. At all times during the game, we also want to get an overview of the contents of the bag. The class Bag must at least support the following methods:

Example

>>> bag = Bag('IAMDIETINGIEATQUINCEJELLYLOTSOFGROUNDMAIZEGIVESVARIETYICOOKRHUBARBANDSODAWEEPANEWORPUTONEXTRAFLESH__')
>>> bag.content
{'U': 4, '_': 2, 'C': 2, 'K': 1, 'D': 4, 'T': 6, 'Q': 1, 'V': 2, 'A': 9, 'F': 2, 'O': 8, 'J': 1, 'I': 9, 'N': 6, 'P': 2, 'S': 4, 'M': 2, 'W': 2, 'E': 12, 'Z': 1, 'G': 3, 'Y': 2, 'B': 2, 'L': 4, 'R': 6, 'X': 1, 'H': 2}
>>> print(bag)
1: JKQXZ
2: BCFHMPVWY_
3: G
4: DLSU
6: NRT
8: O
9: AI
12: E
>>> bag
Bag('AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJKLLLLMMNNNNNNOOOOOOOOPPQRRRRRRSSSSTTTTTTUUUUVVWWXYYZ__')
>>> bag.remove('AEERTYOXMCNB_S')
>>> print(bag)
1: BCJKMQYZ_
2: FHPVW
3: GS
4: DLU
5: NRT
7: O
8: A
9: I
10: E
>>> bag
Bag('AAAAAAAABCDDDDEEEEEEEEEEFFGGGHHIIIIIIIIIJKLLLLMNNNNNOOOOOOOPPQRRRRRSSSTTTTTUUUUVVWWYZ_')
>>> bag.remove('XXX')
Traceback (most recent call last):
AssertionError: not all letters are in the bag
>>> print(bag)
1: BCJKMQYZ_
2: FHPVW
3: GS
4: DLU
5: NRT
7: O
8: A
9: I
10: E
>>> bag
Bag('AAAAAAAABCDDDDEEEEEEEEEEFFGGGHHIIIIIIIIIJKLLLLMNNNNNOOOOOOOPPQRRRRRSSSTTTTTUUUUVVWWYZ_')