feat: add int map implementation
This commit is contained in:
@@ -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)
|
||||
2
day_4.c
2
day_4.c
@@ -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
20
day_5.c
Normal 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
142
map.c
Normal 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
23
map.h
Normal 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
|
||||
Reference in New Issue
Block a user