Une solution du TD 5 de Caml (v.16.1)

Exercice 1
1.
commanderetour
List.map int of char ['0';'2'];; − : int list = [48; 50]
List.fold right (fun x y−>x^y) ["ab";"cd";"ef"] "";; − : string = "abcdef"
List.fold left (-) 1000 [5;10;15;20];; − : int = 950
List.filter (fun n −> n>='G') ['a';'A';'n';'4';'#';'Z'];;   − : char list = ['a'; 'n'; 'Z']
2.
let rec listmap f s =
  if s==[] then []
  else (f (List.hd s))::(listmap f (List.tl s);;

let rec foldright f s b =
  if (List.tl s)==[] then (f (List.hd s) b)
  else (f (List.hd s) (foldright f (List.tl s) b));;

let rec foldleft f a s =
  if (List.tl s)==[] then (f a (List.hd s))
  else (f (foldleft f a (List.tl s)) (List.hd s));;

N.B. Ces deux dernières fonctions ne sont donc pas définies pour une liste vide, en est-il de même pour les fonctions de référence de Caml ?
let rec filter f s =
  if s==[] then []
  else if f(List.hd s) then (List.hd s)::(filter f (List.tl s))
  else (filter f (List.tl s))


Exercice 2
let carreliste s = List.map (fun x->x*x) s;;
let racliste s = List.map (fun x->sqrt(float_of_int(x))) s;;

Exercice 3
let taille s = List.fold_right (fun x y -> 1+y) s 0;;
  pour des listes quelconques.
let somme s = List.fold_right (+) s 0;;
  pour des listes d'entiers (opérateur +).
let produit s = List.fold_right ( * ) s 1;;
  pour des listes d'entiers (opérateur *).
let minimal s = List.fold_right min (List.tl s) (List.hd s);;
  pour des listes dont les éléments sont d'un même type comparable.

Exercice 4
let selectpaire s = List.filter (fun n -> (n mod 2)==0) s;;
let selectmaj s = List.filter (fun c-> (c>='A' && c<='Z')) s;;

Exercice 5
let carresomme s = somme (carreliste s);;
  On peut aussi définir directement cette fonction :
  let carresomme s = List.fold_right (fun x y -> x*x+y) s 0;;
let n_poire s = somme (List.filter (fun x -> match x with |(Poire n)->n |_>0) s);;
  ou directement :
  let n_poire s = List.fold_right (List.filter (fun x y -> (match x with |(Poire n)->n |_>0)+y) s) 0;;

Exercice 6
1.
machin retourne la liste s inchangée (pourquoi?).
2.
truc ne peut être définie car le paramètre de base du fold est la liste [] mais que la fonction utilise x comme élément d'une liste (conflit de types).
3.
Il faut utiliser les idées données par les deux exemples précédents...

Exercice-projet
Cet exercice construit un projet complet utilisant les différentes notions vues précédemment.
(* 1. *)
type caisse =
  Vide |
  Pomme of int |
  Poire of int |
  Peche of int |
  Banane of int;;
(* definir des variables pour tester les types et les fonctions *)
let (k:caisse) = Poire 3;;
(* deux types semantiquement different mais structurellement identique *)
type commande = caisse;;
let (m:commande) = Pomme 2;;
type fourgon = caisse list;;
let (f:fourgon) = [Pomme 2; Bannane 4; Vide; Pomme 1];;
(* definir un type intermediaire pile de caisse *)
type pile = caisse list;;
(* un hangar est une liste de listes de caisse *)
type hangar = pile list;;
let (h:hangar)= [ [] ; [Pomme 2;Poire 3;Vide;Pomme 1]; [Poire 5] ];;
(* 2. *)
(* nombre de fruits dans une caisse ou une commande *)
let nombrefruits c = match c with
  | Vide −> 0
  | Pomme n −> n
  | Poire n −> n
  | Banane n −> n;;
(* 3. *)
(* Y a-t-il au moins nc caisses dans la liste de caisses p *)
let aumoinscaisses p nc =
  List.length(p)>=nc;;
(* definir des fonctions annexes selon les besoins *)
let taillelistecaisse p =
  List.fold_right (+) (List.map nombrefruits p) 0;;
(* Y a-t-il au moins nf fruits dans une liste de caisse p *)
let aumoinsfruits p nf =
  (taillelistecaisse p )>=nf;;
(* 4. *)
(* ajouter une caisse c à une liste de caisse s *)
let ajoutcaisse (c:caisse) s = c::s;;
(* n'ajouter c à s que s'il y a moins de nc caisses dans s *)
let ajoutcaisseSi (c:caisse) s nc =
  if (List.length(s)<=nc) then c::s else s;;
(* 5. *)
(* fonction annexe generalisee : nf=30 pour l'enonce *)
(* dupliquer une caisse c de plus de nf fruit ou supprimer une caisse vide *)
(* la fonction retourne une liste de 0 à 2 caisses *)
let calibrercaisse c nf=
  if (nombrefruits c)>nf then match c with
    | Vide −> []
    | Pomme x −> [Pomme nf;Pomme (x-nf)]
    | Poire x −> [Poire nf;Poire (x-nf)]
    | Peche x −> [Peche nf;Peche (x-nf)]
    | Banane x −> [Banane nf;Banane (x-nf)]
  else [c];;
(* supprime les caisses vides et duplique les caisses de plus
    de nf fruits d'une pile de caisse p *)
(* solution plus generale : *)
(* utiliser avec nf=30 pour repondre a la question de l'enonce *)
let rec repartirfruits p nf =
  if (p==[]) then []
  else (calibrerercaisse (List.hd p) nf)@(repartirfruits (List.tl p) nf);;

Le reste du projet doit être développé en TP.
On construira auparavant des algorithmes pour les fonctions plus élaborées, selon le modèle ci-dessous.
Après implémentation, les fonctions seront testées sur différents exemples bien choisis.

6.
Algorithme organiser
Entrée : un hangar h (liste de piles de caisses).
Sortie : ce hangar réorganisé avec au plus 30 fruits par caisse et 10 caisses par pile.
Si h est vide alors retourner un hangard vide
Sinon si la pile de tête de h est vide alors organiser la queue de h
Sinon dans la pile de tête p de h :
ajouter si nécessaire des caisses dans p (au plus 30 fruits par caisse);
partitionner si nécessaire p en plusieurs piles (au plus 10 caisses par pile);
retourner le hangar obtenu en ajoutant p ou la suite de piles issue de la partition à l'organisation de la queue de h.

7. 8. 9. 10. 11. 12.  : etc.
© 2016 – A. Sigayret