Adloun

Un vrai tableau à deux dimensions, dans la plupart des langages, n'est…

Exercice supplémentaire · niveau 3 (difficile) · NSI (première), chapitre 4 — Les types construits · Aux frontières du programme

Énoncé

Un vrai tableau à deux dimensions, dans la plupart des langages, n'est pas un tableau de tableaux mais un tableau plat de cases, où la case se trouve à l'indice . Programmer cette représentation et vérifier son équivalence. Quel défaut Python-spécifique disparaît alors ?

Corrigé


def creer_plate(L, C):
    """Matrice L x C representee par UN SEUL tableau de L*C cases."""
    assert L >= 1 and C >= 1
    return {"L": L, "C": C, "cases": [0] * (L * C)}

def lire(mp, i, j):
    assert 0 <= i < mp["L"] and 0 <= j < mp["C"], "indice hors matrice"
    return mp["cases"][i * mp["C"] + j]

def ecrire(mp, i, j, v):
    assert 0 <= i < mp["L"] and 0 <= j < mp["C"], "indice hors matrice"
    mp["cases"][i * mp["C"] + j] = v

La formule est l'accès calculé direct du cours, appliqué deux fois : on saute lignes entières de cases, puis cases. C'est ce que fait le processeur pour un tableau à deux dimensions en C, et la raison pour laquelle parcourir une matrice ligne par ligne est plus rapide que colonne par colonne — les cases lues se suivent en mémoire.

Vérification.


mp = creer_plate(2, 3)
ecrire(mp, 0, 2, 7)
ecrire(mp, 1, 0, 5)
print(mp["cases"])       # [0, 0, 7, 5, 0, 0]

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)]
    mp = creer_plate(L, C)
    for i in range(L):
        for j in range(C):
            ecrire(mp, i, j, m[i][j])
    for i in range(L):
        for j in range(C):
            assert lire(mp, i, j) == m[i][j]

Les matrices se transportent et se relisent à l'identique. Le tableau plat [0, 0, 7, 5, 0, 0] se lit ligne par ligne : est en position , et en position .

Le défaut qui disparaît. Le piège [[0] <em> C] </em> L n'a plus de sens : il n'y a qu'un seul tableau, de nombres, et [0] <em> (L </em> C) est parfaitement correct. Aucune ligne à partager, donc aucune ligne partagée par accident. On perd en revanche la commodité de m[i] — il n'existe aucun objet « ligne » — et l'on gagne une nouvelle source d'erreurs : lire(mp, 0, 3) sur une matrice désigne une case qui existe dans le tableau plat (l'indice ) mais qui appartient à la ligne suivante. Sans l'assertion, l'erreur serait silencieuse. Chaque représentation déplace les erreurs, elle ne les supprime pas.

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.