Set puzzle: Difference between revisions

D entry: removed assumeUnique, added immutable and const, used foreach, shorter lines, and other small changes
m (dealing from a shuffled deck is random enough)
(D entry: removed assumeUnique, added immutable and const, used foreach, shorter lines, and other small changes)
Line 69:
 
=={{header|D}}==
<lang d>import std.stdio, std.traitsrandom, std.randomarray, std.conv, std.exceptiontraits,
std.arrayexception;
 
const class SetDealer {
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();
}
 
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 {
Line 104 ⟶ 86:
}
 
immutable Card[81] deck;
}
 
this() pure nothrow {
autoimmutable colors = [EnumMembers!Color];
autoimmutable numbers = [EnumMembers!Number];
autoimmutable symbols = [EnumMembers!Symbol];
autoimmutable fill = [EnumMembers!Fill];
 
foreach (immutable i;, 0ref ..di; deck.length) {
auto cdi = Card(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
 
// case because we're printing to stout. Normally you would want
// 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) const {
enforce(numCards < deck.length, "number of cards too large");
return assumeUnique(randomSample(deck[], .randomSample(numCards).array());
}
 
// The summed enums of valid sets are always zero or a multiple of 3
// of }3.
bool validSet(in ref Card c1, in ref Card c2, in ref Card c3)
const pure nothrow {
return !((c1.c + c2.c + c3.c) % 3 || (c1.n + c2.n + c3.n) % 3 ||
(c1.sn + c2.sn + c3.sn) % 3 || (c1.f + c2.f + c3.f) % 3);
for (intc1.s j+ = ic2.s + 1;c3.s) j% <3 len - 1; j++)||
for (int i = 0; i(c1.f <+ lenc2.f - 2; i++ c3.f) {% 3);
}
 
immutable(Card)[3][] findSets(in Card[] cards, in uint target = 0)
const pure nothrow {
autoimmutable len = cards.length;
if (len >=< 3) {
typeof(return) setsnull;
 
for (int i = 0; i < len - 2; i++) {
typeof(return) nullsets;
for (int j = i + 1; j < len - 1; j++)
forforeach (intimmutable k = j + 1i; k0 <.. len; k++- 2)
foreach (immutable j; i + 1 .. len - if (validSet(cards[i], cards[j], cards[k]1)) {
foreach (immutable k; j + 1 .. sets ~= [cards[i], cards[j], cards[k]];len)
if (targetvalidSet(cards[i], !=cards[j], 0cards[k])) && sets.length > target){
sets ~= [cards[i], cards[j], return nullcards[k]];
}if (target != 0 && sets.length > target)
} return null;
return assumeUnique(sets); }
}return sets;
return null;
}
}
 
const final class SetPuzzleDealer : SetDealer {
enum {basic = 9, advanced = 12}
 
override immutable(Card)[] deal(in uint numCards = basic) const {
autoimmutable numSets = numCards / 2;
typeof(return) cards;
 
do {
cards = super.deal(numCards);
} while (findSets(cards, numSets).length != numSets);
 
return assumeUnique(cards);
}
 
void main() {
autoconst dealer = new SetPuzzleDealer();
autoconst cards = dealer.deal();
 
writefln("\nDEALTDEALT %d CARDS:\n", cards.length);
foreach (Unqual!(typeof(cards[0])) c; cards)
writeln(cast()c);
 
autoimmutable sets = dealer.findSets(cards);
autoimmutable len = sets.length;
writefln("\nFOUND %d %s:\n", len, len == 1 ? "SET" : "SETS");
foreach (set; sets) {
foreach (Unqual!(typeof(set[0])) c; set)
writeln(cast()c);
writeln(c);
}
}</lang>
{{out|Sample output}}
<pre>DEALT 9 CARDS:
Card(green, threetwo, diamond, solidopen)
 
Card(green, onethree, oval, solidstriped)
Card(green, onethree, diamondoval, solid)
Card(green, onethree, squiggle, solidopen)
Card(greenpurple, two, squiggle, open)
Card(greenred, threeone, ovaldiamond, openstriped)
Card(green, three, diamond, solid)
Card(green, three, squiggle, striped)
Card(purple, two, squiggle, solid)
Card(red, one, squiggle, open)
Card(purplered, two, squiggleoval, solidopen)
Card(red, onethree, squigglediamond, open)</pre>
 
FOUND 4 SETS:
Card(green, two, diamond, open)
Card(greenpurple, threetwo, squiggle, stripedopen)
Card(purplered, two, squiggleoval, solidopen)
 
Card(green, onethree, oval, solid)
Card(greenpurple, onetwo, diamondsquiggle, solidopen)
Card(greenred, one, squigglediamond, solidstriped)
 
Card(green, onethree, squiggle, solidopen)
Card(greenpurple, two, squiggle, open)
Card(greenred, threeone, squiggle, stripedopen)
 
Card(greenred, threeone, ovalsquiggle, open)
Card(greenred, threetwo, diamondoval, solidopen)
Card(greenred, three, squigglediamond, stripedopen)</pre>
 
Card(green, three, squiggle, striped)
Card(purple, two, squiggle, solid)
Card(red, one, squiggle, open)</pre>
 
=={{header|J}}==