diff --git a/aoc.h b/aoc.h index 8829c6c..4842da2 100644 --- a/aoc.h +++ b/aoc.h @@ -14,25 +14,25 @@ typedef struct { } Solution; // Macro magic for easy of use -#define ADD_SOLUTION(_day, _parse, _part1, _part2) \ - static parse_cb ptr_##_parse; \ - static solution_cb ptr_##_part1; \ - static Solution ptr_##_part2 \ - __attribute((used, section("g_solutions"))) = { \ - .parse = _parse, \ - .part1 = _part1, \ - .part2 = _part2, \ - .day = _day \ +#define ADD_SOLUTION(_day, _parse, _part1, _part2) \ + static parse_cb ptr_##_parse; \ + static solution_cb ptr_##_part1; \ + static Solution ptr_##_part2 \ + __attribute((used, section("g_solutions"))) = { \ + .parse = _parse, \ + .part1 = _part1, \ + .part2 = _part2, \ + .day = _day \ } -#define SOLUTIONS ({ \ - extern Solution __start_##g_solutions; \ - &__start_##g_solutions; \ +#define SOLUTIONS ({ \ + extern Solution __start_##g_solutions; \ + &__start_##g_solutions; \ }) -#define SOLUTIONS_END ({ \ - extern Solution __stop_##g_solutions; \ - &__stop_##g_solutions; \ +#define SOLUTIONS_END ({ \ + extern Solution __stop_##g_solutions; \ + &__stop_##g_solutions; \ }) #define SOLUTIONS_COUNT SOLUTIONS_END - SOLUTIONS diff --git a/day12.c b/day12.c new file mode 100644 index 0000000..dcf595d --- /dev/null +++ b/day12.c @@ -0,0 +1,190 @@ +#include +#include +#include +#include +#include + +#include "types.h" +#include "point.h" +#include "aoc.h" + +typedef struct { + u8 *map; + u32 width; + u32 height; + Point_u32 start; + Point_u32 end; +} day12_map; + +static void print_day12_map(day12_map *map) +{ + for (size_t y = 0; y < map->height; y++) { + for (size_t x = 0; x < map->width; x++) { + if (map->start.x == x && map->start.y == y) { + printf("S"); + } else if (map->end.x == x && map->end.y == y) { + printf("E"); + } else { + size_t idx = y * map->width + x; + printf("%c", 'a' + map->map[idx]); + } + } + printf("\n"); + } +} + +static void *day12_parse(char **lines, int line_count) +{ + day12_map *map = malloc(sizeof(day12_map)); + map->width = strlen(lines[0]); + map->height = line_count; + map->map = malloc(sizeof(u8) * map->height * map->width); + + for (int y = 0; y < line_count; y++) { + for (int x = 0; x < map->width; x++) { + size_t idx = y * map->width + x; + if (lines[y][x] == 'S') { + map->start.x = x; + map->start.y = y; + map->map[idx] = 0; + } else if (lines[y][x] == 'E') { + map->end.x = x; + map->end.y = y; + map->map[idx] = 'z' - 'a'; + } else { + map->map[idx] = lines[y][x] - 'a'; + } + } + } + + return map; +} + +static bool day12_is_in_bounds(day12_map *map, i32 x, i32 y) +{ + return x >= 0 && y >= 0 && x < map->width && y < map->height; +} + +static int day12_find_by_coord(u32 *stack_x, u32 *stack_y, size_t stack_size, u32 x, u32 y) +{ + for (int i = 0; i < stack_size; i++) { + if (stack_x[i] == x && stack_y[i] == y) { + return i; + } + } + return -1; +} + +static void day12_remove_at(u32 *array, u32 size, size_t at) +{ + for (int i = at; i < size-1; i++) { + array[i] = array[i+1]; + } +} + +static void day12_insert_at(u32 *array, u32 size, u32 capacity, size_t at, u32 value) +{ + assert(size+1 <= capacity); + for (int i = size; i > at; i--) { + array[i] = array[i-1]; + } + array[at] = value; +} + +static size_t day12_find_sorted_idx(day12_map *map, u32 *cost_map, u32 *stack_x, u32 *stack_y, size_t stack_size, u32 cost) +{ + for (int i = 0; i < ((int)stack_size)-1; i++) { + u32 x = stack_x[i]; + u32 y = stack_y[i]; + if (cost_map[y * map->width + x] <= cost) { + return i; + } + } + return stack_size; +} + +static u32 *day12_djikstra(day12_map *map) +{ + u32 *cost_map = malloc(map->height*map->width * sizeof(u32)); + for (size_t y = 0; y < map->height; y++) { + for (size_t x = 0; x < map->width; x++) { + cost_map[y * map->width + x] = -1; + } + } + cost_map[map->end.y * map->width + map->end.x] = 0; + + size_t stack_capacity = map->width*map->height; + u32 stack_x[stack_capacity], stack_y[stack_capacity]; + size_t stack_size = 1; + stack_x[0] = map->end.x; + stack_y[0] = map->end.y; + + while (stack_size > 0) + { + u32 x = stack_x[stack_size-1]; + u32 y = stack_y[stack_size-1]; + u32 cost = cost_map[y * map->width + x]; + stack_size--; + + if (x == map->start.x && y == map->start.y) break; + + u8 height = map->map[y * map->width + x]; + + i8 ox[] = { 0, 0, 1, -1 }; + i8 oy[] = { 1, -1, 0, 0 }; + for (int i = 0; i < 4; i++) { + i32 new_x = x + ox[i]; + i32 new_y = y + oy[i]; + if (!day12_is_in_bounds(map, new_x, new_y)) continue; + u8 new_height = map->map[new_y * map->width + new_x]; + if (height - new_height > 1) continue; + + if (cost_map[new_y * map->width + new_x] > cost + 1) { + if (cost_map[new_y * map->width + new_x] == cost + 1) continue; + + int stack_idx = day12_find_by_coord(stack_x, stack_y, stack_size, new_x, new_y); + if (stack_idx != -1) { + day12_remove_at(stack_x, stack_size, stack_idx); + day12_remove_at(stack_y, stack_size, stack_idx); + stack_size--; + } + cost_map[new_y * map->width + new_x] = cost + 1; + size_t sorted_idx = day12_find_sorted_idx(map, cost_map, stack_x, stack_y, stack_size, cost + 1); + day12_insert_at(stack_x, stack_size, stack_capacity, sorted_idx, new_x); + day12_insert_at(stack_y, stack_size, stack_capacity, sorted_idx, new_y); + stack_size++; + } + } + } + + return cost_map; +} + +static void day12_part1(void *p) +{ + day12_map *map = (day12_map*)p; + + u32 *cost_map = day12_djikstra(map); + printf("Cost: %d\n", cost_map[map->start.y * map->width + map->start.x]); +} + +static void day12_part2(void *p) +{ + day12_map *map = (day12_map*)p; + + u32 *cost_map = day12_djikstra(map); + u32 lowest_cost = -1; + for (u32 y = 0; y < map->height; y++) { + for (u32 x = 0; x < map->height; x++) { + u32 idx = y * map->width + x; + u32 cost = cost_map[idx]; + if (lowest_cost > cost && map->map[idx] == 0) { + lowest_cost = cost; + } + } + } + + printf("Cost: %d\n", lowest_cost); +} + +ADD_SOLUTION(12, day12_parse, day12_part1, day12_part2); diff --git a/main.c b/main.c index 97e6a30..5f38209 100644 --- a/main.c +++ b/main.c @@ -19,6 +19,7 @@ #include "day9.c" #include "day10.c" #include "day11.c" +#include "day12.c" Solution *find_solution(int day) { diff --git a/point.h b/point.h index 7680882..4623b9f 100644 --- a/point.h +++ b/point.h @@ -1,8 +1,18 @@ #ifndef POINT_H_ #define POINT_H_ +#include "types.h" + typedef struct { int x, y; } Point; +typedef struct { + u8 x, y; +} Point_u8; + +typedef struct { + u32 x, y; +} Point_u32; + #endif //POINT_H_ diff --git a/types.h b/types.h new file mode 100644 index 0000000..e1eb896 --- /dev/null +++ b/types.h @@ -0,0 +1,14 @@ +#ifndef TYPES_H_ +#define TYPES_H_ + +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; + +#endif //TYPES_H_ diff --git a/vec.h b/vec.h index a42444c..dc8ee70 100644 --- a/vec.h +++ b/vec.h @@ -2,7 +2,6 @@ #define VEC_H_ #include -#include typedef struct { int count;