Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -1,4 +1,8 @@
Set Puzzles are created with a deck of cards from the [[wp:Set (game)|Set Game™]]. The object of the puzzle is to find sets of 3 cards in a rectangle of cards that have been dealt face up. There are 81 cards in a deck. Each card contains a unique variation of the following four features: ''color, symbol, number and shading''.
{{omit from|GUISS}}
Set Puzzles are created with a deck of cards from the [[wp:Set (game)|Set Game™]]. The object of the puzzle is to find sets of 3 cards in a rectangle of cards that have been dealt face up. <br>
There are 81 cards in a deck.
Each card contains a unique variation of the following four features: ''color, symbol, number and shading''.
; there are three colors: '''red''', '''green''', or '''purple'''
@ -8,9 +12,18 @@ Set Puzzles are created with a deck of cards from the [[wp:Set (game)|Set Game
; there are three shadings: '''solid''', '''open''', or '''striped'''
Three cards form a ''set'' if each feature is either the same on each card, or is different on each card. For instance: all 3 cards are red, all 3 cards have a different symbol, all 3 cards have a different number of symbols, all 3 cards are striped.
Three cards form a ''set'' if each feature is either the same on each card, or is different on each card. <br>
For instance: all 3 cards are red, all 3 cards have a different symbol, all 3 cards have a different number of symbols, all 3 cards are striped.
There are two degrees of difficulty: [http://www.setgame.com/set/rules_basic.htm ''basic''] and [http://www.setgame.com/set/rules_advanced.htm ''advanced'']. The basic mode deals 9 cards, that contain exactly 4 sets; the advanced mode deals 12 cards that contain exactly 6 sets. When creating sets you may use the same card more than once. The task is to write code that deals the cards (9 or 12, depending on selected mode) from a shuffled deck in which the total number of sets that could be found is 4 (or 6, respectively); and print the contents of the cards and the sets. For instance:
There are two degrees of difficulty: [http://www.setgame.com/set/rules_basic.htm ''basic''] and [http://www.setgame.com/set/rules_advanced.htm ''advanced'']. <br>
The basic mode deals 9 cards, that contain exactly 4 sets;
the advanced mode deals 12 cards that contain exactly 6 sets.
When creating sets you may use the same card more than once.
;The task:
Is to write code that deals the cards (9 or 12, depending on selected mode) from a shuffled deck in which the total number of sets that could be found is 4 (or 6, respectively); and print the contents of the cards and the sets.
For instance:
'''DEALT 9 CARDS:'''

View file

@ -0,0 +1,4 @@
---
category:
- Puzzles
note: Cards

View file

@ -0,0 +1,18 @@
package Set_Puzzle is
type Three is range 1..3;
type Card is array(1 .. 4) of Three;
type Cards is array(Positive range <>) of Card;
type Set is array(Three) of Positive;
procedure Deal_Cards(Dealt: out Cards);
-- ouputs an array with disjoint cards
function To_String(C: Card) return String;
generic
with procedure Do_something(C: Cards; S: Set);
procedure Find_Sets(Given: Cards);
-- calls Do_Something once for each set it finds.
end Set_Puzzle;

View file

@ -0,0 +1,78 @@
with Ada.Numerics.Discrete_Random;
package body Set_Puzzle is
package Rand is new Ada.Numerics.Discrete_Random(Three);
R: Rand.Generator;
function Locate(Some: Cards; C: Card) return Natural is
-- returns index of card C in Some, or 0 if not found
begin
for I in Some'Range loop
if C = Some(I) then
return I;
end if;
end loop;
return 0;
end Locate;
procedure Deal_Cards(Dealt: out Cards) is
function Random_Card return Card is
(Rand.Random(R), Rand.Random(R), Rand.Random(R), Rand.Random(R));
begin
for I in Dealt'Range loop
-- draw a random card until different from all card previously drawn
Dealt(I) := Random_Card; -- draw random card
while Locate(Dealt(Dealt'First .. I-1), Dealt(I)) /= 0 loop
-- Dealt(I) has been drawn before
Dealt(I) := Random_Card; -- draw another random card
end loop;
end loop;
end Deal_Cards;
procedure Find_Sets(Given: Cards) is
function To_Set(A, B: Card) return Card is
-- returns the unique card C, which would make a set with A and B
C: Card;
begin
for I in 1 .. 4 loop
if A(I) = B(I) then
C(I) := A(I); -- all three the same
else
C(I) := 6 - A(I) - B(I); -- all three different;
end if;
end loop;
return C;
end To_Set;
X: Natural;
begin
for I in Given'Range loop
for J in Given'First .. I-1 loop
X := Locate(Given, To_Set(Given(I), Given(J)));
if I < X then -- X=0 is no set, 0 < X < I is a duplicate
Do_Something(Given, (J, I, X));
end if;
end loop;
end loop;
end Find_Sets;
function To_String(C: Card) return String is
Col: constant array(Three) of String(1..6)
:= ("Red ", "Green ", "Purple");
Sym: constant array(Three) of String(1..8)
:= ("Oval ", "Squiggle", "Diamond ");
Num: constant array(Three) of String(1..5)
:= ("One ", "Two ", "Three");
Sha: constant array(Three) of String(1..7)
:= ("Solid ", "Open ", "Striped");
begin
return (Col(C(1)) & " " & Sym(C(2)) & " " & Num(C(3)) & " " & Sha(C(4)));
end To_String;
begin
Rand.Reset(R);
end Set_Puzzle;

View file

@ -0,0 +1,50 @@
with Ada.Text_IO, Set_Puzzle, Ada.Command_Line;
procedure Puzzle is
package TIO renames Ada.Text_IO;
Card_Count: Positive := Positive'Value(Ada.Command_Line.Argument(1));
Required_Sets: Positive := Positive'Value(Ada.Command_Line.Argument(2));
Cards: Set_Puzzle.Cards(1 .. Card_Count);
function Cnt_Sets(C: Set_Puzzle.Cards) return Natural is
Cnt: Natural := 0;
procedure Count_Sets(C: Set_Puzzle.Cards; S: Set_Puzzle.Set) is
begin
Cnt := Cnt + 1;
end Count_Sets;
procedure CS is new Set_Puzzle.Find_Sets(Count_Sets);
begin
CS(C);
return Cnt;
end Cnt_Sets;
procedure Print_Sets(C: Set_Puzzle.Cards) is
procedure Print_A_Set(C: Set_Puzzle.Cards; S: Set_Puzzle.Set) is
begin
TIO.Put("(" & Integer'Image(S(1)) & "," & Integer'Image(S(2))
& "," & Integer'Image(S(3)) & " ) ");
end Print_A_Set;
procedure PS is new Set_Puzzle.Find_Sets(Print_A_Set);
begin
PS(C);
TIO.New_Line;
end Print_Sets;
begin
loop -- deal random cards
Set_Puzzle.Deal_Cards(Cards);
exit when Cnt_Sets(Cards) = Required_Sets;
end loop; -- until number of sets is as required
for I in Cards'Range loop -- print the cards
if I < 10 then
TIO.Put(" ");
end if;
TIO.Put_Line(Integer'Image(I) & " " & Set_Puzzle.To_String(Cards(I)));
end loop;
Print_Sets(Cards); -- print the sets
end Puzzle;

View file

@ -1,12 +1,12 @@
import std.stdio, std.random, std.array, std.conv, std.traits,
std.exception;
std.exception, std.range, std.algorithm;
const 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}
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;
@ -15,40 +15,33 @@ const class SetDealer {
Fill f;
}
immutable Card[81] deck;
static immutable Card[81] deck;
}
this() pure nothrow {
Card[] tmpdeck;
static this() pure nothrow @safe {
immutable colors = [EnumMembers!Color];
immutable numbers = [EnumMembers!Number];
immutable symbols = [EnumMembers!Symbol];
immutable fill = [EnumMembers!Fill];
foreach (immutable i; 0 .. deck.length)
tmpdeck ~= Card(colors[i / 27],
numbers[(i / 9) % 3],
symbols[(i / 3) % 3],
fill[i % 3]);
// randomShuffle(tmpdeck); /* not pure nothrow */
deck = assumeUnique(tmpdeck);
deck = deck.length.iota.map!(i => Card(colors[i / 27],
numbers[(i / 9) % 3],
symbols[(i / 3) % 3],
fill[i % 3])).array;
}
// 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 deck[].randomSample(numCards).array();
enforce(numCards < deck.length, "Number of cards too large");
return deck[].randomSample(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)
const pure nothrow {
const pure nothrow @safe @nogc {
return !((c1.c + c2.c + c3.c) % 3 ||
(c1.n + c2.n + c3.n) % 3 ||
(c1.s + c2.s + c3.s) % 3 ||
@ -56,7 +49,7 @@ const class SetDealer {
}
immutable(Card)[3][] findSets(in Card[] cards, in uint target = 0)
const pure nothrow {
const pure nothrow @safe {
immutable len = cards.length;
if (len < 3)
return null;
@ -90,19 +83,14 @@ const final class SetPuzzleDealer : SetDealer {
}
void main() {
const dealer = new SetPuzzleDealer();
const cards = dealer.deal();
const dealer = new SetPuzzleDealer;
const cards = dealer.deal;
writefln("\nDEALT %d CARDS:\n", cards.length);
foreach (c; cards)
writeln(cast()c);
writefln("DEALT %d CARDS:", cards.length);
writefln("%(%s\n%)", cards);
immutable sets = dealer.findSets(cards);
immutable len = sets.length;
writefln("\nFOUND %d %s:\n", len, len == 1 ? "SET" : "SETS");
foreach (set; sets) {
foreach (c; set)
writeln(cast()c);
writeln();
}
writefln("\nFOUND %d SET%s:", len, len == 1 ? "" : "S");
writefln("%(%(%s\n%)\n\n%)", sets);
}

View file

@ -0,0 +1,19 @@
void main() {
import std.stdio, std.algorithm, std.range, std.random, combinations3;
enum nDraw = 9, nGoal = nDraw / 2;
auto deck = cartesianProduct("red green purple".split,
"one two three".split,
"oval squiggle diamond".split,
"solid open striped".split).array;
retry:
auto draw = deck.randomSample(nDraw).map!(t => [t[]]).array;
const sets = draw.combinations(3).filter!(cs => cs.dup
.transposed.all!(t => t.array.sort().uniq.count % 2)).array;
if (sets.length != nGoal)
goto retry;
writefln("Dealt %d cards:\n%(%-(%8s %)\n%)\n", draw.length, draw);
writefln("Containing:\n%(%(%-(%8s %)\n%)\n\n%)", sets);
}

View file

@ -6,11 +6,11 @@ import (
"time"
)
var (
number = []string{"1", "2", "3"}
color = []string{"red", "green", "purple"}
shade = []string{"solid", "open", "striped"}
shape = []string{"oval", "squiggle", "diamond"}
const (
number = [3]string{"1", "2", "3"}
color = [3]string{"red", "green", "purple"}
shade = [3]string{"solid", "open", "striped"}
shape = [3]string{"oval", "squiggle", "diamond"}
)
type card int
@ -25,15 +25,7 @@ func (c card) String() string {
func main() {
rand.Seed(time.Now().Unix())
basic()
advanced()
}
func basic() {
game("Basic", 9, 4)
}
func advanced() {
game("Advanced", 12, 6)
}
@ -59,7 +51,7 @@ func game(level string, cards, sets int) {
l3:
for _, c3 := range d[:j] {
for f := card(1); f < 81; f *= 3 {
if (c1/f%3+c2/f%3+c3/f%3)%3 != 0 {
if (c1/f%3 + c2/f%3 + c3/f%3) % 3 != 0 {
continue l3 // not a set
}
}
@ -77,9 +69,6 @@ func game(level string, cards, sets int) {
}
fmt.Println("Sets:")
for _, s := range found {
fmt.Println(" ", s[0])
fmt.Println(" ", s[1])
fmt.Println(" ", s[2])
fmt.Println()
fmt.Printf(" %s\n %s\n %s\n",s[0],s[1],s[2])
}
}

View file

@ -1,9 +1,9 @@
import java.util.*;
import org.apache.commons.lang3.ArrayUtils;
public class SetPuzzle {
enum Color {
GREEN(0), PURPLE(1), RED(2);
private Color(int v) {
@ -13,6 +13,7 @@ public class SetPuzzle {
}
enum Number {
ONE(0), TWO(1), THREE(2);
private Number(int v) {
@ -22,6 +23,7 @@ public class SetPuzzle {
}
enum Symbol {
OVAL(0), DIAMOND(1), SQUIGGLE(2);
private Symbol(int v) {
@ -31,6 +33,7 @@ public class SetPuzzle {
}
enum Fill {
OPEN(0), STRIPED(1), SOLID(2);
private Fill(int v) {
@ -40,20 +43,22 @@ public class SetPuzzle {
}
private static class Card implements Comparable<Card> {
Color c;
Number n;
Symbol s;
Fill f;
@Override
public String toString() {
return String.format("[Card: %s, %s, %s, %s]", c, n, s, f);
}
@Override
public int compareTo(Card o) {
return (c.val - o.c.val) * 10 + (n.val - o.n.val);
}
}
private static Card[] deck;
public static void main(String[] args) {
@ -79,7 +84,7 @@ public class SetPuzzle {
int cnt;
do {
Collections.shuffle(Arrays.asList(deck));
cards = ArrayUtils.subarray(deck, 0, numCards);
cards = Arrays.copyOfRange(deck, 0, numCards);
cnt = 0;
outer:

View file

@ -0,0 +1,18 @@
colors = {Red, Green, Purple};
symbols = {"0", "\[TildeTilde]", "\[Diamond]"};
numbers = {1, 2, 3};
shadings = {"\[FilledSquare]", "\[Square]", "\[DoublePrime]"};
validTripleQ[l_List] := Entropy[l] != Entropy[{1, 1, 2}];
validSetQ[cards_List] := And @@ (validTripleQ /@ Transpose[cards]);
allCards = Tuples[{colors, symbols, numbers, shadings}];
deal[{numDeal_, setNum_}] := Module[{cards, count = 0},
While[count != setNum,
cards = RandomSample[allCards, numDeal];
count = Count[Subsets[cards, {3}], _?validSetQ]];
cards];
Row[{Style[#2, #1], #3, #4}] & @@@ deal[{9, 4}]

View file

@ -0,0 +1,21 @@
import random, pprint
from itertools import product, combinations
N_DRAW = 9
N_GOAL = N_DRAW // 2
deck = list(product("red green purple".split(),
"one two three".split(),
"oval squiggle diamond".split(),
"solid open striped".split()))
sets = []
while len(sets) != N_GOAL:
draw = random.sample(deck, N_DRAW)
sets = [cs for cs in combinations(draw, 3)
if all(len(set(t)) in [1, 3] for t in zip(*cs))]
print "Dealt %d cards:" % len(draw)
pprint.pprint(draw)
print "\nContaining %d sets:" % len(sets)
pprint.pprint(sets)

View file

@ -0,0 +1,99 @@
/*REXX program finds "sets" (solutions) for the SET puzzle (game). */
parse arg game seed . /*get optional # cards to deal. */
if game ==',' | game=='' then game=9 /*Not specified? Then use default*/
if seed==',' | seed=='' then seed=77 /* " " " " " */
call aGame 0 /*with tell=0, suppress output. */
call aGame 1 /*with tell=1, allow output. */
exit sets /*stick a fork in it, we're done.*/
/*──────────────────────────────────AGAME subroutine────────────────────*/
aGame: tell=arg(1); good=game%2 /*enable or disable the output. */
/* [↑] GOOD is the right # sets.*/
do seed=seed until good==sets /*generate deals until good# sets*/
call random ,,seed /*repeatability for last invoke. */
call genFeatures /*generate various card features.*/
call genDeck /*generate a deck (with 81 cards)*/
call dealer game /*deal a number of cards (game). */
call findSets game%2 /*find sets from the dealt cards.*/
end /*until*/ /*when leaving, SETS is right num*/
return /*return to invoker of this sub. */
/*──────────────────────────────────DEALER subroutine───────────────────*/
dealer: call sey 'dealing' game "cards:",,. /*shuffle and deal cards*/
do cards=1 until cards==game /*keep dealing 'til done*/
_=random(1,words(##)); ##=delword(##,_,1) /*pick card; delete it. */
@.cards=deck._ /*add it to the tableau.*/
call sey right('card' cards,30) " " @.cards /*display card to screen*/
do j=1 for words(@.cards) /*define cells for card.*/
@.cards.j=word(@.cards,j) /*define a cell for card*/
end /*j*/
end /*cards*/
return
/*──────────────────────────────────DEFFEATURES subroutine──────────────*/
defFeatures: parse arg what,v; _=words(v) /*obtain what to define.*/
if _\==values then do; call sey 'error,' what "features ¬=" values,.,.
exit -1
end /* [↑] check for typos.*/
do k=1 for words(values) /*define all possibles. */
call value what'.'k, word(values,k) /*define a card feature.*/
end /*k*/
return
/*──────────────────────────────────GENDECK subroutine──────────────────*/
genDeck: #=0; ##= /*#cards in deck; ##=shuffle aid.*/
do num=1 for values; xnum=word(numbers, num)
do col=1 for values; xcol=word(colors, col)
do sym=1 for values; xsym=word(symbols, sym)
do sha=1 for values; xsha=word(shadings, sha)
#=#+1; ##=## #; deck.#=xnum xcol xsym xsha /*create a card.*/
end /*sha*/
end /*num*/
end /*sym*/
end /*col*/
return /*#: the number of cards in deck.*/
/*──────────────────────────────────GENFEATURES subroutine──────────────*/
genFeatures: features=3; groups=4; values=3 /*define # feats,grps,vals*/
numbers = 'one two three' ; call defFeatures 'number', numbers
colors = 'red green purple' ; call defFeatures 'color', colors
symbols = 'oval squiggle diamond' ; call defFeatures 'symbol', symbols
shadings= 'solid open striped' ; call defFeatures 'shading', shadings
return
/*──────────────────────────────────GENPOSS subroutine──────────────────*/
genPoss: p=0; sets=0; sep=' '; !.= /*define some REXX variables.*/
do i=1 for game /* [↓] the IFs eliminate dups.*/
do j=i+1 to game; if j==i then iterate
do k=j+1 to game; if k==j | k==i then iterate
p=p+1; !.p.1=@.i; !.p.2=@.j; !.p.3=@.k
end /*k*/
end /*j*/
end /*i*/ /* [↑] build permutation list. */
return
/*──────────────────────────────────FINDSETS subroutine─────────────────*/
findSets: parse arg n; call genPoss /*N: the number of sets to find.*/
call sey /*find any sets generated above. */
do j=1 for p /*P is the # of possible sets. */
do f=1 for features
do g=1 for groups; !!.j.f.g=word(!.j.f, g)
end /*g*/
end /*f*/
ok=1 /*everything is OK so far. */
do g=1 for groups; _=!!.j.1.g /*generate strings to hole poss. */
equ=1 /* [↓] handles all equal feats. */
do f=2 to features while equ; equ=equ & _==!!.j.f.g
end /*f*/
dif=1
__=!!.j.1.g /* [↓] handles all unequal feats*/
do f=2 to features while \equ
dif=dif & wordpos(!!.j.f.g,__)==0
__=__ !!.j.f.g /*append to string for next test.*/
end /*f*/
ok=ok&(equ|dif) /*now, see if all equal | unequal*/
end /*g*/
if \ok then iterate /*Is this set OK? Nope, skip it.*/
sets=sets+1 /*bump the number of sets found. */
call sey right('set' sets": ",15) !.j.1 sep !.j.2 sep !.j.3
end /*j*/
call sey sets 'sets found.',.
return
/*──────────────────────────────────SEY subroutine──────────────────────*/
sey: if \tell then return /*should output be suppressed? */
if arg(2)==. then say; say arg(1); if arg(3)==. then say; return