aocc23

Advent of Code 2023
git clone git://www.tkruger.se/aocc23.git
Log | Files | Refs | README

uppgb.c (2341B)


      1 #include "common.h"
      2 
      3 int cmp(const void *a, const void *b);
      4 
      5 int cmp(const void *a, const void *b) {
      6   size_t i;
      7 
      8   hand_t ha = *(const hand_t *)a;
      9   hand_t hb = *(const hand_t *)b;
     10 
     11   uint64_t ha_val = ha.maxval;
     12   uint64_t hb_val = hb.maxval;
     13 
     14   if (ha_val != hb_val) {
     15     if (ha_val < hb_val)
     16       return -1;
     17     else
     18       return 1;
     19   } else {
     20     for (i = 0; i < 5; i++) {
     21       if (ha.cards[i] != hb.cards[i]) {
     22         if (ha.cards[i] < hb.cards[i])
     23           return -1;
     24         else
     25           return 1;
     26       }
     27     }
     28   }
     29 
     30   return 0;
     31 }
     32 
     33 static inline uint8_t char_to_card(const char c) {
     34   if ('2' <= c && c <= '9')
     35     return (uint8_t)(c - '0');
     36   switch (c) {
     37   case 'T':
     38     return 10;
     39   case 'J':
     40     return 1;
     41   case 'Q':
     42     return 12;
     43   case 'K':
     44     return 13;
     45   case 'A':
     46     return 14;
     47   default:
     48     exit(1);
     49   }
     50 }
     51 
     52 static inline int all_jokers_are_aces(hand_t *t, hand_t *h) {
     53   size_t i;
     54 
     55   for (i = 0; i < 5; i++) {
     56     if (h->cards[i] == 1 && t->cards[i] != 14)
     57       return 0;
     58   }
     59 
     60   return 1;
     61 }
     62 
     63 static inline void increment_jokers(hand_t *t, hand_t *h) {
     64   size_t i;
     65 
     66   for (i = 0; i < 5; i++) {
     67     if (h->cards[i] == 1) {
     68       if (t->cards[i] != 14) {
     69         t->cards[i]++;
     70         return;
     71       } else {
     72         t->cards[i] = 2;
     73       }
     74     }
     75   }
     76 }
     77 
     78 static inline uint64_t find_max_val(hand_t h) {
     79   uint64_t maxval = 0;
     80   uint64_t tmpval;
     81   hand_t t = h;
     82 
     83   size_t i;
     84   for (i = 0; i < 5; i++) {
     85     if (t.cards[i] == 1)
     86       t.cards[i] = 2;
     87   }
     88 
     89   while (!all_jokers_are_aces(&t, &h)) {
     90     tmpval = hand_value(t);
     91     if (tmpval > maxval)
     92       maxval = tmpval;
     93     increment_jokers(&t, &h);
     94   }
     95 
     96   tmpval = hand_value(t);
     97   if (tmpval > maxval)
     98     maxval = tmpval;
     99 
    100   return maxval;
    101 }
    102 
    103 static inline void read_hands(hand_t *h, char **lines, const size_t nlines) {
    104   size_t i, j;
    105 
    106   for (i = 0; i < nlines; i++) {
    107     for (j = 0; j < 5; j++)
    108       h[i].cards[j] = char_to_card(lines[i][j]);
    109     sread_next_u64(&(h[i].bid), &lines[i][6]);
    110     h[i].maxval = find_max_val(h[i]);
    111   }
    112 }
    113 
    114 int main(int argc, char **argv) {
    115   char **lines;
    116   size_t nlines = readlines(&lines, "input");
    117 
    118   hand_t h[nlines];
    119   read_hands(h, lines, nlines);
    120 
    121   qsort(h, nlines, sizeof(h[0]), cmp);
    122 
    123   uint64_t m;
    124   uint64_t sum = 0;
    125   for (m = 0; m < nlines; m++) {
    126     sum += (m + 1) * h[m].bid;
    127   }
    128 
    129   printf("%llu\n", sum);
    130 }