Advertisement
Guest User

aoc2023-7

a guest
Dec 7th, 2023
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.60 KB | Source Code | 0 0
  1. #include <assert.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4.  
  5. #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
  6. #define CARDS_PER_HAND_MAX 5
  7.  
  8. typedef enum Card {
  9.     CARD_JOKER, /* Part 2 */
  10.     CARD_TWO,
  11.     CARD_THREE,
  12.     CARD_FOUR,
  13.     CARD_FIVE,
  14.     CARD_SIX,
  15.     CARD_SEVEN,
  16.     CARD_EIGHT,
  17.     CARD_NINE,
  18.     CARD_TEN,
  19.     // CARD_JACK, /* Part 1 */
  20.     CARD_QUEEN,
  21.     CARD_KING,
  22.     CARD_ACE,
  23.  
  24.     CARD_SIZE, /* Number of unique cards. */
  25. } Card;
  26.  
  27. typedef enum HandType {
  28.     HAND_HIGH_CARD,
  29.     HAND_ONE_PAIR,
  30.     HAND_TWO_PAIR,
  31.     HAND_THREE_OF_A_KIND,
  32.     HAND_FULL_HOUSE,
  33.     HAND_FOUR_OF_A_KIND,
  34.     HAND_FIVE_OF_A_KIND,
  35. } HandType;
  36.  
  37. typedef struct Hand {
  38.     Card cards[CARDS_PER_HAND_MAX];
  39.     HandType strength;
  40.     int bid;
  41. } Hand;
  42.  
  43. typedef struct Hands {
  44.     size_t cap;
  45.     size_t len;
  46.     Hand data[];
  47. } Hands;
  48.  
  49. static int ch_to_card(char c, Card *out)
  50. {
  51.     switch (c) {
  52.     case '2':
  53.         *out = CARD_TWO;
  54.         break;
  55.     case '3':
  56.         *out = CARD_THREE;
  57.         break;
  58.     case '4':
  59.         *out = CARD_FOUR;
  60.         break;
  61.     case '5':
  62.         *out = CARD_FIVE;
  63.         break;
  64.     case '6':
  65.         *out = CARD_SIX;
  66.         break;
  67.     case '7':
  68.         *out = CARD_SEVEN;
  69.         break;
  70.     case '8':
  71.         *out = CARD_EIGHT;
  72.         break;
  73.     case '9':
  74.         *out = CARD_NINE;
  75.         break;
  76.     case 'T':
  77.         *out = CARD_TEN;
  78.         break;
  79.     case 'J':
  80.         /* Part 1 */
  81.         // *out = CARD_JACK;
  82.         /* Part 2 */
  83.         *out = CARD_JOKER;
  84.         break;
  85.     case 'Q':
  86.         *out = CARD_QUEEN;
  87.         break;
  88.     case 'K':
  89.         *out = CARD_KING;
  90.         break;
  91.     case 'A':
  92.         *out = CARD_ACE;
  93.         break;
  94.     default:
  95.         return -1;
  96.     }
  97.  
  98.     return 0;
  99. }
  100.  
  101. int cmp_int(const void *a, const void *b)
  102. {
  103.     return (*(int *)a - *(int *)b);
  104. }
  105.  
  106. int cmp_hand(const void *a, const void *b)
  107. {
  108.     const Hand *h1 = a;
  109.     const Hand *h2 = b;
  110.  
  111.     if (h1->strength != h2->strength) {
  112.         return (int)h1->strength - (int)h2->strength;
  113.     }
  114.  
  115.     for (size_t i = 0; i < CARDS_PER_HAND_MAX; i++) {
  116.         if (h1->cards[i] == h2->cards[i]) {
  117.             continue;
  118.         }
  119.  
  120.         return (int)h1->cards[i] - (int)h2->cards[i];
  121.     }
  122.  
  123.     return 0;
  124. }
  125.  
  126. static Hands *parse(FILE *input, Hands *hands)
  127. {
  128.     char cards_ch[CARDS_PER_HAND_MAX];
  129.     int bid;
  130.     for (hands->len = 0;
  131.          fscanf(input, "%5c %d\n", cards_ch, &bid) != EOF;
  132.          hands->len++) {
  133.  
  134.         if (hands->len >= hands->cap) {
  135.             const size_t new_cap = hands->cap * 2;
  136.             Hands *tmp = realloc(hands, sizeof(*hands) + (sizeof(hands->data[0]) * new_cap));
  137.             if (tmp == NULL) {
  138.                 return NULL;
  139.             }
  140.             hands = tmp;
  141.             hands->cap = new_cap;
  142.         }
  143.  
  144.         hands->data[hands->len].bid = bid;
  145.  
  146.         size_t ncard_copies[CARD_SIZE] = { 0 };
  147.         size_t njokers = 0;
  148.  
  149.         for (size_t i = 0; i < ARRAY_SIZE(cards_ch); i++) {
  150.             Card *card = &hands->data[hands->len].cards[i];
  151.             if (ch_to_card(cards_ch[i], card) != 0) {
  152.                 return NULL;
  153.             }
  154.  
  155.             /* Part 1 */
  156.             // ncard_copies[*card]++;
  157.  
  158.             /* Part 2 */
  159.             if (*card == CARD_JOKER) {
  160.                 njokers++;
  161.             } else {
  162.                 ncard_copies[*card]++;
  163.             }
  164.         }
  165.  
  166.         qsort(ncard_copies, ARRAY_SIZE(ncard_copies), sizeof(ncard_copies[0]), cmp_int);
  167.  
  168.         assert(ARRAY_SIZE(ncard_copies) >= 2);
  169.         /* Part 1 */
  170.         // size_t ncopies_most1 = ncard_copies[ARRAY_SIZE(ncard_copies) - 1];
  171.         // size_t ncopies_most2 = ncard_copies[ARRAY_SIZE(ncard_copies) - 2];
  172.  
  173.         /* Part 2 */
  174.         size_t ncopies_most1 = ncard_copies[ARRAY_SIZE(ncard_copies) - 1] + njokers;
  175.         size_t ncopies_most2 = ncard_copies[ARRAY_SIZE(ncard_copies) - 2];
  176.  
  177.         /* Determine strength of hand. */
  178.         if (ncopies_most1 == 5) {
  179.             hands->data[hands->len].strength = HAND_FIVE_OF_A_KIND;
  180.         } else if (ncopies_most1 == 4) {
  181.             hands->data[hands->len].strength = HAND_FOUR_OF_A_KIND;
  182.         } else if (ncopies_most1 == 3 && ncopies_most2 == 2) {
  183.             hands->data[hands->len].strength = HAND_FULL_HOUSE;
  184.         } else if (ncopies_most1 == 3) {
  185.             hands->data[hands->len].strength = HAND_THREE_OF_A_KIND;
  186.         } else if (ncopies_most1 == 2 && ncopies_most2 == 2) {
  187.             hands->data[hands->len].strength = HAND_TWO_PAIR;
  188.         } else if (ncopies_most1 == 2) {
  189.             hands->data[hands->len].strength = HAND_ONE_PAIR;
  190.         } else {
  191.             hands->data[hands->len].strength = HAND_HIGH_CARD;
  192.         }
  193.     }
  194.  
  195.     return hands;
  196. }
  197.  
  198. int main(void)
  199. {
  200.     FILE *input = fopen("../input.txt", "rb");
  201.     if (input == NULL) {
  202.         perror("Error");
  203.         exit(EXIT_FAILURE);
  204.     }
  205.  
  206.     Hands *hands = malloc(sizeof(*hands) + (sizeof(hands->data[0]) * 2));
  207.     if (hands == NULL) {
  208.         perror("Error");
  209.         exit(EXIT_FAILURE);
  210.     }
  211.  
  212.     hands->cap = 2;
  213.     hands->len = 0;
  214.  
  215.     hands = parse(input, hands);
  216.     if (hands == NULL) {
  217.         fprintf(stderr, "Error: failed to parse input");
  218.         exit(EXIT_FAILURE);
  219.     }
  220.  
  221.     qsort(hands->data, hands->len, sizeof(hands->data[0]), cmp_hand);
  222.  
  223.     int result = 0;
  224.  
  225.     for (size_t i = 0; i < hands->len; i++) {
  226.         int rank = (int)i + 1;
  227.         result += hands->data[i].bid * rank;
  228.     }
  229.  
  230.     printf("Result: %d\n", result);
  231.  
  232.     free(hands);
  233.     fclose(input);
  234.  
  235.     return EXIT_SUCCESS;
  236. }
  237.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement