Advertisement
Guest User

12-old.c

a guest
Feb 24th, 2022
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.82 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdbool.h>
  5. #include <ctype.h>
  6.  
  7. // Types
  8. typedef struct cave {
  9.     char *name;
  10.     bool is_small;
  11.     struct cave **connections;
  12.     int connection_amount;
  13. } cave;
  14.  
  15. // Function declarations
  16. int getCaves(cave ***caves);
  17. int getCaveName(char **name);
  18. cave *createCaveStruct(cave ***caves, int *cave_amount, char *name);
  19. cave *checkExistingCaves(cave **caves, int cave_amount, char *name);
  20. int findOncePaths(cave *current, cave** visited_address, int visited_amount);
  21. int findTwicePaths(cave *current, cave** visited_address, int visited_amount,
  22.            bool visited_twice);
  23. bool checkIfVisited(cave *current, cave **visited, int visited_amount);
  24.  
  25. int main(void)
  26. {
  27.     cave **caves = NULL;
  28.     cave *start;
  29.     int cave_amount;
  30.  
  31.     cave_amount = getCaves(&caves);
  32.     start = checkExistingCaves(caves, cave_amount, "start");
  33.     printf("Part 1: %d\n", findOncePaths(start, NULL, 0));
  34.     printf("Part 2: %d\n", findTwicePaths(start, NULL, 0, false));
  35.  
  36.     for (int i = 0; i < cave_amount; ++i) {
  37.         free(caves[i]->name);
  38.         free(caves[i]->connections);
  39.         free(caves[i]);
  40.     }
  41.     free(caves);
  42.     return 0;
  43. }
  44.  
  45. int getCaves(cave ***caves)
  46. {
  47.     cave *cave_a, *cave_b;
  48.     char *name_a, *name_b;
  49.     name_a = name_b = NULL;
  50.     int cave_amount = 0;
  51.  
  52.     while (getCaveName(&name_a)) {
  53.         getCaveName(&name_b);
  54.  
  55.         cave_a = createCaveStruct(caves, &cave_amount, name_a);
  56.         cave_b = createCaveStruct(caves, &cave_amount, name_b);
  57.  
  58.         cave_a->connections = realloc(cave_a->connections, sizeof(cave*)
  59.                          * (cave_a->connection_amount + 1));
  60.         cave_b->connections = realloc(cave_b->connections, sizeof(cave*)
  61.                          * (cave_b->connection_amount + 1));
  62.  
  63.         cave_a->connections[(cave_a->connection_amount)++] = cave_b;
  64.         cave_b->connections[(cave_b->connection_amount)++] = cave_a;
  65.     }
  66.     free(name_a);
  67.     free(name_b);
  68.     return cave_amount;
  69. }
  70.  
  71. int getCaveName(char **name)
  72. {
  73.     int i;
  74.     char c;
  75.  
  76.     for (i = 0; (c = getchar()) != '-' && c != '\n' && c != EOF; ++i) {
  77.         *name = realloc(*name, sizeof(char) * (i + 2));
  78.         (*name)[i] = c;
  79.     }
  80.     (*name)[i] = '\0';
  81.     return i;
  82. }
  83.  
  84. cave *createCaveStruct(cave ***caves, int *cave_amount, char *name)
  85. {
  86.     cave *address = checkExistingCaves(*caves, *cave_amount, name);
  87.  
  88.     if (!address) {
  89.         *caves = realloc(*caves, sizeof(cave*) * (*cave_amount + 1));
  90.         (*caves)[*cave_amount] = malloc(sizeof(cave));
  91.         address = (*caves)[(*cave_amount)++];
  92.         // Initialization of the struct
  93.         address->name = malloc(sizeof(char) * (strlen(name) + 1));
  94.         strcpy(address->name, name);
  95.         address->is_small = islower(name[0]);
  96.         address->connections = NULL;
  97.         address->connection_amount = 0;
  98.     }
  99.     return address;
  100. }
  101.  
  102. cave *checkExistingCaves(cave **caves, int cave_amount, char *name)
  103. {
  104.     for (int i = 0; i < cave_amount; ++i) {
  105.         if (!(strcmp(caves[i]->name, name)))
  106.             return caves[i];
  107.     }
  108.     return NULL;
  109. }
  110.  
  111. int findOncePaths(cave *current, cave** visited_address, int visited_amount)
  112. {
  113.     int found_paths = 0;
  114.     cave** visited = malloc(sizeof(cave *) * visited_amount);
  115.     memcpy(visited, visited_address, sizeof(cave *) * visited_amount);
  116.  
  117.     if (!(strcmp(current->name, "end"))) {
  118.         free(visited);
  119.         return 1;
  120.     }
  121.     if (current->is_small) {
  122.         if (!(checkIfVisited(current, visited, visited_amount))) {
  123.             visited = realloc(visited, sizeof(cave*) *
  124.                       (visited_amount + 1));
  125.             visited[visited_amount++] = current;
  126.         } else {
  127.             free(visited);
  128.             return 0;
  129.         }
  130.     }
  131.  
  132.     for (int i = 0; i < current->connection_amount; ++i) {
  133.         found_paths += findOncePaths(current->connections[i], visited,
  134.                          visited_amount);
  135.     }
  136.     free(visited);
  137.     return found_paths;
  138. }
  139.  
  140. int findTwicePaths(cave *current, cave** visited_address, int visited_amount,
  141.            bool visited_twice)
  142. {
  143.     int found_paths = 0;
  144.     cave** visited = malloc(sizeof(cave *) * visited_amount);
  145.     memcpy(visited, visited_address, sizeof(cave *) * visited_amount);
  146.  
  147.     if (!(strcmp(current->name, "end"))) {
  148.         free(visited);
  149.         return 1;
  150.     }
  151.     if (current->is_small) {
  152.         if (checkIfVisited(current, visited, visited_amount)) {
  153.             if (visited_twice ||
  154.                 (!(strcmp(current->name, "start")) &&
  155.                 visited_address)) {
  156.                 free(visited);
  157.                 return 0;
  158.             } else if (strcmp(current->name, "start")) {
  159.                 visited_twice = checkIfVisited(current, visited,
  160.                                    visited_amount);
  161.             }
  162.         } else {
  163.             visited = realloc(visited, sizeof(cave*) *
  164.                       (visited_amount + 1));
  165.             visited[visited_amount++] = current;
  166.         }
  167.     }
  168.  
  169.     for (int i = 0; i < current->connection_amount; ++i) {
  170.         found_paths += findTwicePaths(current->connections[i], visited,
  171.                           visited_amount, visited_twice);
  172.     }
  173.     free(visited);
  174.     return found_paths;
  175. }
  176.  
  177. bool checkIfVisited(cave *current, cave **visited, int visited_amount)
  178. {
  179.     for (int i = 0; i < visited_amount; ++i) {
  180.         if (current == visited[i])
  181.             return true;
  182.     }
  183.     return false;
  184. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement