added ex2
This commit is contained in:
		
							
								
								
									
										12
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
									
									
									
									
								
							| @@ -36,7 +36,7 @@ def function1( | ||||
| </tr> | ||||
| </table> | ||||
|  | ||||
| [Source](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/src/ex1_.py) | ||||
| [Source](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/src/Ex1.py) | ||||
| / | ||||
| [Tests](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/tests/test_ex1.py) | ||||
|  | ||||
| @@ -46,7 +46,7 @@ def function1( | ||||
| <table> | ||||
| <tr> | ||||
| <td><strong>But</strong></td> | ||||
| <td></td> | ||||
| <td>...</td> | ||||
| </tr> | ||||
| <tr> | ||||
| <td><strong>Input</strong></td> | ||||
| @@ -70,7 +70,7 @@ def function2( | ||||
| </tr> | ||||
| </table> | ||||
|  | ||||
| [Source](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/src/ex2_.py) | ||||
| [Source](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/src/Ex2.py) | ||||
| / | ||||
| [Tests](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/tests/test_ex2.py) | ||||
|  | ||||
| @@ -104,7 +104,7 @@ def function3( | ||||
| </tr> | ||||
| </table> | ||||
|  | ||||
| [Source](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/src/ex3_.py) | ||||
| [Source](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/src/Ex3.py) | ||||
| / | ||||
| [Tests](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/tests/test_ex3.py) | ||||
|  | ||||
| @@ -138,7 +138,7 @@ def function4( | ||||
| </tr> | ||||
| </table> | ||||
|  | ||||
| [Source](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/src/ex4_.py) | ||||
| [Source](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/src/Ex4.py) | ||||
| / | ||||
| [Tests](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/tests/test_ex4.py) | ||||
|  | ||||
| @@ -172,6 +172,6 @@ def function5( | ||||
| </tr> | ||||
| </table> | ||||
|  | ||||
| [Source](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/src/ex5_.py) | ||||
| [Source](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/src/Ex5.py) | ||||
| / | ||||
| [Tests](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/tests/test_ex5.py) | ||||
|   | ||||
							
								
								
									
										95
									
								
								src/Ex2.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/Ex2.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
|  | ||||
| """ | ||||
| Nom/Prénom: Heredero/Louis | ||||
| Explications: | ||||
| Tout d'abord, le réseau de routes et d'intersections peut être représenté par un graphe, | ||||
| dans lequel les interséctions sont les nœuds et les routes les arêtes. | ||||
|  | ||||
| Ainsi, nous cherchons à trouver le chemin le plus court du point de départ au | ||||
| point d'arrivée, tel que les routes marquées 1 ne soient parcourues que de jour | ||||
| (c'est-à-dire si leurs index dans le chemin parcouru est pair), et celles marquées -1 | ||||
| seulement de nuit (index impair). En plus des routes données, nous pouvons aussi | ||||
| rester sur un même nœud pour une nuit. | ||||
| Afin de bien gérer les différences d'états entre jour et nuit, nous pouvons intégrer le demi-jour | ||||
| associé à chaque visite de nœud. Ainsi, une même intersection peut avoir deux nœud: | ||||
| un pour une visite de jour, et un de nuit. | ||||
|  | ||||
| Pour résoudre ce problème, comme nous ne pouvons pas établir d'heuristique mesurant | ||||
| notre distance au point d'arrivée, nous pouvons utiliser un algorithme BFS assez simple: | ||||
| - Initialiser la liste des nœuds à traiter avec le nœud de départ et le demi-jour de départ (`DAY`) | ||||
| - Tant que nous n'avons pas trouvé le nœud d'arrivée: | ||||
|   - Pour chaque nœud à traiter : | ||||
|     - Visiter les nœuds voisins non visités (liés par une route praticable) | ||||
|     - Indiquer pour chaque voisin son parent | ||||
|     - L'ajouter à la nouvelle liste des nœuds à traiter | ||||
|   - Alterner le demi-jour courant | ||||
|   - Recommencer avec la nouvelle liste de nœuds à traiter | ||||
| """ | ||||
| from typing import Optional | ||||
|  | ||||
| ALWAYS = 0 | ||||
| DAY = 1 | ||||
| NIGHT = -1 | ||||
|  | ||||
|  | ||||
| def get_path(visited: dict[tuple[int, int], Optional[int]], end: int, end_time: int) -> list[int]: | ||||
|     path: list[int] = [] | ||||
|     parent: Optional[int] = end | ||||
|  | ||||
|     time: int = end_time | ||||
|     while parent is not None: | ||||
|         path.append(parent) | ||||
|         parent = visited[(parent, time)] | ||||
|         time = -time | ||||
|  | ||||
|     return list(reversed(path)) | ||||
|  | ||||
| def findSafestPath(start: int, end: int, intersections: list[tuple[int, int, int]]) -> list[int]: | ||||
|     edges: dict[int, dict[int, set[int]]] = { | ||||
|         ALWAYS: {}, | ||||
|         DAY: {}, | ||||
|         NIGHT: {} | ||||
|     } | ||||
|  | ||||
|     for i1, i2, mode in intersections: | ||||
|         edge_dict: dict[int, set[int]] = edges[mode] | ||||
|         if i1 not in edge_dict: | ||||
|             edge_dict[i1] = set() | ||||
|         if i2 not in edge_dict: | ||||
|             edge_dict[i2] = set() | ||||
|         edge_dict[i1].add(i2) | ||||
|         edge_dict[i2].add(i1) | ||||
|  | ||||
|     visited: dict[tuple[int, int], Optional[int]] = { | ||||
|         (start, DAY): None | ||||
|     } | ||||
|     to_process: list[int] = [start] | ||||
|     time = DAY | ||||
|     while len(to_process) != 0: | ||||
|         to_process2 = [] | ||||
|         time2 = -time | ||||
|         for idx in to_process: | ||||
|             always: set[int] = edges[ALWAYS].get(idx, set()) | ||||
|             matching_time: set[int] = edges[time].get(idx, set()) | ||||
|             neighbors: set[int] = always | matching_time | ||||
|             neighbors.add(idx) | ||||
|  | ||||
|             for neighbor in neighbors: | ||||
|                 key = (neighbor, time2) | ||||
|                 # Skip if already visited | ||||
|                 if key in visited: | ||||
|                     continue | ||||
|                 visited[key] = idx | ||||
|                 if neighbor == end: | ||||
|                     return get_path(visited, end, time2) | ||||
|                 to_process2.append(neighbor) | ||||
|  | ||||
|         to_process = to_process2 | ||||
|         time = time2 | ||||
|  | ||||
|     return [] | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     print(findSafestPath(0,2,[(0, 1, -1), (1, 2, 0)]) == [0, 0, 1, 2]) | ||||
|     print(findSafestPath(0, 5, [(0,1,0), (0,2,1), (2,1,-1), (1,3,-1), (2,4,-1), (3,5,1), (3,4,0), (4,5,-1)]) == [0, 1, 3, 5]) | ||||
| @@ -1,8 +1,20 @@ | ||||
| import unittest | ||||
|  | ||||
| from Ex2 import findSafestPath | ||||
|  | ||||
|  | ||||
| class MyTestCase(unittest.TestCase): | ||||
|     def test_simple1(self): | ||||
|         pass | ||||
|         self.assertEqual( | ||||
|             findSafestPath(0, 2, [(0, 1, -1), (1, 2, 0)]), | ||||
|             [0, 0, 1, 2] | ||||
|         ) | ||||
|  | ||||
|     def test_simple2(self): | ||||
|         self.assertEqual( | ||||
|             findSafestPath(0, 5, [(0,1,0), (0,2,1), (2,1,-1), (1,3,-1), (2,4,-1), (3,5,1), (3,4,0), (4,5,-1)]), | ||||
|             [0, 1, 3, 5] | ||||
|         ) | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     unittest.main() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user