Les matrices : modules classiques — résumé 4SI

4SI

Sommaire

  1. Déclaration et matrice de l’exemple
  2. Saisie, remplissage et affichage
  3. Les zones d’une matrice
  4. Calculs : sommes, maximum, minimum, occurrences
  5. Recherche d’un élément
  6. Vérifications de propriétés
  7. Transformations : diagonales, transposée, lignes, tris
  8. Matrice et tableau
  9. De la matrice vers un fichier texte
  10. D’un fichier texte vers une matrice
  11. Matrice et fichier de données
  12. Les erreurs les plus fréquentes
  13. Retenons

1. Déclaration et matrice de l’exemple

1.1 Règles communes à tous les modules

  • Chaque module est autonome : il traite une seule tâche.
  • NL est le nombre de lignes et NC le nombre de colonnes ; une matrice carrée a N lignes et N colonnes.
  • Les lignes sont numérotées de 0 à NL - 1, les colonnes de 0 à NC - 1. La case de la ligne i et de la colonne j se note M[i, j].
  • Un paramètre NomFich est une chaîne de caractères qui contient l’emplacement et le nom physique du fichier. Le module ouvre et ferme lui-même le fichier.

1.2 Les types utilisés

TDNT

Nouveau type
Mat = Tableau de 20 lignes * 20 colonnes d'entiers
MatC = Tableau de 20 lignes * 50 colonnes de caractères
Tab = Tableau de 400 entiers
FEnt = Fichier d'entiers

Tab peut contenir les 20 × 20 éléments d’une matrice de type Mat.

En Python
from numpy import array

M = array([[0] * 20] * 20)                  # Mat : 20 lignes * 20 colonnes d'entiers
MC = array([[''] * 50] * 20, dtype='U1')    # MatC : 20 lignes * 50 colonnes de caractères
T = array([0] * 400)                        # Tab : 400 entiers

Remarque importante. Sans dtype, une matrice de chaînes ne garde que le premier caractère de chaque case. Pour une matrice de caractères, dtype='U1' suffit ; pour des chaînes, préciser une longueur : dtype='U20'.

1.3 La matrice de l’exemple

Tous les résultats donnés dans ce résumé ont été obtenus sur la même matrice carrée M de 4 lignes et 4 colonnes :

0123
05291
17328
24603
32957

Le maximum, 9, y figure deux fois, en M[0, 2] et en M[3, 1], et le minimum, 0, une seule fois, en M[2, 2] : c’est ce qui permet de voir, dans les modules de position, laquelle des deux occurrences est retournée.

2. Saisie, remplissage et affichage

2.1 Saisir les dimensions

Procédure qui saisit NL et NC, deux entiers de l’intervalle [2, 20].

Procédure Saisir_Dim (@NL, @NC : Entier)
DEBUT
    Répéter
        Écrire("Nombre de lignes : ")
        Lire(NL)
    Jusqu'à (2 ≤ NL) Et (NL ≤ 20)
    Répéter
        Écrire("Nombre de colonnes : ")
        Lire(NC)
    Jusqu'à (2 ≤ NC) Et (NC ≤ 20)
FIN

Pas de TDOL : la procédure n’a ni variable locale, ni module appelé.

En Python
def Saisir_Dim():
    global NL, NC
    NL = int(input("Nombre de lignes : "))
    while not (2 <= NL <= 20):
        NL = int(input("Nombre de lignes : "))
    NC = int(input("Nombre de colonnes : "))
    while not (2 <= NC <= 20):
        NC = int(input("Nombre de colonnes : "))
En détail

La procédure produit deux résultats : en Python, ils passent par global, jamais par return NL, NC. Pour une matrice carrée, une seule saisie suffit : N.

2.2 Remplir une matrice par saisie contrôlée

Procédure qui remplit M par des entiers strictement positifs.

Procédure Remplir (@M : Mat, NL, NC : Entier)
DEBUT
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            Répéter
                Écrire("M[", i, ",", j, "] : ")
                Lire(M[i, j])
            Jusqu'à M[i, j] > 0
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, jEntier
En Python
def Remplir(M, NL, NC):
    for i in range(NL):
        for j in range(NC):
            M[i, j] = int(input("M[" + str(i) + "," + str(j) + "] : "))
            while not (M[i, j] > 0):
                M[i, j] = int(input("M[" + str(i) + "," + str(j) + "] : "))

Seule la condition de Jusqu'à change d’un énoncé à l’autre : M[i, j] ∈ [0..20] pour une note, Premier(M[i, j]) pour un nombre premier, etc.

2.3 Remplir une matrice par des valeurs aléatoires

Procédure RemplirBinaire(M, NL, NC) qui remplit M par des valeurs aléatoires binaires, 0 ou 1.

Procédure RemplirBinaire (@M : Mat, NL, NC : Entier)
DEBUT
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            M[i, j] ← Aléa(0, 1)
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, jEntier
En Python
from random import randint

def RemplirBinaire(M, NL, NC):
    for i in range(NL):
        for j in range(NC):
            M[i, j] = randint(0, 1)

Pour d’autres bornes, seul l’intervalle change : Aléa(10, 99) donne des entiers de deux chiffres.

2.4 Remplir une matrice par des valeurs distinctes

Procédure RemplirDistinct(M, NL, NC) qui remplit M par des entiers distincts saisis par l’utilisateur.

On lit directement dans M[i, j], puis on vérifie que cette valeur n’apparaît dans aucune des cases déjà remplies : toutes les lignes avant la ligne i, et, sur la ligne i, les colonnes avant j.

Procédure RemplirDistinct (@M : Mat, NL, NC : Entier)
DEBUT
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            Répéter
                Écrire("M[", i, ",", j, "] : ")
                Lire(M[i, j])
            Jusqu'à Non(Deja_Vue(M, NC, i, j))
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, jEntier
Deja_VueFonction
Fonction Deja_Vue (M : Mat, NC, L, C : Entier) : Booléen
DEBUT
    trouve ← Faux
    i ← 0
    Tant que (i ≤ L) Et Non(trouve) Faire
        j ← 0
        Tant que (((i < L) Et (j < NC)) Ou ((i = L) Et (j < C))) Et Non(trouve) Faire
            Si M[i, j] = M[L, C] Alors
                trouve ← Vrai
            Sinon
                j ← j + 1
            FinSi
        Fin Tant que
        i ← i + 1
    Fin Tant que
    Retourner trouve
FIN

TDOL

ObjetType / Nature
i, jEntier
trouveBooléen
En Python
def Deja_Vue(M, NC, L, C):
    trouve = False
    i = 0
    while (i <= L) and not trouve:
        j = 0
        while ((i < L and j < NC) or (i == L and j < C)) and not trouve:
            if M[i, j] == M[L, C]:
                trouve = True
            else:
                j = j + 1
        i = i + 1
    return trouve

