February 11, 2025
While I tried my best to brute force this with code, I came to the conclusion to ask GPT yet again, and after some prompting it gave me a working answer. Pretty cool. I then demanded over and over it be simplified! Finally, I got something I could really read and see how it works.
fun areCardsASet(card1: Card, card2: Card, card3: Card): Boolean {
return card1.shape.allSameOrAllDifferent(card2.shape, card3.shape) &&
card1.color.allSameOrAllDifferent(card2.color, card3.color) &&
card1.fill.allSameOrAllDifferent(card2.fill, card3.fill) &&
card1.count.allSameOrAllDifferent(card2.count, card3.count)
}
fun CardFaceValue.allSameOrAllDifferent(value2: CardFaceValue, value3: CardFaceValue): Boolean {
return (this == value2 && value2 == value3) || (this != value2 && value2 != value3 && this != value3)
}
How nice and simple this looks, but how deceptive the second piece of logic really is. What it's doing is simply brute forcing across our characteristics. The second function has some syntactical sugar but does exactly what it says, returns true if they are all the same or true if they are all different. The key here is the nesting and != negations.
Once we deal our cards then what? We simply loop through our grid and compare each card to each other card in sets of threes. This wasn't quite obvious to me, but here we have a simple x - y loop nested in an outer loop. The outer for will break when we've encountered the first Set.
val dealCards = createHashMap().shuffleAndDeal12()
// Brute force to find a valid set of three cards
outer@for (i in 0 until dealCards.size - 2) {
for (j in i + 1 until dealCards.size - 1) {
for (k in j + 1 until dealCards.size) {
val card1 = dealCards[i].value.first
val card2 = dealCards[j].value.first
val card3 = dealCards[k].value.first
if (areCardsASet(card1, card2, card3)) {
println("\nFound a valid set: ${card1.toCardStr()}, ${card2.toCardStr()}, ${card3.toCardStr()}")
break@outer
}
}
}
}
This was a surprise to me that this worked. Running the main method in MainSetEvaluation.kt
will produce a String representation of a matching set that was shuffled and produced. Sometimes it doesn't find any, but this is very rare.
Check part 4 to see how we actually play our set game!