diff --git a/ex2/ex2.c b/ex2/ex2.c
index 555c0ef7e90a6a783d61f1b3ba8369bf0b91d1f4..7456deb7f1350b9879e8f00c298c29cb95bd4a65 100644
--- a/ex2/ex2.c
+++ b/ex2/ex2.c
@@ -16,30 +16,138 @@
 #include <stdlib.h>
 #include <string.h>
 
+typedef struct Entry {
+    char *key;
+    double value;
+} Entry;
+
+typedef struct Vector {
+    int capacity;
+    int length;
+    Entry **items;
+} Vector;
+
+typedef struct HashMap {
+    int length;
+    Vector **entries;
+} HashMap;
+
+int hash(char key[4], int length) {
+    int index = 0;
+    for (int i = 0; i < 4; ++i) {
+        index = (43 * index + key[i]) % length;
+    }
+    return index;
+}
+
+Entry *entry_init(char *key, double value) {
+    Entry *e = (Entry *)malloc(sizeof(Entry));
+    e->key = key;
+    e->value = value;
+    return e;
+}
+
+void entry_destroy(Entry *e) {
+    free(e);
+}
+
+Vector *vector_init(int capacity) {
+    Vector *v = (Vector *)malloc(sizeof(Vector));
+    v->capacity = capacity;
+    v->length = 0;
+    v->items = (Entry **)malloc(sizeof(Entry *) * v->capacity);
+    return v;
+}
+
+void vector_destroy(Vector *v) {
+    for (int i = 0; i < v->length; i += 1) {
+        entry_destroy(v->items[i]);
+    }
+
+    free(v->items);
+    free(v);
+}
+
+void vector_push(Vector *v, Entry *e) {
+    v->items[v->length] = e;
+    v->length += 1;
+}
+
+void vector_print(Vector *v) {
+    for (int i = 0; i < v->length; i += 1) {
+        printf("(%s, %.1lf)", v->items[i]->key, v->items[i]->value);
+
+        if (i < v->length - 1) {
+            printf(", ");
+        }
+    }
+}
+
+HashMap *hash_map_init(int length) {
+    HashMap *dict = (HashMap *)malloc(sizeof(HashMap));
+    dict->length = length;
+    dict->entries = (Vector **)malloc(sizeof(Vector *) * dict->length);
+
+    for (int i = 0; i < length; i += 1) {
+        dict->entries[i] = vector_init(100);
+    }
+
+    return dict;
+}
+
+void hash_map_destroy(HashMap *dict) {
+    for (int i = 0; i < dict->length; i += 1) {
+        vector_destroy(dict->entries[i]);
+    }
+
+    free(dict->entries);
+    free(dict);
+}
+
+void hash_map_insert(HashMap *dict, char *key, double value) {
+    int index = hash(key, dict->length);
+    Vector *v = dict->entries[index];
+
+    for (int i = 0; i < v->length; i += 1) {
+        if (strcmp(v->items[i]->key, key) == 0) {
+            v->items[i]->value = value;
+            return;
+        }
+    }
+
+    // string copy
+    Entry *e = entry_init(key, value);
+    vector_push(v, e);
+}
+
+void hash_map_print(HashMap *dict) {
+    for (int i = 0; i < dict->length; i += 1) {
+        printf("%d: ", i);
+        vector_print(dict->entries[i]);
+        printf("\n");
+    }
+}
+
 int main() {
-    // int32_t values_length = 5;
-    // double values[values_length];
-
-    // for (int32_t i = 0; i < values_length; i += 1) {
-    //     double value;
-    //     scanf("%lf", &value);
-    //     values[i] = value;
-    // }
-
-    // int32_t values_length = 5;
-    // int32_t values[values_length];
-
-    // for (int32_t i = 0; i < values_length; i += 1) {
-    //     int32_t value;
-    //     scanf("%d", &value);
-    //     values[i] = value;
-    // }
-
-    // char a[100];
-    // int32_t b;
-    // scanf("%s %d", a, &b);
-    // printf("%s %d\n", a, b);
-
-    printf("ex1\n");
+    HashMap *dict = hash_map_init(10);
+    hash_map_insert(dict, "ajku", 1.1);
+    hash_map_insert(dict, "ajkv", 2.2);
+    hash_map_insert(dict, "ajkw", 3.1);
+    hash_map_insert(dict, "ajkx", 4.2);
+    hash_map_insert(dict, "ajky", 5.7);
+    hash_map_insert(dict, "ajkz", 6.1);
+    hash_map_insert(dict, "ajka", 1.8);
+    hash_map_insert(dict, "ajkb", 2.7);
+    hash_map_insert(dict, "ajkc", 3.6);
+    hash_map_insert(dict, "bjkd", 1.9);
+    hash_map_print(dict);
+
+    hash_map_insert(dict, "ajkt", 0.1);
+    hash_map_insert(dict, "ajku", 9.1);
+    hash_map_insert(dict, "ajkx", 2.9);
+    printf("\n");
+    hash_map_print(dict);
+
+    hash_map_destroy(dict);
     return EXIT_SUCCESS;
 }