diff --git a/README.md b/README.md
index 74f925a..64037a2 100644
--- a/README.md
+++ b/README.md
@@ -57,7 +57,11 @@ Mesurez combien de temps prend python à générer un tableau composés de :
Sur un tableur, générez un tableau permettant de visualiser le temps d'éxécution en fonction de la taille de l'entrée.
-Comment vous semble évoluer la courbe ? Observez bien les différentes courbes du graphique ci-dessous. Quelle est la plus ressemblante à notre situation ? *Écrivez votre réponse ici*
+Comment vous semble évoluer la courbe ? Observez bien les différentes courbes du graphique ci-dessous. Quelle est la plus ressemblante à notre situation ?
+
+Le temps de géneration de nombres aléatoire évolut de façon linéaire -> O(n) (résulats des tests dans le fichier `sort/range.py`)
+
+
@@ -75,7 +79,13 @@ Observez attentivement l'animation de tri par sélection ci-dessous pour en comp
-Écrivez en français classique ce que vous voyez. Quel est le fonctionnement ? Comment l'expliqueriez-vous à quelqu'un ? *Écrivez votre réponse ici*
+Écrivez en français classique ce que vous voyez. Quel est le fonctionnement ? Comment l'expliqueriez-vous à quelqu'un ?
+
+1: On parcourt le tableau et on note le nombre le plus petit
+2: Une fois le tableau parcourut on déplace le nombre le plus petit au début du tableau
+3: On reparcourt le tableau en partant de la deuxième entrée du tableau et on note le nombre le plus petit
+4: Une fois le tableau parcourut on déplace le nombre le plus petit à la deuxième case de tableau
+5: On repète se processus autant de fois qu'il y a de cases dans le tableau
Puis implémentez l'algorithme en python dans la fonction `sort` du fichier `sort/selection.py`. Vérifiez son bon fonctionnement en éxécutant le fichier `python3 -m unittest`. Le test correspondant au tri par sélection doit passer.
@@ -88,7 +98,11 @@ Mesurez le temps d'éxécution pour un tableau de :
Tracez le graphique correspondant.
-Quelle semble être la complexité de notre fonction de tri ? Cela est-il logique par rapport au code que vous avez implémenté ? *Écrivez votre réponse ici*
+Quelle semble être la complexité de notre fonction de tri ? Cela est-il logique par rapport au code que vous avez implémenté ?
+
+L'algorithme semble etre de compléxité O(n²) car quand on double le nomdre d'entrées, le temps d'éxecution est multiplié par 4
+
+
### 2. Tri par insertion
@@ -96,7 +110,16 @@ Observez attentivement l'animation de tri par insertion ci-dessous pour en compr
-Écrivez en français classique ce que vous voyez. Quel est le fonctionnement ? Comment l'expliqueriez-vous à quelqu'un ? *Écrivez votre réponse ici*
+Écrivez en français classique ce que vous voyez. Quel est le fonctionnement ? Comment l'expliqueriez-vous à quelqu'un ?
+
+1: On selectionne le premier nombre et on va considérer qu'il se trouve dans une partie du tableau qui est trié
+
+2: On prends le deuxième nome et on va le comparer avec le premier nombre, si il est plus petit on va le placer avant le premier, sinon on le place en deuxième. Maintenant la partie trié de tableau est de taille 2
+
+3: On prends le troisème nombre, on le compare avec le deuxième, si il est plus petit on le compare au premier, on le place en fonction et
+notre tableau trié contient maintenant 3 nombres
+
+4: On répete ces opérations pour tout les nombre du tableau
Puis implémentez l'algorithme en python dans la fonction `sort` du fichier `sort/insertion.py`. Utilisez les tests automatiques pour vérifier votre implémentation.
@@ -109,7 +132,11 @@ Mesurez le temps d'éxécution pour un tableau de :
Tracez le graphique correspondant.
-Quelle semble être la complexité de notre fonction de tri ? Cela est-il logique par rapport au code que vous avez implémenté ? *Écrivez votre réponse ici*
+Quelle semble être la complexité de notre fonction de tri ? Cela est-il logique par rapport au code que vous avez implémenté ?
+
+Le début du graphique resemble à la courbe du tri par selection, donc un O(n²) mais elle semble progrésser plus lentement ensuite pour ressembler un peu plus à un O(n*log(n))
+
+
### 3. Tri par fusion
@@ -154,7 +181,11 @@ Observez bien le schéma suivant : il représente le concept du tri par fusion.
Cet algorithme est de type "diviser pour régner".
-Écrivez en français classique ce que vous voyez. Quel est le fonctionnement ? Comment l'expliqueriez-vous à quelqu'un ? *Écrivez votre réponse ici*
+Écrivez en français classique ce que vous voyez. Quel est le fonctionnement ? Comment l'expliqueriez-vous à quelqu'un ?
+
+1: On divise le tableau, autant de fois que nécessaire afin d'arriver avec des morceaux de taille 1
+2: On compare les morceaux de taille 1 et on les concatène dans l'ordre croissant, on obtient des morceaux de taille 2 (et 1 morceau de taille 1 si la taille du tableau est impaire)
+3: On fusion les tableaux en placant les nombres dans l'orde croissant on répète cette étape jusquà avoir fusion tout les morceaux en un seul
Complétez la fonction `sort` du fichier `sort/fusion.py` en suivant les instructions suivantes.
@@ -174,15 +205,26 @@ Mesurez le temps d'éxécution pour un tableau de :
Tracez le graphique correspondant.
-Quelle semble être la complexité de notre fonction de tri ? Cela est-il logique par rapport au code que vous avez implémenté ? *Écrivez votre réponse ici*
+Quelle semble être la complexité de notre fonction de tri ? Cela est-il logique par rapport au code que vous avez implémenté ?
+
+La compléxité semble être O(n*log(n))
+
+
-Question bonus : Y a-t-il des tailles de tableaux pour lesquelles le tri par fusion n'est pas aussi rapide que les précédents tris abordés ? *Écrivez votre réponse ici*
+Question bonus : Y a-t-il des tailles de tableaux pour lesquelles le tri par fusion n'est pas aussi rapide que les précédents tris abordés ?
+
+Lors de mes tests, le tri par fusion a été le plus rapide peut importe la taille des données
### 4. sort()
Bien que tout cela soit fascinant, Python possède sa propre méthode de tri : `sort()`.
-Une dernière fois, analysez le temps d'exécution et découvrez si python fait mieux que nos implémentations rudimentaires ;)
+Une dernière fois, analysez le temps d'exécution et découvrez si python fait mieux que nos implémentations rudimentaires ;
+
+La fonction sort de python est largement plus rapide, en moyenne 100x plus rapide
+
+
+
## Pour rendre ce TP
diff --git a/__main__.py b/__main__.py
index 98a585e..e76fc9b 100644
--- a/__main__.py
+++ b/__main__.py
@@ -1,5 +1,52 @@
+from sort.range import generate_array_of_number
+from sort.insertion import sort as insertion_sort
+from sort.selection import sort as selection_sort
+from sort.fusion import sort as fusion_sort
+from sort.recursion import get_factorial
+import time
+
+
def main():
- print("Hello world")
+ for sample_size in range(0, 10_000_000, 1_000_000):
+ start: float = time.time()
+ sample: list[int] = generate_array_of_number(sample_size)
+ end: float = time.time()
+ print(f"Génération de {sample_size} nombres aléatoires en \
+ {end-start:.2f}s")
+
+ for sample_size in range(1_000, 11_000, 1_000):
+ sample: list[int] = generate_array_of_number(sample_size)
+ start: float = time.time()
+ sorted_sample: list[int] = selection_sort(sample)
+ end: float = time.time()
+ print(f"Tri par selection: taille tableau={sample_size}, \
+ temps={end-start}s")
+
+ for sample_size in range(1_000, 11_000, 1_000):
+ sample: list[int] = generate_array_of_number(sample_size)
+ start: float = time.time()
+ sorted_sample: list[int] = insertion_sort(sample)
+ end: float = time.time()
+ print(f"Tri par insertion: taille tableau={sample_size}, \
+ temps={end-start}s")
+
+ # print(get_factorial(5))
+
+ for sample_size in range(1_000, 11_000, 1_000):
+ sample: list[int] = generate_array_of_number(sample_size)
+ start: float = time.time()
+ sorted_sample: list[int] = fusion_sort(sample)
+ end: float = time.time()
+ print(f"Tri par fusion: taille tableau={sample_size}, \
+ temps={end-start}s")
+
+ for sample_size in range(100_000, 1_100_000, 100_000):
+ sample: list[int] = generate_array_of_number(sample_size)
+ start: float = time.time()
+ sample.sort()
+ end: float = time.time()
+ print(f"Tri Python: taille tableau={sample_size}, \
+ temps={end-start}s")
main()
diff --git a/img/graph_generation_nombres_aleatoires.PNG b/img/graph_generation_nombres_aleatoires.PNG
new file mode 100644
index 0000000..409f05e
Binary files /dev/null and b/img/graph_generation_nombres_aleatoires.PNG differ
diff --git a/img/graph_python_sort.PNG b/img/graph_python_sort.PNG
new file mode 100644
index 0000000..a8dbb4b
Binary files /dev/null and b/img/graph_python_sort.PNG differ
diff --git a/img/graph_tri_par_fusion.PNG b/img/graph_tri_par_fusion.PNG
new file mode 100644
index 0000000..3d8f1ed
Binary files /dev/null and b/img/graph_tri_par_fusion.PNG differ
diff --git a/img/graph_tri_par_insertion.PNG b/img/graph_tri_par_insertion.PNG
new file mode 100644
index 0000000..9d016de
Binary files /dev/null and b/img/graph_tri_par_insertion.PNG differ
diff --git a/img/graph_tri_par_selection.PNG b/img/graph_tri_par_selection.PNG
new file mode 100644
index 0000000..a59b570
Binary files /dev/null and b/img/graph_tri_par_selection.PNG differ
diff --git a/sort/fusion.py b/sort/fusion.py
index 73a21d3..9e9fd8f 100644
--- a/sort/fusion.py
+++ b/sort/fusion.py
@@ -1,2 +1,76 @@
def sort(array: list[int]) -> list[int]:
- return array
+ """sort the array using fusion sort"""
+ return fusion_sort(array)
+
+
+def fusion_sort(array: list[int]) -> list[int]:
+ # Fusion sort est une fonction récursive, elle s'apelle elle même
+ # On commence donc par définir les conditions de fin de cette recursion
+
+ # Si le passé est vide on arrette la récursion
+ if array == []:
+ return []
+
+ size: int = len(array)
+
+ # Si le tableau est de taille 1, on arrete la récursion
+ if size == 1:
+ return array
+
+ # La fonction s'appelle elle même deux fois,
+ # Une fois pour chaque moitiée du tableau,
+ # afin de couper le tableau jusqu'a avoir des morceaux de taille 1
+ first_half: list[int] = fusion_sort(array[:size//2])
+ second_half: list[int] = fusion_sort(array[size//2:])
+
+ # Le premier tableau peut être vide
+ # exemple:
+ # array = [1]
+ # size = 1 => size//2 = 0
+ # first_half = [1][:0] = []
+ # second_half = [1][0:] = [1]
+
+ # On fusionne nos deux tableaux
+ return fuse_2_array(first_half, second_half)
+
+
+def fuse_2_array(array1: list[int], array2: list[int]) -> list[int]:
+ """Fuse 2 arrays into 1, the result array is sorted"""
+
+ # Le premier tableau peut être vide apres le passage dans fusion sort
+ # Voir commentaires dans fusion_sort
+ if array1 == []:
+ return array2
+
+ # On a un curseur dans chacun des tableaux
+ index1: int = 0
+ index2: int = 0
+
+ size1: int = len(array1)
+ size2: int = len(array2)
+
+ sorted_array: list[int] = []
+ while len(sorted_array) < size1 + size2:
+ # Si l'un ou l'autre des curseurs a atteinds la fin de son tableau
+ # alors on insère les données de l'autre tableau
+ if index1 >= size1 and index2 < size2:
+ sorted_array += array2[index2:]
+ break
+ elif index2 >= size2 and index1 < size1:
+ sorted_array += array1[index1:]
+ break
+
+ # Sinon comportement classique, on insère le plus petit des deux
+ # nombres en premier
+ number1: int = array1[index1]
+ number2: int = array2[index2]
+
+ if number1 < number2:
+ sorted_array.append(number1)
+ index1 += 1
+ else:
+ sorted_array.append(number2)
+ index2 += 1
+
+ # print(f"fuse {array1} and {array2} => {res}")
+ return sorted_array
diff --git a/sort/insertion.py b/sort/insertion.py
index 73a21d3..3e05e96 100644
--- a/sort/insertion.py
+++ b/sort/insertion.py
@@ -1,2 +1,37 @@
def sort(array: list[int]) -> list[int]:
+ """Sort the array using insertion sort"""
+
+ # nombre de nombre trié dans le tableau
+ # On commence à 1 puisque qu'un tableau de taille 1 est trié
+ number_of_sorted_numbers: int = 1
+
+ # On parcours le tableau dans le sens croissant
+ for index in range(1, len(array)):
+ number: int = array[index]
+ # on parcours la partie trié du tableau dans le sens décroissant
+ for sorted_num_index in reversed(range(0, number_of_sorted_numbers)):
+ sorted_number = array[sorted_num_index]
+
+ if number < sorted_number and sorted_num_index > 0:
+ # Le nombre actuel est plus petit que le nombre trié
+ # et on n'est pas encore a la première case
+ # On continue de traverser le tableau trié
+ continue
+
+ # On insère notre nombre, On vérifie si num sorted_number alors,
+ # on insert number après l'index actuel
+ # Sinon insert à l'index actuel
+ array.pop(index)
+ array.insert(sorted_num_index + (number > sorted_number), number)
+
+ # Le nombre de nombre trié augmente
+ number_of_sorted_numbers += 1
+
+ # On a placé notre nombre, on quitte cette boucle
+ break
+
return array
diff --git a/sort/range.py b/sort/range.py
index fc252ab..4e9a8ae 100644
--- a/sort/range.py
+++ b/sort/range.py
@@ -1,2 +1,22 @@
+import time
+import random
+
+
def generate_array_of_number(array_size: int) -> list[int]:
- return []
+ """Generates an array of size `array_size` filled with random numbers
+ between 0 and 100"""
+ random_numbers: list[int] = [random.randint(0, 100)
+ for i in range(array_size)]
+ return random_numbers
+
+# Résultats
+# Génération de 1000000 nombres aléatoires en 1.42s
+# Génération de 2000000 nombres aléatoires en 3.20s
+# Génération de 3000000 nombres aléatoires en 3.96s
+# Génération de 4000000 nombres aléatoires en 5.15s
+# Génération de 5000000 nombres aléatoires en 6.32s
+# Génération de 6000000 nombres aléatoires en 7.66s
+# Génération de 7000000 nombres aléatoires en 8.97s
+# Génération de 8000000 nombres aléatoires en 10.20s
+# Génération de 9000000 nombres aléatoires en 11.47s
+# Génération de 10000000 nombres aléatoires en 13.51s
diff --git a/sort/recursion.py b/sort/recursion.py
index e7f4320..a394a19 100644
--- a/sort/recursion.py
+++ b/sort/recursion.py
@@ -1,2 +1,3 @@
def get_factorial(number: int) -> int:
- return number
+ """Returns the factorial of a number"""
+ return number * get_factorial(number-1) if number > 1 else 1
diff --git a/sort/selection.py b/sort/selection.py
index 73a21d3..c6fc3ea 100644
--- a/sort/selection.py
+++ b/sort/selection.py
@@ -1,2 +1,46 @@
def sort(array: list[int]) -> list[int]:
+ """Sorts the array using selection sort"""
+
+ array_size: int = len(array)
+
+ # `number_of_sorted_numbers` helps keep track of how many value has been
+ # sorted so far
+ # It tells us where we have to insert the lowest value we found
+ for number_of_sorted_numbers in range(array_size):
+
+ # `smallest_number_index` stores the index of the smallest number
+ # we intialize it with the index of the first value of the table that
+ # isnt sorted yet
+ smallest_number_index: int = number_of_sorted_numbers
+
+ # We go through the part of the table that is not sorted
+ # and store the smallest value
+ for index in range(number_of_sorted_numbers, array_size):
+ number: int = array[index]
+ if number < array[smallest_number_index]:
+ smallest_number_index = index
+
+ # We remove the smallest number with its index
+ smallest_number: int = array.pop(smallest_number_index)
+ # We insert it back after the other sorted numbers
+ array.insert(number_of_sorted_numbers, smallest_number)
+
return array
+
+
+# Résultats
+# Trie par insertion: taille tableau=1000, temps=0.10017824172973633s
+# Trie par insertion: taille tableau=2000, temps=0.2648162841796875s
+# Trie par insertion: taille tableau=3000, temps=0.5844788551330566s
+# Trie par insertion: taille tableau=4000, temps=1.1860754489898682s
+# Trie par insertion: taille tableau=5000, temps=1.6009154319763184s
+# Trie par insertion: taille tableau=6000, temps=2.032719135284424s
+# Trie par insertion: taille tableau=7000, temps=2.8216004371643066s
+# Trie par insertion: taille tableau=8000, temps=3.711418867111206s
+# Trie par insertion: taille tableau=9000, temps=4.674601316452026s
+# Trie par insertion: taille tableau=10000, temps=5.86929988861084s
+# Trie par insertion: taille tableau=11000, temps=8.09083604812622s
+# Trie par insertion: taille tableau=16000, temps=15.981599569320679s
+# Trie par insertion: taille tableau=21000, temps=29.68224310874939s
+# Trie par insertion: taille tableau=26000, temps=45.70301032066345s
+# Trie par insertion: taille tableau=31000, temps=61.37903904914856s