#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define dprintf

#define MAX_PLAYERS 32

#define SF 0x8000000 // straight flush
#define FK 0x7000000 // four of a kind
#define FH 0x6000000 // full house
#define FL 0x5000000 // flush
#define ST 0x4000000 // straight
#define TK 0x3000000 // three of a kind
#define TP 0x2000000 // two pairs
#define OP 0x1000000 // one pair
#define HC 0x0000000 // high card

unsigned int hcrank(int *card, int discard)
{
	// high-card ranking
	int rank = 0;

	for (int i = 12; i >= 0; --i) {
		for (int j = 0; j < card[i]; ++j) {
		 	rank <<= 4;
			rank |= i;
		}
	}

	return rank >> (discard << 2);
}

char hand[7][3];

int straightflush(int suit)
{
	int card[13] = {};

	for (int i = 0; i < 7; ++i) {
		if (hand[i][1] == suit)
			card[(int)hand[i][0]]++;
	}

	// straight preprocessing
	int straight = 0;

	int sum[13] = { !!card[0] };
	//printf("%d ", sum[0]);
	for (int i = 1; i < 13; ++i) {
		sum[i] = (sum[i-1] + 1) * !!card[i];
		//printf("%d ", sum[i]);

		if (sum[i] >= 5) {
			straight = i;
		}
	}
	//printf("\n");
	if (!straight && sum[3] == 4 && card[12]) {
		straight = 3; // five-high straight
	}

	return straight;
}

unsigned int score()
{
	// basic preprocessing
	int suit[4] = {};
	int card[13] = {};

	for (int i = 0; i < 7; ++i) {
		dprintf("%2d:%d ", hand[i][0], hand[i][1]);
		card[(int)hand[i][0]]++;
		suit[(int)hand[i][1]]++;
	}
	dprintf("\t");

	// flush preprocessing
	int flush = -1;

	for (int i = 0; i < 4; ++i) {
		if (suit[i] >= 5) {
			flush = i;
			break;
		}
	}
	//printf("flush: %d\n", flush);

	// straight preprocessing
	int straight = 0;

	int sum[13] = { !!card[0] };
	//printf("%d ", sum[0]);
	for (int i = 1; i < 13; ++i) {
		sum[i] = (sum[i-1] + 1) * !!card[i];
		//printf("%d ", sum[i]);

		if (sum[i] >= 5) {
			straight = i;
		}
	}
	//printf("\n");
	if (!straight && sum[3] == 4 && card[12]) {
		straight = 3; // five-high straight
	}

	//printf("straight: %d\n", straight);

	// straight flush
	if (straight && flush != -1) {
		// maybe theres a straight flush here
		int sf = straightflush(flush);

		if (sf) {
			return SF | sf;
		}
	}

	// more processing
	int counts[5] = { -1, -1, -1, -1, -1 };
	for (int i = 0; i < 13; ++i) {
		counts[card[i]] = i;
	}

	// four of a kind
	if (counts[4] != -1) {
		return FK | (counts[4] << 4) | counts[1];
	}

	// full house
	if (counts[3] != -1) {
		int j = counts[3];
		//printf("fh %d\n", j);
		for (int i = 12; i >= 0; --i) {
			if (card[i] >= 2 && i != j) {
				if (card[i] == 3)
					return FH |
						i << (i > j ? 4 : 0) |
						j << (i > j ? 0 : 4);
				else
					return FH | (j << 4) | i;
			}
		}
	}

	// flush
	if (flush != -1) {
		int discard = 2;
		for (int i = 0; i < 7; ++i) {
			if (hand[i][1] != flush) {
				card[(int)hand[i][0]]--;
				discard--;
			}
		}
		return FL | hcrank(card, discard);
	}

	// straight
	if (straight) {
		return ST | straight;
	}

	// three of a kind
	if (counts[3] != -1) {
		card[counts[3]] = 0;
		return TK | (counts[3] << 8) | hcrank(card, 2);
	}

	// pairs
	if (counts[2] != -1) {
		int firstpair = counts[2];
		int secondpair = -1;

		for (int i = 12; i >= 0; --i) {
			if (card[i] == 2 && i != firstpair) {
				secondpair = i;
				break;
			}
		}

		if (secondpair == -1) {
			card[firstpair] = 0;
			return OP | (firstpair << 16) | hcrank(card, 2);
		}

		card[firstpair] = 0;
		card[secondpair] = 0;
		return TP | (firstpair << 8) | (secondpair << 4) | hcrank(card, 2);
	}

	return HC + hcrank(card, 2);
}

void readcard(char *c)
{
	scanf("%s", c);

	if (c[0] >= '2' && c[0] <= '9')
		c[0] -= '2';
	if (c[0] == 'T') c[0] = 8;
	if (c[0] == 'J') c[0] = 9;
	if (c[0] == 'Q') c[0] = 10;
	if (c[0] == 'K') c[0] = 11;
	if (c[0] == 'A') c[0] = 12;

	if (c[1] == 'h') c[1] = 0;
	if (c[1] == 'd') c[1] = 1;
	if (c[1] == 's') c[1] = 2;
	if (c[1] == 'c') c[1] = 3;
}

int best[MAX_PLAYERS];

int main()
{
	int T;
	scanf("%d", &T);

	while (T--) {
		int n, bestscore = 0;
		scanf("%d", &n);

		for (int i = 0; i < 5; ++i) {
			readcard(hand[i]);
		}

		for (int i = 0; i < n; ++i) {
			readcard(hand[5]);
			readcard(hand[6]);

			best[i] = score();
			dprintf("%07x\n", best[i]);
			if (best[i] > bestscore) {
				bestscore = best[i];
			}
		}

		int first = 1;
		for (int i = 0; i < n; ++i) {
			if (best[i] == bestscore) {
				if (first) {
					printf("%d", i);
					first = 0;
				}
				else {
					printf(" %d", i);
				}
			}
		}
		printf("\n");
	}

	return 0;
}

Scoreboard

lzm bas adv bon 200
sirpengi bas adv bon 200
sixthgear bas adv bon 190
mserrano bas adv bon 190
robbinsr bas adv bon 190
synx bas adv bon 50

What do?

  1. Write your program according to the problem description
  2. Download the basic input set. The timer will start.
  3. Feed the input file to your program and save the output.
  4. Upload the output file along with your source code. If it is correct, you will receive points. If not you may try again until the timer expires.
  5. If the timer expires. You may try again, but a new input file will be generated.
  6. Repeat fot each set.

Note: The input sets use unix line endings (\n) and the verifier expects them as well.


Come Chat!

Join channel ##proggit on freenode.

Bugs

Having issues with the the site? Let us know.