def RemplirDistinct(M, NL, NC):
    for i in range(NL):
        for j in range(NC):
            M[i, j] = int(input("M[" + str(i) + "," + str(j) + "] : "))
            while Deja_Vue(M, NC, i, j):
                M[i, j] = int(input("M[" + str(i) + "," + str(j) + "] : "))

Exemple vérifié. Pour une matrice de 3 lignes et 2 colonnes, les saisies 5, 5, 2, 9, 2, 5, 1, 7, 7, 3 donnent la matrice 5 2 / 9 1 / 7 3 : les valeurs refusées sont le deuxième 5, puis 2 et 5, puis le deuxième 7.

Remarque importante. Lire directement dans M[i, j] est sûr : la zone parcourue par Deja_Vue s’arrête avant la case (L, C), la valeur saisie ne se compare donc jamais à elle-même. Pour la première case, (0, 0), la zone est vide et Deja_Vue retourne Faux : aucun test (i = 0) Et (j = 0) n’est nécessaire.

En détail

La condition de la boucle intérieure décrit la zone déjà remplie : sur les lignes i < L, toutes les colonnes ; sur la ligne L, les colonnes j < C seulement. Comparée à une recherche directe sur 20 000 matrices tirées au hasard, cette fonction n’a donné aucun écart.

2.5 Afficher une matrice

Procédure qui affiche M ligne par ligne, les éléments d’une même ligne étant séparés par un espace.

Procédure Afficher (M : Mat, NL, NC : Entier)
DEBUT
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            Écrire(M[i, j], " ")
        Fin Pour
        Écrire_nl()
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, jEntier
En Python
def Afficher(M, NL, NC):
    for i in range(NL):
        for j in range(NC):
            print(M[i, j], end=" ")
        print()
En détail

Le passage à la ligne se place après la boucle sur j : un Écrire_nl() dans la boucle afficherait un élément par ligne. Python n’affiche jamais print(M) : on affiche élément par élément.

3. Les zones d’une matrice

3.1 Les conditions sur les indices

La case courante étant M[i, j] :

ZoneCondition sur (i, j)
Diagonale principalei = j
Diagonale secondairei + j = N - 1, matrice carrée
Au-dessus de la diagonale principalej > i
Au-dessous de la diagonale principalej < i
Au-dessus de la diagonale secondairei + j < N - 1
Au-dessous de la diagonale secondairei + j > N - 1
Bordure(i = 0) Ou (i = NL - 1) Ou (j = 0) Ou (j = NC - 1)
Les deux diagonales passant par M[L, C](i + j = L + C) Ou (i - j = L - C), ou encore Abs(i - L) = Abs(j - C)

3.2 Parcourir une zone sans tester toutes les cases

Une condition de zone peut se placer dans un Si, à l’intérieur du parcours complet. Mais il est souvent plus simple de parcourir directement la zone, en choisissant les bornes des boucles :

Zone parcourueBoucles
Diagonale principalePour i de 0 à N - 1 → M[i, i]
Diagonale secondairePour i de 0 à N - 1 → M[i, N - 1 - i]
Au-dessus de la diagonale principalePour i de 0 à N - 2 puis Pour j de i + 1 à N - 1
Au-dessous de la diagonale principalePour i de 1 à N - 1 puis Pour j de 0 à i - 1
Au-dessus de la diagonale secondairePour i de 0 à N - 2 puis Pour j de 0 à N - 2 - i

Sur la matrice M : la diagonale principale 5, 3, 0, 7 a pour somme 15, la diagonale secondaire 1, 2, 6, 2 a pour somme 11.

En détail

Les modules du paragraphe 7.1, qui échangent les deux moitiés d’une matrice autour d’une diagonale, parcourent exactement une de ces zones : celle au-dessous de la diagonale principale, et celle au-dessus de la diagonale secondaire.

4. Calculs : sommes, maximum, minimum, occurrences

4.1 SommeMatrice

Fonction SommeMatrice(M, NL, NC) qui calcule la somme de tous les éléments de M.

Fonction SommeMatrice (M : Mat, NL, NC : Entier) : Entier
DEBUT
    s ← 0
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            s ← s + M[i, j]
        Fin Pour
    Fin Pour
    Retourner s
FIN

TDOL

ObjetType / Nature
s, i, jEntier
En Python
def SommeMatrice(M, NL, NC):
    s = 0
    for i in range(NL):
        for j in range(NC):
            s = s + M[i, j]
    return s

Sur la matrice M : 73.

4.2 SommeLigne et SommeColonne

Fonction SommeLigne(M, NC, NUML) qui calcule la somme des éléments de la ligne NUML, et fonction SommeColonne(M, NL, NUMC) qui calcule celle des éléments de la colonne NUMC.

Fonction SommeLigne (M : Mat, NC, NUML : Entier) : Entier
DEBUT
    s ← 0
    Pour j de 0 à NC - 1 Faire
        s ← s + M[NUML, j]
    Fin Pour
    Retourner s
FIN

TDOL

ObjetType / Nature
s, jEntier
Fonction SommeColonne (M : Mat, NL, NUMC : Entier) : Entier
DEBUT
    s ← 0
    Pour i de 0 à NL - 1 Faire
        s ← s + M[i, NUMC]
    Fin Pour
    Retourner s
FIN

TDOL

ObjetType / Nature
s, iEntier
En Python
def SommeLigne(M, NC, NUML):
    s = 0
    for j in range(NC):
        s = s + M[NUML, j]
    return s

def SommeColonne(M, NL, NUMC):
    s = 0
    for i in range(NL):
        s = s + M[i, NUMC]
    return s

Sur la matrice M :

0123
Somme de la ligne17201323
Somme de la colonne18201619

Remarque importante. Pour une ligne, l’indice de ligne est fixe et seul j varie ; pour une colonne, c’est l’inverse. Une seule boucle suffit : la fonction n’a besoin que de NC pour une ligne, de NL pour une colonne.

4.3 SommeDiagonales

Fonction SommeDiagonales(M, N) qui calcule la somme des éléments des deux diagonales d’une matrice carrée.

Fonction SommeDiagonales (M : Mat, N : Entier) : Entier
DEBUT
    s ← 0
    Pour i de 0 à N - 1 Faire
        s ← s + M[i, i] + M[i, N - i - 1]
    Fin Pour
    Si N Mod 2 = 1 Alors
        s ← s - M[N Div 2, N Div 2]
    FinSi
    Retourner s
FIN

TDOL

