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 }