Re: 10315 - Poker Hands
Posted: Mon Dec 15, 2014 8:16 pm
help me out guys
i've checked all samples but still wrong answer from the judge
i've checked all samples but still wrong answer from the judge
Code: Select all
/*
* UVa Online Judge
* 10315 - Poker Hands
* Ad-Hoc - Game
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef enum {
BLACK = 0,
WHITE = 1,
PLAYER_COUNT,
TIE,
} player;
typedef enum {
HIGH_CARD, PAIR, TWO_PAIRS, THREE_OF_A_KIND,
STRAIGHT, FLUSH, FULL_HOUSE, FOUR_OF_A_KIND,
STRAIGHT_FLUSH,
} hand;
typedef enum {
CARD_2 = 2, CARD_3 = 3, CARD_4 = 4, CARD_5 = 5,
CARD_6 = 6, CARD_7 = 7, CARD_8 = 8, CARD_9 = 9,
CARD_10 = 10, CARD_J = 11, CARD_Q = 12, CARD_K = 13,
CARD_A = 14
} card_value;
unsigned int sym_to_num[] = {
['2'] = CARD_2, ['3'] = CARD_3, ['4'] = CARD_4, ['5'] = CARD_5,
['6'] = CARD_6, ['7'] = CARD_7, ['8'] = CARD_8, ['9'] = CARD_9,
['T'] = CARD_10, ['J'] = CARD_J, ['Q'] = CARD_Q, ['K'] = CARD_K,
['A'] = CARD_A,
};
#define CARDS_PLAYER 5
#define SYM_PER_CARD 3
#define VALUE_NDX 0
#define SUIT_NDX 1
#define MAX_POSSIBLE_PAIRS 2
struct poker_hand {
char cards[CARDS_PLAYER * SYM_PER_CARD];
bool seen[CARDS_PLAYER];
size_t pairs;
char pair_values[MAX_POSSIBLE_PAIRS];
size_t same_cnt;
char same_value;
};
/* ----------- DEBUG -------------- */
void print_hand(struct poker_hand *h)
{
printf("Cards: ");
size_t i, j;
for (i = 0; i < CARDS_PLAYER; ++i) {
char *card = h->cards + (i * SYM_PER_CARD);
if (h->seen[i]) printf("[%s] ", card);
else printf("%s ", card);
}
printf("\n---\n");
printf("Pairs: %ld", h->pairs);
if (h->pairs > 0) {
printf(" ");
for (j = 0; j < h->pairs; ++j)
printf("[%c] ", h->pair_values[j]);
}
printf("\nSame: %ld", h->same_cnt);
if (h->same_cnt > 0) {
printf(" [%c]", h->same_value);
}
printf("\n");
}
void print_players(struct poker_hand *players)
{
printf("---------------------------------------\n");
printf(" -= BLACK =- \n");
print_hand(&players[BLACK]);
printf("\n -= WHITE =- \n");
print_hand(&players[WHITE]);
printf("---------------------------------------\n");
}
void print_hands(char cards[2][5][3])
{
printf("--- Black --- --- White ---\n");
size_t i, j;
for (i = 0; i < PLAYER_COUNT; ++i) {
for (j = 0; j < CARDS_PLAYER; ++j) {
printf("%s ", cards[i][j]);
}
printf(" ");
}
printf("\n");
}
/* ----------- END OF DEBUG -------------- */
int compare_ints(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
bool get_is_straight(struct poker_hand *player_hand)
{
size_t matches = 0;
unsigned int next_card = sym_to_num[player_hand->cards[VALUE_NDX]];
size_t i;
for (i = 0; i < CARDS_PLAYER; ++i) {
if (next_card > CARD_A) break;
if (next_card++ !=
sym_to_num[(player_hand->cards + i * SYM_PER_CARD)[VALUE_NDX]]) break;
++matches;
}
return (matches == CARDS_PLAYER);
}
bool get_is_flush(struct poker_hand *player_hand)
{
size_t same_suit = 1;
char suit = player_hand->cards[SUIT_NDX];
size_t i;
for (i = 1; i < CARDS_PLAYER; ++i) {
if ((player_hand->cards + (i * SYM_PER_CARD))[SUIT_NDX] == suit) ++same_suit;
}
return (same_suit == CARDS_PLAYER);
}
int compare_cards(const void *a, const void *b)
{
char *card_a = (char *)a;
char *card_b = (char *)b;
return sym_to_num[card_a[0]] - sym_to_num[card_b[0]];
}
void count_same(struct poker_hand *player_hand)
{
bool same_locations[CARDS_PLAYER];
size_t i, j, k;
for (i = 0; i < CARDS_PLAYER; ++i) {
if (player_hand->seen[i]) continue;
memset(same_locations, 0, sizeof(bool) * CARDS_PLAYER);
char current_card = (player_hand->cards + i * SYM_PER_CARD)[VALUE_NDX];
same_locations[i] = true;
size_t same_cnt = 1;
/* the actual counting */
for (j = 0; j < CARDS_PLAYER; ++j) {
if (player_hand->seen[i] || i == j) continue;
if (current_card == (player_hand->cards + j * SYM_PER_CARD)[VALUE_NDX]) {
same_locations[j] = true;
++same_cnt;
}
}
/* assign counts */
if (same_cnt >= 2) {
for (k = 0; k < CARDS_PLAYER; ++k) {
if ( !player_hand->seen[k]) {
player_hand->seen[k] = same_locations[k];
}
}
if (same_cnt > 2 && same_cnt > player_hand->same_cnt) {
player_hand->same_cnt = same_cnt;
player_hand->same_value = current_card;
}
else if (same_cnt == 2) {
player_hand->pair_values[player_hand->pairs++] = current_card;
}
}
}
}
hand player_hand_rank(struct poker_hand *player_hand)
{
qsort(player_hand->cards, CARDS_PLAYER,
sizeof(char) * SYM_PER_CARD,
compare_cards);
count_same(player_hand);
bool is_straight = get_is_straight(player_hand);
bool is_flush = get_is_flush(player_hand);
if (is_straight && is_flush)
return STRAIGHT_FLUSH;
if (player_hand->same_cnt == 4)
return FOUR_OF_A_KIND;
if (player_hand->same_cnt == 3 && player_hand->pairs == 1)
return FULL_HOUSE;
if (is_flush)
return FLUSH;
if (is_straight)
return STRAIGHT;
if (player_hand->same_cnt == 3 && player_hand->pairs == 0)
return THREE_OF_A_KIND;
if (player_hand->pairs == 2)
return TWO_PAIRS;
if (player_hand->pairs == 1)
return PAIR;
return HIGH_CARD;
}
player player_high_card(struct poker_hand *player_hands)
{
struct poker_hand *white = &player_hands[WHITE];
struct poker_hand *black = &player_hands[BLACK];
size_t white_ndx = CARDS_PLAYER - 1;
unsigned int white_card =
sym_to_num[(white->cards + (white_ndx-- * SYM_PER_CARD))[VALUE_NDX]];
player winner = TIE;
int i;
for (i = CARDS_PLAYER - 1; i >= 0; --i) {
unsigned int black_card =
sym_to_num[(black->cards + (i * SYM_PER_CARD))[VALUE_NDX]];
if (white_card != black_card) {
if (white_card < black_card) winner = BLACK;
else if (white_card > black_card) winner = WHITE;
break;
}
else {
white_card =
sym_to_num[(white->cards + (white_ndx * SYM_PER_CARD))[VALUE_NDX]];
i = 1 + white_ndx--;
}
}
return winner;
}
unsigned int next_unseen(struct poker_hand *player_hand)
{
unsigned int next_card = 0;
int i;
for (i = CARDS_PLAYER - 1; i >= 0; --i) {
if ( !player_hand->seen[i]) {
next_card = sym_to_num[(player_hand->cards + (i * SYM_PER_CARD))[VALUE_NDX]];
player_hand->seen[i] = true;
break;
}
}
return next_card;
}
player player_pair(struct poker_hand *player_hands)
{
struct poker_hand *white = &player_hands[WHITE];
struct poker_hand *black = &player_hands[BLACK];
/* get value of pair symbol for the pair */
unsigned int white_card = sym_to_num[white->pair_values[0]];
unsigned int black_card = sym_to_num[black->pair_values[0]];
player winner = TIE;
if (black_card == white_card) {
int i;
for (i = CARDS_PLAYER - 1; i >= 0; --i) {
black_card = next_unseen(black);
white_card = next_unseen(white);
if (white_card != black_card) {
if (white_card < black_card) winner = BLACK;
else if (white_card > black_card) winner = WHITE;
break;
}
}
}
else if (black_card > white_card) winner = BLACK;
else winner = WHITE;
return winner;
}
player _player_2pairs_2equal(struct poker_hand *white,
struct poker_hand *black)
{
unsigned int black_card = next_unseen(black);
unsigned int white_card = next_unseen(white);
if (white_card < black_card) return BLACK;
else if (white_card > black_card) return WHITE;
else return TIE;
}
player _player_2pairs_1equal(struct poker_hand *white,
unsigned int white_cards[],
struct poker_hand *black,
unsigned int black_cards[])
{
/* get the MAX indices */
size_t white_ndx = (white_cards[0] > white_cards[1]) ? 0 : 1;
size_t black_ndx = (black_cards[0] > black_cards[1]) ? 0 : 1;
player winner = TIE;
if (white_cards[white_ndx] > black_cards[black_ndx]) {
winner = WHITE;
}
else if (white_cards[white_ndx] < black_cards[black_ndx]) {
winner = BLACK;
}
else if (white_cards[white_ndx] == black_cards[black_ndx]) {
/* get the other pair (the MIN indices), by flipping MAX */
white_ndx = (white_ndx + 1) % 2;
black_ndx = (black_ndx + 1) % 2;
if (white_cards[white_ndx] == black_cards[black_ndx]) {
white_cards[0] = next_unseen(black);
black_cards[0] = next_unseen(white);
if (white_cards[0] != black_cards[0]) {
if (white_cards[0] < black_cards[0]) winner = BLACK;
else if (white_cards[0] > black_cards[0]) winner = WHITE;
}
}
else if (white_cards[white_ndx] > black_cards[black_ndx])
winner = WHITE;
else if (white_cards[white_ndx] < black_cards[black_ndx])
winner = BLACK;
}
return winner;
}
player player_2pairs(struct poker_hand *player_hands)
{
struct poker_hand *white = &player_hands[WHITE];
struct poker_hand *black = &player_hands[BLACK];
/* get value of pair symbol for the pair */
unsigned int white_cards[] = {
sym_to_num[white->pair_values[0]],
sym_to_num[white->pair_values[1]],
};
unsigned int black_cards[] = {
sym_to_num[black->pair_values[0]],
sym_to_num[black->pair_values[1]],
};
player winner = TIE;
/* both pairs are equal, e.g. KK,QQ and QQ,KK, check the remaining
* card for high value */
if ((white_cards[0] == black_cards[0] && white_cards[1] == black_cards[1])
|| (white_cards[0] == black_cards[1] && white_cards[1] == black_cards[0])) {
/* check the remaining card */
winner = _player_2pairs_2equal(white, black);
}
/* one pair is equal and the other differs */
else if ( (white_cards[0] == black_cards[0] && white_cards[1] != black_cards[1])
|| (white_cards[0] == black_cards[1] && white_cards[1] != black_cards[0])
|| (white_cards[1] == black_cards[0] && white_cards[0] != black_cards[1])
|| (white_cards[1] == black_cards[1] && white_cards[0] != black_cards[0])) {
winner = _player_2pairs_1equal(white, white_cards, black, black_cards);
}
/* both have 2 pairs which are different from each other */
else {
size_t white_ndx = (white_cards[0] > white_cards[1]) ? 0 : 1;
size_t black_ndx = (black_cards[0] > black_cards[1]) ? 0 : 1;
/* compare the largest pairs from both */
if (white_cards[white_ndx] < black_cards[black_ndx]) winner = BLACK;
else if (white_cards[white_ndx] > black_cards[black_ndx]) winner = WHITE;
}
return winner;
}
player player_3kind(struct poker_hand *player_hands)
{
struct poker_hand *white = &player_hands[WHITE];
struct poker_hand *black = &player_hands[BLACK];
unsigned int white_card = sym_to_num[white->same_value];
unsigned int black_card = sym_to_num[black->same_value];
if (white_card < black_card) return BLACK;
else if (white_card > black_card) return WHITE;
else {
do {
black_card = next_unseen(black);
white_card = next_unseen(white);
} while (black_card == white_card && (black_card != 0 || white_card != 0));
if (white_card < black_card) return BLACK;
else if (white_card > black_card) return WHITE;
return TIE;
}
}
player player_straight(struct poker_hand *player_hands)
{
struct poker_hand *white = &player_hands[WHITE];
struct poker_hand *black = &player_hands[BLACK];
unsigned int white_card = sym_to_num[
(white->cards + (CARDS_PLAYER - 1) * SYM_PER_CARD)[VALUE_NDX]];
unsigned int black_card = sym_to_num[
(black->cards + (CARDS_PLAYER - 1) * SYM_PER_CARD)[VALUE_NDX]];
if (white_card < black_card) return BLACK;
else if (white_card > black_card) return WHITE;
else return TIE;
}
player player_flush(struct poker_hand *player_hands)
{
return player_high_card(player_hands);
}
player player_full_house(struct poker_hand *player_hands)
{
struct poker_hand *white = &player_hands[WHITE];
struct poker_hand *black = &player_hands[BLACK];
player winner = player_3kind(player_hands);
if (winner == TIE) {
/* check for pair ranks if 3ees match */
unsigned int white_card = (white->pairs == 1) ?
sym_to_num[white->pair_values[0]] : 0;
unsigned int black_card = (black->pairs == 1) ?
sym_to_num[black->pair_values[0]] : 0;
if (white_card < black_card) winner = BLACK;
else if (white_card > black_card) winner = WHITE;
}
return winner;
}
player player_4kind(struct poker_hand *player_hands)
{
return player_3kind(player_hands);
}
player player_straight_flush(struct poker_hand *player_hands)
{
return player_straight(player_hands);
}
void find_winner(struct poker_hand *player_hands)
{
hand black_hand = player_hand_rank(&player_hands[BLACK]);
hand white_hand = player_hand_rank(&player_hands[WHITE]);
player winner = TIE;
if (black_hand > white_hand)
winner = BLACK;
else if (black_hand < white_hand)
winner = WHITE;
else { /* black_hand == white_hand */
if (black_hand == STRAIGHT_FLUSH)
winner = player_straight_flush(player_hands);
else if (black_hand == FOUR_OF_A_KIND)
winner = player_4kind(player_hands);
else if (black_hand == FULL_HOUSE)
winner = player_full_house(player_hands);
else if (black_hand == FLUSH)
winner = player_flush(player_hands);
else if (black_hand == STRAIGHT)
winner = player_straight(player_hands);
else if (black_hand == THREE_OF_A_KIND)
winner = player_3kind(player_hands);
else if (black_hand == TWO_PAIRS)
winner = player_2pairs(player_hands);
else if (black_hand == PAIR)
winner = player_pair(player_hands);
else if (black_hand == HIGH_CARD)
winner = player_high_card(player_hands);
}
if (winner == BLACK) printf("Black wins.\n");
else if (winner == WHITE) printf("White wins.\n");
else if (winner == TIE) printf("Tie.\n");
}
int main(int argc, const char **argv)
{
(void)argc;
(void)argv;
int status;
size_t i, j;
struct poker_hand player_hands[PLAYER_COUNT];
while ( !feof(stdin)) {
memset(player_hands, 0, sizeof(player_hands));
for (i = 0; i < PLAYER_COUNT; ++i) {
for (j = 0; j < CARDS_PLAYER; ++j) {
status = scanf(" %2s", player_hands[i].cards + (j * SYM_PER_CARD));
}
}
status = scanf("\n");
find_winner(player_hands);
}
exit(EXIT_SUCCESS);
}