ObjetType / Nature
s, iEntier
En Python
def SommeDiagonales(M, N):
    s = 0
    for i in range(N):
        s = s + M[i, i] + M[i, N - i - 1]
    if N % 2 == 1:
        s = s - M[N // 2, N // 2]
    return s

Sur la matrice M : 15 + 11 = 26.

Remarque importante. Lorsque N est impair, les deux diagonales se croisent sur la case centrale M[N Div 2, N Div 2], ajoutée deux fois par la boucle : on la retranche une fois. Lorsque N est pair, elles n’ont aucune case commune. Pour la matrice 1 2 3 / 4 5 6 / 7 8 9, la fonction retourne 25 ; sans la correction, elle retournerait 30.

4.4 MaximumMatrice

Fonction MaximumMatrice(M, NL, NC) qui retourne le plus grand élément de M.

Fonction MaximumMatrice (M : Mat, NL, NC : Entier) : Entier
DEBUT
    max ← M[0, 0]
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            Si M[i, j] > max Alors
                max ← M[i, j]
            FinSi
        Fin Pour
    Fin Pour
    Retourner max
FIN

TDOL

ObjetType / Nature
max, i, jEntier
En Python
def MaximumMatrice(M, NL, NC):
    Max = M[0, 0]
    for i in range(NL):
        for j in range(NC):
            if M[i, j] > Max:
                Max = M[i, j]
    return Max

Sur la matrice M : 9.

Remarque importante. On initialise avec un élément de la matrice, M[0, 0], jamais avec 0 : sur une matrice dont tous les éléments sont négatifs, une initialisation à 0 retournerait 0, qui n’est pas dans la matrice.

En détail

La boucle repasse sur M[0, 0], déjà utilisé pour l’initialisation. C’est sans effet sur le résultat, puisque M[0, 0] > M[0, 0] est faux, et cela évite un traitement à part de la ligne 0.

4.5 PositionMinimum

Procédure PositionMinimum(M, NL, NC, LMin, CMin) qui détermine la ligne LMin et la colonne CMin du plus petit élément de M. Si le minimum apparaît plusieurs fois, on retient la première case rencontrée.

La procédure produit deux résultats : c’est une procédure, et LMin, CMin sont passés par référence.

Méthode 1 : on garde la valeur du minimum

Procédure PositionMinimum (M : Mat, NL, NC : Entier, @LMin, @CMin : Entier)
DEBUT
    min ← M[0, 0]
    LMin ← 0
    CMin ← 0
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            Si M[i, j] < min Alors
                min ← M[i, j]
                LMin ← i
                CMin ← j
            FinSi
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
min, i, jEntier

Méthode 2 : on garde seulement la position

Procédure PositionMinimum (M : Mat, NL, NC : Entier, @LMin, @CMin : Entier)
DEBUT
    LMin ← 0
    CMin ← 0
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            Si M[i, j] < M[LMin, CMin] Alors
                LMin ← i
                CMin ← j
            FinSi
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, jEntier
En Python
def PositionMinimum(M, NL, NC):
    global LMin, CMin
    LMin = 0
    CMin = 0
    for i in range(NL):
        for j in range(NC):
            if M[i, j] < M[LMin, CMin]:
                LMin = i
                CMin = j

Sur la matrice M : LMin = 2, CMin = 2. La valeur du minimum s’obtient ensuite par M[LMin, CMin], soit 0.

Remarque importante. C’est la comparaison stricte < qui garantit la première occurrence. Avec ≤, on retiendrait la dernière : la recherche de la position du maximum avec ≥ donne (3, 1) sur la matrice M, au lieu de (0, 2).

4.6 MaximumLigne et MaximumColonne

Fonction MaximumLigne(M, NC, NUML) qui retourne le maximum de la ligne NUML, et fonction MaximumColonne(M, NL, NUMC) qui retourne le maximum de la colonne NUMC.

Fonction MaximumLigne (M : Mat, NC, NUML : Entier) : Entier
DEBUT
    max ← M[NUML, 0]
    Pour j de 1 à NC - 1 Faire
        Si M[NUML, j] > max Alors
            max ← M[NUML, j]
        FinSi
    Fin Pour
    Retourner max
FIN

TDOL

ObjetType / Nature
max, jEntier
Fonction MaximumColonne (M : Mat, NL, NUMC : Entier) : Entier
DEBUT
    max ← M[0, NUMC]
    Pour i de 1 à NL - 1 Faire
        Si M[i, NUMC] > max Alors
            max ← M[i, NUMC]
        FinSi
    Fin Pour
    Retourner max
FIN

TDOL

ObjetType / Nature
max, iEntier
En Python
def MaximumLigne(M, NC, NUML):
    Max = M[NUML, 0]
    for j in range(1, NC):
        if M[NUML, j] > Max:
            Max = M[NUML, j]
    return Max

def MaximumColonne(M, NL, NUMC):
    Max = M[0, NUMC]
    for i in range(1, NL):
        if M[i, NUMC] > Max:
            Max = M[i, NUMC]
    return Max

Sur la matrice M :

0123
Maximum de la ligne9869
Maximum de la colonne7998

Le minimum d’une ligne ou d’une colonne s’écrit de la même façon, en inversant la comparaison.

4.7 Nb_Occurrences

Fonction Nb_Occurrences(M, NL, NC, X) qui retourne le nombre d’apparitions de l’entier X dans M.

Fonction Nb_Occurrences (M : Mat, NL, NC, X : Entier) : Entier
DEBUT
    nb ← 0
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            Si M[i, j] = X Alors
                nb ← nb + 1
            FinSi
        Fin Pour
    Fin Pour
    Retourner nb
FIN

TDOL

ObjetType / Nature
nb, i, jEntier
En Python
def Nb_Occurrences(M, NL, NC, X):
    nb = 0
    for i in range(NL):
        for j in range(NC):
            if M[i, j] == X:
                nb = nb + 1
    return nb

Sur la matrice M : Nb_Occurrences(M, 4, 4, 9) retourne 2, Nb_Occurrences(M, 4, 4, 2) retourne 3.

5. Recherche d’un élément

5.1 RechercheLigne

Fonction RechercheLigne(M, NC, NUML, X) qui vérifie si l’entier X figure dans la ligne NUML.

Méthode 1 : avec un drapeau

Fonction RechercheLigne (M : Mat, NC, NUML, X : Entier) : Booléen
DEBUT
    trouve ← Faux
    j ← 0
    Tant que (j < NC) Et Non(trouve) Faire
        Si M[NUML, j] = X Alors
            trouve ← Vrai
        Sinon
            j ← j + 1
        FinSi
    Fin Tant que
    Retourner trouve
FIN

TDOL

ObjetType / Nature
jEntier
trouveBooléen

Méthode 2 : la condition dans la boucle

Fonction RechercheLigne (M : Mat, NC, NUML, X : Entier) : Booléen
DEBUT
    j ← 0
    Tant que (j < NC) Et (M[NUML, j] ≠ X) Faire
        j ← j + 1
    Fin Tant que
    Retourner j < NC
FIN

TDOL

ObjetType / Nature
jEntier
En Python
def RechercheLigne(M, NC, NUML, X):
    j = 0
    while (j < NC) and (M[NUML, j] != X):
        j = j + 1
    return j < NC

Sur la matrice M : RechercheLigne(M, 4, 1, 8) retourne Vrai, RechercheLigne(M, 4, 1, 9) retourne Faux.

5.2 RechercheMatrice

Fonction RechercheMatrice(M, NL, NC, X) qui vérifie si l’entier X figure dans M. La recherche s’arrête dès que X est trouvé.

Fonction RechercheMatrice (M : Mat, NL, NC, X : Entier) : Booléen
DEBUT
    trouve ← Faux
    i ← 0
    Tant que (i < NL) Et Non(trouve) Faire
        j ← 0
        Tant que (j < NC) Et Non(trouve) Faire
            Si M[i, j] = X Alors
                trouve ← Vrai
            Sinon
                j ← j + 1
            FinSi
        Fin Tant que
        i ← i + 1
    Fin Tant que
    Retourner trouve
FIN

TDOL

ObjetType / Nature
i, jEntier
trouveBooléen
En Python
def RechercheMatrice(M, NL, NC, X):
    trouve = False
    i = 0
    while (i < NL) and not trouve:
        j = 0
        while (j < NC) and not trouve:
            if M[i, j] == X:
                trouve = True
            else:
                j = j + 1
        i = i + 1
    return trouve

Sur la matrice M : la recherche de 6 retourne Vrai, celle de 10 retourne Faux.

En détail

Les deux boucles portent la condition Non(trouve) : la boucle intérieure s’arrête sur la case trouvée, la boucle extérieure ne commence pas de nouvelle ligne. Avec deux boucles Pour, la fonction donnerait le même résultat, mais parcourrait toujours toute la matrice.

5.3 PositionEntierMatrice

Procédure PositionEntierMatrice(M, NL, NC, X, LX, CX) qui détermine la ligne LX et la colonne CX de la première apparition de X dans M. Si X est absent, LX et CX reçoivent -1.

Procédure PositionEntierMatrice (M : Mat, NL, NC, X : Entier, @LX, @CX : Entier)
DEBUT
    LX ← -1
    CX ← -1
    i ← 0
    Tant que (i < NL) Et (LX = -1) Faire
        j ← 0
        Tant que (j < NC) Et (LX = -1) Faire
            Si M[i, j] = X Alors
                LX ← i
                CX ← j
            Sinon
                j ← j + 1
            FinSi
        Fin Tant que
        i ← i + 1
    Fin Tant que
FIN

TDOL

ObjetType / Nature
i, jEntier
En Python
def PositionEntierMatrice(M, NL, NC, X):
    global LX, CX
    LX = -1
    CX = -1
    i = 0
    while (i < NL) and (LX == -1):
        j = 0
        while (j < NC) and (LX == -1):
            if M[i, j] == X:
                LX = i
                CX = j
            else:
                j = j + 1
        i = i + 1

Sur la matrice M : pour X = 9, LX = 0 et CX = 2 ; pour X = 10, LX = CX = -1.

En détail

La valeur -1 ne peut pas être un indice : elle joue ici le rôle du drapeau. Tant que LX vaut -1, X n’a pas été trouvé.

6. Vérifications de propriétés

Une vérification « tous les éléments respectent une propriété » s’arrête dès le premier contre-exemple : elle s’écrit avec Tant que. Deux boucles Pour donneraient le bon résultat, mais parcourraient toute la matrice même après un contre-exemple.

6.1 Symetrique

Une matrice carrée est symétrique lorsque M[i, j] = M[j, i] pour toutes les cases. Il suffit de comparer chaque case située au-dessous de la diagonale principale à sa symétrique.

Fonction Symetrique (M : Mat, N : Entier) : Booléen
DEBUT
    ok ← Vrai
    i ← 1
    Tant que (i < N) Et ok Faire
        j ← 0
        Tant que (j < i) Et ok Faire
            Si M[i, j] ≠ M[j, i] Alors
                ok ← Faux
            Sinon
                j ← j + 1
            FinSi
        Fin Tant que
        i ← i + 1
    Fin Tant que
    Retourner ok
FIN

TDOL

ObjetType / Nature
i, jEntier
okBooléen
En Python
def Symetrique(M, N):
    ok = True
    i = 1
    while (i < N) and ok:
        j = 0
        while (j < i) and ok:
            if M[i, j] != M[j, i]:
                ok = False
            else:
                j = j + 1
        i = i + 1
    return ok

Exemple vérifié. La matrice ci-dessous est symétrique ; la matrice M ne l’est pas, puisque M[1, 0] = 7 et M[0, 1] = 2.

012
0147
1425
2753
En détail

Pour N = 4, on fait au plus 6 comparaisons au lieu de 16 : la diagonale n’est pas testée, et chaque paire n’est comparée qu’une fois.

6.2 Triangulaire_Sup

Une matrice carrée est triangulaire supérieure lorsque tous les éléments situés au-dessous de la diagonale principale sont nuls. On parcourt la même zone que pour la symétrie.

Fonction Triangulaire_Sup (M : Mat, N : Entier) : Booléen
DEBUT
    ok ← Vrai
    i ← 1
    Tant que (i < N) Et ok Faire
        j ← 0
        Tant que (j < i) Et ok Faire
            Si M[i, j] ≠ 0 Alors
                ok ← Faux
            Sinon
                j ← j + 1
            FinSi
        Fin Tant que
        i ← i + 1
    Fin Tant que
    Retourner ok
FIN

TDOL

ObjetType / Nature
i, jEntier
okBooléen
En Python
def Triangulaire_Sup(M, N):
    ok = True
    i = 1
    while (i < N) and ok:
        j = 0
        while (j < i) and ok:
            if M[i, j] != 0:
                ok = False
            else:
                j = j + 1
        i = i + 1
    return ok

Exemple vérifié. La fonction retourne Vrai pour la matrice ci-dessous, et Faux pour la matrice symétrique du paragraphe 6.1.

012
0147
1025
2003

7. Transformations : diagonales, transposée, lignes, tris

7.1 InverserDiag1 et InverserDiag2

Procédure InverserDiag1(M, N) qui échange les éléments d’une matrice carrée de part et d’autre de sa diagonale principale : M[i, j] et M[j, i] échangent leurs valeurs. La matrice obtenue est la transposée de M.

Procédure InverserDiag1 (@M : Mat, N : Entier)
DEBUT
    Pour i de 1 à N - 1 Faire
        Pour j de 0 à i - 1 Faire
            aux ← M[i, j]
            M[i, j] ← M[j, i]
            M[j, i] ← aux
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, j, auxEntier

Procédure InverserDiag2(M, N) qui échange les éléments de part et d’autre de la diagonale secondaire : M[i, j] et M[N - 1 - j, N - 1 - i] échangent leurs valeurs.

Procédure InverserDiag2 (@M : Mat, N : Entier)
DEBUT
    Pour i de 0 à N - 2 Faire
        Pour j de 0 à N - i - 2 Faire
            aux ← M[i, j]
            M[i, j] ← M[N - j - 1, N - i - 1]
            M[N - j - 1, N - i - 1] ← aux
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, j, auxEntier
En Python
def InverserDiag1(M, N):
    for i in range(1, N):
        for j in range(i):
            aux = M[i, j]
            M[i, j] = M[j, i]
            M[j, i] = aux

def InverserDiag2(M, N):
    for i in range(N - 1):
        for j in range(N - i - 1):
            aux = M[i, j]
            M[i, j] = M[N - j - 1, N - i - 1]
            M[N - j - 1, N - i - 1] = aux

Sur la matrice M : à gauche après InverserDiag1, à droite après InverserDiag2. Les diagonales concernées ne bougent pas.

0123
05742
12369
29205
31837
0123
07381
15029
29632
32475

Remarque importante. On ne parcourt que la moitié de la matrice : la zone au-dessous de la diagonale principale pour InverserDiag1, la zone au-dessus de la diagonale secondaire pour InverserDiag2. Parcourir toute la matrice échangerait chaque paire deux fois : la matrice reviendrait à son état de départ, sans aucun message d’erreur.

7.2 Transposee

Pour une matrice qui n’est pas carrée, la transposée ne peut pas se construire sur place : M a NL lignes et NC colonnes, sa transposée M2 a NC lignes et NL colonnes.

Procédure Transposee (M : Mat, NL, NC : Entier, @M2 : Mat)
DEBUT
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            M2[j, i] ← M[i, j]
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, jEntier
En Python
def Transposee(M, NL, NC, M2):
    for i in range(NL):
        for j in range(NC):
            M2[j, i] = M[i, j]

Exemple vérifié. La matrice 1 2 3 / 4 5 6, de 2 lignes et 3 colonnes, donne 1 4 / 2 5 / 3 6, de 3 lignes et 2 colonnes.

7.3 PermuterLignes

Procédure PermuterLignes(M, NC, L1, L2) qui échange le contenu des lignes L1 et L2, case par case.

Procédure PermuterLignes (@M : Mat, NC, L1, L2 : Entier)
DEBUT
    Pour j de 0 à NC - 1 Faire
        aux ← M[L1, j]
        M[L1, j] ← M[L2, j]
        M[L2, j] ← aux
    Fin Pour
FIN

TDOL

ObjetType / Nature
j, auxEntier
En Python
def PermuterLignes(M, NC, L1, L2):
    for j in range(NC):
        aux = M[L1, j]
        M[L1, j] = M[L2, j]
        M[L2, j] = aux

Sur la matrice M, PermuterLignes(M, 4, 0, 3) donne la première ligne 2 9 5 7 et la dernière 5 2 9 1. L’échange de deux colonnes s’écrit de la même façon, avec Pour i de 0 à NL - 1 et M[i, C1], M[i, C2].

7.4 TrierLigne

Procédure TrierLigne(M, NC, NUML) qui trie par ordre croissant les éléments de la ligne NUML. Ce sont les tris d’un tableau, où T[j] est remplacé par M[NUML, j] : l’indice de ligne reste fixe.

Méthode 1 : tri à bulles

Procédure TrierLigne (@M : Mat, NC, NUML : Entier)
DEBUT
    Répéter
        Permut ← Faux
        Pour j de 0 à NC - 2 Faire
            Si M[NUML, j] > M[NUML, j + 1] Alors
                aux ← M[NUML, j]
                M[NUML, j] ← M[NUML, j + 1]
                M[NUML, j + 1] ← aux
                Permut ← Vrai
            FinSi
        Fin Pour
        NC ← NC - 1
    Jusqu'à Non(Permut) Ou (NC = 1)
FIN

TDOL

ObjetType / Nature
j, auxEntier
PermutBooléen

Méthode 2 : tri par sélection

Procédure TrierLigne (@M : Mat, NC, NUML : Entier)
DEBUT
    Pour j de 0 à NC - 2 Faire
        posmin ← j
        Pour k de j + 1 à NC - 1 Faire
            Si M[NUML, k] < M[NUML, posmin] Alors
                posmin ← k
            FinSi
        Fin Pour
        Si posmin ≠ j Alors
            aux ← M[NUML, j]
            M[NUML, j] ← M[NUML, posmin]
            M[NUML, posmin] ← aux
        FinSi
    Fin Pour
FIN

TDOL

ObjetType / Nature
j, k, posmin, auxEntier

Méthode 3 : tri par insertion

Procédure TrierLigne (@M : Mat, NC, NUML : Entier)
DEBUT
    Pour j de 1 à NC - 1 Faire
        aux ← M[NUML, j]
        k ← j
        Tant que (k > 0) Et (M[NUML, k - 1] > aux) Faire
            M[NUML, k] ← M[NUML, k - 1]
            k ← k - 1
        Fin Tant que
        M[NUML, k] ← aux
    Fin Pour
FIN

TDOL

ObjetType / Nature
j, k, auxEntier
En Python
def TrierLigne(M, NC, NUML):          # méthode 1, tri à bulles
    Permut = True
    while Permut and NC > 1:
        Permut = False
        for j in range(NC - 1):
            if M[NUML, j] > M[NUML, j + 1]:
                aux = M[NUML, j]
                M[NUML, j] = M[NUML, j + 1]
                M[NUML, j + 1] = aux
                Permut = True
        NC = NC - 1

def TrierLigne_Insertion(M, NC, NUML):  # méthode 3
    for j in range(1, NC):
        aux = M[NUML, j]
        k = j
        while k > 0 and M[NUML, k - 1] > aux:
            M[NUML, k] = M[NUML, k - 1]
            k = k - 1
        M[NUML, k] = aux

Sur la matrice M, les trois méthodes donnent pour la ligne 0 : 1 2 5 9. Les autres lignes ne sont pas modifiées.

Remarque importante. Dans la méthode 1, NC est passé par valeur : le décrémenter ne modifie pas le nombre de colonnes du programme appelant. La condition d’arrêt Non(Permut) Ou (NC = 1) évite un dernier parcours vide.

7.5 TrierColonne

Procédure TrierColonne(M, NL, NUMC) qui trie par ordre croissant les éléments de la colonne NUMC. C’est le même algorithme, où l’indice de colonne reste fixe et l’indice de ligne varie.

Procédure TrierColonne (@M : Mat, NL, NUMC : Entier)
DEBUT
    Pour i de 1 à NL - 1 Faire
        aux ← M[i, NUMC]
        k ← i
        Tant que (k > 0) Et (M[k - 1, NUMC] > aux) Faire
            M[k, NUMC] ← M[k - 1, NUMC]
            k ← k - 1
        Fin Tant que
        M[k, NUMC] ← aux
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, k, auxEntier
En Python
def TrierColonne(M, NL, NUMC):
    for i in range(1, NL):
        aux = M[i, NUMC]
        k = i
        while k > 0 and M[k - 1, NUMC] > aux:
            M[k, NUMC] = M[k - 1, NUMC]
            k = k - 1
        M[k, NUMC] = aux

Sur la matrice M, la colonne 1 devient 2 3 6 9.

Pour passer d’un tri de ligne à un tri de colonne, avec n’importe quelle méthode :

Tri d’une ligneTri d’une colonne
M[NUML, j]M[i, NUMC]
borne NCborne NL

8. Matrice et tableau

8.1 TransfertVersTableau

Procédure TransfertVersTableau(M, NL, NC, T) qui range les éléments de M, ligne après ligne, dans un tableau T de NL * NC éléments.

Méthode 1 : un compteur pour le tableau

Procédure TransfertVersTableau (M : Mat, NL, NC : Entier, @T : Tab)
DEBUT
    k ← 0
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            T[k] ← M[i, j]
            k ← k + 1
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, j, kEntier

Méthode 2 : l’indice calculé

Procédure TransfertVersTableau (M : Mat, NL, NC : Entier, @T : Tab)
DEBUT
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            T[i * NC + j] ← M[i, j]
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, jEntier
En Python
def TransfertVersTableau(M, NL, NC, T):
    k = 0
    for i in range(NL):
        for j in range(NC):
            T[k] = M[i, j]
            k = k + 1

Sur la matrice M :

T5291732846032957
0123456789101112131415

Remarque importante. La case M[i, j] va dans T[i * NC + j] : chaque ligne complète décale de NC cases. Inversement, la case T[k] vient de la ligne k Div NC et de la colonne k Mod NC.

8.2 TransfertVersMatrice

Procédure TransfertVersMatrice(T, N, M) qui remplit une matrice carrée M de N lignes à partir d’un tableau T de N * N entiers.

Méthode 1 : un compteur pour le tableau

Procédure TransfertVersMatrice (T : Tab, N : Entier, @M : Mat)
DEBUT
    k ← 0
    Pour i de 0 à N - 1 Faire
        Pour j de 0 à N - 1 Faire
            M[i, j] ← T[k]
            k ← k + 1
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, j, kEntier

Méthode 2 : l’indice calculé

Procédure TransfertVersMatrice (T : Tab, N : Entier, @M : Mat)
DEBUT
    Pour i de 0 à N - 1 Faire
        Pour j de 0 à N - 1 Faire
            M[i, j] ← T[i * N + j]
        Fin Pour
    Fin Pour
FIN

TDOL

ObjetType / Nature
i, jEntier
En Python
def TransfertVersMatrice(T, N, M):
    for i in range(N):
        for j in range(N):
            M[i, j] = T[i * N + j]

Le tableau du paragraphe 8.1 redonne exactement la matrice M, par les deux méthodes.

En détail

Le passage par un tableau sert surtout à trier tous les éléments d’une matrice : on transfère dans T, on trie T avec un tri du chapitre des tris, puis on retransfère dans M. La matrice est alors triée ligne après ligne.

9. De la matrice vers un fichier texte

Une ligne d’un fichier texte est une seule chaîne de caractères. Pour y écrire plusieurs nombres, on les convertit par Convch et on les concatène, séparés par un espace, avant d’écrire la ligne par Écrire_nl.

9.1 SauvegarderLignes

Procédure SauvegarderLignes(M, NL, NC, NomFich) qui enregistre chaque ligne de M sur une ligne du fichier texte NomFich, les éléments séparés par un espace. Le dernier élément d’une ligne n’est pas suivi d’un espace.

Procédure SauvegarderLignes (M : Mat, NL, NC : Entier, NomFich : Chaîne de caractères)
DEBUT
    Ouvrir(NomFich, f, "w")
    Pour i de 0 à NL - 1 Faire
        ligne ← ""
        Pour j de 0 à NC - 1 Faire
            ligne ← ligne + Convch(M[i, j]) + " "
        Fin Pour
        Écrire_nl(f, Sous_chaine(ligne, 0, Long(ligne) - 1))
    Fin Pour
    Fermer(f)
FIN

TDOL

ObjetType / Nature
fFichier texte
i, jEntier
ligneChaîne de caractères
En Python
def SauvegarderLignes(M, NL, NC, NomFich):
    f = open(NomFich, "w")
    for i in range(NL):
        ligne = ""
        for j in range(NC):
            ligne = ligne + str(M[i, j]) + " "
        f.write(ligne[0:len(ligne) - 1] + "\n")
    f.close()

Sur la matrice M, le fichier obtenu contient :

5 2 9 1
7 3 2 8
4 6 0 3
2 9 5 7

Remarque importante — la technique du dernier séparateur. On ajoute un espace après chaque élément, puis on retire le dernier par Sous_chaine(ligne, 0, Long(ligne) - 1). C’est la forme des corrigés officiels (session de contrôle 2023, matrice zoomée écrite avec le séparateur |). Elle évite de tester, à chaque élément, s’il est le dernier de la ligne.

9.2 SauvegarderColonnes

Procédure SauvegarderColonnes(M, NL, NC, NomFich) qui enregistre chaque colonne de M sur une ligne du fichier texte NomFich. Les deux boucles sont simplement inversées : la boucle extérieure porte sur les colonnes.

Procédure SauvegarderColonnes (M : Mat, NL, NC : Entier, NomFich : Chaîne de caractères)
DEBUT
    Ouvrir(NomFich, f, "w")
    Pour j de 0 à NC - 1 Faire
        colonne ← ""
        Pour i de 0 à NL - 1 Faire
            colonne ← colonne + Convch(M[i, j]) + " "
        Fin Pour
        Écrire_nl(f, Sous_chaine(colonne, 0, Long(colonne) - 1))
    Fin Pour
    Fermer(f)
FIN

TDOL

ObjetType / Nature
fFichier texte
i, jEntier
colonneChaîne de caractères
En Python
def SauvegarderColonnes(M, NL, NC, NomFich):
    f = open(NomFich, "w")
    for j in range(NC):
        colonne = ""
        for i in range(NL):
            colonne = colonne + str(M[i, j]) + " "
        f.write(colonne[0:len(colonne) - 1] + "\n")
    f.close()

Sur la matrice M, le fichier obtenu contient :

5 7 4 2
2 3 6 9
9 2 0 5
1 8 3 7

C’est la transposée de M : la même que celle obtenue par InverserDiag1 au paragraphe 7.1.

9.3 SauvegarderMaxLigne

Procédure SauvegarderMaxLigne(M, NL, NC, NomFich) qui enregistre dans le fichier texte NomFich le maximum de chaque ligne de M, à raison d’une ligne du fichier par ligne de la matrice, sous la forme Ligne i : maximum.

Procédure SauvegarderMaxLigne (M : Mat, NL, NC : Entier, NomFich : Chaîne de caractères)
DEBUT
    Ouvrir(NomFich, f, "w")
    Pour i de 0 à NL - 1 Faire
        max ← M[i, 0]
        Pour j de 1 à NC - 1 Faire
            Si M[i, j] > max Alors
                max ← M[i, j]
            FinSi
        Fin Pour
        Écrire_nl(f, "Ligne " + Convch(i) + " : " + Convch(max))
    Fin Pour
    Fermer(f)
FIN

TDOL

ObjetType / Nature
fFichier texte
i, j, maxEntier
En Python
def SauvegarderMaxLigne(M, NL, NC, NomFich):
    f = open(NomFich, "w")
    for i in range(NL):
        Max = M[i, 0]
        for j in range(1, NC):
            if M[i, j] > Max:
                Max = M[i, j]
        f.write("Ligne " + str(i) + " : " + str(Max) + "\n")
    f.close()

Sur la matrice M, le fichier obtenu contient :

Ligne 0 : 9
Ligne 1 : 8
Ligne 2 : 6
Ligne 3 : 9

9.4 SauvegarderMinColonne

Procédure SauvegarderMinColonne(M, NL, NC, NomFich) qui enregistre le minimum de chaque colonne, sous la forme Colonne j : minimum.

Procédure SauvegarderMinColonne (M : Mat, NL, NC : Entier, NomFich : Chaîne de caractères)
DEBUT
    Ouvrir(NomFich, f, "w")
    Pour j de 0 à NC - 1 Faire
        min ← M[0, j]
        Pour i de 1 à NL - 1 Faire
            Si M[i, j] < min Alors
                min ← M[i, j]
            FinSi
        Fin Pour
        Écrire_nl(f, "Colonne " + Convch(j) + " : " + Convch(min))
    Fin Pour
    Fermer(f)
FIN

TDOL

ObjetType / Nature
fFichier texte
i, j, minEntier
En Python
def SauvegarderMinColonne(M, NL, NC, NomFich):
    f = open(NomFich, "w")
    for j in range(NC):
        Min = M[0, j]
        for i in range(1, NL):
            if M[i, j] < Min:
                Min = M[i, j]
        f.write("Colonne " + str(j) + " : " + str(Min) + "\n")
    f.close()

Sur la matrice M, le fichier obtenu contient :

Colonne 0 : 2
Colonne 1 : 2
Colonne 2 : 0
Colonne 3 : 1
En détail

Le calcul du maximum d’une ligne est écrit directement dans la procédure. On peut aussi appeler la fonction MaximumLigne du paragraphe 4.6 : Convch(MaximumLigne(M, NC, i)). Elle figure alors dans le TDOL, avec la nature Fonction, et j et max en disparaissent.

10. D’un fichier texte vers une matrice

10.1 ChargerLignes

Procédure ChargerLignes(M, NL, NC, NomFich) qui remplit M à partir du fichier texte NomFich : chaque ligne du fichier contient une ligne de la matrice, NC entiers séparés par un espace, comme le fichier produit au paragraphe 9.1.

Chaque ligne lue est découpée : Pos donne la position du premier espace, Sous_chaine extrait le nombre qui le précède, Effacer supprime ce nombre et l’espace, et l’on recommence sur le reste.

Procédure ChargerLignes (@M : Mat, NL, NC : Entier, NomFich : Chaîne de caractères)
DEBUT
    Ouvrir(NomFich, f, "r")
    Pour i de 0 à NL - 1 Faire
        Lire_ligne(f, ligne)
        ligne ← ligne + " "
        Pour j de 0 à NC - 1 Faire
            p ← Pos(" ", ligne)
            M[i, j] ← Valeur(Sous_chaine(ligne, 0, p))
            ligne ← Effacer(ligne, 0, p + 1)
        Fin Pour
    Fin Pour
    Fermer(f)
FIN

TDOL

ObjetType / Nature
fFichier texte
i, j, pEntier
ligneChaîne de caractères
En Python
def ChargerLignes(M, NL, NC, NomFich):
    f = open(NomFich, "r")
    for i in range(NL):
        ligne = f.readline()
        ligne = ligne[:len(ligne) - 1]      # retrait du "\n", en Python seulement
        ligne = ligne + " "
        for j in range(NC):
            p = ligne.find(" ")
            M[i, j] = int(ligne[0:p])
            ligne = ligne[p + 1:]
    f.close()

Appliquée au fichier du paragraphe 9.1, la procédure redonne exactement la matrice M.

Remarque importante — l’espace sentinelle. Le dernier nombre d’une ligne n’est suivi d’aucun espace. Sans l’instruction ligne ← ligne + " ", la recherche de l’espace échoue sur ce dernier nombre : pour ligne = "1", Pos(" ", ligne) retourne -1, et Sous_chaine(ligne, 0, -1) n’a pas de sens. On ajoute donc un espace à la fin de la ligne avant de la découper : chaque nombre est alors suivi d’un espace. C’est l’opération inverse de la technique du dernier séparateur.

Remarque importante. La matrice est remplie par la procédure : elle est passée par référence (par adresse), @M. Sans le @, la procédure remplirait une copie, et la matrice du programme appelant resterait inchangée.

En détail

Le nombre de lignes NL est connu : la lecture se fait avec une boucle Pour, sans Fin_fichier. Lorsque le nombre de lignes n’est pas connu, on utilise Tant que Non(Fin_fichier(f)) et on compte les lignes lues, comme au paragraphe 10.2.

10.2 ChargerTexteMat

Procédure ChargerTexteMat(M, NL, NomFich) qui remplit une matrice de caractères M, de 50 colonnes, à partir du fichier texte NomFich : chaque ligne du fichier devient une ligne de la matrice, complétée par des # si elle contient moins de 50 caractères. NL reçoit le nombre de lignes du fichier.

Méthode 1 : compléter case par case

Procédure ChargerTexteMat (@M : MatC, @NL : Entier, NomFich : Chaîne de caractères)
DEBUT
    Ouvrir(NomFich, f, "r")
    NL ← 0
    Tant que Non(Fin_fichier(f)) Faire
        Lire_ligne(f, ligne)
        Pour j de 0 à 49 Faire
            Si j < Long(ligne) Alors
                M[NL, j] ← ligne[j]
            Sinon
                M[NL, j] ← "#"
            FinSi
        Fin Pour
        NL ← NL + 1
    Fin Tant que
    Fermer(f)
FIN

TDOL

ObjetType / Nature
fFichier texte
jEntier
ligneChaîne de caractères

Méthode 2 : compléter la chaîne d’abord

Procédure ChargerTexteMat (@M : MatC, @NL : Entier, NomFich : Chaîne de caractères)
DEBUT
    Ouvrir(NomFich, f, "r")
    NL ← 0
    Tant que Non(Fin_fichier(f)) Faire
        Lire_ligne(f, ligne)
        Tant que Long(ligne) < 50 Faire
            ligne ← ligne + "#"
        Fin Tant que
        Pour j de 0 à 49 Faire
            M[NL, j] ← ligne[j]
        Fin Pour
        NL ← NL + 1
    Fin Tant que
    Fermer(f)
FIN

Le TDOL est le même.

En Python
def ChargerTexteMat(M, NomFich):
    global NL
    f = open(NomFich, "r")
    NL = 0
    ligne = f.readline()
    while ligne != "":
        ligne = ligne[:len(ligne) - 1]
        for j in range(50):
            if j < len(ligne):
                M[NL, j] = ligne[j]
            else:
                M[NL, j] = "#"
        NL = NL + 1
        ligne = f.readline()
    f.close()

Exemple vérifié. Pour un fichier de trois lignes Bac 2027, Matrices et fichiers et ABN, NL reçoit 3 et la matrice contient, lignes complétées jusqu’à la colonne 49 :

Bac 2027##########################################
Matrices et fichiers##############################
ABN###############################################
En détail

On suppose que chaque ligne du fichier compte au plus 50 caractères et que le fichier compte au plus 20 lignes. Le nombre de lignes n’étant pas connu, le parcours se fait par Tant que Non(Fin_fichier(f)), et NL, passé par référence, sert à la fois de compteur et d’indice de la ligne à remplir.

11. Matrice et fichier de données

Dans un fichier de données, chaque élément est écrit et relu tel quel, sans conversion ni découpage : un fichier d’entiers reçoit des entiers.

11.1 Mat_Vers_Dat

Procédure Mat_Vers_Dat(M, NL, NC, NomFich) qui enregistre les éléments de M, ligne après ligne, dans le fichier d’entiers NomFich.

Procédure Mat_Vers_Dat (M : Mat, NL, NC : Entier, NomFich : Chaîne de caractères)
DEBUT
    Ouvrir(NomFich, f, "wb")
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            Écrire(f, M[i, j])
        Fin Pour
    Fin Pour
    Fermer(f)
FIN

TDOL

ObjetType / Nature
fFEnt
i, jEntier

11.2 Dat_Vers_Mat

Procédure Dat_Vers_Mat(M, NL, NC, NomFich) qui remplit M à partir du fichier d’entiers NomFich, qui contient NL * NC entiers rangés ligne après ligne. Le nombre d’éléments est connu : la lecture se fait avec deux boucles Pour.

Procédure Dat_Vers_Mat (@M : Mat, NL, NC : Entier, NomFich : Chaîne de caractères)
DEBUT
    Ouvrir(NomFich, f, "rb")
    Pour i de 0 à NL - 1 Faire
        Pour j de 0 à NC - 1 Faire
            Lire(f, M[i, j])
        Fin Pour
    Fin Pour
    Fermer(f)
FIN

TDOL

ObjetType / Nature
fFEnt
i, jEntier
En Python
from pickle import dump, load

def Mat_Vers_Dat(M, NL, NC, NomFich):
    f = open(NomFich, "wb")
    for i in range(NL):
        for j in range(NC):
            dump(int(M[i, j]), f)
    f.close()

def Dat_Vers_Mat(M, NL, NC, NomFich):
    f = open(NomFich, "rb")
    for i in range(NL):
        for j in range(NC):
            M[i, j] = load(f)
    f.close()

Un aller-retour Mat_Vers_Dat puis Dat_Vers_Mat redonne exactement la matrice M.

Remarque importante. Le nom logique du fichier est le premier paramètre de Écrire et de Lire : Écrire(f, M[i, j]), jamais Écrire(M[i, j], f). L’inversion est une erreur sanctionnée à la correction du bac.

En détail

En Python, int(M[i, j]) convertit l’élément numpy en entier Python avant l’écriture ; dump(M[i, j], f) fonctionnerait aussi, mais enregistrerait un objet numpy.

12. Les erreurs les plus fréquentes

Chaque conséquence a été obtenue en exécutant l’instruction erronée sur la matrice M.

Instruction erronéeInstruction correcteConséquence
max ← 0max ← M[0, 0]sur une matrice d’éléments négatifs, le maximum retourné est 0
Position du maximum avec ≥avec >la dernière occurrence est retenue : (3, 1) au lieu de (0, 2)
SommeDiagonales sans Si N Mod 2 = 1avec la correctionpour N impair, la case centrale est comptée deux fois : 30 au lieu de 25 sur 1 2 3 / 4 5 6 / 7 8 9
InverserDiag1 avec Pour j de 0 à N - 1Pour j de 0 à i - 1chaque paire est échangée deux fois : la matrice est inchangée
Écrire_nl() dans la boucle sur japrès la boucle sur jun élément affiché par ligne
Écrire_nl(f, ligne) sans Sous_chaineSous_chaine(ligne, 0, Long(ligne) - 1)chaque ligne du fichier se termine par un espace : "5 2 9 1 "
Découpage sans ligne ← ligne + " "avec l’espace sentinellePos retourne -1 sur le dernier nombre de la ligne
Procédure ChargerLignes (M : Mat, …)@M : Matla matrice du programme appelant n’est pas remplie
Écrire(M[i, j], f)Écrire(f, M[i, j])erreur sanctionnée au bac : le fichier est le premier paramètre
Vérification avec deux boucles Pourdeux boucles Tant querésultat juste, mais la matrice entière est parcourue même après un contre-exemple

13. Retenons

Indices. Les lignes vont de 0 à NL - 1, les colonnes de 0 à NC - 1. Une ligne : i fixe, j varie. Une colonne : j fixe, i varie.

Zones. Diagonale principale i = j, diagonale secondaire i + j = N - 1. Pour échanger autour d’une diagonale, on ne parcourt que la moitié de la matrice.

Extremums. On initialise avec un élément de la matrice, jamais avec 0. La comparaison stricte retient la première occurrence.

Recherche et vérification. On s’arrête au premier élément trouvé ou au premier contre-exemple : boucles Tant que.

Matrice et tableau. M[i, j] correspond à T[i * NC + j] ; T[k] correspond à M[k Div NC, k Mod NC].

Vers un fichier texte. On convertit par Convch, on concatène avec un séparateur, on retire le dernier séparateur, puis Écrire_nl.

Depuis un fichier texte. On ajoute un séparateur sentinelle à la fin de la ligne, puis on découpe par Pos, Sous_chaine, Valeur et Effacer.

Fichier de données. Chaque élément s’écrit et se relit tel quel : Écrire(f, M[i, j]), Lire(f, M[i, j]).

TâcheBoucle
Parcours complet, calcul, remplissagedeux Pour
Recherche, vérificationdeux Tant que
Saisie contrôléeRépéter … Jusqu'à
Lecture d’un fichier au nombre de lignes connuPour
Lecture d’un fichier au nombre de lignes inconnuTant que Non(Fin_fichier(f))

ABN Academy · Anis Ben Nacib · Résumé « Les matrices — modules classiques » · 4ᵉ SI

Pour aller plus loin : le cours complet, les exercices corrigés et le quiz dans Les tableaux à deux dimensions.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *