aocc22

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

uppgc.c (5038B)


      1 #include "common.h"
      2 #include <strings.h>
      3 
      4 #define DEFAULT_BOARD_SIZE 250000000
      5 #define MAXJ 1000000000000L
      6 //#define MAXJ 2022L
      7 
      8 typedef struct {
      9   size_t nalloc;
     10   long cmax;
     11   uint8_t *bd;
     12 } board;
     13 
     14 typedef struct {
     15   size_t height;
     16   uint8_t bd[4];
     17 } piece;
     18 
     19 static inline int isset(uint8_t row, size_t i) {
     20   assert(i < 7);
     21   if ((row & (0x40 >> i)) != 0)
     22     return 1;
     23   return 0;
     24 }
     25 
     26 static inline void set(uint8_t *row, size_t i) {
     27   assert(i < 7);
     28   *row |= (0x40 >> i);
     29 }
     30 
     31 void init_board(board *b) {
     32   b->nalloc = DEFAULT_BOARD_SIZE;
     33   b->cmax = -1;
     34   b->bd = calloc(b->nalloc, sizeof(*b->bd));
     35 }
     36 
     37 static inline void print_line(uint8_t v) {
     38   size_t j;
     39   for (j = 0; j < 7; j++) {
     40     if (isset(v, j)) {
     41       printf("#");
     42     } else {
     43       printf(".");
     44     }
     45   }
     46 }
     47 
     48 void print_piece(piece p) {
     49   printf("piece> h = %zu\n", p.height);
     50   size_t i;
     51   for (i = 0; i < p.height; i++) {
     52     print_line(p.bd[i]);
     53     printf("\n");
     54   }
     55 }
     56 
     57 void print_board(board *b) {
     58   int i;
     59   printf("+-------+\n");
     60   for (i = 0; i < b->cmax + 2; i++) {
     61     printf("|");
     62     print_line(b->bd[i]);
     63     printf("|\n");
     64   }
     65 }
     66 
     67 void print_board_with_piece(board *b, piece *p, long height) {
     68   size_t i;
     69   printf("+-------+\n");
     70   for (i = 0; i < height + 4; i++) {
     71     uint8_t d = 0;
     72     if (i < b->nalloc) {
     73       d |= b->bd[i];
     74     }
     75     if (i >= height && (i - height) < p->height) {
     76       d |= p->bd[i - height];
     77     }
     78     printf("|");
     79     print_line(d);
     80     printf("|\n");
     81   }
     82 }
     83 
     84 #define SWAP(x, y) (x ^= y ^= x ^= y)
     85 
     86 void read_pieces(piece *pcs, size_t npcs, char *filename) {
     87   char **lines;
     88   size_t nlines = readlines(&lines, filename);
     89   size_t cp = 0;
     90   size_t cpi = 0;
     91   size_t i, j;
     92 
     93   for (i = 0; i < npcs; i++)
     94     memset(pcs[i].bd, 0, 4);
     95 
     96   for (i = 0; i < nlines; i++) {
     97     if (strlen(lines[i]) < 2) {
     98       pcs[cp].height = cpi;
     99       cp++;
    100       cpi = 0;
    101       continue;
    102     }
    103     for (j = 0; j < strlen(lines[i]); j++) {
    104       if (lines[i][j] == '#') {
    105         set(&(pcs[cp].bd[cpi]), j);
    106       }
    107     }
    108     cpi++;
    109   }
    110   pcs[cp].height = cpi;
    111 
    112   for (i = 0; i < npcs; i++) {
    113     for (j = 0; j < pcs[i].height / 2; j++) {
    114       SWAP(pcs[i].bd[j], pcs[i].bd[pcs[i].height - 1 - j]);
    115     }
    116     for (j = 0; j < pcs[i].height; j++)
    117       pcs[i].bd[j] >>= 2;
    118   }
    119 }
    120 
    121 static inline void r_push_piece(piece *p, board *b, long h) {
    122   size_t i;
    123   for (i = 0; i < p->height; i++) {
    124     if ((p->bd[i] & 0x01) != 0)
    125       return; // cannot push
    126     if (((p->bd[i] >> 1) & b->bd[h + i]) != 0)
    127       return;
    128   }
    129 
    130   // pushable
    131   for (i = 0; i < p->height; i++)
    132     p->bd[i] >>= 1;
    133 }
    134 
    135 static inline void l_push_piece(piece *p, board *b, long h) {
    136   size_t i;
    137   for (i = 0; i < p->height; i++) {
    138     if ((p->bd[i] & 0x40) != 0)
    139       return; // cannot
    140     if (((p->bd[i] << 1) & b->bd[h + i]) != 0)
    141       return;
    142   }
    143 
    144   // pushable
    145   for (i = 0; i < p->height; i++)
    146     p->bd[i] <<= 1;
    147 }
    148 
    149 static inline int can_move_up(piece *p, board *b, long cheight) {
    150   size_t i;
    151   if (cheight <= 0)
    152     return 0;
    153   for (i = 0; i < p->height; i++) {
    154     if ((b->bd[i + cheight - 1] & p->bd[i]) != 0)
    155       return 0;
    156   }
    157   return 1;
    158 }
    159 
    160 static inline void draw_piece(piece *p, board *b, long height) {
    161   size_t i;
    162   for (i = 0; i < p->height; i++) {
    163     b->bd[i + height] |= p->bd[i];
    164   }
    165   //  printf("> drawing piece of h %zu at h %ld\n", p->height, height);
    166   long nmax = height + p->height - 1;
    167   b->cmax = nmax > b->cmax ? nmax : b->cmax;
    168 }
    169 
    170 static inline void try_lr_move(piece *p, board *b, long h, char *moves,
    171                                size_t nmoves, size_t *i) {
    172   if (moves[*i % nmoves] == '>') {
    173     r_push_piece(p, b, h);
    174   } else {
    175     l_push_piece(p, b, h);
    176   }
    177   (*i)++;
    178 }
    179 
    180 static inline void drop_piece(board *b, piece p, char *moves, size_t nmoves,
    181                               size_t *i) {
    182   long cheight = b->cmax + 4;
    183   try_lr_move(&p, b, cheight, moves, nmoves, i);
    184   while (can_move_up(&p, b, cheight)) {
    185     cheight--;
    186     try_lr_move(&p, b, cheight, moves, nmoves, i);
    187   }
    188 
    189   draw_piece(&p, b, cheight);
    190 }
    191 
    192 static inline long chomp_board(board *b) {
    193   long chomping = DEFAULT_BOARD_SIZE / 2;
    194   b->cmax -= chomping;
    195   memcpy(b->bd, &(b->bd[chomping]), chomping);
    196   bzero(&(b->bd[chomping]), chomping);
    197   return chomping;
    198 }
    199 
    200 int main(int argc, char **argv) {
    201   char **lines;
    202   size_t nlines = readlines(&lines, "input");
    203   printf("#lines: %lu\n", nlines);
    204 
    205   assert(nlines == 1);
    206 
    207   char *moves = lines[0];
    208   size_t nmoves = strlen(moves);
    209   if (moves[nmoves - 1] == '\n')
    210     nmoves--;
    211 
    212   printf("#moves: %zu\n", nmoves);
    213 
    214   board b;
    215   init_board(&b);
    216 
    217   piece pcs[5];
    218   read_pieces(pcs, 5, "pieces");
    219 
    220   size_t i;
    221   for (i = 0; i < 5; i++) {
    222     print_piece(pcs[i]);
    223   }
    224 
    225   i = 0;
    226   size_t j;
    227   long chompd = 0;
    228   for (j = 0; j < MAXJ; j++) {
    229     drop_piece(&b, pcs[j % 5], moves, nmoves, &i);
    230     if (b.cmax + 5 > DEFAULT_BOARD_SIZE)
    231       chompd += chomp_board(&b);
    232     if ((j % (MAXJ / 1000)) == 0)
    233       printf("%lu\n", j / (MAXJ / 1000));
    234   }
    235   printf("(%zu): %lu\n", j, chompd + b.cmax + 1);
    236   printf("chompd %lu\n", chompd);
    237 }