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
78 changes: 66 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +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.

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 ?
```diff
@@ La courbe a une allure linéaire. On peut en déduire que complexité de la fonction est O(n). @@
```
<img src="img/o.webp" width="400">

#### Quelques exemples de complexités courante :
Expand All @@ -75,8 +77,15 @@ Observez attentivement l'animation de tri par sélection ci-dessous pour en comp

<img src="img/selection.gif">

É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 ?
```diff
@@ On observe un parcours du tableau progressif. @@
@@ A chaque nouveau parcours du tableau, on identifie l'élément à trier et on @@
@@ parcours le reste du tableau à la recherche d'un autre plus petit. @@
@@ Arrivé à la fin du parcours, on échange l'élément comparé avec le plus petit @@
@@ trouvé dans le reste du tableau, sinon on ne fait rien. @@
@@ On passe à l'élément suivant. @@
```
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,16 +97,28 @@ 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é ?
```diff
@@ La courbe obtenue a une allure carrée. On en déduit une complexité proche @@
@@ de O(n^2). Ce n'est pas étonnant dans la mesure où le tableau est en bonne @@
@@ partie reparcouru pour chaque élément comparé, cela décuple au carré le nombre @@
@@ d'opération nécessaires au pire cas. @@
```
<img src="img/results/selection.png">

### 2. Tri par insertion

Observez attentivement l'animation de tri par insertion ci-dessous pour en comprendre le fonctionnement.

<img src="img/insertion.gif">

É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 ?
```diff
@@ On observe un parcours de tableau progressif. @@
@@ A chaque élément comparé, on parcours la portion de tableau le précedent. @@
@@ On insère celui-ci entre un élément plus petit et un élément plus grand. @@
@@ Puis on passe à l'élément suivant. @@
```
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,7 +130,12 @@ 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é ?
```diff
@@ Pour les même raison que citée précédemment, la complexité au pire cas est de @@
@@ O(n^2). L'imbrication de deux boucles justifie cette exponentialité. @@
```
<img src="img/results/insertion.png">

### 3. Tri par fusion

Expand Down Expand Up @@ -154,8 +180,15 @@ 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 ?
```diff
@@ On oberve un parcours de tableau dichotomique. @@
@@ A chaque nouvelle itération de la fonction, le tableau est séparé en deux @@
@@ puis réitéré jusqu'à ce qu'on obtienne un série de tableaux de taille 1. @@
@@ Les tableaux sont alors rassemblés à nouveaux avec un traitement de tri @@
@@ à chaque nouveau rassemblement, ce qui rédui considérablement la charge @@
@@ de l'algorithme de tri, au détriment de la pile. @@
```
Complétez la fonction `sort` du fichier `sort/fusion.py` en suivant les instructions suivantes.

Il vous faudra deux fonctions :
Expand All @@ -174,15 +207,34 @@ 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é ?
```diff
@@ En observant la courbe de la fusion, on remarque une fonction linéaire. Ce qui @@
@@ n'est pas absurde lorsqu'on sait qu'une boucle est appelée lors du tri, @@
@@ assoçié à une recherche dichotomique. On peut donc en déduire que la @@
@@ complexité est de O(nlog(n)). @@
```
<img src="img/results/fusion.png">

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 ?
```diff
@@ Le tri par fusion risque d'être plus lent pour des tableaux de très @@
@@ petite taille, engendré par le calcul supplémentaire du à la séparation @@
@@ dichotomique. On peut s'en douter en obesrvant la courbe d'un logarithme, qui @@
@@ croit très rapidement au départ avant d'avoir un comportement asymptotique à @@
@@ l'infini. @@
```

### 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 ;)
```diff
@@ Je n'ai plus les mots : @@
```
<img src="img/results/wtf.png">

## Pour rendre ce TP

Expand All @@ -193,3 +245,5 @@ Le nom de la PR doit contenir votre nom.
Vérifiez que votre code est conforme aux normes pep8 et aux autres critères de qualité dont nous avons parlé.

La PR doit également contenir un ou plusieurs graphiques présentant vos résultats sur la complexité des fonctions de tri.

<img src="img/results/all.png">
80 changes: 79 additions & 1 deletion __main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,83 @@
import time
import matplotlib.pyplot as plt
from sort.range import generate_array_of_number
import sort.selection as selection
import sort.insertion as insertion
import sort.fusion as fusion


def main():
print("Hello world")

tests: list[list[int]] = []

plt.figure()
plt.xlabel("Array Size")
plt.ylabel("Compute Time")
plt.title("Faisons le tri - Hugo JEUDY")

array_sizes: list[int] = []
generation_times: list[float] = []
selection_times: list[float] = []
insertion_times: list[float] = []
fusion_times: list[float] = []
sort_times: list[float] = []

for i in range(1000, 20001, 500):

print(f"Doing it with {i}")

array_sizes.append(i)

# compute array completion

timer_start: float = time.time()
rand_numbers_array: list[int] = generate_array_of_number(i)
timer_end: float = time.time()
generation_times.append(timer_end - timer_start)

# compute array selection sort

selection_array = rand_numbers_array.copy()
timer_start = time.time()
selection.sort(selection_array)
timer_end: float = time.time()
selection_times.append(timer_end - timer_start)

# compute array insertion sort

insertion_array = rand_numbers_array.copy()
timer_start = time.time()
insertion.sort(insertion_array)
timer_end: float = time.time()
insertion_times.append(timer_end - timer_start)

# compute array fusion sort

fusion_array = rand_numbers_array.copy()
timer_start = time.time()
fusion.sort(fusion_array)
timer_end: float = time.time()
fusion_times.append(timer_end - timer_start)

# compute array sort from python

sort_array = rand_numbers_array.copy()
timer_start = time.time()
sort_array.sort()
timer_end: float = time.time()
sort_times.append(timer_end - timer_start)

plt.plot(array_sizes, generation_times, "-",
color='lightgrey', label='Array Generation')
plt.plot(array_sizes, selection_times, "-",
color='darkolivegreen', label='Selection')
plt.plot(array_sizes, insertion_times, "-",
color='mediumslateblue', label='Insertion')
plt.plot(array_sizes, fusion_times, "-", color='peru', label='Fusion')
plt.plot(array_sizes, sort_times, "-", color='coral', label="Sort")

plt.legend()
plt.show()


main()
Binary file added img/results/Figure_2.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/results/all.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/results/fusion.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/results/insertion.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/results/selection.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/results/wtf.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 51 additions & 1 deletion sort/fusion.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,52 @@
import sort.insertion as insertion
import time


def sort(array: list[int]) -> list[int]:
return array
'''
Return the array by using fusion sort
'''

if len(array) <= 1:
return array
else:
half = len(array) // 2
return merge(sort(array[:half]), sort(array[half:]))


def merge(array: list[int], array2: list[int]) -> list[int]:
'''
Merge two arrays by sorting them
'''

sorted_array = []

array_index = 0
array2_index = 0

while len(sorted_array) != len(array) + len(array2):

# Avoid list out of range
if array_index >= len(array):

sorted_array.append(array2[array2_index])
array2_index += 1

elif array2_index >= len(array2):

sorted_array.append(array[array_index])
array_index += 1

# or check wich value is the smallest

elif array2[array2_index] < array[array_index]:

sorted_array.append(array2[array2_index])
array2_index += 1

elif array[array_index] <= array2[array2_index]:

sorted_array.append(array[array_index])
array_index += 1

return sorted_array
21 changes: 21 additions & 0 deletions sort/insertion.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,23 @@
def sort(array: list[int]) -> list[int]:
'''
Sort an array using insertion sort.
'''

for i in range(len(array)):
# checking every elements of the array

compared_element: int = array[i]

j: int = i - 1

while array[j] > compared_element and j >= 0:
# reverse the course of the array to place the currently selected
# element after another one if it is smaller

array[j + 1] = array[j]

j -= 1

array[j + 1] = compared_element

return array
9 changes: 8 additions & 1 deletion sort/range.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
import random


def generate_array_of_number(array_size: int) -> list[int]:
return []
'''
Return a random numbers (0 to 100 both included) array
with the given size
'''
return [random.randint(0, 100) for i in range(array_size)]
14 changes: 12 additions & 2 deletions sort/recursion.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
def get_factorial(number: int) -> int:
return number
def get_factorial(number: int, max: int = 100) -> int:
'''
Return the factorial of the number
'''

if (max == 0):
return 0

if number == 1:
return number
else:
return number * get_factorial(number - 1, max - 1)
24 changes: 24 additions & 0 deletions sort/selection.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,26 @@
def sort(array: list[int]) -> list[int]:
'''
Sort an array using selection sort.
'''
for i in range(len(array)):
# Checking all element of the array

compared_element: int = array[i]

temp_element: int = compared_element
switch_index: int = i

for j in range(i + 1, len(array)):
# checking the rest of the array in search for smaller elements

if (array[j] < temp_element):

temp_element = array[j]
switch_index = j

if compared_element != temp_element:
# switching the two elements if a smaller one has been found
array[i] = temp_element
array[switch_index] = compared_element

return array