BlueRains

AdventOfCode C 2024 day 6

Dec 6th, 2024
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.68 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #define SIZE 1000
  4. #define POINTS 16900
  5. #define LENGTH 130
  6.  
  7. struct point_t {
  8.     int x;
  9.     int y;
  10.     int added_blockage;
  11. };
  12. typedef struct point_t Point;
  13. struct encountered_t {
  14.     int x;
  15.     int y;
  16.     enum Direction dir; // Is either 0, 1, 2, or 3. 3 means both directions
  17. };
  18. typedef struct encountered_t Encounter;
  19.  
  20. enum Direction {
  21.     NONE,
  22.     UP,   // 1
  23.     LEFT, // 2
  24.     UNUSED1,
  25.     DOWN, // 4
  26.     UNUSED2,
  27.     UNUSED3,
  28.     UNUSED4,
  29.     RIGHT // 8
  30. };
  31.  
  32. enum Direction direction(int dx, int dy) {
  33.     if (dx == 0 && dy == 1) {
  34.         // South
  35.         return 4;
  36.     }
  37.     else if (dx == 0) {
  38.         return 1;
  39.     }
  40.     else if (dx == 1) {
  41.         // Right
  42.         return 8;
  43.     }
  44.     else {
  45.         return 2;
  46.     }
  47. }
  48.  
  49. bool compPoint(Point* point1, Point* point2) {
  50.     return point1->x == point2->x && point1->y == point2->y;
  51. }
  52. bool compEncounter(Point point1, Encounter* point2) {
  53.     return point1.x == point2->x && point1.y == point2->y;
  54. }
  55.  
  56. bool in_bounds(int x, int y, int* bounds) {
  57.     return !(x < 0 || y < 0 || x >= bounds[0] || y >= bounds[1]);
  58. }
  59.  
  60. bool is_occupied(Point* point, Point* garbage, int size) {
  61.     for (size_t i = 0; i < size; i++) {
  62.         if (compPoint(point, garbage + i)) {
  63.             return true;
  64.         }
  65.     }
  66.     return false;
  67. }
  68.  
  69. void print_map(Encounter* path, Point* garbage, int* bounds, int encounter_size, int garbage_size) {
  70.     // Transform into a list of lists.
  71.     // Then print
  72.     // Set the default
  73.     char items[LENGTH + 1][LENGTH];
  74.     for (size_t i = 0; i < LENGTH; i++) {
  75.         for (size_t j = 0; j < LENGTH; j++) {
  76.             items[i][j] = '.';
  77.         }
  78.         items[LENGTH][i] = '\0';
  79.     }
  80.     // Set the path
  81.     for (size_t i = 0; i < encounter_size; i++) {
  82.         Encounter encounter = *(path + i);
  83.         char val = 'E'; // This shouldn't end up
  84.         // if more than 1 flag is set, it's going in multiple directions.
  85.         // Print a pretty +
  86.         int dir = encounter.dir;
  87.         if (dir & 5 && dir & 10) {
  88.             val = '+';
  89.         }
  90.         else if (dir & 1 || dir & 4) {
  91.             val = '|';
  92.         }
  93.         else if (dir & 2 || dir & 8) {
  94.             val = '-';
  95.         }
  96.         items[encounter.y][encounter.x] = val;
  97.     }
  98.     // Set the blockages
  99.     for (size_t i = 0; i < garbage_size; i++) {
  100.         Point point = *(garbage + i);
  101.         if (point.added_blockage == 1) {
  102.             items[point.y][point.x] = 'O';
  103.         }
  104.         else {
  105.             items[point.y][point.x] = '#';
  106.         }
  107.     }
  108.     for (size_t i = 0; i < LENGTH; i++) {
  109.         for (size_t j = 0; j < LENGTH; j++) {
  110.             printf("%c", items[i][j]);
  111.             /* code */
  112.         }
  113.         printf("\n");
  114.     }
  115.  
  116. }
  117.  
  118.  
  119.  
  120. int parse(FILE* ptr, Point* places, Point* guard, int bounds[2]) {
  121.     int index = 0;
  122.     int y = 0;
  123.     int x = 0;
  124.     int c;
  125.     int val;
  126.     while ((c = fgetc(ptr)) != EOF) {
  127.         if (c == '\n') {
  128.             y++;
  129.             x = -1;
  130.         }
  131.         else if (c == '#') {
  132.             Point point = { x, y,0 };
  133.             *(places + index) = point;
  134.             index++;
  135.         }
  136.         else if (c == '^') {
  137.             Point point = { x, y,0 };
  138.             *guard = point;
  139.         }
  140.         x++;
  141.     }
  142.     bounds[0] = x;
  143.     bounds[1] = y;
  144.     return index;
  145. }
  146.  
  147.  
  148. int part_one(Point* guard, Point places[SIZE], int* bounds, int size) {
  149.     Point locations[POINTS];
  150.     int index = 0;
  151.     int dx = 0;
  152.     int dy = -1;
  153.     int x = guard->x;
  154.     int y = guard->y;
  155.     // Rotating clockwise means dx, dy = -dy, dx
  156.     while (in_bounds(x, y, bounds)) {
  157.         Point new_loc = { x + dx, y + dy,0 };
  158.         if (is_occupied(&new_loc, places, size)) {
  159.             int temp = dx;
  160.             dx = -dy;
  161.             dy = temp;
  162.         }
  163.         else {
  164.             x += dx;
  165.             y += dy;
  166.             bool found = false;
  167.             for (size_t i = 0; i < index; i++) {
  168.                 if (compPoint(&new_loc, locations + i)) {
  169.                     found = true;
  170.                     break;
  171.                 }
  172.             }
  173.             if (!found) {
  174.                 locations[index] = new_loc;
  175.                 index++;
  176.             }
  177.         }
  178.     }
  179.     return index;
  180. }
  181.  
  182.  
  183. int detect_previous(Encounter* locations, int index, Point point, enum Direction dir) {
  184.     //printf("Need to look through %d locations for place %d,%d\n", index, point.x, point.y);
  185.     for (size_t i = 0; i < index; i++) {
  186.         if (compEncounter(point, locations + i)) {
  187.             int val = locations[i].dir;
  188.             if (val & dir) {
  189.                 // We already went in this direction
  190.                 return 3;
  191.             }
  192.             locations[i].dir |= dir; // If turning, always ends up a crossing
  193.             return 1;
  194.         }
  195.     }
  196.     return 0;
  197. }
  198.  
  199. bool detect_loop(Point* guard, Point places[SIZE], int* bounds, int size) {
  200.     // We will record where it's been.
  201.     // Then for all locations it's been, we try and add to places.
  202.     // Then we do cycle detection, aka if it goes over a place twice in the same direction
  203.     Encounter locations[POINTS];
  204.     int index = 0;
  205.     int dx = 0;
  206.     int dy = -1;
  207.     int x = guard->x;
  208.     int y = guard->y;
  209.     // Rotating clockwise means dx, dy = -dy, dx
  210.     while (in_bounds(x, y, bounds)) {
  211.         Point new_loc = { x + dx, y + dy ,0 };
  212.         if (is_occupied(&new_loc, places, size)) {
  213.             int temp = dx;
  214.             dx = -dy;
  215.             dy = temp;
  216.             Point old_loc = { x,y,0 };
  217.             if (detect_previous(locations, index, old_loc, direction(dx, dy)) == 3) {
  218.                 //print_map(locations, places, bounds, index, size);
  219.                 //printf("\n");
  220.                 return true;
  221.             }
  222.         }
  223.         else {
  224.             x += dx;
  225.             y += dy;
  226.             int found = detect_previous(locations, index, new_loc, direction(dx, dy));
  227.             if (!found) {
  228.                 // Need to make a new copy
  229.                 Encounter point = { x , y , direction(dx,dy) };
  230.                 locations[index] = point;
  231.                 index++;
  232.             }
  233.         }
  234.     }
  235.     return false;
  236. }
  237. int get_path(Encounter* locations, Point* guard, Point places[SIZE], int* bounds, int size) {
  238.     // We will record where it's been.
  239.     // Then for all locations it's been, we try and add to places.
  240.     // Then we do cycle detection, aka if it goes over a place twice in the same direction
  241.     int index = 0;
  242.     int dx = 0;
  243.     int dy = -1;
  244.     int x = guard->x;
  245.     int y = guard->y;
  246.     // Rotating clockwise means dx, dy = -dy, dx
  247.     while (in_bounds(x, y, bounds)) {
  248.         Point new_loc = { x + dx, y + dy,0 };
  249.         if (is_occupied(&new_loc, places, size)) {
  250.             int temp = dx;
  251.             dx = -dy;
  252.             dy = temp;
  253.             Point old_loc = { x,y,0 };
  254.             detect_previous(locations, index, old_loc, direction(dx, dy));
  255.         }
  256.         else {
  257.             x += dx;
  258.             y += dy;
  259.             bool found = detect_previous(locations, index, new_loc, direction(dx, dy));
  260.             if (!found) {
  261.                 // Need to make a new copy
  262.                 Encounter point = { x , y , direction(dx,dy) };
  263.                 locations[index] = point;
  264.                 index++;
  265.             }
  266.         }
  267.     }
  268.     print_map(locations, places, bounds, index, size);
  269.     return index;
  270. }
  271.  
  272. int part_two(Point* guard, Point places[SIZE], int* bounds, int size) {
  273.     // We will record where it's been.
  274.     // Then for all locations it's been, we try and add to places.
  275.     // Then we do cycle detection, aka if it goes over a place twice in the same direction
  276.     Encounter locations[POINTS];
  277.     int index = get_path(locations, guard, places, bounds, size);
  278.     printf("Trying %d blockages\n", index);
  279.     int total = 0;
  280.     for (size_t i = 0; i < index; i++) {
  281.         Encounter encounter = locations[i];
  282.         Point point = { encounter.x,encounter.y, 1 };
  283.         if (compPoint(guard, &point)) {
  284.             continue;
  285.         }
  286.         places[size] = point;
  287.         if (detect_loop(guard, places, bounds, size + 1)) {
  288.             total++;
  289.         }
  290.     }
  291.     return total;
  292. }
  293.  
  294. int main() {
  295.     Point garbage[SIZE];
  296.     Point guard;
  297.     int bounds[2] = { 0 };
  298.  
  299.     FILE* file = fopen("2024-6.txt", "r");
  300.     int size = parse(file, garbage, &guard, bounds);
  301.     printf("Parsed\n");
  302.     fclose(file);
  303.     printf("Location: %d, %d\n", guard.x, guard.y);
  304.  
  305.     printf("Part one: %d\n", part_one(&guard, garbage, bounds, size));
  306.     printf("Location: %d, %d\n", guard.x, guard.y);
  307.     printf("Part two: %d\n", part_two(&guard, garbage, bounds, size));
  308. }
  309.  
Advertisement
Add Comment
Please, Sign In to add comment