1
0

solve day 12

This commit is contained in:
Rokas Puzonas 2023-06-09 18:43:52 +03:00
parent 9890e141f2
commit 3d8e66f2dc
6 changed files with 230 additions and 16 deletions

30
aoc.h
View File

@ -14,25 +14,25 @@ typedef struct {
} Solution; } Solution;
// Macro magic for easy of use // Macro magic for easy of use
#define ADD_SOLUTION(_day, _parse, _part1, _part2) \ #define ADD_SOLUTION(_day, _parse, _part1, _part2) \
static parse_cb ptr_##_parse; \ static parse_cb ptr_##_parse; \
static solution_cb ptr_##_part1; \ static solution_cb ptr_##_part1; \
static Solution ptr_##_part2 \ static Solution ptr_##_part2 \
__attribute((used, section("g_solutions"))) = { \ __attribute((used, section("g_solutions"))) = { \
.parse = _parse, \ .parse = _parse, \
.part1 = _part1, \ .part1 = _part1, \
.part2 = _part2, \ .part2 = _part2, \
.day = _day \ .day = _day \
} }
#define SOLUTIONS ({ \ #define SOLUTIONS ({ \
extern Solution __start_##g_solutions; \ extern Solution __start_##g_solutions; \
&__start_##g_solutions; \ &__start_##g_solutions; \
}) })
#define SOLUTIONS_END ({ \ #define SOLUTIONS_END ({ \
extern Solution __stop_##g_solutions; \ extern Solution __stop_##g_solutions; \
&__stop_##g_solutions; \ &__stop_##g_solutions; \
}) })
#define SOLUTIONS_COUNT SOLUTIONS_END - SOLUTIONS #define SOLUTIONS_COUNT SOLUTIONS_END - SOLUTIONS

190
day12.c Normal file
View File

@ -0,0 +1,190 @@
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);

1
main.c
View File

@ -19,6 +19,7 @@
#include "day9.c" #include "day9.c"
#include "day10.c" #include "day10.c"
#include "day11.c" #include "day11.c"
#include "day12.c"
Solution *find_solution(int day) Solution *find_solution(int day)
{ {

10
point.h
View File

@ -1,8 +1,18 @@
#ifndef POINT_H_ #ifndef POINT_H_
#define POINT_H_ #define POINT_H_
#include "types.h"
typedef struct { typedef struct {
int x, y; int x, y;
} Point; } Point;
typedef struct {
u8 x, y;
} Point_u8;
typedef struct {
u32 x, y;
} Point_u32;
#endif //POINT_H_ #endif //POINT_H_

14
types.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef TYPES_H_
#define TYPES_H_
#include <stdint.h>
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_

1
vec.h
View File

@ -2,7 +2,6 @@
#define VEC_H_ #define VEC_H_
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
typedef struct { typedef struct {
int count; int count;