aocc22

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

uppga.c (4496B)


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