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 -}