From 4a3d02bd19d9579801e8ffa1b9cb831fcbe5caf5 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 17 Nov 2023 12:31:32 +0100 Subject: [PATCH 01/19] =?UTF-8?q?G=C3=A9n=C3=A9ration=20de=20nombres=20al?= =?UTF-8?q?=C3=A9atoires?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++- __main__.py | 14 +++++++++++++- sort/range.py | 26 +++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 74f925a..91e7a2e 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,9 @@ 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 (résulats des tests dans le fichier `sort/range.py`) diff --git a/__main__.py b/__main__.py index 98a585e..5acf065 100644 --- a/__main__.py +++ b/__main__.py @@ -1,5 +1,17 @@ +from sort.range import generate_array_of_number + + def main(): - print("Hello world") + generate_array_of_number(1_000_000) + generate_array_of_number(2_000_000) + generate_array_of_number(3_000_000) + generate_array_of_number(4_000_000) + generate_array_of_number(5_000_000) + generate_array_of_number(6_000_000) + generate_array_of_number(7_000_000) + generate_array_of_number(8_000_000) + generate_array_of_number(9_000_000) + generate_array_of_number(10_000_000) main() diff --git a/sort/range.py b/sort/range.py index fc252ab..a216603 100644 --- a/sort/range.py +++ b/sort/range.py @@ -1,2 +1,26 @@ +import time +import random + def generate_array_of_number(array_size: int) -> list[int]: - return [] + + start: float = time.time() + + random_numbers: list[int] = [random.randint(0, 100) for i in range(array_size)] + + end: float = time.time() + + print(f"Génération de {array_size} nombres aléatoires en {end-start:.2f}s") + + 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 \ No newline at end of file From 79df499d29ab39a397006f0d35ae19d9abe95c9b Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 17 Nov 2023 15:36:07 +0100 Subject: [PATCH 02/19] Tri par selection --- README.md | 10 ++++++++-- sort/selection.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 91e7a2e..1a86d15 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Sur un tableur, générez un tableau permettant de visualiser le temps d'éxécu 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 (résulats des tests dans le fichier `sort/range.py`) +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`) @@ -77,7 +77,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. diff --git a/sort/selection.py b/sort/selection.py index 73a21d3..a95ae3a 100644 --- a/sort/selection.py +++ b/sort/selection.py @@ -1,2 +1,31 @@ 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` stores the smallest number found + # `smallest_number_index` stores its index + # we intialize them with the first value of the table that + # isnt sorted yet + smallest_number: int = array[number_of_sorted_numbers] + 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 < smallest_number: + smallest_number = number + smallest_number_index = index + + # We remove the smallest number with its index + array.pop(smallest_number_index) + # We insert it back after the other sorted numbers + array.insert(number_of_sorted_numbers, smallest_number) + return array From 0f309329d3b7fbcc459ebefaabb9cb5cdda810a9 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 17 Nov 2023 15:38:58 +0100 Subject: [PATCH 03/19] Application norme PEP8 --- sort/range.py | 6 ++++-- sort/selection.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sort/range.py b/sort/range.py index a216603..0179d95 100644 --- a/sort/range.py +++ b/sort/range.py @@ -1,11 +1,13 @@ import time import random + def generate_array_of_number(array_size: int) -> list[int]: start: float = time.time() - random_numbers: list[int] = [random.randint(0, 100) for i in range(array_size)] + random_numbers: list[int] = [random.randint(0, 100) + for i in range(array_size)] end: float = time.time() @@ -23,4 +25,4 @@ def generate_array_of_number(array_size: int) -> list[int]: # 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 \ No newline at end of file +# Génération de 10000000 nombres aléatoires en 13.51s diff --git a/sort/selection.py b/sort/selection.py index a95ae3a..f3c83bb 100644 --- a/sort/selection.py +++ b/sort/selection.py @@ -3,11 +3,11 @@ def sort(array: list[int]) -> list[int]: array_size: int = len(array) - # `number_of_sorted_numbers` helps keep track of how many value has been + # `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` stores the smallest number found # `smallest_number_index` stores its index # we intialize them with the first value of the table that From a83ddc10921931806734a4ea770f819d91bfe7ca Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 17 Nov 2023 15:56:00 +0100 Subject: [PATCH 04/19] =?UTF-8?q?Tests=20et=20r=C3=A9sulats=20trie=20par?= =?UTF-8?q?=20selection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __main__.py | 19 +++++++++---------- sort/selection.py | 13 +++++++++++++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/__main__.py b/__main__.py index 5acf065..834b20e 100644 --- a/__main__.py +++ b/__main__.py @@ -1,17 +1,16 @@ from sort.range import generate_array_of_number +from sort.selection import sort +import time def main(): - generate_array_of_number(1_000_000) - generate_array_of_number(2_000_000) - generate_array_of_number(3_000_000) - generate_array_of_number(4_000_000) - generate_array_of_number(5_000_000) - generate_array_of_number(6_000_000) - generate_array_of_number(7_000_000) - generate_array_of_number(8_000_000) - generate_array_of_number(9_000_000) - generate_array_of_number(10_000_000) + for sample_size in range(1000, 11_000, 1000): + sample: list[int] = generate_array_of_number(sample_size) + start: float = time.time() + sorted_sample: list[int] = sort(sample) + end: float = time.time() + print(f"Trie par insertion: taille tableau={sample_size}, \ + temps={end-start}s") main() diff --git a/sort/selection.py b/sort/selection.py index f3c83bb..211e182 100644 --- a/sort/selection.py +++ b/sort/selection.py @@ -29,3 +29,16 @@ def sort(array: list[int]) -> list[int]: 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 From 57b81769065b5ef8594df61baeee92d59b6882c3 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 17 Nov 2023 16:06:11 +0100 Subject: [PATCH 05/19] Test plus grand sample & conclusion --- README.md | 4 +++- __main__.py | 2 +- sort/selection.py | 5 +++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1a86d15..e5efb75 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,9 @@ 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 diff --git a/__main__.py b/__main__.py index 834b20e..80d08c4 100644 --- a/__main__.py +++ b/__main__.py @@ -4,7 +4,7 @@ def main(): - for sample_size in range(1000, 11_000, 1000): + for sample_size in range(1_000, 35_000, 5_000): sample: list[int] = generate_array_of_number(sample_size) start: float = time.time() sorted_sample: list[int] = sort(sample) diff --git a/sort/selection.py b/sort/selection.py index 211e182..4fed42d 100644 --- a/sort/selection.py +++ b/sort/selection.py @@ -42,3 +42,8 @@ def sort(array: list[int]) -> list[int]: # 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 \ No newline at end of file From 139e76ba51d7215ee9e9ab91d5898853ee9e4295 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 11:16:03 +0100 Subject: [PATCH 06/19] Tri par insertion fonctionel --- README.md | 11 ++++++++++- __main__.py | 21 ++++++++++++++++++--- sort/insertion.py | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e5efb75..69646d1 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,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. diff --git a/__main__.py b/__main__.py index 80d08c4..6f0948e 100644 --- a/__main__.py +++ b/__main__.py @@ -1,16 +1,31 @@ from sort.range import generate_array_of_number -from sort.selection import sort +from sort.insertion import sort as insertion_sort +from sort.selection import sort as selection_sort +from sort.fusion import sort as fusion_sort import time def main(): - for sample_size in range(1_000, 35_000, 5_000): + for sample_size in range(0, 10_000_000, 1_000_000): + sample: list[int] = generate_array_of_number(sample_size) + + 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] = sort(sample) + sorted_sample: list[int] = selection_sort(sample) + end: float = time.time() + print(f"Trie par selection: taille tableau={sample_size}, \ + temps={end-start}s") + + for sample_size in range(1_000, 10_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"Trie par insertion: taille tableau={sample_size}, \ temps={end-start}s") + + main() diff --git a/sort/insertion.py b/sort/insertion.py index 73a21d3..06555c9 100644 --- a/sort/insertion.py +++ b/sort/insertion.py @@ -1,2 +1,35 @@ def sort(array: list[int]) -> list[int]: + # 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_number_index in reversed(range(0, number_of_sorted_numbers)): + sorted_number = array[sorted_number_index] + + if number < sorted_number and sorted_number_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 Date: Fri, 24 Nov 2023 11:41:46 +0100 Subject: [PATCH 07/19] =?UTF-8?q?Graphiques=20&=20r=C3=A9ponses?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 +++++++- __main__.py | 26 ++++++++++++-------- img/graph_generation_nombres_aleatoires.PNG | Bin 0 -> 30092 bytes img/graph_tri_par_insertion.PNG | Bin 0 -> 30917 bytes img/graph_tri_par_selection.PNG | Bin 0 -> 29445 bytes sort/range.py | 8 ------ 6 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 img/graph_generation_nombres_aleatoires.PNG create mode 100644 img/graph_tri_par_insertion.PNG create mode 100644 img/graph_tri_par_selection.PNG diff --git a/README.md b/README.md index 69646d1..f2ad699 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,8 @@ Comment vous semble évoluer la courbe ? Observez bien les différentes courbes 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`) + + #### Quelques exemples de complexités courante : @@ -100,6 +102,8 @@ Quelle semble être la complexité de notre fonction de tri ? Cela est-il logiqu 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 Observez attentivement l'animation de tri par insertion ci-dessous pour en comprendre le fonctionnement. @@ -128,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 diff --git a/__main__.py b/__main__.py index 6f0948e..a789e37 100644 --- a/__main__.py +++ b/__main__.py @@ -6,18 +6,24 @@ def main(): - for sample_size in range(0, 10_000_000, 1_000_000): - sample: list[int] = generate_array_of_number(sample_size) + # 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"Trie par selection: taille tableau={sample_size}, \ - temps={end-start}s") - for sample_size in range(1_000, 10_000, 1_000): + # 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"Trie 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) diff --git a/img/graph_generation_nombres_aleatoires.PNG b/img/graph_generation_nombres_aleatoires.PNG new file mode 100644 index 0000000000000000000000000000000000000000..409f05e568bba5f4055055997c41ba764f22452f GIT binary patch literal 30092 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 literal 0 HcmV?d00001 diff --git a/img/graph_tri_par_insertion.PNG b/img/graph_tri_par_insertion.PNG new file mode 100644 index 0000000000000000000000000000000000000000..9d016dece33947837d7eea81e98cd09f1475e23a GIT binary patch literal 30917 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

