main.c (20982B)
1#include "aoc.h" 2#include "allocator.h" 3#include "dvec_s.h" 4#include "hmap.h" 5#include "util.h" 6#include "list.h" 7#include "vec.h" 8 9#include <signal.h> 10#include <assert.h> 11#include <ctype.h> 12#include <stdbool.h> 13#include <stdint.h> 14 15struct state { 16 struct vec2i pos; 17 uint32_t acquired; 18 size_t dist; 19 struct list_link link; 20}; 21 22struct state_multi { 23 struct vec2i pos[4]; 24 uint32_t acquired; 25 size_t dist; 26 struct list_link link; 27}; 28 29struct prog { 30 uint32_t acquired; 31 size_t dist; 32}; 33 34struct path { 35 uint32_t required; 36 size_t dist; 37}; 38 39struct keypath { 40 uint32_t required; 41 size_t dist; 42 struct vec2i pos; 43 uint32_t keymask; 44 char key; 45}; 46 47struct node { 48 struct dvec edges; 49 int key; 50}; 51 52const struct vec2i dirs[] = { 53 { 0, -1 }, 54 { 1, 0 }, 55 { 0, 1 }, 56 { -1, 0 }, 57}; 58 59static inline bool 60bit_subset(uint32_t a, uint32_t b) 61{ 62 return (a & b) == a; 63} 64 65static inline bool 66bit_proper_subset(uint32_t a, uint32_t b) 67{ 68 return bit_subset(a, b) && (a < b); 69} 70 71static inline bool 72bit_superset(uint32_t a, uint32_t b) 73{ 74 return (a & b) == b; 75} 76 77static inline bool 78bit_proper_superset(uint32_t a, uint32_t b) 79{ 80 return bit_superset(a, b) && (a > b); 81} 82 83bool 84vec2i_hmap_keycmp(struct hmap_key k1, struct hmap_key k2) 85{ 86 const struct vec2i *v1 = k1.p, *v2 = k2.p; 87 88 return vec2i_eql(v1, v2); 89} 90 91uint32_t 92vec2i_hmap_hash(struct hmap_key key) 93{ 94 const struct vec2i *v = key.p; 95 96 return (uint32_t) v->x + (uint32_t) v->y * 80; 97} 98 99bool 100vec2i_multi_hmap_keycmp(struct hmap_key k1, struct hmap_key k2) 101{ 102 const struct vec2i *v1 = k1.p, *v2 = k2.p; 103 size_t i; 104 105 for (i = 0; i < 4; i++) { 106 if (!vec2i_eql(&v1[i], &v2[i])) 107 return false; 108 } 109 110 return true; 111} 112 113uint32_t 114vec2i_multi_hmap_hash(struct hmap_key key) 115{ 116 const struct vec2i *v = key.p; 117 uint32_t hash; 118 size_t i; 119 120 hash = 0; 121 for (i = 0; i < 4; i++) 122 hash += (uint32_t) v[i].x + (uint32_t) v[i].y * 80; 123 124 return hash; 125} 126 127void 128print_map(const struct hmap *map, struct hmap *distmap, 129 const struct vec2i *start, uint32_t acquired) 130{ 131 struct hmap_iter iter; 132 struct hmap_link *link; 133 struct vec2i min, max; 134 struct vec2i pos; 135 uint32_t mask; 136 char c; 137 138 vec2i_set(&min, start); 139 vec2i_set(&max, start); 140 for (HMAP_ITER(map, iter)) { 141 vec2i_set(&pos, iter.link->key._p); 142 if (pos.x < min.x) min.x = pos.x; 143 if (pos.y < min.y) min.y = pos.y; 144 if (pos.x > max.x) max.x = pos.x; 145 if (pos.y > max.y) max.y = pos.y; 146 } 147 148 aoc_debug("+"); 149 for (pos.x = min.x; pos.x <= max.x; pos.x++) 150 aoc_debug("-"); 151 aoc_debug("+\n"); 152 153 for (pos.y = min.y; pos.y <= max.y; pos.y++) { 154 aoc_debug("|"); 155 for (pos.x = min.x; pos.x <= max.x; pos.x++) { 156 if (vec2i_eql(&pos, start)) { 157 aoc_debug("\x1b[5m@\x1b[0m"); 158 continue; 159 } 160 161 link = hmap_get(map, (struct hmap_key) {.p = &pos}); 162 if (link) { 163 c = link->value.c; 164 if (isalpha(c)) { 165 mask = islower(c) ? 1 << (c - 'a') 166 : 1 << (c - 'A'); 167 if (acquired & mask) { 168 aoc_debug("\x1b[90m%c\x1b[0m", c); 169 } else { 170 aoc_debug("%c", c); 171 } 172 continue; 173 } 174 175 link = hmap_get(distmap, 176 (struct hmap_key) {.p = &pos}); 177 if (link) { 178 aoc_debug(" "); 179 } else { 180 aoc_debug("%c", c); 181 } 182 } else { 183 aoc_debug(" "); 184 } 185 } 186 aoc_debug("|\n"); 187 } 188 189 aoc_debug("+"); 190 for (pos.x = min.x; pos.x <= max.x; pos.x++) 191 aoc_debug("-"); 192 aoc_debug("+\n"); 193} 194 195void 196parse_input(struct hmap *map, struct vec2i *start, size_t *keycnt) 197{ 198 const char *lpos, *lend; 199 const char *c; 200 char line[256]; 201 struct vec2i pos; 202 void *key; 203 204 *keycnt = 0; 205 206 lpos = aoc.input; 207 lend = aoc.input + aoc.input_size; 208 vec2i_setv(&pos, 0, 0); 209 while (readtok(line, sizeof(line), '\n', &lpos, lend)) { 210 pos.x = 0; 211 for (c = line; *c; c++) { 212 key = memdup(&pos, sizeof(struct vec2i)); 213 hmap_add(map, (struct hmap_key) {.p = key}, 214 (struct hmap_val) {.c = *c}); 215 if (islower(*c)) *keycnt += 1; 216 if (*c == '@') vec2i_set(start, &pos); 217 pos.x += 1; 218 } 219 pos.y += 1; 220 } 221} 222 223bool 224update_paths(struct dvec *paths, size_t dist, uint32_t required) 225{ 226 struct path *path; 227 228 for (DVEC_ITER(paths, path)) { 229 if (dist < path->dist) { 230 if (bit_subset(required, path->required)) { 231 path->required = required; 232 path->dist = dist; 233 return true; 234 } 235 } else if (dist == path->dist) { 236 if (bit_proper_subset(required, path->required)) { 237 path->required = required; 238 return true; 239 } 240 } else { 241 if (bit_superset(required, path->required)) 242 return false; 243 } 244 } 245 246 path = dvec_add_slot(paths); 247 path->dist = dist; 248 path->required = required; 249 250 return true; 251} 252 253void 254add_node(struct hmap *graph, const struct hmap *map, 255 const struct vec2i *start, int key) 256{ 257 struct hmap_iter iter; 258 struct dvec active, active_next; 259 struct state state, *cstate, *nstate; 260 struct dvec *paths; 261 struct path *path; 262 struct keypath *keypath; 263 struct hmap_link *link, **linkp; 264 struct hmap distmap; 265 struct node *node; 266 struct vec2i *pos; 267 size_t i; 268 char c; 269 270 /* 271 * - dijkstra from start pos 272 * - when we encounter a door, must have acquired corresponding key 273 * - distmap resolves to dvec of paths 274 * - only save new distance if less than all known paths 275 * and/or path requires a subset of keys 276 * 277 * - loop over keys in generated distance map 278 * - add keys as edges to node 279 */ 280 281 dvec_init(&active, sizeof(struct state), 10, 282 &stdlib_strict_heap_allocator); 283 dvec_init(&active_next, sizeof(struct state), 10, 284 &stdlib_strict_heap_allocator); 285 hmap_init(&distmap, 64, vec2i_hmap_hash, vec2i_hmap_keycmp, 286 &stdlib_strict_heap_allocator); 287 288 cstate = dvec_add_slot(&active_next); 289 vec2i_set(&cstate->pos, start); 290 cstate->acquired = 0; 291 cstate->dist = 0; 292 293 pos = memdup(start, sizeof(struct vec2i)); 294 paths = dvec_alloc(sizeof(struct path), 1, 295 &stdlib_strict_heap_allocator, NULL); 296 path = dvec_add_slot(paths); 297 path->dist = 0; 298 path->required = 0; 299 hmap_add(&distmap, (struct hmap_key) {.p = pos}, 300 (struct hmap_val) {.p = paths}); 301 302 while (!dvec_empty(&active_next)) { 303 dvec_swap(&active, &active_next); 304 dvec_clear(&active_next); 305 306 for (DVEC_ITER(&active, cstate)) { 307 for (i = 0; i < ARRLEN(dirs); i++) { 308 vec2i_add(&state.pos, &cstate->pos, &dirs[i]); 309 310 link = hmap_get(map, 311 (struct hmap_key) {.p = &state.pos}); 312 assert(link != NULL); 313 c = link->value.c; 314 if (c == '#') continue; 315 316 state.dist = cstate->dist + 1; 317 state.acquired = cstate->acquired; 318 if (isupper(c)) /* need key for door */ 319 state.acquired |= (1U << (c - 'A')); 320 321 linkp = hmap_link_pos(&distmap, 322 (struct hmap_key) {.p = &state.pos}); 323 if (*linkp) { 324 paths = (*linkp)->value._p; 325 } else { 326 pos = memdup(&state.pos, sizeof(struct vec2i)); 327 paths = dvec_alloc(sizeof(struct path), 328 1, &stdlib_strict_heap_allocator, 329 NULL); 330 *linkp = hmap_link_alloc(&distmap, 331 (struct hmap_key) {.p = pos}, 332 (struct hmap_val) {.p = paths}, 333 NULL); 334 } 335 336 if (update_paths(paths, state.dist, state.acquired)) { 337 nstate = dvec_add_slot(&active_next); 338 memcpy(nstate, &state, sizeof(struct state)); 339 } 340 } 341 } 342 } 343 344 node = malloc(sizeof(struct node)); 345 node->key = key; 346 dvec_init(&node->edges, sizeof(struct keypath), 1, 347 &stdlib_strict_heap_allocator); 348 for (HMAP_ITER(map, iter)) { 349 c = iter.link->value.c; 350 if (vec2i_eql(iter.link->key.p, start)) 351 continue; 352 if (islower(c)) { 353 link = hmap_get(&distmap, iter.link->key); 354 if (!link) continue; 355 pos = iter.link->key._p; 356 for (DVEC_ITER(link->value.p, path)) { 357 keypath = dvec_add_slot(&node->edges); 358 keypath->key = c; 359 keypath->keymask = 1U << (c - 'a'); 360 keypath->dist = path->dist; 361 keypath->required = path->required; 362 vec2i_set(&keypath->pos, iter.link->key.p); 363 } 364 } 365 } 366 pos = memdup(start, sizeof(struct vec2i)); 367 hmap_add(graph, (struct hmap_key) {.p = pos}, 368 (struct hmap_val) {.p = node}); 369 370 if (aoc.debug == 2) { 371 aoc_debug("add_node: %li %li\n", start->x, start->y); 372 print_map(map, &distmap, start, 0); 373 for (DVEC_ITER(&node->edges, keypath)) { 374 aoc_debug("path: %c %3lu %032b\n", keypath->key, 375 keypath->dist, keypath->required); 376 } 377 aoc_debug("\n"); 378 } 379 380 for (HMAP_ITER(&distmap, iter)) { 381 free(iter.link->key._p); 382 dvec_free(iter.link->value._p); 383 } 384 hmap_deinit(&distmap); 385 dvec_deinit(&active_next); 386 dvec_deinit(&active); 387} 388 389void 390gen_graph(struct hmap *graph, const struct hmap *map, 391 const struct vec2i *start, size_t keycnt) 392{ 393 struct hmap_iter iter; 394 395 add_node(graph, map, start, -1); 396 for (HMAP_ITER(map, iter)) { 397 if (islower(iter.link->value.c)) { 398 add_node(graph, map, iter.link->key.p, 399 iter.link->value.c - 'a'); 400 } 401 } 402} 403 404void 405sort_edges(struct dvec *edges) 406{ 407 struct keypath tmp, *a, *b; 408 size_t i, k; 409 410 if (!edges->len) return; 411 for (i = 0; i < edges->len - 1; i++) { 412 for (k = 0; k < edges->len - 1; k++) { 413 a = dvec_at(edges, k); 414 b = dvec_at(edges, k + 1); 415 if (a->dist > b->dist) { 416 memcpy(&tmp, b, sizeof(struct keypath)); 417 memcpy(b, a, sizeof(struct keypath)); 418 memcpy(a, &tmp, sizeof(struct keypath)); 419 } 420 } 421 } 422} 423 424struct prog * 425update_progs(struct dvec *progs, size_t dist, uint32_t acquired) 426{ 427 struct prog *prog; 428 429 for (DVEC_ITER(progs, prog)) { 430 if (bit_superset(acquired, prog->acquired)) { 431 if (dist < prog->dist) { 432 prog->acquired = acquired; 433 prog->dist = dist; 434 return prog; 435 } else if (dist == prog->dist) { 436 if (acquired > prog->acquired) { 437 prog->acquired = acquired; 438 return prog; 439 } else { 440 return NULL; 441 } 442 } 443 } 444 } 445 446 prog = dvec_add_slot(progs); 447 prog->dist = dist; 448 prog->acquired = acquired; 449 450 return prog; 451} 452 453struct state * 454state_alloc(const struct vec2i *pos, size_t dist, uint32_t acquired) 455{ 456 struct state *state; 457 458 state = malloc(sizeof(struct state)); 459 vec2i_set(&state->pos, pos); 460 state->dist = dist; 461 state->acquired = acquired; 462 state->link = LIST_LINK_INIT; 463 464 return state; 465} 466 467bool 468state_dist_ordering(const void *p1, const void *p2, void *u) 469{ 470 const struct state *s1 = p1, *s2 = p2; 471 472 return s1->dist < s2->dist; 473} 474 475void 476add_keys(struct list *active, struct hmap *graph, 477 struct hmap *distmap, struct state *cstate, size_t keycnt) 478{ 479 struct hmap_link *link, **linkp; 480 struct state state, *nstate; 481 struct keypath *keypath; 482 struct dvec *progs; 483 struct node *node; 484 struct prog *prog; 485 struct vec2i *pos; 486 487 link = hmap_get(graph, (struct hmap_key) {.p = &cstate->pos}); 488 assert(link != NULL); 489 node = link->value._p; 490 491 for (DVEC_ITER(&node->edges, keypath)) { 492 if (cstate->acquired & keypath->keymask) 493 continue; 494 495 if (!bit_superset(cstate->acquired, keypath->required)) 496 continue; 497 498 vec2i_set(&state.pos, &keypath->pos); 499 state.dist = cstate->dist + keypath->dist; 500 state.acquired = cstate->acquired | keypath->keymask; 501 502 linkp = hmap_link_pos(distmap, (struct hmap_key) {.p = &state.pos}); 503 if (*linkp) { 504 progs = (*linkp)->value._p; 505 } else { 506 pos = memdup(&state.pos, sizeof(struct vec2i)); 507 progs = dvec_alloc(sizeof(struct prog), 1, 508 &stdlib_strict_heap_allocator, NULL); 509 *linkp = hmap_link_alloc(distmap, 510 (struct hmap_key) {.p = pos}, 511 (struct hmap_val) {.p = progs}, NULL); 512 } 513 514 if ((prog = update_progs(progs, state.dist, state.acquired))) { 515 aoc_debug("updated prog %i %i %032b %032b\n", 516 prog->dist, state.dist, prog->acquired, state.acquired); 517 nstate = state_alloc(&state.pos, state.dist, state.acquired); 518 list_insert_sorted(active, &nstate->link, 519 false, state_dist_ordering, 520 LIST_OFFSET(struct state, link), NULL); 521 } 522 } 523} 524 525size_t 526min_dist_all_keys(struct hmap *graph, const struct vec2i *start, size_t keycnt) 527{ 528 struct list_link *list_link; 529 struct hmap_link *hmap_link; 530 struct hmap_iter iter; 531 struct hmap distmap; 532 struct list active; 533 struct state *cstate; 534 struct dvec *progs; 535 struct prog *prog; 536 struct node *node; 537 struct vec2i *pos; 538 size_t mdist; 539 540 /* 541 * - dijkstra from starting node 542 * - only move over edges that we collected keys for 543 * - distmap resolves to dvec of progs 544 * - only save new distance if less than all known progs 545 * and/or we have a superset of previous keys 546 * - if we reach key and have, save mindist 547 */ 548 549 list_init(&active); 550 hmap_init(&distmap, 256, vec2i_hmap_hash, vec2i_hmap_keycmp, 551 &stdlib_strict_heap_allocator); 552 553 cstate = state_alloc(start, 0, 0); 554 list_insert_back(&active, &cstate->link); 555 556 pos = memdup(start, sizeof(struct vec2i)); 557 progs = dvec_alloc(sizeof(struct prog), 1, 558 &stdlib_strict_heap_allocator, NULL); 559 prog = dvec_add_slot(progs); 560 prog->acquired = 0; 561 prog->dist = 0; 562 hmap_add(&distmap, (struct hmap_key) {.p = pos}, 563 (struct hmap_val) {.p = progs}); 564 565 for (HMAP_ITER(graph, iter)) { 566 node = iter.link->value._p; 567 sort_edges(&node->edges); 568 } 569 570 mdist = 0; 571 while (!list_empty(&active)) { 572 list_link = list_front(&active); 573 cstate = LIST_UPCAST(list_link, struct state, link); 574 if (cstate->acquired == (1U << keycnt) - 1) { 575 mdist = cstate->dist; 576 goto exit; 577 } 578 579 list_link_pop(list_link); 580 581 hmap_link = hmap_get(&distmap, (struct hmap_key) {.p = &cstate->pos}); 582 assert(link != NULL); 583 for (DVEC_ITER(hmap_link->value.p, prog)) { 584 if (prog->dist < cstate->dist) { 585 if (bit_superset(prog->acquired, 586 cstate->acquired)) 587 break; 588 } else if (prog->dist == cstate->dist) { 589 if (bit_proper_superset(prog->acquired, 590 cstate->acquired)) 591 break; 592 } 593 } 594 if (prog) { 595 free(cstate); 596 continue; 597 } 598 599 aoc_debug("active %02li %02li %032b %lu\n", 600 cstate->pos.x, cstate->pos.y, 601 cstate->acquired, cstate->dist); 602 603 add_keys(&active, graph, &distmap, cstate, keycnt); 604 605 free(cstate); 606 } 607 608exit: 609 for (HMAP_ITER(&distmap, iter)) { 610 free(iter.link->key._p); 611 dvec_free(iter.link->value._p); 612 } 613 hmap_deinit(&distmap); 614 list_free_items(&active, free, LIST_OFFSET(struct state, link)); 615 616 return mdist; 617} 618 619void 620write_map(struct hmap *map, ssize_t x, ssize_t y, char c) 621{ 622 struct hmap_link *hmap_link; 623 struct vec2i pos; 624 625 vec2i_setv(&pos, x, y); 626 hmap_link = hmap_get(map, (struct hmap_key) {.p = &pos}); 627 assert(hmap_link); 628 hmap_link->value.c = c; 629} 630 631struct state_multi * 632state_multi_alloc(const struct vec2i *pos, size_t dist, uint32_t acquired) 633{ 634 struct state_multi *state; 635 636 state = malloc(sizeof(struct state_multi)); 637 memcpy(state->pos, pos, 4 * sizeof(struct vec2i)); 638 state->dist = dist; 639 state->acquired = acquired; 640 state->link = LIST_LINK_INIT; 641 642 return state; 643} 644 645bool 646state_multi_dist_ordering(const void *p1, const void *p2, void *u) 647{ 648 const struct state_multi *s1 = p1, *s2 = p2; 649 650 return s1->dist < s2->dist; 651} 652 653void 654add_keys_multi(struct list *active, struct hmap *graphs, 655 struct hmap *distmap, struct state_multi *cstate, size_t keycnt) 656{ 657 struct hmap_link *link, **linkp; 658 struct state_multi state, *nstate; 659 struct keypath *keypath; 660 struct dvec *progs; 661 struct node *node; 662 struct prog *prog; 663 struct vec2i *pos; 664 size_t i; 665 666 for (i = 0; i < 4; i++) { 667 link = hmap_get(&graphs[i], (struct hmap_key) {.p = &cstate->pos[i]}); 668 assert(link != NULL); 669 node = link->value._p; 670 671 for (DVEC_ITER(&node->edges, keypath)) { 672 if (cstate->acquired & keypath->keymask) 673 continue; 674 675 if (!bit_subset(keypath->required, cstate->acquired)) 676 continue; 677 678 memcpy(state.pos, cstate->pos, 4 * sizeof(struct vec2i)); 679 vec2i_set(&state.pos[i], &keypath->pos); 680 state.dist = cstate->dist + keypath->dist; 681 state.acquired = cstate->acquired | keypath->keymask; 682 683 linkp = hmap_link_pos(distmap, (struct hmap_key) {.p = state.pos}); 684 if (*linkp) { 685 aoc_debug("old\n"); 686 progs = (*linkp)->value._p; 687 } else { 688 pos = memdup(state.pos, sizeof(struct vec2i) * 4); 689 progs = dvec_alloc(sizeof(struct prog), 1, 690 &stdlib_strict_heap_allocator, NULL); 691 *linkp = hmap_link_alloc(distmap, 692 (struct hmap_key) {.p = pos}, 693 (struct hmap_val) {.p = progs}, NULL); 694 } 695 696 if ((prog = update_progs(progs, state.dist, state.acquired))) { 697 aoc_debug("update prog %li,%li %li,%li %li,%li %li,%li " 698 "%i %i %032b %032b\n", 699 state.pos[0].x, state.pos[0].y, 700 state.pos[1].x, state.pos[1].y, 701 state.pos[2].x, state.pos[2].y, 702 state.pos[3].x, state.pos[3].y, 703 prog->dist, state.dist, 704 prog->acquired, state.acquired); 705 nstate = state_multi_alloc(state.pos, state.dist, state.acquired); 706 list_insert_sorted(active, &nstate->link, 707 false, state_multi_dist_ordering, 708 LIST_OFFSET(struct state_multi, link), 709 NULL); 710 } 711 } 712 } 713} 714 715size_t 716min_dist_all_keys_multi(struct hmap *graphs, const struct vec2i *starts, size_t keycnt) 717{ 718 struct list_link *list_link; 719 struct hmap_link *hmap_link; 720 struct hmap_iter hmap_iter; 721 struct hmap distmap; 722 struct list active; 723 struct state_multi *cstate; 724 struct dvec *progs; 725 struct prog *prog; 726 struct node *node; 727 struct vec2i *pos; 728 size_t mdist; 729 size_t i; 730 731 /* 732 * - dijkstra from starting node 733 * - only move over edges that we collected keys for 734 * - distmap resolves to dvec of progs 735 * - only save new distance if less than all known progs 736 * and/or we have a superset of previous keys 737 * - if we reach key and have, save mindist 738 */ 739 740 list_init(&active); 741 hmap_init(&distmap, 256, vec2i_multi_hmap_hash, vec2i_multi_hmap_keycmp, 742 &stdlib_strict_heap_allocator); 743 744 cstate = state_multi_alloc(starts, 0, 0); 745 list_insert_back(&active, &cstate->link); 746 747 pos = memdup(starts, sizeof(struct vec2i) * 4); 748 progs = dvec_alloc(sizeof(struct prog), 1, 749 &stdlib_strict_heap_allocator, NULL); 750 prog = dvec_add_slot(progs); 751 prog->acquired = 0; 752 prog->dist = 0; 753 hmap_add(&distmap, (struct hmap_key) {.p = pos}, 754 (struct hmap_val) {.p = progs}); 755 756 for (i = 0; i < 4; i++) { 757 for (HMAP_ITER(&graphs[i], hmap_iter)) { 758 node = hmap_iter.link->value._p; 759 sort_edges(&node->edges); 760 } 761 } 762 763 mdist = 0; 764 while (!list_empty(&active)) { 765 list_link = list_front(&active); 766 cstate = LIST_UPCAST(list_link, struct state_multi, link); 767 if (cstate->acquired == (1U << keycnt) - 1) { 768 mdist = cstate->dist; 769 goto exit; 770 } 771 772 list_link_pop(list_link); 773 774 hmap_link = hmap_get(&distmap, (struct hmap_key) {.p = cstate->pos}); 775 assert(hmap_link != NULL); 776 for (DVEC_ITER(hmap_link->value.p, prog)) { 777 if (prog->dist < cstate->dist) { 778 if (bit_superset(prog->acquired, 779 cstate->acquired)) 780 break; 781 } else if (prog->dist == cstate->dist) { 782 if (bit_proper_superset(prog->acquired, 783 cstate->acquired)) 784 break; 785 } 786 } 787 if (prog) { 788 free(cstate); 789 continue; 790 } 791 792 aoc_debug("active %li,%li %li,%li %li,%li %li,%li %032b %li\n", 793 cstate->pos[0].x, cstate->pos[0].y, 794 cstate->pos[1].x, cstate->pos[1].y, 795 cstate->pos[2].x, cstate->pos[2].y, 796 cstate->pos[3].x, cstate->pos[3].y, 797 cstate->acquired, cstate->dist); 798 799 add_keys_multi(&active, graphs, &distmap, cstate, keycnt); 800 801 free(cstate); 802 } 803 804exit: 805 for (HMAP_ITER(&distmap, hmap_iter)) { 806 free(hmap_iter.link->key._p); 807 dvec_free(hmap_iter.link->value._p); 808 } 809 hmap_deinit(&distmap); 810 list_free_items(&active, free, LIST_OFFSET(struct state_multi, link)); 811 812 return mdist; 813} 814 815void 816part1(void) 817{ 818 struct hmap_iter iter; 819 struct hmap map; 820 struct hmap graph; 821 struct vec2i start; 822 struct node *node; 823 size_t keycnt; 824 size_t answer; 825 826 signal(SIGUSR1, exit); 827 828 hmap_init(&map, 256, vec2i_hmap_hash, vec2i_hmap_keycmp, 829 &stdlib_strict_heap_allocator); 830 hmap_init(&graph, 32, vec2i_hmap_hash, vec2i_hmap_keycmp, 831 &stdlib_strict_heap_allocator); 832 833 parse_input(&map, &start, &keycnt); 834 835 gen_graph(&graph, &map, &start, keycnt); 836 837 answer = min_dist_all_keys(&graph, &start, keycnt); 838 aoc.answer = aprintf("%lu", answer); 839 aoc.solution = "5402"; 840 841 for (HMAP_ITER(&graph, iter)) { 842 free(iter.link->key._p); 843 node = iter.link->value._p; 844 dvec_deinit(&node->edges); 845 free(node); 846 } 847 hmap_deinit(&graph); 848 849 for (HMAP_ITER(&map, iter)) 850 free(iter.link->key._p); 851 hmap_deinit(&map); 852} 853 854void 855part2(void) 856{ 857 struct hmap_iter hmap_iter; 858 struct hmap map; 859 struct hmap graphs[4]; 860 struct vec2i center; 861 struct vec2i starts[4]; 862 struct node *node; 863 size_t keycnt; 864 size_t answer; 865 size_t i; 866 867 signal(SIGUSR1, exit); 868 869 hmap_init(&map, 256, vec2i_hmap_hash, vec2i_hmap_keycmp, 870 &stdlib_strict_heap_allocator); 871 872 parse_input(&map, ¢er, &keycnt); 873 874 write_map(&map, center.x - 1, center.y, '#'); 875 write_map(&map, center.x + 1, center.y, '#'); 876 write_map(&map, center.x, center.y - 1, '#'); 877 write_map(&map, center.x, center.y + 1, '#'); 878 write_map(&map, center.x, center.y, '#'); 879 880 for (i = 0; i < 4; i++) { 881 vec2i_add(&starts[i], ¢er, &dirs[i]); 882 vec2i_add(&starts[i], &starts[i], &dirs[(i+1)%4]); 883 hmap_init(&graphs[i], 32, vec2i_hmap_hash, vec2i_hmap_keycmp, 884 &stdlib_strict_heap_allocator); 885 gen_graph(&graphs[i], &map, &starts[i], keycnt); 886 } 887 888 answer = min_dist_all_keys_multi(graphs, starts, keycnt); 889 aoc.answer = aprintf("%lu", answer); 890 aoc.solution = "2138"; 891 892 for (i = 0; i < 4; i++) { 893 for (HMAP_ITER(&graphs[i], hmap_iter)) { 894 free(hmap_iter.link->key._p); 895 node = hmap_iter.link->value._p; 896 dvec_deinit(&node->edges); 897 free(node); 898 } 899 hmap_deinit(&graphs[i]); 900 } 901 902 for (HMAP_ITER(&map, hmap_iter)) 903 free(hmap_iter.link->key._p); 904 hmap_deinit(&map); 905}