How to resolve the algorithm Set puzzle step by step in the Tcl programming language
How to resolve the algorithm Set puzzle step by step in the Tcl programming language
Table of Contents
Problem Statement
Set Puzzles are created with a deck of cards from the 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. 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: basic and 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.
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:
CONTAINING 4 SETS:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Set puzzle step by step in the Tcl programming language
Source code in the tcl programming language
# 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]
}
# 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]
You may also check:How to resolve the algorithm Loops/While step by step in the EchoLisp programming language
You may also check:How to resolve the algorithm Number reversal game step by step in the jq programming language
You may also check:How to resolve the algorithm Benford's law step by step in the Elixir programming language
You may also check:How to resolve the algorithm Polymorphic copy step by step in the Lua programming language
You may also check:How to resolve the algorithm Arbitrary-precision integers (included) step by step in the Dart programming language