diff --git a/day_7/parser.y b/day_7/parser.y index aa52c0a..a9b0f02 100644 --- a/day_7/parser.y +++ b/day_7/parser.y @@ -35,6 +35,10 @@ #include "parser.h" #include "lexer.h" + const unsigned long upper_bound = 100000; + const unsigned long fs_size = 70000000; + const unsigned long needed_space = 30000000; + struct dirstack* dirstack_push(struct dirstack *stack, struct dirnode *item) { struct dirstack *head = calloc(1, sizeof(struct dirstack)); if (!head) { @@ -111,12 +115,7 @@ command state->cur = state->stackptr->item; } | PROMPT CHDIR SPACE PATHSPEC NEWLINE { - // TODO: CLEANUP - if (!state) { - fprintf(stderr, "\033[91m[error] the fuck\033[0m\n"); - } else { - printf("searching in %s now for path %s\n", state->cur->name, $4); - } + // printf("searching in %s now for path %s\n", state->cur->name, $4); // move into the new directory (creating it if it doesn't exist is not necessary, LIST does that) struct dirnode *cur_node = state->cur; @@ -128,17 +127,18 @@ command if (strcmp($4, cur_node->directories[i]->name) == 0) { found = i; c = 0; - printf("equal: [%s] and [%s]\n", $4, cur_node->directories[i]->name); + // printf("equal: [%s] and [%s]\n", $4, cur_node->directories[i]->name); } else { - printf("not equal: [%s] and [%s]\n", $4, cur_node->directories[i]->name); + // printf("not equal: [%s] and [%s]\n", $4, cur_node->directories[i]->name); } } + if (c == -1) { fprintf(stderr, "\033[91m[error] got no such directory lol\033[0m\n"); // TODO: error, directory not found - } else { - printf("found it\n"); - } + } // else { + // printf("found it\n"); + // } struct dirnode *next = cur_node->directories[found]; @@ -165,7 +165,6 @@ listing item->name = $3; add_directory(state->cur, item); - printf("know about %zu dirs now!\n", state->cur->num_dirs); } | SIZE SPACE PATHSPEC { struct filenode *item = calloc(1, sizeof(struct filenode)); @@ -183,13 +182,59 @@ listing %% +unsigned long sum_and_count(struct dirnode *node) { + unsigned long total_sum = 0; + + for (size_t i = 0; i < node->num_files; i++) { + node->size += node->files[i]->size; + } + + for (size_t j = 0; j < node->num_dirs; j++) { + // recursively call function on subdirectory to compute its size + total_sum += sum_and_count(node->directories[j]); + node->size += node->directories[j]->size; + } + + if (node->size <= upper_bound) { + total_sum += node->size; + } + + return total_sum; +} + + +struct dirnode* find_deletion_candidate(struct dirnode *cur, unsigned long needed_space) { + if (cur->size < needed_space) { + // abort recursion if directory sizes get too small + return NULL; + } + + struct dirnode *best_candidate = cur; + unsigned long best_diff = best_candidate->size - needed_space; + + for (size_t i = 0; i < cur->num_dirs; i++) { + struct dirnode *candidate = find_deletion_candidate(cur->directories[i], needed_space); + // only proceed if there's an actual candidate + if (candidate) { + unsigned long delta = candidate->size - needed_space; + if (delta < best_diff) { + best_candidate = candidate; + best_diff = delta; + } + } + } + + return best_candidate; +} + + int main(void) { struct dirnode *root = calloc(1, sizeof(struct dirnode)); if (!root) { fprintf(stderr, "\033[91m[error] Ran out of memory\033[0m\n"); return EXIT_FAILURE; } - root->name = "\0"; + root->name = "/\0"; struct dirstack *stack_ptr = dirstack_push(NULL, root); @@ -217,7 +262,25 @@ int main(void) { yylex_destroy(scanner); - // TODO: evaluation (bottom-up computation of sizes using a dirstack) + // task 1 + unsigned long sum_of_sizes = sum_and_count(root); + printf("The sum of all directory sizes < %zu is: %zu\n", upper_bound, sum_of_sizes); + + // task 2 + unsigned long free_space = fs_size - root->size; + unsigned long to_clear = needed_space - free_space; + + printf("------------------------------------------------\n"); + printf("Total Disk Space Available: %zu\n", fs_size); + printf("Total Disk Space Used: %zu\n", root->size); + printf("Free Disk Space: %zu\n", free_space); + printf("Required Disk Space: %zu\n", needed_space); + printf("------------------------------------------------\n\n"); + printf("Looking to free %zu units\n", to_clear); + + struct dirnode *closest_match = find_deletion_candidate(root, to_clear); + + printf("Recommended deletion candidate: `%s` (size %zu)\n", closest_match->name, closest_match->size); return 0; }