Correction TP1 INFO1

Voici une proposition de correction du TP1-DUT1 des semaines 41 et 42 :

Haskell
---
--     M o y e n n e    o l y m p i q u e
----
 
 
-- Version 1 : avec 4 nombres (type numérique quelconque)
-- On fait la somme des 4 nbs puis on retranche le mini, le maxi et on divise par 2
 
m_o4 :: (Fractional t, Ord t) => t -> t -> t -> t -> t 
m_o4               a    b    c    d =
  (s - mini - maxi) / 2
  where {
    s    = a + b + c + d ;
    mini = min d (min c (min a b)) ;
    maxi = max d (max c (max a b))
        }
 
-- Bof : et si on avait 5 nbs ? et si on avait 145 456 765 812 nbs ?
-- Version 2 : calculons la mo d'une liste de nombres de longueur quelconque 
 
-- Préliminaire 1 : parlons de récursion
-- Factorielle : 0! = 1 et n! = n * (n - 1)!
fac :: Integer -> Integer
fac    0   =  1
fac    n   =  n * (fac (n - 1))
 
-- Préliminaire 2 : calculons la somme des éléments d'une liste de nombres 
-- On utilise un  FILTRAGΕ PAR MOTIF (pattern matching) 
-- c.a.d. je regarde à quoi ressemble mon argument et j'agis selon les cas
-- Je prends un type quelconque typ qui est dans la classe Num (donc un nombre qu'on peut additionner)
som_liste :: (Num typ) => [typ]                               -> typ
som_liste                 []                                  =  error "Ta liste est vide !!"
som_liste                 (tete_de_liste : [])                =  tete_de_liste  
som_liste                 (tete_de_liste : liste_décapitée)   =  (+) tete_de_liste (som_liste liste_décapitée) 
 
-- On peut mainenant calculer le minimum d'une liste de la même manière
-- t doit être de la classe Ord (utilisation de min nécessite un type ordonnable)
min_liste :: ( Ord t) => [t]                      -> t
min_liste                []                       =  error "Ta liste est vide !!"
min_liste                (tete : [])              =  tete
min_liste                (tete : liste_décapitée) =  min tete (min_liste liste_décapitée)
 
-- Plus rapide !!! min_liste xs = foldl1 min xs à adapter à min, max, long_float
 
-- t doit être de la classe Ord (utilisation de max)
max_liste :: (Ord t) => [t]                      -> t
max_liste               []                       =  error "Ta liste est vide !!"
max_liste               (tete : [])              =  tete
max_liste               (tete : liste_décapitée) =  max tete (max_liste liste_décapitée)
 
-- Longueur d'une liste (il existe déjà length mais son codomaine est Int : on ne pourra pas
--                        utiliser l'opérateur / dans m_o)
-- La longueur renvoyée est un type de la classe Fractional car on va diviser la somme
-- des notes par cette longueur
long_float :: Fractional nb => [patates]      -> nb -- nb est Float ou Double
long_float                     []             =  0
long_float    (tete : liste_décapitée)        =  1 +  (long_float liste_décapitée)
 
-- On peut maintenant calculer la moyenne olympique d'une liste : 
--      le type doit être dans Fractional pour diviser et dans Ord pour classer 
m_o :: (Ord t, Fractional t) => [t] -> t
m_o     liste_notes      =
                        if nb_notes <= 0 then error "Liste trop courte !"
                        else 
                          (som_notes - note_mini - note_maxi) / nb_notes
  where {
    som_notes =  som_liste  liste_notes ;
    note_mini =  min_liste  liste_notes ;
    note_maxi =  max_liste  liste_notes ;
    nb_notes  =  (long_float liste_notes) - 2
    }
 
 
 
{- version 2  avec let in au lieu de where
 
m_o :: (Ord t, Fractional t) => [t] -> t
m_o     liste_notes      =
  let {
    som_notes =  som_liste  liste_notes ;
    note_mini =  min_liste  liste_notes ;
    note_maxi =  max_liste  liste_notes ;
    nb_notes  =  (long_float liste_notes) - 2
    }
  in 
   if nb_notes <= 0 then error "Liste trop courte !"
   else 
     (som_notes - note_mini - note_maxi) / nb_notes 
-}