U@2(iLqys&AhK}3_;u7byj!Xr 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볤=(P{g5J@?5Xm%N|-@VEGOuwK#HaS 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 Q2RL$5QB@)DFO#SL4-}li)c^nh literal 0 HcmV?d00001 diff --git a/sort/range.py b/sort/range.py index 0179d95..4dab531 100644 --- a/sort/range.py +++ b/sort/range.py @@ -3,16 +3,8 @@ def generate_array_of_number(array_size: int) -> list[int]: - - start: float = time.time() - random_numbers: list[int] = [random.randint(0, 100) for i in range(array_size)] - - end: float = time.time() - - print(f"Génération de {array_size} nombres aléatoires en {end-start:.2f}s") - return random_numbers # Résultats From f0e245dadfdb9d5cecb911eb4782fa1615959ed0 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 11:46:44 +0100 Subject: [PATCH 08/19] =?UTF-8?q?Fonction=20r=C3=A9cursive=20factorielles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __main__.py | 17 +++++++++-------- sort/recursion.py | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/__main__.py b/__main__.py index a789e37..4ae6ea3 100644 --- a/__main__.py +++ b/__main__.py @@ -2,6 +2,7 @@ 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 @@ -23,15 +24,15 @@ def main(): # print(f"Trie 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"Trie par insertion: 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"Trie par insertion: taille tableau={sample_size}, \ + # temps={end-start}s") + print(get_factorial(5)) main() diff --git a/sort/recursion.py b/sort/recursion.py index e7f4320..3243ead 100644 --- a/sort/recursion.py +++ b/sort/recursion.py @@ -1,2 +1,2 @@ def get_factorial(number: int) -> int: - return number + return number * get_factorial(number-1) if number > 1 else 1 From 98e5809bedeab2894eee38c792dff27a3291e5b4 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 12:41:27 +0100 Subject: [PATCH 09/19] Tri fusion --- README.md | 16 ++++++++--- __main__.py | 44 +++++++++++++++++------------- img/graph_tri_par_fusion.PNG | Bin 0 -> 35360 bytes sort/fusion.py | 51 ++++++++++++++++++++++++++++++++++- 4 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 img/graph_tri_par_fusion.PNG diff --git a/README.md b/README.md index f2ad699..bd37588 100644 --- a/README.md +++ b/README.md @@ -181,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. @@ -201,9 +205,15 @@ 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 ? -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* +Lors de mes tests, le tri par fusion a été le plus rapide peut importe la taille des données ### 4. sort() diff --git a/__main__.py b/__main__.py index 4ae6ea3..82fac09 100644 --- a/__main__.py +++ b/__main__.py @@ -9,30 +9,36 @@ def main(): # 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"Trie 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"Trie 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] = selection_sort(sample) + end: float = time.time() + print(f"Trie 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"Trie 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"Trie par insertion: taille tableau={sample_size}, \ + temps={end-start}s") main() diff --git a/img/graph_tri_par_fusion.PNG b/img/graph_tri_par_fusion.PNG new file mode 100644 index 0000000000000000000000000000000000000000..3d8f1ed488b1aa30a13338504d97827292194b0c GIT binary patch literal 35360 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%0AqdWx&lnX^fRBg>1~lX<2MRcN1%J4 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

=aWmlofU9NaNe)| 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 Qb~b3JX list[int]: - return array + return fusion_sort(array) + + +def fusion_sort(array: list[int]) -> list[int]: + if array == []: + return [] + + size: int = len(array) + if size == 1: + return array + + first_half: list[int] = fusion_sort(array[:size//2]) + second_half: list[int] = fusion_sort(array[size//2:]) + + return fuse_2_array(first_half, second_half) + + +def fuse_2_array(array1: list[int], array2: list[int]) -> list[int]: + if array2 == []: + return array1 + + index1: int = 0 + index2: int = 0 + + size1: int = len(array1) + size2: int = len(array2) + + res: list[int] = [] + while len(res) < size1 + size2: + if index1 >= size1 and index2 < size2: + res.append(array2[index2]) + index2 += 1 + continue + elif index2 >= size2 and index1 < size1: + res.append(array1[index1]) + index1 += 1 + continue + + number1: int = array1[index1] + number2: int = array2[index2] + + if number1 < number2: + res.append(number1) + index1 += 1 + else: + res.append(number2) + index2 += 1 + + # print(f"fuse {array1} and {array2} => {res}") + return res From bd9fd7681b0b08104b5319e0583897da1d120ac0 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 12:46:47 +0100 Subject: [PATCH 10/19] Comparaison tri python --- README.md | 4 +++- __main__.py | 25 +++++++++++++++++-------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index bd37588..b51ffda 100644 --- a/README.md +++ b/README.md @@ -219,7 +219,9 @@ Lors de mes tests, le tri par fusion a été le plus rapide peut importe la tail 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 82fac09..ae1aa2d 100644 --- a/__main__.py +++ b/__main__.py @@ -7,11 +7,11 @@ def main(): - # 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(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): @@ -19,7 +19,7 @@ def main(): start: float = time.time() sorted_sample: list[int] = selection_sort(sample) end: float = time.time() - print(f"Trie par selection: taille tableau={sample_size}, \ + print(f"Tri par selection: taille tableau={sample_size}, \ temps={end-start}s") for sample_size in range(1_000, 11_000, 1_000): @@ -27,7 +27,7 @@ def main(): start: float = time.time() sorted_sample: list[int] = insertion_sort(sample) end: float = time.time() - print(f"Trie par insertion: taille tableau={sample_size}, \ + print(f"Tri par insertion: taille tableau={sample_size}, \ temps={end-start}s") # print(get_factorial(5)) @@ -37,8 +37,17 @@ def main(): start: float = time.time() sorted_sample: list[int] = fusion_sort(sample) end: float = time.time() - print(f"Trie par insertion: taille tableau={sample_size}, \ + print(f"Tri par fusion: 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() + sample.sort() + end: float = time.time() + print(f"Tri Python: taille tableau={sample_size}, \ temps={end-start}s") + main() From 46a566dcd2c1cf24da669c8498f4bf50b8cddf45 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 12:48:38 +0100 Subject: [PATCH 11/19] =?UTF-8?q?Conformit=C3=A9=20PEP8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __main__.py | 5 ++--- sort/fusion.py | 4 ++-- sort/insertion.py | 11 +++++------ sort/selection.py | 2 +- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/__main__.py b/__main__.py index ae1aa2d..149b046 100644 --- a/__main__.py +++ b/__main__.py @@ -11,8 +11,8 @@ def main(): 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") - + 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) @@ -49,5 +49,4 @@ def main(): temps={end-start}s") - main() diff --git a/sort/fusion.py b/sort/fusion.py index 79826ef..05ec922 100644 --- a/sort/fusion.py +++ b/sort/fusion.py @@ -19,7 +19,7 @@ def fusion_sort(array: list[int]) -> list[int]: def fuse_2_array(array1: list[int], array2: list[int]) -> list[int]: if array2 == []: return array1 - + index1: int = 0 index2: int = 0 @@ -46,6 +46,6 @@ def fuse_2_array(array1: list[int], array2: list[int]) -> list[int]: else: res.append(number2) index2 += 1 - + # print(f"fuse {array1} and {array2} => {res}") return res diff --git a/sort/insertion.py b/sort/insertion.py index 06555c9..6c9911a 100644 --- a/sort/insertion.py +++ b/sort/insertion.py @@ -7,10 +7,10 @@ def sort(array: list[int]) -> list[int]: 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_number_index in reversed(range(0, number_of_sorted_numbers)): - sorted_number = array[sorted_number_index] + for sorted_numberIndex in reversed(range(0, number_of_sorted_numbers)): + sorted_number = array[sorted_numberIndex] - if number < sorted_number and sorted_number_index > 0: + if number < sorted_number and sorted_numberIndex > 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é @@ -21,9 +21,9 @@ def sort(array: list[int]) -> list[int]: # On doit donc vérifier où placer le nombre array.pop(index) if number < sorted_number: - array.insert(sorted_number_index, number) + array.insert(sorted_numberIndex, number) else: - array.insert(sorted_number_index+1, number) + array.insert(sorted_numberIndex+1, number) # Le nombre de nombre trié augmente number_of_sorted_numbers += 1 @@ -31,5 +31,4 @@ def sort(array: list[int]) -> list[int]: # On a placé notre nombre, on quitte cette boucle break - return array diff --git a/sort/selection.py b/sort/selection.py index 4fed42d..c65c2fb 100644 --- a/sort/selection.py +++ b/sort/selection.py @@ -46,4 +46,4 @@ def sort(array: list[int]) -> list[int]: # 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 \ No newline at end of file +# Trie par insertion: taille tableau=31000, temps=61.37903904914856s From 86fd4cfaa0284e950a464760f57205d9eba63b59 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 12:54:07 +0100 Subject: [PATCH 12/19] Graph python sort --- README.md | 3 ++ __main__.py | 68 +++++++++++++++++++------------------- img/graph_python_sort.PNG | Bin 0 -> 35305 bytes 3 files changed, 37 insertions(+), 34 deletions(-) create mode 100644 img/graph_python_sort.PNG diff --git a/README.md b/README.md index b51ffda..64037a2 100644 --- a/README.md +++ b/README.md @@ -223,6 +223,9 @@ Une dernière fois, analysez le temps d'exécution et découvrez si python fait La fonction sort de python est largement plus rapide, en moyenne 100x plus rapide + + + ## Pour rendre ce TP Merci de faire une Pull Request vers ce repository. diff --git a/__main__.py b/__main__.py index 149b046..5564b1b 100644 --- a/__main__.py +++ b/__main__.py @@ -7,40 +7,40 @@ def main(): - 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(1_000, 11_000, 1_000): + # 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() diff --git a/img/graph_python_sort.PNG b/img/graph_python_sort.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a8dbb4bb2c3a40190c25ca5cacf2028c542b884a GIT binary patch literal 35305 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
1B0*pe)^Y=bi(8-J3-syS>+edg& z3xvI~;l}IX=HXMI@ItUiRctPivbS zBT(WxuGQ~>)E2>CoP#~Ay3~)!lATIVm@r>D(6k@QhCq}%Jq+LopXKRJ-C33j{$eVO zq+<(L)fay>9>bqW>UY_e%1$!htWGMe&}J6R&NOE`G0;grW+PKcLaDFf6gZ$+F{L_m zyrPsK%)Ji8QMf24A!mr69Y%uJ9_=`3XkkWZ21<2gHyG|B^Gl{wf;1BuUd+-~a6gW= zwz2$#P^g!_dlyauA@dOARQLt67RQRFPxJ?QI$696MVwpihAM!8bjo_!*DAzTVB4?r zXCZ;#UcM&U+L(SxP{H(*54AkQBMbMy+N0@d}TR?%(4Kr;jJD*{nGg zdsOr#X0aP!tZEZaId5fDG^ zc}XdV(xP8Wh#2`bpq+J_I=s)}$37k(j_rVlKF}a_1`HjkIsl<=MSoZ>1BY-LyRQwd zbmhQC6E2t@HBOCD36T?{M4)yqP3sz}fi8IAzWQ5hREq3!bEASYV=l@+eT#T+Guw~v zmPqyoC!PoNqNG&ydTQ_Rk(9I(x3a#>-Uk(rt+p{5?sXl@PLqXk zaXLue6MfkF1ow>o>L4e*?>I?-az0X=;Z}kWORlzN?w{Ky2}DxRt!jBNJe7v=k;ulq zrU{~&oOblbG>Pel5>35d+)N^fpYbzhhXgk665HPb3|iqTskQo>@iCr|q)5sk)SY#a zTlG%}Lc2CkWhw+;hNP2DW< z6$zIoI+u&B-3x5u-20Q~X5Yv6Kj;nwS&Vhs=lkG%&BK++uTMBEjEO5i3zl+aD3t)u zGqDaewEWCTXB4k$(uZ!XCj7A`!87ZaJ3SAR>6l9=L#ARpDz+!NE7bs<%M2N4urqpq zJs>_97{V~r@*iv-=$*^#3OiV@#QN4AERP>32^?&ASh%`_M;!v!Nb#ySffQoi8^MCB zW-pw%f;dMFd4wu4&&(jT>cEkLtBL`ynpWVHr(8qJWDKCLOI?HGE)|=}TbQx8R{1Tw z7#p*B2uU|CB%kulA(n(UlZ@F6G8LG9m}S+pK38?DRD-gNyYNMOQB2~)@XhUDc47z~ z?p`_Z@$@0fpS@O^NoyT(_xh!%_mWeRhLZlVp*OpC|9l*r->;O5PT=EZAT+T+P`DNX z2iSDj5Ac7l$*Fr9ZwEgKdqL53XG}ihY9x=)WX1!VVe+m&S{+cb@MMKD^tV~=bH1I0 ztWAY%ks@gYhqqEepCl-I5#9xomEUzJP+8fEx_VYx5k59|vGfXa*dJR!p8U0Z4?t!n zA;2ZPeeSWxtN*kB1yzQXm>UhmA_Ojb@<50iXalPA28tA`-r%s*Shjv|9^&R!XK!v1 zp(QrzeTgh19g|E&tjeqbx=QhX4`n6IuuD-~>Mvj?T-d#hRd zCGN_wX>Teox9KRQVMC_e3x_&s&M*}nw}SoT^=qwfCHwkiP2_^|N!bKUW^^Z`L2lev zS9d5d&Atd0kT((-#!-8I;e@yDf6|}TVeZNuX+0*Y-Jia*CMVLVPo2N3x=D`Q&Ard< zWF08Evgk;a8oOgYkNz#1We4R#-S_>v+H8X3KASKR;=M;43NU)Gvdb?K=ise5b%t)0 zsV;-B@vA^hgX0?*4+5M=rDSQIPhnfIqKazubw4}(E}0P+nazJF3Oo-=sGlok8GW^HO1qMeGFE;^Ra#p#TK zCuIPO@%NMPsQxU;YF5VFrbpGRc+s@|K~M0L7L}lp5dV{DVV;2}LctR*cDF~m%GuOD zYCw77c#4x{xD_sLu)fo{Wbu@6xB=h~Z=}e*>Rb7GhY

6Marix~( zQE0x^(RN(v&6O;b_k$>d)4q)bt^e;!BEKL%UZC?2>uf36zpje#;7s>8p^M znU1JXP5JS<9qI6`z@&=DuUvB9W~jB*;j_bXt^v76hk*k9i-q`~ckrSk%kI?C*K}}x z47u4$5DMxb7SPBiS!y++D{ zc?vDhT=v>=sHIE5D;y6J1An<|Nf*_&%$|TUhSC}3&mBZVC?3KF?-(6P44XU+E%qFO*ZY&bUMq11-y3kPXVBgciYkjbnZ()* zQo$Xj{veFS?U69ew~QksLq%}d7NqG>rLQHT?kRhd<|HCTf&C**0#ibIHp{{%`(jRG zi-2%@_SUPnM{JZhOz=kvkld)=wSqxpO1K|A4srpyRT11>^nR}3U#~s=oY)K8T4hQ z<_)~_JMud_8$y;HWzpi0pO+L_8Fv#`p`@JHqS5x&*1%}uD$I%;3>H=rKWoIrd(|tY zQ$LP-*&>`$7LfnI4Gzl=2UFR&gQ7%fU-H?C@&r+4#(l3$5`*G1vmTo(!4tI$wTs=? z;xm4G9rf;^76?dYQk&08Q+M^##3K7ybQUX5!+0(O{`;XcuJla_5sr5*oyUT(f%2Fd zbK;)RRG0anhr|!m=31Jkq=EVr+Y-RGi14B_B>UAojJt<_NQ{YsqC%*q$qjBl4=8)_ zQL}y9L2WPb3Ff&5_RWZ%y_^OouSkVL1t_A%Ef4wzws?&OrX<%-W;%x|mTR#g5qHu` z+ZW}lqY&xoai!noyfXKf)|jrPdFYT#-8EH$D>I>~-5T=dxWzX``PSx+WS-gFYM6(*$=KfHAM*)ZEde4~(M@-z$l@Rnp%qK0x+RklKEI4&050q<-;` zZSq&M2QKU7Rqw^Bx#tQMQ#Yl(?X)VV&e+{7xhbnH4?& zy2q1#X#B>Dt1uX#9k-?!aWwAWQAsVP#Oa8?X>|Au>D`_?`O|GN*cxWJD8mzX7r1en zK}AA&YwuChX2x%M+Dl6ti7%Rw+y3=2cW{A$np})X8Fz?MZw0*!piVsUlpzu&fl@E$ z87%my9SJ{IwM(Rh9=D(6>}ab8G?LKf(xs(V zPHx@Qqw?{JOk>llHh$@t|Dk&L_8%k0`DNFC3*Zi~yO7pE3Gz zw(35+KuIRN6cx+ToA6MH%zR^3Nmbr=Jx+W#Zk97kQK1zrR7p@};UU~%D!$_$rky)D zHWAc#Cp-Ab?`T`22?_Mll+-V(M^vX5PYBAo7ORWV$AS&B1r<+n8PGiCO!P!Q;$ynP zUuBAAYjSOS>hLipX1ZT5qH<`J;D$*44r^A4$SasQQGsroD7_5JBPHO=v&Afr7n|v} zrnrD_HABqpY=xf96*?el2kAZe4=_Sn=M{aBi!f2P~s^w(8u zNb3t6HeD#qf+ef(n!S=h?P8qv(4`DE<%nc;i{2#4lf$8@e@E@&vEysK~HAp@X$A5Rp_iiSPoB!WI!iY>*oSgfT8hGH=XYCbx-> zgA>i>k#2C5c55`q#ip^mSn6I^|7zEkdt!-NML$3I1nUt}bFlJS_Y5oq+X#6a&Hgrxwst z+<1P*EqyPjnSNqbqWJwqnCAz;`TRx1e+urO-#@GssAq~P`!}9nOJIWmH0%ne*F$DB zJUDD*{HChyw$Zs8cd>_nx~I5-?k%)v_HoV%*|(Jj_p4e}(9QTCWp2LCbTTI(XPMJ zrpNCh0`F3D{^g>^TGzx5``QaF{b5GdSu}q#F+Q99TGQKnJl&vX^M+e`3%2W^-^ti^ z+hu>^Q2F-?G0zhjHCPFfx+|iftJK9EDw)``!eAf&=+gey$!Qqo@ALM-o<7db+uS*t z4A8skLpsv$6*J|oqT>(~h7WE|9#DGzJ)J8^wOPvWYl!- ztwYHl5c*Wpa+iC6TBre3z;TJ*wpj`0_E6|P3H!S9Cq=C-nqRy*VUv|%sMoPOB^N7G zevYY?t(HzYYv{ddSpJ@6@#C@-Y15dYL(!!x4bItj{pQfvO%|moF!QVLXBRuFc~OEC|&^U{?>P@VU4ErA;rL^QXn5 m+1 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 Date: Fri, 24 Nov 2023 15:24:59 +0100 Subject: [PATCH 13/19] Commentaire et PEP8 --- __main__.py | 64 +++++++++++++++++++++++------------------------ sort/fusion.py | 34 +++++++++++++++++++------ sort/insertion.py | 2 ++ sort/range.py | 2 ++ sort/recursion.py | 1 + 5 files changed, 64 insertions(+), 39 deletions(-) diff --git a/__main__.py b/__main__.py index 5564b1b..e76fc9b 100644 --- a/__main__.py +++ b/__main__.py @@ -7,38 +7,38 @@ def main(): - # 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(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) diff --git a/sort/fusion.py b/sort/fusion.py index 05ec922..b1569c9 100644 --- a/sort/fusion.py +++ b/sort/fusion.py @@ -1,51 +1,71 @@ def sort(array: list[int]) -> list[int]: + """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:]) + # 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 deuxième tableau peut être vide si le tableau original + # a une taille impaire if array2 == []: return array1 + # On a un curseur dans chacun des tableaux index1: int = 0 index2: int = 0 size1: int = len(array1) size2: int = len(array2) - res: list[int] = [] - while len(res) < size1 + size2: + 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: - res.append(array2[index2]) + sorted_array.append(array2[index2]) index2 += 1 continue elif index2 >= size2 and index1 < size1: - res.append(array1[index1]) + sorted_array.append(array1[index1]) index1 += 1 continue + # 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: - res.append(number1) + sorted_array.append(number1) index1 += 1 else: - res.append(number2) + sorted_array.append(number2) index2 += 1 # print(f"fuse {array1} and {array2} => {res}") - return res + return sorted_array diff --git a/sort/insertion.py b/sort/insertion.py index 6c9911a..4cba614 100644 --- a/sort/insertion.py +++ b/sort/insertion.py @@ -1,4 +1,6 @@ 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 diff --git a/sort/range.py b/sort/range.py index 4dab531..4e9a8ae 100644 --- a/sort/range.py +++ b/sort/range.py @@ -3,6 +3,8 @@ def generate_array_of_number(array_size: int) -> list[int]: + """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 diff --git a/sort/recursion.py b/sort/recursion.py index 3243ead..a394a19 100644 --- a/sort/recursion.py +++ b/sort/recursion.py @@ -1,2 +1,3 @@ def get_factorial(number: int) -> int: + """Returns the factorial of a number""" return number * get_factorial(number-1) if number > 1 else 1 From f862c67f69d73ef016153dd7cccf19aa6f14457f Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 16:14:10 +0100 Subject: [PATCH 14/19] Pas besoin de stocker le plus petit nombre --- sort/selection.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/sort/selection.py b/sort/selection.py index c65c2fb..c6fc3ea 100644 --- a/sort/selection.py +++ b/sort/selection.py @@ -8,23 +8,20 @@ def sort(array: list[int]) -> list[int]: # It tells us where we have to insert the lowest value we found for number_of_sorted_numbers in range(array_size): - # `smallest_number` stores the smallest number found - # `smallest_number_index` stores its index - # we intialize them with the first value of the table that - # isnt sorted yet - smallest_number: int = array[number_of_sorted_numbers] + # `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 < smallest_number: - smallest_number = number + if number < array[smallest_number_index]: smallest_number_index = index # We remove the smallest number with its index - array.pop(smallest_number_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) From 4efb42624dfd50fe3443b9e443fdd57cc8307d29 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 16:16:51 +0100 Subject: [PATCH 15/19] Respecter snake_case --- sort/insertion.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sort/insertion.py b/sort/insertion.py index 4cba614..b6b0746 100644 --- a/sort/insertion.py +++ b/sort/insertion.py @@ -9,10 +9,10 @@ def sort(array: list[int]) -> list[int]: 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_numberIndex in reversed(range(0, number_of_sorted_numbers)): - sorted_number = array[sorted_numberIndex] + for sorted_num_index in reversed(range(0, number_of_sorted_numbers)): + sorted_number = array[sorted_num_index] - if number < sorted_number and sorted_numberIndex > 0: + 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é @@ -23,9 +23,9 @@ def sort(array: list[int]) -> list[int]: # On doit donc vérifier où placer le nombre array.pop(index) if number < sorted_number: - array.insert(sorted_numberIndex, number) + array.insert(sorted_num_index, number) else: - array.insert(sorted_numberIndex+1, number) + array.insert(sorted_num_index+1, number) # Le nombre de nombre trié augmente number_of_sorted_numbers += 1 From ce8bca1f37a18ed28079ad9a9de3d909cf5362fa Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 16:32:22 +0100 Subject: [PATCH 16/19] =?UTF-8?q?Le=20tableau1=20peut=20=C3=AAtre=20vide?= =?UTF-8?q?=20pas=20le=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sort/fusion.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sort/fusion.py b/sort/fusion.py index b1569c9..b93aa17 100644 --- a/sort/fusion.py +++ b/sort/fusion.py @@ -23,6 +23,13 @@ def fusion_sort(array: list[int]) -> list[int]: 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) @@ -30,10 +37,10 @@ def fusion_sort(array: list[int]) -> list[int]: def fuse_2_array(array1: list[int], array2: list[int]) -> list[int]: """Fuse 2 arrays into 1, the result array is sorted""" - # Le deuxième tableau peut être vide si le tableau original - # a une taille impaire - if array2 == []: - return array1 + # 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 From 6efddae11a989c85fa6b9546191e4f030c12206c Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 16:38:11 +0100 Subject: [PATCH 17/19] Ajouter le reste du tableau d'un coup --- sort/fusion.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sort/fusion.py b/sort/fusion.py index b93aa17..9e9fd8f 100644 --- a/sort/fusion.py +++ b/sort/fusion.py @@ -54,13 +54,11 @@ def fuse_2_array(array1: list[int], array2: list[int]) -> list[int]: # 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.append(array2[index2]) - index2 += 1 - continue + sorted_array += array2[index2:] + break elif index2 >= size2 and index1 < size1: - sorted_array.append(array1[index1]) - index1 += 1 - continue + sorted_array += array1[index1:] + break # Sinon comportement classique, on insère le plus petit des deux # nombres en premier From 969ce93c4981d2c430b96eb2d16e403f0f536eb5 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 16:49:02 +0100 Subject: [PATCH 18/19] Pas de condition pour l'insertion finale --- sort/insertion.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sort/insertion.py b/sort/insertion.py index b6b0746..74068d5 100644 --- a/sort/insertion.py +++ b/sort/insertion.py @@ -22,10 +22,10 @@ def sort(array: list[int]) -> list[int]: # Car on peut se trouver dans le cas où index==0 # On doit donc vérifier où placer le nombre array.pop(index) - if number < sorted_number: - array.insert(sorted_num_index, number) - else: - array.insert(sorted_num_index+1, number) + + # Si number > sorted_number alors insert à l'index 1 + # Sinon insert à l'index 0 + array.insert(number > sorted_number, number) # Le nombre de nombre trié augmente number_of_sorted_numbers += 1 From 5e6d6c2634db0c68fce30d2e80c30487a1efc683 Mon Sep 17 00:00:00 2001 From: MZASU Date: Fri, 24 Nov 2023 16:56:39 +0100 Subject: [PATCH 19/19] =?UTF-8?q?R=C3=A9parer=20tri=20insertion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sort/insertion.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sort/insertion.py b/sort/insertion.py index 74068d5..3e05e96 100644 --- a/sort/insertion.py +++ b/sort/insertion.py @@ -21,11 +21,12 @@ def sort(array: list[int]) -> list[int]: # 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) - - # Si number > sorted_number alors insert à l'index 1 - # Sinon insert à l'index 0 - array.insert(number > sorted_number, number) + array.insert(sorted_num_index + (number > sorted_number), number) # Le nombre de nombre trié augmente number_of_sorted_numbers += 1