diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000000000000000000000000000000000000..d5459c5924e1a50da05683740f0501ed2aa22a29
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+tp_2_miso_dict.py
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index dc9ea4906e15825848ae951155a4381c08529eaf..db8786c06ed9719181cd25ebe2615cc99c8490eb 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
+  <component name="Black">
+    <option name="sdkName" value="Python 3.12" />
+  </component>
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" />
 </project>
\ No newline at end of file
diff --git a/.idea/tp2_hachage.iml b/.idea/tp2_hachage.iml
index 039314de6c082718b0c4495bd64f8df7279e477f..a1045faca8f1312bd08dc93f6b22ccacfb876b67 100644
--- a/.idea/tp2_hachage.iml
+++ b/.idea/tp2_hachage.iml
@@ -2,7 +2,7 @@
 <module type="PYTHON_MODULE" version="4">
   <component name="NewModuleRootManager">
     <content url="file://$MODULE_DIR$" />
-    <orderEntry type="inheritedJdk" />
+    <orderEntry type="jdk" jdkName="Python 3.12" jdkType="Python SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
   <component name="PyDocumentationSettings">
diff --git a/tp_2_miso_dict.py b/tp_2_miso_dict.py
index 2fb1d598541f695dfe1de06bd905325116c5ef6a..e5f8eb18019cc008dc2ab80d078c475c67ad8709 100644
--- a/tp_2_miso_dict.py
+++ b/tp_2_miso_dict.py
@@ -2,6 +2,7 @@ import matplotlib.pyplot as plt
 import numpy as np
 import time
 import sys
+import statistics  #pour faire la moyenne des temps d'insertion pour chaque facteur de charge
 
 
 
@@ -21,13 +22,38 @@ def experiment_load_factor(load_factors : list):
 		Les nombres de réallocations de mémoire
 		Les tailles de mémoire occupée par le dictionnaire pour chaque facteur de charge
 	"""
+	# Initialisation
 	insertion_times = []
 	num_resizes = []
 	sizes = []
+
 	for factor in load_factors :
 		dictio = {}
-	# num_elements = .......... QUESTION 2 PARTIE 2
-	return [],[],[]
+		num_resize=0
+		last_size = sys.getsizeof(dictio)
+		num_elements = int(factor*100)
+		tempsecoules = []
+
+		for i in range(num_elements) :
+			cle = 'cle'+str(i)
+			start_time = time.time()
+			dictio[cle] = i
+			end_time = time.time()
+			tempsecoule = end_time - start_time
+			tempsecoules.append(tempsecoule)
+			current_size = sys.getsizeof(dictio)
+
+			if current_size > last_size :
+				num_resize += 1
+				last_size = current_size
+
+		size = sys.getsizeof(dictio)
+		insertion_time = statistics.mean(tempsecoules)
+		insertion_times.append(insertion_time)
+		num_resizes.append(num_resize)
+		sizes.append(size)
+
+	return insertion_times, num_resizes, sizes
 
 def experiment_longest():
 	"""
@@ -50,24 +76,42 @@ def visualisation(load_factors, insertion_times, num_resizes, sizes, frequencies
 	"""
 	Visualisation des résultats
 	"""
+	num_elements = []
+	for factor in load_factors :
+		num_elements.append(factor*100)
 	# Temps d'insertion en fonction du facteur de charge
-
+	plt.plot(load_factors, insertion_times)
+	plt.xlabel('Facteur de charge')
+	plt.xticks(load_factors, [str(x) for x in load_factors], rotation=45)
+	plt.ylabel("Temps d'insertion (secondes)")
+	plt.title("Temps d'insertion en fonction du facteur de charge")
+	plt.savefig("temps_d_insertion.png")
 	# Nombre de réallocations de mémoire en fonction du facteur de charge
-	
+	plt.plot(load_factors, num_resizes)
+	plt.xlabel('Facteur de charge')
+	plt.xticks(load_factors, [str(x) for x in load_factors], rotation=45)
+	plt.ylabel("Nombre de réallocations de mémoire")
+	plt.title("Nombre de réallocations de mémoire en fonction du facteur de charge")
+	plt.savefig("nombre_reallocations.png")
 	# Taille de mémoire occupée en fonction du nombre d'éléments
-	
+	plt.plot(sizes, num_elements)
+	plt.xlabel("Nombre d'éléments")
+	plt.xticks(num_elements, [str(x) for x in num_elements], rotation=45)
+	plt.ylabel("Taille de mémoire occupée (octets)")
+	plt.title("Taille de mémoire occupée en fonction du nombre d'éléments")
+	plt.savefig("taille_memoire.png")
 	# Deuxième étude
-	f = list()
+	f = list(frequencies)
 	plt.figure(figsize=(10, 6))
 	plt.bar(range(len(f)), f)
 	plt.xlabel('Temps d\'insertion (s)')
 	plt.ylabel('Fréquence')
 	plt.title('Histogramme des fréquences des temps d\'insertions')
 	plt.yscale('log')
-	xticks = np.logspace(-6, 1, 3)  
-	xtick_labels = [f'{x:.1e}' for x in xticks]  
-	plt.xticks(xticks, xtick_labels)    
-	plt.savefig('histogramme.png')
+	xticks = np.logspace(-6, 1, 3)
+	xtick_labels = [f'{x:.1e}' for x in xticks]
+	plt.xticks(xticks, xtick_labels)
+	plt.savefig('deuxieme_etude.png')
 
 load_factors = [0.01, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
 insertion_times, num_resizes, sizes = experiment_load_factor(load_factors)
diff --git a/tp_2_miso_mphf.py b/tp_2_miso_mphf.py
index 3aee1c40ac8708692f56e988965a85ce36f39a7f..37c883388f2a6c34e33421695d9feef3c17416b1 100644
--- a/tp_2_miso_mphf.py
+++ b/tp_2_miso_mphf.py
@@ -8,8 +8,7 @@ import random
 ###### PARTIE 1 ######
 
 def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3):
-	
-	"""
+    """
 	Construit une fonction de hachage minimale parfaite (MPHF) pour un ensemble de k-mers.
 
 	Parameters:
@@ -32,76 +31,76 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3):
 	>>> len(mphf) == n
 	True
 	"""
-	# Initialisation
-	set_kmer_courant = set_kmer.copy()
-	tableaux = []
-	collision = set()
-	for _ in range(nb_niveaux):
-		if len(set_kmer_courant) > 0:
-			l = len(set_kmer_courant)
-			if l==0 :
-				break #Evite une division par 0
-			tableau_principal = [-1] * (gamma * l)
-			for kmer in set_kmer_courant:
-				# hacher le k-mer (attention, hash() peut rendre des entiers signés, nous voulons des entiers positifs)
-				hachage = abs(hash(kmer))
-				# récupérer l'adresse
-				# si le tableau principal est déjà rempli à l'adresse:
-					# mettre le kmer dans collision()
-					# sinon, écrire le hash à l'adresse dans le tableau principal
-				adresse = hachage % (gamma * l)
-				if tableau_principal[adresse] != -1:
-					collision.add(kmer)
-				else:
-					tableau_principal[adresse] = hachage
-			tableaux.append(tableau_principal) # expliquer
-			# Chaque niveau de hachage produit un nouveau tableau de hachage.
-			# Donc on enregistre le tableau dans tableaux pour garder une trace des niveaux.
-			set_kmer_courant = collision.copy() # expliquer
-			# On hache à nouveau les k-mers qui ont causé des collisions.
-			collision = set() # expliquer
-			# On réinitialise collision pour le prochain niveau de hachage, pour pas que les valeurs dont on n'a plus besoin s'accumulent.
-			if not set_kmer_courant:  # Arrête la boucle si plus de collisions
-				break
-
-	# Construction de la MPHF
-	mphf = [] 
-	grand_tableau = []
-	for tableau in tableaux:
-		grand_tableau.extend(tableau) # expliquer
-	# Après avoir fait tous les hachages, on regroupe les tableaux finaux de hachage dans un seul tableau.
-	grand_tableau_dict = {val: i for i, val in enumerate(grand_tableau)}
-
-	max_rang = 0
-	i = 0
-	for kmer in set_kmer:
-		# hacher le kmer
-		hache = abs(hash(kmer))
-		# si le hash est dans le grand_tableau
-			# récupérer son index
-			# récupérer son rang (utiliser la fonction count())
-			# ajouter à la mphf [h, rang]
-			# mettre à jour max_rang
-		if hache in grand_tableau_dict :
-			index = grand_tableau_dict[hache]
-			rang = grand_tableau[:index].count(hache)
-			mphf.append([hache, rang])
-			max_rang = max(max_rang, rang)
-
-	for kmer in set_kmer_courant: #gestion des collisions: expliquer les 3 lignes du dessous
-		max_rang += 1 # On attribue un nouveau rang unique à chaque élément en collision.
-		h = abs(hash(kmer)) # Recalcul du hash, on veut uniquement des entiers positifs.
-		mphf.append([h, max_rang])  # On ajoute le k-mer à mphf
-		# On fait ces étapes car les collisions n'ont pas pu être placées avant,
-		#  on leur attribue un rang plus grand pour ne pas perturber l'ordre précédent
-	if not mphf:
-		print("⚠️ Attention : MPHF vide, vérifiez les données en entrée.")
-
-	return mphf
+    # Initialisation
+    set_kmer_courant = set_kmer.copy()
+    tableaux = []
+    collision = set()
+    for _ in range(nb_niveaux):
+        if len(set_kmer_courant) > 0:
+            l = len(set_kmer_courant)
+            if l == 0:
+                break  # Evite une division par 0
+            tableau_principal = [-1] * (gamma * l)
+            for kmer in set_kmer_courant:
+                # hacher le k-mer (attention, hash() peut rendre des entiers signés, nous voulons des entiers positifs)
+                hachage = abs(hash(kmer))
+                # récupérer l'adresse
+                # si le tableau principal est déjà rempli à l'adresse:
+                # mettre le kmer dans collision()
+                # sinon, écrire le hash à l'adresse dans le tableau principal
+                adresse = hachage % (gamma * l)
+                if tableau_principal[adresse] != -1:
+                    collision.add(kmer)
+                else:
+                    tableau_principal[adresse] = hachage
+            tableaux.append(tableau_principal)  # expliquer
+            # Chaque niveau de hachage produit un nouveau tableau de hachage.
+            # Donc on enregistre le tableau dans tableaux pour garder une trace des niveaux.
+            set_kmer_courant = collision.copy()  # expliquer
+            # On hache à nouveau les k-mers qui ont causé des collisions.
+            collision = set()  # expliquer
+            # On réinitialise collision pour le prochain niveau de hachage, pour pas que les valeurs dont on n'a plus besoin s'accumulent.
+            if not set_kmer_courant:  # Arrête la boucle si plus de collisions
+                break
+
+    # Construction de la MPHF
+    mphf = []
+    grand_tableau = []
+    for tableau in tableaux:
+        grand_tableau.extend(tableau)  # expliquer
+    # Après avoir fait tous les hachages, on regroupe les tableaux finaux de hachage dans un seul tableau.
+    grand_tableau_dict = {val: i for i, val in enumerate(grand_tableau)}
+
+    max_rang = 0
+    i = 0
+    for kmer in set_kmer:
+        # hacher le kmer
+        hache = abs(hash(kmer))
+        # si le hash est dans le grand_tableau
+        # récupérer son index
+        # récupérer son rang (utiliser la fonction count())
+        # ajouter à la mphf [h, rang]
+        # mettre à jour max_rang
+        if hache in grand_tableau_dict:
+            index = grand_tableau_dict[hache]
+            rang = grand_tableau[:index].count(hache)
+            mphf.append([hache, rang])
+            max_rang = max(max_rang, rang)
+
+    for kmer in set_kmer_courant:  # gestion des collisions: expliquer les 3 lignes du dessous
+        max_rang += 1  # On attribue un nouveau rang unique à chaque élément en collision.
+        h = abs(hash(kmer))  # Recalcul du hash, on veut uniquement des entiers positifs.
+        mphf.append([h, max_rang])  # On ajoute le k-mer à mphf
+    # On fait ces étapes car les collisions n'ont pas pu être placées avant,
+    #  on leur attribue un rang plus grand pour ne pas perturber l'ordre précédent
+    if not mphf:
+        print("Attention : MPHF vide, vérifiez les données en entrée.")
+
+    return mphf
 
 
 def get_hash_mphf(mphf, kmer):
-	"""
+    """
 	Calcule le hash d'un k-mer à l'aide d'une fonction de hachage minimale parfaite (MPHF).
 
 	Parameters:
@@ -120,15 +119,15 @@ def get_hash_mphf(mphf, kmer):
 	>>> 0 <= hash_mphf < n
 	True
 	"""
-	hache = abs(hash(kmer))
-	for h, rang in mphf :
-		if h == hache :
-			return rang
-	return -1
+    hache = abs(hash(kmer))
+    for h, rang in mphf:
+        if h == hache:
+            return rang
+    return -1
 
 
 def create_hash_table(set_kmer, n):
-	"""
+    """
 	Crée une table de hachage à partir d'un ensemble de k-mers et d'une mphf
 
 	Parameters:
@@ -148,59 +147,61 @@ def create_hash_table(set_kmer, n):
 	>>> all(kmer in tableau for kmer in set_kmer)
 	True
 	"""
-	mphf = construction_mphf(set_kmer, n)   # créer la mphf pour les kmers
-	# initialiser un tableau de taille n (une liste)
-	tableau = [None]*n
-	# écrire les kmers aux adresses du tableau données par la mphf
-	for kmer in set_kmer :
-		adresse = get_hash_mphf(mphf, kmer)
-		if adresse == -1:
-			print(f"Erreur : Impossible de trouver l'adresse pour {kmer} (MPHF renvoie -1)")
-			continue
-		if 0 <= adresse < n:
-			tableau[adresse]=kmer
-	return tableau, mphf # retourner le tableau et la mphf
+    mphf = construction_mphf(set_kmer, n)  # créer la mphf pour les kmers
+    # initialiser un tableau de taille n (une liste)
+    tableau = [None] * n
+    # écrire les kmers aux adresses du tableau données par la mphf
+    for kmer in set_kmer:
+        adresse = get_hash_mphf(mphf, kmer)
+        if adresse == -1:
+            print(f"Erreur : Impossible de trouver l'adresse pour {kmer} (MPHF renvoie -1)")
+            continue
+        if 0 <= adresse < n:
+            tableau[adresse] = kmer
+    return tableau, mphf  # retourner le tableau et la mphf
 
 
 def generer_kmers(n, k):
-	'''
+    '''
 	genere un set de n k-mers
 	'''
-	kmers = set()
-	while len(kmers) < n:
-		kmer = ''.join(random.choice('ATCG') for _ in range(k))
-		kmers.add(kmer)
-	return kmers
+    kmers = set()
+    while len(kmers) < n:
+        kmer = ''.join(random.choice('ATCG') for _ in range(k))
+        kmers.add(kmer)
+    return kmers
 
 
 def compare_taille(n_max, fichier_sortie):
-	n_values = []
-	table_size = []
-	dict_size = []
-	k = 21
-	
-	for n in range(100, n_max, 1000):
-		set_kmer = generer_kmers(n, k)
-		tableau, mphf = create_hash_table(set_kmer, n)
-
-		n_values.append(n)
-		table_size.append(sys.getsizeof(tableau)+sys.getsizeof(mphf)) # pourquoi ici on ne mesure pas juste la taille en mémoire du tableau ?
-		#Car sys.getsizeof(tableau) ne mesure que la liste elle-même, pas les objets stockés dedans.
-		# On veut mesurer la mémoire totale du système de hachage, pas seulement la liste.
-		dict_size.append(sys.getsizeof(set_kmer))
-
-	plt.plot(n_values, table_size, label='Table avec MPHF')
-	plt.plot(n_values, dict_size, label='Dict')
-	plt.xlabel('n')
-	plt.xticks(n_values, [str(x) for x in n_values], rotation=45)
-	plt.ylabel('Taille (octets)')
-	plt.title('Évolution de la taille de la table de hachage avec MPHF et du dict')
-	plt.legend()
-	plt.savefig(fichier_sortie)
-	plt.close()
+    n_values = []
+    table_size = []
+    dict_size = []
+    k = 21
+
+    for n in range(100, n_max, 1000):
+        set_kmer = generer_kmers(n, k)
+        tableau, mphf = create_hash_table(set_kmer, n)
+
+        n_values.append(n)
+        table_size.append(sys.getsizeof(tableau) + sys.getsizeof(
+            mphf))  # pourquoi ici on ne mesure pas juste la taille en mémoire du tableau ?
+        # Car sys.getsizeof(tableau) ne mesure que la liste elle-même, pas les objets stockés dedans.
+        # On veut mesurer la mémoire totale du système de hachage, pas seulement la liste.
+        dict_size.append(sys.getsizeof(set_kmer))
+
+    plt.plot(n_values, table_size, label='Table avec MPHF')
+    plt.plot(n_values, dict_size, label='Dict')
+    plt.xlabel('n')
+    plt.xticks(n_values, [str(x) for x in n_values], rotation=45)
+    plt.ylabel('Taille (octets)')
+    plt.title('Évolution de la taille de la table de hachage avec MPHF et du dict')
+    plt.legend()
+    plt.savefig(fichier_sortie)
+    plt.close()
+
 
 # dé-commenter quand vous êtes prêts, expliquer les résultats
-compare_taille(10000,"mphf.png")
+compare_taille(10000, "mphf.png")
 
 # Sur le graphe obtenu, on observe que la taille de la table de hachage du dictionnaire augmente par paliers,
 # alors que celle de la MPHF augmente de manière linéaire, et beaucoup plus progressivement.