diff --git a/CMakeLists.txt b/CMakeLists.txt index 39dec8f..b3a59f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,4 +22,6 @@ target_link_libraries(day_02 m) add_executable(day_03 day_3.c input_handler.c) -add_executable(day_04 day_4.c input_handler.c) \ No newline at end of file +add_executable(day_04 day_4.c input_handler.c) + +add_executable(day_05 day_5.c input_handler.c map.c) \ No newline at end of file diff --git a/day_4.c b/day_4.c index 1bc7827..aadca1e 100644 --- a/day_4.c +++ b/day_4.c @@ -120,6 +120,6 @@ CardList* load_cards(const char *file_name) { clist_add(list, card); } - free(buffer); + // free(buffer); return list; } diff --git a/day_5.c b/day_5.c new file mode 100644 index 0000000..df4a6a0 --- /dev/null +++ b/day_5.c @@ -0,0 +1,20 @@ +// +// Created by lennart on 12/7/23. +// + +#include +#include +#include "map.h" + +int main() { + Map *map = map_create(); + + for(int i = 0; i < 10000; i++) { + map_put(map, i, i + 1); + } + for(int i = 1; i < 10000; i++) { + assert(map_get(map, i) == i + 1); + } + + map_free(map); +} diff --git a/map.c b/map.c new file mode 100644 index 0000000..bffa4bc --- /dev/null +++ b/map.c @@ -0,0 +1,142 @@ +// +// Created by lennart on 12/8/23. +// + +#include +#include +#include +#include +#include "map.h" + +#include + +// Load factor. Targets how much space is used under ideal conditions +#define LOAD_FACTOR 0.5 + +typedef struct MapNode_struct { + struct MapNode_struct *next; + int key; + int value; +} MapNode; + +struct _Map { + MapNode *nodes; + uint32_t size; + uint32_t capacity; +}; + +static uint32_t map_index(Map *map, int key); +static void map_set_node(Map *map, MapNode node); +static void map_ensure_capacity(Map *map); + +__inline Map* map_create() { + Map *map = malloc(sizeof (Map)); + map->size = 0; + map->capacity = 1 << 4; + map->nodes = calloc(sizeof (MapNode), map->capacity); + return map; +} + +void map_put(Map *map, int key, int value) { + map_ensure_capacity(map); + MapNode node; + node.key = key; + node.value = value; + node.next = NULL; + map_set_node(map, node); +} + +__inline int map_get(Map *map, int key) { + MapNode node = map->nodes[map_index(map, key)]; + int value = node.value; + MapNode *next = node.next; + while(__glibc_unlikely(next != NULL && (size_t) next != UINTPTR_MAX)) { + if(next->key == key) { + value = next->value; + break; + } + next = next->next; + } + return value; +} + +bool map_has(Map *map, int key) { + MapNode node = map->nodes[map_index(map, key)]; + bool value = node.next != NULL && node.key == key; + MapNode *next = node.next; + while(__glibc_unlikely(!value && next != NULL && (size_t) next != UINTPTR_MAX)) { + if(next->key == key) { + value = true; + } + next = next->next; + } + return value; +} + +void map_free(Map *map) { + for(int i = 0; i < map->capacity; i++) { + MapNode *next = map->nodes[i].next; + if(next != NULL) { + while((size_t) next != UINTPTR_MAX) { + MapNode *after = next->next; + free(next); + next = after; + } + } + } + free(map->nodes); + free(map); +} + +static __inline uint32_t map_index(Map *map, int key) { + return key & (map->capacity - 1); +} + +__inline void map_set_node(Map *map, MapNode node) { + MapNode *current = &map->nodes[map_index(map, node.key)]; + if(current->next == NULL || current->key == node.key) { + if(current->next == NULL) map->size++; + current->key = node.key; + current->value = node.value; + current->next = (MapNode*) UINTPTR_MAX; + } else { + while((size_t) current->next != UINTPTR_MAX) { + current = current->next; + if(current->key == node.key) break; + } + if(current->key == node.key) { + current->value = node.value; + } else { + MapNode *copy = malloc(sizeof (MapNode)); + *copy = node; + copy->next = (MapNode*) UINTPTR_MAX; + current->next = copy; + map->size++; + } + } +} + +__inline void map_ensure_capacity(Map *map) { + uint32_t capacity = map->capacity; + if(__glibc_unlikely(map->size >= capacity * LOAD_FACTOR)) { + map->capacity <<= 1; + map->size = 0; // Re-add all nodes + MapNode *nodes = map->nodes; + map->nodes = calloc(sizeof (MapNode), map->capacity); + for(int i = 0; i < capacity; i++) { + MapNode node = nodes[i]; + MapNode *next = node.next; + map_set_node(map, node); + if(next != NULL) { + while((size_t) next != UINTPTR_MAX) { + map_set_node(map, *next); + MapNode *after = next->next; + assert(after != NULL); + free(next); + next = after; + } + } + } + free(nodes); + } +} diff --git a/map.h b/map.h new file mode 100644 index 0000000..1cddc9d --- /dev/null +++ b/map.h @@ -0,0 +1,23 @@ +// +// Created by lennart on 12/8/23. +// + +#include + +#ifndef MAP_H + +struct _Map; +typedef struct _Map Map; + +Map* map_create(); + +void map_put(Map *map, int key, int value); + +int map_get(Map *map, int key); + +bool map_has(Map *map, int key); + +void map_free(Map *map); + +#define MAP_H +#endif //MAP_H