Historically, the Rummikub game was played
with two sets of cards. Because this required quite some space on the
table, modern versions of the game replaced cards by 106 smaller tiles:
two sets of tiles that range in value from one to thirteen, in four colors
(red, yellow, blue and black), and two joker tiles (
At the start of the game, the pool of tiles are shuffled together and spread out face down across the table so that the face of the tiles is not reveiled to the players. Each player draws and reveals one tile. The player whose tile has the highest number value will start the game. Tiles are returned to the pool, and players in turn collect 14 random tiles and arrange them on their racks. Play then begins with the starting player, and proceeds in a clockwise direction.
For a player's first move, he must play a set with a value of at least 30 points. Point values are taken from the face value of each tile played, with the joker (if played) assuming the value of the tile it is being used in place of. The player may not use other players' tiles to make the initial 30 or more. A player's first move is known as the initial meld. If a player cannot make an initial meld, he must pick up a single tile from the pool and add it to his rack. Play then proceeds to the next player. Game play continues until a player has used all of the tiles in the rack, at which point he should call out "Rummikub" and is declared the winner.
In this assignment we represent a tile
in the Rummikub game as a string. This string starts with an integer from
the range
A group of tiles represents for example all tiles a player has on his rack, or an initial meld of tiles that is played on the table by a player. We use two distinct ways to represent a group of tiles: as a sequence (a list or a tuple) or as a dictionary.
The first way represents a group of tiles as a sequence (a list or a tuple) of tiles. Because the same tile might occur more than once in the group — we even allow the same tile to occur more than twice — it may happen that the same string occurs more than once in the sequence that represents the group of tiles.
De second way represents a group of tiles as a dictionary that maps tiles onto the number of occurrences of tiles in the group. The string representation of the tiles is thus used as a key in the dictionary, and the number of occurrences as the corresponding values. All values in the dictionary are strictly positive. Tiles that do not occur in the group are never used as keys in the dictionary. Your task:
Write a function group that takes a sequence (a list or a tuple) of strings that represents a group of tiles. The function must return a dictionary that represents the given group of tiles.
Write a function play that takes two dictionaries. The first dictionary represent an initial meld that a player wants to put on the table. The second dictionary represents all tiles the player has on his rack. The function must return a Boolean value that indicates whether or not the player can put the initial meld on the table. The latter is the case if the player has all the tiles in the initial meld on his rack. If the play can put the initial meld on the table, the function must make sure that all tiles from the initial meld are removed from the dictionary that represents the tiles on the rack. If the player cannot put the initial meld on the table, the function may not modify the given dictionary that represents the tiles the player has on his rack.
>>> group(['9Y', '7R', '9Y', '7R', '9Y', '7R', '9Y'])
{'9Y': 4, '7R': 3}
>>> group(['1Y', '7Y', '8Y', '12Y', '12B', '13B', '13B', '13Z', '13Y', '2Z', '3Z', '4Z', '11Z', '11Z', '4R', '5R'])
{'8Y': 1, '12Y': 1, '13B': 2, '3Z': 1, '5R': 1, '7Y': 1, '1Y': 1, '13Y': 1, '4Z': 1, '13Z': 1, '12B': 1, '2Z': 1, '4R': 1, '11Z': 2}
>>> meld = group(['13B', '13Z', '13Y'])
>>> rack = group(['1Y', '7Y', '8Y', '12Y', '12B', '13B', '13B', '13Z', '13Y', '2Z', '3Z', '4Z', '11Z', '11Z', '4R', '5R'])
>>> play(meld, rack)
True
>>> meld
{'13B': 1, '13Y': 1, '13Z': 1}
>>> rack
{'8Y': 1, '12Y': 1, '13B': 1, '3Z': 1, '5R': 1, '7Y': 1, '1Y': 1, '4Z': 1, '12B': 1, '2Z': 1, '4R': 1, '11Z': 2}
>>> meld = group(['12B', '12Z', '12Y'])
>>> play(meld, rack)
False
>>> rack
{'8Y': 1, '12Y': 1, '13B': 1, '3Z': 1, '5R': 1, '7Y': 1, '1Y': 1, '4Z': 1, '12B': 1, '2Z': 1, '4R': 1, '11Z': 2}