mirror of
https://github.com/Fare-spec/cours.git
synced 2025-12-08 03:00:37 +00:00
Add university content
This commit is contained in:
26
high-school/graphes/DS_possible/main.py
Normal file
26
high-school/graphes/DS_possible/main.py
Normal file
@@ -0,0 +1,26 @@
|
||||
graphe = {
|
||||
"node1": ["node2", "node4"],
|
||||
"node2": ["node2", "node3", "node6"],
|
||||
"node3": ["node5"],
|
||||
"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)
|
||||
if node not in visited:
|
||||
print(node)
|
||||
visited.add(node)
|
||||
for neighbor in graphe[node]:
|
||||
if neighbor not in visited:
|
||||
queue.append(neighbor)
|
||||
|
||||
|
||||
bfs(graphe, "node1")
|
||||
BIN
high-school/graphes/DS_possible/v
Normal file
BIN
high-school/graphes/DS_possible/v
Normal file
Binary file not shown.
57
high-school/graphes/homework_wednesday.py
Normal file
57
high-school/graphes/homework_wednesday.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# Chatgpt code
|
||||
|
||||
import heapq
|
||||
|
||||
|
||||
def dijkstra(graph, source):
|
||||
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
|
||||
while node is not None:
|
||||
path.append(node)
|
||||
node = previous[node]
|
||||
path.reverse()
|
||||
return path
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
graph = {
|
||||
"R1": [("R2", 1)],
|
||||
"R2": [("R3", 1), ("R5", 10)],
|
||||
"R3": [("R4", 1), ("R5", 1)],
|
||||
"R5": [("R4", 10)],
|
||||
"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)
|
||||
0
high-school/graphes/ht
Normal file
0
high-school/graphes/ht
Normal file
368
high-school/graphes/leaudibidon/Water_jug.py
Normal file
368
high-school/graphes/leaudibidon/Water_jug.py
Normal file
@@ -0,0 +1,368 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- Coding: utf-8 -*-
|
||||
|
||||
|
||||
class Graphe_Oriente(object):
|
||||
"""
|
||||
Classe des Graphes Orientés (GO).
|
||||
|
||||
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
|
||||
|
||||
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 ajoute_sommet(self, s):
|
||||
"""
|
||||
Ajoute le sommet s à l'instance de GO.
|
||||
|
||||
:param s data: etiquette du sommet
|
||||
"""
|
||||
|
||||
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.
|
||||
|
||||
: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:
|
||||
|
||||
: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
|
||||
|
||||
|
||||
def construire_chemins(graphe, depart):
|
||||
"""
|
||||
Construit tous les cheminement du graphe de depart donné
|
||||
|
||||
: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)
|
||||
|
||||
: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
|
||||
|
||||
|
||||
def reconstruire_chemin_vers(dico_chemins, *arrivee):
|
||||
"""
|
||||
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
|
||||
|
||||
|
||||
def affichage_chemin(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]
|
||||
)
|
||||
|
||||
|
||||
# DEFINITION DES OPERATIONS DE TRANSITION
|
||||
|
||||
|
||||
def vider(numero, etat):
|
||||
"""
|
||||
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)
|
||||
|
||||
|
||||
def remplir(numero, etat, capacites):
|
||||
"""
|
||||
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
|
||||
|
||||
>>> 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
|
||||
|
||||
: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)
|
||||
|
||||
|
||||
# FONCTION LIEES AU GRAPHE DU WATER_JUG
|
||||
|
||||
|
||||
# Pour construire les etats
|
||||
def produit_cartesien(*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
|
||||
|
||||
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
|
||||
|
||||
: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
|
||||
|
||||
|
||||
def atteindre(quantite, graphe_water_jug, depart=None, plus_court=False):
|
||||
"""
|
||||
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)
|
||||
|
||||
: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("--------------------------------------")
|
||||
|
||||
|
||||
def question1():
|
||||
|
||||
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("--------------------------------------")
|
||||
|
||||
|
||||
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("--------------------------------------")
|
||||
|
||||
|
||||
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("--------------------------------------")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod(verbose=True)
|
||||
main()
|
||||
question1()
|
||||
question2()
|
||||
question3()
|
||||
question4()
|
||||
20
high-school/graphes/leaudibidon/correction.py
Normal file
20
high-school/graphes/leaudibidon/correction.py
Normal file
@@ -0,0 +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))
|
||||
|
||||
|
||||
liste1 = [(_,) for _ in range(3)]
|
||||
liste2 = [(_,) for _ in range(5)]
|
||||
liste3 = [(_,) for _ in range(8)]
|
||||
print(produit_cartesien(liste1, liste2))
|
||||
35
high-school/graphes/leaudibidon/main.py
Normal file
35
high-school/graphes/leaudibidon/main.py
Normal file
@@ -0,0 +1,35 @@
|
||||
class leaudibidon(object):
|
||||
|
||||
def __init__(self, capacity):
|
||||
self.capacity = capacity
|
||||
self.quantity = 0
|
||||
|
||||
def fullfill_b5(b5, b3):
|
||||
b5.quantity = b5.capacity
|
||||
print("Fullfill b5")
|
||||
|
||||
def fullfill_b3(b5, b3):
|
||||
b3.quantity = b3.capacity
|
||||
print("Fullfill b3")
|
||||
|
||||
def void_b5(b5, b3):
|
||||
b5.quantity = 0
|
||||
print("void b5")
|
||||
|
||||
def void_b3(b5, b3):
|
||||
b3.quantity = 0
|
||||
print("void 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):
|
||||
transfer_amount = min(b3.quantity, b5.capacity - b5.quantity)
|
||||
b5.quantity, b3.quantity = (
|
||||
b5.quantity + transfer_amount,
|
||||
b3.quantity - transfer_amount,
|
||||
)
|
||||
20
high-school/graphes/maze/fifo.py
Normal file
20
high-school/graphes/maze/fifo.py
Normal file
@@ -0,0 +1,20 @@
|
||||
class Pile:
|
||||
def __init__(self) -> None:
|
||||
self.element = []
|
||||
|
||||
def empiler(self, element) -> None:
|
||||
self.element.append(element)
|
||||
|
||||
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:
|
||||
return len(self.element)
|
||||
|
||||
def index(self, k):
|
||||
assert not self.est_vide(), "La pile est vide"
|
||||
return self.element[k]
|
||||
20
high-school/graphes/maze/lifo.py
Normal file
20
high-school/graphes/maze/lifo.py
Normal file
@@ -0,0 +1,20 @@
|
||||
class Queue:
|
||||
def __init__(self) -> None:
|
||||
self.element = []
|
||||
|
||||
def enfiler(self, element):
|
||||
self.element.append(element)
|
||||
|
||||
def est_vide(self):
|
||||
return len(self.element) == 0
|
||||
|
||||
def defiler(self):
|
||||
assert self.est_vide(), "La file est vide"
|
||||
return self.element.pop(0)
|
||||
|
||||
def size(self):
|
||||
return len(self.element)
|
||||
|
||||
def index(self, k):
|
||||
assert self.est_vide(), "La file est vide"
|
||||
return self.element[k]
|
||||
7
high-school/graphes/maze/main.py
Normal file
7
high-school/graphes/maze/main.py
Normal file
@@ -0,0 +1,7 @@
|
||||
import maze_creator as mc
|
||||
|
||||
|
||||
lab = mc.Labyrinth(10, 10)
|
||||
lab.set_start_end((0, 0), (100, 100))
|
||||
lab.generate_maze()
|
||||
print(lab.__str__())
|
||||
78
high-school/graphes/maze/maze_creator.py
Normal file
78
high-school/graphes/maze/maze_creator.py
Normal file
@@ -0,0 +1,78 @@
|
||||
import random as rnd
|
||||
|
||||
|
||||
class Labyrinth:
|
||||
def __init__(self, rows, cols) -> None:
|
||||
self.rows = rows
|
||||
self.cols = cols
|
||||
# Grille initiale : 1 = mur, 0 = chemin
|
||||
self.grid = [[1 for _ in range(cols)] for _ in range(rows)]
|
||||
self.start = None
|
||||
self.end = None
|
||||
|
||||
def voisins(self, x, y):
|
||||
"""
|
||||
Retourne les voisins valides (encore des murs) de la cellule (x, y).
|
||||
"""
|
||||
directions = [(0, 2), (0, -2), (2, 0), (-2, 0)]
|
||||
voisins = []
|
||||
|
||||
for dx, dy in directions:
|
||||
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):
|
||||
"""
|
||||
Casse le mur entre les cellules (x1, y1) et (x2, y2).
|
||||
"""
|
||||
mx, my = (x1 + x2) // 2, (y1 + y2) // 2 # Coordonnées du mur à casser
|
||||
self.grid[mx][my] = 0 # Transformer le mur en chemin
|
||||
self.grid[x2][y2] = 0 # Transformer la cellule voisine en chemin
|
||||
|
||||
def generate_maze(self):
|
||||
"""
|
||||
Génère un labyrinthe parfait à l'aide de l'algorithme de Prim.
|
||||
"""
|
||||
# Choisir une cellule de départ aléatoire
|
||||
x, y = rnd.randrange(0, self.rows, 2), rnd.randrange(0, self.cols, 2)
|
||||
self.grid[x][y] = 0 # Transformer la cellule en chemin
|
||||
|
||||
# Liste des murs candidats (voisins de la cellule initiale)
|
||||
murs = self.voisins(x, y)
|
||||
|
||||
while murs:
|
||||
# Choisir un mur aléatoire
|
||||
nx, ny = rnd.choice(murs)
|
||||
murs.remove((nx, ny))
|
||||
|
||||
# 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
|
||||
):
|
||||
# Casser le mur entre les deux cellules
|
||||
self.casser_mur(cx, cy, nx, ny)
|
||||
# Ajouter les nouveaux murs adjacents
|
||||
murs.extend(self.voisins(nx, ny))
|
||||
break
|
||||
|
||||
def set_start_end(self, start, end):
|
||||
"""
|
||||
Définit les points de départ et d'arrivée du labyrinthe.
|
||||
"""
|
||||
self.start = start
|
||||
self.end = end
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
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
|
||||
)
|
||||
54
high-school/graphes/maze/test.py
Normal file
54
high-school/graphes/maze/test.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from fifo import (
|
||||
Pile,
|
||||
) # Remplacez "fifo" par le nom exact de votre fichier contenant la classe Pile
|
||||
|
||||
# Initialisation
|
||||
pile = Pile()
|
||||
|
||||
# Test de empiler
|
||||
pile.empiler(5)
|
||||
pile.empiler(10)
|
||||
assert pile.size() == 2, "Erreur : La taille de la pile devrait être 2"
|
||||
assert pile.element == [5, 10], "Erreur : Les éléments de la pile ne correspondent pas"
|
||||
|
||||
# Test de est_vide
|
||||
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"
|
||||
|
||||
# Test de defiler
|
||||
pile.empiler(7)
|
||||
pile.empiler(3)
|
||||
assert pile.defiler() == 3, "Erreur : Le dernier élément défilé devrait être 3"
|
||||
assert pile.defiler() == 7, "Erreur : Le dernier élément défilé devrait être 7"
|
||||
try:
|
||||
pile.defiler()
|
||||
assert False, "Erreur : defiler devrait lever une exception pour une pile vide"
|
||||
except AssertionError as e:
|
||||
pass # Test réussi
|
||||
|
||||
# Test de size
|
||||
pile.empiler(4)
|
||||
assert pile.size() == 1, "Erreur : La taille de la pile devrait être 1"
|
||||
pile.defiler()
|
||||
assert pile.size() == 0, "Erreur : La taille de la pile devrait être 0 après defiler"
|
||||
|
||||
# Test de index
|
||||
pile.empiler(1)
|
||||
pile.empiler(2)
|
||||
pile.empiler(3)
|
||||
assert pile.index(0) == 1, "Erreur : L'élément à l'index 0 devrait être 1"
|
||||
assert pile.index(2) == 3, "Erreur : L'élément à l'index 2 devrait être 3"
|
||||
try:
|
||||
pile.defiler()
|
||||
pile.defiler()
|
||||
pile.defiler()
|
||||
pile.index(0)
|
||||
assert False, "Erreur : index devrait lever une exception pour une pile vide"
|
||||
except AssertionError as e:
|
||||
pass # Test réussi
|
||||
|
||||
print("Tous les tests sont passés avec succès !")
|
||||
111
high-school/graphes/monday_homework.py
Normal file
111
high-school/graphes/monday_homework.py
Normal file
@@ -0,0 +1,111 @@
|
||||
def construire_bfs(graphe: dict, origine: str) -> dict:
|
||||
"""
|
||||
Construit un arbre BFS à partir de graphe et d'un sommet d'origine.
|
||||
|
||||
Args:
|
||||
graphe (dict): Un dictionnaire représentant le graphe, où les clés sont les sommets et les valeurs sont des listes de sommets adjacents.
|
||||
origine (str): Le sommet de départ pour la recherche en largeur.
|
||||
|
||||
Returns:
|
||||
dict: Un dictionnaire représentant l'arbre BFS, où les clés sont les sommets et les valeurs sont des tuples contenant la distance depuis l'origine et le sommet precédent.
|
||||
|
||||
Examples:
|
||||
>>> graphe = {
|
||||
... '1': ['2', '3'],
|
||||
... '2': ['4', '5'],
|
||||
... '3': ['6'],
|
||||
... '4': [],
|
||||
... '5': ['6'],
|
||||
... '6': []
|
||||
... }
|
||||
>>> construire_bfs(graphe, '1')
|
||||
{'1': (0, None), '2': (1, '1'), '3': (1, '1'), '4': (2, '2'), '5': (2, '2'), '6': (2, '3')}
|
||||
|
||||
>>> graphe = {
|
||||
... 'A': ['B', 'C'],
|
||||
... 'B': ['D'],
|
||||
... 'C': ['E'],
|
||||
... 'D': [],
|
||||
... 'E': []
|
||||
... }
|
||||
>>> construire_bfs(graphe, 'A')
|
||||
{'A': (0, None), 'B': (1, 'A'), 'C': (1, 'A'), 'D': (2, 'B'), 'E': (2, 'C')}
|
||||
"""
|
||||
|
||||
couleur = dict()
|
||||
resultat = dict()
|
||||
for som in graphe.keys():
|
||||
couleur[som] = 0
|
||||
frontiere = [origine]
|
||||
resultat[origine] = (0, None)
|
||||
couleur[origine] = 1
|
||||
while len(frontiere) > 0:
|
||||
courant = frontiere.pop(0)
|
||||
longueur, precedent = resultat[courant]
|
||||
for som in graphe[courant]:
|
||||
if couleur[som] == 0:
|
||||
frontiere.append(som)
|
||||
resultat[som] = (longueur + 1, courant)
|
||||
couleur[som] = 1
|
||||
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.
|
||||
|
||||
Args:
|
||||
graphe (dict): Un dictionnaire représentant le graphe, où les clés sont les sommets et les valeurs sont des listes de sommets adjacents.
|
||||
origine (str): Le sommet de départ pour la recherche en profondeur.
|
||||
|
||||
Returns:
|
||||
dict: Un dictionnaire représentant l'arbre DFS.
|
||||
|
||||
Examples:
|
||||
>>> graphe = {
|
||||
... '1': ['2', '3'],
|
||||
... '2': ['4', '5'],
|
||||
... '3': ['6'],
|
||||
... '4': [],
|
||||
... '5': ['6'],
|
||||
... '6': []
|
||||
... }
|
||||
>>> construire_dfs(graphe, '1')
|
||||
{'1': (0, None), '2': (1, '1'), '3': (1, '1'), '6': (2, '3'), '4': (2, '2'), '5': (2, '2')}
|
||||
|
||||
>>> graphe = {
|
||||
... 'A': ['B', 'C'],
|
||||
... 'B': ['D'],
|
||||
... 'C': ['E'],
|
||||
... 'D': [],
|
||||
... 'E': []
|
||||
... }
|
||||
>>> construire_dfs(graphe, 'A')
|
||||
{'A': (0, None), 'B': (1, 'A'), 'C': (1, 'A'), 'E': (2, 'C'), 'D': (2, 'B')}
|
||||
"""
|
||||
|
||||
couleur = dict()
|
||||
resultat = dict()
|
||||
for som in graphe.keys():
|
||||
couleur[som] = 0
|
||||
frontiere = [origine]
|
||||
resultat[origine] = (0, None)
|
||||
couleur[origine] = 1
|
||||
while len(frontiere) > 0:
|
||||
courant = frontiere.pop()
|
||||
longueur, precedent = resultat[courant]
|
||||
for som in graphe[courant]:
|
||||
if couleur[som] == 0:
|
||||
frontiere.append(som)
|
||||
resultat[som] = (longueur + 1, courant)
|
||||
couleur[som] = 1
|
||||
couleur[courant] = 2
|
||||
return resultat
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod(verbose=True)
|
||||
print(construire_dfs(g, "1"))
|
||||
0
high-school/graphes/why
Normal file
0
high-school/graphes/why
Normal file
Reference in New Issue
Block a user