This commit is contained in:
Dobos Ádám
2022-12-10 21:08:03 +01:00
parent 2a69c8ba67
commit b3d9e1f078
3 changed files with 1294 additions and 0 deletions

BIN
day7/dir Executable file
View File

Binary file not shown.

242
day7/dir.c Normal file
View File

@@ -0,0 +1,242 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 64
#define MAX_FILES 32
#define MAX_CHILDREN 16
#define THRESHOLD 100000
// at most
#define RULE <=
#define TOTAL_SIZE 70000000
#define SPACE_NEEDED 30000000
typedef enum commands {
CD,
LS
} COMMAND;
typedef struct fnode {
char name[BUFFER_SIZE];
unsigned long size;
} FNODE;
typedef struct dir {
char name[BUFFER_SIZE];
FNODE files[MAX_FILES];
int files_num;
struct dir *parent;
struct dir *children[MAX_CHILDREN];
int children_num;
int cached;
unsigned long cached_size;
} DIR;
COMMAND map_cmd(char *);
DIR* createDir(char*, DIR*);
void cp(char*, char*);
DIR* findDirName(DIR*, char*);
FNODE* findFileName(DIR*, char*);
int cmp(char*, char*);
void release(DIR*);
unsigned long dirsize(DIR*);
void gotta_catch_em_all(DIR*);
void omelette_du_fromage(DIR*, DIR**, unsigned long);
unsigned long sum;
int main() {
char linebuf[BUFFER_SIZE], buf[BUFFER_SIZE], *p, c;
memset(linebuf, 0, BUFFER_SIZE);
p = linebuf;
COMMAND cmd;
DIR *currentDir = NULL, *rootDir = NULL, *target;
FNODE *tmpf;
unsigned long fsize;
while ((c = getchar()) != EOF) {
*p++ = c;
if (c == '\n') {
if (linebuf[0] == '$') {
// command
memset(buf, 0 , BUFFER_SIZE);
sscanf(linebuf, "$ %s", buf);
cmd = map_cmd(buf);
if (cmd == CD) {
memset(buf, 0 , BUFFER_SIZE);
sscanf(linebuf + 4, "%s", buf);
if (buf[0] == '/' && buf[1] == 0) {
// Root
if (rootDir == NULL)
rootDir = createDir(buf, NULL);
currentDir = rootDir;
} else if (buf[0] == '.' && buf[1] == '.' && buf[2] == 0) {
currentDir = currentDir->parent;
} else {
target = findDirName(currentDir, buf);
if (target == NULL) {
target = createDir(buf, currentDir);
}
currentDir = target;
}
} else if (cmd == LS) {
// Nothing to do
}
}
memset(buf, 0 , BUFFER_SIZE);
if (sscanf(linebuf, "%lu %s", &fsize, buf)) {
// File
tmpf = findFileName(currentDir, buf);
if (tmpf == NULL) {
cp(buf, currentDir->files[currentDir->files_num].name);
currentDir->files[currentDir->files_num].size = fsize;
currentDir->files_num++;
}
} else {
// Dir
sscanf(linebuf, "dir %s", buf);
target = findDirName(currentDir, buf);
if (target == NULL) {
target = createDir(buf, currentDir);
}
}
memset(linebuf, 0, BUFFER_SIZE);
p = linebuf;
}
}
// First part
gotta_catch_em_all(rootDir);
printf("%lu\n", sum);
// Second part
DIR *bestMatch = rootDir;
unsigned long free_space = TOTAL_SIZE - dirsize(rootDir);
printf("\nFREE SPACE: %lu\n", free_space);
omelette_du_fromage(rootDir, &bestMatch, free_space);
printf("TO DELETE: %s, %lu\n", bestMatch->name, dirsize(bestMatch));
currentDir = NULL;
// "Aki malloc-ot mond, mondjon free-t is"
release(rootDir);
free(rootDir);
}
COMMAND map_cmd(char *buf) {
if (buf[0] == 'c' && buf[1] == 'd') {
return CD;
} else if (buf[0] == 'l' && buf[1] == 's') {
return LS;
}
return -1;
}
DIR* createDir(char* name, DIR* parent) {
DIR* newDir = (DIR*)malloc(sizeof(DIR));
memset(newDir->files, 0, MAX_FILES*sizeof(FNODE));
memset(newDir->children, 0, MAX_CHILDREN*sizeof(DIR*));
newDir->files_num = 0;
newDir->children_num = 0;
newDir->parent = parent;
newDir->cached = 0;
if (parent != NULL) {
parent->children[parent->children_num] = newDir;
parent->children_num++;
}
cp(name, newDir->name);
return newDir;
}
void cp(char *p , char *q){
while((*q++ = *p++) != 0) {}
}
DIR* findDirName(DIR* dir, char *name) {
for (int i = 0; i < dir->children_num; i++) {
if (cmp(dir->children[i]->name, name)) {
return dir->children[i];
}
}
return NULL;
}
int cmp(char *p, char *q) {
for (int i = 0; i < BUFFER_SIZE; i++) {
if (p[i] != q[i]) {
return 0;
}
}
return 1;
}
void release(DIR* dir) {
for (int i = 0; i < dir->children_num; i++) {
release(dir->children[i]);
free(dir->children[i]);
}
}
FNODE* findFileName(DIR* dir, char* name) {
for (int i = 0; i < dir->files_num; i++) {
if (cmp(dir->files[i].name, name)) {
return &dir->files[i];
}
}
return NULL;
}
unsigned long dirsize(DIR* dir) {
if (dir->cached) {
return dir->cached_size;
}
unsigned long mysize = 0;
// Files here
for (int i = 0; i < dir->files_num; i++) {
mysize += dir->files[i].size;
}
// Files in subdirectories
for (int i = 0; i < dir->children_num; i++) {
mysize += dirsize(dir->children[i]);
}
dir->cached = 1;
dir->cached_size = mysize;
return mysize;
}
// I know this is shit, each directory should have a size cache
// so if we already know its size we don't recurse it again
// But I don't care at this point
void gotta_catch_em_all(DIR* dir) {
unsigned long schlong = dirsize(dir);
if (schlong RULE THRESHOLD) {
sum += schlong;
}
for (int i = 0; i < dir->children_num; i++) {
gotta_catch_em_all(dir->children[i]);
}
}
void omelette_du_fromage(DIR* dir, DIR** bestMatch, unsigned long freeSpace) {
unsigned long current = freeSpace + dirsize(dir);
if (current > SPACE_NEEDED && current < (freeSpace + dirsize(*bestMatch))) {
*bestMatch = dir;
}
for (int i = 0; i < dir->children_num; i++) {
omelette_du_fromage(dir->children[i], bestMatch, freeSpace);
}
}

1052
day7/input.txt Normal file
View File

File diff suppressed because it is too large Load Diff