added ex2
This commit is contained in:
parent
70daa208d0
commit
9c6bf54f20
12
README.md
12
README.md
@ -36,7 +36,7 @@ def function1(
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</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)
|
[Tests](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/tests/test_ex1.py)
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ def function1(
|
|||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>But</strong></td>
|
<td><strong>But</strong></td>
|
||||||
<td></td>
|
<td>...</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Input</strong></td>
|
<td><strong>Input</strong></td>
|
||||||
@ -70,7 +70,7 @@ def function2(
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</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)
|
[Tests](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/tests/test_ex2.py)
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ def function3(
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</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)
|
[Tests](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/tests/test_ex3.py)
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ def function4(
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</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)
|
[Tests](https://git.kb28.ch/HEL/AlgoDS-Examen2025/src/branch/main/tests/test_ex4.py)
|
||||||
|
|
||||||
@ -172,6 +172,6 @@ def function5(
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</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)
|
[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
|
import unittest
|
||||||
|
|
||||||
|
from Ex2 import findSafestPath
|
||||||
|
|
||||||
|
|
||||||
class MyTestCase(unittest.TestCase):
|
class MyTestCase(unittest.TestCase):
|
||||||
def test_simple1(self):
|
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__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user