diff --git a/hashtable.c b/hashtable.c
index 23c17ce8631fc88901aed4c43ff0ac2f7e458a2c..7e2c0dd9c5ef9d6a94b36e894d66dafc4419a3ea 100644
--- a/hashtable.c
+++ b/hashtable.c
@@ -8,41 +8,156 @@
 #include <stdlib.h>
 #include <string.h>
 
+int hash(char *key, int64_t length) {
+    // If the size of the int is too low the hash methods will generate overflow errors
+    int64_t val = 0;
+    for (size_t i = 0; i < strlen(key); i++) {
+        val = 43 * val + key[i];
+    }
+    return (val % length);
+}
+
+entry *entry_create_empty() {
+    entry *e = malloc(sizeof(entry));
+    e->key = NULL;
+    e->value = NULL;
+    e->next = NULL;
+    return e;
+}
+
 hm *hm_create(unsigned int length) {
     hm *hashmap = malloc(sizeof(hm));
     hashmap->length = length;
     hashmap->entries = malloc(sizeof(entry) * length);
-    for (int i = 0; i < length; i++) {
-        hashmap->entries[i] = malloc(sizeof(entry));
+    for (size_t i = 0; i < length; i++) {
+        hashmap->entries[i] = entry_create_empty();
     }
 
     return hashmap;
 }
 
+entry *get_entry_by_key(entry *e, char *key) {
+    if (e->key == key) {
+        return e;
+    } else if (e->next != NULL) {
+        return get_entry_by_key(e->next, key);
+    } else {
+        return e;
+    }
+}
+
 void hm_destroy(hm **hm) {
     for (int i = 0; i < (*hm)->length; i++) {
-        free((*hm)->entries[i]);
+        entry *e = (*hm)->entries[i];
+        while (e != NULL) {
+            entry *to_free = e;
+            e = e->next;
+            free(to_free);
+        }
     }
     free((*hm)->entries);
     free((*hm));
+    (*hm) = NULL;
 }
 
 hm *hm_set(hm *hm, const char *const key, const char *const value) {
-    return NULL;
+    // Hash the key and get the corresponding entry
+    int key_index = hash((char *)key, hm->length);
+    entry *e = get_entry_by_key(hm->entries[key_index], (char *)key);
+
+    // Set the key and create the next entry if the key is not existing
+    if (e->key != key) {
+        e->key = (char *)key;
+        if (e->next == NULL) {
+            e->next = entry_create_empty();
+        }
+    }
+
+    // Set the entry value and return the hashmap
+    e->value = (char *)value;
+    return hm;
 }
 
 char *hm_get(const hm *const hm, const char *const key) {
-    return NULL;
+    int key_index = hash((char *)key, hm->length);
+    char *c = get_entry_by_key(hm->entries[key_index], (char *)key)->value;
+    return c;
 }
 
 char *hm_rm(hm *hm, const char *const key) {
-    return NULL;
+    int key_index = hash((char *)key, hm->length);
+    entry *e = get_entry_by_key(hm->entries[key_index], (char *)key);
+    entry *previous_entry = NULL;
+    entry *current_entry = hm->entries[key_index];
+    int entry_index = 0;
+
+    while (current_entry != e) {
+        previous_entry = current_entry;
+        current_entry = current_entry->next;
+        entry_index++;
+    }
+
+    if (entry_index == 0) {
+        hm->entries[key_index] = hm->entries[key_index]->next;
+    } else if (previous_entry != NULL) {
+        previous_entry->next = e->next;
+    }
+
+    char *entry_key = e->key;
+    free(e);
+    e = NULL;
+    return entry_key;
+}
+
+int get_entry_list_size(entry *e) {
+    int size = 0;
+    size += sizeof(e->key) + sizeof(e->value) + 16;
+    if (e->next != NULL) {
+        size += get_entry_list_size(e->next);
+    }
+    return size;
 }
 
-char *hmo_str(const hm *const hm) {
-    return NULL;
+char *hm_to_str(const hm *const hm) {
+    int str_size = sizeof(hm) * hm->length;
+    for (int i = 0; i < hm->length; i++) {
+        str_size += get_entry_list_size(hm->entries[i]);
+    }
+
+    char *hm_str = malloc(str_size);
+    // Ensure that the string is empty before doing anything
+    hm_str[0] = '\0';
+
+    strcat(hm_str, "[\n");
+    for (int i = 0; i < hm->length; i++) {
+        strcat(hm_str, "    [\n");
+        entry *e = hm->entries[i];
+        while (e != NULL && e->key != NULL) {
+            strcat(hm_str, "        [\"");
+            strcat(hm_str, e->key);
+            strcat(hm_str, "\": \"");
+            strcat(hm_str, e->value);
+            strcat(hm_str, "\"]");
+            if (e->next != NULL && e->next->key != NULL) {
+                strcat(hm_str, ",");
+            }
+            strcat(hm_str, "\n");
+            e = e->next;
+        }
+
+        strcat(hm_str, "    ]");
+        if (i < hm->length - 1) {
+            strcat(hm_str, ",");
+        }
+        strcat(hm_str, "\n");
+    }
+
+    strcat(hm_str, "]\n");
+    return hm_str;
 }
 
 void hm_print(const hm *const hm) {
-    return NULL;
+    char *str = hm_to_str(hm);
+    printf("%s\n", str);
+    free(str);
 }
diff --git a/main.c b/main.c
index 09ae288928dd80d4db07b75589fe999f4b0ccdad..7a4af81ce300ddccc7eeb8deb94d5e7d87c4e0a4 100644
--- a/main.c
+++ b/main.c
@@ -9,6 +9,37 @@
 
 int main() {
     hm *hashmap = hm_create(10);
+    hm_set(hashmap, "Key1", "Value1");
+    hm_set(hashmap, "Key2", "Value1");
+    hm_set(hashmap, "Key1", "Value2");
+    hm_set(hashmap, "Key3", "Value1");
+    hm_set(hashmap, "Key4", "FOUR");
+    hm_set(hashmap, "Key1", "Value3");
+    hm_set(hashmap, "Key5", "I think it's good now");
+    hm_set(hashmap, "Key6", "6");
+    hm_set(hashmap, "Key7", "7");
+    hm_set(hashmap, "Key8", "8");
+    hm_set(hashmap, "Key9", "9");
+    hm_set(hashmap, "Key27", "MORE ?");
+    hm_set(hashmap, "Key10", "Is this the end ?");
+
+    printf("Value of %s : %s\n", "Key1", hm_get(hashmap, "Key1"));
+    printf("Value of %s : %s\n", "Key2", hm_get(hashmap, "Key2"));
+    printf("Value of %s : %s\n", "Key3", hm_get(hashmap, "Key3"));
+    printf("Value of %s : %s\n", "Key4", hm_get(hashmap, "Key4"));
+    printf("Value of %s : %s\n", "Key5", hm_get(hashmap, "Key5"));
+    printf("Value of %s : %s\n", "Key6", hm_get(hashmap, "Key6"));
+    printf("Value of %s : %s\n", "Key7", hm_get(hashmap, "Key7"));
+    printf("Value of %s : %s\n", "Key8", hm_get(hashmap, "Key8"));
+    printf("Value of %s : %s\n", "Key9", hm_get(hashmap, "Key9"));
+    printf("Value of %s : %s\n", "Key10", hm_get(hashmap, "Key10"));
+
+    hm_print(hashmap);
+    hm_rm(hashmap, "Key1");
+    hm_print(hashmap);
+    hm_rm(hashmap, "Key10");
+    hm_print(hashmap);
+
     hm_destroy(&hashmap);
 
     return EXIT_SUCCESS;