<?php
/**
* SET card game solver
* @author Bryan Donovan
*/
$sets = array();

$attributes = array(
        
0=>array('1','2','3'),
        
1=>array('G','P','R'),
        
2=>array('E','F','L'),
        
3=>array('D','O','S')
        );
// Initialize hand
// Hand array format is:
// array('number','color','shading','shape')
// e.g. ('1,'P','L','O') is read as:
// "One purple lined oblong"

if (!empty($_POST)) {
        foreach (
$_POST as $card) {
                
$handKeys[] = $card;
                
$hand[] = getHandFromKey($card);
        }
} else {
        
$newHand = getRandomHand();
        
$hand = $newHand[0];
        
$handKeys = $newHand[1];
}

$handSize = count($handKeys);

//create array of possible two-card combinations
for ($x=0;$x<$handSize;$x++) {
    for (
$i=$x+1;$i<$handSize;$i++) {
        
$comb[] = array($x,$i);
    }
}
//compare the two cards within each pair
foreach ($comb as $pair) {
    
$card1 = $hand[$pair[0]];
    
$card2 = $hand[$pair[1]];
    for (
$k=0;$k<count($card1);$k++) {
        if(
$card1[$k]==$card2[$k]) {
            
$compare[$k]=1;
        } else {
            
$compare[$k]=0;
        }
    }

    
//determine what the 3rd card of the set is
    
for($i=0;$i<count($compare);$i++) {
        if (
$compare[$i]==1) {
            
$thirdCard[$i] = $card1[$i];
        } else {
            
$thirdCard[$i] = getOddAttribute($i,$card1[$i],$card2[$i]);
        }
    }

    
$thirdCardFromHand =getThirdCardFromHand($thirdCard);
    if(
$thirdCardFromHand) {
        global
$sets;
        
$setArray = array($pair[0],$pair[1],$thirdCardFromHand);
        
$sets[]=$setArray;
    }

}
//Sort each set so we can remove duplicates
if (isset($sets)) {
        foreach(
$sets as $set) {
                
sort($set);
                
$sortedSets[] = $set;
        }
        
$uniqueSets = arrayUnique($sortedSets);
}
/***********************************************
*          HTML OUTPUT
* *********************************************/
?>
<html>
<head>
<title>SET Solver</title>
<style>
body {font: 12px verdana,arial,sans-serif;
padding:20px;background:#fafafa;}
table {font-size:10px; border:1px; border-collapse:collapse}
th {background-color:#e5e5e5; border:1px solid silver;}
td {border:1px solid silver; text-align:center;}
a {color:slateblue;}
a:visited {color:slateblue;}
a:hover {color:chocolate;}
</style>
<script type="text/javascript">
function hide(what)
{
    hideWhat = document.getElementById(what);
    hideWhat.style.display = "none";
}

function show(what)
{
    showWhat = document.getElementById(what);
    showWhat.style.display = "block";
}
window.onload = function()
{
    hide('solution');
}
</script>
</head>
<body>
<h2>SET Solver</h2>
<p>Solves a random hand of <a href="http://www.setgame.com/set/">SET</a></p>
<p><a href="set.phps.html">View PHP Source</a></p>

<?php
echo "<h3>Hand: </h3>";
echo
"<div style=\"width:340px;\">";
foreach(
$hand as $key=>$card) {
    echo  
getImg($handKeys[$key]);
    if (
$key<10) {
        
$key .= "&nbsp;";
    }
    
$key .="&nbsp;";
    echo
"<span style=\"font-size:9px;font-family:courier\">$key</span>";
}
echo
"</div>";
echo
"<p><a href=\"../set/\">Deal new hand</a> | <a href=\"../set/custom_hand.php\">Create Your Own Hand</a></p>\n";

echo
"<p>Number of sets: ". count($uniqueSets) . "</p>\n";
?>
<p>
Solution: <a href="javascript:show('solution');">Show</a> | <a href="javascript:hide('solution');">Hide</a>
</p>
<div id="solution">
<?php
$i
=0;
echo
"<p>";
if(isset(
$uniqueSets)) {
    foreach (
$uniqueSets as $set) {
    
$i++;
        echo
"<br />Set $i: \n";
        foreach(
$set as $key=>$val) {
            echo
getImg($handKeys[$val]);
            if (
$val<10) {
                
$val .= "&nbsp;";
            }
            
$val .="&nbsp;";
            echo
"<span style=\"font-size:9px;font-family:courier\">$val</span>";
        }
    }
}
echo
"</p>";
echo
"</div>";
?>

</body>
</html>
<?php

/***********************************************
*         FUNCTIONS
* *********************************************/

function getOddAttribute($i,$card1Val,$card2Val) {
    global
$attributes;
    foreach(
$attributes[$i] as $attr) {
        if ((
$attr != $card1Val) && ($attr != $card2Val)) {
            return
$attr;
        }
    }
}
function
getThirdCardFromHand($thirdCard) {
    global
$hand;

    foreach (
$hand as $key=>$card) {
        if(
count(array_diff($card,$thirdCard))==0) {
            return
$key;
        }
    }
}

function
arrayUnique ( $rArray ){
  if(
count($rArray)>0) {
    
$rReturn = array ();
    while ( list(
$key, $val ) = each ( $rArray ) ){
        if ( !
in_array( $val, $rReturn ) )
            
array_push( $rReturn, $val );
    }
     return
$rReturn;
  } else {
     return
null;
  }
}
function
getRandomHand() {
        
$deck = getDeck();
        
$handIndexArray = array_rand($deck,12);
        
shuffle($handIndexArray);

        for (
$i=0;$i<=11;$i++) {
                
$hand[$i] = $deck[$handIndexArray[$i]];
        }
        return array(
$hand,$handIndexArray);
}

function
getHandFromKey($key){
        
$deck = getDeck();
        return
$deck[$key];
}


function
getDeck() {
    return array(
            
70=>  array('1','G','E','D'),
            
79=>  array('1','G','E','O'),
            
61=>  array('1','G','E','S'),
            
16=>  array('1','G','F','D'),
            
25=>  array('1','G','F','O'),
            
7=>   array('1','G','F','S'),
            
43=>  array('1','G','L','D'),
            
52=>  array('1','G','L','O'),
            
34=>  array('1','G','L','S'),

            
67=>  array('1','P','E','D'),
            
76=>  array('1','P','E','O'),
            
58=>  array('1','P','E','S'),
            
13=>  array('1','P','F','D'),
            
22=>  array('1','P','F','O'),
            
4=>   array('1','P','F','S'),
            
40=>  array('1','P','L','D'),
            
49=>  array('1','P','L','O'),
            
31=>  array('1','P','L','S'),

            
64=>  array('1','R','E','D'),
            
73=>  array('1','R','E','O'),
            
55=>  array('1','R','E','S'),
            
10=>  array('1','R','F','D'),
            
19=>  array('1','R','F','O'),
            
1=>   array('1','R','F','S'),
            
37=>  array('1','R','L','D'),
            
46=>  array('1','R','L','O'),
            
28=>  array('1','R','L','S'),

            
71=>  array('2','G','E','D'),
            
80=>  array('2','G','E','O'),
            
62=>  array('2','G','E','S'),
            
17=>  array('2','G','F','D'),
            
26=>  array('2','G','F','O'),
            
8=>   array('2','G','F','S'),
            
44=>  array('2','G','L','D'),
            
53=>  array('2','G','L','O'),
            
35=>  array('2','G','L','S'),

            
68=>  array('2','P','E','D'),
            
77=>  array('2','P','E','O'),
            
59=>  array('2','P','E','S'),
            
14=>  array('2','P','F','D'),
            
23=>  array('2','P','F','O'),
            
5=>   array('2','P','F','S'),
            
41=>  array('2','P','L','D'),
            
50=>  array('2','P','L','O'),
            
32=>  array('2','P','L','S'),

            
65=>  array('2','R','E','D'),
            
74=>  array('2','R','E','O'),
            
56=>  array('2','R','E','S'),
            
11=>  array('2','R','F','D'),
            
20=>  array('2','R','F','O'),
            
2=>   array('2','R','F','S'),
            
38=>  array('2','R','L','D'),
            
47=>  array('2','R','L','O'),
            
29=>  array('2','R','L','S'),

            
72=>  array('3','G','E','D'),
            
81=>  array('3','G','E','O'),
            
63=>  array('3','G','E','S'),
            
18=>  array('3','G','F','D'),
            
27=>  array('3','G','F','O'),
            
9=>   array('3','G','F','S'),
            
45=>  array('3','G','L','D'),
            
54=>  array('3','G','L','O'),
            
36=>  array('3','G','L','S'),

            
69=>  array('3','P','E','D'),
            
78=>  array('3','P','E','O'),
            
60=>  array('3','P','E','S'),
            
15=>  array('3','P','F','D'),
            
24=>  array('3','P','F','O'),
            
6=>   array('3','P','F','S'),
            
42=>  array('3','P','L','D'),
            
51=>  array('3','P','L','O'),
            
33=>  array('3','P','L','S'),

            
66=>  array('3','R','E','D'),
            
75=>  array('3','R','E','O'),
            
57=>  array('3','R','E','S'),
            
12=>  array('3','R','F','D'),
            
21=>  array('3','R','F','O'),
            
3=>   array('3','R','F','S'),
            
39=>  array('3','R','L','D'),
            
48=>  array('3','R','L','O'),
            
30=>  array('3','R','L','S')
                );
}

function
getImg($key) {
   if(
$key < 10) {
     
$key = "0".$key;
   }
   
$url = "<img src=\"images/$key.gif\" WIDTH=\"95\" HEIGHT=\"62\" style=\"border:1px solid silver\"/>";
   return
$url;
}


?>