From 961f9770679219a1a9de858367f221f95b4d7fac Mon Sep 17 00:00:00 2001 From: Spectre Date: Sun, 16 Feb 2025 20:29:43 +0100 Subject: [PATCH] Auto commit --- Dijkstra/algo.py | 212 +++++++++++++++-------- Dijkstra/fonctions.md | 46 +++++ graphes/DS_possible/elouan_fare.tar | Bin 376 -> 0 bytes graphes/leaudibidon/Water_jug(en_xz).tar | Bin 3408 -> 0 bytes pygame/bouncing_ball_project.zip | Bin 4347 -> 0 bytes 5 files changed, 190 insertions(+), 68 deletions(-) create mode 100644 Dijkstra/fonctions.md delete mode 100644 graphes/DS_possible/elouan_fare.tar delete mode 100644 graphes/leaudibidon/Water_jug(en_xz).tar delete mode 100644 pygame/bouncing_ball_project.zip diff --git a/Dijkstra/algo.py b/Dijkstra/algo.py index 51fd726..ebcc86c 100644 --- a/Dijkstra/algo.py +++ b/Dijkstra/algo.py @@ -1,74 +1,150 @@ -# https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm +def dijkstra(graph: dict, start: any) -> tuple: + """ + L'algorithme de Dijkstra pour trouver les plus courts chemins depuis un sommet de départ. -graph = { - 'A': [('B', 4), ('C', 2)], - 'B': [('C', 5), ('D', 10)], - 'C': [('D', 3), ('E', 8)], - 'D': [('E', 4), ('F', 11)], - 'E': [('G', 6)], - 'F': [('G', 2)], - 'G': [] -} + Args: + graph (dict): Le graphe à parcourir sous forme de dictionnaire, où les clés sont les sommets + et les valeurs sont des listes de tuples (voisin, poids). + start (any): Le sommet de départ. -p = {} - -def chemin(predecesseur, debut, fin): - chemin = [] - courant = fin - while courant != debut: - chemin.insert(0, courant) - courant = predecesseur.get(courant) - if courant is None: - return None - chemin.insert(0, debut) - return chemin - - -def initialisation(G, debut): - distances = {key: float('inf') for key in G} - distances[debut] = 0 - return distances - - -def trouve_min(Q, distances): - mini = float('inf') - sommet = None - for s in Q: - if distances[s] < mini: - mini = distances[s] - sommet = s - return sommet - -def poid(s1, s2): - for voisin, poids in graph[s1]: - if voisin == s2: - return poids - return float('inf') - -def distances_update(s1, s2, distances, predecesseur): - poids = poid(s1, s2) - if distances[s2] > distances[s1] + poids: - distances[s2] = distances[s1] + poids - predecesseur[s2] = s1 - -def dijkstra(G, debut='A'): - distances = initialisation(G, debut) - predecesseur = {} - Q = set(G.keys()) - - while Q: - s1 = trouve_min(Q, distances) - if s1 is None: - break - Q.remove(s1) - - for voisin, _ in G[s1]: - if voisin in Q: - distances_update(s1, voisin, distances, predecesseur) + Returns: + tuple: Un tuple contenant deux dictionnaires : + - Le premier associe à chaque sommet la distance minimale depuis le sommet de départ. + - Le second associe à chaque sommet (sauf le départ) son prédécesseur sur le chemin le plus court. + Exemples: + >>> graph = { + ... 'A': [('B', 4), ('C', 2)], + ... 'B': [('C', 5), ('D', 10)], + ... 'C': [('D', 3), ('E', 8)], + ... 'D': [('E', 4), ('F', 11)], + ... 'E': [('G', 6)], + ... 'F': [('G', 2)], + ... 'G': [] + ... } + >>> distances, predecesseur = dijkstra(graph, 'A') + >>> distances['A'] + 0 + >>> distances['B'] + 4 + >>> distances['C'] + 2 + >>> distances['D'] + 5 + >>> distances['E'] + 9 + >>> distances['F'] + 16 + >>> distances['G'] + 15 + >>> predecesseur['B'] + 'A' + >>> predecesseur['C'] + 'A' + >>> predecesseur['D'] + 'C' + >>> predecesseur['E'] + 'D' + >>> predecesseur['F'] + 'D' + >>> predecesseur['G'] + 'E' + """ + distances, predecesseur, unvisited = {}, {}, {} + for sommet in graph: + distances[sommet] = float('inf') + unvisited[sommet] = distances[sommet] + distances[start] = 0 + while unvisited: + current = min(unvisited, key=unvisited.get) + del unvisited[current] + for voisin, poid in graph[current]: + new_distance = distances[current] + poid + if new_distance < distances[voisin]: + distances[voisin] = new_distance + predecesseur[voisin] = current + if voisin in unvisited: + unvisited[voisin] = new_distance return distances, predecesseur + +def reconstruire_chemin(predecesseur: dict, start: any, end: any) -> list: + """reconstruit le chemin grace au predecesseur + + Args: + predecesseur (dict): les predecesseurs + start (any): le debut + end (any): la fin + + Returns: + list: renvoie une liste contenant le chemin le plus court (si aucun trouver alors renvoie liste vide) + Examples: + >>> pred = {'B': 'A', 'C': 'A', 'D': 'C', 'E': 'D', 'F': 'D', 'G': 'E'} + >>> reconstruire_chemin(pred, 'A', 'F') + ['A', 'C', 'D', 'F'] + >>> reconstruire_chemin(pred, 'A', 'G') + ['A', 'C', 'D', 'E', 'G'] + """ + chemin = [end] + current = end + while current != start: + if current not in predecesseur: + return [] + current = predecesseur[current] + chemin.append(current) + chemin.reverse() + return chemin + +def solutions_dijkstra(graph: dict, start: any) -> dict: + """elle renvoie le dictionnaire des noeud et distances grace au chemin + + Args: + graph (dict): le graphe + start (any): le debut + + Returns: + dict: contenant les noeuds et leurs distances + Exemples: + >>> graph = { + ... 'A': [('B', 4), ('C', 2)], + ... 'B': [('C', 5), ('D', 10)], + ... 'C': [('D', 3), ('E', 8)], + ... 'D': [('E', 4), ('F', 11)], + ... 'E': [('G', 6)], + ... 'F': [('G', 2)], + ... 'G': [] + ... } + >>> sol = solutions_dijkstra(graph, 'A') + >>> sol['F'] + {'distance': 16, 'chemin': ['A', 'C', 'D', 'F']} + >>> sol['G'] + {'distance': 15, 'chemin': ['A', 'C', 'D', 'E', 'G']} + """ + distances, predecesseur = dijkstra(graph, start) + solutions = {} + for sommet in graph: + if sommet == start: + chemin = [start] + else: + chemin = reconstruire_chemin(predecesseur, start, sommet) + if not chemin: + chemin = None + solutions[sommet] = {"distance": distances[sommet], "chemin": chemin} + return solutions + if __name__ == "__main__": - distances, predecesseur = dijkstra(graph, 'A') - print("Distances depuis A :", distances) - print("Chemin le plus court de A à G :", chemin(predecesseur, 'A', 'G')) + import doctest + doctest.testmod(verbose=True) + graph = { + 'A': [('B', 4), ('C', 2)], + 'B': [('C', 5), ('D', 10)], + 'C': [('D', 3), ('E', 8)], + 'D': [('E', 4), ('F', 11)], + 'E': [('G', 6)], + 'F': [('G', 2)], + 'G': [] + } + solution = solutions_dijkstra(graph, 'A') + for sommet, info in solution.items(): + print(f"sommet: {sommet} ----- Distance: {info['distance']} ------- chemin: {info['chemin']}") + diff --git a/Dijkstra/fonctions.md b/Dijkstra/fonctions.md new file mode 100644 index 0000000..fd91053 --- /dev/null +++ b/Dijkstra/fonctions.md @@ -0,0 +1,46 @@ +# Dijkstra +## Fonctions +### `dijkstra(graph: dict, start: any) -> tuple` +- **Paramètres :** + - `graph` : Dictionnaire représentant le graphe. Chaque clé est un noeud et sa valeur est une liste de tuples `(voisin, poids)`. + - `start` : Le noeud de départ. +- **Retourne :** + - Un tuple contenant : + - `distances` : Un dictionnaire associant à chaque noeud la distance minimale depuis `start`. + - `predecesseur` : Un dictionnaire associant à chaque noeud son prédécesseur dans le chemin le plus court. + +--- +### `reconstruct_chemin(predecesseur: dict, start: any, end: any) -> list` + +- **Paramètres :** + - `predecesseur` : Dictionnaire des prédécesseurs. + - `start` : Le noeud de départ. + - `end` : Le noeud d'arrivée. +- **Retourne :** + - Une liste représentant le chemin le plus court de `start` à `end`. + Si aucun chemin n'est trouvé, la fonction renvoie une liste vide. + +--- +### `solutions_dijkstra(graph: dict, start: any) -> dict` + +- **Paramètres :** + - `graph` : Dictionnaire représentant le graphe. + - `start` : Le noeud de départ. +- **Retourne :** + - Un dictionnaire où chaque clé est un noeud du graphe et la valeur associée est un sous-dictionnaire contenant : + - `"distance"` : La distance minimale depuis `start`. + - `"chemin"` : Le chemin le plus court sous forme de liste de noeuds None si pas trouver. + +--- +## Utilisation +Le graphe doit être défini sous forme de dictionnaire. Exemple : + ```python +graph = { + 'A': [('B', 4), ('C', 2)], + 'B': [('C', 5), ('D', 10)], + 'C': [('D', 3), ('E', 8)], + 'D': [('E', 4), ('F', 11)], + 'E': [('G', 6)], + 'F': [('G', 2)], + 'G': [] +} diff --git a/graphes/DS_possible/elouan_fare.tar b/graphes/DS_possible/elouan_fare.tar deleted file mode 100644 index 4d6ac82154165f8e3966566914c2af8365841c0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 376 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 diff --git a/pygame/bouncing_ball_project.zip b/pygame/bouncing_ball_project.zip deleted file mode 100644 index d0b275528abb9bc362ed984fd3434ca5e9b93cf0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4347 zcmcgwTaVjB6i#n|4TzWWKH5Aap;zcCf;xqMu~_gab1iiM{=m_w2LMvyF7ii)W8e8#0!I1 z^i?c+_>ssUQL$YX9qC~<`h_pWKm{s^l)by&zSBBvyRFUk`krWt8;ypr@2($q@|~YG z8j#-%$G#dz_Qvk|-X^A2S5{Z+!u(US_x88j)ZM5H`dhPY?W{vCRclt6U6Z~SOY)E% z9EN=;C1=gb$WWxrjJ&I=7s&tyQmuV29{FxWAxpk6|?ieZLu@!9sf)+B$QBP@e&{F;)Mfdg(@3%G% zJDvT#t^F_e$fgA)yr>{d1phu$!%ph~NeUVCQ(qscNzTlE1{<5=iaf{RN_OYl>dsS@Kr>0}X)$DW93 zci4N;mnh(@N(K85!Sy7GyzV%O#hQrZ1VvOAPe);l&qRNoo_Gnh@WK3hDmg}J&~&4^ zF4CZAXKbsl2EuizHeFX#;e|gCH9_H|pN=-u6xSN2hYdEx^+v;)_ObP*_%z?guAt9Z zHIn2N3gJ5Bv|Z!WyjeDKrOEC%q-m;y)@cUPWg-XIS1qJ}Yrk(XprMAc@#XyZP0`?_ z)5F@mbV6#B%Yuh_jaTy0w*-(;80|d1SbMtobOL)`%%~sMJAZzTOrrNgycu{StqRzN z7y_qX3DZS%CUC|(m%M-d^3xyfi=`61@559iACFa%%;)bQ3WvE|w2l)MF@PMg8;Hz-jKCXk;sXmP zP-G0KVD=APZIz6pK#%T)0nQ$)H5e#fV>gWYdgNZ%_Xape{EAGmNCS`xgbxf;fv-+* zQr6jqCwdi%5=u7qx;WP0=?S)7$CBd>{cua`IQ?EUMC=7&fXJs%IUfrh%D0F`pZ5To z|EE~UhvAsW*W1Q|LWnY7X7Dj-&*3>ENan;Np}IadbWSmEbo!Be;zX*K=p(UCY^}i% zfuE=-4y!{&gsLbIsO1%qy1XlOlpR==4e)i{0Lg{p1LULPx9J$1rTq3vGAqswCm~MKWG9EF%GEl@vtIhq>B1lncn%s*~ zETsdQq1wznPhZTC&(j}?DDx2v;GH25Z_hprJAPB{DddUjO$+_COtdVv=_XL5+hO;i zN@80Fu&HSYsM0iW%_$(D*ESq)p12B878{zWjv^2HH$qk00?%vtDovti5!qzc%Bu7{ zLH8cRQcc%lu9`B`$6nHHDSzA1-3SG*F7uL;!MH}-PSSMS^Knz7dm2wzHjCh4XsK$s zloaVk%DI|Fa&t}Kv6*|p!Opq!moF^7!~^5_dH#$(YjBnUW}@CZ1wNP;d=-9Yf`8i!(EMQM5_FbIm+)ulT&Z;W H5w-pUGVBX}