diff --git a/.~lock.temps_exec_prog1.ods# b/.~lock.temps_exec_prog1.ods# new file mode 100644 index 0000000..06868bc --- /dev/null +++ b/.~lock.temps_exec_prog1.ods# @@ -0,0 +1 @@ +,DESKTOP-PMFVC5P/HP,DESKTOP-PMFVC5P,25.11.2023 17:47,file:///C:/Users/HP/AppData/Roaming/LibreOffice/4; \ No newline at end of file diff --git a/README.md b/README.md index 74f925a..65d8049 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ 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 ? Malgré une précision assez mauvaise distingue une courbe semblante à O(n) @@ -75,7 +75,7 @@ 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 ? Nous avons une variable à laquelle nous affectons la première valeur non triée de la liste, puis nous commençons à parcourir la liste, lorsque nous croisons une valeur plus petite que celle stockée dans notre variable nous l'affectons à notre variable jusqu'à arriver au bout de la liste, dès que nous y sommes arrivés nous plaçons l'élément à la suite des éléments triés, et ainsi de suite 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 +88,7 @@ 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 complexité semble être O(n2²), cela semble logique par rapport au code implémenté, nous avons 2 boucles imbriquées. ### 2. Tri par insertion @@ -96,7 +96,7 @@ 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 ? L'algorithme de tri par insertion prend chaque élément de la liste un par un et les replaces dans le liste en les comparant à la partie déjà trié. Il ne bouge pas le premier élément car il n'y a pas encore de partie triée, puis il séléctionne le deuxième et le trie par rapport au premier, pour fait de même avec le troisième etc.... 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 +109,7 @@ 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é ? De la même manière que pour le tri par selection nous avons un programme qui imbrique 2 boucles, nous devrions donc retrouver un complexité de 0( n² ) et c'est bel et bien ce que le grahique nous retransmet ### 3. Tri par fusion @@ -154,7 +154,7 @@ 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 ? Nous divisons un tableau en 2 puis nous divisons ces 2 nouveaux tableaux en 4 et ce jusqu'à obtenir des tableaux de taille 1, après tout avoir divisé nous devons les réassembler mais cette fois ci dans le bon ordre, chaque membre s'assemble avec son membre de gauche ou droite pour former un tableau trié et ainsi de suite jusqu'à revenir à seul tableau mais cette fois ci, trié Complétez la fonction `sort` du fichier `sort/fusion.py` en suivant les instructions suivantes. @@ -174,15 +174,17 @@ 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 complexité semble être O ( n log n ), nous avons un algorithme de division récursive donc cela paraît logique -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 ? Les tailles de tableau très petite sont défavorables pour le tri fusion ### 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 ;) + +Nos algos sont bien moins rapide que le sort de python ## Pour rendre ce TP diff --git a/__main__.py b/__main__.py index 98a585e..62cd098 100644 --- a/__main__.py +++ b/__main__.py @@ -1,5 +1,84 @@ +from sort.range import time_to_generate_array, generate_array_of_number +from sort.selection import time_to_sort_selection +from sort.insertion import time_to_sort_insertion +from sort.fusion import time_to_sort_fusion +import time + + def main(): - print("Hello world") + """Fonction principale, ici permettra de tester l'efficacité des algos""" + + # print("---Temps Exec Génération Tableau---") + # time_to_generate_array(1000000) + # time_to_generate_array(2000000) + # time_to_generate_array(3000000) + # time_to_generate_array(4000000) + # time_to_generate_array(5000000) + # time_to_generate_array(6000000) + # time_to_generate_array(7000000) + # time_to_generate_array(8000000) + # time_to_generate_array(9000000) + # time_to_generate_array(10000000) + + # print("---Temps Exec Tri Selection---") + # time_to_sort_selection(1000) + # time_to_sort_selection(2000) + # time_to_sort_selection(3000) + # time_to_sort_selection(4000) + # time_to_sort_selection(5000) + # time_to_sort_selection(6000) + # time_to_sort_selection(7000) + # time_to_sort_selection(8000) + # time_to_sort_selection(9000) + # time_to_sort_selection(10000) + + # print("---Temps Exec Tri Insertion---") + # time_to_sort_insertion(1000) + # time_to_sort_insertion(2000) + # time_to_sort_insertion(3000) + # time_to_sort_insertion(4000) + # time_to_sort_insertion(5000) + # time_to_sort_insertion(6000) + # time_to_sort_insertion(7000) + # time_to_sort_insertion(8000) + # time_to_sort_insertion(9000) + # time_to_sort_insertion(10000) + + # print("---Temps Exec Tri Fusion---") + # time_to_sort_fusion(1000) + # time_to_sort_fusion(2000) + # time_to_sort_fusion(3000) + # time_to_sort_fusion(4000) + # time_to_sort_fusion(5000) + # time_to_sort_fusion(6000) + # time_to_sort_fusion(7000) + # time_to_sort_fusion(8000) + # time_to_sort_fusion(9000) + # time_to_sort_fusion(10000) + + print("---Temps Exec Sort By Python---") + time_to_sort_by_pyhton(1000) + time_to_sort_by_pyhton(2000) + time_to_sort_by_pyhton(3000) + time_to_sort_by_pyhton(4000) + time_to_sort_by_pyhton(5000) + time_to_sort_by_pyhton(6000) + time_to_sort_by_pyhton(7000) + time_to_sort_by_pyhton(8000) + time_to_sort_by_pyhton(9000) + time_to_sort_by_pyhton(10000) + time_to_sort_by_pyhton(999999) + + +def time_to_sort_by_pyhton(length: int): + """Temps pour trier un tableau d'une taille donnnée en paramètre avec le + tri par selection""" + array = generate_array_of_number(length) + start: float = time.time() + array.sort() + end: float = time.time() + print("Taille du tableau = ", length) + print("Temps écoulé : ", end - start) main() diff --git a/sort/fusion.py b/sort/fusion.py index 73a21d3..658bfb6 100644 --- a/sort/fusion.py +++ b/sort/fusion.py @@ -1,2 +1,69 @@ +import time +from sort.range import generate_array_of_number + + def sort(array: list[int]) -> list[int]: - return array + """Divise le tableau pour le trier plus facilement.""" + if len(array) <= 1: + return array + + # On cherche le milieu pour séparer le tableau en 2 parties de même taille + # (ou presque si impair, grâce à la division entière) + center = len(array) // 2 + + # On copie les sous-tableaux + array_split_1 = array[:center] + array_split_2 = array[center:] + + # On continue de manière récursive de diviser notre tableau + sorted_array_1 = sort(array_split_1) + sorted_array_2 = sort(array_split_2) + + # Puis on renvoie la fusion de nos tableaux triés + return merge(sorted_array_1, sorted_array_2) + + +def merge(array1: list[int], array2: list[int]) -> list[int]: + """Combine des tableaux triés.""" + temp_array = [] + index_1 = 0 + index_2 = 0 + + while index_1 < len(array1) and index_2 < len(array2): + if array1[index_1] < array2[index_2]: + temp_array.append(array1[index_1]) + index_1 += 1 + else: + temp_array.append(array2[index_2]) + index_2 += 1 + + # Ajoute les éléments restants s'il y en a dans array1 + while index_1 < len(array1): + temp_array.append(array1[index_1]) + index_1 += 1 + + # Ajoute les éléments restants s'il y en a dans array2 + while index_2 < len(array2): + temp_array.append(array2[index_2]) + index_2 += 1 + + # Crée un nouvel array pour stocker le résultat fusionné + merged_array = [0] * (len(array1) + len(array2)) + + # Copie les éléments de temp_array dans merged_array + # ( pylint m'a consillé cette syntaxe elle est pas mal je connaissais pas ) + for i, value in enumerate(temp_array): + merged_array[i] = value + + return merged_array + + +def time_to_sort_fusion(length: int): + """Temps pour trier un tableau d'une taille donnée en paramètre avec le + tri par insertion.""" + array = generate_array_of_number(length) + start_time = time.time() + sort(array) + end_time = time.time() + print("Taille du tableau =", length) + print("Temps écoulé :", end_time - start_time) diff --git a/sort/insertion.py b/sort/insertion.py index 73a21d3..a0ea192 100644 --- a/sort/insertion.py +++ b/sort/insertion.py @@ -1,2 +1,38 @@ +import time +from sort.range import generate_array_of_number + + def sort(array: list[int]) -> list[int]: + """Tri par insertion.""" + + # On lance une boucle for qui prendra chaque élément un par un pour les + # trier. On commence à 1 car 0 est déjà trié. + for item_to_sort in range(1, len(array)): + + # La variable item_to_test aura pour but de tester les éléments placés + # avant l'élément que nous voulons trier. + item_to_test = item_to_sort - 1 + current_item = array[item_to_sort] + + # Puis on lance une boucle while qui "déplacera" notre élément tant + # qu'il n'est pas à la bonne place. + while current_item < array[item_to_test] and item_to_test >= 0: + # On décale les éléments car nous ne voulons pas insérer notre + # élément ici. + array[item_to_test + 1] = array[item_to_test] + item_to_test -= 1 + + array[item_to_test + 1] = current_item + return array + + +def time_to_sort_insertion(length: int): + """Temps pour trier un tableau d'une taille donnée en paramètre avec le + tri par insertion.""" + array = generate_array_of_number(length) + start_time = time.time() + sort(array) + end_time = time.time() + print("Taille du tableau =", length) + print("Temps écoulé :", end_time - start_time) diff --git a/sort/range.py b/sort/range.py index fc252ab..99f1ecc 100644 --- a/sort/range.py +++ b/sort/range.py @@ -1,2 +1,17 @@ +import time +import random + + def generate_array_of_number(array_size: int) -> list[int]: - return [] + """Génère une array de taille donnée en paramètre""" + array = [random.randint(0, 100) for i in range(array_size)] + return array + + +def time_to_generate_array(length: int): + """temps pour générer une array de taille passée en paramètre""" + start: float = time.time() + generate_array_of_number(length) + end: float = time.time() + print("Taille du tableau = ", length) + print("Temps écoulé : ", end - start) diff --git a/sort/recursion.py b/sort/recursion.py index e7f4320..754d166 100644 --- a/sort/recursion.py +++ b/sort/recursion.py @@ -1,2 +1,8 @@ def get_factorial(number: int) -> int: - return number + """Retoune la factorielle de manière recursive""" + # On test le cas de factotrielle de 0 + if number == 0: + return 1 + # Sinon on calcule la factorille récursivement + else: + return number * get_factorial(number - 1) diff --git a/sort/selection.py b/sort/selection.py index 73a21d3..517a9c7 100644 --- a/sort/selection.py +++ b/sort/selection.py @@ -1,2 +1,40 @@ +import time +from sort.range import generate_array_of_number + + def sort(array: list[int]) -> list[int]: + """Tri par sélection""" + + # On parcourt la liste une fois de moins que sa taille + for iteration in range(len(array) - 1): + + # On affecte la première valeur non triée à la variable smallest_number + smallest_number = array[iteration] + index_pop = iteration + + # On parcourt la liste pour trouver la plus petite valeur non triée + for iteration2 in range(iteration + 1, len(array)): + + if smallest_number > array[iteration2]: + + # Quand on trouve une valeur plus petite, + # on la stocke dans la variable + smallest_number = array[iteration2] + index_pop = iteration2 + + # On échange la plus petite valeur trouvée avec + # l'élément non trié actuel + array[index_pop], array[iteration] = array[iteration], array[index_pop] + return array + + +def time_to_sort_selection(length: int): + """Temps pour trier un tableau d'une taille donnnée en paramètre avec le + tri par selection""" + array = generate_array_of_number(length) + start: float = time.time() + sort(array) + end: float = time.time() + print("Taille du tableau = ", length) + print("Temps écoulé : ", end - start) diff --git a/temps_exec_prog1.ods b/temps_exec_prog1.ods new file mode 100644 index 0000000..d53063d Binary files /dev/null and b/temps_exec_prog1.ods differ