Set puzzle: Difference between revisions

(add draft task)
 
(→‎{{header|D}}: added D)
Line 68:
 
purple, three, oval, open
 
 
=={{header|D}}==
<lang d>import std.stdio, std.traits, std.random, std.conv, std.exception,
std.array;
 
class SetDealer {
protected {
enum Color : ubyte {green, purple, red}
enum Number : ubyte {one, two, three}
enum Symbol : ubyte {oval, diamond, squiggle}
enum Fill : ubyte {open, striped, solid}
 
static struct Card {
Color c;
Number n;
Symbol s;
Fill f;
}
 
Card[81] deck;
}
 
this() nothrow {
auto colors = [EnumMembers!Color];
auto numbers = [EnumMembers!Number];
auto symbols = [EnumMembers!Symbol];
auto fill = [EnumMembers!Fill];
 
foreach (immutable i; 0 .. deck.length) {
auto c = colors[i / 27];
auto n = numbers[(i / 9) % 3];
auto s = symbols[(i / 3) % 3];
auto f = fill[i % 3];
deck[i] = Card(c, n, s, f);
}
}
 
 
// randomSample produces a sorted output that's convenient in our case
// because we're printing to stout. Normally you would want to shuffle.
immutable(Card)[] deal(in uint numCards) {
enforce(numCards < deck.length, "number of cards too large");
return assumeUnique(randomSample(deck[], numCards).array());
}
 
// The summed enums of valid sets are always zero or a multiple of 3
bool validSet(in ref Card c1, in ref Card c2, in ref Card c3)
pure nothrow {
return !((c1.c + c2.c + c3.c) % 3 || (c1.n + c2.n + c3.n) % 3 ||
(c1.s + c2.s + c3.s) % 3 || (c1.f + c2.f + c3.f) % 3);
}
 
immutable(Card)[3][] findSets(in Card[] cards) pure nothrow {
auto len = cards.length;
if (len >= 3) {
typeof(return) sets;
for (int i = 0; i < len - 2; i++) {
for (int j = i + 1; j < len - 1; j++)
for (int k = j + 1; k < len; k++)
if (validSet(cards[i], cards[j], cards[k]))
sets ~= [cards[i], cards[j], cards[k]];
}
return assumeUnique(sets);
}
return null;
}
}
 
class SetPuzzleDealer : SetDealer {
enum NumCards {basic = 9, advanced = 12}
 
override immutable(Card)[] deal(in uint numCards = NumCards.basic) {
auto numSets = numCards / 2;
typeof(return) cards;
do {
cards = super.deal(numCards);
} while (findSets(cards).length != numSets);
 
return assumeUnique(cards);
}
}
 
void main() {
auto dealer = new SetPuzzleDealer();
auto cards = dealer.deal();
 
writefln("\nDEALT %d CARDS:\n", cards.length);
foreach (Unqual!(typeof(cards[0])) c; cards)
writeln(c);
 
auto sets = dealer.findSets(cards);
auto len = sets.length;
writefln("\nFOUND %d %s:\n", len, len == 1 ? "SET" : "SETS");
foreach (set; sets) {
foreach (Unqual!(typeof(set[0])) c; set)
writeln(c);
writeln();
}
}</lang>
<pre>DEALT 9 CARDS:
 
Card(green, one, oval, solid)
Card(green, one, diamond, solid)
Card(green, one, squiggle, solid)
Card(green, two, squiggle, open)
Card(green, three, oval, open)
Card(green, three, diamond, solid)
Card(green, three, squiggle, striped)
Card(purple, two, squiggle, solid)
Card(red, one, squiggle, open)
 
FOUND 4 SETS:
 
Card(green, one, oval, solid)
Card(green, one, diamond, solid)
Card(green, one, squiggle, solid)
 
Card(green, one, squiggle, solid)
Card(green, two, squiggle, open)
Card(green, three, squiggle, striped)
 
Card(green, three, oval, open)
Card(green, three, diamond, solid)
Card(green, three, squiggle, striped)
 
Card(green, three, squiggle, striped)
Card(purple, two, squiggle, solid)
Card(red, one, squiggle, open)</pre>
Anonymous user