diff options
| author | Mistivia <i@mistivia.com> | 2024-01-27 14:02:35 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2024-01-27 14:02:35 +0800 |
| commit | 6580dcd9127f69aaa794472ec92bc46015dc4019 (patch) | |
| tree | dc2c7e102c75180f7bd98c2f3a14f8b55f83c0f2 /advent-of-code/2023/lib | |
init
Diffstat (limited to 'advent-of-code/2023/lib')
| -rw-r--r-- | advent-of-code/2023/lib/map.c | 90 | ||||
| -rw-r--r-- | advent-of-code/2023/lib/map.h | 33 | ||||
| -rw-r--r-- | advent-of-code/2023/lib/rb_tree.c | 378 | ||||
| -rw-r--r-- | advent-of-code/2023/lib/rb_tree.h | 64 | ||||
| -rw-r--r-- | advent-of-code/2023/lib/str.c | 143 | ||||
| -rw-r--r-- | advent-of-code/2023/lib/str.h | 24 | ||||
| -rw-r--r-- | advent-of-code/2023/lib/vec.c | 72 | ||||
| -rw-r--r-- | advent-of-code/2023/lib/vec.h | 15 |
8 files changed, 819 insertions, 0 deletions
diff --git a/advent-of-code/2023/lib/map.c b/advent-of-code/2023/lib/map.c new file mode 100644 index 0000000..846033e --- /dev/null +++ b/advent-of-code/2023/lib/map.c @@ -0,0 +1,90 @@ +#include "map.h" +#include "rb_tree.h" + +#include <string.h> + +typedef int (*rb_cmp_t)(void*, void*); + +void* new_map(cmp_t compare) { + rb_tree_t *tree = malloc(sizeof(rb_tree_t)); + rb_cmp_t cmp = (rb_cmp_t)compare; + *tree = (rb_tree_t){NULL, cmp, NULL}; + return tree; +} + +void map_set(void* self, void* key, void* value) { + node_entry_t *iter = rb_tree_find(self, &key); + if (iter == NULL) { + iter = malloc(sizeof(*iter)); + iter->key = key; + iter->value = value; + rb_tree_insert(self, iter); + } else { + iter->value = value; + } +} + +void* map_get(void* self, void* key) { + node_entry_t *iter = rb_tree_find(self, &key); + if (iter == NULL) return NULL; + return iter->value; +} + +void map_erase(void* self, void* key) { + rb_tree_remove(self, key); +} + +void* map_begin(void *self) { + return rb_tree_min(self); +} + +void* map_next(void *self, void *iter) { + return rb_tree_next(self, iter); +} + +void* map_iter_key(void* iter_) { + node_entry_t *iter = iter_; + return iter->key; +} + +void* map_iter_value(void* iter_) { + node_entry_t *iter = iter_; + return iter->value; +} + +static int dict_cmp(void **a, void** b) { + return strcmp(*a, *b); +} +void* new_dict() { + return new_map(dict_cmp); +} + +void dict_set(void* self, const char *key, void* value) { + map_set(self, (void*)key, value); +} + +void* dict_get(void* self, const char* key) { + return map_get(self, (void*)key); +} + +void dict_erase(void* self, const char* key) { + map_erase(self, (void*)key); +} + +void* dict_begin(void *self) { + return map_begin(self); +} + +void* dict_next(void *self, void *iter) { + return map_next(self, iter); +} + +const char* dict_iter_key(void* iter) { + return map_iter_key(iter); +} + +void* dict_iter_value(void* iter) { + return map_iter_value(iter); +} + + diff --git a/advent-of-code/2023/lib/map.h b/advent-of-code/2023/lib/map.h new file mode 100644 index 0000000..c54048c --- /dev/null +++ b/advent-of-code/2023/lib/map.h @@ -0,0 +1,33 @@ +#ifndef MAP_H_ +#define MAP_H_ + +#include "rb_tree.h" + +typedef struct { + rb_node_t node; + void *key; + void *value; +} node_entry_t; +typedef int (*cmp_t)(void** a, void** b); + +void* new_map(cmp_t compare); +void map_set(void* self, void* key, void* value); +void* map_get(void* self, void* key); +void map_erase(void* self, void* key); + +void* map_begin(void *self); +void* map_next(void *self, void *iter); +void* map_iter_key(void* iter); +void* map_iter_value(void* iter); + +void* new_dict(); +void dict_set(void* self, const char *key, void* value); +void* dict_get(void* self, const char* key); +void dict_erase(void* self, const char* key); + +void* dict_begin(void *self); +void* dict_next(void *self, void *iter); +const char* dict_iter_key(void* iter); +void* dict_iter_value(void* iter); + +#endif diff --git a/advent-of-code/2023/lib/rb_tree.c b/advent-of-code/2023/lib/rb_tree.c new file mode 100644 index 0000000..5aa7905 --- /dev/null +++ b/advent-of-code/2023/lib/rb_tree.c @@ -0,0 +1,378 @@ +// Copyright (C) 2023 Mistivia <i@mistivia.com> +// Licensed under GPLv3. See LICENSE for details. + +/* + * Copyright 2002 Niels Provos <provos@citi.umich.edu> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "rb_tree.h" + +#define RED 1 +#define BLACK 0 + +static rb_node_t *rb_tree_minmax(rb_tree_t *, int); +void *rb_tree_min(rb_tree_t *head) { return rb_tree_minmax(head, -1); } +void *rb_tree_max(rb_tree_t *head) { return rb_tree_minmax(head, 1); } + +void *rb_tree_left(void *node) { + rb_node_t *elm = node; + if (node == NULL) return NULL; + return elm->entry.rbe_left; +} +void *rb_tree_right(void *node) { + rb_node_t *elm = node; + if (node == NULL) return NULL; + return elm->entry.rbe_right; +} +void *rb_tree_parent(void *node) { + rb_node_t *elm = node; + if (node == NULL) return NULL; + return elm->entry.rbe_parent; +} + +static void augment(rb_tree_t *head, rb_node_t *elm) { + if (head->augment != NULL) head->augment(elm); +} + +static void rb_tree_insert_color(rb_tree_t *head, rb_node_t *elm); +static void rb_tree_remove_color(rb_tree_t *head, rb_node_t *parent, + rb_node_t *elm); + +static void rotate_left(rb_tree_t *head, rb_node_t *elm) { + rb_node_t *tmp = elm->entry.rbe_right; + if ((elm->entry.rbe_right = tmp->entry.rbe_left)) { + tmp->entry.rbe_left->entry.rbe_parent = elm; + } + augment(head, elm); + if ((tmp->entry.rbe_parent = elm->entry.rbe_parent)) { + if (elm == elm->entry.rbe_parent->entry.rbe_left) + elm->entry.rbe_parent->entry.rbe_left = tmp; + else + elm->entry.rbe_parent->entry.rbe_right = tmp; + } else { + head->rbh_root = tmp; + } + tmp->entry.rbe_left = elm; + elm->entry.rbe_parent = tmp; + augment(head, tmp); + if (tmp->entry.rbe_parent) { + augment(head, tmp->entry.rbe_parent); + } +} + +static void rotate_right(rb_tree_t *head, rb_node_t *elm) { + rb_node_t *tmp = elm->entry.rbe_left; + if ((elm->entry.rbe_left = tmp->entry.rbe_right)) { + tmp->entry.rbe_right->entry.rbe_parent = elm; + } + augment(head, elm); + if ((tmp->entry.rbe_parent = elm->entry.rbe_parent)) { + if (elm == elm->entry.rbe_parent->entry.rbe_left) + elm->entry.rbe_parent->entry.rbe_left = tmp; + else + elm->entry.rbe_parent->entry.rbe_right = tmp; + } else { + head->rbh_root = tmp; + } + tmp->entry.rbe_right = elm; + elm->entry.rbe_parent = tmp; + augment(head, tmp); + if (tmp->entry.rbe_parent) { + augment(head, tmp->entry.rbe_parent); + } +} + +static void rb_tree_insert_color(rb_tree_t *head, rb_node_t *elm) { + rb_node_t *parent, *gparent, *tmp; + while ((parent = elm->entry.rbe_parent) && parent->entry.rbe_color == 1) { + gparent = parent->entry.rbe_parent; + if (parent == gparent->entry.rbe_left) { + tmp = gparent->entry.rbe_right; + if (tmp && tmp->entry.rbe_color == 1) { + tmp->entry.rbe_color = BLACK; + parent->entry.rbe_color = BLACK; + gparent->entry.rbe_color = RED; + elm = gparent; + continue; + } + if (parent->entry.rbe_right == elm) { + rotate_left(head, parent); + tmp = parent; + parent = elm; + elm = tmp; + } + parent->entry.rbe_color = BLACK; + gparent->entry.rbe_color = RED; + rotate_right(head, gparent); + } else { + tmp = gparent->entry.rbe_left; + if (tmp && tmp->entry.rbe_color == 1) { + tmp->entry.rbe_color = BLACK; + parent->entry.rbe_color = BLACK; + gparent->entry.rbe_color = RED; + ; + elm = gparent; + continue; + } + if (parent->entry.rbe_left == elm) { + rotate_right(head, parent); + tmp = parent; + parent = elm; + elm = tmp; + } + parent->entry.rbe_color = BLACK; + gparent->entry.rbe_color = RED; + rotate_left(head, gparent); + } + } + head->rbh_root->entry.rbe_color = BLACK; +} + +static void rb_tree_remove_color(rb_tree_t *head, rb_node_t *parent, + rb_node_t *elm) { + rb_node_t *tmp; + while ((elm == NULL || elm->entry.rbe_color == 0) && + elm != head->rbh_root) { + if (parent->entry.rbe_left == elm) { + tmp = parent->entry.rbe_right; + if (tmp->entry.rbe_color == 1) { + tmp->entry.rbe_color = BLACK; + parent->entry.rbe_color = RED; + rotate_left(head, parent); + tmp = parent->entry.rbe_right; + } + if ((tmp->entry.rbe_left == NULL || + tmp->entry.rbe_left->entry.rbe_color == 0) && + (tmp->entry.rbe_right == NULL || + tmp->entry.rbe_right->entry.rbe_color == 0)) { + tmp->entry.rbe_color = RED; + elm = parent; + parent = elm->entry.rbe_parent; + } else { + if (tmp->entry.rbe_right == NULL || + tmp->entry.rbe_right->entry.rbe_color == 0) { + rb_node_t *oleft; + if ((oleft = tmp->entry.rbe_left)) + oleft->entry.rbe_color = BLACK; + tmp->entry.rbe_color = RED; + rotate_right(head, tmp); + tmp = parent->entry.rbe_right; + } + tmp->entry.rbe_color = parent->entry.rbe_color; + parent->entry.rbe_color = BLACK; + if (tmp->entry.rbe_right) + tmp->entry.rbe_right->entry.rbe_color = BLACK; + rotate_left(head, parent); + elm = head->rbh_root; + break; + } + } else { + tmp = parent->entry.rbe_left; + if (tmp->entry.rbe_color == 1) { + tmp->entry.rbe_color = BLACK; + parent->entry.rbe_color = RED; + rotate_right(head, parent); + tmp = parent->entry.rbe_left; + } + if ((tmp->entry.rbe_left == NULL || + tmp->entry.rbe_left->entry.rbe_color == 0) && + (tmp->entry.rbe_right == NULL || + tmp->entry.rbe_right->entry.rbe_color == 0)) { + tmp->entry.rbe_color = RED; + elm = parent; + parent = elm->entry.rbe_parent; + } else { + if (tmp->entry.rbe_left == NULL || + tmp->entry.rbe_left->entry.rbe_color == 0) { + rb_node_t *oright; + if ((oright = tmp->entry.rbe_right)) + oright->entry.rbe_color = BLACK; + tmp->entry.rbe_color = RED; + rotate_left(head, tmp); + tmp = parent->entry.rbe_left; + } + tmp->entry.rbe_color = parent->entry.rbe_color; + parent->entry.rbe_color = BLACK; + if (tmp->entry.rbe_left) + tmp->entry.rbe_left->entry.rbe_color = BLACK; + rotate_right(head, parent); + elm = head->rbh_root; + break; + } + } + } + if (elm) elm->entry.rbe_color = BLACK; +} + +void rb_tree_remove(rb_tree_t *head, void *elmv) { + rb_node_t *elm = elmv; + rb_node_t *child, *parent; + int color; + if (elm->entry.rbe_left == NULL) + child = elm->entry.rbe_right; + else if (elm->entry.rbe_right == NULL) + child = elm->entry.rbe_left; + else { + rb_node_t *old = elm, *left; + elm = elm->entry.rbe_right; + while ((left = elm->entry.rbe_left)) + elm = left; + child = elm->entry.rbe_right; + parent = elm->entry.rbe_parent; + color = elm->entry.rbe_color; + if (child) child->entry.rbe_parent = parent; + if (parent) { + if (parent->entry.rbe_left == elm) + parent->entry.rbe_left = child; + else + parent->entry.rbe_right = child; + augment(head, parent); + } else + head->rbh_root = child; + if (elm->entry.rbe_parent == old) parent = elm; + elm->entry = old->entry; + if (old->entry.rbe_parent) { + if ((old->entry.rbe_parent)->entry.rbe_left == old) + (old->entry.rbe_parent)->entry.rbe_left = elm; + else + (old->entry.rbe_parent)->entry.rbe_right = elm; + augment(head, old->entry.rbe_parent); + } else + head->rbh_root = elm; + old->entry.rbe_left->entry.rbe_parent = elm; + if (old->entry.rbe_right) old->entry.rbe_right->entry.rbe_parent = elm; + if (parent) { + left = parent; + if (head->augment != NULL) { + do { + augment(head, left); + } while ((left = left->entry.rbe_parent)); + } + } + goto color; + } + parent = elm->entry.rbe_parent; + color = elm->entry.rbe_color; + if (child) child->entry.rbe_parent = parent; + if (parent) { + if (parent->entry.rbe_left == elm) + parent->entry.rbe_left = child; + else + parent->entry.rbe_right = child; + rb_node_t *goback = parent; + if (head->augment != NULL) { + do { + augment(head, goback); + } while ((goback = goback->entry.rbe_parent)); + } + } else + head->rbh_root = child; +color: + if (color == 0) rb_tree_remove_color(head, parent, child); +} + +void *rb_tree_insert(rb_tree_t *head, void *elmv) { + rb_node_t *elm = elmv; + rb_node_t *tmp; + rb_node_t *parent = NULL; + int comp = 0; + tmp = head->rbh_root; + while (tmp) { + parent = tmp; + comp = head->cmp((void *)elm->content, (void *)parent->content); + if (comp < 0) + tmp = tmp->entry.rbe_left; + else if (comp > 0) + tmp = tmp->entry.rbe_right; + else + return tmp; + } + elm->entry.rbe_parent = parent; + elm->entry.rbe_left = elm->entry.rbe_right = NULL; + elm->entry.rbe_color = RED; + if (parent != NULL) { + if (comp < 0) + parent->entry.rbe_left = elm; + else + parent->entry.rbe_right = elm; + rb_node_t *goback = parent; + if (head->augment != NULL) { + do { + augment(head, goback); + } while ((goback = goback->entry.rbe_parent)); + } + } else + head->rbh_root = elm; + rb_tree_insert_color(head, elm); + return (NULL); +} + +void *rb_tree_find(rb_tree_t *head, void *key) { + rb_node_t *tmp = head->rbh_root; + int comp; + while (tmp) { + comp = head->cmp(key, (void *)tmp->content); + if (comp < 0) + tmp = tmp->entry.rbe_left; + else if (comp > 0) + tmp = tmp->entry.rbe_right; + else + return tmp; + } + return (NULL); +} + +void *rb_tree_next(rb_tree_t *head, void *elmv) { + rb_node_t *elm = elmv; + if (elm->entry.rbe_right) { + elm = elm->entry.rbe_right; + while (elm->entry.rbe_left) + elm = elm->entry.rbe_left; + } else { + if (elm->entry.rbe_parent && + (elm == (elm->entry.rbe_parent)->entry.rbe_left)) + elm = elm->entry.rbe_parent; + else { + while (elm->entry.rbe_parent && + (elm == (elm->entry.rbe_parent)->entry.rbe_right)) + elm = elm->entry.rbe_parent; + elm = elm->entry.rbe_parent; + } + } + return elm; +} + +static rb_node_t *rb_tree_minmax(rb_tree_t *head, int val) { + rb_node_t *tmp = head->rbh_root; + rb_node_t *parent = NULL; + while (tmp) { + parent = tmp; + if (val < 0) + tmp = tmp->entry.rbe_left; + else + tmp = tmp->entry.rbe_right; + } + return parent; +}; + diff --git a/advent-of-code/2023/lib/rb_tree.h b/advent-of-code/2023/lib/rb_tree.h new file mode 100644 index 0000000..2096ff6 --- /dev/null +++ b/advent-of-code/2023/lib/rb_tree.h @@ -0,0 +1,64 @@ +// Copyright (C) 2023 Mistivia <i@mistivia.com> +// Licensed under GPLv3. See LICENSE for details. + +/* + * Copyright 2002 Niels Provos <provos@citi.umich.edu> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RB_TREE_H_ +#define RB_TREE_H_ + +#include <stdlib.h> + +struct rb_node { + struct { + struct rb_node *rbe_left; + struct rb_node *rbe_right; + struct rb_node *rbe_parent; + int rbe_color; + } entry; + char content[0]; +}; +typedef struct rb_node rb_node_t; + +struct rb_tree { + rb_node_t *rbh_root; + int (*cmp)(void *k1, void *k2); + void (*augment)(void *elm); +}; +typedef struct rb_tree rb_tree_t; + +void rb_tree_remove(rb_tree_t *, void *iter); + +// return a iterator +void *rb_tree_insert(rb_tree_t *, void *treenode); +void *rb_tree_find(rb_tree_t *, void *val); +void *rb_tree_next(rb_tree_t *, void *iter); +void *rb_tree_min(rb_tree_t *); +void *rb_tree_max(rb_tree_t *); +void *rb_tree_left(void *node); +void *rb_tree_right(void *node); +void *rb_tree_parent(void *node); + +#endif diff --git a/advent-of-code/2023/lib/str.c b/advent-of-code/2023/lib/str.c new file mode 100644 index 0000000..511e45b --- /dev/null +++ b/advent-of-code/2023/lib/str.c @@ -0,0 +1,143 @@ +// Copyright (C) 2023 Mistivia <i@mistivia.com> +// Licensed under GPLv3. See LICENSE for details. + +#include "str.h" + +#include <ctype.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "vec.h" + +void *str_split(const char *str, char delim) { + void* ret = new_vec(); + + if (str == NULL) return NULL; + if (*str == '\n') { + return ret; + } + int count = 0; + const char *begin = str; + for (const char *p = str; *p != '\0'; p++) { + if (*p != delim && !(delim == '\0' && isspace(*p))) { + continue; + } + int size = p - begin; + if (size > 0) count++; + } + count++; + + begin = str; + int i = 0; + bool finished = false; + for (const char *p = str; !finished; p++) { + if (*p == '\0') finished = true; + if (*p != delim && *p != '\0' && !(delim == '\0' && isspace(*p))) { + continue; + } + int size = p - begin; + if (size == 0) { + begin = p + 1; + continue; + } + char *buf = malloc(sizeof(char) * (size + 1)); + buf[size] = '\0'; + memcpy(buf, begin, size * sizeof(char)); + begin = p + 1; + vec_push_back(ret, buf); + } + return ret; +} + +char *str_strip(const char *str) { + if (str == NULL) return NULL; + int len = strlen(str); + const char *begin = str; + const char *end = str + len - 1; + while (isspace(*begin) && begin < end) { + begin++; + } + while (isspace(*end) && end >= begin) { + end--; + } + len = end - begin + 1; + char *buf = malloc(sizeof(char) * (len) + 1); + buf[len] = '\0'; + memcpy(buf, begin, len); + return buf; +} + +typedef struct { + size_t size; + size_t cap; + char *buf; +} str_builder_t; + +// string stream +void* new_ss() { + str_builder_t *self = malloc(sizeof(str_builder_t)); + *self = (str_builder_t){.size = 0, .cap = 16}; + self->buf = malloc(sizeof(char) * 17); + return self; +} + +static void ss_reserve(str_builder_t *self, int extra) { + if (self->size + extra <= self->cap) { + return; + } + int new_cap = (self->size + extra) * 2; + self->buf = realloc(self->buf, new_cap + 1); + memset(self->buf + self->cap, 0, new_cap - self->cap + 1); + self->cap = new_cap; +} + +void ss_add(void *self_, char *format, ...) { + str_builder_t *self = self_; + va_list va1; + va_list va2; + va_start(va1, format); + va_copy(va2, va1); + int size = vsnprintf(NULL, 0, format, va1); + ss_reserve(self, size); + vsnprintf(self->buf + self->size, self->cap - self->size + 1, format, va2); + self->size += size; +} + +void ss_addc(void *self_, char c) { + str_builder_t *self = self_; + ss_reserve(self, 1); + self->buf[self->size] = c; + self->size++; +} + +char *ss_cstr(void *self_) { + str_builder_t *self = self_; + return self->buf; +} + +size_t ss_size(void *self_) { + str_builder_t *self = self_; + return self->size; +} + +char *fgetline(FILE *fp) { + void *ss = new_ss(); + while (true) { + int c = fgetc(fp); + if (c == EOF && ss_size(ss) == 0) return NULL; + if (c != EOF) ss_addc(ss, c); + if (c == EOF || c == '\n') return ss_cstr(ss); + } + return NULL; +} + +int fpeek(FILE *fp) { + int c = fgetc(fp); + if (c == EOF) return c; + ungetc(c, fp); + return c; +} diff --git a/advent-of-code/2023/lib/str.h b/advent-of-code/2023/lib/str.h new file mode 100644 index 0000000..214e297 --- /dev/null +++ b/advent-of-code/2023/lib/str.h @@ -0,0 +1,24 @@ +// Copyright (C) 2023 Mistivia <i@mistivia.com> +// Licensed under GPLv3. See LICENSE for details. + +#ifndef DYMC_STR_H_ +#define DYMC_STR_H_ + +#include <stdio.h> +#include <stddef.h> + +char *str_strip(const char *str); +void* str_split(const char *str, char delim); + + +// string stream +void* new_ss(); +void ss_add(void *self, char *format, ...); +void ss_addc(void *self, char c); +char *ss_cstr(void *self); +size_t ss_size(void* self); + +char *fgetline(FILE *fp); +int fpeek(FILE *fp); + +#endif diff --git a/advent-of-code/2023/lib/vec.c b/advent-of-code/2023/lib/vec.c new file mode 100644 index 0000000..c3d8a0a --- /dev/null +++ b/advent-of-code/2023/lib/vec.c @@ -0,0 +1,72 @@ +#include "vec.h" + +#include <string.h> +#include "stdlib.h" + +struct vec { + size_t length; + size_t capacity; + void** buf; +}; + +static void vec_enlarge(struct vec* self) { + self->buf = realloc(self->buf, self->capacity * sizeof(void*) * 2); + self->capacity = self->capacity * 2; +} + +void *new_vec() { + struct vec* vec = malloc(sizeof(struct vec)); + vec->length = 0; + vec->capacity = 16; + vec->buf = malloc(16 * sizeof(void*)); + return vec; +} + +void vec_push_back(void *self_, void* obj) { + struct vec *self = self_; + if (self->length == self->capacity) vec_enlarge(self); + self->buf[self->length] = obj; + self->length++; +} + +void* vec_get(void *self_, size_t n) { + struct vec *self = self_; + if (n < 0 || n >= self->length) return NULL; + return self->buf[n]; +} + + +void vec_erase(void *self_, size_t n) { + struct vec *self = self_; + if (self->length <= n) { + return; + } + memmove(self->buf + n, self->buf + n + 1, (self->length - n - 1) * sizeof(void*)); + self->length--; +} + +size_t vec_size(void *self_) { + struct vec *self = self_; + return self->length; +} + +void vec_reserve(void *self_, size_t n) { + struct vec *self = self_; + if (n <= self->capacity) { + return; + } + self->buf = malloc(sizeof(void*) * n); + self->capacity = n; +} + +void vec_insert(void *self_, size_t pos, void *obj) { + struct vec *self = self_; + if (self->length == self->capacity) { + vec_enlarge(self); + } + if (pos > self->length || pos < 0) return; + memmove(self->buf + pos + 1, self->buf + pos, sizeof(void*) * (self->length - pos)); + self->buf[pos] = obj; + self->length++; +} + diff --git a/advent-of-code/2023/lib/vec.h b/advent-of-code/2023/lib/vec.h new file mode 100644 index 0000000..5778689 --- /dev/null +++ b/advent-of-code/2023/lib/vec.h @@ -0,0 +1,15 @@ +#ifndef VEC_H_ +#define VEC_H_ + +#include <stddef.h> + +void *new_vec(); +void vec_push_back(void *self, void* obj); +void* vec_get(void *self, size_t n); +size_t vec_length(void *self); +void vec_erase(void *self, size_t n); +size_t vec_size(void* self); +void vec_reserve(void* self, size_t n); +void vec_insert(void* self, size_t pos, void* obj); + +#endif |
