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 }