feat: add int map implementation

This commit is contained in:
2023-12-08 04:00:29 +01:00
parent 14dc992bbc
commit b203c93f47
5 changed files with 189 additions and 2 deletions

View File

@@ -23,3 +23,5 @@ 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)
add_executable(day_05 day_5.c input_handler.c map.c)

View File

@@ -120,6 +120,6 @@ CardList* load_cards(const char *file_name) {
clist_add(list, card);
}
free(buffer);
// free(buffer);
return list;
}

20
day_5.c Normal file
View File

@@ -0,0 +1,20 @@
//
// Created by lennart on 12/7/23.
//
#include <stdio.h>
#include <assert.h>
#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);
}

142
map.c Normal file
View File

@@ -0,0 +1,142 @@
//
// Created by lennart on 12/8/23.
//
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
#include "map.h"
#include <stdlib.h>
// 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);
}
}

23
map.h Normal file
View File

@@ -0,0 +1,23 @@
//
// Created by lennart on 12/8/23.
//
#include <stdbool.h>
#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