From 25d56534c9dcb4308670f23526e1d2a057898423 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Thu, 8 Dec 2022 21:55:45 +0200 Subject: [PATCH] solve day 7 --- Makefile | 2 +- day7.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 1 + vec.h | 7 ++- 4 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 day7.c diff --git a/Makefile b/Makefile index 0488875..ffa878d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -main: main.c day*.c +main: main.c day*.c vec.h aoc.h gcc -o main main.c -lcurl run: main diff --git a/day7.c b/day7.c new file mode 100644 index 0000000..cbf4e9b --- /dev/null +++ b/day7.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include + +#include "aoc.h" +#include "vec.h" + +#define CD_CMD "$ cd" +#define LS_CMD "$ ls" + +#define TOTAL_FS_SIZE 70000000 +#define UPDATE_SIZE 30000000 + +struct TreeNode { + char *name; + struct TreeNode *parent; + struct TreeNode **children; + size_t children_count; + size_t size; +}; + +static struct TreeNode *append_node(struct TreeNode *parent, char *child_name, size_t size) +{ + struct TreeNode *new_child = calloc(1, sizeof(struct TreeNode)); + new_child->parent = parent; + new_child->name = child_name; + new_child->size = size; + + parent->children = realloc(parent->children, sizeof(struct TreeNode*)*(parent->children_count+1)); + parent->children[parent->children_count] = new_child; + parent->children_count++; + return new_child; +} + +static struct TreeNode *get_or_append_child(struct TreeNode *parent, char *child_name) +{ + for (int i = 0; i < parent->children_count; i++) { + struct TreeNode *child = parent->children[i]; + if (strcmp(child->name, child_name) == 0) { + return child; + } + } + + return append_node(parent, child_name, -1); +} + +static int find_char(char *haystack, char needle) { + int n = strlen(haystack); + for (int i = 0; i < n; i++) { + if (haystack[i] == needle) { + return i; + } + } + return -1; +} + +static void populate_directory_sizes(struct TreeNode *start) +{ + struct TreeNode *current = start; + while (current != start->parent) { + bool is_explored = true; + for (int i = 0; i < current->children_count; i++) { + struct TreeNode *child = current->children[i]; + if (child->size == -1) { + current = child; + is_explored = false; + break; + } + } + + if (is_explored) { + current->size = 0; + for (int i = 0; i < current->children_count; i++) { + current->size += current->children[i]->size; + } + + current = current->parent; + } + } +} + +static void *day7_parse(char **lines, int line_count) +{ + struct TreeNode *root = calloc(1, sizeof(struct TreeNode)); + root->name = "/"; + + struct TreeNode *current = root; + for (int i = 0; i < line_count; i++) { + char *line = lines[i]; + if (strncmp(line, CD_CMD, sizeof(CD_CMD)-1) == 0) { + char *dir_name = line + sizeof(CD_CMD); + if (strncmp(dir_name, "/", 1) == 0) { + current = root; + } else if (strncmp(dir_name, "..", 2) == 0) { + current = current->parent; + } else { + current = get_or_append_child(current, dir_name); + } + } else if (strncmp(line, LS_CMD, sizeof(LS_CMD)) == 0) { + continue; + } else { + if (strncmp(line, "dir", 3) == 0) { + char *dir_name = line + 4; + get_or_append_child(current, dir_name); + } else { + int sep = find_char(line, ' '); + char *child_name = line + sep + 1; + line[sep] = '\0'; + int size = strtol(line, NULL, 10); + line[sep] = ' '; + append_node(current, child_name, size); + } + } + } + + return root; +} + +static void day7_part1(void *p) +{ + struct TreeNode *root = p; + + populate_directory_sizes(root); + + int result = 0; + Vec *stack = vec_malloc(10); + vec_push(stack, root); + while (stack->count > 0) { + struct TreeNode *node = vec_pop(stack); + if (node->size <= 100000 && node->children_count > 0) { + result += node->size; + } + for (int i = 0; i < node->children_count; i++) { + vec_push(stack, node->children[i]); + } + } + + printf("%d\n", result); +} + +static void day7_part2(void *p) +{ + struct TreeNode *root = p; + + populate_directory_sizes(root); + + int needed_space = UPDATE_SIZE - (TOTAL_FS_SIZE - root->size); + + int result = INT_MAX; + Vec *stack = vec_malloc(10); + vec_push(stack, root); + while (stack->count > 0) { + struct TreeNode *node = vec_pop(stack); + if (node->size >= needed_space && node->children_count > 0) { + result = MIN(result, node->size); + } + for (int i = 0; i < node->children_count; i++) { + vec_push(stack, node->children[i]); + } + } + + printf("%d\n", result); +} + +ADD_SOLUTION(7, day7_parse, day7_part1, day7_part2); diff --git a/main.c b/main.c index 5d9c26b..8ba7063 100644 --- a/main.c +++ b/main.c @@ -14,6 +14,7 @@ #include "day4.c" #include "day5.c" #include "day6.c" +#include "day7.c" Solution *find_solution(int day) { diff --git a/vec.h b/vec.h index 998e5b9..a42444c 100644 --- a/vec.h +++ b/vec.h @@ -23,17 +23,18 @@ static inline void vec_push(Vec *vec, void* value) { if (vec->count >= vec->capacity) { vec->capacity = (vec->capacity + 1) * 2; - vec->data = (void**)realloc(vec->data, vec->capacity); + vec->data = (void**)realloc(vec->data, vec->capacity * sizeof(void*)); } vec->data[vec->count++] = value; } -inline void vec_pop(Vec* vec) +static inline void *vec_pop(Vec* vec) { vec->count--; + return vec->data[vec->count]; } -inline void vec_free(Vec *v) +static inline void vec_free(Vec *v) { free(v->data); free(v);