From 9e3a875e37629bcb2191bd661903fc259098f2dd Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Sat, 10 Dec 2022 16:43:34 +0100 Subject: [PATCH] 2022 day 7: C final version (parts 1 & 2) --- 2022/RESULTS.txt | 8 +++ 2022/day07/aoc-c.c | 127 +++++++++++---------------------------------- 2 files changed, 38 insertions(+), 97 deletions(-) diff --git a/2022/RESULTS.txt b/2022/RESULTS.txt index 7073e46..97aef94 100644 --- a/2022/RESULTS.txt +++ b/2022/RESULTS.txt @@ -139,7 +139,15 @@ aoc.bash: res=1390824 time: 0:00.05 real, 0.03 user, 0.01 sys context-switch: 7+1, page-faults: 0+307 +aoc-c: res=1390824 + time: 0:00.00 real, 0.00 user, 0.00 sys + context-switch: 0+1, page-faults: 0+98 + +++++++++++++++++ part 2 aoc.bash: res=7490863 time: 0:00.05 real, 0.05 user, 0.00 sys context-switch: 9+1, page-faults: 0+308 + +aoc-c: res=7490863 + time: 0:00.00 real, 0.00 user, 0.00 sys + context-switch: 0+1, page-faults: 0+98 diff --git a/2022/day07/aoc-c.c b/2022/day07/aoc-c.c index 4f6baea..44ed36f 100644 --- a/2022/day07/aoc-c.c +++ b/2022/day07/aoc-c.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "pool.h" #include "debug.h" @@ -39,35 +40,16 @@ typedef struct dir { static pool_t *pool_dirs; -static void print_hash() -{ - ulong bucket; - dir_t *cur; - log(3, "------------------- hashtable\n"); - hash_for_each(hasht_dir, bucket, cur, hlist) { - log(3, "hash=%lu/%u [%.*s] size=%u\n", bucket, cur->hash, - cur->namelen, cur->name, cur->size); - } - log(3, "-------------------\n"); -} - /** * find_dir - find entry in an hashtable bucket */ static dir_t *find_dir(struct hlist_head *head, uint hash, char *dir, uint len) { dir_t *cur; - print_hash(); - hlist_for_each_entry(cur, head, hlist) { - if (cur->hash == hash) { - if (cur->namelen == len && !memcmp(cur->name, dir, len)) { - log(4, "found hash [%.*s]\n", len, dir); + hlist_for_each_entry(cur, head, hlist) + if (cur->hash == hash && cur->namelen == len && !memcmp(cur->name, dir, len)) return cur; - } - } - } - log(4, "hash [%.*s] not found\n", len, dir); return NULL; } @@ -84,17 +66,9 @@ static dir_t *find_dirname(char *name, uint len) */ static int parent_dir(char *dir, uint len) { - log_f(4, "len=%u [%.*s] ", len, len, dir); - if (len > 1) { /* not root dir */ - char *p = dir + len - 1; - for (; *p != '/'; p--) /* assume there is always '/' */ - ; - len = p - dir; - if (!len) - len = 1; - } - log(4, "newlen=%u [%.*s]\n", len, len, dir); - return len; + for (--len; len && *(dir + len) != '/'; --len) + ; + return len? len: 1; } static void adjust_dirsize(dir_t *dir, uint size) @@ -102,43 +76,33 @@ static void adjust_dirsize(dir_t *dir, uint size) dir_t *cur = dir; uint len = cur->namelen; - log_f(3, "dir=[%.*s]\n", len, cur->name); while (len > 1) { cur = find_dirname(dir->name, len); - //bucket = hash_32(hash, HBITS); - //cur = find_dir(&hasht_dir[bucket], hash, dir->name, len); if (!cur) { log(1, "FATAL hash issue"); exit(1); } - log_f(3, "adjusting %.*s size from %u to %u\n", len, cur->name, - cur->size, cur->size + size); cur->size +=size; len = parent_dir(dir->name, len); }; - //hash = pjwhash("/", 1); - //bucket = hash_32(hash, HBITS); - cur = find_dirname("/", 1); + cur = find_dirname("/", 1); /* do not forget "/" */ cur->size += size; } /** * add_dir - add an entry in hashtable */ -static struct dir *add_dir(char *dir, uint len, uint hash, uint bucket, int calc) +static struct dir *add_dir(char *dir, uint len) { + uint hash = pjwhash(dir, len); + uint bucket = hash_32(hash, HBITS); dir_t *new = pool_get(pool_dirs); - if (calc) { /* not calculated yet */ - hash = pjwhash(dir, len); - bucket = hash_32(hash, HBITS); - } + memcpy(new->name, dir, len); new->namelen = len; new->hash = hash; new->size = 0; hlist_add_head(&new->hlist, &hasht_dir[bucket]); - log(3, "NEW DIR: "); - log(3, "hash(%.*s)=%u/%u\n", len, dir, hash, bucket); return new; } @@ -147,81 +111,52 @@ static struct dir *add_dir(char *dir, uint len, uint hash, uint bucket, int calc */ static struct dir *add_dir_maybe(char *dir, int len) { - uint hash = pjwhash(dir, len), bucket = hash_32(hash, HBITS); - dir_t *new; - if (!(new = find_dir(&hasht_dir[bucket], hash, dir, len))) { - new = add_dir(dir, len, hash, bucket, 0); - log(5, "add_maybe: added [%.*s]\n", len, dir); - } else { - log(5, "add_maybe: found existing [%.*s]\n", len, dir); - } - return new; + dir_t *new = find_dirname(dir, len); + return new? new: add_dir(dir, len); } static struct dir *cd(struct dir *dir, char *to, uint tolen) { - //char *p = dir->name + dir->namelen - 1, *newname = dir->name; char *newname = dir->name; - dir_t *newdir; - int newlen; + int newlen, add_slash = 0; + if (!dir) + return add_dir_maybe(to, tolen); if (dir->namelen + tolen + 1 > DIRNAME_SIZE) /* conservative (think / or ..) */ return NULL; - if (*to == '.') { /* .. = parent dir */ newlen = parent_dir(dir->name, dir->namelen); - if (!newlen) - newlen = 1; - - log(3, "GOING UP from=%d[%.*s] ", dir->namelen, dir->namelen, newname); - log(3, "to=%d[%.*s] ", tolen, tolen, to); - log(3, "diff=%d\n", newlen); - log(3, "new = %d[%.*s]\n", newlen, newlen, newname); } else if (*to == '/') { /* root */ newname = to; newlen = tolen; - log(3, "GOING ROOT from %d[%.*s]\n", dir->namelen, dir->namelen, dir->name); } else { /* subdir */ - int notroot = 0; newlen = dir->namelen + tolen; - if (dir->namelen > 1) { /* +1 for '/' */ + if (dir->namelen > 1) { /* add '/' separator */ dir->name[dir->namelen] = '/'; - notroot = 1; + add_slash = 1; + newlen++; } - memcpy(dir->name + dir->namelen + notroot, to, tolen); - newlen += notroot; - log(3, "GOING DOWN from=%d[%.*s] ", dir->namelen, dir->namelen, dir->name); - log(3, "to=%d[%.*s] ", tolen, tolen, to); - log(3, "new = %d[%.*s]\n", newlen, newlen, dir->name); + memcpy(dir->name + dir->namelen + add_slash, to, tolen); } - newdir = add_dir_maybe(newname, newlen); - return newdir; + return add_dir_maybe(newname, newlen); } #define CDLEN (sizeof("$ cd ") - 1) -static void parse(dir_t *curdir) +static void parse() { + dir_t *curdir = NULL; size_t alloc = 0; char *buf = NULL, *tok; ssize_t buflen; - uint size; while ((buflen = getline(&buf, &alloc, stdin)) > 0) { buf[--buflen] = 0; tok = buf; - printf("PARSING buf=[%s] len=%zu\n", buf, buflen); - if (*tok == '$') { - if (*(tok+2) == 'l') /* ignore ls */ - continue; - tok += CDLEN; - printf("****** buf=[%s] len=%zu\n", tok, buflen - CDLEN); - curdir = cd(curdir, tok, buflen - CDLEN); - } else if (*tok != 'd') { /* ignore "dir" keyword */ - size = atoi(tok); - printf("****** size=%u\n", size); - adjust_dirsize(curdir, size); - } + if (*tok == '$' &&*(tok+2) == 'c') /* ignore "ls"" */ + curdir = cd(curdir, tok + CDLEN, buflen - CDLEN); + else if (isdigit(*tok)) /* ignore "dir" keyword */ + adjust_dirsize(curdir, atoi(tok)); } free(buf); return; @@ -251,11 +186,9 @@ int main(int ac, char **av) { int part = parseargs(ac, av); pool_dirs = pool_create("dirs", 128, sizeof(dir_t)); - puts("zobi"); - dir_t *root = add_dir("/", 1, 0, 0, 1); - puts("zobi"); - parse(root); - print_hash(); + + parse(); printf("%s: res=%d\n", *av, solve(part)); + pool_destroy(pool_dirs); exit(0); }