Advertisement
Guest User

12.c

a guest
Feb 22nd, 2022
440
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.74 KB | None | 0 0
  1. /* Advent of Code 2021 - Day 12 */
  2. /* Written by Henry Peaurt */
  3.  
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <stdbool.h>
  7.  
  8. #include "strmanip.h"
  9. #include "memmanage.h"
  10.  
  11. /* Types */
  12. typedef struct cave {
  13.     char *name;
  14.     bool is_small;
  15.     int visits;
  16.  
  17.     struct cave **conn_list;
  18.     int conn_cnt;
  19. } cave;
  20.  
  21. typedef struct {
  22.     cave **cave_list;
  23.     int cave_cnt;
  24. } cntxt;
  25.  
  26. /* Function declarations */
  27. void input_caves(cntxt *c);
  28. cave* get_cave(cntxt *c, char *name);
  29. cave* alloc_cave(cntxt *c, char *name);
  30. void connect_caves(cave *a, cave *b);
  31. unsigned int pathfind(cave *curr, int max_vst, _Bool vstd_twice);
  32.  
  33. int
  34. main(void)
  35. {
  36.     cntxt c = {
  37.         .cave_list = NULL,
  38.         .cave_cnt = 0,
  39.     };
  40.  
  41.     input_caves(&c);
  42.  
  43.     cave *start = get_cave(&c, "start");
  44.  
  45.     printf("Part 1: %u\n", pathfind(start, 1, false));
  46.     printf("Part 2: %u\n", pathfind(start, 2, false));
  47.  
  48.     mem_clean();
  49.  
  50.     return 0;
  51. }
  52.  
  53. void
  54. input_caves(cntxt *c)
  55. {
  56.     char *s = NULL;
  57.  
  58.     while ((s = str_input()))
  59.     {
  60.         char *name_a = str_word(0, s);
  61.         char *name_b = str_word(1, s);
  62.  
  63.         cave *a = get_cave(c, name_a);
  64.         if (a == NULL) a = alloc_cave(c, name_a);
  65.  
  66.         cave *b = get_cave(c, name_b);
  67.         if (b == NULL) b = alloc_cave(c, name_b);
  68.  
  69.         connect_caves(a, b);
  70.     }
  71. }
  72.  
  73. cave*
  74. get_cave(cntxt *c, char *name)
  75. {
  76.     for (int i = 0; i < c->cave_cnt; ++i) {
  77.         if (strcmp(name, c->cave_list[i]->name) == 0)
  78.             return c->cave_list[i];
  79.     }
  80.  
  81.     return NULL;
  82. }
  83.  
  84. cave*
  85. alloc_cave(cntxt *c, char *name)
  86. {
  87.     cave *p = mem_alloc(sizeof(cave));
  88.     p->name = name;
  89.     p->is_small = 'a' <= *name && *name <= 'z';
  90.     p->conn_list = NULL;
  91.     p->conn_cnt = 0;
  92.  
  93.     c->cave_list = mem_realloc(c->cave_list, (c->cave_cnt + 1) * sizeof(cave*));
  94.     c->cave_list[c->cave_cnt++] = p;
  95.  
  96.     return p;
  97. }
  98.  
  99. void
  100. connect_caves(cave *a, cave *b)
  101. {
  102.     a->conn_list = mem_realloc(a->conn_list, (a->conn_cnt + 1) * sizeof(cave*));
  103.     b->conn_list = mem_realloc(b->conn_list, (b->conn_cnt + 1) * sizeof(cave*));
  104.  
  105.     a->conn_list[a->conn_cnt++] = b;
  106.     b->conn_list[b->conn_cnt++] = a;
  107. }
  108.  
  109. unsigned int
  110. pathfind(cave *curr, int max_vst, _Bool vstd_twice)
  111. {
  112.     if (strcmp(curr->name, "end") == 0)
  113.         return 1;
  114.  
  115.     if (
  116.         curr->is_small && curr->visits >= 1 &&
  117.         (strcmp(curr->name, "start") == 0 || max_vst == 1 || vstd_twice)
  118.        )
  119.         return 0;
  120.  
  121.     ++curr->visits;
  122.     vstd_twice = vstd_twice || (curr->is_small && max_vst == 2 && curr->visits >= 2);
  123.  
  124.     unsigned int found_paths = 0;
  125.  
  126.     for (int i = 0; i < curr->conn_cnt; ++i) {
  127.         found_paths += pathfind(curr->conn_list[i], max_vst, vstd_twice);
  128.     }
  129.  
  130.     --curr->visits; /* The number of visits doesn't increase past 2, so it subs 1 after the twice-visited cave is
  131.              * processed and backtracks to tell the next paths the cave hasn't been visited twice */
  132.  
  133.     return found_paths;
  134. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement