Skip to content

Instantly share code, notes, and snippets.

@Alwinfy
Created December 7, 2023 06:31
Show Gist options
  • Save Alwinfy/68798e1873bb223024823da1f22c0c4f to your computer and use it in GitHub Desktop.
Save Alwinfy/68798e1873bb223024823da1f22c0c4f to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
typedef enum {
C_ACE, C_KING, C_QUEEN, C_JACK,
C_TEN, C_NINE, C_EIGHT, C_SEVEN,
C_SIX, C_FIVE, C_FOUR, C_THREE,
C_TWO
} card_t;
card_t parse_card(char ch) {
switch (ch) {
case 'A': return C_ACE;
case 'K': return C_KING;
case 'Q': return C_QUEEN;
case 'J': return C_JACK;
case 'T': return C_TEN;
case '9': return C_NINE;
case '8': return C_EIGHT;
case '7': return C_SEVEN;
case '6': return C_SIX;
case '5': return C_FIVE;
case '4': return C_FOUR;
case '3': return C_THREE;
case '2': return C_TWO;
}
fprintf(stderr, "bad card character: %c", ch);
exit(11);
}
int value(card_t card) {
return card;
}
int value2(card_t card) {
return card == C_JACK ? C_TWO + 1 : card;
}
typedef card_t hand_t[5];
typedef enum {
FIVE_OF_A_KIND,
FOUR_OF_A_KIND,
FULL_HOUSE,
THREE_OF_A_KIND,
TWO_PAIR,
ONE_PAIR,
HIGH_CARD,
} hand_strength;
hand_strength find_strength(const hand_t hand) {
struct {
card_t card;
int count;
} freqs[5];
int nfreqs = 0;
for (int i = 0; i < 5; i++) {
card_t card = hand[i];
for (int j = 0; j < nfreqs; j++) {
if (card == freqs[j].card) {
++freqs[j].count;
goto next;
}
}
freqs[nfreqs].card = card;
freqs[nfreqs].count = 1;
++nfreqs;
next: ;
}
switch (nfreqs) {
case 1: return FIVE_OF_A_KIND;
case 2: switch (freqs[0].count) {
case 1: case 4: return FOUR_OF_A_KIND;
case 2: case 3: return FULL_HOUSE;
}
case 3: do switch (freqs[--nfreqs].count) {
case 3: return THREE_OF_A_KIND;
case 2: return TWO_PAIR;
} while (1);
case 4: return ONE_PAIR;
case 5: return HIGH_CARD;
}
}
hand_strength optimize_hand(const hand_t in, hand_t test, int position) {
if (position) {
int i = position - 1;
if (in[i] == C_JACK) {
hand_strength best_strength = HIGH_CARD;
for (card_t card = C_ACE; card <= C_TWO; card++) {
if (card != C_JACK) {
test[i] = card;
}
hand_strength next_strength = optimize_hand(in, test, i);
best_strength = best_strength < next_strength ? best_strength : next_strength;
}
return best_strength;
}
else {
test[i] = in[i];
return optimize_hand(in, test, i);
}
}
return find_strength(test);
}
hand_strength run_optimize_hand(const hand_t in) {
hand_t test;
return optimize_hand(in, test, 5);
}
typedef struct {
hand_t hand;
int bid;
int score;
} hand_bid;
int bid_value(hand_bid bids[], int nbids) {
int acc = 0;
for (int i = 0; i < nbids; i++) {
acc += (i + 1) * bids[i].bid;
}
return acc;
}
int (*card_scorer)(card_t card);
int compare_hand_bids(const hand_bid *left, const hand_bid *right) {
int score_delta = right->score - left->score;
if (score_delta) return score_delta;
for (int i = 0; i < 5; i++) {
int val_delta = card_scorer(right->hand[i]) - card_scorer(left->hand[i]);
if (val_delta) return val_delta;
}
return 0;
}
void sort_bids(hand_bid bids[], int n_bids, hand_strength (*optimizer)(const hand_t hand)) {
for (int i = 0; i < n_bids; i++) {
bids[i].score = optimizer(bids[i].hand);
}
qsort(bids, n_bids, sizeof *bids, compare_hand_bids);
}
#define N_BIDS 1000
int main() {
hand_bid bids[N_BIDS];
size_t len;
char *buf;
for (int i = 0; i < N_BIDS; i++) {
getline(&buf, &len, stdin);
for (int j = 0; j < 5; j++) {
bids[i].hand[j] = parse_card(buf[j]);
}
bids[i].bid = atoi(buf + 6);
}
card_scorer = value;
sort_bids(bids, N_BIDS, find_strength);
printf("total value: %d\n", bid_value(bids, N_BIDS));
card_scorer = value2;
sort_bids(bids, N_BIDS, run_optimize_hand);
printf("total value: %d\n", bid_value(bids, N_BIDS));
free(buf);
exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment