Compare commits

...

7 Commits

Author SHA1 Message Date
0dcccd2b74 updated test imports
All checks were successful
Python unit tests / unittests (push) Successful in 4s
2025-01-28 17:32:57 +01:00
35f194f649 completed README
Some checks failed
Python unit tests / unittests (push) Failing after 4s
2025-01-28 17:28:24 +01:00
2fda876df3 added ex5
Some checks failed
Python unit tests / unittests (push) Failing after 5s
2025-01-28 16:52:27 +01:00
68ccc3c183 added ex4 2025-01-28 15:20:24 +01:00
3c100a08fe added ex3 2025-01-28 15:01:53 +01:00
9c6bf54f20 added ex2 2025-01-28 14:32:19 +01:00
70daa208d0 added ex1 2025-01-28 13:53:41 +01:00
11 changed files with 616 additions and 40 deletions

View File

@@ -12,31 +12,31 @@ Voici mes réponses pour l'examen 2025 d'_Algorithmes et Structures de données_
<table>
<tr>
<td><strong>But</strong></td>
<td>...</td>
<td>Compter le nombre de valeurs positives différentes ayant leur opposé dans une liste</td>
</tr>
<tr>
<td><strong>Input</strong></td>
<td>...</td>
<td>La liste des demi-touches (entiers relatifs non-nuls)</td>
</tr>
<tr>
<td><strong>Output</strong></td>
<td>...</td>
<td>Le nombre de touches distinctes dont les valeurs positives et négatives sont dans la liste</td>
</tr>
<tr>
<td><strong>Signature</strong></td>
<td>
```python
def function1(
*args
) -> Any:
def countKey(
pieces: list[int]
) -> int:
```
</td>
</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,31 +46,33 @@ def function1(
<table>
<tr>
<td><strong>But</strong></td>
<td></td>
<td>Trouver le chemin le plus court entre deux points, en considérant que certaines routes ne sont praticables que de nuit/jour</td>
</tr>
<tr>
<td><strong>Input</strong></td>
<td>...</td>
<td>Nœud de départ (index), nœud d'arrivée (index) et liste des routes / arêtes (nœud 1, nœud 2, restriction)</td>
</tr>
<tr>
<td><strong>Output</strong></td>
<td>...</td>
<td>Liste des nœuds (index) à parcourir</td>
</tr>
<tr>
<td><strong>Signature</strong></td>
<td>
```python
def function2(
*args
) -> Any:
def findSafestPath(
start: int,
end: int,
intersections: list[tuple[int, int, int]]
) -> list[int]:
```
</td>
</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)
@@ -80,31 +82,32 @@ def function2(
<table>
<tr>
<td><strong>But</strong></td>
<td>...</td>
<td>Trouver dans un réseau de console un sous-graphe connexe de taille donnée</td>
</tr>
<tr>
<td><strong>Input</strong></td>
<td>...</td>
<td>Taille n du sous-graphe recherché, liste des connexions</td>
</tr>
<tr>
<td><strong>Output</strong></td>
<td>...</td>
<td>Liste de n consoles toutes interconnectées</td>
</tr>
<tr>
<td><strong>Signature</strong></td>
<td>
```python
def function3(
*args
) -> Any:
def findTightlyLinkedConsoles(
n: int,
consoles: list[tuple[int, int]]
) -> list[int]:
```
</td>
</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)
@@ -114,31 +117,33 @@ def function3(
<table>
<tr>
<td><strong>But</strong></td>
<td>...</td>
<td>Compter le nombre de séquences de N coups infligeant un total de H dégâts</td>
</tr>
<tr>
<td><strong>Input</strong></td>
<td>...</td>
<td>Nombre N de coups dans la séquence, nombre C de coups possibles (dégâts 1 à C inclus), total H de dégâts</td>
</tr>
<tr>
<td><strong>Output</strong></td>
<td>...</td>
<td>Nombre de séquences possibles</td>
</tr>
<tr>
<td><strong>Signature</strong></td>
<td>
```python
def function4(
*args
) -> Any:
def computeNbrOfDifferentSequences(
N: int,
C: int,
H: int
) -> int:
```
</td>
</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)
@@ -148,30 +153,32 @@ def function4(
<table>
<tr>
<td><strong>But</strong></td>
<td>...</td>
<td>Trouver les placements de pièces Minitris formant un rectangle plein</td>
</tr>
<tr>
<td><strong>Input</strong></td>
<td>...</td>
<td>Largeur de la grille, longueur de la grille, liste des pièces à poser</td>
</tr>
<tr>
<td><strong>Output</strong></td>
<td>...</td>
<td>Liste des positions des pièces</td>
</tr>
<tr>
<td><strong>Signature</strong></td>
<td>
```python
def function5(
*args
) -> Any:
def playMinitrisFastAndWell(
board_width: int,
board_height: int,
pieces: list[tuple[tuple[int,int], tuple[int,int]]]
) -> list[list[int, int]]:
```
</td>
</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)

