Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
__pycache__
__pycache__
.idea
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ 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.

<img src="img/tableau random list.png" width="800">

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*
* La courbe semble évoluer de manière linéaire. La plus ressemblante à notre situation est la courbe O(n).

<img src="img/o.webp" width="400">

Expand All @@ -77,6 +80,8 @@ 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*

* Le tri par sélection consiste à parcourir le tableau pour trouver le plus petit élément, puis à le placer en première position. On recommence ensuite avec le deuxième plus petit élément, et ainsi de suite jusqu'à ce que le tableau soit trié.

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.

Mesurez le temps d'éxécution pour un tableau de :
Expand All @@ -88,8 +93,12 @@ Mesurez le temps d'éxécution pour un tableau de :

Tracez le graphique correspondant.

<img src="img/selection graph.png" width="600">

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*

* La complexité de notre fonction de tri est O(n²). C'est logique par rapport au code que nous avons implémenté car nous avons deux boucles imbriquées.

### 2. Tri par insertion

Observez attentivement l'animation de tri par insertion ci-dessous pour en comprendre le fonctionnement.
Expand All @@ -98,6 +107,8 @@ 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*

* Le tri par insertion consiste à parcourir le tableau en plaçant au fur et à mesure chaque élément à sa place dans le tableau trié. Pour cela, on compare l'élément avec les éléments précédents, et on les décale vers la droite tant que l'élément est plus petit.

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.

Mesurez le temps d'éxécution pour un tableau de :
Expand All @@ -109,8 +120,12 @@ Mesurez le temps d'éxécution pour un tableau de :

Tracez le graphique correspondant.

<img src="img/insertion graph.png" width="600">

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*

* La complexité de notre fonction de tri est O(n²). C'est logique par rapport au code que nous avons implémenté car nous avons deux boucles imbriquées.

### 3. Tri par fusion

Le tri par fusion est plus complexe : il utilise en effet la récursion, c'est à dire une fonction qui s'appelle elle-même.
Expand Down Expand Up @@ -156,6 +171,8 @@ 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*

* Le tri par fusion consiste à diviser le tableau en deux, puis de diviser chaque moitié jusqu'à ce qu'il ne reste plus que 1 ou 2 éléments. On trie ces éléments, puis on fusionne les tableaux, on les tries etc... jusqu'à ce qu'il ne reste plus qu'un seul tableau trié.

Complétez la fonction `sort` du fichier `sort/fusion.py` en suivant les instructions suivantes.

Il vous faudra deux fonctions :
Expand All @@ -174,16 +191,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*
<img src="img/fusion graph.png" width="600">

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é de notre fonction de tri est O(n log n).
ça peut s'expliquer par le fait que nous divisons le tableau en deux à chaque fois, et que nous fusionnons les tableaux en les triant.
la division du tableau en deux se fait en O(log n) et la fusion se fait en O(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*

* Le tri par fusion est plus rapide que les autres tris abordés pour toutes les tailles de tableaux.

### 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 ;)

* après avoir fait plusieurs tests, il s'avère que la fonction sort() de python est plus rapide que le tri fusion qui était pourtant le plus rapide des tris que nous avons implémentés.

## Pour rendre ce TP

Merci de faire une Pull Request vers ce repository.
Expand Down
45 changes: 43 additions & 2 deletions __main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,46 @@
def main():
print("Hello world")
import time
from typing import Callable

from sort import selection, insertion, fusion
from sort.range import generate_array_of_number


def measure_time(sort_function: Callable[[list[int]], list[int]],
array: list[int]) -> float:
"""
Measure the time it takes to run a sorting function on an array.

:param sort_function: The sorting function to be measured.
:param array: The array to be sorted.
:return: The time taken to run the sorting function on the array.
"""
start: float = time.time()
sort_function(array)
end: float = time.time()
return end - start


def main() -> None:
sizes: list[int] = [1000 * i for i in
range(1, 11)] # 1000, 2000, ..., 10000

algorithms: list[Callable[[list[int]], list[int]]] = [
selection.sort,
insertion.sort,
fusion.sort,
sorted
]
algorithms_names: list[str] = ["Selection", "Insertion", "Fusion",
"Python's sorted"]

# Loop to measure and print the time taken by each sorting algorithm for
# different array sizes
for algorithm, name in zip(algorithms, algorithms_names):
print(f"\nTime measurements for {name} sort:")
for size in sizes:
array: list[int] = generate_array_of_number(size)
elapsed_time: float = measure_time(algorithm, array)
print(f"Size: {size}, Time: {elapsed_time} seconds")


main()
Binary file added img/fusion graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/insertion graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/selection graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/tableau random list.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 43 additions & 1 deletion sort/fusion.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,44 @@
def sort(array: list[int]) -> list[int]:
return array
"""
Sorts an array in ascending order using the merge sort algorithm.

:param array: The array to be sorted.
:return: The sorted array.
"""
if len(array) <= 1:
return array

# Divide the array into two halves and sort each half.
mid: int = len(array) // 2
left: list[int] = sort(array[:mid])
right: list[int] = sort(array[mid:])

return merge(left, right)


def merge(left_array: list[int], right_array: list[int]) -> list[int]:
"""
Merge two lists in a sorted order.

:param left_array: The first list to be merged.
:param right_array: The second list to be merged.
:return: A new list that is a sorted merge of the two input lists.
"""
result: list[int] = []
left_index: int = 0
right_index: int = 0

while left_index < len(left_array) and right_index < len(right_array):
# Append the smaller element between
# left_array[left_index] and right_array[right_index] to the result
if left_array[left_index] < right_array[right_index]:
result.append(left_array[left_index])
left_index += 1
else:
result.append(right_array[right_index])
right_index += 1

# Append any remaining elements in left and right to the result
result.extend(left_array[left_index:])
result.extend(right_array[right_index:])
return result
12 changes: 12 additions & 0 deletions sort/insertion.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
def sort(array: list[int]) -> list[int]:
"""
Sort the given array in ascending order using the insertion sort algorithm.

:param array: The array to be sorted.
:return: The sorted array.
"""
for i in range(1, len(array)):
value_to_insert: int = array[i]
j: int = i - 1
while j >= 0 and value_to_insert < array[j]:
j -= 1
array.insert(j + 1, array.pop(i))
return array
13 changes: 11 additions & 2 deletions sort/range.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
def generate_array_of_number(array_size: int) -> list[int]:
return []
import random


def generate_array_of_number(n: int) -> list:
"""
Generate a list of random integers.
:param n: The number of elements to generate in the array.
:return: A list of random integers with 'n' elements.
"""
array: list[int] = [random.randint(0, 100) for _ in range(n)]
return array
8 changes: 7 additions & 1 deletion sort/recursion.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
def get_factorial(number: int) -> int:
return number
"""
Calculate the factorial of a given number.

:param number: The number for which the factorial needs to be calculated.
:return: The factorial of the given number.
"""
return 1 if number == 0 else number * get_factorial(number - 1)
17 changes: 17 additions & 0 deletions sort/selection.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,19 @@
def sort(array: list[int]) -> list[int]:
"""
Sorts an array in ascending order using the selection sort algorithm.

:param array: A list of integers to be sorted.
:return: The sorted list.
"""
for i in range(len(array)):
min_index: int = i

# Find the index of the smallest element
# in the unsorted part of the array
for j in range(i + 1, len(array)):
if array[j] < array[min_index]:
min_index = j

# Swap the smallest element with the first element of the unsorted part
array[i], array[min_index] = array[min_index], array[i]
return array