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) <- 5Corrigé
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.