Adloun

Trois lignes, une matrice fausse

Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 6 — Types et structures de données abstraites

Énoncé

Que valent les deux matrices après ces lignes ? Expliquer, et donner la bonne écriture.


let m = Array.make 3 (Array.make 3 0)
let () = m.(0).(0) <- 5

let n = Array.make_matrix 3 3 0
let () = n.(0).(0) <- 5

Corrigé

Mesuré :


m = [|5;0;0|] [|5;0;0|] [|5;0;0|]      <-- les TROIS lignes ont change
n = [|5;0;0|] [|0;0;0|] [|0;0;0|]      <-- correct

Pourquoi. Array.make 3 v range la même valeur v dans les trois cases. Ici v est un tableau, donc une valeur mutable : les trois cases désignent le même tableau de trois entiers. Écrire par l'une, c'est écrire par les trois. L'expression Array.make 3 0 n'a été évaluée qu'une fois — c'est un argument, pas une recette.

Les deux bonnes écritures :


let n = Array.make_matrix 3 3 0
let o = Array.init 3 (fun _ -> Array.make 3 0)   (* la fonction est RAPPELEE *)

La seconde dit exactement où est la différence : Array.init reçoit une fonction et l'appelle une fois par ligne, donc alloue trois tableaux.

Le même piège, une seconde fois. Array.copy est une copie superficielle : elle duplique le tableau extérieur et recopie les cases telles quelles. Mesuré, sur une matrice correcte :


let c = Array.copy n in c.(1).(1) <- 8   =>   n vaut [|5;0;0|] [|0;8;0|] [|0;0;0|]

La copie et l'original partagent leurs lignes. Le programme mentionne explicitement ce point — « copy (y compris le caractère superficiel de cette copie) » —, et c'est le même fait que le premier : en OCaml, ce qui se copie, c'est le bloc, pas ce qu'il désigne.

Le test qui l'attrape à coup sûr, et qu'il faut prendre l'habitude d'écrire : après avoir construit une matrice , modifier m.(0).(0) et vérifier que m.(1).(0) n'a pas bougé. Trois lignes de test contre une classe entière de fautes.

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.