all tasks

This commit is contained in:
Ingy döt Net 2013-04-11 01:07:29 -07:00
parent b83f433714
commit 68f8f3e56b
14735 changed files with 178959 additions and 0 deletions

View file

@ -0,0 +1,62 @@
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''.
; there are three colors: '''red''', '''green''', or '''purple'''
; there are three symbols: '''oval''', '''squiggle''', or '''diamond'''
; there is a number of symbols on the card: '''one''', '''two''', or '''three'''
; 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.
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:
'''DEALT 9 CARDS:'''
:green, one, oval, striped
:green, one, diamond, open
:green, one, diamond, striped
:green, one, diamond, solid
:purple, one, diamond, open
:purple, two, squiggle, open
:purple, three, oval, open
:red, three, oval, open
:red, three, diamond, solid
'''CONTAINING 4 SETS:'''
: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

View file

@ -0,0 +1,95 @@
#include <stdio.h>
#include <stdlib.h>
char *names[4][3] = {
{ "red", "green", "purple" },
{ "oval", "squiggle", "diamond" },
{ "one", "two", "three" },
{ "solid", "open", "striped" }
};
int set[81][81];
void init_sets(void)
{
int i, j, t, a, b;
for (i = 0; i < 81; i++) {
for (j = 0; j < 81; j++) {
for (t = 27; t; t /= 3) {
a = (i / t) % 3;
b = (j / t) % 3;
set[i][j] += t * (a == b ? a : 3 - a - b);
}
}
}
}
void deal(int *out, int n)
{
int i, j, t, c[81];
for (i = 0; i < 81; i++) c[i] = i;
for (i = 0; i < n; i++) {
j = i + (rand() % (81 - i));
t = c[i], c[i] = out[i] = c[j], c[j] = t;
}
}
int get_sets(int *cards, int n, int sets[][3])
{
int i, j, k, s = 0;
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
for (k = j + 1; k < n; k++) {
if (set[cards[i]][cards[j]] == cards[k])
sets[s][0] = i,
sets[s][1] = j,
sets[s][2] = k,
s++;
}
}
}
return s;
}
void show_card(int c)
{
int i, t;
for (i = 0, t = 27; t; i++, t /= 3)
printf("%9s", names[i][(c/t)%3]);
putchar('\n');
}
void deal_sets(int ncard, int nset)
{
int c[81];
int csets[81][3]; // might not be enough for large ncard
int i, j, s;
do deal(c, ncard); while ((s = get_sets(c, ncard, csets)) != nset);
printf("dealt %d cards\n", ncard);
for (i = 0; i < ncard; i++) {
printf("%2d:", i);
show_card(c[i]);
}
printf("\nsets:\n");
for (i = 0; i < s; i++) {
for (j = 0; j < 3; j++) {
printf("%2d:", csets[i][j]);
show_card(c[csets[i][j]]);
}
putchar('\n');
}
}
int main(void)
{
init_sets();
deal_sets(9, 4);
while (1) deal_sets(12, 6);
return 0;
}

View file

@ -0,0 +1,108 @@
import std.stdio, std.random, std.array, std.conv, std.traits,
std.exception;
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}
static struct Card {
Color c;
Number n;
Symbol s;
Fill f;
}
immutable Card[81] deck;
}
this() pure nothrow {
Card[] tmpdeck;
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);
}
// 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();
}
// 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 {
return !((c1.c + c2.c + c3.c) % 3 ||
(c1.n + c2.n + c3.n) % 3 ||
(c1.s + c2.s + c3.s) % 3 ||
(c1.f + c2.f + c3.f) % 3);
}
immutable(Card)[3][] findSets(in Card[] cards, in uint target = 0)
const pure nothrow {
immutable len = cards.length;
if (len < 3)
return null;
typeof(return) sets;
foreach (immutable i; 0 .. len - 2)
foreach (immutable j; i + 1 .. len - 1)
foreach (immutable k; j + 1 .. len)
if (validSet(cards[i], cards[j], cards[k])) {
sets ~= [cards[i], cards[j], cards[k]];
if (target != 0 && sets.length > target)
return null;
}
return sets;
}
}
const final class SetPuzzleDealer : SetDealer {
enum {basic = 9, advanced = 12}
override immutable(Card)[] deal(in uint numCards = basic) const {
immutable numSets = numCards / 2;
typeof(return) cards;
do {
cards = super.deal(numCards);
} while (findSets(cards, numSets).length != numSets);
return cards;
}
}
void main() {
const dealer = new SetPuzzleDealer();
const cards = dealer.deal();
writefln("\nDEALT %d CARDS:\n", cards.length);
foreach (c; cards)
writeln(cast()c);
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();
}
}

View file

@ -0,0 +1,24 @@
require 'stats/base'
Number=: ;:'one two three'
Colour=: ;:'red green purple'
Fill=: ;:'solid open striped'
Symbol=: ;:'oval squiggle diamond'
Features=: Number ; Colour ; Fill ;< Symbol
Deck=: > ; <"1 { i.@#&.> Features
sayCards=: (', ' joinstring Features {&>~ ])"1
drawRandom=: ] {~ (? #)
isSet=: *./@:(1 3 e.~ [: #@~."1 |:)"2
getSets=: ([: (] #~ isSet) ] {~ 3 comb #)
countSets=: #@:getSets
set_puzzle=: verb define
target=. <. -: y
whilst. target ~: countSets Hand do.
Hand=. y drawRandom Deck
end.
echo 'Dealt ',(": y),' Cards:'
echo sayCards Hand
echo 'Found ',(":target),' Sets:'
echo sayCards getSets Hand
)

View file

@ -0,0 +1,27 @@
set_puzzle 9
Dealt 9 Cards:
three, purple, open, oval
three, green, open, diamond
three, red, solid, squiggle
three, green, solid, oval
three, purple, striped, oval
three, red, open, oval
one, red, solid, oval
one, green, open, squiggle
two, purple, striped, squiggle
Found 4 Sets:
three, green, open, diamond
three, red, solid, squiggle
three, purple, striped, oval
three, green, open, diamond
one, red, solid, oval
two, purple, striped, squiggle
three, red, solid, squiggle
one, green, open, squiggle
two, purple, striped, squiggle
three, green, solid, oval
three, purple, striped, oval
three, red, open, oval

View file

@ -0,0 +1,126 @@
import java.util.*;
import org.apache.commons.lang3.ArrayUtils;
public class SetPuzzle {
enum Color {
GREEN(0), PURPLE(1), RED(2);
private Color(int v) {
val = v;
}
public final int val;
}
enum Number {
ONE(0), TWO(1), THREE(2);
private Number(int v) {
val = v;
}
public final int val;
}
enum Symbol {
OVAL(0), DIAMOND(1), SQUIGGLE(2);
private Symbol(int v) {
val = v;
}
public final int val;
}
enum Fill {
OPEN(0), STRIPED(1), SOLID(2);
private Fill(int v) {
val = v;
}
public final int val;
}
private static class Card implements Comparable<Card> {
Color c;
Number n;
Symbol s;
Fill f;
public String toString() {
return String.format("[Card: %s, %s, %s, %s]", c, n, s, f);
}
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) {
deck = new Card[81];
Color[] colors = Color.values();
Number[] numbers = Number.values();
Symbol[] symbols = Symbol.values();
Fill[] fillmodes = Fill.values();
for (int i = 0; i < deck.length; i++) {
deck[i] = new Card();
deck[i].c = colors[i / 27];
deck[i].n = numbers[(i / 9) % 3];
deck[i].s = symbols[(i / 3) % 3];
deck[i].f = fillmodes[i % 3];
}
findSets(12);
}
private static void findSets(int numCards) {
int target = numCards / 2;
Card[] cards;
Card[][] sets = new Card[target][3];
int cnt;
do {
Collections.shuffle(Arrays.asList(deck));
cards = ArrayUtils.subarray(deck, 0, numCards);
cnt = 0;
outer:
for (int i = 0; i < cards.length - 2; i++) {
for (int j = i + 1; j < cards.length - 1; j++) {
for (int k = j + 1; k < cards.length; k++) {
if (validSet(cards[i], cards[j], cards[k])) {
if (cnt < target)
sets[cnt] = new Card[]{cards[i], cards[j], cards[k]};
if (++cnt > target) {
break outer;
}
}
}
}
}
} while (cnt != target);
Arrays.sort(cards);
System.out.printf("GIVEN %d CARDS:\n\n", numCards);
for (Card c : cards) {
System.out.println(c);
}
System.out.println();
System.out.println("FOUND " + target + " SETS:\n");
for (Card[] set : sets) {
for (Card c : set) {
System.out.println(c);
}
System.out.println();
}
}
private static boolean validSet(Card c1, Card c2, Card c3) {
int tot = 0;
tot += (c1.c.val + c2.c.val + c3.c.val) % 3;
tot += (c1.n.val + c2.n.val + c3.n.val) % 3;
tot += (c1.s.val + c2.s.val + c3.s.val) % 3;
tot += (c1.f.val + c2.f.val + c3.f.val) % 3;
return tot == 0;
}
}

View file

@ -0,0 +1,26 @@
enum Color (red => 0o1000, green => 0o2000, purple => 0o4000);
enum Count (one => 0o100, two => 0o200, three => 0o400);
enum Shape (oval => 0o10, squiggle => 0o20, diamond => 0o40);
enum Style (solid => 0o1, open => 0o2, striped => 0o4);
my @deck := (Color.enums X Count.enums X Shape.enums X Style.enums).tree;
sub MAIN($DRAW = 9, $GOAL = $DRAW div 2) {
my @combinations = combine(3, [^$DRAW]);
my @draw;
repeat until (my @sets) == $GOAL {
@draw = @deck.pick($DRAW);
my @bits = @draw.map: { [+] @^enums».value }
@sets = gather for @combinations -> @c {
take @draw[@c].item when /^ <[1247]>+ $/ given ( [+|] @bits[@c] ).base(8);
}
}
say "Drew $DRAW cards:";
show-cards @draw;
for @sets.kv -> $i, @cards {
say "\nSet {$i+1}:";
show-cards @cards;
}
}
sub show-cards(@c) { for @c -> $c { printf " %-6s %-5s %-8s %s\n", $c».key } }

View file

@ -0,0 +1,46 @@
#!/usr/bin/python
from itertools import product, combinations
from random import sample
## Major constants
features = [ 'green purple red'.split(),
'one two three'.split(),
'oval diamond squiggle'.split(),
'open striped solid'.split() ]
deck = list(product(list(range(3)), repeat=4))
dealt = 9
## Functions
def printcard(card):
print(' '.join('%8s' % f[i] for f,i in zip(features, card)))
def getdeal(dealt=dealt):
deal = sample(deck, dealt)
return deal
def getsets(deal):
good_feature_count = set([1, 3])
sets = [ comb for comb in combinations(deal, 3)
if all( [(len(set(feature)) in good_feature_count)
for feature in zip(*comb)]
) ]
return sets
def printit(deal, sets):
print('Dealt %i cards:' % len(deal))
for card in deal: printcard(card)
print('\nFound %i sets:' % len(sets))
for s in sets:
for card in s: printcard(card)
print('')
if __name__ == '__main__':
while True:
deal = getdeal()
sets = getsets(deal)
if len(sets) == dealt / 2:
break
printit(deal, sets)

View file

@ -0,0 +1,82 @@
# Generate random integer uniformly on range [0..$n-1]
proc random n {expr {int(rand() * $n)}}
# Generate a shuffled deck of all cards; the card encoding was stolen from the
# Perl6 solution. This is done once and then used as a constant. Note that the
# rest of the code assumes that all cards in the deck are unique.
set ::AllCards [apply {{} {
set cards {}
foreach color {1 2 4} {
foreach symbol {1 2 4} {
foreach number {1 2 4} {
foreach shading {1 2 4} {
lappend cards [list $color $symbol $number $shading]
}
}
}
}
# Knuth-Morris-Pratt shuffle (not that it matters)
for {set i [llength $cards]} {$i > 0} {} {
set j [random $i]
set tmp [lindex $cards [incr i -1]]
lset cards $i [lindex $cards $j]
lset cards $j $tmp
}
return $cards
}}]
# Randomly pick a hand of cards from the deck (itself in a global for
# convenience).
proc drawCards n {
set cards $::AllCards; # Copies...
for {set i 0} {$i < $n} {incr i} {
set idx [random [llength $cards]]
lappend hand [lindex $cards $idx]
set cards [lreplace $cards $idx $idx]
}
return $hand
}
# Test if a particular group of three cards is a valid set
proc isValidSet {a b c} {
expr {
([lindex $a 0]|[lindex $b 0]|[lindex $c 0]) in {1 2 4 7} &&
([lindex $a 1]|[lindex $b 1]|[lindex $c 1]) in {1 2 4 7} &&
([lindex $a 2]|[lindex $b 2]|[lindex $c 2]) in {1 2 4 7} &&
([lindex $a 3]|[lindex $b 3]|[lindex $c 3]) in {1 2 4 7}
}
}
# Get all unique valid sets of three cards in a hand.
proc allValidSets {hand} {
set sets {}
for {set i 0} {$i < [llength $hand]} {incr i} {
set a [lindex $hand $i]
set hand [set cards2 [lreplace $hand $i $i]]
for {set j 0} {$j < [llength $cards2]} {incr j} {
set b [lindex $cards2 $j]
set cards2 [set cards3 [lreplace $cards2 $j $j]]
foreach c $cards3 {
if {[isValidSet $a $b $c]} {
lappend sets [list $a $b $c]
}
}
}
}
return $sets
}
# Solve a particular version of the set puzzle, by picking random hands until
# one is found that satisfies the constraints. This is usually much faster
# than a systematic search. On success, returns the hand found and the card
# sets within that hand.
proc SetPuzzle {numCards numSets} {
while 1 {
set hand [drawCards $numCards]
set sets [allValidSets $hand]
if {[llength $sets] == $numSets} {
break
}
}
return [list $hand $sets]
}

View file

@ -0,0 +1,29 @@
# Render a hand (or any list) of cards (the "."s are just placeholders).
proc PrettyHand {hand {separator \n}} {
set Co {. red green . purple}
set Sy {. oval squiggle . diamond}
set Nu {. one two . three}
set Sh {. solid open . striped}
foreach card $hand {
lassign $card co s n sh
lappend result [format "(%s,%s,%s,%s)" \
[lindex $Co $co] [lindex $Sy $s] [lindex $Nu $n] [lindex $Sh $sh]]
}
return $separator[join $result $separator]
}
# Render the output of the Set Puzzle solver.
proc PrettyOutput {setResult} {
lassign $setResult hand sets
set sep "\n "
puts "Hand (with [llength $hand] cards) was:[PrettyHand $hand $sep]"
foreach s $sets {
puts "Found set [incr n]:[PrettyHand $s $sep]"
}
}
# Demonstrate on the two cases
puts "=== BASIC PUZZLE ========="
PrettyOutput [SetPuzzle 9 4]
puts "=== ADVANCED PUZZLE ======"
PrettyOutput [SetPuzzle 12 6]