249 lines
6.8 KiB
C
249 lines
6.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define LINE_MAX_LENGTH 64
|
|
#define MAX_HANDS 2048
|
|
#define CARDS_PER_HAND 5
|
|
|
|
enum hand_type {
|
|
UNKNOWN,
|
|
FIVE_OF_A_KIND,
|
|
FOUR_OF_A_KIND,
|
|
FULL_HOUSE,
|
|
THREE_OF_A_KIND,
|
|
TWO_PAIR,
|
|
ONE_PAIR,
|
|
HIGH_CARD
|
|
};
|
|
|
|
const char card_values[] = {'A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2'};
|
|
const char card_values2[] = {'A', 'K', 'Q', 'T', '9', '8', '7', '6', '5', '4', '3', '2', 'J'};
|
|
|
|
#define card_values_len (sizeof(card_values) / sizeof(card_values[0]))
|
|
|
|
typedef struct hand {
|
|
char cards[CARDS_PER_HAND];
|
|
unsigned long bid;
|
|
enum hand_type type;
|
|
} hand_t;
|
|
|
|
enum hand_type get_hand_type(hand_t *hand, int allow_joker);
|
|
int cmp(const void *a, const void *b);
|
|
int cmp2(const void *a, const void *b);
|
|
|
|
int main() {
|
|
char *p, *buf, c;
|
|
|
|
buf = (char *)malloc(LINE_MAX_LENGTH);
|
|
memset(buf, 0, LINE_MAX_LENGTH);
|
|
p = buf;
|
|
|
|
hand_t hands[MAX_HANDS];
|
|
memset(hands, 0, MAX_HANDS * sizeof(hand_t));
|
|
int hands_num = 0;
|
|
|
|
while ((c = getchar()) != EOF) {
|
|
*p++ = c;
|
|
if (c == '\n') {
|
|
p = buf;
|
|
sscanf(p, "%c%c%c%c%c %lu", &hands[hands_num].cards[0], &hands[hands_num].cards[1], &hands[hands_num].cards[2], &hands[hands_num].cards[3], &hands[hands_num].cards[4], &hands[hands_num].bid);
|
|
hands_num++;
|
|
memset(buf, 0, LINE_MAX_LENGTH);
|
|
p = buf;
|
|
}
|
|
}
|
|
|
|
// Part1
|
|
for (int i = 0; i < hands_num; i++) {
|
|
hands[i].type = get_hand_type(&hands[i], 0);
|
|
}
|
|
|
|
qsort(hands, hands_num, sizeof(hand_t), cmp);
|
|
|
|
unsigned long part1 = 0;
|
|
for (int i = 0; i < hands_num; i++) {
|
|
part1 += (i+1) * hands[i].bid;
|
|
}
|
|
|
|
printf("%lu\n", part1);
|
|
|
|
// Part2
|
|
for (int i = 0; i < hands_num; i++) {
|
|
hands[i].type = get_hand_type(&hands[i], 1);
|
|
}
|
|
|
|
qsort(hands, hands_num, sizeof(hand_t), cmp2);
|
|
|
|
unsigned long part2 = 0;
|
|
for (int i = 0; i < hands_num; i++) {
|
|
part2 += (i+1) * hands[i].bid;
|
|
}
|
|
|
|
printf("%lu\n", part2);
|
|
|
|
free(buf);
|
|
}
|
|
|
|
enum hand_type get_hand_type(hand_t *hand, int allow_joker) {
|
|
// Five of a kind
|
|
int good = 0;
|
|
for (int i = 0; i < CARDS_PER_HAND; i++) {
|
|
good = 0;
|
|
for (int j = 0; j < CARDS_PER_HAND; j++) {
|
|
if (hand->cards[i] == hand->cards[j] || (allow_joker && hand->cards[j] == 'J')) {
|
|
good++;
|
|
}
|
|
}
|
|
if (good == 5) {
|
|
return FIVE_OF_A_KIND;
|
|
}
|
|
}
|
|
|
|
// Four of a kind
|
|
for (int i = 0; i < CARDS_PER_HAND; i++) {
|
|
good = 0;
|
|
for (int j = 0; j < CARDS_PER_HAND; j++) {
|
|
if (hand->cards[i] == hand->cards[j] || (allow_joker && hand->cards[j] == 'J')) {
|
|
good++;
|
|
}
|
|
}
|
|
if (good == 4) {
|
|
return FOUR_OF_A_KIND;
|
|
}
|
|
}
|
|
|
|
// Full house
|
|
int good2 = 0;
|
|
for (int i = 0; i < CARDS_PER_HAND; i++) {
|
|
for (int j = 0; j < CARDS_PER_HAND; j++) {
|
|
good = 0;
|
|
good2 = 0;
|
|
int used_jokers[5] = {0, 0, 0, 0, 0};
|
|
for (int k = 0; k < CARDS_PER_HAND; k++) {
|
|
if (hand->cards[i] == hand->cards[k] || (allow_joker && !used_jokers[k] && hand->cards[k] == 'J')) {
|
|
good++;
|
|
if (allow_joker && hand->cards[k] == 'J') {
|
|
used_jokers[k] = 1;
|
|
}
|
|
}
|
|
}
|
|
for (int k = 0; k < CARDS_PER_HAND; k++) {
|
|
if (hand->cards[j] == hand->cards[k] || (allow_joker && !used_jokers[k] && hand->cards[k] == 'J')) {
|
|
good2++;
|
|
}
|
|
}
|
|
if ((good == 3 && good2 == 2 || good == 2 && good2 == 3) && hand->cards[i] != 'J' && hand->cards[j] != 'J' && hand->cards[i] != hand->cards[j]) {
|
|
return FULL_HOUSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Three of a kind
|
|
for (int i = 0; i < CARDS_PER_HAND; i++) {
|
|
good = 0;
|
|
for (int j = 0; j < CARDS_PER_HAND; j++) {
|
|
if (hand->cards[i] == hand->cards[j] || (allow_joker && hand->cards[j] == 'J')) {
|
|
good++;
|
|
}
|
|
}
|
|
if (good == 3) {
|
|
return THREE_OF_A_KIND;
|
|
}
|
|
}
|
|
|
|
// Two pair
|
|
for (int i = 0; i < CARDS_PER_HAND; i++) {
|
|
for (int j = 0; j < CARDS_PER_HAND; j++) {
|
|
good = 0;
|
|
good2 = 0;
|
|
int used_joker = 0;
|
|
for (int k = 0; k < CARDS_PER_HAND; k++) {
|
|
if (hand->cards[i] == hand->cards[k] || (allow_joker && hand->cards[k] == 'J')) {
|
|
good++;
|
|
if (allow_joker && hand->cards[k] == 'J') {
|
|
used_joker = 1;
|
|
}
|
|
}
|
|
}
|
|
for (int k = 0; k < CARDS_PER_HAND; k++) {
|
|
if (hand->cards[j] == hand->cards[k] || (allow_joker && !used_joker && hand->cards[k] == 'J')) {
|
|
good2++;
|
|
}
|
|
}
|
|
if (good == 2 && good2 == 2 && hand->cards[i] != hand->cards[j]) {
|
|
return TWO_PAIR;
|
|
}
|
|
}
|
|
}
|
|
|
|
// One pair
|
|
for (int i = 0; i < CARDS_PER_HAND; i++) {
|
|
good = 0;
|
|
for (int j = 0; j < CARDS_PER_HAND; j++) {
|
|
if (hand->cards[i] == hand->cards[j] || (allow_joker && hand->cards[j] == 'J')) {
|
|
good++;
|
|
}
|
|
}
|
|
if (good == 2) {
|
|
return ONE_PAIR;
|
|
}
|
|
}
|
|
|
|
return HIGH_CARD;
|
|
}
|
|
|
|
int cmp(const void *a, const void *b) {
|
|
hand_t *hand1 = (hand_t*) a, *hand2 = (hand_t*) b;
|
|
|
|
if (hand1->type == hand2->type) {
|
|
for (int i = 0; i < CARDS_PER_HAND; i++) {
|
|
int j, k;
|
|
|
|
for (j = 0; j < card_values_len; j++) {
|
|
if (hand1->cards[i] == card_values[j]) {
|
|
break;
|
|
}
|
|
}
|
|
for (k = 0; k < card_values_len; k++) {
|
|
if (hand2->cards[i] == card_values[k]) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j != k) {
|
|
return k - j;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hand2->type - hand1->type;
|
|
}
|
|
|
|
int cmp2(const void *a, const void *b) {
|
|
hand_t *hand1 = (hand_t*) a, *hand2 = (hand_t*) b;
|
|
|
|
if (hand1->type == hand2->type) {
|
|
for (int i = 0; i < CARDS_PER_HAND; i++) {
|
|
int j, k;
|
|
|
|
for (j = 0; j < card_values_len; j++) {
|
|
if (hand1->cards[i] == card_values2[j]) {
|
|
break;
|
|
}
|
|
}
|
|
for (k = 0; k < card_values_len; k++) {
|
|
if (hand2->cards[i] == card_values2[k]) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j != k) {
|
|
return k - j;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hand2->type - hand1->type;
|
|
}
|