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:

  1. The symbol on the card (diamonds, squiggles, rectangles)
  2. The number of symbols (one, two, three)
  3. The color of the symbols (red, green or purple)
  4. 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
an example of SET cards

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.