Set puzzle: Difference between revisions

50,898 bytes added ,  3 months ago
m
m (→‎{{header|REXX}}: changed wording in the REXX section header.)
m (→‎{{header|Wren}}: Minor tidy)
 
(19 intermediate revisions by 12 users not shown)
Line 75:
:purple, three, oval, open
<br><br>
 
=={{header|Acornsoft Lisp}}==
 
<syntaxhighlight lang="lisp">
(setq numbers '(one two three))
(setq shadings '(solid open striped))
(setq colours '(red green purple))
(setq symbols '(oval squiggle diamond))
 
(defun play ((n-cards . 9))
(find-enough-sets n-cards (quotient n-cards 2)))
 
(defun find-enough-sets (n-cards enough (deal) (sets))
(loop
(setq deal (random-sample n-cards (deck)))
(setq sets (find-sets deal))
(while (lessp (length sets) enough)
(show-cards deal)
(printc)
(show-sets sets))))
 
(defun show-cards (cards)
(printc (length cards) '! cards)
(map printc cards))
 
(defun show-sets (sets)
(printc (length sets) '! sets)
(map '(lambda (set)
(printc)
(map printc set))
sets))
 
(defun find-sets (deal)
(keep-if is-set (combinations 3 deal)))
 
(defun is-set (cards)
(every feature-makes-set (transpose cards)))
 
(defun feature-makes-set (feature-values)
(or (all-same feature-values)
(all-different feature-values)))
 
(defun combinations (n items)
(cond
((zerop n) '(()))
((null items) '())
(t (append
(mapc '(lambda (c) (cons (car items) c))
(combinations (sub1 n) (cdr items)))
(combinations n (cdr items))))))
 
'( Making a deck )
 
(defun deck ()
' ( The deck has to be made only once )
(cond ((get 'deck 'cards))
(t (put 'deck 'cards (make-deck)))))
 
(defun make-deck ()
(add-feature numbers
(add-feature shadings
(add-feature colours
(add-feature symbols
(list '()))))))
 
(defun add-feature (values deck)
(flatmap '(lambda (value)
(mapc '(lambda (card) (cons value card))
deck))
values))
 
'( Utilities )
 
(defun all-same (values)
(every '(lambda (v) (eq v (car values)))
values))
 
(defun all-different (values)
(every '(lambda (v) (onep (count v values)))
values))
 
(defun count (v values (n . 0))
(loop (until (null values) n)
(cond ((eq (car values) v) (setq n (add1 n))))
(setq values (cdr values))))
(defun every (test suspects)
(or (null suspects)
(and (test (car suspects))
(every test (cdr suspects)))))
 
(defun transpose (rows)
(apply mapc (cons list rows)))
 
(defun reverse (list (result . ()))
(map '(lambda (e) (setq result (cons e result)))
list)
result)
 
(defun append (a b)
(reverse (reverse a) b))
 
(defun flatmap (_f_ _list_)
(cond ((null _list_) '())
(t (append (_f_ (car _list_))
(flatmap _f_ (cdr _list_))))))
 
(defun keep-if (_p_ _items_ (_to_keep_))
(map '(lambda (_i_)
(cond ((_p_ _i_)
(setq _to_keep_ (cons _i_ _to_keep_)))))
_items_)
(reverse _to_keep_))
</syntaxhighlight>
 
{{Out}}
 
Calling <code>(play)</code> will output:
 
<pre>
9 cards
(three open red oval)
(three solid green diamond)
(two solid red squiggle)
(one open red oval)
(two striped green oval)
(one striped red diamond)
(three solid purple oval)
(one solid purple oval)
(three solid purple diamond)
 
4 sets
 
(three open red oval)
(two solid red squiggle)
(one striped red diamond)
 
(three open red oval)
(two striped green oval)
(one solid purple oval)
 
(three solid green diamond)
(two solid red squiggle)
(one solid purple oval)
 
(one open red oval)
(two striped green oval)
(three solid purple oval)
</pre>
 
=={{header|Ada}}==
Line 80 ⟶ 229:
We start with the specification of a package "Set_Puzzle.
 
<langsyntaxhighlight Adalang="ada">package Set_Puzzle is
type Three is range 1..3;
Line 97 ⟶ 246:
-- calls Do_Something once for each set it finds.
end Set_Puzzle;</langsyntaxhighlight>
 
Now we implement the package "Set_Puzzle".
 
<langsyntaxhighlight Adalang="ada">with Ada.Numerics.Discrete_Random;
 
package body Set_Puzzle is
Line 178 ⟶ 327:
begin
Rand.Reset(R);
end Set_Puzzle;</langsyntaxhighlight>
 
Finally, we write the main program, using the above package. It reads two parameters from the command line. The first parameter describes the number of cards, the second one the number of sets. Thus, for the basic mode one has to call "puzzle 9 4", for the advanced mode "puzzle 12 6", but the program would support any other combination of parameters just as well.
 
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO, Set_Puzzle, Ada.Command_Line;
 
procedure Puzzle is
Line 231 ⟶ 380:
Print_Sets(Cards); -- print the sets
end Puzzle;</langsyntaxhighlight>
 
{{out}}
Line 263 ⟶ 412:
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight lang="autohotkey">; Generate deck; card encoding from Raku
Loop, 81
deck .= ToBase(A_Index-1, 3)+1111 ","
Line 366 ⟶ 515:
c%j% += 1
}
}</langsyntaxhighlight>
{{out|Sample output}}
<pre>Dealt 9 cards:
Line 446 ⟶ 595:
=={{header|C}}==
Brute force. Each card is a unique number in the range of [0,81]. Randomly deal a hand of cards until exactly the required number of sets are found.
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
 
Line 540 ⟶ 689:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp}}==
{{works with|C sharp|8}}
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using static System.Linq.Enumerable;
Line 628 ⟶ 777:
static bool AreSameOrDifferent(int a, int b, int c) => (a + b + c) % 3 == 0;
static IEnumerable<int> To(this int start, int end) => Range(start, end - start - 1);
}</langsyntaxhighlight>
{{out}}
<pre style="height:30ex;overflow:scroll">
Line 673 ⟶ 822:
=={{header|C++}}==
{{trans|Java}}
<langsyntaxhighlight lang="cpp">
#include <time.h>
#include <algorithm>
Line 805 ⟶ 954:
return 0;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 880 ⟶ 1,029:
=={{header|Ceylon}}==
Add import ceylon.random "1.3.3" to your module.ceylon file
<langsyntaxhighlight lang="ceylon">import ceylon.random {
Random,
DefaultRandom
Line 1,019 ⟶ 1,168:
}
 
}</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
{{trans|Acornsoft Lisp}}
 
<syntaxhighlight lang="lisp">
(defparameter numbers '(one two three))
(defparameter shadings '(solid open striped))
(defparameter colours '(red green purple))
(defparameter symbols '(oval squiggle diamond))
 
(defun play (&optional (n-cards 9))
(find-enough-sets n-cards (floor n-cards 2)))
 
(defun find-enough-sets (n-cards enough)
(loop
(let* ((deal (random-sample n-cards (deck)))
(sets (find-sets deal)))
(when (>= (length sets) enough)
(show-cards deal)
(show-sets sets)
(return t)))))
 
(defun show-cards (cards)
(format t "~D cards~%~{~(~{~10S~}~)~%~}~%"
(length cards) cards))
 
(defun show-sets (sets)
(format t "~D sets~2%~:{~(~@{~{~8S~}~%~}~)~%~}"
(length sets) sets))
 
(defun find-sets (deal)
(remove-if-not #'is-set (combinations 3 deal)))
 
(defun is-set (cards)
(every #'feature-makes-set (transpose cards)))
 
(defun feature-makes-set (feature-values)
(or (all-same feature-values)
(all-different feature-values)))
 
(defun combinations (n items)
(cond
((zerop n) '(()))
((null items) '())
(t (append
(mapcar (lambda (c) (cons (car items) c))
(combinations (1- n) (cdr items)))
(combinations n (cdr items))))))
 
;;; Making a deck
 
(defun deck ()
;; The deck has to be made only once
(or (get 'deck 'cards)
(setf (get 'deck 'cards) (make-deck))))
 
(defun make-deck ()
(add-feature numbers
(add-feature shadings
(add-feature colours
(add-feature symbols
(list '()))))))
 
(defun add-feature (values deck)
(mapcan (lambda (value)
(mapcar (lambda (card) (cons value card))
deck))
values))
 
;;; Utilities
 
(defun random-sample (n items)
(let ((len (length items))
(taken '()))
(dotimes (_ n)
(loop
(let ((i (random len)))
(unless (find i taken)
(setq taken (cons i taken))
(return)))))
(mapcar (lambda (i) (nth i items)) taken)))
 
(defun all-same (values)
(every #'eql values (rest values)))
 
(defun all-different (values)
(every (lambda (v) (= (count v values) 1))
values))
 
(defun transpose (rows)
(apply #'mapcar #'list rows))
</syntaxhighlight>
 
{{Out}}
 
Calling <code>(play 12)</code> will output:
 
<pre>
12 cards
two open red oval
three solid red squiggle
one striped red oval
three solid green squiggle
three solid green diamond
three solid red oval
one open purple squiggle
two solid red diamond
three open red squiggle
two striped green diamond
two striped red squiggle
three solid purple oval
 
6 sets
 
two open red oval
one striped red oval
three solid red oval
 
two open red oval
two solid red diamond
two striped red squiggle
 
three solid red squiggle
three solid green diamond
three solid purple oval
 
one striped red oval
two solid red diamond
three open red squiggle
 
three solid green squiggle
one open purple squiggle
two striped red squiggle
 
three solid red oval
one open purple squiggle
two striped green diamond
</pre>
 
=={{header|D}}==
===Basic Version===
<langsyntaxhighlight lang="d">import std.stdio, std.random, std.array, std.conv, std.traits,
std.exception, std.range, std.algorithm;
 
Line 1,118 ⟶ 1,405:
writefln("\nFOUND %d SET%s:", len, len == 1 ? "" : "S");
writefln("%(%(%s\n%)\n\n%)", sets);
}</langsyntaxhighlight>
{{out|Sample output}}
<pre>DEALT 9 CARDS:
Line 1,150 ⟶ 1,437:
===Short Version===
This requires the third solution module of the Combinations Task.
<langsyntaxhighlight lang="d">void main() {
import std.stdio, std.algorithm, std.range, std.random, combinations3;
 
Line 1,168 ⟶ 1,455:
writefln("Dealt %d cards:\n%(%-(%8s %)\n%)\n", draw.length, draw);
writefln("Containing:\n%(%(%-(%8s %)\n%)\n\n%)", sets);
}</langsyntaxhighlight>
{{out}}
<pre>Dealt 9 cards:
Line 1,197 ⟶ 1,484:
purple one squiggle striped
green three diamond striped</pre>
 
=={{header|EasyLang}}==
<syntaxhighlight>
attr$[][] &= [ "one " "two " "three" ]
attr$[][] &= [ "solid " "striped" "open " ]
attr$[][] &= [ "red " "green " "purple" ]
attr$[][] &= [ "diamond" "oval" "squiggle" ]
#
subr init
for card = 0 to 80
pack[] &= card
.
.
proc card2attr card . attr[] .
attr[] = [ ]
for i to 4
attr[] &= card mod 3 + 1
card = card div 3
.
.
proc printcards cards[] . .
for card in cards[]
card2attr card attr[]
for i to 4
write attr$[i][attr[i]] & " "
.
print ""
.
print ""
.
proc getsets . cards[] set[] .
set[] = [ ]
for i to len cards[]
card2attr cards[i] a[]
for j = i + 1 to len cards[]
card2attr cards[j] b[]
for k = j + 1 to len cards[]
card2attr cards[k] c[]
ok = 1
for at to 4
s = a[at] + b[at] + c[at]
if s <> 3 and s <> 6 and s <> 9
ok = 0
.
.
if ok = 1
set[] &= cards[i]
set[] &= cards[j]
set[] &= cards[k]
.
.
.
.
.
proc run ncards nsets . .
#
repeat
init
cards[] = [ ]
for i to ncards
ind = random len pack[]
cards[] &= pack[ind]
pack[ind] = pack[len pack[]]
len pack[] -1
.
getsets cards[] set[]
until len set[] = 3 * nsets
.
print "Cards:"
printcards cards[]
print "Sets:"
for i = 1 step 3 to 3 * nsets - 2
printcards [ set[i] set[i + 1] set[i + 2] ]
.
.
run 9 4
print " --------------------------"
run 12 6
</syntaxhighlight>
 
=={{header|EchoLisp}}==
<langsyntaxhighlight lang="scheme">
(require 'list)
 
Line 1,250 ⟶ 1,616:
))
 
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,311 ⟶ 1,677:
=={{header|Elixir}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="elixir">defmodule RC do
def set_puzzle(deal, goal) do
{puzzle, sets} = get_puzzle_and_answer(deal, goal, produce_deck)
Line 1,364 ⟶ 1,730:
 
RC.set_puzzle(9, 4)
RC.set_puzzle(12, 6)</langsyntaxhighlight>
 
{{out}}
Line 1,438 ⟶ 1,804:
=={{header|Erlang}}==
Until a better solution is found this is one.
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( set ).
 
Line 1,522 ⟶ 1,888:
make_sets_acc( true, Set, Sets ) -> [Set | Sets];
make_sets_acc( false, _Set, Sets ) -> Sets.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,582 ⟶ 1,948:
 
=={{header|F Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">open System
 
type Number = One | Two | Three
Line 1,663 ⟶ 2,029:
solve 12 6
 
playGame()</langsyntaxhighlight>
Output:
<pre>
Line 1,734 ⟶ 2,100:
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: arrays backtrack combinators.short-circuit formatting
fry grouping io kernel literals math.combinatorics math.matrices
prettyprint qw random sequences sets ;
Line 1,775 ⟶ 2,141:
12 6 set-puzzle ;
 
MAIN: main</langsyntaxhighlight>
{{out}}
<pre style="height:65ex">
Line 1,847 ⟶ 2,213:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,920 ⟶ 2,286:
fmt.Printf(" %s\n %s\n %s\n",s[0],s[1],s[2])
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,992 ⟶ 2,358:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Control.Monad.State
(State, evalState, replicateM, runState, state)
import System.Random (StdGen, newStdGen, randomR)
Line 2,094 ⟶ 2,460:
main = do
showSolutions 9 4
showSolutions 12 6</langsyntaxhighlight>
{{out}}
<pre style="font-size:80%">Showing hand of 9 cards with 4 solutions.
Line 2,167 ⟶ 2,533:
=={{header|J}}==
'''Solution:'''
<langsyntaxhighlight lang="j">require 'stats/base'
 
Number=: ;:'one two three'
Line 2,190 ⟶ 2,556:
echo LF,'Found ',(":target),' Sets:'
echo sayCards sort"2 getSets Hand
)</langsyntaxhighlight>
 
'''Example:'''
<langsyntaxhighlight lang="j"> set_puzzle 9
Dealt 9 Cards:
one, red, solid, oval
Line 2,220 ⟶ 2,586:
three, red, open, oval
three, green, solid, oval
three, purple, striped, oval </langsyntaxhighlight>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.util.*;
 
public class SetPuzzle {
Line 2,353 ⟶ 2,719:
return tot == 0;
}
}</langsyntaxhighlight>
<pre>GIVEN 12 CARDS:
 
Line 2,397 ⟶ 2,763:
=={{header|Julia}}==
Plays one basic game and one advanced game.
<langsyntaxhighlight lang="julia">using Random, IterTools, Combinatorics
 
function SetGameTM(basic = true)
Line 2,440 ⟶ 2,806:
SetGameTM()
SetGameTM(false)
</langsyntaxhighlight> {{output}} <pre>
Dealt 9 cards:
("green", "one", "oval", "open")
Line 2,510 ⟶ 2,876:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.3
 
import java.util.Collections.shuffle
Line 2,598 ⟶ 2,964:
println()
playGame(Degree.ADVANCED)
}</langsyntaxhighlight>
 
Sample output:
Line 2,675 ⟶ 3,041:
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
A simple brute force approach. This code highlights two things: 1) a few of Mathematica's "higher-level" functions such as Tuples and Subsets and 2) the straightforwardness enabled by the language's "dynamic typing" (more precisely, its symbolic semantics) and its usage of lists for everything (in this particular example, the fact that functions such as Tuples and Entropy can be used on lists with arbitrary content).
 
<langsyntaxhighlight Mathematicalang="mathematica">colors = {Red, Green, Purple};
symbols = {"0", "\[TildeTilde]", "\[Diamond]"};
numbers = {1, 2, 3};
Line 2,692 ⟶ 3,058:
cards = RandomSample[allCards, numDeal];
count = Count[Subsets[cards, {3}], _?validSetQ]];
cards];
Row[{Style[#2, #1], #3, #4}] & @@@ deal[{9, 4}]</syntaxhighlight>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">import algorithm, math, random, sequtils, strformat, strutils
 
type
 
# Card features.
Number {.pure.} = enum One, Two, Three
Color {.pure.} = enum Red, Green, Purple
Symbol {.pure.} = enum Oval, Squiggle, Diamond
Shading {.pure.} = enum Solid, Open, Striped
 
# Cards and list of cards.
Card = tuple[number: Number; color: Color; symbol: Symbol; shading: Shading]
Triplet = array[3, Card]
Deck = array[81, Card]
 
# Game level.
Level {.pure.} = enum Basic = "basic", Advanced = "advanced"
 
 
proc `$`(card: Card): string =
## Return the string representation of a card.
toLowerAscii(&"{card.number:<5} {card.color:<6} {card.symbol:<8} {card.shading:<7}")
 
 
proc initDeck(): Deck =
## Create a new deck.
var i = 0
for num in Number.low..Number.high:
for col in Color.low..Color.high:
for sym in Symbol.low..Symbol.high:
for sh in Shading.low..Shading.high:
result[i] = (number: num, color: col, symbol: sym, shading: sh)
inc i
 
 
proc isSet(triplet: Triplet): bool =
## Check if a triplets of cards is a set.
sum(triplet.mapIt(ord(it.number))) mod 3 == 0 and
sum(triplet.mapIt(ord(it.color))) mod 3 == 0 and
sum(triplet.mapIt(ord(it.symbol))) mod 3 == 0 and
sum(triplet.mapIt(ord(it.shading))) mod 3 == 0
 
 
proc playGame(level: Level) =
## Play the game at given level.
 
var deck = initDeck()
let (nCards, nSets) = if level == Basic: (9, 4) else: (12, 6)
var sets: seq[Triplet]
var hand: seq[Card]
echo &"Playing {level} game: {nCards} cards, {nSets} sets."
 
block searchHand:
while true:
sets.setLen(0)
deck.shuffle()
hand = deck[0..<nCards]
block countSets:
for i in 0..(nCards - 3):
for j in (i + 1)..(nCards - 2):
for k in (j + 1)..(nCards - 1):
let triplet = [hand[i], hand[j], hand[k]]
if triplet.isSet():
sets.add triplet
if sets.len > nSets:
break countSets # Too much sets. Try with a new hand.
if sets.len == nSets:
break searchHand # Found: terminate search.
 
# Display the hand and the sets.
echo "\nCards:"
for card in sorted(hand): echo " ", card
echo "\nSets:"
for s in sets:
for card in sorted(s): echo " ", card
echo()
 
 
randomize()
playGame(Basic)
echo()
playGame(Advanced)</syntaxhighlight>
 
{{out}}
<pre>Playing basic game: 9 cards, 4 sets.
 
Cards:
one purple oval solid
one purple diamond open
two red squiggle open
two green diamond open
two green diamond striped
two purple oval open
three red diamond solid
three red diamond open
three purple squiggle open
 
Sets:
one purple diamond open
two purple oval open
three purple squiggle open
 
one purple diamond open
two green diamond striped
three red diamond solid
 
two red squiggle open
two green diamond open
two purple oval open
 
one purple diamond open
two green diamond open
three red diamond open
 
 
Playing advanced game: 12 cards, 6 sets.
 
Cards:
one green diamond striped
one purple diamond striped
two red oval open
two red diamond open
two green oval solid
two green oval striped
three red squiggle striped
three green oval solid
three green squiggle solid
three green squiggle open
three green squiggle striped
three purple diamond open
 
Sets:
one green diamond striped
two green oval striped
three green squiggle striped
 
one purple diamond striped
two green oval striped
three red squiggle striped
 
one green diamond striped
two green oval solid
three green squiggle open
 
one purple diamond striped
two red oval open
three green squiggle solid
 
three green squiggle solid
three green squiggle open
three green squiggle striped
 
three red squiggle striped
Row[{Style[#2, #1], #3, #4}] & @@@ deal[{9, 4}]</lang>
three green oval solid
three purple diamond open</pre>
 
=={{header|PARI/GP}}==
<langsyntaxhighlight lang="parigp">dealraw(cards)=vector(cards,i,vector(4,j,1<<random(3)));
howmany(a,b,c)=hammingweight(bitor(a,bitor(b,c)));
name(v)=Str(["red","green",0,"purple"][v[1]],", ",["oval","squiggle",0,"diamond"][v[2]],", ",["one","two",0,"three"][v[3]],", ",["solid","open",0,"striped"][v[4]]);
Line 2,725 ⟶ 3,246:
};
deal(9,4)
deal(12,6)</langsyntaxhighlight>
{{output}}
<pre>green, diamond, one, open
Line 2,795 ⟶ 3,316:
It's actually slightly simplified, since generating Enum classes
and objects would be overkill for this particular task.
<langsyntaxhighlight lang="perl">#!perl
use strict;
use warnings;
Line 2,874 ⟶ 3,395:
 
__END__
</syntaxhighlight>
</lang>
{{out}}
<pre>Drew 12 cards:
Line 2,904 ⟶ 3,425:
=={{header|Phix}}==
Converts cards 1..81 (that idea from C) to 1/2/4 [/7] (that idea from Perl) but inverts the validation
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function comb(sequence pool, integer needed, sequence res={}, integer done=0, sequence chosen={})
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
if needed=0 then -- got a full set
<span style="color: #008080;">function</span> <span style="color: #000000;">comb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">pool</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">needed</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">={},</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">done</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">chosen</span><span style="color: #0000FF;">={})</span>
sequence {a,b,c} = chosen
<span style="color: #008080;">if</span> <span style="color: #000000;">needed</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- got a full set</span>
if not find_any({3,5,6},flatten(sq_or_bits(sq_or_bits(a,b),c))) then
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">chosen</span>
res = append(res,chosen)
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find_any</span><span style="color: #0000FF;">({</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">},</span><span style="color: #7060A8;">flatten</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_or_bits</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_or_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">),</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)))</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">chosen</span><span style="color: #0000FF;">)</span>
elsif done+needed<=length(pool) then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
-- get all combinations with and without the next item:
<span style="color: #008080;">elsif</span> <span style="color: #000000;">done</span><span style="color: #0000FF;">+</span><span style="color: #000000;">needed</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
done += 1
<span style="color: #000080;font-style:italic;">-- get all combinations with and without the next item:</span>
res = comb(pool,needed-1,res,done,append(chosen,pool[done]))
<span style="color: #000000;">done</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
res = comb(pool,needed,res,done,chosen)
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">comb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">,</span><span style="color: #000000;">needed</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">done</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">chosen</span><span style="color: #0000FF;">),</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">[</span><span style="color: #000000;">done</span><span style="color: #0000FF;">]))</span>
end if
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">comb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">,</span><span style="color: #000000;">needed</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">done</span><span style="color: #0000FF;">,</span><span style="color: #000000;">chosen</span><span style="color: #0000FF;">)</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant m124 = {1,2,4}
 
<span style="color: #008080;">constant</span> <span style="color: #000000;">m124</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}</span>
function card(integer n)
--returns the nth card (n is 1..81, res is length 4 of 1/2/4)
<span style="color: #008080;">function</span> <span style="color: #000000;">card</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
n -= 1
<span style="color: #000080;font-style:italic;">--returns the nth card (n is 1..81, res is length 4 of 1/2/4)</span>
sequence res = repeat(0,4)
<span style="color: #000000;">n</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
for i=1 to 4 do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
res[i] = m124[remainder(n,3)+1]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
n = floor(n/3)
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m124</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
end for
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant colours = {"red", "green", 0, "purple"},
symbols = {"oval", "squiggle", 0, "diamond"},
<span style="color: #008080;">constant</span> <span style="color: #000000;">colours</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"red"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"green"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"purple"</span><span style="color: #0000FF;">},</span>
numbers = {"one", "two", 0, "three"},
<span style="color: #000000;">symbols</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"oval"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"squiggle"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"diamond"</span><span style="color: #0000FF;">},</span>
shades = {"solid", "open", 0, "striped"}
<span style="color: #000000;">numbers</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"one"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"two"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"three"</span><span style="color: #0000FF;">},</span>
 
<span style="color: #000000;">shades</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"solid"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"open"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"striped"</span><span style="color: #0000FF;">}</span>
procedure print_cards(sequence hand, sequence cards)
for i=1 to length(cards) do
<span style="color: #008080;">procedure</span> <span style="color: #000000;">print_cards</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">hand</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">cards</span><span style="color: #0000FF;">)</span>
integer {c,m,n,g} = cards[i],
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cards</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
id = find(cards[i],hand)
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cards</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span>
printf(1,"%3d: %-7s %-9s %-6s %s\n",{id,colours[c],symbols[m],numbers[n],shades[g]})
<span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cards</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3d: %-7s %-9s %-6s %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">colours</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">],</span><span style="color: #000000;">symbols</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m</span><span style="color: #0000FF;">],</span><span style="color: #000000;">numbers</span><span style="color: #0000FF;">[</span><span style="color: #000000;">n</span><span style="color: #0000FF;">],</span><span style="color: #000000;">shades</span><span style="color: #0000FF;">[</span><span style="color: #000000;">g</span><span style="color: #0000FF;">]})</span>
printf(1,"\n")
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end procedure
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
procedure play(integer cards=9, integer sets=4)
integer deals = 1
<span style="color: #008080;">procedure</span> <span style="color: #000000;">play</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">cards</span><span style="color: #0000FF;">=</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
while 1 do
<span style="color: #004080;">integer</span> <span style="color: #000000;">deals</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
sequence deck = shuffle(tagset(81))
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
sequence hand = deck[1..cards]
<span style="color: #004080;">sequence</span> <span style="color: #000000;">deck</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">81</span><span style="color: #0000FF;">))</span>
for i=1 to length(hand) do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">hand</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">deck</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">cards</span><span style="color: #0000FF;">]</span>
hand[i] = card(hand[i])
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">hand</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">card</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
sequence res = comb(hand,3)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if length(res)=sets then
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">comb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
printf(1,"dealt %d cards (%d deals)\n",{cards,deals})
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">sets</span> <span style="color: #008080;">then</span>
print_cards(hand,hand)
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"dealt %d cards (%d deals)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">cards</span><span style="color: #0000FF;">,</span><span style="color: #000000;">deals</span><span style="color: #0000FF;">})</span>
printf(1,"with %d sets\n",{sets})
<span style="color: #000000;">print_cards</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">)</span>
for i=1 to sets do
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"with %d sets\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">})</span>
print_cards(hand,res[i])
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">sets</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">print_cards</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
exit
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end if
<span style="color: #008080;">exit</span>
deals += 1
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #000000;">deals</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
play()
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
--play(12,6)
<span style="color: #000000;">play</span><span style="color: #0000FF;">()</span>
--play(9,6)</lang>
<span style="color: #000080;font-style:italic;">--play(12,6)
--play(9,6)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 3,000 ⟶ 3,524:
8: red diamond two open
</pre>
 
=={{header|Picat}}==
The problem generator check that it problem has exactly one solution, so that step can take a little time (some seconds). <code>fail/0</code> is used to check for unicity of the solution.
<syntaxhighlight lang="picat">import util.
import cp.
 
%
% Solve the task in the description.
%
go ?=>
sets(1,Sets,SetLen,NumSets),
print_cards(Sets),
set_puzzle(Sets,SetLen,NumSets,X),
print_sol(Sets,X),
nl,
fail, % check for other solutions
nl.
go => true.
 
%
% Generate and solve a random instance with NumCards cards,
% giving exactly NumSets sets.
%
go2 =>
_ = random2(),
NumCards = 9, NumSets = 4, SetLen = 3,
generate_and_solve(NumCards,NumSets,SetLen),
fail, % prove unicity
nl.
 
go3 =>
_ = random2(),
NumCards = 12, NumSets = 6, SetLen = 3,
generate_and_solve(NumCards,NumSets,SetLen),
fail, % prove unicity)
nl.
 
%
% Solve a Set Puzzle.
%
set_puzzle(Cards,SetLen,NumWanted, X) =>
Len = Cards.length,
NumFeatures = Cards[1].length,
 
X = new_list(NumWanted),
foreach(I in 1..NumWanted)
Y = new_array(SetLen),
foreach(J in 1..SetLen)
member(Y[J], 1..Len)
end,
% unicity and symmetry breaking of Y
increasing2(Y),
% ensure unicity of the selected cards in X
if I > 1 then
foreach(J in 1..I-1) X[J] @< Y end
end,
foreach(F in 1..NumFeatures)
Z = [Cards[Y[J],F] : J in 1..SetLen],
(allequal(Z) ; alldiff(Z))
end,
X[I] = Y
end.
 
% (Strictly) increasing
increasing2(List) =>
foreach(I in 1..List.length-1)
List[I] @< List[I+1]
end.
 
% All elements must be equal
allequal(List) =>
foreach(I in 1..List.length-1)
List[I] = List[I+1]
end.
 
% All elements must be different
alldiff(List) =>
Len = List.length,
foreach(I in 1..Len, J in 1..I-1)
List[I] != List[J]
end.
 
% Print a solution
print_sol(Sets,X) =>
println("Solution:"),
println(x=X),
foreach(R in X)
println([Sets[R[I]] : I in 1..3])
end,
nl.
 
% Print the cards
print_cards(Cards) =>
println("Cards:"),
foreach({Card,I} in zip(Cards,1..Cards.len))
println([I,Card])
end,
nl.
 
%
% Generate a problem instance with NumSets sets (a unique solution).
%
% Note: not all random combinations of cards give a unique solution so
% it might generate a number of deals.
%
generate_instance(NumCards,NumSets,SetLen, Cards) =>
println([numCards=NumCards,numWantedSets=NumSets,setLen=SetLen]),
Found = false,
% Check that this instance has a unique solution.
while(Found = false)
if Cards = random_deal(NumCards),
count_all(set_puzzle(Cards,SetLen,NumSets,_X)) = 1
then
Found := true
end
end.
 
%
% Generate a random problem instance of N cards.
%
random_deal(N) = Deal.sort() =>
all_combinations(Combinations),
Deal = [],
foreach(_I in 1..N)
Len = Combinations.len,
Rand = random(1,Len),
Comb = Combinations[Rand],
Deal := Deal ++ [Comb],
Combinations := delete_all(Combinations, Comb)
end.
 
%
% Generate a random instance and solve it.
%
generate_and_solve(NumCards,NumSets,SetLen) =>
generate_instance(NumCards,NumSets,SetLen, Cards),
print_cards(Cards),
set_puzzle(Cards,SetLen,NumSets,X), % solve it
print_sol(Cards,X),
nl.
 
 
%
% All the 81 possible combinations (cards)
%
table
all_combinations(All) =>
Colors = [red, green, purple],
Symbols = [oval, squiggle, diamond],
Numbers = [one, two, three],
Shadings = [solid, open, striped],
All = findall([Color,Symbol,Number,Shading],
(member(Color,Colors),
member(Symbol,Symbols),
member(Number,Numbers),
member(Shading,Shadings))).
 
%
% From the task description.
%
% Solution: [[1,6,9],[2,3,4],[2,6,8],[5,6,7]]
%
sets(1,Sets,SetLen,Wanted) =>
Sets =
[
[green, one, oval, striped], % 1
[green, one, diamond, open], % 2
[green, one, diamond, striped], % 3
[green, one, diamond, solid], % 4
[purple, one, diamond, open], % 5
[purple, two, squiggle, open], % 6
[purple, three, oval, open], % 7
[red, three, oval, open], % 8
[red, three, diamond, solid] % 9
],
SetLen = 3,
Wanted = 4.</syntaxhighlight>
 
 
Solving the instance in the task description (<code>go/0</code>):
{{out}}
<pre>[1,[green,one,oval,striped]]
[2,[green,one,diamond,open]]
[3,[green,one,diamond,striped]]
[4,[green,one,diamond,solid]]
[5,[purple,one,diamond,open]]
[6,[purple,two,squiggle,open]]
[7,[purple,three,oval,open]]
[8,[red,three,oval,open]]
[9,[red,three,diamond,solid]]
 
Solution:
x = [{1,6,9},{2,3,4},{2,6,8},{5,6,7}]
[[green,one,oval,striped],[purple,two,squiggle,open],[red,three,diamond,solid]]
[[green,one,diamond,open],[green,one,diamond,striped],[green,one,diamond,solid]]
[[green,one,diamond,open],[purple,two,squiggle,open],[red,three,oval,open]]
[[purple,one,diamond,open],[purple,two,squiggle,open],[purple,three,oval,open]]</pre>
 
Solving the two random tasks (<code>go2/0</code>) and <code>go3/0</code>):
{{out}::
<pre>[numCards = 9,numWantedSets = 4,setLen = 3]
Cards:
[1,[green,squiggle,one,solid]]
[2,[green,squiggle,two,solid]]
[3,[purple,diamond,three,striped]]
[4,[purple,oval,two,striped]]
[5,[purple,squiggle,one,striped]]
[6,[purple,squiggle,three,solid]]
[7,[purple,squiggle,three,striped]]
[8,[red,squiggle,one,open]]
[9,[red,squiggle,three,open]]
 
Solution:
x = [{1,5,8},{2,5,9},{2,7,8},{3,4,5}]
[[green,squiggle,one,solid],[purple,squiggle,one,striped],[red,squiggle,one,open]]
[[green,squiggle,two,solid],[purple,squiggle,one,striped],[red,squiggle,three,open]]
[[green,squiggle,two,solid],[purple,squiggle,three,striped],[red,squiggle,one,open]]
[[purple,diamond,three,striped],[purple,oval,two,striped],[purple,squiggle,one,striped]]
 
[numCards = 12,numWantedSets = 6,setLen = 3]
Cards:
[1,[green,diamond,one,solid]]
[2,[green,diamond,two,solid]]
[3,[green,oval,one,open]]
[4,[purple,oval,one,solid]]
[5,[purple,squiggle,one,open]]
[6,[purple,squiggle,one,solid]]
[7,[purple,squiggle,one,striped]]
[8,[red,diamond,one,solid]]
[9,[red,diamond,two,striped]]
[10,[red,oval,one,striped]]
[11,[red,squiggle,three,solid]]
[12,[red,squiggle,three,striped]]
 
Solution:
x = [{1,5,10},{2,4,11},{3,4,10},{3,7,8},{5,6,7},{9,10,12}]
[[green,diamond,one,solid],[purple,squiggle,one,open],[red,oval,one,striped]]
[[green,diamond,two,solid],[purple,oval,one,solid],[red,squiggle,three,solid]]
[[green,oval,one,open],[purple,oval,one,solid],[red,oval,one,striped]]
[[green,oval,one,open],[purple,squiggle,one,striped],[red,diamond,one,solid]]
[[purple,squiggle,one,open],[purple,squiggle,one,solid],[purple,squiggle,one,striped]]
[[red,diamond,two,striped],[red,oval,one,striped],[red,squiggle,three,striped]]</pre>
 
===Constraint model===
Here is the additional code for a '''constraint model'''. Note that the constraint solver only handles integers so the features must be converted to integers. To simplify, the random instance generator does not check for unicity of the problem instance, so it can have (and often have) a lot of solutions.
<syntaxhighlight lang="picat">go4 =>
NumCards = 18,
NumWanted = 9,
SetLen = 3,
time(generate_instance2(NumCards,NumWanted, SetLen,Sets)),
 
print_cards(Sets),
println(setLen=SetLen),
println(numWanted=NumWanted),
SetsConv = convert_sets_to_num(Sets),
 
set_puzzle_cp(SetsConv,SetLen,NumWanted, X),
 
println(x=X),
foreach(Row in X)
println([Sets[I] : I in Row])
end,
nl,
fail, % more solutions?
nl.
 
set_puzzle_cp(Cards,SetLen,NumWanted, X) =>
NumFeatures = Cards[1].len,
NumSets = Cards.len,
X = new_array(NumWanted,SetLen),
X :: 1..NumSets,
 
foreach(I in 1..NumWanted)
% ensure unicity of the selected sets
all_different(X[I]),
increasing_strict(X[I]), % unicity and symmetry breaking of Y
 
foreach(F in 1..NumFeatures)
Z = $[ S : J in 1..SetLen, matrix_element(Cards, X[I,J],F, S) ],
% all features are different or all equal
(
(sum([ Z[J] #!= Z[K] : J in 1..SetLen, K in 1..SetLen, J != K ])
#= SetLen*SetLen - SetLen)
#\/
(sum([ Z[J-1] #= Z[J] : J in 2..SetLen]) #= SetLen-1)
)
end
end,
 
% Symmetry breaking (lexicographic ordered rows)
lex2(X),
 
solve($[ff,split],X).
 
%
% Symmetry breaking
% Ensure that the rows in X are lexicographic ordered
%
lex2(X) =>
Len = X[1].length,
foreach(I in 2..X.length)
lex_lt([X[I-1,J] : J in 1..Len], [X[I,J] : J in 1..Len])
end.
 
%
% Convert sets of "verbose" instances to integer
% representations.
%
convert_sets_to_num(Sets) = NewSets =>
Maps = new_map([
red=1,green=2,purple=3,
1=1,2=2,3=3,
one=1,two=2,three=3,
oval=1,squiggle=2,squiggles=2,diamond=3,
solid=1,open=2,striped=3
]),
NewSets1 = [],
foreach(S in Sets)
NewSets1 := NewSets1 ++ [[Maps.get(T) : T in S]]
end,
NewSets = NewSets1.
 
 
%
% Plain random problem instance, no check of solvability.
%
generate_instance2(NumCards,_NumSets,_SetLen, Cards) =>
Cards = random_deal(NumCards).</syntaxhighlight>
 
{{out}}
This problem instance happens to have 10 solutions.
<pre>Cards:
[1,[green,diamond,one,open]]
[2,[green,diamond,one,solid]]
[3,[green,oval,one,open]]
[4,[green,oval,three,solid]]
[5,[green,oval,two,solid]]
[6,[green,squiggle,three,striped]]
[7,[green,squiggle,two,striped]]
[8,[purple,diamond,one,solid]]
[9,[purple,diamond,two,striped]]
[10,[purple,oval,one,solid]]
[11,[purple,oval,two,open]]
[12,[purple,squiggle,two,open]]
[13,[red,diamond,two,solid]]
[14,[red,oval,one,open]]
[15,[red,oval,three,solid]]
[16,[red,oval,two,solid]]
[17,[red,oval,two,striped]]
[18,[red,squiggle,one,striped]]
 
setLen = 3
numWanted = 9
x = {{1,4,7},{1,5,6},{1,10,18},{3,8,18},{4,10,16},{5,10,15},{5,11,17},{7,9,17},{7,11,13}}
[[green,diamond,one,open],[green,oval,three,solid],[green,squiggle,two,striped]]
[[green,diamond,one,open],[green,oval,two,solid],[green,squiggle,three,striped]]
[[green,diamond,one,open],[purple,oval,one,solid],[red,squiggle,one,striped]]
[[green,oval,one,open],[purple,diamond,one,solid],[red,squiggle,one,striped]]
[[green,oval,three,solid],[purple,oval,one,solid],[red,oval,two,solid]]
[[green,oval,two,solid],[purple,oval,one,solid],[red,oval,three,solid]]
[[green,oval,two,solid],[purple,oval,two,open],[red,oval,two,striped]]
[[green,squiggle,two,striped],[purple,diamond,two,striped],[red,oval,two,striped]]
[[green,squiggle,two,striped],[purple,oval,two,open],[red,diamond,two,solid]]
 
x = {{1,4,7},{1,5,6},{1,10,18},{3,8,18},{4,10,16},{5,10,15},{5,11,17},{7,9,17},{14,15,17}}
[[green,diamond,one,open],[green,oval,three,solid],[green,squiggle,two,striped]]
[[green,diamond,one,open],[green,oval,two,solid],[green,squiggle,three,striped]]
[[green,diamond,one,open],[purple,oval,one,solid],[red,squiggle,one,striped]]
[[green,oval,one,open],[purple,diamond,one,solid],[red,squiggle,one,striped]]
[[green,oval,three,solid],[purple,oval,one,solid],[red,oval,two,solid]]
[[green,oval,two,solid],[purple,oval,one,solid],[red,oval,three,solid]]
[[green,oval,two,solid],[purple,oval,two,open],[red,oval,two,striped]]
[[green,squiggle,two,striped],[purple,diamond,two,striped],[red,oval,two,striped]]
[[red,oval,one,open],[red,oval,three,solid],[red,oval,two,striped]]
 
...</pre>
 
=={{header|Prolog}}==
 
<langsyntaxhighlight Prologlang="prolog">do_it(N) :-
card_sets(N, Cards, Sets),
!,
Line 3,047 ⟶ 3,947:
match([A|T1],[B|T2],[C|T3]) :-
dif(A,B), dif(B,C), dif(A,C),
match(T1,T2,T3).</langsyntaxhighlight>
{{out}}
<pre>
Line 3,125 ⟶ 4,025:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">#!/usr/bin/python
from itertools import product, combinations
Line 3,171 ⟶ 4,071:
break
printit(deal, sets)
</syntaxhighlight>
</lang>
<small>Note: You could remove the inner square brackets of the <code>'if all( [...] )'</code> part of the sets computation in the getsets function. It is a remnant of Python 2.7 debugging which gives access to the name <code>feature</code>. The code works on Python 3.X too, but not that access.</small>
 
Line 3,205 ⟶ 4,105:
===Short Version===
{{trans|D}}
<langsyntaxhighlight lang="python">import random, pprint
from itertools import product, combinations
 
Line 3,225 ⟶ 4,125:
pprint.pprint(draw)
print "\nContaining %d sets:" % len(sets)
pprint.pprint(sets)</langsyntaxhighlight>
{{out}}
<pre>Dealt 9 cards:
Line 3,251 ⟶ 4,151:
('green', 'three', 'oval', 'open'),
('purple', 'three', 'squiggle', 'solid'))]</pre>
 
=={{header|Quackery}}==
 
<code>cards</code>, <code>sets</code>, and <code>echocard</code> are defined at [[Set, the card game#Quackery]].
 
<syntaxhighlight lang="Quackery"> [ temp put
[ dup cards dup
sets dup size
temp share != while
2drop again ]
swap
say "Cards:" cr
witheach echocard
cr
say "Sets:" cr
witheach
[ witheach echocard cr ]
drop
temp release ] is task ( n n --> )
 
basic task
cr
advanced task</syntaxhighlight>
 
{{out}}
 
<pre>BASIC
 
Cards:
three striped purple ovals
two solid green squiggles
two open green squiggles
one open purple squiggle
three striped red squiggles
two striped red ovals
one solid purple squiggle
two solid red diamonds
two open purple diamonds
 
Sets:
two open green squiggles
three striped red squiggles
one solid purple squiggle
 
two solid green squiggles
two striped red ovals
two open purple diamonds
 
two solid green squiggles
one open purple squiggle
three striped red squiggles
 
three striped purple ovals
one solid purple squiggle
two open purple diamonds
 
 
ADVANCED
 
Cards:
one open green oval
two solid purple squiggles
one striped red diamond
three solid purple diamonds
two solid green squiggles
two open purple squiggles
two open green ovals
two striped red squiggles
two open green diamonds
two striped red ovals
three open purple ovals
one open red oval
 
Sets:
two open green ovals
three open purple ovals
one open red oval
 
two solid green squiggles
two open purple squiggles
two striped red squiggles
 
one striped red diamond
two solid green squiggles
three open purple ovals
 
one striped red diamond
three solid purple diamonds
two open green diamonds
 
two solid purple squiggles
two open green diamonds
two striped red ovals
 
one open green oval
three solid purple diamonds
two striped red squiggles
</pre>
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 3,290 ⟶ 4,288:
(deal 9 4)
(deal 12 6)
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 3,296 ⟶ 4,294:
 
The trick here is to allocate three different bits for each enum, with the result that the cards of a matching set OR together to produce a 4-digit octal number that contains only the digits 1, 2, 4, or 7. This OR is done by funny looking <tt>[+|]</tt>, which is the reduction form of <tt>+|</tt>, which is the numeric bitwise OR. (Because Raku stole the bare <tt>|</tt> operator for composing junctions instead.)
<syntaxhighlight lang="raku" perl6line>enum Color (red => 0o1000, green => 0o2000, purple => 0o4000);
enum Count (one => 0o100, two => 0o200, three => 0o400);
enum Shape (oval => 0o10, squiggle => 0o20, diamond => 0o40);
Line 3,323 ⟶ 4,321:
show-cards @cards;
}
}</langsyntaxhighlight>
{{out}}
<pre>Drew 9 cards:
Line 3,363 ⟶ 4,361:
 
The particular set of cards dealt (show below) used Regina 3.9.3 under a Windows/XP environment.
<langsyntaxhighlight lang="rexx">/*REXX program finds and displays "sets" (solutions) for the SET puzzle (game). */
parse arg game seed . /*get optional # cards to deal and seed*/
if game ==',' | game==''"," then game= 9 /*Not specified? Then use the default.*/
if seed==',' | seed==''"," then seed= 77 /* " " " " " " */
call aGame 0 /*with tell=0: suppress the output. */
call aGame 1 /*with tell=1: display " " */
exit sets /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────AGAME subroutine──────────────────────────*/
aGame: tell=parse arg(1) tell; good= game % 2 /*enable/disable the showing of output.*/
/* [↑] the GOOD var is the right #sets*/
do seed=seed until good==sets /*generate deals until good # of sets.*/
call random ,,seed /*repeatability for the RANDOM invokes.*/
call genFeatures /*generate various card game features. */
call genDeck /*generate " a deck (with 81 "cards").*/
call dealer game /*deal a number of cards for the game. */
call findSets game%2 /*find # of sets from the dealt cards. */
end /*until*/ /* [↓] when leaving, SETS is right #.*/
return /*return to invoker of this subroutine.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────DEALER subroutine─────────────────────────*/
dealer: call sey 'dealing' game "cards:", , . /*shuffle and deal the cards. */
do cards=1 until cards==game /*keep dealing until finished.*/
_=random(1,words(##)); ##=delword(##,_,1) /*pick card; delete a card. */
@.cards=deck._ /*add the card to the tableau.*/
call sey right('card' cards,30) " " @.cards /*display the card to screen. */
do j=1 for words(@.cards) /* [↓] define cells for cards*/
@.cards.j=word(@.cards,j) /*define a cell for a card.*/
end /*j*/
end /*cards*/
return
/*──────────────────────────────────DEFFEATURES subroutine────────────────────*/
defFeatures: parse arg what,v; _=words(v) /*obtain what is to be defined*/
if _\==values then do; call sey 'error,' what "features ¬=" values,.,.
exit -1
end /* [↑] check for typos/errors*/
do k=1 for words(values) /*define all the possible vals*/
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 the deck. */
/*──────────────────────────────────GENFEATURES subroutine────────────────────*/
genFeatures: features=3; groups=4; values=3 /*define # features, groups, 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 duplicates.*/
do j=i+1 to game
do k=j+1 to game
p=p+1; !.p.1=@.i; !.p.2=@.j; !.p.3=@.k
end /*k*/
end /*j*/
end /*i*/ /* [↑] generate the permutation list. */
return
/*──────────────────────────────────FINDSETS subroutine───────────────────────*/
findSets: parse arg n; call genPoss /*N: the number of sets to be found. */
call sey /*find any sets that were generated [↑]*/
do j=1 for p /*P: is the number 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 peachy─kean (OK) so far*/
do g=1 for groups; _=!!.j.1.g /*build strings to hold possibilities. */
equ=1 /* [↓] handles all the equal features.*/
do f=2 to features while equ; equ=equ & _==!!.j.f.g
end /*f*/
dif=1
__=!!.j.1.g /* [↓] handles all unequal features.*/
do f=2 to features while \equ
dif=dif & (wordpos(!!.j.f.g,__)==0)
__=__ !!.j.f.g /*append to the string for next test. */
end /*f*/
ok=ok & (equ | dif) /*now, see if all are equal or unequal.*/
end /*g*/
 
if \ok then iterate do cards=1 until cards==game /*Iskeep dealing until finished. this set OK? Nope, then skip it.*/
sets=sets+1 _= random(1, words(##) ) /*bumppick a card. the number of the sets found. */
call sey right ##= delword('set'##, _, 1) /*delete sets": ",15) !.j.1 sep !.j.2 sep !.j.3 */
@.cards= deck._ /*add the card to the tableau. */
end /*j*/
call sey right('card' cards, 30) " " @.cards /*display a card to terminal.*/
 
do j=1 for words(@.cards) /* [↓] define cells for cards. */
call sey sets 'sets found.',.
@.cards.j= word(@.cards, j) /*define a cell for a card. */
return
end /*j*/
/*──────────────────────────────────SEY subroutine────────────────────────────*/
sey: if \tell then return end /*¬ tell? Then suppress the output. cards*/
 
if arg(2)==. then say; say arg(1); if arg(3)==. then say; return</lang>
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
defFeatures: parse arg what,v; _= words(v) /*obtain what is to be defined. */
 
if _\==values then do; call sey 'error,' what "features ¬=" values, ., .
exit -1
end /* [↑] check for typos and/or errors. */
 
do k=1 for words(values) /*define all the possible values. */
call value what'.'k, word(values, k) /*define a card feature. */
end /*k*/
 
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
findSets: parse arg n; call genPoss /*N: the number of sets to be found. */
call sey /*find any sets that were generated [↑]*/
 
do j=1 for p /*P: is the number 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 peachy─kean (OK) so far*/
 
do g=1 for groups
_= !!.j.1.g /*build strings to hold possibilities. */
equ= 1 /* [↓] handles all the equal features.*/
 
do f=2 to features while equ; equ= equ & _==!!.j.f.g
end /*f*/
 
dif= 1
__= !!.j.1.g /* [↓] handles all unequal features.*/
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 are equal or unequal.*/
end /*g*/
 
if \ok then iterate /*Is this set OK? Nope, then skip it.*/
sets= sets + 1 /*bump the number of the sets found. */
call sey right('set' sets": ", 15) !.j.1 sep !.j.2 sep !.j.3
end /*j*/
 
call sey sets 'sets found.', .
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
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 the deck. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
genFeatures: features= 3; groups= 4; values= 3 /*define # features, groups, values. */
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: p= 0; sets= 0; sep=' ───── ' /*define some REXX variables. */
!.=
do i=1 for game /* [↓] the IFs eliminate duplicates.*/
do j=i+1 to game
do k=j+1 to game
p= p + 1; !.p.1= @.i; !.p.2= @.j; !.p.3= @.k
end /*k*/
end /*j*/
end /*i*/ /* [↑] generate the permutation list. */
 
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
sey: if \tell then return /*¬ tell? Then suppress the output. */
if arg(2)==. then say; say arg(1); if arg(3)==. then say; return</syntaxhighlight>
'''output''' when using the default input:
<pre>
Line 3,483 ⟶ 4,500:
4 sets found.
</pre>
'''{{out|output'''|text=&nbsp; when using the input of: &nbsp; &nbsp; <tt> 12 </tt>}}
<pre>
dealing 12 cards:
Line 3,512 ⟶ 4,529:
=={{header|Ruby}}==
Brute force.
<langsyntaxhighlight lang="ruby">COLORS = %i(red green purple) #use [:red, :green, :purple] in Ruby < 2.0
SYMBOLS = %i(oval squiggle diamond)
NUMBERS = %i(one two three)
Line 3,547 ⟶ 4,564:
 
set_puzzle(9)
set_puzzle(12)</langsyntaxhighlight>
{{out}}
<pre>
Line 3,616 ⟶ 4,633:
green oval two open
red diamond two striped
</pre>
=={{header|Rust}}==
<syntaxhighlight lang="rust">
use itertools::Itertools;
use rand::Rng;
 
const DECK_SIZE: usize = 81;
const NUM_ATTRIBUTES: usize = 4;
const ATTRIBUTES: [&[&str]; NUM_ATTRIBUTES] = [
&["red", "green", "purple"],
&["one", "two", "three"],
&["oval", "squiggle", "diamond"],
&["solid", "open", "striped"],
];
 
fn get_random_card_indexes(num_of_cards: usize) -> Vec<usize> {
let mut selected_cards: Vec<usize> = Vec::with_capacity(num_of_cards);
let mut rng = rand::thread_rng();
loop {
let idx = rng.gen_range(0..DECK_SIZE);
if !selected_cards.contains(&idx) {
selected_cards.push(idx);
}
if selected_cards.len() == num_of_cards {
break;
}
}
 
selected_cards
}
 
fn run_game(num_of_cards: usize, minimum_number_of_sets: usize) {
println!(
"\nGAME: # of cards: {} # of sets: {}",
num_of_cards, minimum_number_of_sets
);
 
// generate the deck with 81 unique cards
let deck = (0..NUM_ATTRIBUTES)
.map(|_| (0..=2_usize))
.multi_cartesian_product()
.collect::<Vec<_>>();
 
// closure to return true if the three attributes are the same, or each of them is different
let valid_attribute =
|a: usize, b: usize, c: usize| -> bool { a == b && b == c || (a != b && b != c && a != c) };
 
// closure to test all attributes, each of them should be true to have a valid set
let valid_set = |t: &Vec<&Vec<usize>>| -> bool {
for attr in 0..NUM_ATTRIBUTES {
if !valid_attribute(t[0][attr], t[1][attr], t[2][attr]) {
return false;
}
}
true
};
 
loop {
// select the required # of cards from the deck randomly
let selected_cards = get_random_card_indexes(num_of_cards)
.iter()
.map(|idx| deck[*idx].clone())
.collect::<Vec<_>>();
 
// generate all combinations, and filter/keep only which are valid sets
let valid_sets = selected_cards
.iter()
.combinations(3)
.filter(|triplet| valid_set(triplet))
.collect::<Vec<_>>();
 
// if the # of the sets is matching the requirement, print it and finish
if valid_sets.len() == minimum_number_of_sets {
print!("SELECTED CARDS:");
for card in &selected_cards {
print!("\ncard: ");
for attr in 0..NUM_ATTRIBUTES {
print!("{}, ", ATTRIBUTES[attr][card[attr]]);
}
}
 
print!("\nSets:");
for triplet in &valid_sets {
print!("\nSet: ");
for card in triplet {
for attr in 0..NUM_ATTRIBUTES {
print!("{}, ", ATTRIBUTES[attr][card[attr]]);
}
print!(" | ");
}
}
 
break;
}
 
//otherwise generate again
}
}
fn main() {
run_game(9, 4);
run_game(12, 6);
}
 
</syntaxhighlight>
{{out}}
<pre>
GAME: # of cards: 9 # of sets: 4
SELECTED CARDS:
card: green, two, diamond, striped,
card: green, two, oval, solid,
card: red, one, oval, striped,
card: red, three, oval, striped,
card: purple, three, squiggle, striped,
card: green, three, diamond, solid,
card: red, three, oval, open,
card: purple, two, squiggle, open,
card: red, two, oval, striped,
Sets:
Set: green, two, diamond, striped, | red, one, oval, striped, | purple, three, squiggle, striped, |
Set: red, one, oval, striped, | red, three, oval, striped, | red, two, oval, striped, |
Set: red, one, oval, striped, | green, three, diamond, solid, | purple, two, squiggle, open, |
Set: purple, three, squiggle, striped, | green, three, diamond, solid, | red, three, oval, open, |
GAME: # of cards: 12 # of sets: 6
SELECTED CARDS:
card: purple, three, squiggle, solid,
card: purple, three, squiggle, striped,
card: green, three, diamond, striped,
card: purple, three, oval, solid,
card: green, two, oval, open,
card: green, one, diamond, solid,
card: red, three, oval, open,
card: green, one, squiggle, solid,
card: red, three, oval, solid,
card: purple, three, diamond, open,
card: red, two, oval, open,
card: red, three, oval, striped,
Sets:
Set: purple, three, squiggle, solid, | green, three, diamond, striped, | red, three, oval, open, |
Set: purple, three, squiggle, striped, | green, three, diamond, striped, | red, three, oval, striped, |
Set: purple, three, squiggle, striped, | purple, three, oval, solid, | purple, three, diamond, open, |
Set: purple, three, squiggle, striped, | green, one, diamond, solid, | red, two, oval, open, |
Set: green, three, diamond, striped, | green, two, oval, open, | green, one, squiggle, solid, |
Set: red, three, oval, open, | red, three, oval, solid, | red, three, oval, striped, |
</pre>
 
=={{header|Tailspin}}==
Dealing cards at random to the size of the desired hand, then trying again if the desired set count is not achieved.
<langsyntaxhighlight lang="tailspin">
def deck: [ { by 1..3 -> \(def colour: $;),
by 1..3 -> \(def symbol: $;),
by 1..3 -> \(def number: $;),
by 1..3 -> {colour: $colour, symbol: $symbol, number: $number, (shading: $)} !
\) !
\) !
\)
];
 
Line 3,637 ⟶ 4,794:
templates isSet
def set : $;
[ $(1).colour::raw + $(2).colour::raw + $(3).colour::raw, $(1).symbol::raw + $(2).symbol::raw + $(3).symbol::raw,
$(1).number::raw + $(2).number::raw + $(3).number::raw, $(1).shading::raw + $(2).shading::raw + $(3).shading::raw ] -> #
// if it is an array where all elements of 3, 6 or 9, it is a set
when <[<=3|=6|=9>+ VOID]> do $set !
Line 3,655 ⟶ 4,812:
def nCards: $(1);
def nSets: $(2);
{sets: []} -> #
when <{sets: <[]($nSets..)>}> do $ !
otherwise
Line 3,663 ⟶ 4,820:
 
templates formatCard
def colours: colour´1:['red', 'green', 'purple'];
def symbols: symbol´1:['oval', 'squiggle', 'diamond'];
def numbers: number´1:['one', 'two', 'three'];
def shadings: shading´1:['solid', 'open', 'striped'];
$ -> '$colours($.colour);-$symbols($.symbol);-$numbers($.number);-$shadings($.shading);' !
end formatCard
Line 3,679 ⟶ 4,836:
end formatSets
 
[9,4] -> setPuzzle -> formatSets -> !OUT::write</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,702 ⟶ 4,858:
 
Twelve cards with six sets
<langsyntaxhighlight lang="tailspin">
[12,6] -> setPuzzle -> formatSets -> !OUT::write
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,733 ⟶ 4,889:
The principle behind this code is that the space of possible solutions is a substantial proportion of the space of possible hands, so picking a random hand and verifying that it is a solution, repeating until that verification succeeds, is a much quicker way to find a solution than a systematic search.
It also makes the code substantially simpler.
<langsyntaxhighlight lang="tcl"># Generate random integer uniformly on range [0..$n-1]
proc random n {expr {int(rand() * $n)}}
 
Line 3,814 ⟶ 4,970:
}
return [list $hand $sets]
}</langsyntaxhighlight>
Demonstrating:
<langsyntaxhighlight lang="tcl"># Render a hand (or any list) of cards (the "."s are just placeholders).
proc PrettyHand {hand {separator \n}} {
set Co {. red green . purple}
Line 3,844 ⟶ 5,000:
PrettyOutput [SetPuzzle 9 4]
puts "=== ADVANCED PUZZLE ======"
PrettyOutput [SetPuzzle 12 6]</langsyntaxhighlight>
{{out|Sample output}}
<pre>
Line 3,922 ⟶ 5,078:
{{libheader|Wren-math}}
{{libheader|Wren-sort}}
<langsyntaxhighlight ecmascriptlang="wren">import "./dynamic" for Enum
import "./trait" for Comparable
import "./fmt" for Fmt
import "./str" for Str
import "./math" for Nums
import "./sort" for Sort
import "random" for Random
 
Line 4,032 ⟶ 5,188:
playGame.call(Degree.BASIC)
System.print()
playGame.call(Degree.ADVANCED)</langsyntaxhighlight>
 
{{out}}
Line 4,112 ⟶ 5,268:
=={{header|zkl}}==
{{trans|D}}
<langsyntaxhighlight lang="zkl">const nDraw=9, nGoal=(nDraw/2); // Basic
var [const] UH=Utils.Helpers; // baked in stash of goodies
deck:=Walker.cproduct("red green purple".split(), // Cartesian product of 4 lists of lists
Line 4,133 ⟶ 5,289:
draw.pump(Void,fcn(card){ println(("%8s "*4).fmt(card.xplode())) });
println("\nContaining:");
sets.pump(Void,fcn(card){ println((("%8s "*4 + "\n")*3).fmt(card.xplode())) });</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits