mirror of
https://github.com/Fare-spec/cours.git
synced 2025-12-08 03:00:37 +00:00
formatte file
This commit is contained in:
@@ -1,27 +1,26 @@
|
||||
graphe = {
|
||||
"node1": ["node2","node4"],
|
||||
"node2": ["node2","node3","node6"],
|
||||
"node1": ["node2", "node4"],
|
||||
"node2": ["node2", "node3", "node6"],
|
||||
"node3": ["node5"],
|
||||
"node5": ["node5","node6"],
|
||||
"node4": ["node1","node5"],
|
||||
"node6": []
|
||||
"node5": ["node5", "node6"],
|
||||
"node4": ["node1", "node5"],
|
||||
"node6": [],
|
||||
}
|
||||
print(graphe["node1"])
|
||||
|
||||
|
||||
def bfs(graphe, start_node):
|
||||
queue = [start_node]
|
||||
|
||||
|
||||
visited = set()
|
||||
while queue:
|
||||
node = queue.pop(0)
|
||||
node = queue.pop(0)
|
||||
if node not in visited:
|
||||
print(node)
|
||||
visited.add(node)
|
||||
print(node)
|
||||
visited.add(node)
|
||||
for neighbor in graphe[node]:
|
||||
if neighbor not in visited:
|
||||
queue.append(neighbor)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bfs(graphe,"node1")
|
||||
bfs(graphe, "node1")
|
||||
|
||||
@@ -2,29 +2,31 @@
|
||||
|
||||
import heapq
|
||||
|
||||
|
||||
def dijkstra(graph, source):
|
||||
distances = {node: float('inf') for node in graph}
|
||||
distances = {node: float("inf") for node in graph}
|
||||
distances[source] = 0
|
||||
|
||||
|
||||
previous = {node: None for node in graph}
|
||||
|
||||
|
||||
queue = [(0, source)]
|
||||
|
||||
|
||||
while queue:
|
||||
current_distance, current_node = heapq.heappop(queue)
|
||||
|
||||
|
||||
if current_distance > distances[current_node]:
|
||||
continue
|
||||
|
||||
|
||||
for neighbor, weight in graph[current_node]:
|
||||
distance = current_distance + weight
|
||||
if distance < distances[neighbor]:
|
||||
distances[neighbor] = distance
|
||||
previous[neighbor] = current_node
|
||||
heapq.heappush(queue, (distance, neighbor))
|
||||
|
||||
|
||||
return distances, previous
|
||||
|
||||
|
||||
def reconstruct_path(previous, start, end):
|
||||
path = []
|
||||
node = end
|
||||
@@ -34,22 +36,22 @@ def reconstruct_path(previous, start, end):
|
||||
path.reverse()
|
||||
return path
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
if __name__ == "__main__":
|
||||
graph = {
|
||||
"R1": [("R2", 1)],
|
||||
"R2": [("R3", 1), ("R5", 10)],
|
||||
"R3": [("R4", 1), ("R5", 1)],
|
||||
"R5": [("R4", 10)],
|
||||
"R4": []
|
||||
"R4": [],
|
||||
}
|
||||
|
||||
|
||||
source = "R1"
|
||||
destination = "R4"
|
||||
|
||||
|
||||
distances, previous = dijkstra(graph, source)
|
||||
|
||||
|
||||
print("Shortest distances from", source, ":", distances)
|
||||
|
||||
|
||||
path = reconstruct_path(previous, source, destination)
|
||||
print("Shortest path from", source, "to", destination, ":", path)
|
||||
|
||||
|
||||
@@ -2,345 +2,367 @@
|
||||
# -*- Coding: utf-8 -*-
|
||||
|
||||
|
||||
|
||||
class Graphe_Oriente(object):
|
||||
"""
|
||||
Classe des Graphes Orientés (GO).
|
||||
"""
|
||||
Classe des Graphes Orientés (GO).
|
||||
|
||||
Les graphes sont représentés par
|
||||
- une liste de sommets
|
||||
- leur liste d'adjacence
|
||||
Les graphes sont représentés par
|
||||
- une liste de sommets
|
||||
- leur liste d'adjacence
|
||||
|
||||
Attributs (publics)
|
||||
- sommets : liste des sommets
|
||||
- voisins : dictionnaire des listes d'adjacence
|
||||
Attributs (publics)
|
||||
- sommets : liste des sommets
|
||||
- voisins : dictionnaire des listes d'adjacence
|
||||
|
||||
Méthodes (publiques)
|
||||
- ajoute_sommet : ajout d'un sommet
|
||||
- ajoute_arcs : ajout d'un arc
|
||||
"""
|
||||
Méthodes (publiques)
|
||||
- ajoute_sommet : ajout d'un sommet
|
||||
- ajoute_arcs : ajout d'un arc
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.sommets = list()
|
||||
self.voisins = dict()
|
||||
return None
|
||||
def __init__(self):
|
||||
self.sommets = list()
|
||||
self.voisins = dict()
|
||||
return None
|
||||
|
||||
def ajoute_sommet(self, s):
|
||||
"""
|
||||
Ajoute le sommet s à l'instance de GO.
|
||||
def ajoute_sommet(self, s):
|
||||
"""
|
||||
Ajoute le sommet s à l'instance de GO.
|
||||
|
||||
:param s data: etiquette du sommet
|
||||
"""
|
||||
:param s data: etiquette du sommet
|
||||
"""
|
||||
|
||||
self.sommets.append(s)
|
||||
self.voisins[s] = list()
|
||||
return None
|
||||
self.sommets.append(s)
|
||||
self.voisins[s] = list()
|
||||
return None
|
||||
|
||||
def ajoute_arc(self, origine, extremite):
|
||||
"""
|
||||
Ajoute l'arc origine -> extremite à l'instance de GO.
|
||||
def ajoute_arc(self, origine, extremite):
|
||||
"""
|
||||
Ajoute l'arc origine -> extremite à l'instance de GO.
|
||||
|
||||
:param self Graphe_Oriente: instance à laquelle ajouter un arc
|
||||
:param origine data: un sommet de l'instance, origine de l'arc
|
||||
:param extremite data: un sommet de l'instance, extremité de l'arc
|
||||
:param self Graphe_Oriente: instance à laquelle ajouter un arc
|
||||
:param origine data: un sommet de l'instance, origine de l'arc
|
||||
:param extremite data: un sommet de l'instance, extremité de l'arc
|
||||
|
||||
:return None:
|
||||
:return None:
|
||||
|
||||
:effet de bord: Modification de l'instance
|
||||
:effet de bord: Modification de l'instance
|
||||
|
||||
:pré-condition: les sommets doivent exister
|
||||
"""
|
||||
assert origine in self.sommets, "{} inconnu".format(origine)
|
||||
assert extremite in self.sommets, "{} inconnu".format(extremite)
|
||||
self.voisins[origine].append(extremite)
|
||||
return None
|
||||
:pré-condition: les sommets doivent exister
|
||||
"""
|
||||
assert origine in self.sommets, "{} inconnu".format(origine)
|
||||
assert extremite in self.sommets, "{} inconnu".format(extremite)
|
||||
self.voisins[origine].append(extremite)
|
||||
return None
|
||||
|
||||
|
||||
def construire_chemins(graphe, depart):
|
||||
"""
|
||||
Construit tous les cheminement du graphe de depart donné
|
||||
"""
|
||||
Construit tous les cheminement du graphe de depart donné
|
||||
|
||||
:param graphe GO: graphe à parcourir
|
||||
:param depart data: sommet de départ dans le graphe
|
||||
:param graphe GO: graphe à parcourir
|
||||
:param depart data: sommet de départ dans le graphe
|
||||
|
||||
:return resultat dict: dictionnaire
|
||||
- clef : sommet atteint
|
||||
- valeur : tuple (longueur itinéraire, sommet prédécesseur)
|
||||
:return resultat dict: dictionnaire
|
||||
- clef : sommet atteint
|
||||
- valeur : tuple (longueur itinéraire, sommet prédécesseur)
|
||||
|
||||
:effet de bord: Aucun
|
||||
>>> graphe = Graphe_Oriente()
|
||||
>>> graphe.ajoute_sommet('A')
|
||||
>>> graphe.ajoute_sommet('B')
|
||||
>>> graphe.ajoute_sommet('C')
|
||||
>>> graphe.ajoute_arc('A', 'B')
|
||||
>>> graphe.ajoute_arc('B', 'C')
|
||||
>>> construire_chemins(graphe, 'A')
|
||||
{'A': (0, None), 'B': (1, 'A'), 'C': (2, 'B')}
|
||||
"""
|
||||
resultat = dict()
|
||||
file = [depart] # initialise une file (sous forme de liste ici)
|
||||
resultat[depart] = (0, None) # None car le depart n'a aucun predesseceur
|
||||
while len(file) > 0:
|
||||
sommet = file.pop(0) # retire le premier element de la file -> FIFO
|
||||
for voisin in graphe.voisins[sommet]: # Parcours tous les voisins du sommet
|
||||
if voisin not in resultat: # Verifie que cette partie de l arbre (ou du graphe) n a pas deja ete explorer
|
||||
distance = resultat[sommet][0] + 1 # Definie distance -> Distance du dernier sommet + 1
|
||||
resultat[voisin] = (distance, sommet) # Insere le nouveau sommet dans le dictionnaire
|
||||
file.append(voisin) # Permet la reiteration de la boucle a partir de se sommet
|
||||
:effet de bord: Aucun
|
||||
>>> graphe = Graphe_Oriente()
|
||||
>>> graphe.ajoute_sommet('A')
|
||||
>>> graphe.ajoute_sommet('B')
|
||||
>>> graphe.ajoute_sommet('C')
|
||||
>>> graphe.ajoute_arc('A', 'B')
|
||||
>>> graphe.ajoute_arc('B', 'C')
|
||||
>>> construire_chemins(graphe, 'A')
|
||||
{'A': (0, None), 'B': (1, 'A'), 'C': (2, 'B')}
|
||||
"""
|
||||
resultat = dict()
|
||||
file = [depart] # initialise une file (sous forme de liste ici)
|
||||
resultat[depart] = (0, None) # None car le depart n'a aucun predesseceur
|
||||
while len(file) > 0:
|
||||
sommet = file.pop(0) # retire le premier element de la file -> FIFO
|
||||
for voisin in graphe.voisins[sommet]: # Parcours tous les voisins du sommet
|
||||
if (
|
||||
voisin not in resultat
|
||||
): # Verifie que cette partie de l arbre (ou du graphe) n a pas deja ete explorer
|
||||
distance = (
|
||||
resultat[sommet][0] + 1
|
||||
) # Definie distance -> Distance du dernier sommet + 1
|
||||
resultat[voisin] = (
|
||||
distance,
|
||||
sommet,
|
||||
) # Insere le nouveau sommet dans le dictionnaire
|
||||
file.append(
|
||||
voisin
|
||||
) # Permet la reiteration de la boucle a partir de se sommet
|
||||
|
||||
return resultat
|
||||
return resultat
|
||||
|
||||
|
||||
def reconstruire_chemin_vers(dico_chemins, *arrivee):
|
||||
"""
|
||||
Remonte tout l'itinéraire depuis un sommet fixé
|
||||
vers un ou des sommets du graphe
|
||||
"""
|
||||
Remonte tout l'itinéraire depuis un sommet fixé
|
||||
vers un ou des sommets du graphe
|
||||
|
||||
:param dico_chemins dict: table des longueurs/prédécessurs
|
||||
:param *arrivee: nombre quelconque de sommet à atteindre
|
||||
(si vide, on considère tous les sommets)
|
||||
:return resultat list: liste des chemins ie des listes de sommets traversés
|
||||
>>> dico_chemins = {'A': (0, None), 'B': (1, 'A'), 'C': (2, 'B')}
|
||||
>>> reconstruire_chemin_vers(dico_chemins, 'C')
|
||||
[['A', 'B', 'C']]
|
||||
"""
|
||||
chemins = list()
|
||||
cibles = arrivee # Creer une liste avec les sommets a remonter
|
||||
if len(cibles) == 0:
|
||||
return list(dico_chemins.keys()) # si la liste est vide, on renvoie les chemins (sans leurs attributs)
|
||||
for sommet in cibles:
|
||||
sous_chemin = []
|
||||
current = sommet
|
||||
while current is not None:
|
||||
sous_chemin.insert(0, current) # on insere le sommet au début de la liste (permet de maintenir l ordre)
|
||||
current = dico_chemins[current][1] # on change current avec le sommet predesseceur pour que la boucle continue
|
||||
chemins.append(sous_chemin)
|
||||
return chemins
|
||||
:param dico_chemins dict: table des longueurs/prédécessurs
|
||||
:param *arrivee: nombre quelconque de sommet à atteindre
|
||||
(si vide, on considère tous les sommets)
|
||||
:return resultat list: liste des chemins ie des listes de sommets traversés
|
||||
>>> dico_chemins = {'A': (0, None), 'B': (1, 'A'), 'C': (2, 'B')}
|
||||
>>> reconstruire_chemin_vers(dico_chemins, 'C')
|
||||
[['A', 'B', 'C']]
|
||||
"""
|
||||
chemins = list()
|
||||
cibles = arrivee # Creer une liste avec les sommets a remonter
|
||||
if len(cibles) == 0:
|
||||
return list(
|
||||
dico_chemins.keys()
|
||||
) # si la liste est vide, on renvoie les chemins (sans leurs attributs)
|
||||
for sommet in cibles:
|
||||
sous_chemin = []
|
||||
current = sommet
|
||||
while current is not None:
|
||||
sous_chemin.insert(
|
||||
0, current
|
||||
) # on insere le sommet au début de la liste (permet de maintenir l ordre)
|
||||
current = dico_chemins[current][
|
||||
1
|
||||
] # on change current avec le sommet predesseceur pour que la boucle continue
|
||||
chemins.append(sous_chemin)
|
||||
return chemins
|
||||
|
||||
|
||||
def affichage_chemin(chemin):
|
||||
"""
|
||||
Produit le texte d'affichage d'un chemin
|
||||
"""
|
||||
Produit le texte d'affichage d'un chemin
|
||||
|
||||
:param chemin list: liste des sommets constituant le chemin
|
||||
:return string: chemin mis en forme pour affichage
|
||||
"""
|
||||
long = len(chemin) - 1
|
||||
return "{} etapes :\n".format(long) + "\n\t-> ".join(
|
||||
[str(sommet) for sommet in chemin]
|
||||
)
|
||||
:param chemin list: liste des sommets constituant le chemin
|
||||
:return string: chemin mis en forme pour affichage
|
||||
"""
|
||||
long = len(chemin) - 1
|
||||
return "{} etapes :\n".format(long) + "\n\t-> ".join(
|
||||
[str(sommet) for sommet in chemin]
|
||||
)
|
||||
|
||||
|
||||
# DEFINITION DES OPERATIONS DE TRANSITION
|
||||
|
||||
|
||||
def vider(numero, etat):
|
||||
"""
|
||||
Vide un bidon
|
||||
"""
|
||||
Vide un bidon
|
||||
|
||||
:param numero INT: index du bidon
|
||||
:param etat tuple: etat des bidons avant l'opération
|
||||
:return tuple: nouvel etat aprés opération
|
||||
:effet de bord: aucun
|
||||
>>> vider(1,(3,5,2))
|
||||
(3, 0, 2)
|
||||
"""
|
||||
index_b = list(etat)
|
||||
index_b[numero] = 0
|
||||
return tuple(index_b)
|
||||
:param numero INT: index du bidon
|
||||
:param etat tuple: etat des bidons avant l'opération
|
||||
:return tuple: nouvel etat aprés opération
|
||||
:effet de bord: aucun
|
||||
>>> vider(1,(3,5,2))
|
||||
(3, 0, 2)
|
||||
"""
|
||||
index_b = list(etat)
|
||||
index_b[numero] = 0
|
||||
return tuple(index_b)
|
||||
|
||||
|
||||
def remplir(numero, etat, capacites):
|
||||
"""
|
||||
Remplit un bidon
|
||||
"""
|
||||
Remplit un bidon
|
||||
|
||||
:param numero INT: index du bidon
|
||||
:param etat tuple: etat des bidons avant l'opération
|
||||
:param capacites tuple: capacités des bidons
|
||||
:return tuple: nouvel etat aprés opération
|
||||
:effet de bord: aucun
|
||||
:param numero INT: index du bidon
|
||||
:param etat tuple: etat des bidons avant l'opération
|
||||
:param capacites tuple: capacités des bidons
|
||||
:return tuple: nouvel etat aprés opération
|
||||
:effet de bord: aucun
|
||||
|
||||
>>> remplir(1, (3, 2, 1), (5, 4, 3))
|
||||
(3, 4, 1)
|
||||
"""
|
||||
cap = list(capacites)
|
||||
index_b = list(etat)
|
||||
index_b[numero] = cap[numero]
|
||||
return tuple(index_b)
|
||||
>>> remplir(1, (3, 2, 1), (5, 4, 3))
|
||||
(3, 4, 1)
|
||||
"""
|
||||
cap = list(capacites)
|
||||
index_b = list(etat)
|
||||
index_b[numero] = cap[numero]
|
||||
return tuple(index_b)
|
||||
|
||||
|
||||
def transvaser(source, destination, etat, capacites):
|
||||
"""
|
||||
Transvase un bidon dans un autre
|
||||
"""
|
||||
Transvase un bidon dans un autre
|
||||
|
||||
:param origine int: index du bidon source
|
||||
:param destination int: index du bidon destination
|
||||
:param etas tuple: etat des bidons avant l'opération
|
||||
:param capacites tuple: capacités des bidons
|
||||
:return tuple: nouvel etat aprés opération
|
||||
:effet de bord: aucun
|
||||
>>> transvaser(0, 1, (3, 2, 1), (5, 4, 3))
|
||||
(1, 4, 1)
|
||||
"""
|
||||
transfer_amount = min(
|
||||
list(etat)[source], list(capacites)[destination] - list(etat)[destination]
|
||||
)
|
||||
new_state = list(etat)
|
||||
:param origine int: index du bidon source
|
||||
:param destination int: index du bidon destination
|
||||
:param etas tuple: etat des bidons avant l'opération
|
||||
:param capacites tuple: capacités des bidons
|
||||
:return tuple: nouvel etat aprés opération
|
||||
:effet de bord: aucun
|
||||
>>> transvaser(0, 1, (3, 2, 1), (5, 4, 3))
|
||||
(1, 4, 1)
|
||||
"""
|
||||
transfer_amount = min(
|
||||
list(etat)[source], list(capacites)[destination] - list(etat)[destination]
|
||||
)
|
||||
new_state = list(etat)
|
||||
|
||||
new_state[source] -= transfer_amount
|
||||
new_state[destination] += transfer_amount
|
||||
return tuple(new_state)
|
||||
new_state[source] -= transfer_amount
|
||||
new_state[destination] += transfer_amount
|
||||
return tuple(new_state)
|
||||
|
||||
|
||||
# FONCTION LIEES AU GRAPHE DU WATER_JUG
|
||||
|
||||
|
||||
# Pour construire les etats
|
||||
def produit_cartesien(*listes):
|
||||
"""
|
||||
Concatène les tuples issus des différentes listes
|
||||
"""
|
||||
Concatène les tuples issus des différentes listes
|
||||
|
||||
:param *listes: un nombre quelconque de listes de tuples
|
||||
:return list: une liste des tuples concaténés
|
||||
:param *listes: un nombre quelconque de listes de tuples
|
||||
:return list: une liste des tuples concaténés
|
||||
|
||||
Exemple
|
||||
--------
|
||||
>>> produit_cartesien([(1,2), (3, 4)], [(5, 6), (7, 8,)])
|
||||
[(1, 2, 5, 6), (1, 2, 7, 8), (3, 4, 5, 6), (3, 4, 7, 8)]
|
||||
"""
|
||||
if listes == None:
|
||||
return []
|
||||
if len(listes) == 1:
|
||||
return listes[0]
|
||||
result = []
|
||||
for elt in listes[0]:
|
||||
for tuples in produit_cartesien(*listes[1:]):
|
||||
result.append(elt + tuples)
|
||||
return result
|
||||
Exemple
|
||||
--------
|
||||
>>> produit_cartesien([(1,2), (3, 4)], [(5, 6), (7, 8,)])
|
||||
[(1, 2, 5, 6), (1, 2, 7, 8), (3, 4, 5, 6), (3, 4, 7, 8)]
|
||||
"""
|
||||
if listes == None:
|
||||
return []
|
||||
if len(listes) == 1:
|
||||
return listes[0]
|
||||
result = []
|
||||
for elt in listes[0]:
|
||||
for tuples in produit_cartesien(*listes[1:]):
|
||||
result.append(elt + tuples)
|
||||
return result
|
||||
|
||||
|
||||
def creer_water_jug(*capacites):
|
||||
"""
|
||||
Création du graphe de Water Jug en fonction des capacités des bidons
|
||||
"""
|
||||
Création du graphe de Water Jug en fonction des capacités des bidons
|
||||
|
||||
:param *capacites: capacités des bidons disponibles
|
||||
:return resultat GO: le graphe orienté du W_J
|
||||
:pre-condition: au moins 2 bidons
|
||||
:param *capacites: capacités des bidons disponibles
|
||||
:return resultat GO: le graphe orienté du W_J
|
||||
:pre-condition: au moins 2 bidons
|
||||
|
||||
:effet de bord: Aucun
|
||||
"""
|
||||
nb_bidons = len(capacites)
|
||||
assert nb_bidons >= 2, "Pas assez de bidons"
|
||||
resultat = Graphe_Oriente()
|
||||
# CREATION DES SOMMETS
|
||||
etats_marginaux = [
|
||||
[(contenu,) for contenu in range(1 + capacite)] for capacite in capacites
|
||||
]
|
||||
etats_systeme = produit_cartesien(*etats_marginaux)
|
||||
for etat in etats_systeme:
|
||||
resultat.ajoute_sommet(etat)
|
||||
# CREATION DES TRANSITIONS
|
||||
for sommet in resultat.sommets:
|
||||
voisins = list()
|
||||
# VIDER
|
||||
for bidon in range(nb_bidons):
|
||||
voisin = vider(bidon, sommet)
|
||||
if voisin != sommet and not (voisin in voisins):
|
||||
voisins.append(voisin)
|
||||
# REMPLIR
|
||||
for bidon in range(nb_bidons):
|
||||
voisin = remplir(bidon, sommet, capacites)
|
||||
if voisin != sommet and not (voisin in voisins):
|
||||
voisins.append(voisin)
|
||||
# TRANSVASER
|
||||
for origine in range(nb_bidons):
|
||||
for destination in range(nb_bidons):
|
||||
if origine != destination:
|
||||
voisin = transvaser(origine, destination, sommet, capacites)
|
||||
if voisin != sommet and not (voisin in voisins):
|
||||
voisins.append(voisin)
|
||||
# CREATION LISTES ADJACENCE
|
||||
for voisin in voisins:
|
||||
resultat.ajoute_arc(sommet, voisin)
|
||||
return resultat
|
||||
:effet de bord: Aucun
|
||||
"""
|
||||
nb_bidons = len(capacites)
|
||||
assert nb_bidons >= 2, "Pas assez de bidons"
|
||||
resultat = Graphe_Oriente()
|
||||
# CREATION DES SOMMETS
|
||||
etats_marginaux = [
|
||||
[(contenu,) for contenu in range(1 + capacite)] for capacite in capacites
|
||||
]
|
||||
etats_systeme = produit_cartesien(*etats_marginaux)
|
||||
for etat in etats_systeme:
|
||||
resultat.ajoute_sommet(etat)
|
||||
# CREATION DES TRANSITIONS
|
||||
for sommet in resultat.sommets:
|
||||
voisins = list()
|
||||
# VIDER
|
||||
for bidon in range(nb_bidons):
|
||||
voisin = vider(bidon, sommet)
|
||||
if voisin != sommet and not (voisin in voisins):
|
||||
voisins.append(voisin)
|
||||
# REMPLIR
|
||||
for bidon in range(nb_bidons):
|
||||
voisin = remplir(bidon, sommet, capacites)
|
||||
if voisin != sommet and not (voisin in voisins):
|
||||
voisins.append(voisin)
|
||||
# TRANSVASER
|
||||
for origine in range(nb_bidons):
|
||||
for destination in range(nb_bidons):
|
||||
if origine != destination:
|
||||
voisin = transvaser(origine, destination, sommet, capacites)
|
||||
if voisin != sommet and not (voisin in voisins):
|
||||
voisins.append(voisin)
|
||||
# CREATION LISTES ADJACENCE
|
||||
for voisin in voisins:
|
||||
resultat.ajoute_arc(sommet, voisin)
|
||||
return resultat
|
||||
|
||||
|
||||
def atteindre(quantite, graphe_water_jug, depart=None, plus_court=False):
|
||||
"""
|
||||
Résolution du problème pour une quantite donnée
|
||||
"""
|
||||
Résolution du problème pour une quantite donnée
|
||||
|
||||
:param quantite int: la quantité à mesurer
|
||||
:param graphe_water_jug GO: le graphe de la situation
|
||||
:param depart tuple: etat initial, sommet d'origine dans le graphe
|
||||
(bidons tous vides si depart est None, ie non fourni)
|
||||
:param plus_court bool: si vrai, seul le(s) plus court(s) chemin(s)
|
||||
est (sont) retenu(s)
|
||||
:param quantite int: la quantité à mesurer
|
||||
:param graphe_water_jug GO: le graphe de la situation
|
||||
:param depart tuple: etat initial, sommet d'origine dans le graphe
|
||||
(bidons tous vides si depart est None, ie non fourni)
|
||||
:param plus_court bool: si vrai, seul le(s) plus court(s) chemin(s)
|
||||
est (sont) retenu(s)
|
||||
|
||||
:return list: la liste des tuples (sommet arrivee, nb d'etapes, ititneraire) ok
|
||||
"""
|
||||
if depart is None:
|
||||
nb_bidons = len(graphe_water_jug.sommets[0])
|
||||
depart = tuple([0 for _ in range(nb_bidons)])
|
||||
chemins = construire_chemins(graphe_water_jug, depart)
|
||||
resultat = list()
|
||||
for sommet in chemins:
|
||||
if quantite in sommet:
|
||||
longueur, _ = chemins[sommet]
|
||||
chemin = reconstruire_chemin_vers(chemins, sommet).pop()
|
||||
index = len(resultat)
|
||||
resultat.append((sommet, longueur, chemin))
|
||||
while index > 0:
|
||||
if resultat[index - 1][1] < longueur:
|
||||
break
|
||||
else:
|
||||
resultat[index], resultat[index - 1] = (
|
||||
resultat[index - 1],
|
||||
resultat[index],
|
||||
)
|
||||
index -= 1
|
||||
if len(resultat) < 2 or not (plus_court):
|
||||
return resultat
|
||||
mini = resultat[0][1]
|
||||
return [element for element in resultat if element[1] == mini]
|
||||
:return list: la liste des tuples (sommet arrivee, nb d'etapes, ititneraire) ok
|
||||
"""
|
||||
if depart is None:
|
||||
nb_bidons = len(graphe_water_jug.sommets[0])
|
||||
depart = tuple([0 for _ in range(nb_bidons)])
|
||||
chemins = construire_chemins(graphe_water_jug, depart)
|
||||
resultat = list()
|
||||
for sommet in chemins:
|
||||
if quantite in sommet:
|
||||
longueur, _ = chemins[sommet]
|
||||
chemin = reconstruire_chemin_vers(chemins, sommet).pop()
|
||||
index = len(resultat)
|
||||
resultat.append((sommet, longueur, chemin))
|
||||
while index > 0:
|
||||
if resultat[index - 1][1] < longueur:
|
||||
break
|
||||
else:
|
||||
resultat[index], resultat[index - 1] = (
|
||||
resultat[index - 1],
|
||||
resultat[index],
|
||||
)
|
||||
index -= 1
|
||||
if len(resultat) < 2 or not (plus_court):
|
||||
return resultat
|
||||
mini = resultat[0][1]
|
||||
return [element for element in resultat if element[1] == mini]
|
||||
|
||||
|
||||
def main():
|
||||
solutions = atteindre(4, creer_water_jug(3,5))
|
||||
|
||||
for (sommet_final, nb_etapes, chemin) in solutions:
|
||||
print(f"sommet atteint: {sommet_final}, en {nb_etapes} etapes")
|
||||
print(affichage_chemin(chemin))
|
||||
print("--------------------------------------")
|
||||
solutions = atteindre(4, creer_water_jug(3, 5))
|
||||
|
||||
for sommet_final, nb_etapes, chemin in solutions:
|
||||
print(f"sommet atteint: {sommet_final}, en {nb_etapes} etapes")
|
||||
print(affichage_chemin(chemin))
|
||||
print("--------------------------------------")
|
||||
|
||||
|
||||
def question1():
|
||||
|
||||
print("Non pas tous les quantités de litres peuvent être représenter comme 6l.")
|
||||
print("Non pas tous les quantités de litres peuvent être représenter comme 6l.")
|
||||
|
||||
|
||||
def question2():
|
||||
for i in range(10):
|
||||
resolutions = atteindre(i,creer_water_jug(3,5),None, True)
|
||||
for (sommet_final, nb_etapes, chemin) in resolutions:
|
||||
print(f"sommet atteint: {sommet_final}, en {nb_etapes} etapes")
|
||||
print(affichage_chemin(chemin))
|
||||
print("--------------------------------------")
|
||||
for i in range(10):
|
||||
resolutions = atteindre(i, creer_water_jug(3, 5), None, True)
|
||||
for sommet_final, nb_etapes, chemin in resolutions:
|
||||
print(f"sommet atteint: {sommet_final}, en {nb_etapes} etapes")
|
||||
print(affichage_chemin(chemin))
|
||||
print("--------------------------------------")
|
||||
|
||||
|
||||
def question3():
|
||||
solution = atteindre(4,creer_water_jug(3,5),None,True)
|
||||
for (sommet_final, nb_etapes, chemin) in solution:
|
||||
print(f"sommet atteint: {sommet_final}, en {nb_etapes} etapes")
|
||||
print(affichage_chemin(chemin))
|
||||
print("--------------------------------------")
|
||||
solution = atteindre(4, creer_water_jug(3, 5), None, True)
|
||||
for sommet_final, nb_etapes, chemin in solution:
|
||||
print(f"sommet atteint: {sommet_final}, en {nb_etapes} etapes")
|
||||
print(affichage_chemin(chemin))
|
||||
print("--------------------------------------")
|
||||
|
||||
|
||||
def question4():
|
||||
solution = atteindre(1,creer_water_jug(3,5,9),None,True)
|
||||
for (sommet_final, nb_etapes, chemin) in solution:
|
||||
print(f"sommet atteint: {sommet_final}, en {nb_etapes} etapes")
|
||||
print(affichage_chemin(chemin))
|
||||
print("--------------------------------------")
|
||||
solution = atteindre(1, creer_water_jug(3, 5, 9), None, True)
|
||||
for sommet_final, nb_etapes, chemin in solution:
|
||||
print(f"sommet atteint: {sommet_final}, en {nb_etapes} etapes")
|
||||
print(affichage_chemin(chemin))
|
||||
print("--------------------------------------")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
doctest.testmod(verbose=True)
|
||||
main()
|
||||
question1()
|
||||
question2()
|
||||
question3()
|
||||
question4()
|
||||
import doctest
|
||||
|
||||
doctest.testmod(verbose=True)
|
||||
main()
|
||||
question1()
|
||||
question2()
|
||||
question3()
|
||||
question4()
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
def produit_cartesien(*listes):
|
||||
if not listes:
|
||||
return []
|
||||
if len(listes) == 1:
|
||||
return listes[0]
|
||||
if len(listes) == 2:
|
||||
liste1, liste2 = listes
|
||||
resultat = list()
|
||||
for tuple_1 in liste1:
|
||||
for tuple_2 in liste2:
|
||||
resultat.append(tuple_1 + tuple_2)
|
||||
return resultat
|
||||
liste1, *reste = listes
|
||||
return produit_cartesien(liste1, produit_cartesien(*reste))
|
||||
|
||||
if not listes:
|
||||
return []
|
||||
if len(listes) == 1:
|
||||
return listes[0]
|
||||
if len(listes) == 2:
|
||||
liste1, liste2 = listes
|
||||
resultat = list()
|
||||
for tuple_1 in liste1:
|
||||
for tuple_2 in liste2:
|
||||
resultat.append(tuple_1 + tuple_2)
|
||||
return resultat
|
||||
liste1, *reste = listes
|
||||
return produit_cartesien(liste1, produit_cartesien(*reste))
|
||||
|
||||
|
||||
liste1 = [(_,) for _ in range(3)]
|
||||
liste2 = [(_,) for _ in range(5)]
|
||||
liste3 = [(_,)for _ in range(8)]
|
||||
print(produit_cartesien(liste1,liste2))
|
||||
|
||||
liste3 = [(_,) for _ in range(8)]
|
||||
print(produit_cartesien(liste1, liste2))
|
||||
|
||||
@@ -1,31 +1,35 @@
|
||||
class leaudibidon(object):
|
||||
|
||||
def __init__(self,capacity):
|
||||
def __init__(self, capacity):
|
||||
self.capacity = capacity
|
||||
self.quantity = 0
|
||||
|
||||
def fullfill_b5(b5,b3):
|
||||
def fullfill_b5(b5, b3):
|
||||
b5.quantity = b5.capacity
|
||||
print("Fullfill b5")
|
||||
|
||||
def fullfill_b3(b5,b3):
|
||||
def fullfill_b3(b5, b3):
|
||||
b3.quantity = b3.capacity
|
||||
print("Fullfill b3")
|
||||
|
||||
def void_b5(b5,b3):
|
||||
def void_b5(b5, b3):
|
||||
b5.quantity = 0
|
||||
print("void b5")
|
||||
|
||||
|
||||
def void_b3(b5,b3):
|
||||
def void_b3(b5, b3):
|
||||
b3.quantity = 0
|
||||
print("void b3")
|
||||
|
||||
def transfer_b5_b3(b5,b3):
|
||||
def transfer_b5_b3(b5, b3):
|
||||
transfer_amount = min(b5.quantity, b3.capacity - b3.quantity)
|
||||
b5.quantity, b3.quantity = b5.quantity - transfer_amount, b3.quantity + transfer_amount
|
||||
|
||||
|
||||
def transfer_b3_b5(b5,b3):
|
||||
b5.quantity, b3.quantity = (
|
||||
b5.quantity - transfer_amount,
|
||||
b3.quantity + transfer_amount,
|
||||
)
|
||||
|
||||
def transfer_b3_b5(b5, b3):
|
||||
transfer_amount = min(b3.quantity, b5.capacity - b5.quantity)
|
||||
b5.quantity, b3.quantity = b5.quantity + transfer_amount, b3.quantity - transfer_amount
|
||||
b5.quantity, b3.quantity = (
|
||||
b5.quantity + transfer_amount,
|
||||
b3.quantity - transfer_amount,
|
||||
)
|
||||
|
||||
@@ -2,17 +2,17 @@ class Pile:
|
||||
def __init__(self) -> None:
|
||||
self.element = []
|
||||
|
||||
def empiler(self,element)->None:
|
||||
def empiler(self, element) -> None:
|
||||
self.element.append(element)
|
||||
|
||||
def est_vide(self)->bool:
|
||||
def est_vide(self) -> bool:
|
||||
return len(self.element) == 0
|
||||
|
||||
def defiler(self):
|
||||
assert not self.est_vide(), "La pile est vide"
|
||||
return self.element.pop()
|
||||
|
||||
def size(self)->int:
|
||||
def size(self) -> int:
|
||||
return len(self.element)
|
||||
|
||||
def index(self, k):
|
||||
|
||||
@@ -2,7 +2,7 @@ class Queue:
|
||||
def __init__(self) -> None:
|
||||
self.element = []
|
||||
|
||||
def enfiler(self,element):
|
||||
def enfiler(self, element):
|
||||
self.element.append(element)
|
||||
|
||||
def est_vide(self):
|
||||
@@ -16,5 +16,5 @@ class Queue:
|
||||
return len(self.element)
|
||||
|
||||
def index(self, k):
|
||||
assert self.est_vide() , "La file est vide"
|
||||
assert self.est_vide(), "La file est vide"
|
||||
return self.element[k]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import maze_creator as mc
|
||||
|
||||
|
||||
lab = mc.Labyrinth(10,10)
|
||||
lab.set_start_end((0,0),(100,100))
|
||||
lab = mc.Labyrinth(10, 10)
|
||||
lab.set_start_end((0, 0), (100, 100))
|
||||
lab.generate_maze()
|
||||
print(lab.__str__())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import random as rnd
|
||||
|
||||
|
||||
class Labyrinth:
|
||||
def __init__(self, rows, cols) -> None:
|
||||
self.rows = rows
|
||||
@@ -20,7 +21,7 @@ class Labyrinth:
|
||||
nx, ny = x + dx, y + dy
|
||||
if 0 <= nx < self.rows and 0 <= ny < self.cols and self.grid[nx][ny] == 1:
|
||||
voisins.append((nx, ny))
|
||||
|
||||
|
||||
return voisins
|
||||
|
||||
def casser_mur(self, x1, y1, x2, y2):
|
||||
@@ -50,7 +51,11 @@ class Labyrinth:
|
||||
# Trouver une cellule voisine qui est déjà un chemin
|
||||
for dx, dy in [(-2, 0), (2, 0), (0, -2), (0, 2)]:
|
||||
cx, cy = nx + dx, ny + dy
|
||||
if 0 <= cx < self.rows and 0 <= cy < self.cols and self.grid[cx][cy] == 0:
|
||||
if (
|
||||
0 <= cx < self.rows
|
||||
and 0 <= cy < self.cols
|
||||
and self.grid[cx][cy] == 0
|
||||
):
|
||||
# Casser le mur entre les deux cellules
|
||||
self.casser_mur(cx, cy, nx, ny)
|
||||
# Ajouter les nouveaux murs adjacents
|
||||
@@ -68,5 +73,6 @@ class Labyrinth:
|
||||
"""
|
||||
Représente le labyrinthe sous forme de chaîne de caractères.
|
||||
"""
|
||||
return "\n".join("".join(" " if cell == 0 else "#" for cell in row) for row in self.grid)
|
||||
|
||||
return "\n".join(
|
||||
"".join(" " if cell == 0 else "#" for cell in row) for row in self.grid
|
||||
)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
from fifo import Pile # Remplacez "fifo" par le nom exact de votre fichier contenant la classe Pile
|
||||
from fifo import (
|
||||
Pile,
|
||||
) # Remplacez "fifo" par le nom exact de votre fichier contenant la classe Pile
|
||||
|
||||
# Initialisation
|
||||
pile = Pile()
|
||||
@@ -13,7 +15,9 @@ assert pile.element == [5, 10], "Erreur : Les éléments de la pile ne correspon
|
||||
assert not pile.est_vide(), "Erreur : La pile ne devrait pas être vide"
|
||||
pile.defiler()
|
||||
pile.defiler()
|
||||
assert pile.est_vide(), "Erreur : La pile devrait être vide après avoir défiler tous les éléments"
|
||||
assert (
|
||||
pile.est_vide()
|
||||
), "Erreur : La pile devrait être vide après avoir défiler tous les éléments"
|
||||
|
||||
# Test de defiler
|
||||
pile.empiler(7)
|
||||
@@ -48,4 +52,3 @@ except AssertionError as e:
|
||||
pass # Test réussi
|
||||
|
||||
print("Tous les tests sont passés avec succès !")
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ def construire_bfs(graphe: dict, origine: str) -> dict:
|
||||
couleur[courant] = 2
|
||||
return resultat
|
||||
|
||||
|
||||
def construire_dfs(graphe: dict, origine: str) -> dict:
|
||||
"""
|
||||
Construit un arbre DFS à partir de graphe et d'un sommet d'origine.
|
||||
@@ -102,7 +103,9 @@ def construire_dfs(graphe: dict, origine: str) -> dict:
|
||||
couleur[courant] = 2
|
||||
return resultat
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod(verbose=True)
|
||||
print(construire_dfs(g, '1'))
|
||||
print(construire_dfs(g, "1"))
|
||||
|
||||
Reference in New Issue
Block a user