57
src/Ex1.py Normal file
View File

@@ -0,0 +1,57 @@
"""
Nom/Prénom: Heredero/Louis
Explications:
Une approche serait de trier la liste des valeurs par ordre croissant
Une fois triée, nous pouvons comparer les valeurs absolues des 2 extrémités :
- Si elles sont égales, nous avons une touche complète supplémentaire (nous les enlevons de la liste)
- Sinon, nous enlevons celle avec la plus grande valeur absolue
NB: Afin de ne compter que les paires distinctes, nous pouvons soit transformer
la liste en `set` (retire les valeurs à double), soit garder une liste des valeurs
de touches complètes trouvées
Cela permettrait aussi peut-être d'améliorer l'efficacité de l'algorithme de la manière suivante:
- Créer deux `set` : valeurs positives et valeurs négatives (stocker la valeur
absolue des valeurs négatives dans le `set`)
- Calculer l'intersection des deux `set` :
`intersection = positives.intersection(negatives)`
- Le nombre de touches complètes est la taille de cette intersection :
`complete = len(intersection)`
Par exemple :
list = [-3, -2, -1, 1, 2, 5] -> |-3| != |5| -> on enlève 5
list = [-3, -2, -1, 1, 2] -> |-3| != |2| -> on enlève -3
list = [-2, -1, 1, 2] -> |-2| = |2| -> une touche complète
list = [-1, 1] -> |-1| = |1| -> une autre touche complète
list = []
"""
def countKey(pieces: list[int]) -> int:
pieces = sorted(pieces)
complete: int = 0
while len(pieces) >= 2:
a, b = pieces[0], pieces[-1]
# Si toutes les pièces restantes sont de même signe, on peut s'arrêter
if a >= 0 or b <= 0:
break
abs_a, abs_b = abs(a), abs(b)
if abs_a == abs_b:
complete += 1
pieces = pieces[1:-1]
elif abs_a < abs_b:
pieces.pop(-1)
else:
pieces.pop(0)
return complete
if __name__ == '__main__':
#print(countKey([-3, 4, 2, 8, 9, 1, -3, -8, -4, 2, 8, 2, -8, 1, 3]) == 3)
print(countKey([-3, 4, 2, 8, 9, 1, -3, -8, -4, 2, 8, 2, -8, 1, 3]) == 4)
print(countKey([-4, 5, 6, -1500, 4, 7, 49, 60, -60, 82, -41, 1500, 1, -7]) == 4)

96
src/Ex2.py Normal file
View File

