PRFO23 : TP1 avancé

Préambule

Dans la mesure du possible on évitera d'écrire des fonctions récursives et on utilisera les fonctions du module List de la bibliothèque standard d'OCaml. Toute question devra être commentée et testée.

Exercice 1 : Question préliminaire

  1. Écrire une fonction all_same de type ('a -> 'b) -> 'a list -> bool telle que all_same f l retourne true ssi f retourne la même valeur pour tous les éléments de l.

Exercice 2 : Matrices comme listes de listes

On considère une matrice comme un liste qui contient des listes d'éléments, toutes ces listes étant de même longueur. On utilisera donc le type 'a list list. Par exemple, la matrice

123
456
sera représentée par la liste [[1; 2; 3]; [4; 5; 6]].

On fera l'hypothèse qu'aucune des listes d'une matrice n'est vide

  1. Écrire une fonction qui vérifie qu'une liste de listes représente bien une matrice, c'est-à-dire que toutes les listes qu'elle contient ont la même longueur.
  2. Écrire une fonction qui prend en paramètre une matrice et qui retourne sa dimension sous la forme d'un couple d'entiers.
  3. Écrire une fonction qui affiche une matrice sur la sortie standard.
  4. Écrire une fonction qui prend en paramètre deux matrices d'entiers et qui retourne la somme de ces matrices.
    On ne vérifiera pas que les dimensions coïncident, mais on pourra éventuellement rattraper les exceptions levées dans ce cas pour en lever une plus distinctive.
  5. Écrire une fonction qui prend en paramètre une matrice carrée d'entiers et qui retourne la trace de cette matrice.
    On ne vérifiera pas que la matrice est carrée, mais on pourra éventuellement rattraper les exceptions levées dans ce cas pour en lever une plus distinctive.
  6. Écrire une fonction qui prend en paramètre une matrice et qui retourne un couple formé d'une liste correspondant aux éléments de la première colonne de la matrice, et du reste de la matrice.
    Par exemple sur
    123
    456
    on retournera [1; 4], [[2; 3]; [5; 6]].
    (Attention ! Si la matrice ne contient qu'une colonne, le deuxième composant du couple sera une liste de listes vides et ne sera donc pas vraiment une matrice.)
  7. Écrire une fonction qui calcule la transposée d'une matrice.
  8. Écrire une fonction qui prend en paramètre deux matrices d'entiers et qui retourne le produit de ces matrices.
    Il pourra être utile de travailler avec la transposée de la deuxième matrice.
    On ne vérifiera pas que les dimensions sont compatibles, mais on pourra éventuellement rattraper les exceptions levées dans ce cas pour en lever une plus distinctive.

Exercice 3 : Stockage des dimensions

On veut garder les dimensions des matrices pour pouvoir facilement vérifier quelles sont correctes lors des calculs.

On définit donc un type

type 'a matrix = { content : 'a list list; h : int; w : int }
h est le nombre de lignes de la matrice et w le nombre de colonnes.

On réutilisera les fonctions de l'exercice précédent.

  1. Écrire une fonction qui prend en paramètre une liste de listes, qui vérifie qu'elle représente bien une matrice, et qui retourne la matrix correspondante.
  2. Écrire une fonction qui prend en paramètre une 'a matrix et qui vérifie que les dimensions indiquées dans les champs h et w sont bien celles de la liste content.
  3. Écrire une fonction qui prend en paramètre deux int matrix et qui retourne la somme de ces matrices.
    On vérifiera que les dimensions des deux matrices sont bien les mêmes.
  4. Écrire une fonction qui prend en paramètre une 'a matrix et qui retourne sa transposée.
  5. Écrire une fonction qui prend en paramètre deux int matrix et qui retourne le produit de ces matrices.
    On vérifiera que le nombre de colonnes de la première est bien égal au nombre de ligne de la seconde.

Exercice 4 : Généralisation

Généraliser les fonctions d'addition et de multiplication des matrices, pour quelles puissent prendre des matrices de n'importe quel type d'éléments. Pour cela, les fonctions d'addition et de multiplication prendront trois paramètres supplémentaires correspondant au zéro pour l'addition et aux opérations d'addition et de multiplication sur le type des éléments de la matrice.

On aura donc des fonctions de type

'a -> ('a -> 'a -> 'a) -> ('a -> 'a -> 'a) -> 'a matrix -> 'a matrix -> 'a matrix
(ou un type plus général).