Écrire rotation 90(m) , qui renvoie la matrice tournée d'un quart de…
Exercice de TD · niveau 3 (difficile) · NSI (première), chapitre 4 — Les types construits · Matrices, et le piège de la référence partagée
Énoncé
Écrire rotation_90(m), qui renvoie la matrice tournée d'un quart de tour dans le sens des aiguilles d'une montre. Quelles sont les dimensions du résultat ? Trouver la propriété qui se teste sans écrire aucune réponse à la main, et dire pourquoi on ne peut pas faire cette rotation « en place ».
Corrigé
L'idée. Après rotation horaire, la première colonne de (lue de bas en haut) devient la première ligne du résultat. La case du résultat vaut donc , où est le nombre de lignes de .
def rotation_90(m):
"""Matrice m tournee d'un quart de tour dans le sens horaire.
Precondition : m est non vide, a lignes de meme longueur.
Postcondition : le resultat a len(m[0]) lignes et len(m) colonnes.
"""
assert len(m) > 0 and all(len(l) == len(m[0]) for l in m)
L, C = len(m), len(m[0])
r = [[m[L - 1 - j][i] for j in range(L)] for i in range(C)]
assert len(r) == C and len(r[0]) == L
return r
Les dimensions s'échangent : une matrice devient , comme pour la transposée. C'est déjà un contrôle : sur [[1, 2, 3]], qui est , le résultat doit être — et c'est bien [[1], [2], [3]].
La propriété qui se teste sans réponse écrite à la main : quatre rotations redonnent la matrice de départ.
assert rotation_90([[1, 2], [3, 4]]) == [[3, 1], [4, 2]]
assert rotation_90([[1, 2, 3]]) == [[1], [2], [3]]
for _ in range(300):
L, C = random.randint(1, 5), random.randint(1, 5)
m = [[random.randint(0, 9) for _ in range(C)] for _ in range(L)]
q = m
for _ in range(4):
q = rotation_90(q)
assert q == m
Les matrices passent. Ce test-ci est meilleur que celui de la transposée : l'identité ne le passerait pas, puisqu'elle échouerait dès la première rotation sur les dimensions d'une matrice rectangulaire. Le cas nommé [[1, 2], [3, 4]] -> [[3, 1], [4, 2]] reste indispensable pour distinguer le sens horaire du sens contraire — la propriété « quatre rotations » est vraie des deux.
Pourquoi pas « en place ». Parce que le résultat n'a pas les mêmes dimensions que la donnée dès que la matrice n'est pas carrée : il n'y a littéralement pas de place. Et même sur une matrice carrée, écrire m[i][j] = m[L-1-j][i] case par case écrase des valeurs dont on aura besoin plus tard — c'est le même défaut que le jeu de la vie signalé dans la piste de projet du cours. Quand la nouvelle valeur d'une case dépend d'anciennes valeurs d'autres cases, on construit une nouvelle matrice.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.