Adloun

Écrire spirale(m) , qui parcourt une matrice en spirale depuis le coin…

Exercice supplémentaire · niveau 3 (difficile) · NSI (première), chapitre 4 — Les types construits · Les matrices au travail : images et automates

Énoncé

Écrire spirale(m), qui parcourt une matrice en spirale depuis le coin haut gauche et renvoie le tableau des valeurs rencontrées. Quelle propriété se teste sur des matrices aléatoires sans écrire la réponse ?

Corrigé

L'idée : quatre bornes qui se resserrent. On maintient les indices haut, bas, gauche, droite de la partie non encore parcourue. À chaque tour, on longe le bord supérieur, puis le droit, puis l'inférieur, puis le gauche, en rétrécissant après chaque côté.


def spirale(m):
    """Elements de m parcourus en spirale, depuis le coin haut gauche.

    Precondition  : m est non vide, a lignes de meme longueur.
    Postcondition : le resultat contient chaque case exactement une fois.
    """
    assert len(m) > 0 and all(len(l) == len(m[0]) for l in m)
    haut, bas = 0, len(m) - 1
    gauche, droite = 0, len(m[0]) - 1
    r = []
    while haut <= bas and gauche <= droite:
        for j in range(gauche, droite + 1):
            r.append(m[haut][j])
        haut = haut + 1
        for i in range(haut, bas + 1):
            r.append(m[i][droite])
        droite = droite - 1
        if haut <= bas:                          # sinon on relit la meme ligne
            for j in range(droite, gauche - 1, -1):
                r.append(m[bas][j])
            bas = bas - 1
        if gauche <= droite:                     # sinon on relit la meme colonne
            for i in range(bas, haut - 1, -1):
                r.append(m[i][gauche])
            gauche = gauche + 1
    return r

Les deux if au milieu sont le cœur de l'exercice. Sans eux, une matrice d'une seule ligne verrait cette ligne parcourue deux fois — une fois à l'aller, une fois au « retour » — et le résultat aurait trop d'éléments. Ils ne servent que dans les cas dégénérés, et ce sont eux qu'un jeu de tests limité aux matrices carrées ne toucherait jamais.

La propriété qui se teste sans réponse écrite : le parcours est une permutation des cases — même longueur, mêmes valeurs, chacune une fois.


assert spirale([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) == [1, 2, 3, 6, 9, 8, 7, 4, 5]
assert spirale([[1, 2, 3]]) == [1, 2, 3]
assert spirale([[1], [2], [3]]) == [1, 2, 3]
assert spirale([[1]]) == [1]

for _ in range(300):
    L, C = random.randint(1, 6), random.randint(1, 6)
    m = [[i * C + j for j in range(C)] for i in range(L)]   # cases distinctes
    s = spirale(m)
    assert len(s) == L * C
    assert sorted(s) == sorted(x for ligne in m for x in ligne)

Les matrices passent. Le remplissage par n'est pas décoratif : il donne à chaque case une valeur distincte, sans quoi un doublon dans le parcours passerait inaperçu au tri. C'est aussi la formule d'aplatissement de l'exercice suivant.

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.