Note: This is related to a variation of the game Rummikub
Background & Rules
Rummikub is a tile-based game. There are four colors: red, orange, blue and black. For each color there are 13 tiles (labeled from 1 to 13), and there are also 2 Jokers which are color-independent, hence there are 54 pieces in total. In this variation of Rummikub, each player receives 14 tiles and must get one more tile and drop another one each round, such that the tile count is constant. The players don't see each other's tiles. The goal is to group the tiles, such that all pieces belong to at least one group (see below). When a player has all the pieces grouped, they drop their tile board and reveal their pieces. The others then check if all the combinations are valid, and if they are, the player wins the round.
How can the tiles be grouped?
There are only two types of groups:
Multi-color groups:
- They consist of 3 or 4 tiles.
- They only contain tiles with the same number on them.
- All the tiles are of different colors.
- Example:
RED 9, BLUE 9, BLACK 9
.
Mono-color groups:
- They consist of at least 3 tiles.
- They cannot contain more than 13 tiles.
- They only contain tiles with different, consecutive numbers on them, in ascending order.
- All the tiles have the same color.
- Tiles labeled with
1
may not be places after tiles labeled13
. - Example:
RED 5, RED 6, RED 7
.
Wait, what do the Jokers do?
Jokers can substitue any piece in the game. For example, our first example can become JOKER, BLUE 9, BLACK 9
, RED 9, JOKER, BLACK 9
or RED 9, BLUE 9, JOKER
. The same applies to our other example. However, one may not place two Jokers in the same group, so things like JOKER, ORANGE 8, JOKER
are forbidden.
Task
Given a Rummikub tile group, determine whether it is valid. You are guaranteed that no duplicate tiles will appear, except for the 2 jokers and that the tiles you receive as input are valid (eg. things like 60
will not appear).
Input / Output
You may take input and provide the output by any standard method.
Some valid input formats: list of strings, list of tuples, nested lists, strings, or anything else you find suitable. The colors can be taken as Strings (e.g: "Blue","Red", etc.
), as String abbreviations (please make Blue and Black tiles distinguishable), or as integers coresponding to a color. When it comes to Jokers, you should mention the way your program receives them as input. If you choose Strings, you may have something like RED 9, JOKER, ...
, if you choose tuples you can have (9,"RED"), ("JOKER")
or something equivalent. If it helps, you may receive a color for that Joker (which should not affect the output of your program). For example, you may have ("JOKER","RED")
or ("JOKER","BLUE")
, but that should not influence the output in any way.
Regarding the output, standard rules for a decision-problem apply.
Worked examples
Let's take an example, that would hopefully make it easier to understand. Given a group as follows, where each tuple represents a tile:
[(9, "RED"), (9, "ORANGE"), ("JOKER"), (9, "BLACK")]
This should return a truthy value, because the input is valid. In this case, the Joker substitutes (9, "BLUE")
, and they form a multi-color group.
If you would be given the following group:
[(9, "BLUE"), (9, "ORANGE"), (9, "RED"), (9, "BLACK"), ("JOKER")]
It would be invalid, and thus you program should return a falsy value, because there is nothing left for the joker to substitute, because the maximum number of cards in a multi-color group is 4.
Additional Test Cases
These are for an extended test suite that cover nearly all possible situations:
Input -> Output [(1,"BLUE"),(2,"BLUE"),(3,"BLUE"),(4,"BLUE"),(5,"BLUE"), (6,"BLUE")] -> truthy [(6,"BLUE"),(6,"RED"),(6,"BLACK)] -> truthy [(5,"BLACK"),(6,"BLACK"),(7,"BLACK"),(8,"BLACK"),(9,"BLACK"),(10,"BLACK"),("JOKER"),(12,"BLACK")] -> truthy [("JOKER"),(3,"BLUE"),(3,"RED")] -> truthy [(8,"BLACK"),(2,"RED"),(13,"BLUE")] -> falsy [(4,"RED"), (3,"RED"), (5,"RED")] -> falsy [(5,"BLACK"), (6, "BLACK)] -> falsy [("JOKER"),(5,"RED"),("JOKER")] -> falsy [(4,"RED"),(5,"RED"),(6, BLUE")] -> falsy [(4,"RED"),("JOKER"),(5,"RED")] -> falsy [(12,"BLACK"),(13,"BLACK),(1,"BLACK")] -> falsy
This is code-golf, so the shortest code in bytes in every language wins!