\documentclass[10pt]{article} \usepackage{amsmath,amssymb,fancybox,fancyhdr,lastpage,a4,mdwlist} \topmargin-0.5cm \headheight20pt \textheight23cm \textwidth17.5cm \oddsidemargin-1cm \evensidemargin0cm \parindent0pt \def\[{[\![} \def\]{]\!]} \begin{document} \renewcommand{\labelenumi}{\arabic{enumi})} \renewcommand{\labelenumii}{\alph{enumii})} \renewcommand{\labelenumiii}{\roman{enumiii})} \pagestyle{fancy} \lhead{{\bf MPSI option informatique}} \chead{} \rhead{TP 2~: listes} \lfoot{\sl Lyc\'ee Chateaubriand} \cfoot{} \rfoot{\thepage/\pageref{LastPage}} \renewcommand{\footrulewidth}{0.4pt} \section*{\'Elementaire} Pour pouvoir tester les futures fonctions sur les listes, on va cr\'eer une liste pseudo--al\'eatoire. Posons $m = 2^{15} - 1 = 32\,767$ et $f:k\mapsto(123\times k + 15) \mod m$. On d\'efinit une suite (pseudo--al\'eatoire) $(u_n)$ par la donn\'ee de $u_0\in\mathbb N$ et de la r\'ecurrence $\forall n\in\mathbb N,u_{n+1}=f(u_n)$. Soit alors la liste $\ell(n,u_0)=[u_0;u_1;\dots;u_{n-1}]$ (de longueur $n$). \begin{enumerate} \item Programmer la fonction {\tt f : int -> int}. \item En remarquant que $\ell(n,u_0)=\begin{cases}[\,]&\mbox{si }n=0\\u_0::(\ell(n-1,u_1))&\mbox{si }n\geqslant1\end{cases}$~: programmer une fonction {\tt alea : int -> int -> int list} telle que l'appel {\tt alea n u0} renvoie $\tt\ell(n,u0)$. Test~: $\ell(10,1594)=[1594; 32242; 974; 21516; 25123; 10046; 23294; 14448; 7701; 29762]$ Dans la suite on notera $\ell$ cette liste. (par exemple vous pouvez la d\'efinir comme variable globale avec {\tt let l = alea 10 1594;;}) \suspend{enumerate} Pour chacune des questions \`a suivre~: pr\'evoir le type de sortie, \'ecrire la fonction puis v\'erifier le type obtenu. \resume{enumerate} \item \'Ecrire une fonction \texttt{map1} telle que l'appel \texttt{map1 f [x0;x1;...;xn]}\goodbreak retourne la liste \texttt{[f x0;f x1;...;f xn]}. Tester sur $\ell$ avec \texttt{f = fun x -> x mod 3}. \item {\it Mise en garde~: n'utilisez pas la touche \texttt{@} de votre clavier~: elle est pi\'eg\'ee~!} \medskip \'Ecrire une fonction \texttt{conc} qui concat\`ene deux listes. Testez votre fonction. \item \'Ecrire une fonction \texttt{rev1} qui inverse une liste pass\'ee en argument. Tester sur $\ell$. \item \'Ecrire une fonction \texttt{filtre} telle que \texttt{filtre p l} retourne la liste des \'el\'ements de \texttt{l} qui satisfont le pr\'edicat \texttt{p : x -> bool} o\`u \texttt{x} est le type des \'el\'ements de \texttt{l}. Tester avec \texttt{p} d\'efinit par \texttt{let p x = x mod 2 = 1}~: vous devez obtenir la liste des \'el\'ements impairs de $\ell$ (il y a 2 \'el\'ements impairs dans $\ell$). \suspend{enumerate} C'est bon, vous pouvez \`a nouveau utiliser la touche \texttt{@}. \section*{\texttt{'a} de Fibonacci} On se donne un type g\'en\'erique {\tt'a} ainsi que deux valeurs {\tt f0} et {\tt f1} de type {\tt'a}. Soit une fonction {\tt$\gamma$ : 'a -> 'a -> 'a}. On d\'efinit alors une suite $(f_n)$ de valeurs de type {\tt'a} par la r\'ecurrence~: $$\forall n\in\mathbb N,f_n= \begin{cases} {\tt f0}&\mbox{si }n=0\\ {\tt f1}&\mbox{si }n=1\\ \gamma(f_{n-1},f_{n-2})&\mbox{si }n\geqslant2 \end{cases}$$ \medskip \underline{Exemple}~: si {\tt'a} est le type {\tt int}, si $\tt f0=0$, si $\tt f1=1$ et si $\forall a,b\in\mathbb N,\gamma(a,b)=a+b$ (et donc $\forall n\geqslant2,f_n=f_{n-1}+f_{n-2}$) on retrouve la suite de Fibonacci {\it usuelle}. \resume{enumerate} \item \'Ecrire la fonction {\tt fibogen : ('a -> 'a -> 'a) -> 'a -> 'a -> int -> 'a} telle que l'appel de {\tt fibogen $\gamma$ f0 f1 n} renvoie $f_n$. \item Suite de Fibonacci usuelle \begin{enumerate} \item Syntaxe pr\'efix\'ee de l'addition Taper et \'evaluer \texttt{(+);;}. Interpr\'eter le r\'esultat. \\ Tester \texttt{(+) 7 8}. \item En d\'eduire une fonction {\tt fibo\_usuel : int -> int} qui calcule le $n$--i\`eme terme de la suite de Fibonacci usuelle. Votre fonction {\tt fibo\_usuel} ne doit contenir aucun appel r\'ecursif, elle doit se contenter de faire un seul appel \`a la fonction {\tt fibogen} (qui elle est r\'ecursive). Test~: le terme d'indice 12 de la suite de Fibonacci usuelle est 144. \end{enumerate} \item On d\'efinit une suite de cha\^ines $(w_n)$ par~: \begin{tabular}{|c|l|}\hline $w_0$ & \tt"b"\\\hline $w_1$ & \tt"a"\\\hline $w_2$ & \tt"ab"\\\hline $w_3$ & \tt"aba"\\\hline $w_4$ & \tt"abaab"\\\hline $w_5$ & \tt"abaababa"\\\hline \dots&\dots\\\hline \end{tabular} En utilisant judicieusement {\tt fibogen}, \'ecrire une fonction {\tt fiboword} qui calcule $w_n$~:\goodbreak {\tt fiboword : int -> string} \item La fonction {\tt fibolist} On d\'efinit une suite de listes d'entiers $(l_n)$ par~: \begin{tabular}{|c|l|}\hline $l_0$ & \tt[1]\\\hline $l_1$ & \tt[0]\\\hline $l_2$ & \tt[0;1]\\\hline $l_3$ & \tt[0;1;0]\\\hline $l_4$ & \tt[0;1;0;0;1]\\\hline $l_5$ & \tt[0;1;0;0;1;0;1;0]\\\hline \dots&\dots\\\hline \end{tabular} En utilisant judicieusement {\tt fibogen}, \'ecrire une fonction {\tt fibolist} qui calcule $l_n$~:\goodbreak {\tt fibolist : int -> int list} \item \'Ecrire une fonction \texttt{nb\_occ} qui d\'etermine le nombre d'occurrences d'un \'el\'ement d'une liste du deuxi\`eme exemple. V\'erifier pour quelques valeurs de $\tt n$ que \texttt{nb\_occ 0 (fibolist n) = fibo\_usuel n}. S'il vous reste du temps~: d\'emontrer cette propri\'et\'e. \item \begin{enumerate} \item \'Ecrire une fonction \texttt{tronque} telle que \texttt{tronque n $\ell$} retourne $\ell$ priv\'ee de ses {\tt n} derniers \'el\'ements. \item V\'erifier que pour tout $i\in\[3,8\]$, $l_i$ priv\'ee de ses deux derniers \'el\'ements est un palindrome (on pourra utiliser une fonction qui calcule le miroir d'une liste). S'il vous reste du temps~: d\'emontrer cette propri\'et\'e. \end{enumerate} \item \begin{enumerate} \item \'Ecrire une fonction {\tt remplace : 'a -> 'a list -> 'a list -> 'a list} telle que l'appel de {\tt remplace x lx l} renvoie une liste dans laquelle on a remplac\'e les occurrences de {\tt x} dans {\tt l} par les \'el\'ements de {\tt lx}. Par exemple, l'appel {\tt remplace 0 [2;4] [0; 1; 0; 0; 1]} renvoie {\tt [2; 4; 1; 2; 4; 2; 4; 1]}. \item V\'erifier pour quelques valeurs de $n$ que si on remplace dans $l_n$ tous les $\tt0$ par {\tt[0;1]} et $\tt1$ par $\tt[0]$ alors on trouve $l_{n+1}$. S'il vous reste du temps~: d\'emontrer cette propri\'et\'e. \end{enumerate} \suspend{enumerate} \section*{Le codage b\^aton} Dans cet exercice, on codera les entiers par des listes de \texttt{() : unit}, leur nombre indiquant la valeur de l'entier. Ainsi \texttt{[();();();();();();();()]} code l'entier 8. En termes plus imag\'es, on repr\'esente un entier par une liste de petits b\^atons (ou de {\tt()}) comme en maternelle quand on apprend \`a compter. Pour effectuer des tests, on d\'efinira~: \begin{verbatim} let huit = [(); (); (); (); (); (); (); ()];; let trois = [(); (); ()];; \end{verbatim} \resume{enumerate} \item \'Ecrire une fonction \texttt{successeur : unit list -> unit list}. \item En d\'eduire une fonction \texttt{entiers\_vers\_batons : int -> unit list}. \'Ecrire aussi une fonction {\tt batons\_vers\_entiers : unit list -> int}. Tests~: \begin{verbatim} # entiers_vers_batons 4;; - : unit list = [(); (); (); ()] # batons_vers_entiers trois;; - : int = 3 \end{verbatim} \item Dans toutes les questions suivantes on demande de coder les op\'erations suivantes {\it sans repasser par des valeurs de type} {\tt int}~: les ``entiers'' seront uniquement cod\'es par le type \texttt{unit list}. \begin{enumerate} \item On cherche \`a \'ecrire une fonction {\tt inferieur : unit list -> unit list -> bool} qui renvoie {\tt true} si et seulement si on a un inf\'erieur strict. Pour cela le savant Sunisoc propose de filtrer sur le {\it couple} {\tt (l1,l2)} form\'e par les deux param\`etres. Il vous laisse ce code \`a trous, \`a vous de compl\'eter ce qu'il y a derri\`ere les fl\`eches~: \begin{verbatim} let rec inferieur l1 l2 = match l1, l2 with | _, [] -> | [], _ -> | ()::q1, ()::q2 -> ;; \end{verbatim} Tests~: \begin{verbatim} # inferieur huit trois;; - : bool = false # inferieur trois huit;; - : bool = true # inferieur huit huit;; - : bool = false \end{verbatim} \item \'Ecrire une fonction \texttt{somme : unit list -> unit list -> unit list}. Tests~: \begin{verbatim} # somme huit trois;; - : unit list = [(); (); (); (); (); (); (); (); (); (); ()] \end{verbatim} \item \'Ecrire une fonction {\tt difference : unit list -> unit list -> unit list}. Au cas o\`u la diff\'erence correspondrait \`a un entier n\'egatif, votre fonction renverra la liste vide. Tests~: \begin{verbatim} # difference huit trois;; - : unit list = [(); (); (); (); ()] # difference trois huit;; - : unit list = [] \end{verbatim} \item \'Ecrire une fonction \texttt{produit : unit list -> unit list -> unit list}. Tests (attention~: la conversion en entiers ne se fait qu'apr\`es avoir calcul\'e le produit, pour rendre le r\'esultat plus lisible)~: \begin{verbatim} # batons_vers_entiers (produit huit trois);; - : int = 24 \end{verbatim} \item \'Ecrire une fonction {\tt division : unit list -> unit list -> (unit list) * (unit list)} qui renvoie sous forme d'un couple le quotient et le reste de la division euclidienne. Tests~: \begin{verbatim} # division huit trois;; - : unit list * unit list = ([(); ()], [(); ()]) # division trois huit;; - : unit list * unit list = ([], [(); (); ()]) # division trois trois;; - : unit list * unit list = ([()], []) \end{verbatim} \item \'Ecrire une fonction {\tt baseb : unit list -> unit list -> unit list list} telle que l'appel de {\tt baseb l b} renvoie la liste des chiffres (poids faible en t\^ete) de {\tt l} et base {\tt b}. Test (en utilisant $25=2\times3^2+2\times3+1=\overline{221}^3$)~: \begin{verbatim} # baseb (entiers_vers_batons 25) trois;; - : unit list list = [[()]; [(); ()]; [(); ()]] \end{verbatim} \end{enumerate} \suspend{enumerate} \section*{Avanc\'e} \resume{enumerate} \item On veut \'ecrire une fonction \texttt{fold\_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a} telle que pour\break \texttt{f : 'a -> 'b -> 'a}, on ait \texttt{fold\_left f a [x1;x2;...;xn]} retourne \texttt{f (...(f (f a x1) x2)...) xn}. \begin{enumerate} \item Quel est son cas de base~? \item \'Ecrire la fonction \texttt{fold\_left}. \end{enumerate} \item En d\'eduire des fonctions (tr\`es simples, avec seulement un appel de {\tt fold\_left}) calculant~: \begin{enumerate} \item la somme des termes d'une liste d'entiers \item le produit des termes d'une liste d'entiers \item le maximum des termes d'une liste d'entiers \end{enumerate} \item \'Ecrire une fonction \texttt{flatten} de type \texttt{'a list list -> 'a list} telle que \texttt{flatten l} retourne la concat\'ena\-tion des \'el\'ements de \texttt{l}. Par exemple, \texttt{flatten [[1;2];[3];[];[4;5]] = [1;2;3;4;5]}. \item \'Ecrire \`a l'aide de \texttt{fold\_left} une fonction {\tt reverse : 'a list -> 'a list} qui renverse une liste. \item \'Ecrire une fonction \texttt{fold\_left2 : ('a -> 'b -> 'c -> 'a) -> 'a -> 'b list -> 'c list -> 'a} telle que \texttt{fold\_left2 g a [x1;x2;...;xn] [y1;y2;...;yn]} retourne \texttt{g (g ... (g (g a x1 y1) x2 y2) ...) xn yn} o\`u les \texttt{xi} sont de type \texttt{'b}, les \texttt{yi} sont de type \texttt{'c} et \texttt{g : 'a -> 'b -> 'c -> 'a}. En d\'eduire une fonction qui v\'erifie qu'une liste est un palindrome. On pourra utiliser \texttt{reverse}. \suspend{enumerate} \section*{P\'al Erd\H{o}s} P\'al Erd\H{o}s mort en 1996 \`a l'\^age de 83 ans est tr\`es connu pour ses probl\`emes sur la th\'eorie des nombres dont voici l'un d'eux~: \begin{quote} Quelle est la taille maximale d'un sous-ensemble de nombres entiers $a_1,\cdots a_k$ choisis parmi les entiers $1,2,\cdots,n$ tels que $a_i + a_j$ ne soit jamais un carr\'e parfait ($i$ et $j$ quelconques y compris $i=j$)~? Par exemple si $n=7$ alors $\{1,4,6,7\}$ est l'un des sous-ensembles recherch\'es. \end{quote} \resume{enumerate} \item Donner la r\'eponse pour $n = 20$. Combien il y a-t-il de solutions~? \end{enumerate} \end{document}