Mathematics Behind the Set Game
This writeup demonstrates an approach to represent various data structures for the Set game.
First we need a deck of cards.
deck = t(t(c(1:81)))
head(deck)
[,1]
[1,] 1
[2,] 2
[3,] 3
[4,] 4
[5,] 5
[6,] 6
deck = data.frame(deck)
Each of the four attributes: number, color, shape, and texture will be represented by a number from 1 to 3.
This approach facilitates using modulo arithmetic to find the combinations of valid sets. A valid set is where each attribute sum modulo 3 is equal to 0.
onetwothree = c(1:3)
numbers = onetwothree
color = onetwothree
shapes = onetwothree
textures = onetwothree
# generate the 81 unique cards
i = 0
for (n in numbers) {
for (c in color) {
for (s in shapes) {
for (t in textures) {
i = i + 1
deck[i,2] = n
deck[i,3] = c
deck[i,4] = s
deck[i,5] = t
}
}
}
}
colnames(deck) = c("deckID","number","color","shape","texture")
head(deck)
We now randomly pick a group of 12 cards. This uses the R function sample, which, by default, selects a sample without replacement.
Once we have the 12 cards, generate all combinations of 12 cards taken 3 at a time with the combn function.
These are then evaluated with modulo 3 arithmetic to find the actual valid sets.
# select our 12
pick12 = sample(deck[,1],12)
picks = deck[pick12,]
picks
allSets = combn(picks[,1],3)
dim(allSets)
[1] 3 220
totalSets = ncol(allSets)
for (i in 1:totalSets) {
set = deck[allSets[,i],]
#print (set)
#print (sum(set[,2]))
#print (sum(set[,3]))
isSet = (sum(set[,2]) %% 3 == 0) & (sum(set[,3]) %% 3 == 0) &
(sum(set[,4]) %% 3 == 0) & (sum(set[,5]) %% 3 == 0)
if (isSet) {
#print (i)
print (deck[allSets[,i],])
}
}
Translate this to text.
Colors = c(" Red"," Green"," Blue")
Shapes = c(" Oval"," Diamond"," Sqiggle")
Textures = c(" Solid"," Shaded"," Open")
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIyMgTWF0aGVtYXRpY3MgQmVoaW5kIHRoZSBTZXQgR2FtZQ0KDQpUaGlzIHdyaXRldXAgZGVtb25zdHJhdGVzIGFuIGFwcHJvYWNoIHRvIHJlcHJlc2VudCB2YXJpb3VzIGRhdGEgc3RydWN0dXJlcyBmb3IgdGhlIFNldCBnYW1lLiANCg0KRmlyc3Qgd2UgbmVlZCBhIGRlY2sgb2YgY2FyZHMuDQoNCg0KDQpgYGB7cn0NCg0KZGVjayA9IHQodChjKDE6ODEpKSkNCmhlYWQoZGVjaykNCmRlY2sgPSBkYXRhLmZyYW1lKGRlY2spDQpgYGANCg0KRWFjaCBvZiB0aGUgZm91ciBhdHRyaWJ1dGVzOiBudW1iZXIsIGNvbG9yLCBzaGFwZSwgYW5kIHRleHR1cmUgd2lsbCBiZSByZXByZXNlbnRlZCBieSBhIG51bWJlciBmcm9tIDEgdG8gMy4NCg0KVGhpcyBhcHByb2FjaCBmYWNpbGl0YXRlcyB1c2luZyBtb2R1bG8gYXJpdGhtZXRpYyB0byBmaW5kIHRoZSBjb21iaW5hdGlvbnMgb2YgdmFsaWQgc2V0cy4gQSB2YWxpZCBzZXQgaXMgd2hlcmUgZWFjaCBhdHRyaWJ1dGUgc3VtIG1vZHVsbyAzIGlzIGVxdWFsIHRvIDAuDQpgYGB7cn0NCm9uZXR3b3RocmVlID0gYygxOjMpDQpudW1iZXJzID0gb25ldHdvdGhyZWUNCmNvbG9yID0gb25ldHdvdGhyZWUNCnNoYXBlcyA9IG9uZXR3b3RocmVlDQp0ZXh0dXJlcyA9IG9uZXR3b3RocmVlDQojIGdlbmVyYXRlIHRoZSA4MSB1bmlxdWUgY2FyZHMNCmkgPSAwDQpmb3IgKG4gaW4gbnVtYmVycykgew0KICAgIGZvciAoYyBpbiBjb2xvcikgew0KICAgICAgICBmb3IgKHMgaW4gc2hhcGVzKSB7DQogICAgICAgICAgICBmb3IgKHQgaW4gdGV4dHVyZXMpIHsNCiAgICAgICAgICAgICAgICBpID0gaSArIDENCiAgICAgICAgICAgICAgICBkZWNrW2ksMl0gPSBuDQogICAgICAgICAgICAgICAgZGVja1tpLDNdID0gYw0KICAgICAgICAgICAgICAgIGRlY2tbaSw0XSA9IHMNCiAgICAgICAgICAgICAgICBkZWNrW2ksNV0gPSB0IA0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH0NCmNvbG5hbWVzKGRlY2spID0gYygiZGVja0lEIiwibnVtYmVyIiwiY29sb3IiLCJzaGFwZSIsInRleHR1cmUiKQ0KICAgIA0KaGVhZChkZWNrKQ0KYGBgDQoNCldlIG5vdyByYW5kb21seSBwaWNrIGEgZ3JvdXAgb2YgMTIgY2FyZHMuIFRoaXMgdXNlcyB0aGUgUiBmdW5jdGlvbiBzYW1wbGUsIHdoaWNoLCBieSBkZWZhdWx0LCBzZWxlY3RzIGEgc2FtcGxlIHdpdGhvdXQgcmVwbGFjZW1lbnQuDQoNCk9uY2Ugd2UgaGF2ZSB0aGUgMTIgY2FyZHMsIGdlbmVyYXRlIGFsbCBjb21iaW5hdGlvbnMgb2YgMTIgY2FyZHMgdGFrZW4gMyBhdCBhIHRpbWUgd2l0aCB0aGUgY29tYm4gZnVuY3Rpb24uDQoNClRoZXNlIGFyZSB0aGVuIGV2YWx1YXRlZCB3aXRoIG1vZHVsbyAzIGFyaXRobWV0aWMgdG8gZmluZCB0aGUgYWN0dWFsIHZhbGlkIHNldHMuIA0KYGBge3J9DQojIHNlbGVjdCBvdXIgMTINCnBpY2sxMiA9IHNhbXBsZShkZWNrWywxXSwxMikNCnBpY2tzID0gZGVja1twaWNrMTIsXQ0KcGlja3MNCmFsbFNldHMgPSBjb21ibihwaWNrc1ssMV0sMykNCmRpbShhbGxTZXRzKQ0KDQp0b3RhbFNldHMgPSBuY29sKGFsbFNldHMpDQpmb3IgKGkgaW4gMTp0b3RhbFNldHMpIHsNCiAgICBzZXQgPSBkZWNrW2FsbFNldHNbLGldLF0NCiAgICAjcHJpbnQgKHNldCkNCiAgICAjcHJpbnQgKHN1bShzZXRbLDJdKSkNCiAgICAjcHJpbnQgKHN1bShzZXRbLDNdKSkgICAgICANCiAgICBpc1NldCA9IChzdW0oc2V0WywyXSkgJSUgMyA9PSAwKSAmIChzdW0oc2V0WywzXSkgJSUgMyA9PSAwKSAmIA0KICAgICAgICAoc3VtKHNldFssNF0pICUlIDMgPT0gMCkgJiAoc3VtKHNldFssNV0pICUlIDMgPT0gMCkNCiAgICBpZiAoaXNTZXQpIHsNCiAgICAgICAgI3ByaW50IChpKQ0KICAgICAgICBwcmludCAoZGVja1thbGxTZXRzWyxpXSxdKQ0KICAgIH0NCn0NCg0KDQpgYGANClRyYW5zbGF0ZSB0aGlzIHRvIHRleHQuDQpgYGB7cn0NCg0KQ29sb3JzID0gYygiIFJlZCIsIiBHcmVlbiIsIiBCbHVlIikNClNoYXBlcyA9IGMoIiBPdmFsIiwiIERpYW1vbmQiLCIgU3FpZ2dsZSIpDQpUZXh0dXJlcyA9IGMoIiBTb2xpZCIsIiBTaGFkZWQiLCIgT3BlbiIpDQpgYGANCg0KDQo=