<?php /**********************************************************
* Nicholas Clark
* 9/12/02
* Poker Contest
**********************************************************/
define('TWO_KIND',2);
define('TWO_PAIR',5);
define('THREE_KIND',8);
define('STRAIGHT',10);
define('FLUSH',15);
define('FULL_HOUSE',17);
define('FOUR_KIND',20);
define('STRAIGHT_FLUSH',25);
main();
function main() {
global $deck_values,$deck_suits,$hand_values,$hand_suits,$total_odds_value,$deck,$final_points;
get_deck_file();
while (sizeof($deck) > 8) {
$total_odds_value = $newhand_value = $newhand_suits = $test_suits = $test_value = $hand_suits = $hand_values = array();
$deck_keys = array_keys($deck);
for ($i = 0; $i < 5; $i++) {
$hand_suits[] = $deck_suits[$deck_keys[$i]];
$hand_values[] = $deck_values[$deck_keys[$i]];
unset($deck_suits[$deck_keys[$i]]);unset($deck_values[$deck_keys[$i]]);unset($deck[$deck_keys[$i]]);
}
$hand = array_join($hand_suits,$hand_values,',');
for ($i = 0; $i < 32; $i++) {
for ($j = 0; $j < 5; $j++) {
if ($i & pow(2,$j)) {
$test_suits[$i][] = $hand_suits[$j];
$test_value[$i][] = $hand_values[$j];
}
else {
$test_suits[$i][] = '*';
$test_value[$i][] = '*';
}
}
get_odds($test_value[$i],$test_suits[$i]);
}
arsort($total_odds_value);
$keys = array_keys($total_odds_value);
$count = 0;
$deck_keys = array_keys($deck);
for ($i = 0; $i < 5; $i++) {
if ($test_value[$keys[0]][$i]) {
$newhand_value[$i] = $test_value[$keys[0]][$i];
$newhand_suits[$i] = $test_suits[$keys[0]][$i];
}
else {
$newhand_suits[$i] = $deck_suits[$deck_keys[$count]];
$newhand_value[$i] = $deck_values[$deck_keys[$count]];
unset($deck_suits[$deck_keys[$count]]);unset($deck_values[$deck_keys[$count]]);unset($deck[$deck_keys[$count]]);
$count++;
}
}
$final_points += $final_hands[] = get_points($newhand_value,$newhand_suits);
}
$keys = array_keys($deck);
$file = fopen("output.txt",'w');
$final_hands = array_count_values($final_hands);
$total_hands = 0;
$total_points = 0;
foreach (array(
//0 => 'ZERO_HAND',
TWO_KIND => 'TWO_KIND',
TWO_PAIR => 'TWO_PAIR',
THREE_KIND => 'THREE_KIND',
STRAIGHT => 'STRAIGHT',
FLUSH => 'FLUSH',
FULL_HOUSE => 'FULL_HOUSE',
FOUR_KIND => 'FOUR_KIND',
STRAIGHT_FLUSH => 'STRAIGHT_FLUSH',
) as $id => $name) {
$final_hands[$id] += 1-1;
fwrite($file,$name.': '.$final_hands[$id]."n");
$total_hands += $final_hands[$id];
$total_points += $final_hands[$id]*$id;
}
fwrite($file,$total_hands."n".($total_points/$total_hands)."n".$total_points);
fclose($file);
}
function get_deck_file() {
global $suits,$cards,$deck_suits,$deck_values,$deck;
$suits = array('d','c','s','h');
$cards = array(2,3,4,5,6,7,8,9,10,11,12,13,14);
$file = file("input.txt");
foreach ($file as $card) {
$deck_values[] = str_replace(array('T','J','Q','K','A'),array(10,11,12,13,14),substr($card,0,1));
$deck_suits[] = strtolower(substr($card,1,1));
}
$deck = array_join($deck_suits,$deck_values,'');
}
function get_odds(&$values,&$suits) {
global $deck,$total_odds_value,$total_odds;
for ($i = 0; $i < 5; $i++) if ($values[$i] == '*') { unset($values[$i]);unset($suits[$i]); }
if (sizeof($values) < 2 && !in_array(14,$values)) {$total_odds_value[] = ''; return false;}
// odds for a straight-flush
$odds += get_odds_straightflush($values,$suits) * STRAIGHT_FLUSH;
// odds for a flush
$odds += get_odds_flush($suits) * FLUSH;
// odds for a straight
$odds += get_odds_straight($values) * STRAIGHT;
// odds for 4-kind
$odds += get_odds_xkind($values,4) * FOUR_KIND;
// odds for full house
$odds += get_odds_fullhouse($values) * FULL_HOUSE;
// odds for 3-kind
$odds += get_odds_xkind($values,3) * THREE_KIND;
// odds for 2-pair
$odds += get_odds_twopair($values) * TWO_PAIR;
// odds for 2-kind
$odds += get_odds_xkind($values,2) * TWO_KIND;
$total_odds_value[] = $odds;
return $odds;
}
function get_points(&$values,&$suits) {
// points for a straight-flush
if (get_points_straightflush($values,$suits)) return STRAIGHT_FLUSH;
// points for a flush
elseif (get_points_flush($suits)) return FLUSH;
// points for a straight
elseif (get_odds_straight($values)) return STRAIGHT;
// points for 4-kind
elseif (get_points_xkind($values,4)) return FOUR_KIND;
// points for full house
elseif (get_points_fullhouse($values)) return FULL_HOUSE;
// points for 3-kind
elseif (get_points_xkind($values,3)) return THREE_KIND;
// points for 2-pair
elseif (get_points_twopair($values)) return TWO_PAIR;
// points for 2-kind
elseif (get_points_xkind($values,2)) return TWO_KIND;
else return 0;
}
function get_odds_straightflush($values,$suits) {
global $deck,$deck_values,$total_odds;
if (array_max($values,0) > 1 || array_max($suits,0) != sizeof($suits)) return 0;
asort($values);
$keys = array_keys($values);
$lo = $values[$keys[0]];
$hi = $values[$keys[sizeof($values)-1]];
if ($hi - $lo >= 5) return 0;
if (sizeof($hand) == 5) return 1;
$deck_count = array_count_values($deck);
for ($i = $lo-4; $i <= $lo; $i++) {
if ($i < $hi-4 || $i < 2 || $i+4 > 14) continue;
$temp = 1;
for ($j = 0; $j < 5; $j++) {
if (in_array($j+$i,$values)) continue;
$temp *= $deck_count[$suits[$keys[0]].($j+$i)]/(sizeof($deck)-$count);
}
$odds += $temp*factorial(5-sizeof($values));
}
return $odds;
}
function get_odds_xkind($values,$amount) {
global $deck_values,$deck,$total_odds;
$left = array_count_values($deck_values);
$numleft = array_count_values($left);
// odds of getting x of a kind using one of the cards already in hand
foreach (array_count_values($values) as $key => $count) {
$numleft[4-$count]--;
if ($amount == $count) return 1;
elseif ($amount < $count) return 0;
elseif ($amount - $count > 5 - sizeof($values)) continue;
$temp = choose($left[$key],$amount-$count)*choose(sizeof($deck_values)-$left[$key],5-sizeof($values)-($amount-$count));
$odds += $temp;
}
// odds of getting x of a kind with a card not currently in your hand
if ($amount <= 5-sizeof($values)) {
for ($i = 4; $i >= $amount; $i--) {
$odds += choose($numleft[$i],1)*choose($i,$amount);
}
}
return $odds / choose(sizeof($deck),5-sizeof($values));
}
function get_odds_fullhouse($values) {
global $deck_values,$deck,$total_odds;
$cards = array_count_values($values);
if (sizeof($cards) > 2) return 0;
$keys = array_keys($cards);
$left = array_count_values($deck_values);
foreach ($left as $key => $value) {
if ($cards[$key]) continue;
$numleft[$value]++;
}
if (sizeof($cards) == 1) {
for ($j = 4; $j > 1; $j--) {
if (!$numleft[$j]) continue;
$odds += choose($left[$keys[0]],3-$cards[$keys[0]])*choose($numleft[$j],1)*choose($j,2) +
choose($left[$keys[0]],2-$cards[$keys[0]])*choose($numleft[$j],1)*choose($j,3);
}
}
else {
$odds = choose($left[$keys[0]],3-$cards[$keys[0]])*choose(1,1)*choose($cards[$keys[1]],2)+
choose($left[$keys[1]],3-$cards[$keys[1]])*choose(1,1)*choose($cards[$keys[0]],2);
}
return $odds / choose(sizeof($deck),5-sizeof($values));
}
function get_odds_twopair($values) {
global $deck_values,$deck,$total_odds;
$cards = array_count_values($values);
if (sizeof($cards) > 3) return 0;
arsort($cards);
$keys = array_keys($cards);
if (array_max($values,0) == 2 && array_max($values,1) == 2) return 1;
$left = array_count_values($deck_values);
foreach ($left as $key => $value) {
if ($cards[$key]) continue;
$numleft[$value]++;
}
if ($cards[$keys[0]] == 2) {
for ($i = 1; $i < sizeof($cards); $i++) {
$odds += choose($left[$keys[$i]],1)*choose(sizeof($deck)-$left[$keys[0]]-$left[$keys[$i]],5-sizeof($values)-1);
}
if (2 <= 5-sizeof($values)) {
for ($i = 4; $i >= 2; $i--) {
$odds += choose($numleft[$i],1)*choose($i,2)*choose(sizeof($deck)-$left[$keys[0]]-$i,5-sizeof($values)-2);
}
}
}
else {
for ($i = 0; $i < sizeof($cards); $i++) {
for ($j = 4; $j >= 2; $j--) {
$odds += choose($left[$keys[$i]],1)*choose($numleft[$j],1)*choose($j,2)*choose(sizeof($deck)-$left[$keys[$i]]-$j,5-sizeof($values)-3);
}
foreach ($values as $key => $value) {
if ($values[$keys[$i]] == $value) continue;
$odds += choose($left[$keys[$j]],1)*choose($left[$keys[$j]],1)*choose(sizeof($deck)-$left[$keys[$j]]-$left[$key],5-sizeof($values)-2);
}
}
}
return $odds / choose(sizeof($deck),5-sizeof($values));
}
function get_odds_flush($values) {
global $deck_suits,$total_odds;
if (sizeof(array_count_values($values)) != 1) return 0;
if (sizeof($values) == 5) return 1;
$left = array_count_values($deck_suits);
$keys = array_keys($values);
return choose($left[$values[$keys[0]]],5-sizeof($values))/choose(sizeof($deck_suits),5-sizeof($values));
}
function get_odds_straight($values) {
global $deck,$deck_values;
if (sizeof(array_count_values($values)) != sizeof($values)) return 0;
asort($values);
$keys = array_keys($values);
$lo = $values[$keys[0]];
$hi = $values[$keys[sizeof($values)-1]];
if ($hi - $lo >= 5) return 0;
if (sizeof($values) == 5) return 1;
$deck_count = array_count_values($deck_values);
for ($i = $lo-4; $i <= $lo; $i++) {
if ($i < $hi-4 || $i < 2 || $i+4 > 14) continue;
$temp = 1;
for ($j = 0; $j < 5; $j++) {
if (in_array($j+$i,$values)) continue;
$temp *= $deck_count[$j+$i]/(sizeof($deck)-$count);
}
$odds += $temp*factorial(5-sizeof($values));
}
return $odds;
}
function get_points_straightflush(&$values,&$suits) {
if (array_max($values,0) == 1 && array_max($suits,0) == 5) {
arsort($values);
$keys = array_keys($values);
if ($values[$keys[0]] - $values[$keys[4]] == 4) return true;
}
return false;
}
function get_points_flush(&$suits) {
if (array_max($suits,0) == 5) return true;
return false;
}
function get_points_straight(&$values) {
if (array_max($values,0) == 1) {
arsort($values);
$keys = array_keys($values);
if ($values[$keys[0]] - $values[$keys[4]] == 4) return true;
}
return false;
}
function get_points_xkind($values,$amount) {
if (array_max($values,0) == $amount) return true;
return false;
}
function get_points_fullhouse(&$values) {
if (array_max($values,0) == 3 && array_max($values,1) == 2) return true;
return false;
}
function get_points_twopair(&$values) {
if (array_max($values,0) == 2 && array_max($values,1) == 2) return true;
return false;
}
function choose($a=0,$b=0) {
if ($b > $a || $a < 0 || $b < 0) return 0;
$temp = 1;
for ($i = $a; $i > $a - $b; $i--) $temp *= $i;
return $temp / factorial($b);
}
function factorial($start) {
global $cache;
if ($start < 1) return 1;
if ($cache[$start]) return $cache[$start];
$output = 1;
for ($i = 1; $i <= $start; $i++) $output *= $i;
$cache[$start] = $output;
return $output;
}
function array_join($one,$two,$join) {
if (sizeof($one) != sizeof($two)) return false;
foreach ($one as $id => $key) $new[$id] = $one[$id].$join.$two[$id];
return $new;
}
function array_max($array,$offset = 0) {
$count = array_count_values($array);
arsort($count);
$keys = array_keys($count);
return $count[$keys[$offset]];
}
function array_multiply($keys) {
$output = 1;
foreach ($keys as $val) $output *= $val;
return $output;
} ?>
|
|