Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <assert.h>
- #include <stdio.h>
- #include <stdlib.h>
- #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
- #define CARDS_PER_HAND_MAX 5
- typedef enum Card {
- CARD_JOKER, /* Part 2 */
- CARD_TWO,
- CARD_THREE,
- CARD_FOUR,
- CARD_FIVE,
- CARD_SIX,
- CARD_SEVEN,
- CARD_EIGHT,
- CARD_NINE,
- CARD_TEN,
- // CARD_JACK, /* Part 1 */
- CARD_QUEEN,
- CARD_KING,
- CARD_ACE,
- CARD_SIZE, /* Number of unique cards. */
- } Card;
- typedef enum HandType {
- HAND_HIGH_CARD,
- HAND_ONE_PAIR,
- HAND_TWO_PAIR,
- HAND_THREE_OF_A_KIND,
- HAND_FULL_HOUSE,
- HAND_FOUR_OF_A_KIND,
- HAND_FIVE_OF_A_KIND,
- } HandType;
- typedef struct Hand {
- Card cards[CARDS_PER_HAND_MAX];
- HandType strength;
- int bid;
- } Hand;
- typedef struct Hands {
- size_t cap;
- size_t len;
- Hand data[];
- } Hands;
- static int ch_to_card(char c, Card *out)
- {
- switch (c) {
- case '2':
- *out = CARD_TWO;
- break;
- case '3':
- *out = CARD_THREE;
- break;
- case '4':
- *out = CARD_FOUR;
- break;
- case '5':
- *out = CARD_FIVE;
- break;
- case '6':
- *out = CARD_SIX;
- break;
- case '7':
- *out = CARD_SEVEN;
- break;
- case '8':
- *out = CARD_EIGHT;
- break;
- case '9':
- *out = CARD_NINE;
- break;
- case 'T':
- *out = CARD_TEN;
- break;
- case 'J':
- /* Part 1 */
- // *out = CARD_JACK;
- /* Part 2 */
- *out = CARD_JOKER;
- break;
- case 'Q':
- *out = CARD_QUEEN;
- break;
- case 'K':
- *out = CARD_KING;
- break;
- case 'A':
- *out = CARD_ACE;
- break;
- default:
- return -1;
- }
- return 0;
- }
- int cmp_int(const void *a, const void *b)
- {
- return (*(int *)a - *(int *)b);
- }
- int cmp_hand(const void *a, const void *b)
- {
- const Hand *h1 = a;
- const Hand *h2 = b;
- if (h1->strength != h2->strength) {
- return (int)h1->strength - (int)h2->strength;
- }
- for (size_t i = 0; i < CARDS_PER_HAND_MAX; i++) {
- if (h1->cards[i] == h2->cards[i]) {
- continue;
- }
- return (int)h1->cards[i] - (int)h2->cards[i];
- }
- return 0;
- }
- static Hands *parse(FILE *input, Hands *hands)
- {
- char cards_ch[CARDS_PER_HAND_MAX];
- int bid;
- for (hands->len = 0;
- fscanf(input, "%5c %d\n", cards_ch, &bid) != EOF;
- hands->len++) {
- if (hands->len >= hands->cap) {
- const size_t new_cap = hands->cap * 2;
- Hands *tmp = realloc(hands, sizeof(*hands) + (sizeof(hands->data[0]) * new_cap));
- if (tmp == NULL) {
- return NULL;
- }
- hands = tmp;
- hands->cap = new_cap;
- }
- hands->data[hands->len].bid = bid;
- size_t ncard_copies[CARD_SIZE] = { 0 };
- size_t njokers = 0;
- for (size_t i = 0; i < ARRAY_SIZE(cards_ch); i++) {
- Card *card = &hands->data[hands->len].cards[i];
- if (ch_to_card(cards_ch[i], card) != 0) {
- return NULL;
- }
- /* Part 1 */
- // ncard_copies[*card]++;
- /* Part 2 */
- if (*card == CARD_JOKER) {
- njokers++;
- } else {
- ncard_copies[*card]++;
- }
- }
- qsort(ncard_copies, ARRAY_SIZE(ncard_copies), sizeof(ncard_copies[0]), cmp_int);
- assert(ARRAY_SIZE(ncard_copies) >= 2);
- /* Part 1 */
- // size_t ncopies_most1 = ncard_copies[ARRAY_SIZE(ncard_copies) - 1];
- // size_t ncopies_most2 = ncard_copies[ARRAY_SIZE(ncard_copies) - 2];
- /* Part 2 */
- size_t ncopies_most1 = ncard_copies[ARRAY_SIZE(ncard_copies) - 1] + njokers;
- size_t ncopies_most2 = ncard_copies[ARRAY_SIZE(ncard_copies) - 2];
- /* Determine strength of hand. */
- if (ncopies_most1 == 5) {
- hands->data[hands->len].strength = HAND_FIVE_OF_A_KIND;
- } else if (ncopies_most1 == 4) {
- hands->data[hands->len].strength = HAND_FOUR_OF_A_KIND;
- } else if (ncopies_most1 == 3 && ncopies_most2 == 2) {
- hands->data[hands->len].strength = HAND_FULL_HOUSE;
- } else if (ncopies_most1 == 3) {
- hands->data[hands->len].strength = HAND_THREE_OF_A_KIND;
- } else if (ncopies_most1 == 2 && ncopies_most2 == 2) {
- hands->data[hands->len].strength = HAND_TWO_PAIR;
- } else if (ncopies_most1 == 2) {
- hands->data[hands->len].strength = HAND_ONE_PAIR;
- } else {
- hands->data[hands->len].strength = HAND_HIGH_CARD;
- }
- }
- return hands;
- }
- int main(void)
- {
- FILE *input = fopen("../input.txt", "rb");
- if (input == NULL) {
- perror("Error");
- exit(EXIT_FAILURE);
- }
- Hands *hands = malloc(sizeof(*hands) + (sizeof(hands->data[0]) * 2));
- if (hands == NULL) {
- perror("Error");
- exit(EXIT_FAILURE);
- }
- hands->cap = 2;
- hands->len = 0;
- hands = parse(input, hands);
- if (hands == NULL) {
- fprintf(stderr, "Error: failed to parse input");
- exit(EXIT_FAILURE);
- }
- qsort(hands->data, hands->len, sizeof(hands->data[0]), cmp_hand);
- int result = 0;
- for (size_t i = 0; i < hands->len; i++) {
- int rank = (int)i + 1;
- result += hands->data[i].bid * rank;
- }
- printf("Result: %d\n", result);
- free(hands);
- fclose(input);
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement