Skip to content
Snippets Groups Projects
tp2.ml 7.89 KiB
Newer Older
(**********************************************************************)
(**********************************************************************)
(* 1.1 *)

(**
Concatène 2 listes
@param l1 la première liste à concaténer
@param l2 la deuxième liste
@return la liste résultant de la concaténation de l1 avec l2 
*)
let rec concatene (l1 : int list) (l2 : int list) : int list =
  match l1 with [] -> l2 | x :: l1' -> x :: concatene l1' l2
;;

(* Quelques tests *)
concatene [ 1; 2; 3 ] [ 4; 5; 6 ] = [ 1; 2; 3; 4; 5; 6 ];;
concatene [] [ 4; 5; 6 ] = [ 4; 5; 6 ];;
concatene [ 1; 2; 3 ] [] = [ 1; 2; 3 ];;
concatene [] [] = []

(**********************************************************************)
(* 1.2 *)

(**
applatit prend une liste de liste et renvoie la liste resultant de la concatenation des sous-listes
@param ll la liste contenant les liste à concatener
@return la liste contenant les élements des sous-listes    
*)
let rec applatit (ll : int list list) : int list =
  match ll with [] -> [] | l :: ll' -> concatene l (applatit ll')
;;

(* Quelques tests *)
applatit [ [ 1; 2 ]; [ 3; 4; 5 ]; []; [ 6 ] ] = [ 1; 2; 3; 4; 5; 6 ];;
applatit [ [ 1 ] ] = [ 1 ];;
applatit [ [] ] = [];;
applatit [] = []

(**
applatit2 prend une liste de liste et renvoie la liste resultant de la concatenation des sous-listes.
applatit2 n'utilise pas concatene
@param ll la liste contenant les liste à concatener
@return la liste contenant les élements des sous-listes    
*)
let rec applatit2 (ll : int list list) : int list =
  match ll with
  | [] -> []
  | [] :: ll' -> applatit2 ll'
  | (n :: l') :: ll' -> n :: applatit2 (l' :: ll')
;;

(* Quelques tests *)
applatit2 [ [ 1; 2 ]; [ 3; 4; 5 ]; []; [ 6 ] ] = [ 1; 2; 3; 4; 5; 6 ];;
applatit2 [ [ 1 ] ] = [ 1 ];;
applatit2 [ [] ] = [];;
applatit2 [] = []

(**********************************************************************)
(**********************************************************************)
(* 2 *)

(**
Renverse une liste.
@param l la liste à renverse.
@return la liste renversée    
*)
let renverse =
  (*
  Cette fonction concatène son premier argument renversé à son second
  @param lr la liste à renverser
  @param lc la liste à laquelle on veut concaténer des éléments
  @return la concaténation de lr renversée et de lc    
  *)
  let rec renverse_ajoute (lr : int list) (lc : int list) : int list =
    match lr with
    | [] -> lc
    | n :: lr' ->
        (* on ajoute n en tête de la liste lc et on fait l'appel récursif
           qui ajoutera les autres éléments devant *)
        renverse_ajoute lr' (n :: lc)
  in
  fun (l : int list) -> renverse_ajoute l []

(**********************************************************************)
(**********************************************************************)
(* 3.1 *)
(* Insersion dans une liste triée *)

(**
Insère un entier dans une liste triée.
@param n la valeur à insérer
@param l la liste dans laquelle on fait l'insertion    
@return une nouvelle liste contenant les élément de l et n et elle-même
*)
let rec insertion (n : int) (l : int list) : int list =
  match l with
  | [] -> [ n ] (* on aurait pu écrire [n] *)
  | k :: l' ->
      if k >= n (* on veut placer n en tête de liste *) then n :: l
        (* attention c'est n :: l et pas n :: l'
           on aurait aussi pu écrire n :: k :: l' *)
      else k :: insertion n l'
;;

(* Quelques tests*)
insertion 3 [ 1; 2; 4; 5 ] = [ 1; 2; 3; 4; 5 ];;
insertion 3 [ 1; 2; 3; 4; 5 ] = [ 1; 2; 3; 3; 4; 5 ];;
insertion 3 [ 4; 5 ] = [ 3; 4; 5 ];;
insertion 3 [ 1; 2 ] = [ 1; 2; 3 ];;
insertion 3 [] = [ 3 ]
(**********************************************************************)
(* 3.2 *)

(**
Trie une liste en utilisant l'algorithme de tri par insertion
@param l la liste à trier
@return la liste contenant les éléments de l triés    
*)
let rec tri_insertion (l : int list) : int list =
  match l with
  | [] -> []
  | n :: l' ->
      (* Ici, on insère dans le reste de la liste triée *)
      insertion n (tri_insertion l')
;;

(* Quelques tests *)
tri_insertion [ 1; 4; 2; 3 ] = [ 1; 2; 3; 4 ];;
tri_insertion [ 1; 2; 3; 4 ] = [ 1; 2; 3; 4 ];;
tri_insertion [ 4; 3; 2; 1 ] = [ 1; 2; 3; 4 ];;
tri_insertion [ 1 ] = [ 1 ];;
tri_insertion [] = []

(**********************************************************************)
(**********************************************************************)
(* 4.1 *)

(** 
Résultat d'une recherche 
*)
type resultat =
  (* une valeur a été trouvée,
     on associe la donnée de cette valeur au constructeur,
     elle a donc le type string*)
  | Trouve of string
  (* On a rien trouvé, pas de donnée associée *)
  | Rien

(* 4.2 *)

(**
Cherche la valeur associée à une clé dans une liste de paires (clé,valeur).
@param cle la clé
@param la la liste d'association
@return Trouve v si la paire (cle,v) est dans la liste, Rien sinon
*)
let rec cherche (cle : int) (la : (int * string) list) : resultat =
  match la with
  | [] -> Rien
  | (cle', v) :: la' ->
      if cle' = cle (* si on a trouvé la clé *) then Trouve v
      else (* on cherche dans le reste de la liste *)
        cherche cle la'
;;

(* Quelques tests *)
cherche 3 [ (1, "a"); (3, "b"); (5, "c") ] = Trouve "b";;
cherche 3 [ (3, "b"); (5, "c") ] = Trouve "b";;
cherche 3 [ (1, "a"); (3, "b") ] = Trouve "b";;
cherche 3 [ (5, "b"); (1, "a") ] = Rien;;
cherche 3 [] = Rien

(**********************************************************************)
(**********************************************************************)

(**
Type représentant les opérateurs binaires.    
*)
type binop = Plus | Moins | Mult | Div

(**
Type représentant les morceaux d'expression.
*)
type elt_expr = Op of binop | Cst of int

(**
Type représentant les résultats.    
*)
type resultat =
  | Ok of int
  | ErrDivZero
  | ErrExpr
      (**
Évalue le résultat d'une opération binaire.
Prend l'opération en argument ainsi que deux résultats.
S'il l'un des arguments est une erreur, cette (une de ces)
erreur est renvoyée comme résultat.
@param op l'opération à effectuer
@param a1 la première valeur à passer à op
@param a2 la deuxième valeur à passer à op
@return le réultat de l'opération ou une erreur le cas échéant
*)
(* 5.1 *)

let eval_op (op : binop) (a1 : resultat) (a2 : resultat) : resultat =
  match (a1, a2) with
  | Ok v1, Ok v2 -> (
      match op with
      | Plus -> Ok (v1 + v2)
      | Moins -> Ok (v1 - v2)
      | Mult -> Ok (v1 * v2)
      | Div -> if v2 = 0 then ErrDivZero else Ok (v1 / v2))
  | Ok _, err -> err
  | err, _ -> err
;;

(* Quelques tests *)
eval_op Plus (Ok 1) (Ok 2) = Ok 3;;
eval_op Moins (Ok 2) (Ok 3) = Ok (-1);;
eval_op Div (Ok 3) (Ok 0) = ErrDivZero;;
eval_op Div (Ok 5) (Ok 2) = Ok 2;;
eval_op Mult (Ok 7) (Ok 6) = Ok 42;;
eval_op Plus ErrDivZero (Ok 5) = ErrDivZero;;
eval_op Mult ErrExpr (Ok 4) = ErrExpr;;
eval_op Div (Ok 5) ErrExpr = ErrExpr;;
eval_op Moins (Ok 4) ErrDivZero = ErrDivZero;;
eval_op Plus ErrDivZero ErrExpr = ErrDivZero

(**********************************************************************)
(* 5.2 *)

(**
Évalue une suite d'expressions et donne la liste des résultats
@param la liste d'éléments d'expression formant la liste suite d'expressions
@return le résultat de l'évaluation des expressions
*)
let rec eval_expr (le : elt_expr list) : resultat list =
  match le with
  | [] -> []
  | Cst n :: le' -> Ok n :: eval_expr le'
  | Op op :: le' -> (
      match eval_expr le' with
      | r1 :: r2 :: rl -> eval_op op r1 r2 :: rl
      | _ -> [ ErrExpr ])
;;

(* Quelques tests *)
eval_expr [ Cst 3 ] = [ Ok 3 ];;
eval_expr [ Op Mult; Cst 3; Cst 2 ] = [ Ok 6 ];;
eval_expr [ Op Div; Cst 7; Cst 3 ] = [ Ok 2 ];;
eval_expr [ Op Moins; Cst 3; Cst 1 ] = [ Ok 2 ];;
eval_expr [ Op Plus; Op Div; Cst 7; Cst 3 ] = [ ErrExpr ];;
eval_expr [ Op Plus; Op Div; Cst 7; Cst 3; Cst 5 ] = [ Ok 7 ];;

eval_expr [ Op Plus; Op Div; Cst 7; Op Moins; Cst 2; Cst 2; Cst 3 ]
= [ ErrDivZero ]
;;

eval_expr [ Op Plus; Cst 3; Cst 5; Op Moins; Cst 2; Cst 7 ] = [ Ok 8; Ok (-5) ]