@@ -0,0 +1,96 @@
"""
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œuds :
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])

76
src/Ex3.py Normal file
View File

@@ -0,0 +1,76 @@
"""
Nom/Prénom: Heredero/Louis
Explications:
Comme indiqué dans la donnée de l'exercice, il s'agit ici de trouvé un sous-graphe
connexe dans un graphe quelconque de consoles interconnectées
Pour ce faire, nous pouvons procéder ainsi :
Étape 1 :
- Compter le nombre de voisins de chaque nœud (console)
- Éliminer ceux ayant moins de voisins que la taille de sous-graphe recherché
- Supprimer également les arêtes connectées à ces nœuds
- Recommencer jusqu'à ce que :
a) il y ait moins de nœuds que la taille du sous-graphe recherché
-> il n'est donc pas possible de trouver un sous-graphe connexe de taille n
b) aucun nœud du graphe n'ait moins de voisins que voulu (aucune suppression de nœud)
-> il peut exister un sous-graphe connexe de taille n (Cf. étape 2)
Étape 2 :
- Pour chaque nœud du graphe :
- Calculer l'ensemble des nœuds communs entre ses voisins (et lui-même),
et les voisins de ses voisins (et eux-mêmes)'
C'est-à-dire, si N1 est un nœud et nb(N1) = {N2, N3, ...} est l'ensemble de ses voisins,
on cherche l'intersection de {N1} U nb(N1), {N2} U nb(N2), {N3} U nb(N3), etc.
- Si cet ensemble contient au moins n éléments, il s'agit alors d'un sous-graphe connexe.
On peut ainsi en extraire les n premiers nœuds comme résultat
"""
def findTightlyLinkedConsoles(n: int, consoles: list[tuple[int, int]]) -> list[int]:
nodes: dict[int, set[int]] = {}
for i1, i2 in consoles:
if i1 not in nodes:
nodes[i1] = set()
if i2 not in nodes:
nodes[i2] = set()
nodes[i1].add(i2)
nodes[i2].add(i1)
while True:
removed: set[int] = set()
for node, neighbors in nodes.items():
if len(neighbors) < n - 1:
removed.add(node)
if len(removed) == 0:
break
new_nodes = {}
for node, neighbors in nodes.items():
if node in removed:
continue
new_nodes[node] = neighbors - removed
nodes = new_nodes
if len(nodes) < n:
return []
for node, neighbors in nodes.items():
common: set[int] = neighbors | {node}
for nb in neighbors:
common = common.intersection(nodes[nb] | {nb})
if len(common) >= n:
return list(sorted(common))[:n]
return []
if __name__ == '__main__':
print(findTightlyLinkedConsoles(3, [(0, 1), (0, 4), (2, 1), (3, 1), (4, 2), (2, 3)]) == [1, 2, 3])
print(findTightlyLinkedConsoles(4, [(0, 1), (0, 4), (2, 1), (3, 1), (4, 2), (2, 3)]) == [])
print(findTightlyLinkedConsoles(4, [(0, 1), (0, 4), (2, 1), (3, 1), (4, 2), (2, 3), (1, 4), (4, 3)]) == [1, 2, 3, 4])

75
src/Ex4.py Normal file
View File

@@ -0,0 +1,75 @@
"""
Nom/Prénom: Heredero/Louis
Explications:
Une approche pour résoudre ce problème grâce à la programmation dynamique consiste
à se représenter les différentes séquences comme un arbre de décisions, où chaque nœud
représente une séquence, et chaque arête un coup supplémentaire
On peut alors parcourir l'arbre en profondeur (DFS) jusqu'à trouver une séquence
de longueur N et de valeur H (en élaguant les branches dépassant H ou N)
On peut également mémoïser un certain nombre de valeurs : en effet, pour une même
combinaison N, C, H, le résultat sera toujours le même. Cela optimise donc grandement
le calcul récursif puisque cela évite de calculer les états partagés (sous-branches
identiques)
Bonus :
Nous cherchons la valeur N la plus petite telle que :
`computeNbrOfDifferentSequences(N, 5, 100) > 2^16`
"""
mem: dict[tuple[int, int, int], int] = {}
def computeNbrOfDifferentSequences(N: int, C: int, H: int) -> int:
if N == 0:
if H == 0:
return 1
return 0
if H < 0:
return 0
key: tuple[int, int, int] = (N, C, H)
if key in mem:
return mem[key]
total: int = 0
for c in range(1, C + 1):
total += computeNbrOfDifferentSequences(N - 1, C, H - c)
mem[key] = total
return total
def bonus():
# Finding N2
N1 = 100
N2 = 1_000_000_000
C = 5
H = 100
lim = 2 ** 16
while computeNbrOfDifferentSequences(N2, C, H) <= lim:
N2 *= 2
print(f"*= 2 -> {N2}")
print(f"{N2=}")
# Finding N
while N2 - N1 > 1:
Nm = (N1 + N2) // 2
value = computeNbrOfDifferentSequences(Nm, C, H)
if value == lim:
return Nm
if value < lim:
N1 = Nm
else:
N2 = Nm
return N2
if __name__ == '__main__':
print(computeNbrOfDifferentSequences(1, 6, 3) == 1)
print(computeNbrOfDifferentSequences(2, 6, 7) == 6)
#print(bonus())

190
src/Ex5.py Normal file
View File

@@ -0,0 +1,190 @@
"""
Nom/Prénom: Heredero/Louis
"""
from typing import Optional
# UTILITY FUNCTIONS
# Those functions are provided as helpers, you do not have to use them
# The displayBoardSequence function will be used to visualize the results of your algorithms during the evaluation
def printPiece(piece:tuple[tuple[int,int], tuple[int,int]]) -> None:
print(piece[0][1], piece[1][1])
print(piece[0][0], piece[1][0])
def printBoard(board:list[list[int, int]]) -> None:
if len(board) <= 0 or len(board[0]) <= 0:
print("Empty board -> skipping printing")
return None
for i in range(len(board)-1):
if len(board[i]) != len(board[i+1]):
print("Board is not a rectangle --> skipping printing")
return None
for y in range(len(board[0])-1, -1, -1):
line = ""
for x in range(len(board)):
line += str(board[x][y],)
print(line)
def placeAt(loc, board, piece):
for x in range(2):
for y in range(2):
if piece[x][y] == 0:
continue
board[loc[0] + x][loc[1] + y] = piece[x][y]
def displayBoardSequence(board_width:int, board_height:int, pieces:list[tuple[tuple[int,int], tuple[int,int]]], placements:list[list[int, int]]):
"""Display a sequence of move on the board by placing the blocs at the given locations
==> /!\ This is an unsafe function that simply place the 1 ones of the given blocs at the given placements, it will crash while trying to place blocs outside the board
==> /!\ it does not check the validity of the placement
=> It's main use is for debugging
"""
board = [None] * board_width
for i in range(board_width):
board[i] = [0] * board_height
for i in range(len(pieces)):
print( "----", i, "----")
print("Piece to place")
printPiece(pieces[i])
print("Board state after placing piece @ "+ str(placements[i]))
placeAt(placements[i], board, pieces[i])
printBoard(board)
"""
Explications:
Une approche possible consiste à représenter la partie sous la forme d'un arbre
dans lequel les nœuds sont les états de la grille et les arêtes sont les coups
possibles (i.e. placement d'une pièce)
Ainsi, l'état initial serait celui de la grille vide, et chaque "niveau" de l'arbre
représenterait une pièce différente pouvant être posée
On peut ensuite parcourir l'arbre en largeur (BFS) ce qui nous garantit de trouver une solution optimale en premier.
On peut également le parcourir en profondeur (DFS) jusqu'à trouver une solution, puis en parcourant le reste de l'arbre
à la recherche d'une meilleure solution. Cela permettrait également d'appliquer
de la mémoïsation (principe de programmation dynamique) afin d'optimiser la recherche
Afin d'accélérer la recherche nous pouvons appliquer les optimisations suivantes:
- élagage des branches inintéressantes : dès qu'une pièce laisse un espace vide sous elle, il devient impossible de le remplir
- tri des branches selon la hauteur de la pièce une fois posée : prioriser les branches plaçant les pièces le plus bas possible
- combinaisons de pièces en macro-blocs : combiner les pièces pouvant s'assembler (p.ex. coin et carré)
"""
def find_y(board: list[list[int]], height: int, piece: tuple[tuple[int,int], tuple[int,int]], x: int) -> int:
y_max = height - 2
if piece[0][1] == 0 and piece[1][1] == 0:
y_max = height - 1
y_min = 0
if piece[0][0] == 0 and piece[1][0] == 0:
y_min = -1
lowest = 0
for y in range(y_max, y_min - 1, -1):
valid = True
for dy in range(2):
for dx in range(2):
if piece[dx][dy] == 1 and board[x + dx][y + dy] == 1:
valid = False
break
if not valid:
break
if valid:
lowest = y
else:
break
return lowest
def copy_board(board: list[list[int]]) -> list[list[int]]:
new_board: list[list[int]] = [
row.copy()
for row in board
]
return new_board
def playMinitris(
board_width: int,
board_height: int,
board: list[list[int]],
pieces: list[tuple[tuple[int,int], tuple[int,int]]],
path: list[tuple[int, int]]
) -> Optional[list[tuple[int, int]]]:
if len(pieces) == 0:
for y in range(board_height):
row = []
for x in range(board_width):
row.append(board[x][y])
if row != [row[0]] * board_width:
return None
return path
first_piece: tuple[tuple[int, int], tuple[int, int]] = pieces[0]
rest: list[tuple[tuple[int, int], tuple[int, int]]] = pieces[1:]
x_min = 0
if first_piece[0][0] == 0 and first_piece[0][1] == 0:
x_min = -1
x_max = board_width - 2
if first_piece[1][0] == 0 and first_piece[1][1] == 0:
x_max = board_width - 1
for x in range(x_min, x_max + 1):
y = find_y(board, board_height, first_piece, x)
new_board = copy_board(board)
pos = (x, y)
path2 = path + [pos]
placeAt(pos, new_board, first_piece)
# If space below piece
if first_piece[0][1] == 1 and first_piece[1][1] and first_piece[0][0] != first_piece[1][0]:
if new_board[x][y] == 0 or new_board[x + 1][y] == 0:
return None
res: Optional[list[tuple[int, int]]] = playMinitris(board_width, board_height, new_board, rest, path2)
if res is not None:
return res
return None
# This is the function to fill
def playMinitrisFastAndWell(
board_width: int,
board_height: int,
pieces: list[tuple[tuple[int,int], tuple[int,int]]]
) -> list[list[int, int]]:
board: list[list[int]] = [
[0] * board_height
for _ in range(board_width)
]
result: Optional[list[tuple[int, int]]] = playMinitris(
board_width,
board_height,
board,
pieces,
[]
)
if result is None:
return []
return list(map(list, result))
if __name__ == '__main__':
displayBoardSequence(3, 4, [((1, 0), (0, 0)), ((1, 0), (0, 0)), ((1, 0), (0, 0))], [(0, 0), (1, 0), (2, 0)])
displayBoardSequence(3, 4, [((1, 0), (0, 0)), ((1, 1), (0, 1)), ((1, 1), (0, 0))], [(1, 0), (0, 0), (2, 0)])
w = 3
h = 4
pieces = [((1, 0), (0, 0)), ((1, 0), (0, 0)), ((1, 0), (0, 0))]
seq = playMinitrisFastAndWell(w, h, pieces)
displayBoardSequence(w, h, pieces, seq)

View File

@@ -1,8 +1,26 @@
import unittest
from src.Ex1 import countKey
class MyTestCase(unittest.TestCase):
def test_simple1(self):
pass
self.assertEqual(
countKey([-3, 4, 2, 8, 9, 1, -3, -8, -4, 2, 8, 2, -8, 1, 3]),
4
)
def test_simple2(self):
self.assertEqual(
countKey([-4, 5, 6, -1500, 4, 7, 49, 60, -60, 82, -41, 1500, 1, -7]),
4
)
def test_simple3(self):
self.assertEqual(
countKey([-3, -2, -1, 1, 2, 5]),
2
)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,8 +1,20 @@
import unittest
from src.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()

View File

@@ -1,8 +1,27 @@
import unittest
from src.Ex3 import findTightlyLinkedConsoles
class MyTestCase(unittest.TestCase):
def test_simple1(self):
pass
self.assertEqual(
findTightlyLinkedConsoles(3,[(0,1),(0,4),(2,1),(3,1),(4,2),(2,3)]),
[1,2,3]
)
def test_simple2(self):
self.assertEqual(
findTightlyLinkedConsoles(4,[(0,1),(0,4),(2,1),(3,1),(4,2),(2,3)]),
[]
)
def test_simple3(self):
self.assertEqual(
findTightlyLinkedConsoles(4,[(0,1),(0,4),(2,1),(3,1),(4,2),(2,3),(1,4),(4,3)]),
[1,2,3,4]
)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,8 +1,21 @@
import unittest
from src.Ex4 import computeNbrOfDifferentSequences
class MyTestCase(unittest.TestCase):
def test_simple1(self):
pass
self.assertEqual(
computeNbrOfDifferentSequences(1, 6, 3),
1
)
def test_simple2(self):
self.assertEqual(
computeNbrOfDifferentSequences(2, 6, 7),
6
)
if __name__ == '__main__':
unittest.main()

View File

@@ -1,8 +1,21 @@
import unittest
from src.Ex5 import playMinitrisFastAndWell
class MyTestCase(unittest.TestCase):
def test_simple1(self):
pass
self.assertEqual(
playMinitrisFastAndWell(3, 4, [((1, 0), (0, 0)), ((1, 0), (0, 0)), ((1, 0), (0, 0))]),
[[0, 0], [1, 0], [2, 0]]
)
def test_simple2(self):
self.assertEqual(
playMinitrisFastAndWell(3, 4, [((1, 0), (0, 0)), ((1, 1), (0, 1)), ((1, 1), (0, 0))]),
[[1, 0], [0, 0], [2, 0]]
)
if __name__ == '__main__':
unittest.main()