SET¶
SET is a board game published by Set Enterprises, Inc, in which the goal is to find a set of cards. Concretely, the rules are as follows:
SET
12 cards are placed on the table, each with four attributes:
- The symbol on the card (diamonds, squiggles, rectangles)
- The number of symbols (one, two, three)
- The color of the symbols (red, green or purple)
- The fill of the symbols (striped, filled, empty)
The goal is now to find a set of three cards, that either have the same value or a different value for every attribute.
For example, a possible set in the image below would be the most top-left card together with the two bottom-right cards, as they each have:
- The same symbol (diamonds)
- The same number (2)
- Different colors
- Different fills

First, we start building the glossary of the model. There are a few types that should be declared:
- Card (we will use indices 1 through 12)
- Color
- Number
- Shape
- Fill
Type | ||
---|---|---|
Name | Type | Values |
Card | Int | 1..12 |
Color | String | red, green, purple |
Number | String | one, two, three |
Shape | String | diamonds, squiggles, rectangles |
Fill | String | striped, filled, empty |
Next, we want to add a way to link card indices to card attributes. For this, functions are perfect: every card has exactly one value for every attribute. The concrete values for these functions will be filled out later in a data table.
Function | |
---|---|
Name | Type |
color of Card | Color |
number of Card | Number |
fill of Card | Fill |
shape of Card | Shape |
We also need a way to keep track of what cards are selected to be in our set, and if they have the same/different color, same/different number, … We will use a relation for the former, and booleans for the latter (as these are either the same, or different).
Relation |
---|
Name |
selected Card |
Boolean |
---|
Name |
SameColor |
SameNumber |
SameShape |
SameFill |
Finally, to keep track of how many cards have been selected by the system, we introduce a constant.
Constant | |
---|---|
Name | Type |
NbCards | Int |
Now that our glossary is done, we can move on to implementing the rules. These are actually quite straight forward. For every attribute, we want to say the following:
Rule
For every two cards that are selected, if SameAttribute is true, their attribute values should be the same. Similarly, if SameAttribute is false, their attribute values should be different.
Concretely, this is implemented in the following constraint tables:
Color constraint | ||||||
---|---|---|---|---|---|---|
E* | Card called c1 | Card called c2 | selected c1 | selected c2 | SameColor | color of c1 |
1 | - | not(c1) | Yes | Yes | Yes | color of c2 |
2 | - | not(c1) | Yes | Yes | No | not(color of c2) |
Number constraint | ||||||
---|---|---|---|---|---|---|
E* | Card called c1 | Card called c2 | selected c1 | selected c2 | SameNumber | number of c1 |
1 | - | not(c1) | Yes | Yes | Yes | number of c2 |
2 | - | not(c1) | Yes | Yes | No | not(number of c2) |
Fill constraint | ||||||
---|---|---|---|---|---|---|
E* | Card called c1 | Card called c2 | selected c1 | selected c2 | SameFill | fill of c1 |
1 | - | not(c1) | Yes | Yes | Yes | fill of c2 |
2 | - | not(c1) | Yes | Yes | No | not(fill of c2) |
Shape constraint | ||||||
---|---|---|---|---|---|---|
E* | Card called c1 | Card called c2 | selected c1 | selected c2 | SameShape | shape of c1 |
1 | - | not(c1) | Yes | Yes | Yes | shape of c2 |
2 | - | not(c1) | Yes | Yes | No | not(shape of c2) |
The shape constraint table, for example, reads as follows: “For every Card c1 and Card c2 (that isn’t c1), if both c1 and c2 are selected and SameShape is true, then their shape should be the same. If SameShape is false, their shape should be different.”
To finish up, we want to make sure that a set always consists of three selected cards. For that, we add a table which counts the number of selected cards, followed by a constraint on that number.
Count number of selected cards | |||
---|---|---|---|
C+ | Card | selected Card | NbCards |
1 | - | Yes | 1 |
3 cards | |
---|---|
E* | NbCards |
1 | 3 |
Having entered all the rules, all that rests is filling out our data table. We use the example shown in the image above here.
Data Table: Card Data | |||||
---|---|---|---|---|---|
Card | number of Card | color of Card | fill of Card | shape of Card | |
1 | 1 | two | red | striped | diamonds |
1 | 2 | one | purple | filled | diamonds |
3 | 3 | two | green | filled | rectangles |
4 | 4 | one | green | striped | rectangles |
5 | 5 | two | red | filled | rectangles |
6 | 6 | three | red | empty | squiggles |
7 | 7 | one | red | empty | diamonds |
8 | 8 | one | purple | striped | rectangles |
9 | 9 | two | red | empty | rectangles |
10 | 10 | three | purple | striped | squiggles |
11 | 11 | two | purple | filled | diamonds |
12 | 12 | two | green | empty | diamonds |
We can now run our model using the cDMN solver. In total, we are able to find 5 sets!
Model 1
==========
color_of_Card:={(1)->red; (2)->purple; (3)->green; (4)->green; (5)->red; (6)->red; (7)->red; (8)->purple; (9)->red; (10)->purple; (11)->purple; (12)->green}
number_of_Card:={(1)->two; (2)->one; (3)->two; (4)->one; (5)->two; (6)->three; (7)->one; (8)->one; (9)->two; (10)->three; (11)->two; (12)->two}
fill_of_Card:={(1)->striped; (2)->filled; (3)->filled; (4)->striped; (5)->filled; (6)->empty; (7)->empty; (8)->striped; (9)->empty; (10)->striped; (11)->filled; (12)->empty}
shape_of_Card:={(1)->diamonds; (2)->diamonds; (3)->rectangles; (4)->rectangles; (5)->rectangles; (6)->squiggles; (7)->diamonds; (8)->rectangles; (9)->rectangles; (10)->squiggles; (11)->diamonds; (12)->diamonds}
NbCards:={->3}
selected_Card:={(1)->true; (2)->false; (3)->false; (4)->false; (5)->false; (6)->false; (7)->false; (8)->false; (9)->false; (10)->false; (11)->true; (12)->true}
SameColor:={->false}
SameNumber:={->true}
SameShape:={->true}
SameFill:={->false}
Model 2
==========
color_of_Card:={(1)->red; (2)->purple; (3)->green; (4)->green; (5)->red; (6)->red; (7)->red; (8)->purple; (9)->red; (10)->purple; (11)->purple; (12)->green}
number_of_Card:={(1)->two; (2)->one; (3)->two; (4)->one; (5)->two; (6)->three; (7)->one; (8)->one; (9)->two; (10)->three; (11)->two; (12)->two}
fill_of_Card:={(1)->striped; (2)->filled; (3)->filled; (4)->striped; (5)->filled; (6)->empty; (7)->empty; (8)->striped; (9)->empty; (10)->striped; (11)->filled; (12)->empty}
shape_of_Card:={(1)->diamonds; (2)->diamonds; (3)->rectangles; (4)->rectangles; (5)->rectangles; (6)->squiggles; (7)->diamonds; (8)->rectangles; (9)->rectangles; (10)->squiggles; (11)->diamonds; (12)->diamonds}
NbCards:={->3}
selected_Card:={(1)->false; (2)->false; (3)->false; (4)->true; (5)->false; (6)->true; (7)->false; (8)->false; (9)->false; (10)->false; (11)->true; (12)->false}
SameColor:={->false}
SameNumber:={->false}
SameShape:={->false}
SameFill:={->false}
Model 3
==========
color_of_Card:={(1)->red; (2)->purple; (3)->green; (4)->green; (5)->red; (6)->red; (7)->red; (8)->purple; (9)->red; (10)->purple; (11)->purple; (12)->green}
number_of_Card:={(1)->two; (2)->one; (3)->two; (4)->one; (5)->two; (6)->three; (7)->one; (8)->one; (9)->two; (10)->three; (11)->two; (12)->two}
fill_of_Card:={(1)->striped; (2)->filled; (3)->filled; (4)->striped; (5)->filled; (6)->empty; (7)->empty; (8)->striped; (9)->empty; (10)->striped; (11)->filled; (12)->empty}
shape_of_Card:={(1)->diamonds; (2)->diamonds; (3)->rectangles; (4)->rectangles; (5)->rectangles; (6)->squiggles; (7)->diamonds; (8)->rectangles; (9)->rectangles; (10)->squiggles; (11)->diamonds; (12)->diamonds}
NbCards:={->3}
selected_Card:={(1)->false; (2)->false; (3)->false; (4)->false; (5)->false; (6)->true; (7)->true; (8)->false; (9)->true; (10)->false; (11)->false; (12)->false}
SameColor:={->true}
SameNumber:={->false}
SameShape:={->false}
SameFill:={->true}
Model 4
==========
color_of_Card:={(1)->red; (2)->purple; (3)->green; (4)->green; (5)->red; (6)->red; (7)->red; (8)->purple; (9)->red; (10)->purple; (11)->purple; (12)->green}
number_of_Card:={(1)->two; (2)->one; (3)->two; (4)->one; (5)->two; (6)->three; (7)->one; (8)->one; (9)->two; (10)->three; (11)->two; (12)->two}
fill_of_Card:={(1)->striped; (2)->filled; (3)->filled; (4)->striped; (5)->filled; (6)->empty; (7)->empty; (8)->striped; (9)->empty; (10)->striped; (11)->filled; (12)->empty}
shape_of_Card:={(1)->diamonds; (2)->diamonds; (3)->rectangles; (4)->rectangles; (5)->rectangles; (6)->squiggles; (7)->diamonds; (8)->rectangles; (9)->rectangles; (10)->squiggles; (11)->diamonds; (12)->diamonds}
NbCards:={->3}
selected_Card:={(1)->true; (2)->false; (3)->false; (4)->true; (5)->false; (6)->false; (7)->false; (8)->false; (9)->false; (10)->true; (11)->false; (12)->false}
SameColor:={->false}
SameNumber:={->false}
SameShape:={->false}
SameFill:={->true}
Model 5
==========
color_of_Card:={(1)->red; (2)->purple; (3)->green; (4)->green; (5)->red; (6)->red; (7)->red; (8)->purple; (9)->red; (10)->purple; (11)->purple; (12)->green}
number_of_Card:={(1)->two; (2)->one; (3)->two; (4)->one; (5)->two; (6)->three; (7)->one; (8)->one; (9)->two; (10)->three; (11)->two; (12)->two}
fill_of_Card:={(1)->striped; (2)->filled; (3)->filled; (4)->striped; (5)->filled; (6)->empty; (7)->empty; (8)->striped; (9)->empty; (10)->striped; (11)->filled; (12)->empty}
shape_of_Card:={(1)->diamonds; (2)->diamonds; (3)->rectangles; (4)->rectangles; (5)->rectangles; (6)->squiggles; (7)->diamonds; (8)->rectangles; (9)->rectangles; (10)->squiggles; (11)->diamonds; (12)->diamonds}
NbCards:={->3}
selected_Card:={(1)->false; (2)->false; (3)->true; (4)->false; (5)->false; (6)->false; (7)->true; (8)->false; (9)->false; (10)->true; (11)->false; (12)->false}
SameColor:={->false}
SameNumber:={->false}
SameShape:={->false}
SameFill:={->false}
No more models.