Solve task 1 & 2

This commit is contained in:
Felix Suchert 2023-01-07 21:50:07 +01:00
parent 705fbc4ef5
commit 441e0f327b
Signed by: feliix42
GPG key ID: 24363525EA0E8A99

View file

@ -35,6 +35,10 @@
#include "parser.h" #include "parser.h"
#include "lexer.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* dirstack_push(struct dirstack *stack, struct dirnode *item) {
struct dirstack *head = calloc(1, sizeof(struct dirstack)); struct dirstack *head = calloc(1, sizeof(struct dirstack));
if (!head) { if (!head) {
@ -111,12 +115,7 @@ command
state->cur = state->stackptr->item; state->cur = state->stackptr->item;
} }
| PROMPT CHDIR SPACE PATHSPEC NEWLINE { | PROMPT CHDIR SPACE PATHSPEC NEWLINE {
// TODO: CLEANUP // printf("searching in %s now for path %s\n", state->cur->name, $4);
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);
}
// move into the new directory (creating it if it doesn't exist is not necessary, LIST does that) // move into the new directory (creating it if it doesn't exist is not necessary, LIST does that)
struct dirnode *cur_node = state->cur; struct dirnode *cur_node = state->cur;
@ -128,17 +127,18 @@ command
if (strcmp($4, cur_node->directories[i]->name) == 0) { if (strcmp($4, cur_node->directories[i]->name) == 0) {
found = i; found = i;
c = 0; 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 { } 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) { if (c == -1) {
fprintf(stderr, "\033[91m[error] got no such directory lol\033[0m\n"); fprintf(stderr, "\033[91m[error] got no such directory lol\033[0m\n");
// TODO: error, directory not found // TODO: error, directory not found
} else { } // else {
printf("found it\n"); // printf("found it\n");
} // }
struct dirnode *next = cur_node->directories[found]; struct dirnode *next = cur_node->directories[found];
@ -165,7 +165,6 @@ listing
item->name = $3; item->name = $3;
add_directory(state->cur, item); add_directory(state->cur, item);
printf("know about %zu dirs now!\n", state->cur->num_dirs);
} }
| SIZE SPACE PATHSPEC { | SIZE SPACE PATHSPEC {
struct filenode *item = calloc(1, sizeof(struct filenode)); 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) { int main(void) {
struct dirnode *root = calloc(1, sizeof(struct dirnode)); struct dirnode *root = calloc(1, sizeof(struct dirnode));
if (!root) { if (!root) {
fprintf(stderr, "\033[91m[error] Ran out of memory\033[0m\n"); fprintf(stderr, "\033[91m[error] Ran out of memory\033[0m\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
root->name = "\0"; root->name = "/\0";
struct dirstack *stack_ptr = dirstack_push(NULL, root); struct dirstack *stack_ptr = dirstack_push(NULL, root);
@ -217,7 +262,25 @@ int main(void) {
yylex_destroy(scanner); 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; return 0;
} }