Un tableau à deux dimensions (ou matrice) est une liste de listes. Chaque sous-liste représente une ligne :
grille = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
grille[i][j] donne l'élément à la ligne i, colonne j. Les indices commencent à 0.len(grille).len(grille[0]) (en supposant que toutes les lignes ont la même taille).:
# Matrice n lignes, p colonnes, remplie de 0
M = [[0] * p for _ in range(n)]
:
# INCORRECT : crée n références vers la MÊME ligne !
M = [[0] * p] * n
Avec la méthode incorrecte, modifier M[0][0] modifie aussi M[1][0], M[2][0], etc., car toutes les lignes sont le même objet en mémoire.
:
for i in range(len(grille)):
for j in range(len(grille[i])):
print(grille[i][j], end=' ')
print() # retour à la ligne
:
for ligne in grille:
for element in ligne:
print(element, end=' ')
print()
Le parcours par indice est indispensable dès que l'on doit modifier les éléments ou connaître leur position.
grille[i] renvoie la liste correspondant à la ligne entière.[grille[i][j] for i in range(len(grille))] construit la colonne par compréhension.grille[i][i] pour $i$ de 0 à $n - 1$ (matrice carrée).[[grille[i][j] for i in range(n)] for j in range(p)].grille[i][j] désigne ligne $i$, colonne $j$ (pas l'inverse).[[0]*p]*n au lieu de la compréhension (alias de lignes).grille[i] renvoie une référence vers la ligne, pas une copie : modifier le résultat modifie la grille.len(grille)) et le nombre de colonnes (len(grille[0])).| Code erroné | Code correct | Explication |
|---|---|---|
M = [[0]*3]*4 puis M[0][0] = 5 | M = [[0]*3 for _ in range(4)] | Avec *4, les quatre lignes sont le même objet : modifier l'une modifie toutes les autres. |
grille[j][i] pour (ligne $i$, colonne $j$) | grille[i][j] | Le premier indice est toujours la ligne, le second la colonne. |
for i in range(len(grille[0])) pour les lignes | for i in range(len(grille)) | len(grille) donne le nombre de lignes, len(grille[0]) le nombre de colonnes. |
Modifier ligne = grille[i] puis ligne[0] = 99 | Travailler directement sur grille[i][0] = 99 | ligne est une référence : la modification affecte la grille originale dans les deux cas, mais le piège est de croire que ligne est indépendante. |
n, p = 3, 4
grille = [[0] * p for _ in range(n)]
# Remplir avec des valeurs
for i in range(n):
for j in range(p):
grille[i][j] = i * p + j
# Afficher proprement
for ligne in grille:
print(ligne)
# [0, 1, 2, 3]
# [4, 5, 6, 7]
# [8, 9, 10, 11]
matrice = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
colonne_1 = [matrice[i][1] for i in range(len(matrice))]
print(colonne_1) # [2, 5, 8]
matrice = [[1, 2, 3],
[4, 5, 6]]
total = 0
for ligne in matrice:
for element in ligne:
total += element
print(total) # 21
# Une image en niveaux de gris est un tableau 2D
# où chaque valeur est comprise entre 0 (noir) et 255 (blanc)
image = [[0, 0, 0, 0, 0],
[0, 255, 255, 255, 0],
[0, 255, 0, 255, 0],
[0, 255, 255, 255, 0],
[0, 0, 0, 0, 0]]
# Négatif : inverser chaque pixel
negatif = [[255 - image[i][j]
for j in range(len(image[0]))]
for i in range(len(image))]
somme_ligne(M, i) qui renvoie la somme des éléments de la ligne $i$ d'une matrice M.somme_colonne(M, j) qui renvoie la somme des éléments de la colonne $j$.maximum(M) qui renvoie la plus grande valeur d'une matrice, ainsi que sa position (i, j).def somme_ligne(M, i):
s = 0
for j in range(len(M[i])):
s += M[i][j]
return s
def somme_colonne(M, j):
s = 0
for i in range(len(M)):
s += M[i][j]
return s
def maximum(M):
maxi = M[0][0]
pos = (0, 0)
for i in range(len(M)):
for j in range(len(M[i])):
if M[i][j] > maxi:
maxi = M[i][j]
pos = (i, j)
return maxi, pos
Vérification : pour $M = 1 & 9 & 3 \\ 4 & 5 & 6 $ :
somme_ligne(M, 0) $= 1 + 9 + 3 = 13$ ;somme_colonne(M, 1) $= 9 + 5 = 14$ ;maximum(M) $= (9,\; (0, 1))$.Écrire une fonction transposee(M) qui renvoie la transposée d'une matrice (les lignes deviennent les colonnes et réciproquement). Ne pas utiliser de compréhension de liste.
def transposee(M):
n = len(M) # nombre de lignes
p = len(M[0]) # nombre de colonnes
T = [[0] * n for _ in range(p)]
for i in range(n):
for j in range(p):
T[j][i] = M[i][j]
return T
Principe : l'élément en position $(i, j)$ dans $M$ se retrouve en position $(j, i)$ dans $T$. La transposée d'une matrice $n \times p$ est une matrice $p \times n$.
Vérification : si $M = 1 & 2 & 3 \\ 4 & 5 & 6 $, alors $T = 1 & 4 \\ 2 & 5 \\ 3 & 6 $. ✓
Écrire une fonction damier(n) qui crée une matrice $n \times n$ représentant un damier : 0 pour les cases blanches, 1 pour les cases noires. La case $(0, 0)$ est blanche.
damier(4) donne :
,
[1, 0, 1, 0],
[0, 1, 0, 1],
[1, 0, 1, 0]]
def damier(n):
M = [[0] * n for _ in range(n)]
for i in range(n):
for j in range(n):
M[i][j] = (i + j) % 2
return M
Principe : la parité de $i + j$ détermine la couleur. Si $i + j$ est pair, la case est blanche (0) ; si $i + j$ est impair, la case est noire (1).
Vérification : $(0,0)$ : $0 + 0 = 0$ pair $\to$ 0. $(0,1)$ : $0 + 1 = 1$ impair $\to$ 1. $(1,1)$ : $1 + 1 = 2$ pair $\to$ 0. ✓
voisins(M, i, j) qui renvoie la liste des valeurs des voisins (haut, bas, gauche, droite) de la case $(i, j)$ dans une matrice M, en excluant les voisins hors limites.moyenne_voisins(M, i, j) qui renvoie la moyenne des voisins de $(i, j)$ (utile pour le floutage d'image).def voisins(M, i, j):
n = len(M)
p = len(M[0])
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
result = []
for di, dj in directions:
ni, nj = i + di, j + dj
if 0 <= ni < n and 0 <= nj < p:
result.append(M[ni][nj])
return result
def moyenne_voisins(M, i, j):
v = voisins(M, i, j)
return sum(v) / len(v)
Principe : on teste les quatre directions. La condition 0 <= ni < n and 0 <= nj < p garantit qu'on reste dans les limites de la matrice. Une case dans un coin n'a que deux voisins, une case sur un bord en a trois, les autres en ont quatre.
Vérification : pour $M = 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 $ et $(i, j) = (1, 1)$, les voisins sont 2, 8, 4, 6, de moyenne $\frac{20}{4} = 5$. ✓