% This  work is licensed under  the Creative Commons  GNU General Public
% License License.  To view a copy of this license, visit
%  http://creativecommons.org/licenses/GPL/2.0/   or  send  a   letter  to
%  Creative  Commons,  171  Second   Street,  Suite  300,  San  Francisco,
%  California, 94105, USA. 
% Copyleft Guillaume CONNAN http://tehessin.tuxfamily.org

\documentclass[11pt,a4paper,twoside,svgnames]{report}
\usepackage{etex}
\usepackage[height=250mm,width=180mm]{geometry}
\usepackage[french,vlined,boxed]{algorithm2e}
\usepackage[fourier,biblio]{preambule}
\usepackage{cclicenses}
\usepackage{xlop}
\usepackage{keystroke}
%\usepackage[colorlinks=true,citecolor=red,dvips]{hyperref}

%\usepackage[Lenny]{fncychap}








 % \DeclareMathSymbol{\mthdotlessiup}{\mathalpha}{operators}{16}%
\definecolor{0.1white}{rgb}{.1,.1,.1}

%\usepackage[upright]{fourier}
%\usepackage[upright]{kpfonts}
%\usepackage[scaled=0.85]{luximono}
%\usepackage{lmodern}
% \usepackage[boldsans]{ccfonts}
% \usepackage{beton,euler,luximono}

\graphicspath{{/home/moi/Lycee/2nde/2009_10/}{/home/moi/Photos/Maths/}{/home/moi/Figures/FigSTI/}{/home/moi/Figures/FigSeconde/}{/home/moi/Figures/figuresTS/}{/home/moi/Lycee/TDmaple/2007_8/}{/home/moi/IREM/IREM10_06_09/}{/home/moi/Lycee/TS/}{/home/moi/Lycee/Informatique/XCAS/2008_9/}}

\entete{\leftmark}{\rightmark}{\href{http://tehessin.tuxfamily.org/fr.html}{Licence
    Creative Commons}\byncsa}%g,d,b

% \sectionfont{\LARGE\color{0.2white}}
% \renewcommand\thesection{\Roman{section} }
% \subsubsectionfont{\large\color{0.6white}}
% \subsectionfont{\Large\color{0.4white}}
% \renewcommand\thesubsubsection{\roman{subsubsection}. }



\setlength{\headheight}{15.2pt}
\usepackage{cclicence}
\setcounter{secnumdepth}{3}
\setcounter{tocdepth}{1}

\title{\fontfamily{ugq}\selectfont FAIRE DES MATHÉMATIQUES AU LYCÉE EN PROGRAMMANT
\\ {\itshape Un catalogue libre de 400 programmes\\  avec XCAS,  CAML, SAGE et PYTHON}
 \\
\href{http://tehessin.tuxfamily.org/fr}{ \fontfamily{ugq}\selectfont
  Licence Creative Commons}
\CcGroupByNcSa{1.25}{1.25ex}
%\CcNote{\CcLongnameByNcSa}		
}

\author{\fontfamily{ugq}\selectfont    Guillaume    \textsc{Connan}    -
  \textsc{IREM} de Nantes\\\fontfamily{ugq}\selectfont Courriel~:~\href{mailto:gconnan@free.fr}{\fontfamily{ugq}\selectfont gconnan - at - free.fr}}

\date{\fontfamily{ugq}\selectfont VERSION PROVISOIRE DU \today }

%\thanks{\CcNote{\CcLongnameByNcSa}}

% \thanks{Merci  à  René  \textsc{Thoraval}  d'avoir  eu  la  patience  de
%   m'initier   au    merveilleux   langage   CAML,    si   puissant,   si
%   intelligent....si mathématique}

% \newcommand\xc{\lstset{numbers=none,language=XCAS,xleftmargin=10pt,%
% keywordstyle=\color{black}\bfseries,
% ,basicstyle=\ttfamily\color{0.4white},commentstyle=\normalfont\small\itshape,breaklines=true,backgroundcolor=\color{ciel},frame=trBL,framerule=1pt,framesep=4pt,rulesep=1pt,extendedchars=true}
% }



% \newcommand\xc{\lstset{numbers=none,language=XCAS,xleftmargin=10pt,%
% keywordstyle=\bfseries\color{black},basicstyle=\ttfamily\color{0.1white},commentstyle=\normalfont\scriptstyle\slshape,breaklines=true,frame=trBL,framerule=1pt,framesep=4pt,rulesep=1pt,backgroundcolor=\color{ciel}}
% }

\lstset{numberbychapter=false}


\newcommand\xc{\lstset{numbers=none,language=XCAS,xleftmargin=10pt,%
keywordstyle =\color{bleu}\bfseries,basicstyle=\ttfamily\color{0.1white},commentstyle=\normalfont\scriptsize\slshape,breaklines=true,backgroundcolor=\color{green!20},frame=trBL,framerule=1pt,framesep=4pt,rulesep=1pt,showstringspaces=false,stringstyle=\slshape,captionpos=b}
}

\newcommand\caml{\lstset{numbers=none,language=Caml,xleftmargin=10pt,%
keywordstyle =\color{rouge!70!black}\bfseries,basicstyle=\ttfamily\color{0.1white},commentstyle=\normalfont\scriptsize\slshape,breaklines=true,backgroundcolor=\color{orange!20},frame=trBL,framerule=1pt,framesep=4pt,rulesep=1pt,showstringspaces=false,stringstyle=\slshape,captionpos=b}
}

\newcommand\sage{\lstset{numbers=none,language=sage,xleftmargin=10pt,%
keywordstyle =\color{blue!70!black}\bfseries,basicstyle=\ttfamily\color{0.1white},commentstyle=\normalfont\scriptsize\slshape,breaklines=true,backgroundcolor=\color{blue!20},frame=trBL,framerule=1pt,framesep=4pt,rulesep=1pt,showstringspaces=false,stringstyle=\slshape,captionpos=b,emph={sage},emphstyle=\color{blue!60!black}\bfseries\large,mathescape=true% ,delim=**[l][\ttfamily\color{0.1white}]sage:
,moredelim=[il][\slshape\color{black!30}]§}
}


\renewcommand\lstlistingname{Programme}
\renewcommand\lstlistlistingname{Liste des programmes}
% \newcommand\caml{\lstset{language=Caml,backgroundcolor=\color{creme},numbers=none,xleftmargin=10pt,%
% keywordstyle=\bfseries\color{black},basicstyle=\ttfamily\color{0.1white},commentstyle=normalfont\scriptstyle\color\slshape\color{0.1white},breaklines=true,frame=trBL,framerule=1pt,framesep=4pt,rulesep=1pt}
% }

%\lstMakeShortInline+

% \newcommand\caml{\lstset{numbers=none,language=Caml,xleftmargin=10pt,%
% keywordstyle=\color{black}\bfseries
% ,basicstyle=\ttfamily\color{0.4white},commentstyle=\normalfont\small\itshape,breaklines=true,frame=trBL,framerule=1pt,framesep=4pt,rulesep=1pt,backgroundcolor=\color{creme},extendedchars=true}
% }

\newcommand{\reponse}[1]{
\begin{center}
\textcolor{blue}{\texttt{#1}}
\end{center}
}


\newcommand{\MarqueCommandeGiac}[1]{%
    \color{gray}$>\ $}
\newcommand{\MarqueLaTeXGiac}{%
    \color{blue}}
\newcommand{\InscriptionFigureGiac}[1]{%
    \begin{center}
	\includegraphics[width=7.5cm]{#1}
    \end{center}}



\usepackage{wallpaper}

%\lstMakeShortInline+

\begin{document}


%\input /home/moi/texmf/macros/plain/contrib/font-change/tex/macros/font_bera_concrete





\setlength{\parindent}{0pt}
%\thispagestyle{empty}

\incmargin{1em}
\dontprintsemicolon
%\SetCommentSty{\sffamily}}%\sffamily\color{0.4white}}
\ThisCenterWallPaper{1.33}{fractalenewton2}
% \begin{center}
%   \includegraphics[width=1.3\linewidth]{fractalenewton}
% \end{center}




\maketitle
\pagestyle{plain}

\tableofcontents

\vfill

\eject

\xc


\pagestyle{fancy}

\chapter{Présentation du stage PAF de janvier/mars 2010}



Un aspect qui nous  intéresse particulièrement dans la programmation est
que la  réalisation d'un programme informatique  de façon traditionnelle
passe par l'écriture de son  code source. Il s'agit bien d'une véritable
activité de  rédaction et cela  nous semble important de  convaincre les
élèves  que là  encore, l'obtention  d'un résultat  désiré passe  par la
phase, peut-être laborieuse, d'écriture.


Il  est bien  question d'analyser  un problème  et de  décrire  un moyen
d'obtenir  une  solution, mais  le  \og{}robot\fg{}  -- interpréteur  ou
compilateur --  reste imperturbablement extrêmement  strict, et n'infère
en  rien  les  détails  pensés  mais  non  explicités  par  l'auteur  du
programme.   La  rigueur   est  ici   strictement  nécessaire   à  cette
activité.  Convoquer  la  rigueur  par  le biais  de  la  programmation,
activité pour l'instant inhabituelle  chez les collégiens ou lycéens, ne
peut qu'être  un bénéfice à  plus ou moins  court terme pour  les autres
apprentissages.


Certes,  les  environnements  modernes  de  développement  logiciel  (le
\og{}Rapid    Application   Development\fg{}   dans    la   terminologie
anglo-saxonne)  foisonnent de  dispositifs d'assistance  au programmeur,
dans les outils  employés mais aussi et surtout  depuis quelques années,
la  programmation modulaire  et la  conception objet  qui  permettent de
segmenter  de  gigantesques  projets  pour une  réalisation  commune  et
partagée par  des centaines d'individus.  Il n'en demeure pas  moins que
les  phases d'écriture  perdurent, qui  plus  est avec  des langages  de
programmation qui sont aujourd'hui au nombre de plus de 2000 en ce début
de troisième  millénaire, pour  une activité qui  a réellement  pris son
essor un peu avant la Seconde guerre mondiale.


La programmation  utilise l'algorithmique  pour être efficace  mais doit
fournir  en  plus des  programmes  lisibles,  facilement utilisables  et
modifiables  par d'autres utilisateurs.  Depuis \emph{FORTRAN}  en 1956,
langage  qui  laissait l'utilisateur  très  proche  de  la machine,  les
langages  évoluent  vers  un  plus \og{}haut  niveau\fg{},  c'est-à-dire
qu'ils  s'éloignent du  langage machine  pour se  rapprocher  du langage
humain et gagnent ainsi en simplicité de lecture et d'utilisation.


Par exemple, voici deux  programmes calculant la factorielle d'un entier
naturel $n$:

\begin{itemize}

\item en langage \emph{C}:

\medskip
\xc
\begin{lstlisting}
long Factorielle(int n) {
	unsigned i;
	long resultat = 1;
	if (n==0)
		return 1;
	if (n>0) {
		for (i=2; i<n+1; ++i)
			resultat *=i;
		return resultat;
	}
	return -1;
} 
\end{lstlisting}

\item en langage \emph{CAML}:

\medskip
\caml
\begin{lstlisting}
let rec factorielle = function
   | 0 -> 1
   | n -> n*factorielle(n-1);;
\end{lstlisting}

\end{itemize}


Quel est le langage de plus haut niveau?...



En mathématiques,  les langages de  haut niveau basés sur  un formalisme
logique nous  intéressent au plus haut  point car ils  ont cette rigueur
qui sied  à notre discipline et  sont en même temps  moins parasités par
les détails technologiques des langages  trop près de la machine ou trop
lâches logiquement parlant.


Cependant, les  langages comme le \emph{C} sont  largement employés (car
ils sont liés  aux systèmes \emph{UNIX} pour le  \emph{C}) tout comme la
programmation  objet  si  prisée  pour  la  réalisation  des  interfaces
homme/machine des grands projets industriels.


C'est  pourquoi nous  avons  choisi  trois langages  qui  ont fait  leur
preuve:

\begin{itemize}

\item le langage utilisé par \emph{XCAS} car il est proche du \emph{C++}
  et qu'en même
temps \emph{XCAS} est un outil  pour faire des mathématiques au lycée et
possède de  nombreuses fonctionnalités intéressantes en  calul formel et
géométrie;


\item  \emph{Python}  qui est  orienté  objet  et  permet également  une
  programmation
impérative et  récursive. \emph{Python}  présente une syntaxe  claire et
reste particulièrement abordable pour les débutants, tout en offrant des
constructions de haut niveau;


\item \emph{(O)CAML} qui est essentiellement fonctionnel (et donc très
mathématique)  mais  permet également  une  programmation impérative  et
orientée objet.

\end{itemize}


Les deux  derniers langages sont  largement répandus et  sont développés
par des  équipes à la pointe  de la recherche  informatique:~ils ont été
pensés, améliorés depuis des années  et évitent les écueils de certaines
interfaces prétenduement  simples d'utilisation mais  qui peuvent cacher
de nombreux vices et ne déboucheront sur aucune utilisation en dehors du
lycée.


Comme nous continuons à travailler les mathématiques \og{}avec un papier
et un crayon\fg{} ou bien \og{} calculer à la main\fg{}, nous préférons un
  contexte de programmation le  plus sobre possible, dépouillé de toutes
  les choses fortement inutiles et qui nuisent à la concentration sur le
  sujet de réflexion. Un éditeur de  texte simple (et non un logiciel de
  traitement  de  texte)  fait  amplement  l'affaire,  accompagné  d'une
  console  (\emph{*N*X}  de  préférence)  pour  l'interprétation  ou  la
  compilation, puis l'exécution d'un programme. Il s'agit vraiment de se
  concentrer  sur l'essentiel,  et nous  voyons les  élèves  accepter ce
  travail, dans la  mesure où la récompense est  immédiate: le programme
  fonctionne ou ne  fonctionne pas, ou bien effectue  autre chose que ce
  que  son auteur prévoyait.  Il y  a ici  une question  de satisfaction
  intellectuelle, sans aucune  autre récompense qu'un apprentissage (!),
  ce qui reste une question centrale de l'école.

\bigskip

\begin{flushright}
\begin{tabular}{l}
Le 20 janvier 2010,\\
\quad\\
Pascal CHAUVIN\\
Guillaume CONNAN
\end{tabular}
\end{flushright}



\chapter{Algorithme breton}

Ce  n'est  pas  très  mathématique  mais c'est  un  algorithme  et  pour
affronter tous ceux qui nous attendent, il va nous falloir des forces....

\begin{algorithm}[H]
\caption{algorithme breton pur beurre}
\Entree{masse m totale}\;
\Ini{\;
beurre\aff m/4\;
sucre\aff m/4\;
farine\aff m/4\;
\oe uf \aff m/4\;
}\;
\Deb{
 Couper le beurre en petits moreaux et le mettre à fondre doucement au bain-marie de préférence.
Dès qu'il est fondu arrêter. Laisser refroidir mais attention : le beurre doit être encore liquide ! Il ne doit pas redevenir solide\;

 Mettre le four à préchauffer à 160° (th 5)\;

 Mettre les oeufs entiers avec le sucre dans un saladier. Battre longuement le mélange pour qu'il blanchisse et devienne bien mousseux\;

 Y ajouter le beurre fondu ET FROID\;

 Rajouter progressivement à l'appareil la farine en l'incoporant bien. Cela doit donner une pâte élastique et un peu épaisse\;

 Verser la préparation dans un moule à manqué ou à cake bien beurré\;

 Laisser  cuire  environ  une   heure.  Il  faut  surveiller  le  gâteau
 régulièrement.\; 




\Si{ il  semble brunir  trop vite}{ il  faut baisser  un peu le  four et
  mettre une feuille d'aluminium sur le dessus.}


 Il  faut que  le  dessus du  gâteau  soit blond  foncé,  mais pas  trop
 coloré.\;


\Si{lorsqu'une pique plantée en son milieu ressort sèche}{le gâteau est cuit }

 } 
\end{algorithm}






\chapter{XCAS et CAML}


\section{CAML pour l'impatient}
\caml

\subsection{Installation et utilisation}


Pour   tous   les   O.S.   il   existe   des   distributions   de   CAML
\emph{clé-en-main}           sur           le          page           de
\href{http://pagesperso-orange.fr/jean.mouric/}{Jean Mouric}.

Pour   les    utilisateurs   de   Emacs,   vous    pouvez   charger   le
\href{http://www.emacswiki.org/emacs/TuaregMode}{mode tuareg}.



CAML sous Emacs avec le mode tuareg~:

\begin{figure}
\begin{center}
  \includegraphics[width=\linewidth]{caml1}
\end{center}
\end{figure}


CAML sous JavaCaml~:

\begin{figure}
\begin{center}
  \includegraphics[width=\linewidth]{caml2}
\end{center}
\end{figure}


\subsection{Quelques ressources électroniques}


\href{http://caml.inria.fr/pub/distrib/books/llc.pdf}{Une     passionnante
  introduction à OCAML par un de ses papas...}


\href{http://caml.inria.fr/pub/distrib/books/manuel-cl.pdf}{Le     manuel
  de référence de CAML par Xavier \textsc{Leroy} et Pierre \textsc{Weis}}

\href{http://fr.wikibooks.org/wiki/Objective_Caml}{Une introduction à CAML}

\href{http://www.pps.jussieu.fr/Livres/ora/DA-OCAML/}{Ouvrage de référence CAML}


\href{http://caml.inria.fr/resources/index.fr.html}{Ressources CAML}

\href{http://www.ocaml-tutorial.org/tutoriel_objective_caml}{Un
tutoriel en français}


Des ouvrages en papier sont référencés dans la bibliographie à la fin de
ce document.

\subsection{Les nombres}

Nous utiliserons  dans tout le document  la version basique  de CAML (en
fait  OCAML  (c'est-à-dire  CAML  avec  des modules  pour  faire  de  la
programmation orientée  objet) ou CAML  Light (c'est la version  de base
que  nous utiliserons))  sans  charger de  modules complémentaires  sauf
éventuellement  pour créer  des graphiques  ou travailler  sur certaines
listes.

Nous  travaillerons  en   mode  \emph{toplevel}  c'est-à-dire  que  nous
compilerons automatiquement de manière  interactive. Pour se repérer, ce
que nous  taperons sera  précédé d'un  \# et ce  que renverra  CAML sera
précédé le plus souvent d'un -.

On peut travailler avec des entiers~:

\begin{lstlisting}[caption={}]
#  1+2;;
- : int = 3
\end{lstlisting}


Vous remarquerez  que CAML répond que  le résultat de 1+2  est un entier
(\verb+int+) égal  à 3. En  effet, CAML est adepte  de l'\emph{inférence
de type}, c'est-à-dire qu'il devine  quel type de variable vous utilisez
selon ce que vous avez tapé. Nous en reparlerons plus bas.


Les  priorités des opérations  sont respectées.  En cas  d'ambiguïté, un
parenthésage implicite à gauche est adopté~:

\begin{lstlisting}[caption={}]
# 1+2*3;;
- : int = 7
# 1-2+3;;
- : int = 2
# 1-(2+3);;
- : int = -4
# (1+2)*3;;
- : int = 9
\end{lstlisting}



La division renvoie le quotient entier bien sûr~:

\begin{lstlisting}[caption={}]
# 11/3;;
- : int = 3
# 11/3*2;;
- : int = 6
# 11/(3*2);;
- : int = 1
\end{lstlisting}

On peut utiliser \verb+mod+ pour le reste entier~:

\begin{lstlisting}[caption={}]
# 7 mod 2;;
- : int = 1
# 7/2;;
- : int = 3
# 7-7/2*2;;
- : int = 1
\end{lstlisting}

Enfin, les entiers sont de base compris entre $-2^{30}$ et $2^{30}-1$.


Les nombres non entiers sont de type \emph{float}. Ils sont représentés
en interne par deux entiers~:~une \emph{mantisse} $m$ et un exposant $n$
tel  que  le nombre  flottant  soit  $m\times  10^{n}$. En  externe,  il
apparaît sous forme décimale, le séparateur étant le point.


\begin{lstlisting}[caption={}]
# 1.;;
- : float = 1.
\end{lstlisting}


Attention alors aux opérations~:

\begin{lstlisting}[caption={}]
# 3.14 + 2;;
Characters 0-4:
  3.14 + 2;;
  ^^^^
Error: This expression has type float but an expression was expected of type int
\end{lstlisting}


Cela indique que  vous avez utilisé l'addition des  entiers pour ajouter
un  entier à un  flottant. CAML  en effet  n'effectue pas  de conversion
implicite et  demande que celle-ci soit explicite.  Cela peut apparaître
comme contraignant mais  permet l'inférence de type qui  évite nombre de
\og bugs\fg{}.

Les opérations  arithmétiques sur les entiers doivent  donc être suivies
d'un point~:

\begin{lstlisting}[caption={}]
# 1. +. 2.1 ;;
- : float = 3.1
# 1.2 +. 2.1 ;;
- : float = 3.3
# 1./.2.;;
- : float = 0.5
# 1.5e-5 *. 100. ;;
- : float = 0.0015
# sqrt(2.);;
- : float = 1.41421356237309515
# 3.**2.;;
- : float = 9.
# log(2.);;
- : float = 0.693147180559945286
# exp(1.);;
- : float = 2.71828182845904509
# cos(0.);;
- : float = 1.
# cos(2.*.atan(1.));;
- : float = 6.12303176911188629e-17
# sin(2.*.atan(1.));;
- : float = 1.
\end{lstlisting}


Il existe des moyens de convertir un entier en flottant~:

\begin{lstlisting}[caption={}]
# float(1) +. 3.1;;
- : float = 4.1
# float 1 +. 3.1;;
- : float = 4.1
\end{lstlisting}



et inversement~:

\begin{lstlisting}[caption={}]
# int_of_float(sqrt(2.));;
- : int = 1
\end{lstlisting}

Il ne faut pas confondre \verb+int_of_float+ et \verb+floor+


\begin{lstlisting}[caption={}]
# floor(2.1);;
- : float = 2.
# int_of_float(2.1);;
- : int = 2
\end{lstlisting}


\subsection{Les autres types de base}


\subsubsection{Les booléens}


Ils sont bien sûr au  nombre de deux~:~\verb+true+ et \verb+false+. Nous
en aurons besoin pour les  tests. Les fonctions de comparaison renvoient
un booléen. On  peut combiner des booléens avec  \verb+not+, \verb+&+ et
\verb+or+~:


\begin{lstlisting}[caption={}]
# 3>2;;
- : bool = true
# 3=2;;
- : bool = false
# (3>2) & (3=2);;
- : bool = false
# (3>2) or (3=2);;
- : bool = true
# (3>2) & not(3=2);;
- : bool = true
# (3>2) & not(3=2) & (0<1 or 1>0);;
- : bool = true
\end{lstlisting}





\subsubsection{Les chaînes de caractères}

En anglais~:~\emph{string}. On les entoure de guillemets vb+"+ et on les
concatène avec \verb+^+~:

\begin{lstlisting}[caption={}]
# "Tralala "^"pouet pouet";;
- : string = "Tralala pouet pouet"
\end{lstlisting}


\subsubsection{Les caractères}

En    CAML~:~\emph{char}.   On   les    utilisera   surtout    pour   la
cryptographie.  Il sont entrés entre accents aigus~:

\begin{lstlisting}[caption={}]
# 'a';;
- : char = 'a'
\end{lstlisting}



\subsection{Les définitions}

C'est  comme  en  maths...mais  en  anglais~! Donc  \emph{Soit}  se  dit
\emph{Let}~:

\begin{lstlisting}[caption={}]
# let x=3*2;;
val x : int = 6
# 2+x;;
- : int = 8
# let pi=acos(-1.);;
val pi : float = 3.14159265358979312
# sin(pi/.2.);;
- : float = 1.
\end{lstlisting}

Le nom des identificateurs doit commencer par une lettre minuscule.



On  peut définir  \emph{localement}  une variable,  c'est-à-dire que  sa
portée ne dépassera pas l'expression où elle a été définie~:

\begin{lstlisting}[caption={}]
# let x=99 in x+1;;
- : int = 100
# x;;
- : int = 6
# let a=3 and b=2 in a*a+b*b;;
- : int = 13
\end{lstlisting}




\subsection{Fonctions}

On peut créer des fonctions avec \verb+function+~:

\begin{lstlisting}[caption={}]
# let delta = function
  | (a,b,c) -> b*b-4*a*c;;
  val delta : int * int * int -> int = <fun>

# delta(1,1,1);;
- : int = -3
\end{lstlisting}


Notez le \verb+val delta  : int * int * int ->  int = <fun>+ qui indique
que la  fonction construite...est une fonction (\verb+<fun>+)  qui va de
$\bbz^3$ dans $\bbz$.


On peut de manière plus standard (informatiquement parlant~!) définir la
fonction par son expression générale~:

\begin{lstlisting}[caption={}]
# let discriminant(a,b,c)=b*b-4*a*c;;
val discriminant : int * int * int -> int = <fun>
# discriminant(1,1,1);;
- : int = -3
\end{lstlisting}


On peut disjoindre des cas~:

\begin{lstlisting}[caption={}]
# let sina = function
  | 0. -> 1.
  | x -> sin(x)/.x;;
    val sina : float -> float = <fun>

# sina(0.);;
- : float = 1.

# sina(0.1);;
- : float = 0.998334166468281548
\end{lstlisting}


On peut travailler avec autre chose que des nombres~:

\begin{lstlisting}[caption={}]
# let mystere = function
  | (true,true) -> true
  | _           -> false;;
    val mystere : bool * bool -> bool = <fun>
# mystere(3>2,0=1-1);;
- : bool = true
# mystere(3>2,0>1);;
- : bool = false
\end{lstlisting}


Le tiret \verb+_+ indique \og dans tous les autres cas\fg{}.

On peut  aussi créer des fonctions  \emph{polymorphes}, c'est-à-dire qui
ne travaillent pas sur des types de variables particuliers.

\begin{lstlisting}[caption={}]
# let composee(f,g) = function
  | x ->f(g(x));; 
  val composee : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b = <fun>
\end{lstlisting}

Ici, $f$ est  toute fonction transformant un type de  variable $a$ en un
type de variable $b$ et $g$ une fonction transformant un type de  variable $c$ en un
type de variable $a$. La fonction composée transforme bien  un type de  variable $c$ en un
type de variable $b$.

Si nous reprenons la fonction définie précédemment~:

\begin{lstlisting}[caption={}]
# let carre = function
  | x -> x*.x;;
  val carre : float -> float = <fun>

# composee(sina,carre);;
- : float -> float = <fun>

# composee(sina,carre)(3.);;
- : float = 0.04579094280463962
\end{lstlisting}



\subsection{If...then...else}

On  peut   utiliser  une  structure  conditionnelle   pour  définir  une
fonction~:


\begin{lstlisting}[caption={}]
# let val_abs = function
  | x-> if x>=0 then x else -x;;
  val val_abs : int -> int = <fun>
\end{lstlisting}

ou bien 

\begin{lstlisting}[caption={}]
# let valeur_abs(x)=
     if x>=0 then x
     else -x;; 
    val valeur_abs : int -> int = <fun>
\end{lstlisting}

\subsection{Fonctions récursives}

C'est une fonction  construite à partir d'elle-même. On  utilise la même
syntaxe que pour  une fonction simple mais on  fait suivre le \verb+let+
d'un \verb+rec+~:

\begin{lstlisting}[caption={}]
# let rec factorielle = function
  | 0 -> 1
  | n -> n*factorielle(n-1);;
    val factorielle : int -> int = <fun>

# let rec fact(n)=
      if n=0 then 1
      else n*fact(n);; 
    val fact : int -> int = <fun>
\end{lstlisting}


Pour  plus de  détails sur  les fonctions  récursives, voir  le chapitre~\vref{recu}.


\section{XCAS pour l'impatient}

\subsection{Installation et utilisation}
Vous    récupérez    la    version    pour    votre    O.S.    sur    le
\href{http://www-fourier.ujf-grenoble.fr/~parisse/irem.html}{Site XCAS}.

Vous suivez les instructions et voilà...


\begin{figure}
\begin{center}
  \includegraphics{xcas1}
\end{center}
\end{figure}

Il y a  beaucoup à dire sur XCAS mais  nous nous contenterons d'explorer
les outils de programmation.

Nous  allons  donc  ouvrir   une  fenêtre  de  programmation  en  tapant
\keystroke{Alt} + \keystroke{P}.

Une fenêtre de programmation apparaît~:


\begin{figure}
\begin{center}
  \includegraphics{xcas2}
\end{center}
\end{figure}

Il ne reste plus qu'à programmer...

\xc


\subsection{Les procédures}

XCAS est écrit en C++ et  a donc une syntaxe proche de ce langage...mais
en bien  plus simple. Cependant,  comme le C++,  l'outil de base  est la
procédure qui \emph{ressemble} aux fonctions de CAML.

Par exemple, nous voudrions créer  une procédure qui prend trois nombres
$a$,  $b$  et $c$  en  argument  et  renvoie $b^2-4ac$.  Appelons-la  au
hasard...\verb+Delta+~:



\begin{figure}
\begin{center}
  \includegraphics{xcas3}
\end{center}
\end{figure}

Par la suite, nous représenterons ce script par~:

\begin{lstlisting}[caption={}]
Delta(a,b,c):={
b^2-4*a*c
}:;
\end{lstlisting}

Il suffit ensuite de cliquer sur OK ou de taper sur \keystroke{F9}



\begin{figure}
\begin{center}
  \includegraphics{xcas4}
\end{center}
\end{figure}




Pour évaluer  cette procédure en  un certain triplet, nous  entrons dans
une cellule de calcul~:

\begin{lstlisting}[caption={}]
Delta(1,1,1)
\end{lstlisting}


ce qui apparaît sous la forme~:


\begin{figure}
\begin{center}
  \includegraphics{xcas5}
\end{center}
\end{figure}


\subsection{Tests}


Avec XCAS, on peut programmer en français ou en anglais.

\begin{lstlisting}[caption={}]
val_abs(x):={
si x>0 alors x sinon -x fsi;
}:;
\end{lstlisting}

ou

\begin{lstlisting}[caption={}]
val_abs(x):={
if(x>0)then{x}else{-x}
}:;
\end{lstlisting}

ou même

\begin{lstlisting}[caption={}]
val_abs(x):={
ifte(x>0,x,-x)
}:;
\end{lstlisting}


\subsection{Boucles}

Le bilinguisme est ici aussi  de rigueur. Calculons par exemple la somme
des premiers entiers~:

\begin{lstlisting}[caption={}]
Somme(n):={
local S,k;
S:=0;
pour k de 1 jusque n faire
  S:=S+k;
fpour;
retourne(S);
}:;
\end{lstlisting}


\begin{figure}
\begin{center}
  \includegraphics{xcas6}
\end{center}
\end{figure}


ou 

\begin{lstlisting}[caption={}]
Somme(n):={
local S,k;
S:=0;
for(k:=1;k<=n;k:=k+1){
   S:=S+k
}
return(S);
}:;
\end{lstlisting}


ou 

\begin{lstlisting}[caption={}]
Somme(n):={
local S,k;
S:=0;
k:=1;
tantque k<=n faire 
   S:=S+k;
   k:=k+1;
ftantque;
retourne(S);
}:;
\end{lstlisting}


ou

\begin{lstlisting}[caption={}]
Somme(n):={
local S,k;
S:=0;
k:=1;
while(k<=n){ 
   S:=S+k;
   k:=k+1;
};
return(S);
}:;
\end{lstlisting}




Pour plus de détails sur la programmation impérative voir le chapitre~\vref{recu}.


\chapter{Dis monsieur, dessine-moi un icosagone..}


Certains  connaissent peut-être  le langage  Logo qui  avait  permis aux
petits  écoliers d'il  y  a une  vingtaine  d'années de  s'initier à  la
programmation.

Voyons par exemple un petit  algorithme permettant de tracer un polygone
fermé régulier quelconque.

\section{Algorithme}



\begin{algorithm}[H]
\caption{polygone}
\Entree{nombre N de côtés et longueur a d'un côté}\;
\Deb{
\Pour{k de 1 jusqu'à N }{
avance de a pas\;
tourne de 360/a degrés\;
}
 } 
\end{algorithm}



\section{Traduction XCAS }


XCAS comprend un module \emph{Tortue} très complet~:


\begin{lstlisting}[caption={Totue LOGO}]
polylogo(N,a):={
local k;
pour k de 1 jusque N faire
avance(a);
tourne_droite(360/N);
fpour;
}:;
\end{lstlisting}




\chapter{Algorithmes récursifs / algorithmes impératifs}\label{recu}


\section{Programmation impérative et affectations}

\subsection{Aspect technique}


La  programmation  impérative est  la  plus  répandue (Fortran,  Pascal,
C,...)  et la  plus proche  de la  machine réelle.  Son principe  est de
modifier   à   chaque   instant   l'état   de   la   mémoire   via   les
affectations.  Historiquement,  son  principe  a  été  initié  par  John
\textsc{Von Neumann} et Alan \textsc{Turing}.

Par exemple, lorsqu'on entre avec XCAS~:



\xc
\begin{lstlisting}
a:=2
\end{lstlisting}

cela  signifie que  la case  mémoire  portant le  petit \og  fanion\fg{}
\texttt{a} contient à cet instant la valeur 2.

On peut changer le contenu de cette case mémoire un peu plus tard~:

\begin{lstlisting}
a:=4
\end{lstlisting}


et cette fois la case \texttt{a} contient la valeur 4.

Le  caractère  chronologique  de  ce  type  de  programmation  est  donc
primordial. Regardons la suite d'instructions suivante~:

\begin{lstlisting}[caption={attention aux affectations}]
a:=1;
b:=2;
a:=a+b; // maintenant a contient 3
b:=a-b; // maintenant b contient 3-2=1
a:=a-b; // maintenant a contient 3-1=2
\end{lstlisting}

Cela permet d'échanger les contenus des cases mémoire\verb+a+ et
\verb+b+.

Si l'on change l'ordre d'une  quelconque des trois dernières lignes, les
valeurs présentes  dans les cases mémoires nommées \verb+a+ et\verb+b+
vont être différentes.

Si l'on regarde les deux dernières lignes, elles affectent apparemment
la même valeur  (\verb+a-b+) à\verb+a+ et à \verb+b+ et pourtant c'est
faux car les variables\verb+a+ et\verb+b+ ne contiennent pas les mêmes valeurs
selon le moment où elles sont appelées.

Il faut donc être extrêmement attentif à la chronologie des instructions
données.  C'est un  exercice intéressant  en  soi mais  pas sans  danger
(c'est d'ailleurs la source de la plupart des \og bugs\fg{} en informatique).

\medskip

Question~:~est-ce que 

\begin{lstlisting}
a:=3;
a:=a+1;
\end{lstlisting}

dit la même chose que 

\begin{lstlisting}
a:=a+1;
a:=3;
\end{lstlisting}


\medskip

La motivation première de ce type de fonctionnement a été pratique~:~les
ordinateurs  étant peu puissants,  le souci  principal du  concepteur de
programme a  longtemps été d'économiser  au maximum la mémoire.  Au lieu
d'accumuler  des   valeurs  dans  différents  endroits   de  la  mémoire
(répartition spatiale), on les stocke  au même endroit mais à différents
moments (répartition  temporelle). C'est le modèle des  machines à états
(machine de \textsc{Turing} et architecture de \textsc{Von Neumann}) qui
impose au programmeur  de connaître à tout instant  l'état de la mémoire
centrale. 


\subsection{Exploitation mathématique possible}

En classe  de mathématique,  cet aspect technique  nous importe  peu. Il
nous   permet   cependant  d'illustrer   dynamiquement   la  notion   de
fonction~:

\begin{lstlisting}[caption={affectation et image par une fonction}]
y:=x^2+1;

x:=1;   y;   // ici y=2
x:=-5;  y;   // ici y=26
x:=1/2; y;   // ici y=5/4
\end{lstlisting}

La fonction $f~:~x\mapsto x^2+1$ dépend de la variable $x$. On affecte une certaine
valeur à  la variable ce  qui détermine la  valeur de son image.  Il est
toutefois  à noter qu'en  fait on  a travaillé  ici sur  des expressions
numériques et non pas des fonctions.


On peut enchaîner des affectations~:

\begin{lstlisting}[caption={affectation et composition de fonctions}]
y:=x^2+1;
z:=y+3;

x:=1;   y; z;  /* ici y:=2 et z=5 */
x:=-5   y; z;  // ici y=26  et z=29;
x:=1/2; y; z;  // ici y=5/4 et z=17/4;
\end{lstlisting}


et illustrer ainsi la composition de fonctions.


\medskip


Avec un peu de mauvaise foi  (car le cas est simple et artificiel) mais pas tant que
ça puisque  de tels problèmes  sont source de  milliers de bugs  sur des
milliers de  programmes plus compliqués, nous allons  mettre en évidence
un problème majeur de ce genre de programmation quand on n'est pas assez
attentif.

On créé à un certain moment  une variable\verb+a+ à laquelle on affecte
une valeur~:
\begin{lstlisting}
a:=2;
\end{lstlisting}

On   introduit  plus  tard   une  procédure   (une  sorte   de  fonction
informatique des  langages impératifs) qu'on  nomme $f$ et  qui effectue
certains calculs en utilisant $a$~:

\begin{lstlisting}[caption={exemple de procédure}]
f(x):={
  a:=a+1;
  retourne(x+a)
}
\end{lstlisting}

Alors  $f(5)$ renvoie  $8$  mais si  on  redemande $f(5)$  on obtient  à
présent $9$ et si on recommence  on obtient $10$, etc. car à chaque appel
de  la  procédure  $f$,  la  variable $a$  est  modifiée~:~ici  $2\times
f(5)\neq f(5)+f(5)$~!


On  peut donc construire  un objet  qui \textbf{ressemble}  à une  fonction d'une
variable (mais qui  n'en est évidemment pas) et qui  à une même variable
renvoie  plusieurs valeurs.  En  effet, une  procédure\footnote{Certains
  langages  utilisent  le  terme  fonction  mais  nous  préférerons  \og
  procédure\fg{}   pour   ne    pas   confondre   avec   les   fonctions
  mathématiques. } 
ne dépend pas  uniquement des
arguments  entrés et  donc  peut  changer de  comportement  au cours  du
programme~:~c'est ce qu'on appelle en informatique des \emph{effets de  bord}.


On a en fait plutôt construit ici une fonction de deux variables~:

\[g~:~(a,x)->x+a\]

Le premier appel de $f(5)$ est en fait $g(3,5)$ et le deuxième $g(4,5)$,
etc. mais on a pu le faire en utilisant une forme qui \textbf{laisse à penser}
que $f$ est  une fonction qui renvoie une  infinité d'images différentes
d'un même nombre.

Informatiquement, $a$
 et $x$  jouent des rôles différents  puisque $x$ est un  argument de la
 procédure $f$ et $a$ est une variable globale donc \og extérieure\fg{}
 à  $f$ (on  dirait  un \emph{paramètre}).  D'ailleurs,  XCAS envoie  un
 avertissement pour nous le rappeler ~:

\verb+// Warning: a, declared as global variable(s) compiling f+

\subsection{Programmation fonctionnelle}



\textbf{Les    langages   fonctionnels    bannissent    totalement   les
  affectations.} Ils
utilisent   des  fonctions   \emph{au  sens   mathématique   du  terme},
c'est-à-dire qu'une fonction  associe une unique valeur de  sortie à une
valeur  donnée  en  entrée.  Les  fonctions peuvent être testées une  par une car
\emph{elles ne  changent pas  selon le  moment où elles  sont appelées  dans le
programme.}         On         parle        de        \emph{transparence
référentielle}. Le programmeur  n'a donc pas besoin de  savoir dans quel
état se trouve la mémoire. C'est  le logiciel qui s'occupe de la gestion
de la mémoire.



Historiquement, ce style de programmation est né du
$\lambda$-calcul  développé par  Alonzo \textsc{Church}  juste  avant la
publication   des    travaux   d'Alan   \textsc{Turing}\footnote{qui   a
  d'ailleurs été un étudiant de Church à Princeton...}.


Ce  principe  d'utilisation  de   fonctions  au  sens  mathématique  est
perturbant pour  des programmeurs formés aux langages  impératifs mais ne
devraient pas troubler des mathématiciens...


La  \textbf{récursivité} est  le  mode  habituel de  programmation  avec de  tels
langages~:~il s'agit  de fonctions qui  s'appellent elles-mêmes. Pendant
longtemps,  la  qualité des  ordinateurs  et  des langages  fonctionnels
n'était pas  suffisante et limitaient les domaines  d'application de ces
langages.

On  utilise  également  en  programmation  fonctionnelle  des  \textit{fonctions
d'ordre  supérieur}, c'est-à-dire  des fonctions  ayant  comme arguments
d'autres fonctions~:~cela permet par  exemple de créer des fonctions qui
à une fonction dérivable associe sa fonction dérivée.


\subsection{ Variable, affectation, déclaration, valeur}

Nous allons  préciser maintenant comment  est traitée une  variable dans
les deux modes de programmation étudiés. 

En programmation fonctionnelle, une variable  est un nom pour une valeur
alors qu'en  programmation impérative une  variable est un nom  pour une
case mémoire. En programmation fonctionnelle,  on ne peut pas changer la
valeur  d'une variable.  Nous parlerons  dans ce  cas de  déclaration de
variable pour  la distinguer de  l'affectation de variable  des langages
impératifs. 

Une variable  en programmation fonctionnelle correspond  à une constante
en programmation impérative. 

Par exemple, si nous écrivons dans CAML :

\caml
\begin{lstlisting}[caption={}]
# let x=3;;
\end{lstlisting}

puis
\begin{lstlisting}[caption={}]
# let x=4;;
\end{lstlisting}

on ne modifie pas  la variable x mais on en crée  une nouvelle qui porte
le  même   nom.  L'ancienne  variable   \texttt{x}  est  maintenant   masquée  et
inaccessible.  \og{}  Différence  subtile  pour  informaticien  coupant  les
cheveux en quatre \fg{} me direz-vous...et  bien non car cela peut créer des
surprises si l'on n'en est pas conscient.  

Considérons les déclarations suivantes sur CAML :


\begin{lstlisting}[caption={}]
# let x=3;; (* le # est créé automatiquement par CAML pour signifier qu'il attend nos instructions. Les ;; indiquent que nous avons fini de lui « parler » *)

# let f = function
    y -> y+x;;
\end{lstlisting}


Si l'on veut la valeur de l'image de 2 par la fonction \texttt{f} :


\begin{lstlisting}[caption={}]
# f(2);;  (* ce que nous entrons *)
- : int = 5  (* la réponse de CAML *)
\end{lstlisting}

en effet, $2+3=5$.

Observez maintenant ce qui se passe ensuite :


\begin{lstlisting}[caption={}]
# let x=0;;
x : int = 0

# f(2) ;;
- : int = 5
\end{lstlisting}


On a modifié la  valeur de \texttt{x} et pourtant \texttt{f(2)} ne  change pas.  En effet,
on a défini \texttt{f} en utilisant le nom  \texttt{x} qui vaut 3 lors de la définition de
\texttt{f}. Plus tard,  on redéclare la variable  \texttt{x} avec la valeur 0.  On n'a pas
modifié  la  valeur de  l'ancien  identificateur  \texttt{x}  et donc  \texttt{f(2)}  vaut
toujours 5. Ainsi \texttt{x } est un nom pour la valeur 3 et \texttt{f} un nom pour l'objet
\texttt{function y->y+x} c'est-à-dire \texttt{function y->y+3}. 

Observons maintenant ce que cela donne en programmation impérative avec XCAS.

\xc

\begin{lstlisting}[caption={}]
x:=3;
f:=y->y+x;
\end{lstlisting}


Les objets sont  affectés. XCAS nous renvoie un  message précisant qu'il
comprend  que  \texttt{x} est  une  variable globale  dans  la  définition de  la
procédure \texttt{f}. 


\reponse{// Warning: x, declared as global variable(s)}

\begin{lstlisting}[caption={}]
f(2);
\end{lstlisting}

\reponse{5}

Maintenant, ré-affectons \texttt{x} :

\begin{lstlisting}[caption={}]
x:=0;
f(2);
\end{lstlisting}

\reponse{2}

Cette  fois on  a ré-affecté  la  case mémoire  \texttt{x} qui  contient
maintenant 0 : son ancien contenu est écrasé et c'est comme s'il n'avait
jamais existé.  La procédure \texttt{f}  utilise donc ce  qu'elle trouve
dans  la  case   mémoire  \texttt{x}  au  moment  où   on  l'appelle  et
\texttt{f(2)}  peut donc  prendre des  valeurs différentes  au  cours du
temps. 

Dans toute la suite de ce document, on distinguera donc l'affectation de
variable  (en  tant  que  modification  du contenu  d'une  case  mémoire
étiquetée) de la programmation  impérative et la déclaration de variable
de la programmation fonctionnelle. 


\subsubsection{Une récursion concrète}


On place un certain nombre d'élèves en les classant par ordre décroissant
de taille. Le plus grand voudrait connaître sa propre taille mais chaque
élève ne peut  mesurer que son écart de taille avec  son voisin. Seul le
plus petit connaît sa taille. 

Le plus  grand mesure son  écart avec son  voisin et garde le  nombre en
mémoire.  Le voisin  fait de  même avec  son propre  voisin et  ainsi de
suite. Enfin l'avant dernier fait de même puis le plus petit lui transmet
sa taille : il peut donc calculer sa propre taille et transmet la au
suivant et ainsi  de suite~:~chacun va ainsi pouvoir  calculer sa taille
de proche en proche....

\subsubsection{Un premier exemple d'algorithme récursif}


Si nous  reprenons notre exemple précédant, nous  pouvons faire exprimer
aux élèves  que l'entier  suivant $n$ est  égal à $1+$  l'entier suivant
$n-1$ : on ne  sort pas des limites du cours de  mathématiques et on n'a
pas besoin  d'introduire des  notions d'informatique en  travaillant sur
cette notion.

On peut écrire un algorithme ainsi~:


\begin{minipage}{\textwidth}
\begin{algorithm}[H]
%\caption{successeur d'un entier~-~version récursive}
\eSi{$n=0$}{1}{$1+$ successeur de $n-1$}
\end{algorithm}\end{minipage}



La  récursivité  n'est  pas  l'apanage des  langages  fonctionnels.  Par
exemple XCAS permet d'écrire des programmes récursifs.

En français~:


\xc
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={exemple de programme récursif}]
successeur(k):={
 si k==0 alors 1
 sinon 1+successeur(k-1)
 fsi
}:;
\end{lstlisting}\end{minipage}


En anglais~:

\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={exemple de programme récursif en anglais}]
successeur(k):={
 if(k==0)then{1}
 else{1+successeur(k-1)}
}:;
\end{lstlisting}\end{minipage}


Que  se passe-t-il  dans  le  c\oe ur  de  l'ordinateur lorsqu'on  entre
\verb+successeur(3)+~?


\begin{itemize}


\item On entre comme argument 3~;

\item Comme 3  n'est pas  égal à 0,  alors\verb+successeur(3)+ est  stocké en
mémoire et vaut
\verb/1+successeur(2)/~;


\item Comme 2 n'est pas égal à 0, alors\verb+successeur(2)+ est stocké en
mémoire et  vaut
\verb/1+successeur(1)/~;


\item Comme 1 n'est pas égal à 0, alors\verb+successeur(1)+ est stocké en
mémoire et  vaut
\verb/1+successeur(0)/~;


\item Cette fois,\verb+successeur(0)+ est connu et vaut 1~;


\item\verb+successeur(1)+ est maintenant connu et vaut \verb/1+successeur(0)/
c'est-à-dire 2~;



\item\verb+successeur(2)+ est maintenant connu et vaut \verb/1+successeur(1)/
c'est-à-dire 3~;


\item\verb+successeur(3)+ est maintenant connu et vaut \verb/1+successeur(2)/
c'est-à-dire 4~:~c'est fini~!

\end{itemize}


C'est  assez  long  comme  cheminement  mais  ce  n'est  pas  grave  car
\emph{c'est  l'ordinateur qui  effectue  le \og  sale boulot\fg{}}~!  Il
stocke les  résultats intermédiaires  dans une \emph{pile}  et n'affiche
finalement que le résultat.

Comme il calcule  vite, ce n'est pas grave. L'élève  ou le professeur ne
s'est occupé que de la définition récursive (mathématique~!) du problème.



\smallskip


XCAS calcule facilement\verb+successeur(700)+ mais
\verb+successeur(7000)+ dépasse les possibilités de calcul du logiciel.


Et oui, un langage impératif ne traite pas efficacement le problème de pile, 
c'est pourquoi pendant longtemps  seuls les algorithmes
impératifs ont prévalus. 


\smallskip
{\itshape  {\bf Remarque~:}  par défaut,  XCAS  s'arrête au  bout de  50
  niveaux  de récursion.  Pour  aller  plus loin,  il  faut cliquer  sur
  \texttt{config}  à  côté de  \texttt{save}.  Régler  alors la  fenêtre
  \texttt{recurs} à 1000 par exemple}



\smallskip




Utilisons  à   présent  le  langage  fonctionnel   CAML,  développé  par
l'INRIA\footnote{Institut  National  de  Recherche  en  Informatique  et
  Automatique}. Même s'il intègre  des aspects impératifs pour faciliter
l'écriture de  certains algorithmes, il  est en premier lieu  un langage
fonctionnel  qui en  particulier gère  très efficacement  la  mémoire de
l'ordinateur pour éviter sa saturation lors d'appels récursifs.


Le programme s'écrit comme en mathématique (mais en anglais...)~:


\caml
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={successeur d'un entier}]
# let rec successeur(k)=
  if k=0 then 1
  else 1+successeur(k-1);;  
\end{lstlisting}\end{minipage}



Alors par exemple~:

\begin{minipage}{\textwidth}
\begin{lstlisting}
# successeur(36000);;
- : int = 36001
\end{lstlisting}\end{minipage}

Mais

\begin{minipage}{\textwidth}
\begin{lstlisting}
# successeur(3600000);;
Stack overflow during evaluation (looping recursion?).
\end{lstlisting}\end{minipage}


La \emph{pile} où sont stockés les résultats intermédiaires créés par la
récursion est en effet saturée.

Aujourd'hui, les langages fonctionnels  sont très efficaces et gèrent de
manière  intelligente  la  \emph{pile}. Ils le font soit automatiquement,
soit si la fonction utilise une \emph{récursion terminale}, c'est-à-dire
si l'appel récursif à la fonction n'est pas \emph{enrobé} dans une autre
fonction. 

Ici, ce  n'est pas le  cas car l'appel récursif \verb+successeur(k-1)+ est
enrobé dans la fonction $x\mapsto 1+x$.


On peut y  remédier en introduisant une fonction  intermédiaire qui sera
récursive terminale~:

\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={successeur version terminale (étape 1)}]
# let rec successeur_temp(k,resultat)=
        if k=0 then resultat
        else successeur_temp(k-1,resultat+1);;
\end{lstlisting}\end{minipage}


puis on appelle cette fonction en prenant comme résultat de départ 1~:

\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={successeur version terminale (étape 2)}]
# let successeur_bis(k)=
  successeur_temp(k,1);;
\end{lstlisting}\end{minipage}

Alors~:


\begin{minipage}{\textwidth}
\begin{lstlisting}
# successeur_bis(360000000);;
- : int = 360000001
\end{lstlisting}\end{minipage}

Il n'y a donc aucun problème pour traiter 360 millions d'appels récursifs~!


{\large \bf Dans un premier temps,  on peut laisser de côté ce problème
de récursion terminale au lycée et se contenter de travailler sur de petits
entiers.  Ainsi, on peut  choisir de  travailler avec  CAML ou  XCAS par
exemple, même si ce dernier n'est pas un langage fonctionnel.}









\subsection{Un premier exemple de fonction d'ordre supérieur}

Définissons  une fonction qui  à deux  fonctions $f$  et $g$  associe sa
composée $f\circ g$~:

\begin{lstlisting}[caption={composition de fonction}]
# let compose=function
   (f,g) -> function x->f(g(x));;
\end{lstlisting}

CAML devine le type des objets introduits en répondant~:

\begin{lstlisting}
val compose : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b = <fun>
\end{lstlisting}

Ceci signifie que  compose est une fonction (le \verb+<fun>+ final) qui
prend  comme arguments deux  fonctions (la  première qui  transforme une
variable  de  type\verb+a+  en  une variable  de  type \verb+b+ et  la
deuxième  qui  transforme une
variable  de type \verb+c+ en  une variable  de type \verb+a+)  et qui
renvoie une fonction  qui  transforme une
variable de type \verb+c+ en une variable de  type\verb+b+. En résumé,
on peut schématiser ce qu'a compris CAML~:

\[f~:~'a\mapsto  'b \qquad  g~:~'c\mapsto 'a\qquad  f\circ g~:~'c\mapsto
'b\]


Créons deux fonctions numériques~:

\begin{lstlisting}[caption={création de fonctions simples}]
# let carre = function
      x -> x*x;;

# let double = function
     x -> 2*x;;
\end{lstlisting}

Composons-les~:

\begin{lstlisting}
# compose(double,carre)(2);;
- : int = 8
# compose(carre,double)(2);;
- : int = 16
\end{lstlisting}

En effet, le double du carré de 2  est 8 alors que le carré du double de
2 vaut 16...


On peut faire la même chose avec XCAS~:

\xc

\begin{lstlisting}[caption={composée de fonctions avec XCAS}]
compose(f,g):={
  x->f(g(x))
}
\end{lstlisting}

Puis par exemple~:

\begin{lstlisting}
compose(x->x^2,x->2*x)(2)
\end{lstlisting}





\section{Deux manières d'aborder un même problème}

\subsection{Les tours de Hanoï}

\subsubsection{Le principe}

Ce casse-tête a été posé  par le  mathématicien
français Édouard \textsc{Lucas} en 1883.

Le  jeu  consiste  en  une  plaquette  de bois  où  sont  plantés  trois
piquets. Au  début du jeu, $n$  disques de diamètres croissant  de bas en
haut sont placés  sur le piquet de  gauche. Le but du jeu  est de mettre
ces disques dans le même ordre sur le piquet de droite en respectant les
règles suivantes~:

\begin{itemize}
\item on ne déplace qu'un disque à la fois~;
\item on ne peut poser un disque que sur un disque de diamètre supérieur.
\end{itemize}

\begin{figure}
\begin{center}
  \includegraphics[width=\textwidth]{hanoi}
\end{center}
\end{figure}


Essayez avec 2 puis 3 disques...  Nous n'osons pas vous demander de résoudre
le problème avec 4 disques~!



\subsubsection{Non pas comment mais pourquoi~:~version récursive}

 En  réfléchissant récursivement,  c'est enfantin~!...  Pour  définir un
 algorithme récursif, il nous
faut régler un cas simple et pouvoir simplifier un cas compliqué.


\begin{itemize}
\item \emph{cas simple}~: s'il y a zéro disque, il n'y a rien à faire~!
\item \emph{simplification d'un cas  compliqué}~: nous avons $n$ disques
  au départ  sur le premier disque  et nous savons  résoudre le problème
  pour $n-1$ disques. Appelons A, B et C les piquets de
  gauche à droite. Il suffit de déplacer les $n-1$ disques supérieurs de
  A vers B (hypothèse de récurrence) puis on déplace le plus gros disque resté sur A en C. Il ne
  reste  plus qu'à  déplacer vers  C les  $n-1$ disques  qui  étaient en
  B. (hypothèse de récurrence).
\end{itemize}

On voit bien  la récursion~:~le problème à $n$ disques  est résolu si on
sait résoudre le cas à $n-1$ disques  et on sait quoi faire quand il n'y
a plus de disques. 



On sait pourquoi  cet algorithme va réussir mais on  ne sait pas comment
s'y prendre étape par étape.

On va donc  appeler à l'aide l'ordinateur en  lui demandant d'écrire les
mouvements effectués à chaque étape.


\caml

On commence par créer une fonction qui affichera le mouvement effectué~:

\begin{lstlisting}[caption={mouvement élémentaire}]
let mvt depart arrivee=
print_string
("Déplace un disque de la tige "^départ^" vers la tige "^arrivée);
print_newline();;
\end{lstlisting}


Le programme proprement dit~:

\begin{lstlisting}[caption={résolution  récursive du problème  des tours
de Hanoï}]
let rec hanoi a b c= function
   | 0 -> ()  (*0 disque : on ne fait rien*)
   | n -> hanoi a c b (n-1); (*n-1 disques sont placés dans l'ordre de a vers b*)
          mvt a c; (*on déplace le disque restant en a vers c*)
          hanoi b a c (n-1) (*n-1 disques sont placés dans l'ordre de b vers c*);;
\end{lstlisting}

Les phrases entre\verb+(*+ et\verb+*)+ sont des commentaires.


Par exemple, dans le cas de 3 disques~:

\begin{lstlisting}
# hanoi "A" "B" "C" 3;;
Deplace un disque de la tige A vers la tige C
Deplace un disque de la tige A vers la tige B
Deplace un disque de la tige C vers la tige B
Deplace un disque de la tige A vers la tige C
Deplace un disque de la tige B vers la tige A
Deplace un disque de la tige B vers la tige C
Deplace un disque de la tige A vers la tige C
- : unit = ()
\end{lstlisting}

\subsubsection{Non pas pourquoi mais comment~:~version impérative}



Prenez un papier et  un crayon. Dessinez trois piquets A, C  et B et les
trois disques dans leur position initiale sur le plot A.

Déplacez alors les disques selon la méthode suivante~:

\begin{itemize}
\item  déplacez le  plus petit  disque vers  le plot  suivant  selon une
  permutation circulaire A-C-B-A ;
\item un seul des deux autres disques est déplaçable vers un seul piquet
  possible.
\end{itemize}

Réitérez (en  informatique à l'aide de boucles...)  ce mécanisme jusqu'à
ce que tous les disques soient sur C dans la bonne position.

On voit donc bien ici comment ça  marche ; il est plus délicat de savoir
pourquoi on arrivera au résultat.

Le programme est lui-même  assez compliqué à écrire~:~vous trouverez une
version en \texttt{C} (235 lignes...) à cette adresse~:

\begin{center}
  \href{http://files.codes-sources.com/fichier.aspx?id=38936\&f=HANOI\%5cHANOI.C}{http://files.codes-sources.com/fichier.aspx?id=38936\&f=HANOI\%5cHANOI.C}
\end{center}





% \section{Avec ou sans affectation~:~quelques exemples}\label{exemples}


\subsection{Suites définies par une relation de récurrence}


\subsubsection{Sans affectations}


La relation $u_{n+1}=3u_n+2$ valable pour  tout entier naturel $n$ et la
donnée de $u_0=5$  constituent un algorithme de calcul  récursif de tout
terme de la suite $(u_n)$. 
 


\begin{function}[H]
\caption{u(n,uo)}
\eSi{n=0}{uo}{3$\times$u(n-1,uo)+2}
\end{function}


Sa traduction  dans des langages sachant  plus ou moins  traiter de tels
algorithmes est directe. 


Par exemple, en XCAS, cela devient en français~:

\xc


\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={suite récurrente}]
u(n,uo):={
 si n==0 alors uo
 sinon 3*u(n-1,uo)+2
}
\end{lstlisting}\end{minipage}

et en anglais~:

\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={suite récurrente (VO)}]
u(n,uo):={
if(n==0){return(uo)}
else{3*u(n-1,uo)+2}
}
\end{lstlisting}\end{minipage}


En CAML~:

\caml
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={suite récurrente avec CAML}]
# let rec u(n,uo)=
    if n=0 then uo
    else 3*u(n-1,uo)+2;;
\end{lstlisting}\end{minipage}

En Sage:

\sage

\begin{lstlisting}[caption={suite récurrente avec Sage}]
sage: def u(n,uo):
....: if n==0:
....: return uo
....: else:
....: return 3*u(n-1,uo)+2
\end{lstlisting}


Ici encore, l'accent est mis sur  le \og pourquoi\fg{} et non pas le \og
comment\fg{} même s'il est beaucoup plus simple de le savoir que dans le
cas des tours de Hanoï. On illustre le cours de 1ère sur les suites.



\subsubsection{Avec affectations}

Au lieu de  stocker de nombreuses
valeurs dans une pile, on affecte  une seule case mémoire aux valeurs de
la suite qui sera \emph{ré-affectée},  au fur et à mesure du déroulement
du programme.




\begin{algorithm}[H]
\caption{Suite récurrente~:~version impérative}
\Entree{n,uo}\;
\Ini{temp\aff uo}\;
\Deb{
\Pour{k de 1 jusque n}{temp\aff 3$\times$ temp+2}
 } 
\end{algorithm}

Cela donne en français avec XCAS~:

\xc



\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={suite récurrente version impérative}]
u_imp(n,uo):={
local k,temp;
temp:=uo;
 pour k de 1 jusque n faire
  temp:=3*temp+2;
 fpour
retourne(temp);
}
\end{lstlisting}\end{minipage}


En anglais~:


\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={suite récurrente version impérative (VO)}]
u_imp(n,uo):={
local k,temp;
temp:=uo;
for(k:=1;k<=n;k:=k+1){
temp:=3*temp+2;
}
return(temp);
}
\end{lstlisting}\end{minipage}


Avec Sage/Python:

\sage

\begin{lstlisting}[caption={suite récurrente version impérative en Sage}]
sage: def u_imp(n,uo):
....:    temp=uo
....:    for k in [1..n] : temp=3*temp+2
....:    return(temp)
\end{lstlisting}

Dans  ce cas,  on voit  comment faire  pour calculer  $u_n$ à  partir de
$u_0$. La méthode  peut paraître moins \og élégante\fg{}  mais elle est
sûrement plus \og concrètement\fg{} assimilable.

% Il y  avait  un problème  mathématique  et  s'y ajoute  un
% mécanisme  informatique,  l'affectation, qui  pourrait  dans un  premier
% temps s'avérer perturbant pour des élèves de Seconde.

% D'autant plus que la raison d'être informatique de l'affectation - l'économie de mémoire
% -  n'a plus  vraiment  lieu  d'être avec  le  développement de  langages
% fonctionnels  très puissants comme  CAML qui  se débrouillent  très bien
% avec un algorithme récursif.

\subsection{Calculs de sommes}

On veut  calculer la somme des entiers de 1 à $n$.

\subsubsection{Sans affectation}

 Il suffit de
remarquer que cela revient  à ajouter $n$ à la somme des  entiers de 1 à
$n-1$ sachant que la somme des entiers de 1 à 1 vaut... 1.

L'écriture est donc simple et mathématique~:

\begin{function}[H]
%\caption{som\_ent(n)}
\eSi{n=1}{1}{1+som\_ent(n-1)}
\end{function}



En français avec XCAS~:


\xc
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={somme des entiers avec XCAS}]
som_ent(n):={
  si n==1 alors 1
  sinon n+som_ent(n-1)
  fsi
}:;
\end{lstlisting}\end{minipage}


En anglais~:

\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={somme des entiers avec XCAS (VO)}]
som_ent(n):={
if(n==1){1}
else{n+som_ent(n-1)}
}:;
\end{lstlisting}\end{minipage}


En CAML~:


\caml
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={somme des entiers avec CAML}]
# let rec som_ent(n)=
     if n=1 then 1
     else n+som_ent(n-1);;
\end{lstlisting}\end{minipage}
 

Par exemple~:

\begin{minipage}{\textwidth}
\begin{lstlisting}
# som_ent(100000);;
- : int = 705082704
\end{lstlisting}\end{minipage}



On peut même généraliser cette procédure à n'importe quelle somme
du type $\displaystyle\sum_{k=k_0}^nf(k)$~:


\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={somme  des   images  des  entiers   par  une   fonction avec CAML}]
# let rec som_rec(f,ko,n)=
     if n=ko then f(ko)
     else f(n)+som_rec(f,ko,n-1);;
\end{lstlisting}\end{minipage}



Avec SAGE:


\sage

\begin{lstlisting}[caption={somme des entiers avec Sage}]
sage: def som_ent(n):
....:   if n==1 : return 1
....:   else : return n+som_ent(n-1)
\end{lstlisting}



\begin{lstlisting}[caption={somme des images des entiers par une fonction avec Sage}]
sage: def som_rec(f,ko,n):
....:    if n==ko : return f(ko)
....:    else : return f(n)+som_rec(f,ko,n-1)
\end{lstlisting}


\subsubsection{Avec affectation}


\begin{minipage}{\textwidth}\begin{algorithm}[H]
%\caption{somme des entiers de 1 à n}
\Entree{$n$(entier naturel)}\;
\Ini{S\aff 0}\;
\Deb{
\Pour{k de 1 à n}{S\aff S+k}
\Retour{S}
 } 
\end{algorithm}\end{minipage}


Traduction XCAS en français~:


\xc
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={somme des entiers version impérative avec XCAS}]
som(n):={
local S;
S:=0;
pour k de 1 jusque n faire
  S:=S+k;
fpour;
retourne(S)
}
\end{lstlisting}\end{minipage}


En anglais~:

\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={somme des entiers version impérative (VO)}]
som(n):={
local S;
S:=0;
for(k:=1;k<=n;k++){S:=S+k};
return(S)
}
\end{lstlisting}\end{minipage}



Avec Sage/Python:

\sage

\begin{lstlisting}[caption={somme des entiers version impérative avec Sage}]
sage: def som(n):
....:   S=0
....:   for k in [1..n] : S+=k
....:   return S
\end{lstlisting}


On a une approche physique avec l'algorithme impératif~:~S vaut
0  au départ  et on  demande S  en sortie~;  S ne  vaut donc  plus  0 en
général... Cela  peut être troublant  pour des élèves  qui ont du  mal à
résoudre des  équations simples  et oublient ce  qui se cache  derrière le
symbole  \og =\fg{}. Il  y aurait  une égalité  en mathématiques  et une
autre en informatique~!  

Cependant,  cette  manière de  voir  peut  être  plus intuitive~:~si  on
considère S  comme le solde  de son compte  en banque, on  surveille son
compte régulièrement en ajoutant $k$ à chaque visite. Le compte porte le
même nom, S, mais son contenu change régulièrement.

La version impérative peut de plus être directement liée à l'écriture~:

\[\sum_{k=1}^nk\]

qu'on lit  \og somme  des $k$  pour $k$ variant  de 1  à $n$\fg{}  où la
boucle \og pour\fg{} apparaît de manière naturelle.



\subsection{Partie entière}


On   définit la  partie entière  d'un réel $x$  comme étant  le plus
grand entier inférieur à $x$.




\subsubsection{Sans affectation}

On part du fait que la  partie entière d'un nombre appartenant à $[0;1[$
est nulle.

Ensuite, on \og  descend \fg{} de $x$ vers  0 par pas de 1  si le nombre
est positif en montrant que $\lfloor x\rfloor=1+\lfloor x-1\rfloor$.

Si le nombre est négatif, on \og monte\fg{} vers 0 en montrant que $\lfloor x\rfloor=-1+\lfloor x+1\rfloor$.





\begin{function}[H]
%\caption{partie\_entiere(x)}
\eSi{x est positif et x < 1}{0}{
  \eSi{x est positif}{1+partie\_entiere(x$-$1)}{$-1$+partie\_entiere(x+1)}
}
\end{function}



\xc


En français avec XCAS~:

\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={partie entière récursive}]
partie_entiere(x):={
  si ((x>=0) et (x<1)) alors 0
  sinon si (x>0)
        alors 1+partie_entiere(x-1)
        sinon -1+partie_entiere(x+1)
        fsi
  fsi   
}
\end{lstlisting}\end{minipage}


En anglais~:

\xc
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={partie entière récursive (VO)}]
partie_entiere(x):={
 if((x>=0) and (x<1)){0}
 else{ if(x>0){1+partie_entiere(x-1)}
       else{-1+partie_entiere(x+1)}
    }
}:;
\end{lstlisting}\end{minipage}




En CAML~:

\caml
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={partie entière récursive avec CAML}]
# let rec partie_entiere (x)=
        if x >= 0. && x < 1.
         then 0.
         else if x > 0.
               then   1. +. partie_entiere (x -. 1.) 
	       else -.1. +. partie_entiere (x +. 1.);;
\end{lstlisting}\end{minipage}


\textit{Remarque}~:  la  double  esperluette  correspond  à  l'opérateur
logique \og  ET\fg{}. CAML travaille  avec deux types  de nombres~:~les
entiers et  les flottants. Les  opérations avec les entiers  suivent les
notations habituelles. Lorsqu'on travaille  avec des flottants (c'est le
cas  ici  car  $x$  est  un  réel quelconque)  le  symbole  habituel  de
l'opération est suivi d'un point.

\medskip



Avec Sage/Python:

\sage

\begin{lstlisting}[caption={partie entière récursive avec Sage}]
sage: def partie_entiere(x):
....:   if x>=0 and x<1 : return 0
....:   elif x>0 : return 1+partie_entiere(x-1)
....:   else : return -1+partie_entiere(x+1)
\end{lstlisting}

On notera que l'algorithme  récursif s'applique ici à des \textbf{réels}
et  non plus  à des  \textbf{entiers} :  on dépasse  ainsi le  cadre des
suites.   Pour  que l'algorithme  fonctionne,  on  raisonne sur  des
intervalles et non plus sur une valeur initiale. 



Ici,  on réfléchit à  la notion \emph{mathématique}  de partie
entière.   On   met   en   place  des   résultats   \emph{mathématiques}
intéressants.


\subsubsection{Avec affectation}


Pour les nombres positifs, on part de
0.  Tant qu'on  n'a  pas dépassé  $x$,  on avance  d'un  pas. La  boucle
s'arrête dès  que $k$ est strictement  supérieur à $x$.  La partie entière
vaut donc $k-1$.


Dans le  cas d'un réel  négatif, il faut  cette fois reculer d'un  pas à
chaque tour de boucle et la partie entière est la première valeur de $k$
à être inférieure à $x$~:


\begin{minipage}{\textwidth}\begin{algorithm}[H]
%\caption{partie entière d'un réel quelconque}
\Entree{$x$(réel)}\;
\Ini{k \aff 0}\;
\Deb{
\eSi{x>=0}{
\Tq{k<=x}{k\aff k+1}\;
\Retour{k-1}
}{
\Tq{k>x}{k\aff k-1}\;
\Retour{k}
}
}
\end{algorithm}\end{minipage}



Avec XCAS en Français~:






\xc
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={partie entière impérative (XCAS)}]
pe(x):={
local k;
k:=0;
si x>=0 alors
   tantque k<=x faire
      k:=k+1;
   ftantque;
   retourne(k-1);
sinon 
   tantque k>x faire
      k:=k-1;
   ftantque;
   retourne(k); 
fsi;  
}:;
\end{lstlisting}\end{minipage}

Avec XCAS en anglais~:



\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={partie entière impérative (VO)}]
pe(x):={
local k;
k:=0;
if(x>=0){
   while(k<=x){k:=k+1};
   return(k-1);
        }
else{
   while(k>x){k:=k-1};
   return(k); 
    } 
}:;
\end{lstlisting}\end{minipage}

Avec Sage/Python:

\sage

\begin{lstlisting}[caption={partie entière impérative (Sage/Python)}]
>>> def pe(x):
     k=0
     if x>=0:
         while k<=x : k+=1
         return k-1
     else :
         while k>x : k+=-1
         return k
\end{lstlisting}


On utilise ici une affectation ($k$ devient $k+1$ ou
$k-1$)  et  une  \og  boucle  while\fg{}  avec un  test  et  une  action
d'affectation  tant que  le test  est  vrai. Il  s'agit d'un  traitement
physique de la mémoire. On perd un peu de vue la notion mathématique mais on donne
une  vision dynamique  de la  recherche de  la partie  entière~:~on peut
imaginer un  petit \og  personnage\fg{} se promenant  sur la  droite des
réels  en faisant  des  pas de  longueur  1 et  qui  continue à  avancer
\emph{tant qu'} il n'a pas dépassé le réel. 


\subsection{Développement en fractions continues}
\subsubsection{ Pratique du développement}

 \begin{itemize}
  
\item Vous connaissez l'algorithme suivant~:

\begin{minipage}{\textwidth}
\begin{eqnarray}
172&=&3\times\textcolor{0.2white}{51}+\textcolor{0.2white}{19}\\
\textcolor{0.2white}{51}&=&2\times\textcolor{0.2white}{19}+13\\
19&=&1\times13+6\\
13&=&2\times 6+1\\
6&=&6\times 1+0
\end{eqnarray}
\end{minipage}

\item On peut donc facilement compléter  la suite d'égalité suivante~:


\begin{minipage}{\textwidth}
\[\frac{172}{51}=3+\frac{19}{51}=3+\frac{1}{\frac{51}{19}}=3+\frac{1}{2+\frac{13}{19}}=\dots     \]
\end{minipage}

\item Quand tous les numérateurs sont égaux à 1, on dit qu'on a développé $\frac{172}{51}$ en
  fraction continue et pour simplifier l'écriture on note~:
\[\frac{172}{51}=[3; 2; \dots ]\]

\item Par exemple, on peut développer  $\frac{453}{54}$ en fraction continue.

\item Dans l'autre sens on peut écrire $[2; 5; 4]$ sous la forme d'une fraction irréductible.

  \end{itemize}

Nous allons construire les algorithmes correspondant.

\subsubsection{Sans affectation}


On suppose connus les algorithmes  donnant le reste et le quotient d'une
division euclidienne.


\begin{minipage}{\textwidth}\begin{algorithm}[H]
%\caption{fractions continues : version récursive}\label{fc}
fc(a,b)\;
\eSi{b=0}{\Retour{liste vide}}{
\Retour{[quotient(a,b),fc(b,reste(a,b))]}
} 
\end{algorithm}\end{minipage}

En français en XCAS~:


\xc

\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={fractions continues en récursif}]
fc(a,b):={
  si b==0 alors [] 
  sinon concat(iquo(a,b),fc(b,irem(a,b)))
  fsi
}:;
\end{lstlisting}\end{minipage}



En anglais~:


\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={partie entière en récursif (VO)}]
fc(a,b):={
  if(b==0)then{[]}
  else{concat(iquo(a,b),fc(b,irem(a,b)))}
}:;
\end{lstlisting}\end{minipage}


La commande\verb+concat(élément,liste)+  ajoute\verb+élément+ au début
de\verb+liste+.


Alors\verb+fc(172,51)+ renvoie\verb+[3,2,1,2,6]+


En CAML

\caml

\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={partie entière en récursif avec CAML}]
# let rec fc (a,b) =
        if b = 0
         then []
         else  a/b :: fc(b,a-a/b*b);;
\end{lstlisting}\end{minipage}



Pour  ajouter  un  élément  à  une  liste  sur  CAML,  la  syntaxe  est
\verb+élément::liste+.

\medskip

Avec Sage/Python:
\sage

\begin{lstlisting}[caption={partie entière en récursif (Sage)}]
sage: def fc(a,b):
....:   if b==0 : return []
....:   else : return [a//b]+fc(b,a%b)
\end{lstlisting}

La concaténation des listes sur Sage/Python se fait avec \verb|+|; le quotient entier s'obtient avec \verb+//+ et le reste entier avec \verb+%+.

L'algorithme est très simple à écrire et à comprendre.

\subsubsection{Avec affectation}


\begin{minipage}{\textwidth}\begin{algorithm}[H]
%\caption{Fractions continues~:~version impérative}
\Entree{2 entiers a et b}\;
\Ini{\;
num\aff a\;
den\aff b\;
res\aff reste(num,den)\;
Liste\aff vide\;
}\;
\Deb{
\Tq{res$\neq$0}{
Liste\aff Liste,quotient(num,den)\;
num\aff den\;
den\aff res\;
res\aff reste(num,den)\;
}
 }
\Retour{[Liste,quotient(num,den)]} 
\end{algorithm}\end{minipage}

En français avec XCAS~:

\xc
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={partie entière en impératif}]
frac_cont(a,b):={
local num,den,res,Liste;
num:=a;
den:=b;
res:=irem(num,den);
Liste:=NULL;
 tantque res>0 faire
    Liste:=Liste,iquo(num,den);
    num:=den;
    den:=res;
    res:=irem(num,den);
 ftantque
retourne([Liste,iquo(num,den)]);
}:;
\end{lstlisting}\end{minipage}

En anglais~:

\xc
\begin{minipage}{\textwidth}
\begin{lstlisting}[caption={partie entière en impératif (VO)}]
frac_cont(a,b):={
local num,den,res,Liste;
num:=a;
den:=b;
res:=irem(num,den);
Liste:=NULL;
while(res>0){
    Liste:=Liste,iquo(num,den);
    num:=den;
    den:=res;
    res:=irem(num,den);
}
return([Liste,iquo(num,den)]);
}:;
\end{lstlisting}\end{minipage}




Avec Sage/Python:

\sage
\begin{lstlisting}[caption={partie entière en impératif (Sage)}]
sage: def fc(a,b):
....:   num=a
....:   den=b
....:   res=num%den
....:   Liste=[]
....:   while res>0:
....:      Liste+=[num//den];
....:      num=den;
....:      den=res;
....:      res=num%den;
....:   return Liste+[num//den]
\end{lstlisting}











Ici, 
la manipulation de plusieurs niveaux d'affectation et d'une boucle while
est assez délicate. La chronologie des affectations est primordiale~:~on
ne peut proposer cette version à des débutants...

% \subsection{Décomposition en base 2}

% \subsubsection{Expérimentation}

% Une  méthode  pour  obtenir  l'écriture   en  base  2  d'un  nombre  est
% d'effectuer des divisions successives. Par exemple pour 11~:
% \begin{minipage}{\textwidth}
% \begin{center}
% \opidiv[remainderstyle=\bfseries\large\color{0.2white},resultstyle=\color{blue}]{11}{2}\hspace{1cm}
% \opidiv[remainderstyle=\bfseries\large\color{0.2white},resultstyle=\color{blue}]{5}{2}
% \hspace{1cm}
% \opidiv[remainderstyle=\bfseries\large\color{0.2white},resultstyle=\color{blue}]{2}{2}
% \hspace{1cm}
% \opidiv[remainderstyle=\bfseries\large\color{0.2white},resultstyle=\color{blue}]{1}{2}

% \end{center}
% \end{minipage}


% \begin{minipage}{\textwidth}
% \begin{align*}
% 11 &=\Bigl(2\times5+1\Bigr)
% \\ &=\Bigl(2\times\bigl(2\times2+1\bigr)+1\Bigr)
% \\ &=\Bigl(2\times\bigl(2\times(2\times 1)+1\bigr)+1\Bigr)
% \\ &=\Bigl(2\times (2^2+1)+1\Bigr)
% \\ &=2^3+2+1
% \\ &=1\times 2^3+0\times 2^2+1\times 2^1+1\times 2^0 
% \end{align*}
% \end{minipage}


% L'écriture de  11 en base  2 est donc  1011~:~c'est la liste  des restes
% obtenus mais dans l'ordre inverse.


% La méthode est facilement généralisable.



% \subsubsection{Version récursive}

% Notons $q_n$ et $r_n$ le quotient et le reste après $n$ divisions.

% $q_{n+1}$ est le quotient entier de  $q_n$ par 2 et on rajoute $r_{n+1}$
% à notre liste de restes.




% Après  un certain  nombre  de divisions,  le  quotient sera  strictement
% inférieur à 2.



% \begin{minipage}{\textwidth}\begin{function}[H]
% \caption{Binaire(n)}
% \eSi{n<2}{n}{Binaire(quotient(n,2)),reste(n,2)} 
% \end{function}\end{minipage}




% Ce qui donne en français avec XCAS~:




% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% Binaire(n):={
%     si n<2 alors n
%     sinon Binaire(iquo(n,2)),irem(n,2)
%     fsi
% }
% \end{lstlisting}\end{minipage}









% En anglais~:

% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% Binaire(n):={
%     if (n<2){ n}
%     else{Binaire(iquo(n,2)),irem(n,2)}
% }
% \end{lstlisting}\end{minipage}


% et en CAML~:
% \caml

% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% # let rec binaire n =
%         if n<2 
%           then [n]
%         else  binaire(n/2)\verb+ [n mod 2];;
% \end{lstlisting}\end{minipage}


% {\itshape    On utilise \verb+liste  1\verb+ liste 2+ pour  concaténer deux listes et
%    \verb+ élément :: liste+ pour rajouter un élément en début de liste.
%  } 


% \subsubsection{Version impérative}


% \begin{minipage}{\textwidth}\begin{algorithm}[H]
% %\caption{décomposition en base 2}
% \Entree{un entier $n$}\;
% \Ini{\;
% $r$\aff le reste de la division de $n$ par 2\;
% $q$\aff le quotient de la division de $n$ par 2\;
% R une liste contenant $r$ au départ.
% }\;
% \Deb{
% \Tq{q>0}{
% r\aff le reste de la division de $q$ par 2\;
% $q$\aff le quotient de la division de $q$ par 2\;
% On ajoute r au début de la liste R.
% }
% \Retour{R}
%  } 
% \end{algorithm}\end{minipage}

% En XCAS~:


% Comme dans la plupart des langages de calcul, le reste et le quotient de la division
% euclidienne   de   a   par    b   sont   obtenus   respectivement   avec
% \texttt{irem(a,b)} et \texttt{iquo(a,b)}.

% On concatène deux listes avec \texttt{concat(L1,L2)}.


% En français avec XCAS~:

% \xc
% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% base_deux(n):={
% local r,R,q;
% r:=irem(n,2);
% q:=iquo(n,2);
% R:=[r];
%  tantque q>0 faire
%   r:=irem(q,2);
%   q:=iquo(q,2);
%   R:=concat([r],R); 
%  ftantque
% return(R)
% }
% \end{lstlisting}\end{minipage}



% En anglais~:


% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% base_deux(n):={
% local r,R,q;
% r:=irem(n,2);
% q:=iquo(n,2);
% R:=[r];
%  while(q>0){
%    r:=irem(q,2);
%    q:=iquo(q,2);
%    R:=concat([r],R); 
%  }
% return(R)
% }
% \end{lstlisting}\end{minipage}




% On peut bien sûr généraliser ceci à n'importe quelle base.



\subsection{Dichotomie}


Pour résoudre une équation  du type $f(x)=0$, on recherche graphiquement
un intervalle $[a,b]$ où la fonction semble changer de signe.

On note ensuite $m$ le milieu du segment $[a,b]$. On évalue le signe de $f(m)$.

Si c'est  le même  que celui  de $f(a)$ on  remplace $a$  par $m$  et on
recommence.  Sinon, c'est $b$  qu'on remplace  et on  recommence jusqu'à
obtenir la précision voulue.





\subsubsection{Sans affectation}

On appellera \texttt{eps} la précision voulue.


\begin{minipage}{\textwidth}\begin{function}[H]
%\caption{dicho\_rec(f,a,b,eps)}
\eSi{b-a est plus petit que la précision eps}{
(b+a)/2}{
\eSi{f(a) et f((b+a)/2) sont de même signe }
{dico\_rec(f,(b+a)/2,b,eps)}
{dicho\_rec(f,a,(b+a)/2,eps)}
} 
\end{function}\end{minipage}

On  remarquera  ici que  la  récursion  se  fait sans  faire  intervenir
d'entier~:~le test d'arrêt est effectué sur la précision du calcul.

On va rajouter justement un  compteur pour savoir combien de calculs ont
été effectués.


\xc

En français avec XCAS~:



\begin{lstlisting}[caption={dichotomie en récursif}]
dicho_rec(f,a,b,eps,compteur):={
 si evalf(b-a)<eps alors 0.5*(b+a),compteur+1
 sinon si f(a)*f(0.5*(b+a))>0
       alors dicho(f,0.5*(b+a),b,eps,compteur+1)
       sinon dicho(f,a,0.5*(b+a),eps,compteur+1)
       fsi
 fsi
}:;
\end{lstlisting}






\begin{lstlisting}[caption={dichotomie en récursif (VO)}]
dicho_rec(f,a,b,eps,compteur):={
if(evalf(b-a)<eps){0.5*(b+a),compteur+1};
if(f(a)*f(0.5*(b+a))>0){dicho(f,0.5*(b+a),b,eps,compteur+1)}
                   else{dicho(f,a,0.5*(b+a),eps,compteur+1)}
}:;
\end{lstlisting}

En CAML~:

\caml

\begin{lstlisting}[caption={dichotomie en récursif avec CAML}]
# let rec dicho_rec(f,a,b,eps,compteur)=
    if abs_float(b-.a)<eps then 0.5*.(b+.a),compteur
    else if f(a)*.f(0.5*.(b+.a))>0. then dicho_rec(f,0.5*.(b+.a),b,eps,compteur+1)
         else  dicho_rec(f,a,0.5*.(b+.a),eps,compteur+1);;
\end{lstlisting}



ce qui donne~:


\begin{lstlisting}
# dicho_rec( (fun x->(x*.x-.2.)),1.,2.,0.00001,0);;
- : float * int = (1.41421127319335938,17)
\end{lstlisting}



Avec Sage/Python:

\sage
\begin{lstlisting}[caption={dichotomie en récursif (Sage/Python)}]
sage: def dicho(f,a,b,p,compteur):
....:   if abs(b-a).n(digits=p)<10**(-p) : return [0.5*(b+a).n(digits=p+len(str(floor(a)))),compteur]
....:   elif f(a)*f(0.5*(b+a))>0 : return dicho(f,0.5*(b+a).n(digits=p+len(str(floor(a)))),b,p,compteur+1)
....:   else : return dicho(f,a,0.5*(b+a).n(digits=p+len(str(floor(a)))),p,compteur+1)
....: 
\end{lstlisting}


Alors:

\begin{lstlisting}[caption={}]
sage: def f(x): return x**2-2
....: 
sage: dicho(f,1,2,5,0)
[1.41421, 17]

sage: def f(x): return x**2-153
....: 
sage: dicho(f,10,20,5,0)
[12.36931, 20]
\end{lstlisting}

Le rajout de \verb+len(str(floor(a)))+ permet d'adapter au nombre de chiffres de la partie entière.









\xc



\subsubsection{Avec affectation}

\begin{algorithm}[H]
%\caption{dichotomie}
\Entree{une fonction f, les bornes a et b, une précision p}\;
\Ini{aa\aff a, bb\aff b}\;
\Deb{
\Tq{bb-aa>p}{
\eSi{signe  de  f((aa+bb)/2) est  le  même  que  celui de  f(bb)}{bb\aff
  (aa+bb)/2}{aa\aff (aa+bb)/2}
}
\Retour{(aa+bb)/2}
 } 
\end{algorithm}


Avec XCAS, il faut juste ne  pas oublier de régler quelques problèmes de
précision. On  rajoute aussi pour le  plaisir un compteur  qui nous dira
combien de \og tours de boucles\fg{} le programme aura effectué.



\begin{lstlisting}[caption={dichotomie en impératif (XCAS)}]
dicho(F,p,a,b):={
local aa,bb,k,f,c;
aa:=a;
bb:=b;
epsilon:=1e-100; 
f:=unapply(F,x);
compteur:=0; 
 while(evalf(bb-aa,p)>10^(-p)){
    if( f(0.5*(bb+aa))*f(bb)>0 )
      then{bb:=evalf((aa+bb)/2,p+1)}
      else{aa:=evalf((aa+bb)/2,p+1)}
      k:=k+1; 
    }
return evalf((bb+aa)/2,p+1)+" est la  solution trouvee apres " +(k+1)+ "iterations";
}:;
\end{lstlisting}

En reprenant le même exemple~:

\begin{lstlisting}
dicho(x^2-2,5,1,2)
\end{lstlisting}

On obtient la même réponse~:

\begin{center}
 \verb+1.414211273 est la solution trouvee  apres 18 iterations+
\end{center}


Avec Sage/Python:

\sage

\begin{lstlisting}[caption={dichotomie en impératif (Sage)}]
sage: def dicho(f,a,b,p):
....:   [aa,bb,compteur,c]=[a,b,0,len(str(floor(a)))]
....:   while (bb-aa).n(digits=p)>10**(-p):
....:      if f(0.5*(bb+aa))*f(bb)>0 :
....:         bb=(0.5*(aa+bb)).n(digits=p+c)
....:      else :
....:         aa=(0.5*(aa+bb)).n(digits=p+c)
....:      compteur=compteur+1
....:   return [(0.5*(aa+bb)).n(digits=p+c),compteur]
\end{lstlisting}








Les deux versions sont ici  assez similaires avec toujours peut-être une
plus grande simplicité d'écriture dans le cas récursif.



% \subsection{Méthode des rectangles}


% \subsubsection{Version récursive}

% On  veut  calculer une  intégrale  d'une  fonction  par la  méthode  des
% rectangles. La  définition récursive  est assez naturelle,  dynamique et
% permet de bien comprendre la construction de l'intégrale~:



% \begin{minipage}{\textwidth}\begin{function}[H]
% \caption{integ(f,a,b,dx)}
% \eSi{a>b}{0}{f(a)$\times$ dx+integ(f,a+dx,b,dx)} 
% \end{function}\end{minipage}


% Cela donne en CAML~:

% \caml

% \begin{lstlisting}
% # let rec integ(f,a,b,dx)=
%       if a>b then 0.
%       else f(a)*.dx+.integ(f,a+.dx,b,dx);;
% \end{lstlisting}

% Par exemple~:

% \begin{lstlisting}
% # let g(x)=x;;

% # integ(g,0.,1.,0.0001);;
% \end{lstlisting}

% donne~:

% \begin{lstlisting}
% - : float = 0.500049999999960249
% \end{lstlisting}

% C'est-à-dire $\displaystyle\int_0^1x{\rm d }x\approx 0.5$


% Pour améliorer l'approximation, il faudrait en fait améliorer la méthode
% mathématique... 


% \subsubsection{Version impérative}


% \begin{algorithm}[H]
% \caption{Méthode des rectangles}
% \Entree{f,a,b,dx}\;
% \Ini{S\aff 0\;
% an\aff a}\;
% \Deb{
% \Tq{an<b}{S\aff S+f(an)$\times$ dx\;
%           an\aff an+dx}
% \Retour S
%  } 
% \end{algorithm}


% \xc

% Avec XCAS en français~:


% \begin{lstlisting}
% integ(f,a,b,dx):={
% local S,an;
% S:=0;
% an:=a;
%  tantque an<b faire
%    S:=S+f(an)*dx;
%    an:=an+dx;
%  ftantque
% return(S)
% }
% \end{lstlisting}

% En anglais~:


% \begin{lstlisting}
% integ(f,a,b,dx):={
% local S,an;
% S:=0;
% an:=a;
%  while(an<b){
%    S:=S+f(an)*dx;
%    an:=an+dx;
%  }
% return(S)
% }:;
% \end{lstlisting}

% \section{Calcul  du  PGCD  par  l'algorithme  d'Euclide  et  un  exemple
%   d'application au calcul avec des fractions}



% Un  sujet  phare  de  la  future Seconde  est  l'étude  de  l'algorithme
% d'Euclide.   Il   permet   d'écrire   que,   si   $b$   est   non   nul,
% $PGCD(a,b)=PGCD(b,reste(a,b))$~:~c'est  un  mécanisme  récursif  qui  se
% traduit naturellement.




% \begin{minipage}{\textwidth}\begin{function}[H]
% \caption{pgcd(a,b)}
% \eSi{b=0}{a}{Binaire(quotient(n,2)),reste(n,2)} 
% \end{function}\end{minipage}







% En CAML~:

% \caml
% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% # let rec pgcd (a,b) =
%          if b=0
%           then a
%           else  pgcd(b,a-a/b*b);;
% \end{lstlisting}
% \end{minipage}

% CAML  travaille par défaut  avec des  entiers donc  a/b est  le quotient
% entier de la division de a par  b. Ainsi a-a/b*b est en fait le reste de
% la division euclidienne de a par b. 



% En français avec XCAS~:



% \xc
% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% pgcd(a,b):={
%  si b==0 alors  a
%  sinon pgcd(b,irem(a,b))
%  fsi
% }
% \end{lstlisting}
% \end{minipage}




% En anglais~:

% \xc
% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% pgcd(a,b):={
%  if(b==0)then{a}
%  else{pgcd(b,irem(a,b))}
% }
% \end{lstlisting}
% \end{minipage}


% Cela   va  nous  permettre   de  construire   les  opérations   sur  les
% fractions. Voyons comment procéder avec CAML.


% On va représenter une fraction par une liste du type [numérateur;dénominateur].

% Pour prévenir toute division par  zéro on va créer une  \emph{exception}  qu'on  nommera  \texttt{Division\_par\_zero}  et  qui  nous
% servira de garde-fou~:
% \caml
% \begin{lstlisting}
% # exception Division_par_zero;;
% \end{lstlisting}


% On invoquera cette exception avec la commande \texttt{raise}~:~étant
% donné le niveau d'anglais des élèves, cette commande est naturelle...

% On peut créer un opérateur qui simplifie les fractions~:

% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% # let simp([a;b]) = 
%  if b=0 then raise Division_par_zero
%  else [a/pgcd(a,b);b/pgcd(a,b)];;
% \end{lstlisting}
% \end{minipage}

% Ne pas tenir compte du \og  Warning\fg{} qui indique juste que le cas où
% on entre une liste vide n'a pas été prévu.

% On crée ensuite une somme simplifiée de fractions~:

% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% # let som([a;b],[c;d]) =
%   if b=0 or d=0 then raise Division_par_zero else
%   simp([a*d+b*c;b*d]);;
% \end{lstlisting}
% \end{minipage}



% Par exemple~:

% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% # som([2;3],[1;6]);;
% - : int list = [5; 6]
% \end{lstlisting}
% \end{minipage}

% Une multiplication~:

% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% #  let mul([a;b],[c;d]) =
%   if b=0 or d=0 then raise Division_par_zero else
%   simp([a*c;b*d]);;
% \end{lstlisting}
% \end{minipage}


% Par exemple~:

% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% # mul([3;2],[2;9]);;
% - : int list = [1; 3]
% \end{lstlisting}
% \end{minipage}


% Un inverse~:

% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% #  let inv([a;b]) =
%   if b=0 or a=0 then raise Division_par_zero else
%   simp([b;a]);;
% \end{lstlisting}
% \end{minipage}


% Une division~:

% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% # let div([a;b],[c;d])=mul([a;b],inv([c;d]));;
% \end{lstlisting}
% \end{minipage}



% Par exemple, comment entrer 

% \begin{minipage}{\textwidth}
% \[1+\frac{2+\frac{3}{4}}{1-\frac{5}{6}}\]
% \end{minipage}

% \begin{minipage}{\textwidth}
% \begin{lstlisting}
% # som([1;1],div(som([2;1],[3;4]),som([1;1],[-5;6])));;
% - : int list = [35; 2]
% \end{lstlisting}
% \end{minipage}

% Évidemment,  c'est moins  pratique  que  de taper  le  résultat sur  une
% machine mais  ça permet  de réfléchir aux  différentes opérations,  à la
% notion de fonction,...

% On aurait pu écrire les même instructions en XCAS.



\section{Algorithme récursif ne signifie pas suite récurrente}

Si les suites définies par une relation $u_{n+1}=f(u_n)$ sont facilement
décrites par un algorithme récursif,  ce n'est pas le seul champ d'action
de la récursion.

Dès  qu'on  connaît  une  situation  simple  et  qu'on  est  capable  de
simplifier une situation compliquée, on peut utiliser la récursion.


\subsection{Longueur d'une liste}

Par exemple, si on veut calculer la longueur d'une liste~:

\begin{itemize}
\item la liste vide est de longueur nulle (cas simple)~;
\item la longueur d'une liste est égale à 1+la longueur de la liste sans
  son premier élément.
\end{itemize}



Cela donne en traduction directe avec CAML~:

\caml
\begin{lstlisting}[caption={longueur d'une liste en récursif (CAML)}]
# let rec longueur = function
              [] -> 0
   | tete::corps -> 1+longueur(corps);;
\end{lstlisting}

La  barre verticale  permet  de  définir une  fonction  par morceaux  en
distinguant les cas.

L'écriture \verb+x::liste+ signifie  qu'on rajoute  $x$ en  tête  de la
liste \texttt{liste}.

CAML trouvant lui-même le type des variables utilisées sait qu'on va lui
entrer  une liste  de n'importe  quoi (puisqu'on  peut l'écrire  sous la
forme \texttt{tete} rajoutée à \texttt{corps}) et que \texttt{longueur} sera un entier
(puisqu'on lui ajoute 1).

C'est mathématique...

Avec Sage:
\sage
\begin{lstlisting}[caption={longueur d'une liste en récursif (Sage)}]
sage: def longueur(L):
....:   if L==[]: return 0
....:   else: del L[0]; return(1+longueur(L))
\end{lstlisting}

\subsection{Somme d'entiers}


Supposons  que  nous  ne  sachions  que  trouver  le  successeur  ou  le
prédécesseur d'un
entier. Comment additionner deux entiers quelconques~?

Avec CAML:

\caml
\begin{lstlisting}[caption={somme d'entiers en récursif (CAML)}]
# let rec add = function
          (0,x) -> x
  |       (x,y) -> add((x-1),y)+1;;
\end{lstlisting}





Additionner  $x$ et  $y$ c'est  prendre le  successeur de  l'addition du
prédécesseur de $x$ et de $y$...c'est-à-dire~:~$x+y=\big((x-1)+y\big)+1$
sachant que $0+x=x$.


Avec Sage:

\sage

\begin{lstlisting}[caption={somme d'entiers en récursif (Sage)}]
sage: def add(x,y):
....:   if x==0 : return y
....:   else : return add((x-1),y)+1
....: 
sage: add(3,4)
7
\end{lstlisting}


% \medskip

% Pour la multiplication~:

% \caml
% \begin{lstlisting}
% # let rec mult = function
%       (0,x) -> 0
%   |   (x,y) -> add(mult(x-1,y),y);;
% \end{lstlisting}

% C'est-à-dire~:~$0\times x=0$ et $x\times y=\big((x-1)\times y\big)+y$


% C'est mathématique...




\section{Alors : avec ou sans affectation~?} 


Beaucoup de  professeurs (et donc  d'élèves...) sont habitués  à traiter
certains    problèmes   à    l'aide   d'un    tableur...qui   fonctionne
récursivement~!

En   effet,  pour   étudier  par   exemple  les   termes  de   la  suite
$u_{n+1}=3u_n+2$ de $n=1$ à $n=30$ avec $u_1=7$, on entre $=7$ dans la cellule $A1$
et $=3*A29+2$ dans la cellule $A30$ et on \og
fait  glisser\fg{} de la  cellule $A30$  jusqu'à la  cellule $A2$.  On a
plutôt l'habitude de faire glisser vers le bas mais pourquoi pas vers le
haut~!

Passer  d'un  \og  faire   glisser\fg{}  à  l'écriture  de  l'algorithme
correspondant  est une  évolution naturelle  ce que  l'introduction d'un
langage impératif n'est pas.

La  notion de  fonction est  naturellement illustrée  par l'utilisation
d'un  langage   fonctionnel  alors  que  les   procédures  des  langages
impératifs peuvent prêter à confusion.

\medskip

Comme  de nombreux  collègues,  j'assure des  \og  colles MAPLE\fg{}  en
classes préparatoires scientifiques  depuis plusieurs années. Les élèves
de ces  classes ont habituellement un niveau  en mathématiques supérieur
au niveau moyen rencontré en Seconde et pourtant la plupart des étudiants
éprouve de  réelles difficultés à maîtriser un  langage de programmation
impératif  comme MAPLE  et certains  n'y  arrivent pas  après une  année
d'initiation~!


Évidemment, nous  n'aborderons pas les mêmes problèmes en Seconde
mais pouvoir se concentrer  sur les mathématiques et simplement traduire
nos idées  grâce au clavier de  manière assez directe  nous permettra de
préserver nos  élèves de nombreux  pièges informatiques sans  parler des
notions trompeuses que l'affectation peut introduire dans leurs esprits.


Cependant, utiliser des algorithmes  récursifs nécessite de maîtriser un
tant soit peu...  la notion de récurrence. Or cette étude a été réservée
jusqu'à maintenant aux  seuls élèves de Terminale S.  L'étude des suites
débute depuis de nombreuses années en Première et chaque professeur a fait
l'expérience des difficultés des élèves à maîtriser cette notion.

Ainsi, même si  (ou plutôt parce que) les  algorithmes récursifs peuvent
apparaître   proches  des   notions   mathématiques  qu'ils   permettent
d'étudier, ils demandent de comprendre une notion mathématique délicate,
la récurrence,  même si l'étude  des phénomènes évolutifs  modélisés par
une  relation   $u_{n+1}=f(u_n)$  a   failli  entrer  au   programme  de
Seconde~!...

Il  faut surtout  noter que  le  champ  d'action des  algorithmes
récursifs  dépasse  largement la  notion  de  suite  numérique. On  peut
raisonner récursivement dès  qu'on connaît un état simple  et qu'on peut
simplifier un état compliqué.

D'un autre côté, les algorithmes utilisant les affectations contournent la difficulté de
la récurrence, facilitent l'étude de certains mécanismes comme le calcul
matriciel, permettent souvent une illustration \og physique\fg{}
d'un phénomène  mathématique et en tous cas  complémentaire des versions
sans affectation.

Ils doivent de plus être étudiés car ils sont largement répandus dans
le monde informatique.



\medskip


Il ne faut enfin pas oublier les difficultés que pourraient rencontrer des
professeurs  de  mathématiques n'ayant  pas  réfléchi  à ces  problèmes
d'algorithmique et  qui ne pourront  pas être formé(e)s avant  de devoir
enseigner une notion méconnue, sans manuels et sans le recul nécessaire.


\medskip

Mais  il ne  faudrait pas  pour autant  abandonner l'idée  d'initier les
élèves à  une \og  algorithmique raisonnée\fg{}. La  notion de  test par
exemple (SI...ALORS...SINON) est tout à fait abordable par le plus grand
nombre... et  dans tout  style de programmation.  La notion  de fonction
peut  être étudiée  sans  danger  avec un  langage  fonctionnel et  avec
prudence avec un langage impératif. D'un point de vue plus informatique,
faire découvrir aux  élèves que le \og dialogue\fg{}  avec la machine ne
se réduit pas à des \og clics\fg{} mais que chacun peut \og parler\fg{}
presque  directement à  la machine  en lui  tapant des  instructions est
également un apprentissage enrichissant.


Quant au match avec ou sans affectation, il ne peut se terminer par
l'élimination d'un des participants~:~il faut savoir que l'un ou l'autre
sera plus adapté à la résolution d'un 
problème et
l'emploi \textbf{combiné}  des deux types de  programmation abordés dans
cet article peut surtout permettre d'illustrer sous des angles différents une
même notion mathématique et  donc illustrer de manière enrichissante nos
cours,
 ce qui induit la nécessité de connaître différentes manières de
procéder pour choisir la plus efficace. Cela accroît d'autant plus la
difficulté d'une introduction improvisée de l'algorithmique au lycée...





Mais les difficultés rencontrées par les
étudiants débutants  de l'enseignement supérieur doivent  nous inciter à
la prudence et à nous demander si un enseignement informatique optionnel
en seconde et plus poussé  dans les classes scientifiques supérieures ne
serait  pas plus souhaitable.  On pourra  lire à  ce sujet  l'opinion de
Bernard \textsc{Parisse}, développeur de XCAS\footnote{\href{http://www-fourier.ujf-grenoble.fr/~parisse/irem.html\#algo}{http://www-fourier.ujf-grenoble.fr/~parisse/irem.html\#algo}}.



% \section{Se passer d'affectation}

% La relation $u_{n+1}=3u_n+2$ valable pour  tout entier naturel $n$ et la
% donnée de $u_0=5$  constituent un algorithme de calcul  récursif de tout
% terme de la suite $(u_n)$.


% Sa traduction  dans des langages sachant  plus ou moins  traiter de tels
% algorithmes est directe. 


% Par exemple, en XCAS cela devient~:


% \begin{lstlisting}
% u(n,uo):={
% if(n==0){return(uo)}
% else{3*u(n-1,uo)+2}
% }
% \end{lstlisting}


% et en CAML~:

% \caml
% \begin{lstlisting}
% # let rec u(n,uo)=
%     if n=0 then uo
%     else 3*u(n-1,uo)+2;;
% \end{lstlisting}

% \xc


% Pour la plupart  des langages, de telles définitions,  qui collent au plus
% près à  la situation mathématique,  limitent les capacités de  calcul de
% l'ordinateur car les diférentes valeurs calculées sont stockées dans une
% \emph{pile}.

% Cela a  entraîné la  création d'algorithmes plus  longs à écrire  et plus
% éloignés  des mathématiques  mais qui  avaient à  l'époque  l'intérêt de
% soulager la  mémoire de l'ordinateur~:~au lieu de  stocker de nombreuses
% valeurs dans une pile, on affecte  une seule case mémoire aux valeurs de
% la suite qui sera \emph{ré-affectée},  au fur et à mesure du déroulement
% du programme.

% Cela donne en XCAS~:


% \begin{lstlisting}
% u_imp(n,uo):={
% local k,temp;
% temp:=uo;
% for(k:=1;k<=n;k:=k+1){
% temp:=3*temp+2;
% }
% return(temp);
% }
% \end{lstlisting}


% Mouais,  bon,  il y  avait  un problème  mathématque  et  s'y ajoute  un
% mécanisme  informatique, l'affectation,  ce qui  ne simplifie  pas notre
% enseignement.

% D'autant plus que la raison d'être informatique de l'affectation - l'économie de mémoire
% -  n'a plus  vraiment  lieu  d'être avec  le  développement de  langages
% fonctionnels très puissants comme CAML qui se débrouillent très bien avec une
% fonction récursive.

% Par  exemple, celle  citée  plus haut  n'est  pas du  tout optimisée  et
% pourtant CAML arrive à calculer $u_{100\,000}$ instantanément mais peine
% pour $u_{1\,000\,000}$.

% XCAS,   avec  l'algorithme  impératif,   calcule  $u_{100\,000}$   en  2
% secondes. N'étant pas  construit pour faire de la  récursion, il peine à
% partir de $u_{3\,000}$ avec l'algorithme récursif.

% On peut  d'ailleurs améliorer largement le programme  récursif pour CAML
% en le  transformant en programme  récursif \emph{terminal}, c'est-à-dire
% tel que l'appel récursif soit direct.

% En  effet, dans  l'algorithme  récursif  précédent, on  a  un schéma  où
% l'appel   récursif  à  la   fonction  est   enveloppé  dans   une  autre
% fonction~:~pour pouvoir calculer  $3u_{n-1}+2$, il faut d'abord calculer
% $u_{n-1}$  et ensuite  lui appliquer  $x\mapsto 3x+2$.  L'appel récursif
% n'est donc pas terminal car il n'est pas effectué en dernier.

% Dans  le cas contraire,  les langages  fonctionnels modernes  comme CAML
% transforment l'appel récursif  en un appel itératif ce  qui économise la
% mémoire  et permet  à l'utilisateur  de  garder une  syntaxe collée  aux
% mathématiques.


% Par exemple, pour  le calcul du PGCD avec  l'utilisation de l'algorithme
% des différences (voir algorithme~\vref{pgcddiff}), on écrit~:

% \caml
% \begin{lstlisting}
% # let rec pgcdif (a,b) =
%         if b=0 
%          then a
%          else  if a>b 
%                 then pgcdif(b,a-b)
%                 else pgcdif(a,b-a);;
% \end{lstlisting}


% L'appel à \verb+pgcddif+ est terminal  est rien ne vient s'accumuler sur
% la pile.

% Lorsque  l'appel  récursif  n'est  pas  terminal,  on  peut  souvent  se
% débrouiller pour qu'il le devienne.




% \begin{lstlisting}
% # let rec u_term(uo,n)=
%     if n=0 then uo
%     else u_term(3*uo+2,n-1);;
% \end{lstlisting}

% La  récursion  est  ici  terminale.  


% On  peut en  fait  généraliser  ce mécanisme  à  n'importe quelle  suite
% définie par une relation $u_{n+1}=f(u_n)$~:



% \begin{lstlisting}
% # let rec suite_rec(f,uo,n)=
%     if n=0 then uo
%     else suite_rec(f,f(uo),n-1);;
% \end{lstlisting}


% \section{Les tours de Hanoï }


% % Une  autre grande  différence entre  la programmation  impérative  et la
% % programmation récursive est de ne  pas se demander \og \emph{comment} ça
% % marche     ?\fg{}     mais     plutôt     \og     \emph{pourquoi}     ça
% % marche ?\fg{} (cf l'ouvrage- de  Xavier
% % \textsc{Leroy} et Pierre \textsc{Weis}\cite{leroy}  pages 28 à 31).

% % L'exemple le  plus célèbre  est la résolution  à l'aide  d'un algorithme
% % récursif  du problème  des  tours  de Hanoï  posé  par le  mathématicien
% % français Édouard \textsc{Lucas} en 1883.

% % Le  jeu  consiste  en  une  plaquette  de bois  où  sont  plantés  trois
% % piquets. Au  début du jeu, $n$  disques de diamètres croissant  de bas en
% % haut sont placés  sur le piquet de  gauche. Le but du jeu  est de mettre
% % ces disques dans le même ordre sur le piquet de droite en respectant les
% % règles suivantes~:

% % \begin{itemize}
% % \item on ne déplace qu'un disque à la fois~;
% % \item on ne peut poser un disque que sur un disque de diamètre supérieur.
% % \end{itemize}


% % Essayez avec 2 puis 3 disques...  Je n'ose pas vous demander de résoudre
% % le problème avec 4 disques~!

% % Pourtant,  en réfléchissant  récursivement, c'est  enfantin~!~!  Il nous
% % faut donc régler un cas simple et pouvoir simplifier un cas compliqué.

% % \begin{itemize}
% % \item \emph{cas simple}~: s'il y a zéro disque, il n'y a rien à faire~!
% % \item \emph{simplification d'un cas  compliqué}~: nous avons $n$ disques
% %   au départ  sur le premier  disque. Appelons A,  B et C les  piquets de
% %   gauche à droite. Il suffit de déplacer les $n-1$ disques supérieurs de
% %   A vers B puis  on déplace le plus gros disque resté sur  A en C. Il ne
% %   reste plus qu'à déplacer vers C les $n-1$ disques qui étaient en B.
% % \end{itemize}

% % On voit bien  la récursion~:~le problème à $n$ disques  est résolu si on
% % sait résoudre le cas à $n-1$ disques  et on sait quoi faire quand il n'y
% % a plus de disques.

% % Il  ne   reste  plus  qu'à   l'écrire  (d'après la solution  proposée   par  Xavier
% % \textsc{Leroy} et Pierre \textsc{Weis}\cite{leroy})~:

% % \caml

% % On commence par créer une fonction qui affichera le mouvement effectué~:

% % \begin{lstlisting}
% % let mvt depart arrivee=
% % print_string
% % ("Deplace un disque de la tige "^depart^" vers la tige "^arrivee);
% % print_newline();;
% % \end{lstlisting}


% % Le programme proprement dit~:

% % \begin{lstlisting}
% % let rec hanoi a b c= function
% %    | 0 -> ()  (*0 disque : on ne fait rien*)
% %    | n -> hanoi a c b (n-1); (*n-1 disques sont places dans l'ordre de a vers b*)
% %           mvt a c; (*on deplace le disque restant en a vers c*)
% %           hanoi b a c (n-1)  (*n-1 disques sont places dans l'ordre de b vers c*);;
% % \end{lstlisting}

% % Les phrases entre \verb+(*+ et \verb+*)+ sont des commentaires.


% % Par exemple, dans le cas de 3 disques~:

% % \begin{lstlisting}
% % # hanoi "A" "B" "C" 3;;
% % Deplace un disque de la tige A vers la tige C
% % Deplace un disque de la tige A vers la tige B
% % Deplace un disque de la tige C vers la tige B
% % Deplace un disque de la tige A vers la tige C
% % Deplace un disque de la tige B vers la tige A
% % Deplace un disque de la tige B vers la tige C
% % Deplace un disque de la tige A vers la tige C
% % - : unit = ()
% % \end{lstlisting}

% % On ne sait pas \emph{comment} l'ordinateur a procédé dans cet ordre mais on sait \emph{pourquoi}....

% \subsection{Le principe}

% Ce casse-tête a été posé  par le  mathématicien
% français Édouard \textsc{Lucas} en 1883.

% Le  jeu  consiste  en  une  plaquette  de bois  où  sont  plantés  trois
% piquets. Au  début du jeu, $n$  disques de diamètres croissant  de bas en
% haut sont placés  sur le piquet de  gauche. Le but du jeu  est de mettre
% ces disques dans le même ordre sur le piquet de droite en respectant les
% règles suivantes~:

% \begin{itemize}
% \item on ne déplace qu'un disque à la fois~;
% \item on ne peut poser un disque que sur un disque de diamètre supérieur.
% \end{itemize}


% Essayez avec 2 puis 3 disques...  Nous n'osons pas vous demander de résoudre
% le problème avec 4 disques~!



% \subsection{Non pas comment mais pourquoi~:~version récursive}

%  En  réfléchissant récursivement,  c'est enfantin~!...  Pour  définir un
%  algorithme récursif, il nous
% faut régler un cas simple et pouvoir simplifier un cas compliqué.


% \begin{itemize}
% \item \emph{cas simple}~: s'il y a zéro disque, il n'y a rien à faire~!
% \item \emph{simplification d'un cas  compliqué}~: nous avons $n$ disques
%   au départ  sur le premier disque  et nous savons  résoudre le problème
%   pour $n-1$ disques. Appelons A, B et C les piquets de
%   gauche à droite. Il suffit de déplacer les $n-1$ disques supérieurs de
%   A vers B (hypothèse de récurrence) puis on déplace le plus gros disque resté sur A en C. Il ne
%   reste  plus qu'à  déplacer vers  C les  $n-1$ disques  qui  étaient en
%   B. (hypothèse de récurrence).
% \end{itemize}

% On voit bien  la récursion~:~le problème à $n$ disques  est résolu si on
% sait résoudre le cas à $n-1$ disques  et on sait quoi faire quand il n'y
% a plus de disques. 



% On sait pourquoi  cet algorithme va réussir mais on  ne sait pas comment
% s'y prendre étape par étape.

% On va donc  appeler à l'aide l'ordinateur en  lui demandant d'écrire les
% mouvements effectués à chaque étape.


% \caml

% On commence par créer une fonction qui affichera le mouvement effectué~:

% \begin{lstlisting}
% let mvt depart arrivee=
% print_string
% ("Deplace un disque de la tige "^depart^" vers la tige "^arrivee);
% print_newline();;
% \end{lstlisting}


% Le programme proprement dit~:

% \begin{lstlisting}
% let rec hanoi a b c= function
%    | 0 -> ()  (*0 disque : on ne fait rien*)
%    | n -> hanoi a c b (n-1); (*n-1 disques sont places dans l'ordre de a vers b*)
%           mvt a c; (*on deplace le disque restant en a vers c*)
%           hanoi b a c (n-1) (*n-1 disques sont places dans l'ordre de b vers c*);;
% \end{lstlisting}

% Les phrases entre \verb+(*+ et \verb+*)+ sont des commentaires.


% Par exemple, dans le cas de 3 disques~:

% \begin{lstlisting}
% # hanoi "A" "B" "C" 3;;
% Deplace un disque de la tige A vers la tige C
% Deplace un disque de la tige A vers la tige B
% Deplace un disque de la tige C vers la tige B
% Deplace un disque de la tige A vers la tige C
% Deplace un disque de la tige B vers la tige A
% Deplace un disque de la tige B vers la tige C
% Deplace un disque de la tige A vers la tige C
% - : unit = ()
% \end{lstlisting}

% \subsection{Non pas pourquoi mais comment~:~version impérative}



% Prenez un papier et  un crayon. Dessinez trois piquets A, C  et B et les
% trois disques dans leur position initiale sur le plot A.

% Déplacez alors les disques selon la méthode suivante~:

% \begin{itemize}
% \item  déplacez le  plus petit  disque vers  le plot  suivant  selon une
%   permutation circulaire A-C-B-A ;
% \item un seul des deux autres disques est déplaçable vers un seul piquet
%   possible.
% \end{itemize}

% Réitérez (en  informatique à l'aide de boucles...)  ce mécanisme jusqu'à
% ce que tous les disques soient sur C dans la bonne position.

% On voit donc bien ici comment ça  marche ; il est plus délicat de savoir
% pourquoi on arrivera au résultat.

% Le programme est lui-même  assez compliqué à écrire~:~vous trouverez une
% version en \texttt{C} (235 lignes...) à cette adresse~:

% \begin{center}
%   \href{http://files.codes-sources.com/fichier.aspx?id=38936\&f=HANOI\%5cHANOI.C}{http://files.codes-sources.com/fichier.aspx?id=38936\&f=HANOI\%5cHANOI.C}
% \end{center}





\xc

\chapter{Outils mathématiques basiques}


\section{Valeur absolue}\label{abs}

\subsection{Prérequis}

Test \og si...alors...sinon\fg{}.

\subsection{Algorithme}

On peut définir la valeur absolue  d'un réel $x$ de la manière suivante,
même si ce n'est pas l'usage en seconde~:

\begin{algorithm}[H]
  \caption{valeur absolue}
\Entree{$x$(un réel)}
\Deb{
\eSi{x positif}{\Retour{x}}{\Retour(-x)}
}
\end{algorithm}

\subsection{Traduction XCAS}


\begin{lstlisting}[caption={valeur absolue}]
va(x):={
  si x>0 alors 
    retourne(x) sinon  
    retourne(-x) 
  fsi;  
}
\end{lstlisting}

en anglais~:

\begin{lstlisting}[caption={valeur absolue (VO)}]
va(x):={
  if(x>0){return(x)}
  else{return(-x)}
}
\end{lstlisting}

en plus compact~:

\begin{lstlisting}
va(x):={
ifte(x>0,x,-x)
}
\end{lstlisting}

\subsection{En CAML}

\caml

\begin{lstlisting}[caption={valeur absolue (CAML)}]
# let va(x)=
    if x>0 then x else -x;;
\end{lstlisting}



\subsection{Avec Sage/Python}


\sage


\begin{lstlisting}[caption={valeur absolue (Sage)}]
sage: def va(x):
....:   if x>0 : return x
....:   else : return -x
\end{lstlisting}



\xc
\section{Partie entière}

\subsection{Intérêt}

La partie entière  n'est pas explicitement au programme  de seconde mais
sa  détermination  algorithmique   enrichit  l'étude  des  ensembles  de
nombres.

On peut  définir la  partie entière  d'un réel $x$  comme étant  le plus
grand entier inférieur à $x$.



\subsection{Algorithme récursif}

On part du fait que la  partie entière d'un nombre appartenant à $[0;1[$
est nulle.

Ensuite, on \og  descend \fg{} de $x$ vers  0 par pas de 1  si le nombre
est positif en montant que $\lfloor x\rfloor=1+\lfloor x-1\rfloor$.

Si le nombre est négatif, on \og monte\fg{} vers 0 en montrant que $\lfloor x\rfloor=-1+\lfloor x+1\rfloor$.


\subsubsection{Avec XCAS}\label{per}

\begin{lstlisting}[caption={partie entier en récursif}]
partie_entiere_rec(r):={
  si(r>=0) et (r<1) 
      alors 0
      sinon si r>0
            alors 1+partie_entiere_rec(r-1)
            sinon -1+partie_entiere_rec(r+1)
            fsi       
      fsi
}:;
\end{lstlisting}

En anglais~:

\begin{lstlisting}[caption={partie entière en récursif (VO)}]
partie_entiere_rec(r):={
  if((r>=0) and (r<1)){0}
  else{if(r>0){1+partie_entiere_rec(r-1)}
       else{-1+partie_entiere_rec(r+1)}       
      }
}:;
\end{lstlisting}

\subsubsection{Avec CAML}

\caml
\begin{lstlisting}[caption={partie entière en récursif (CAML)}]
# let rec partie_entiere (r)
        =
        if r >= 0. && r < 1.
         then 0.
         else if r > 0.
               then   1. +. partie_entiere (r -. 1.) 
	       else -.1. +. partie_entiere (r +. 1.)

\end{lstlisting}




\subsubsection{Avec Sage/Python}



Avec Sage/Python:

\sage

\begin{lstlisting}[caption={partie entière récursive avec Sage}]
sage: def partie_entiere(x):
....:   if x>=0 and x<1 : return 0
....:   elif x>0 : return 1+partie_entiere(x-1)
....:   else : return -1+partie_entiere(x+1)
\end{lstlisting}






\xc


\subsection{Algorithme impératif}





On peut  commencer par se restreindre  aux nombres positifs.  On part de
0.  Tant qu'on  n'a  pas dépassé  $x$,  on avance  d'un  pas. La  boucle
s'arrête dès  que $k$ est strictement  supérieur à $x$.  La partie entière
vaut donc $k-1$.



\begin{algorithm}[H]
\caption{partie entière d'un nombre positif}
\Entree{$x$(réel positif)}\;
\Ini{k \aff 0}\;
\Deb{
\Tq{k<=x}{k\aff k+1}\;
\Retour{k-1}
}
\end{algorithm}




Dans le  cas d'un réel  négatif, il faut  cette fois reculer d'un  pas à
chaque tour de boucle et la partie entière est la première valeur de $k$
à être inférieure à $x$~:


\begin{algorithm}[H]
\caption{partie entière d'un réel quelconque}
\Entree{$x$(réel)}\;
\Ini{k \aff 0}\;
\Deb{
eSi{
\Tq{k<=x}{k\aff k+1}\;
\Retour{k-1}
}{
\Tq{k>x}{k\aff k-1}\;
\Retour{k}
}
}
\end{algorithm}


\subsubsection{Traduction XCAS}

\begin{lstlisting}[caption={partie entière en impératif}]
pe(x):={
local k;
k:=0;
si x>=0 alors
   tantque k<=x faire
      k:=k+1;
   ftantque;
   retourne(k-1);
sinon 
   tantque k>x faire
      k:=k-1;
   ftantque;
   retourne(k); 
fsi;  
}:;
\end{lstlisting}

En anglais~:



\begin{lstlisting}[caption={partie entière en impératif (VO)}]
pe(x):={
local k;
k:=0;
if(x>=0){
   while(k<=x){k:=k+1};
   return(k-1);
        }
else{
   while(k>x){k:=k-1};
   return(k); 
    } 
}:;
\end{lstlisting}



\subsubsection{Avec Sage/Python}


\sage

\begin{lstlisting}[caption={partie entière impérative (Sage/Python)}]
>>> def pe(x):
     k=0
     if x>=0:
         while k<=x : k+=1
         return k-1
     else :
         while k>x : k+=-1
         return k
\end{lstlisting}


\section{Arrondis}


On veut arrondir un nombre réel à $10^{-2}$ près par défaut.  

\subsection{Algorithme}

On va
prendre la partie entière (avec l'algorithme créé précédemment) du nombre multiplié par $10^2$ puis le
rediviser par $10^{2}$~:

\begin{algorithm}[H]
              \caption{arrondi}
              \Entree{$x$(réel)}\;
              \Deb{
\Retour{(partie entière de $100x$) divisée par 100}
} 
               \end{algorithm}


\subsection{Traduction XCAS}
\xc
\begin{lstlisting}[caption={arrondi au centième}]
arrondi(x):={
retourne(pe(100*x)/100.0)
}
\end{lstlisting}


\subsection{Traduction CAML}


\caml
\begin{lstlisting}[caption={arrondi au centième avec CAML}]
let arrondi_au_100_eme_par_defaut (r)
    =
    partie_entiere (100. *. r) /. 100.
\end{lstlisting}

\xc

\section{Variante}

On veut arrondir  à $10^{-2}$ près par défaut si  la partie décimale est
strictement inférieure à 0,5 et à $10^{-2}$ près par excès si la partie décimale est
 supérieure à 0,5.

La recherche de la partie décimale peut poser des problèmes. On commence
donc par traiter le cas des nombres positifs~:

\begin{algorithm}[H]
              \caption{arrondi au plus proche}
              \Entree{$x$(réel positif)}\;
             
\Ini{deci\aff  ($x$ $-$  partie entière de $x$)}\;
 \Deb{
\eSi{deci < 0,5}{\Retour{(partie entière de $100x$) divisée par 100}}{
\Retour{0,01+(partie entière de $100x$) divisée par 100}
}
} 
               \end{algorithm}

On peut  ensuite chercher à généraliser à  un réel quelconque~:~beaucoup
d'élèves devraient se tromper ici...ce qui est formateur~!


\section{Calculs de sommes}

On veut par exemple calculer la somme des entiers de 1 à n.


\subsection{Algorithme récursif}

\subsubsection{Avec XCAS}

\begin{lstlisting}[caption={somme des entiers en récursif}]
som_ent(n):={
if(n==0){0}
else{n+som_ent(n-1)}
}:;
\end{lstlisting}


\subsubsection{Avec CAML}

\caml

\begin{lstlisting}[caption={somme des entiers en récursif avec CAML}]
# let rec som_ent(n)=
     if n=0 then 0
     else n+som_ent(n-1);;
\end{lstlisting}
 

Par exemple~:

\begin{lstlisting}
# som_ent(100000);;
- : int = 705082704
\end{lstlisting}


On pense bien sûr à généraliser cette procédure à n'importe quelle somme
du type $\ds\sum_{k=k_0}^nf(k)$~:


\begin{lstlisting}[caption={somme  des   images  des  entiers   par  une
fonction (CAML)}]
# let rec som_rec(f,ko,n)=
     if n=ko then f(ko)
     else f(n)+som_rec(f,ko,n-1);;
\end{lstlisting}


\subsubsection{Avec SAGE}


\sage

\begin{lstlisting}[caption={somme des entiers avec Sage}]
sage: def som_ent(n):
....:   if n==1 : return 1
....:   else : return n+som_ent(n-1)
\end{lstlisting}



\begin{lstlisting}[caption={somme des images des entiers par une fonction avec Sage}]
sage: def som_rec(f,ko,n):
....:    if n==ko : return f(ko)
....:    else : return f(n)+som_rec(f,ko,n-1)
\end{lstlisting}




\xc

\subsection{Algorithme impératif}


\begin{algorithm}[H]
\caption{somme des entiers de 1 à n}
\Entree{$n$(entier naturel)}\;
\Ini{S\aff 0\tcp{la somme est nulle au départ}}\;
\Deb{
\Pour{k de 1 à n}{S\aff S+k}
\Retour{S}
 } 
\end{algorithm}


\subsubsection{Avec XCAS}

\begin{lstlisting}[caption={somme des entiers en impératif}]
som(n):={
local S;
S:=0;
pour k de 1 jusque n faire
  S:=S+k;
fpour;
retourne(S)
}
\end{lstlisting}


en anglais~:

\begin{lstlisting}[caption={somme des entiers en impératif (VO)}]
som(n):={
local S;
S:=0;
for(k:=1;k<=n;k:=k+1){S:=S+k};
return(S)
}
\end{lstlisting}



\subsubsection{Avec Sage}


\sage

\begin{lstlisting}[caption={somme des entiers version impérative avec Sage}]
sage: def som(n):
....:   S=0
....:   for k in [1..n] : S+=k
....:   return S
\end{lstlisting}


\section{Mini et maxi}


\subsection{Version récursive}

Un   petit    travail   sur    les   valeurs   absolues    définies   au
paragraphe~\vref{abs} permet de montrer que~:

\[{\rm max}(x,y)=\frac{x+y+|x-y|}{2}\qquad {\rm min}(x,y)=\frac{x+y-|x-y|}{2}\]

Maintenant, on voudrait trouver les extrema d'une liste de nombres. 


\begin{algorithm}[H]
\caption{maxi(liste)}
\eSi{liste n'a que deux éléments\;}
    {max(les deux éléments)}
    {max(tête de liste,maxi(liste sans sa tête))}
\end{algorithm}


Avec CAML,  on utilise \texttt{List.hd} qui donne  la tête, c'est-à-dire
le premier élément d'une liste,  et \texttt{List.tl} qui donne sa queue,
c'est-à-dire la liste privée de sa tête~:

\caml
\begin{lstlisting}[caption={maximum d'une liste en récursif (1)}]
# let absi(x)=
      if x>0 then x
      else -x;;

    val absi : int -> int = <fun>

# let maxi(x,y)=
      (x+y+absi(x-y))/2;;

  val maxi : int * int -> int = <fun>

# let rec maxlist(lx)=
  if List.tl(List.tl(lx))=[]
   then maxi(List.hd(lx),List.hd(List.tl(lx)))
  else maxi(List.hd(lx),maxlist(List.tl(lx)));;

      val maxlist : int list -> int = <fun>

# maxlist([1;2;3;54;5;3;8;7;98;7;4;2;9]);;

- : int = 98
\end{lstlisting}



Voici une variante évitant le recours au module \og \texttt{List}\fg{}~:

\begin{lstlisting}[caption={maximum d'une liste en récursif (2)}]
# let rec maxilist = function
        | x::y::[] -> maxi(x,y)
        | x::queue -> maxi(x,maxilist(queue));;
\end{lstlisting}

Quand  on écrit  \verb+x::y::[]+,  CAML comprend  qu'on  a rajouté  deux
éléments à la liste vide~:~il s'agit donc d'une liste de deux éléments...



Voici  une variante  sans utiliser  \texttt{maxi}  et en  créant un  \og
garde-fou\fg{}~:

\begin{lstlisting}[caption={maximum d'une liste en récursif (3)}]
# exception Liste_vide;;

# let rec maxbis = function
  | [] -> raise Liste_vide
  | x::[] -> x
  | x::y::queue -> if x>y then maxbis(x::queue)
                          else maxbis(y::queue);;
\end{lstlisting}



\xc


Avec XCAS~:


\begin{lstlisting}[caption={maximum d'une liste en récursif (XCAS)}]
maxlist(lx):={
 if(size(lx)==2)
   then{maxi(lx[0],lx[1])}
   else{maxi(lx[0],maxlist(tail(lx)))}
}:;
\end{lstlisting}


Avec Sage/Python:

\sage
\begin{lstlisting}[caption={maximum d'une liste en récursif (Sage)}]
sage: def maxbis(lx):
....:   if len(lx)==1 : return lx[0]
....:   elif lx[0]>lx[1] : del lx[1]; return maxbis(lx);
....:   else : del lx[0]; return maxbis(lx);
....: 
sage: maxbis([1,2,-1,6,87,2,-10])
87
\end{lstlisting}




\subsection{Version impérative}



\begin{algorithm}[H]
\caption{maximum : version impérative}
\Entree{liste}\;
\Ini{maxloc\aff tête de la liste}\;
\Deb{
\Pour{k de 1 jusqu'à la taille de la liste}
     {maxloc\aff le plus grand entre maxloc et k-eme élément de la liste}
 }
\Retour{maxloc} 
\end{algorithm}


Avec XCAS~:

\xc

\begin{lstlisting}[caption={maximum d'une liste en impératif (XCAS)}]
maxlist_imp(lx):={
local maxloc,k;
maxloc:=lx[0];
  for(k:=1;k<size(lx);k:=k+1){
    maxloc:=maxi(maxloc,lx[k])
  }
return(maxloc)
}:;
\end{lstlisting}


\sage
\begin{lstlisting}[caption={maximum d'une liste en impératif (Sage)}]
sage: def max_imp(lx):
....:   maxloc=lx[0]
....:   for k in [1..len(lx)-1]:
....:      if lx[k]>maxloc : maxloc=lx[k]
....:   return(maxloc)
\end{lstlisting}


\chapter{Algorithmes de calculs \og à la STG\fg{}}

Les sections STG sont initiées  à l'algorithmique en travaillant sur des
problèmes simples de gestion.


\section{Taux de remise variable}

On entre un montant HT $ht$. On effectue une remise sur $ht$ selon la
régle suivante~:
\begin{itemize}
\item si $ht<2500$\texteuro{} alors il n'y a pas de remise~;
\item si $2500\leqslant ht<4000$\texteuro{} alors la remise est de 5\%~;
\item dans les autres cas la remise est de 8\%.
\end{itemize}

La TVA est de 19,6\%. On demande le prix TTC en fonction du prix HT.

\subsection{Algorithme}



\begin{algorithm}[H]
\caption{prix TTC selon remise}
\Entree{HT(réel positif)}\;
\Ini{ht\aff HT}\;
\Deb{
\Si{ht>=2500 et ht<4000}{ht\aff ht$\times$ 0,95}
\Si{ht>=4000}{ht\aff ht$\times$0,92}
\Retour{ht$\times 1.196$}
 } 
\end{algorithm}

\subsection{Avec XCAS}
\xc

\begin{lstlisting}[caption={taux de remise variable en impératif}]
remise(HT):={
local ht;
ht:=HT;
si (ht>=2500) et (ht<4000) alors ht:=ht*0.95; fsi;
si ht>=4000 alors ht:=ht*0.92; fsi;
retourne(ht*1.196)
 }
\end{lstlisting}



En anglais~:


\begin{lstlisting}[caption={taux de remise variable en impératif (VO)}]
remise(HT):={
local ht;
ht:=HT;
 if( (ht>=2500) and (ht<4000)){ht:=ht*0.95};
 if(ht>=4000){ht:=ht*0.92};
return(ht*1.196)
 }
\end{lstlisting}



\subsection{Avec CAML}


\caml
\begin{lstlisting}[caption={taux de remise variable en récursif (CAML)}]
let prix_ttc_apres_remise (prix_hors_taxe)
    =
    let
     taux_remise = if prix_hors_taxe < 2500.
                    then 0.
                    else if prix_hors_taxe < 4000.
                          then 0.05
                          else 0.08
    in
     (1. -. taux_remise) *. prix_hors_taxe *. 1.196

\end{lstlisting}


On  remarque au passage  comment définir  une fonction  locale imbriquée
dans une autre fonction.


\sage




\subsection{Avec Sage}


\begin{lstlisting}[caption={taux de remise variable  (Sage)}]
sage: def remise(HT):
....:   ht=HT
....:   if ht>=2500 and ht<4000 : ht=ht*0.95
....:   if ht>=4000 : ht=ht*0.92
....:   return ht*1.196
\end{lstlisting}




\xc

\chapter{Algorithmes en arithmétique}



\section{Division euclidienne}

\subsection{Quotient de la division euclidienne}

\subsubsection{  Version récursive}


\begin{algorithm}[H]
\caption{Quatient de la division euclidienne : version récursive}
reste(a,b)\;
\Deb{
\Si{a<b}{\Retour{0}}
 } 
\Retour{1+quotient(a-b,b)}
\end{algorithm}


\subsubsection{  Avec XCAS}

\begin{lstlisting}[caption={quotient euclidien en récursif (XCAS)}]
quotient(a,b):={
if(a<b){return(0)};
return(1+quotient(a-b,b));
}
\end{lstlisting}


\subsubsection{Avec Sage}

\sage

\begin{lstlisting}[caption={quotient euclidien en récursif (Sage)}]
sage: def quotient(a,b):
....:   if a<b : return 0
....:   return 1+quotient(a-b,b)
\end{lstlisting}
\subsubsection{  Avec CAML}

\caml

\begin{lstlisting}[caption={quotient euclidien en récursif (CAML)}]
# let rec quotient (a,b)
        =
        if a<b 
         then 0
         else  1+quotient(a-b,b);;
\end{lstlisting}

\xc


\begin{figure}[!h]
  \begin{Remarque}[reste et quotient en CAML]
    CAML étant intelligemment typé, si on entre~:

\verb+ # 37/5;;+

On obtient

\verb+- : int = 7+

c'est-à-dire par  défaut le  quotient entier car  on travaille  avec des
entiers.

Pour avoir une approximation décimale, il faut entrer~:

\verb+ # 37./.5.;;+

et on obtient~:

\verb+- : float = 7.4+

Pour le reste, on peut donc entrer~:

\verb+ # 37-37/5*5;;+

ou utiliser la commande infixée \verb+ mod +

\verb+ # 37 mod 2 ;;+
    \end{Remarque}
  \end{figure}


\subsubsection{  Version impérative}


\begin{algorithm}[H]
\caption{Quotient de la division euclidienne}
\Entree{2 entiers a et b}\;
\Deb{
\Ini{k\aff 0}\;
\Tq{$k\times b\leqslant a$}{k\aff k+1}
 } 
\Retour{k-1}
\end{algorithm}


\subsubsection{  Avec  XCAS}

\begin{lstlisting}[caption={quotient euclidien en impéartif (XCAS)}]
quotient(a,b):={
local k;
k:=0;
while(k*b<=a){k:=k+1}
return(k-1)
}
\end{lstlisting}

\subsubsection{Avec Sage}

\sage

\begin{lstlisting}[caption={quotient euclidien en impéartif (Sage)}]
sage: def quotient(a,b):
....:   k=0
....:   while k*b<=a : k+=1
....:   return(k-1)
\end{lstlisting}


\subsection{Reste de la division euclidienne}

\subsubsection{  Version récursive}


\begin{algorithm}[H]
\caption{Reste de la division euclidienne : version récursive}
reste(a,b)\;
\Deb{
\Si{a<b}{\Retour{a}}
 } 

\Retour{reste(a-b,b)}
\end{algorithm}

\xc
\subsubsection{ Version récursive  avec XCAS}

\begin{lstlisting}[caption={reste euclidien en récursif}]
reste(a,b):={
if(a<b){return(a)};
return(reste(a-b,b));
}
\end{lstlisting}

\subsubsection{  Version récursive avec CAML}

\caml

\begin{lstlisting}[caption={reste euclidien en récursif (CAML)}]
# let rec reste (a,b)
        =
        if a<b 
         then a
         else  reste(a-b,b);;
\end{lstlisting}




\subsubsection{Version récursive avec Sage/Python}






\sage
\begin{lstlisting}[caption={reste euclidien en récursif (Sage)}]
sage: def reste(a,b):
....:   if a<b : return a
....:   return reste(a-b,b)
\end{lstlisting}








\xc

\subsubsection{  Version impérative}


\begin{algorithm}[H]
\caption{Reste de la division euclidienne : version impérative}
\Entree{2 entiers a et b}\;
\Deb{
\Ini{k\aff 0}\;
\Tq{$k\times b\leqslant a$}{k\aff k+1}
 } 
\Retour{$a-b(k-1)$}
\end{algorithm}


\subsubsection{  Version impérative avec XCAS}

\begin{lstlisting}[caption={reste euclidien en impératif (XCAS)}]
reste(a,b):={
local k;
k:=0;
while(k*b<=a){k:=k+1}
return(a-b*(k-1))
}
\end{lstlisting}


\subsubsection{Version impérative avec Sage/Python}

\sage
\begin{lstlisting}[caption={reste euclidien en impératif (Sage)}]
sage: def reste(a,b):
....:   k=0
....:   while k*b<=a : k+=1
....:   return a-b*(k-1)
\end{lstlisting}



\subsection{Divisibilité}


On peut créer une fonction qui testera si un nombre divise un autre.


\begin{algorithm}[H]
\caption{Test de divisibilité}
\Entree{2 entiers n et p}\;
\Deb{
(quotient entier n/p)$\times$ p == n
 } 
\end{algorithm}

On effectue  un test booléen  en utilisant l'opérateur  infixe \verb+==+
qui désigne la relation d'égalité. La réponse du programme sera donc \og
vrai\fg{} ou  \og faux\fg{} ( \og 1\fg{}  ou \og 0\fg{} sur  XCAS et \og true\fg{}  ou \og
false\fg{} sur CAML)


\subsubsection{  Avec XCAS}
\xc
\begin{lstlisting}[caption={divisibilité (XCAS)}]
divise(p,n):={iquo(n,p)*p=n}:;
\end{lstlisting}

\subsubsection{  Avec CAML}

\caml
\begin{lstlisting}[caption={divisibilité (CAML)}]
# let divise p n = ((n/p)*p=n);;
\end{lstlisting}

Qui s'utilise ainsi~:

\begin{lstlisting}
# divise 4 13;;
- : bool = false
# divise 4 12;;
- : bool = true
\end{lstlisting}



\subsubsection{Avec Sage/Python}

\sage

\begin{lstlisting}[caption={divisibilité (Sage)}]
sage: def divise(p,n):
....:   return (n//p)*p==n
....: 
sage: divise(3,37)
False
sage: divise(3,36)
True
\end{lstlisting}






\section{Nombre de diviseurs d'un entier}


\subsection{Version récursive avec CAML}


Une méthode  naïve consisterait  à tester tous  les entiers  jusqu'à $n$
pour compter les diviseurs de $n$~:
\caml

\begin{lstlisting}[caption={nombre de diviseurs en récursif (1)}]
# let nombre_div(a)=
      let rec nombre_div_local(a,n)=
          if n>a/2 
            then 1
            else if a mod n = 0 
                    then 1+nombre_div_local(a,n+1)
	            else nombre_div_local(a,n+1)
      in nombre_div_local(a,1);;
\end{lstlisting}

Par exemple, $\nombre{123456789}$ admet 12 diviseurs~:

\begin{lstlisting}
# nombre_div(123456789);;
- : int = 12
\end{lstlisting}

On peut  facilement être plus  efficace en remarquant que  les diviseurs
marchent par deux~!

\begin{lstlisting}[caption={nombre de diviseurs en récursif (2)}]
# let nombre_div(a)=
    let rec nombre_div_local(a,n)=
          if n*n>a 
            then 1
            else if n=1 or (a mod n=0 & n=a/n)
                 then 1+nombre_div_local(a,n+1)
                 else if a mod n = 0 
                      then 2+nombre_div_local(a,n+1)
	              else nombre_div_local(a,n+1)
      in nombre_div_local(a,1);;
\end{lstlisting}

Pour $\nombre{999999999}$~:

\begin{lstlisting}
# nombre_div(999999999);;
- : int = 20
\end{lstlisting}

\subsection{Version impérative }


\subsubsection{Avec XCAS}

Méthode  naïve~:
\xc
\begin{lstlisting}[caption={nombre de diviseurs en impératif (1) XCAS}]
NbDivNaif(x):={
local t,k; 
  t:=0;  
  pour k de 1 jusque x pas 1 faire
      si irem(x,k)==0 alors t:=t+1
      fsi 
  fpour
  retourne(t) 
}:; 
\end{lstlisting}



Il faut  alors plus de 7  minutes pour compter  les diviseurs de
$100010010$ (mille cent dix :-) )

Plus efficacement~!

\begin{lstlisting}[caption={nombre de diviseurs en impératif (2) XCAS}]
NbDiv(n):={
local t,k,fin;
t:=2;
fin:=n;
pour k de 2 jusque fin pas 1 faire
   si irem(n,k)==0 alors 
      fin:=n/k;
      si k==fin alors t:=t+1 sinon t:=t+2
      fsi
   fsi
fpour
retourne(t)
}:;
\end{lstlisting}



Ensuite, on peut avoir une représentation graphique~:

\begin{lstlisting}[caption={représentation graphique du nombre de diviseurs (XCAS)}]
Graphe_NbDiv(a,b):={
local P,k;
P:=NULL;
 pour k de a jusque b pas 1 faire
  P:=P,[k,NbDiv(k)]
 fpour
affichage(nuage_points([P]),point_point+epaisseur_point_3)
}:;
\end{lstlisting}

Entre 0 et 100 cela donne~:


\begin{figure}
\begin{center}
  \includegraphics{NbDiv}
\end{center}
\end{figure}




\subsubsection{Avec Sage}


\sage

Méthode naïve:
\begin{lstlisting}[caption={nombre de diviseurs en impératif (1) Sage}]
sage: def NbDivNaif(n):
....:   t=0
....:   for k in [1..n] :
....:      if n%k==0 : t+=1
....:   return t
....: 
sage: NbDivNaif(1000100)
36
\end{lstlisting}

Méthode plus rapide:

\begin{lstlisting}[caption={nombre de diviseurs en impératif (2) Sage}]
sage: def NbDiv(n):
....:   t=2
....:   fin=n 
....:   k=2
....:   while k<fin :
....:      if n%k==0 :
....:         fin=n//k;
....:         if k==fin : t+=1
....:         else : t+=2
....:      k+=1
....:   return t
\end{lstlisting}


Et on obtient instantanément:

\begin{lstlisting}[caption={}]
sage: NbDiv(100010010)
32
\end{lstlisting}


Pour le tracé:

\begin{lstlisting}[caption={représentation graphique du nombre de diviseurs(Sage)}]
sage: def plot_NbDiv(a,b):
....:   P=[]
....:   for k in [a..b]:
....:      P.append([k,NbDiv(k)])
....:   p=point(P)
....:   p.show()
\end{lstlisting}


%\begin{figure}
\begin{center}
  \includegraphics{plot_NbDiv}
\end{center}
%\end{figure}




\section{Nombres parfaits}

Un nombre parfait  est un nombre entier $n$  strictement supérieur à $1$
qui est égal à la somme de ses diviseurs (sauf $n$ bien sûr~!)


On peut adapter les programmes précédents.

\subsection{En récursif avec CAML}


\caml

\begin{lstlisting}[caption={liste des diviseurs en récursif (1)}]
# let liste_div(a)=
      let rec liste_div_n(a,n)=
          if n>a/2 
            then []
            else if a mod n = 0 
                    then n::liste_div_n(a,n+1)
	            else liste_div_n(a,n+1)
      in liste_div_n(a,1);;
\end{lstlisting}


donne la liste des diviseurs.


\begin{lstlisting}
# liste_div(240);;
- : int list =
[1; 2; 3; 4; 5; 6; 8; 10; 12; 15; 16; 20; 24; 30; 40; 48; 60; 80; 120]
\end{lstlisting}

On  crée ensuite  une fonction  qui calcule  la somme  des  termes d'une
liste~:

\begin{lstlisting}[caption={somme des termes d'une liste en récursif (1)}]
# let rec somme=function
  | []-> 0
  | tete::queue -> tete + somme(queue);;
\end{lstlisting}

Puis on teste si un nombre est parfait :

\begin{lstlisting}[caption={nombres parfaits}]
# let parfait(a)=
      somme(liste_div(a))=a;;
\end{lstlisting}

Ocaml répond \og vrai\fg{} ou \og faux\fg{}~:


\begin{lstlisting}
# parfait(8128);;
- : bool = true
\end{lstlisting}



On aurait pu  être plus efficace en utilisant  des algorithmes terminaux
et en remarquant que les diviseurs  vont souvent 2 par 2 et qu'il suffit
de s'arrêter après la partie entière de $\sqrt{n}$~:


\begin{lstlisting}[caption={liste des diviseurs d'un entier (2)}]
#  let liste_div(a)=
    let rec liste_div_n(a,n,res)=
          if n*n>a 
            then res
            else if n=1 or (a mod n=0 & n=a/n)
                 then liste_div_n(a,n+1,n::res)
                 else if a mod n = 0 
                      then liste_div_n(a,n+1,n::a/n::res)
	              else liste_div_n(a,n+1,res)
      in liste_div_n(a,1,[]);;
\end{lstlisting}

On rend \verb+somme+ terminal~:

\begin{lstlisting}[caption={somme des termes d'une liste en récursif (2)}]
#  let somme(liste)=
     let rec som_temp=function
       | ([],res)-> res
       | (tete::queue,res) -> som_temp(queue,res+tete)
     in som_temp(liste,0);;
\end{lstlisting}


On ne change pas \verb+parfait+~:

\begin{lstlisting}
# let parfait(a)=
      somme(liste_div(a))=a;;
\end{lstlisting}


Par exemple~:


\begin{lstlisting}
#  parfait(33550336);;
- : bool = true
\end{lstlisting}


On peut pousser  le vice jusqu'à demander de créer  la liste des nombres
parfaits entre 0 et un nombre $n$ donné~:

Version non terminale~:


\begin{lstlisting}[caption={liste des nombre parfait en récursif}]
# let rec liste_parfait(n)=
      if n=1 then []
      else if parfait(n) then n::liste_parfait(n-1)
           else liste_parfait(n-1);;
\end{lstlisting}


Version terminale~:

\begin{lstlisting}[caption={liste des nombres parfaits en récursif (version terminale)}]
# let liste_parfait(n)=
    let rec liste_parfait_local(n,res)= 
      if n=1 then res
      else if parfait(n) 
            then liste_parfait_local(n-1,n::res)
            else liste_parfait_local(n-1,res)
    in liste_parfait_local(n,[]);;
\end{lstlisting}

Alors on trouve 4 nombres parfaits entre $0$ et $\nombre{100000}$~:

\begin{lstlisting}
# liste_parfait(100000);;
- : int list = [6; 28; 496; 8128]
\end{lstlisting}

\subsection{En impératif avec XCAS}

On adapte un peu \verb+NbDiv+ pour avoir la liste des diviseurs~:

\xc

\begin{lstlisting}[caption={Liste des diviseurs en impératif}]
ListeDiv(n):={
local L,k,fin;
L:=1,n;
fin:=n;
for(k:=2;k<fin;k:=k+1){
   if(irem(n,k)==0)then{
     fin:=n/k;
     if(k==fin) then{L:=L,k} else{L:=L,k,n/k};}
}
return([L])
}:;
\end{lstlisting}

Une petite retouche pour savoir si un entier est parfait~:

\begin{lstlisting}[caption={nombres parfaits en impératif}]
Parfait(n):={
local S,k,fin;
S:=1;
fin:=n;
for(k:=2;k<fin;k:=k+1){
   if(irem(n,k)==0)then{
     fin:=n/k;
     if(k==fin) then{S:=S+k} else{S:=S+k+n/k};}
}
if(S==n)then{return("Parfait !")}
             else{return("Pas parfait...")}
}:;
\end{lstlisting}

Par exemple~:

\begin{lstlisting}
Parfait(33550336)
\end{lstlisting}

\reponse{Parfait !}

Il ne reste  plus qu'à obtenir la  liste des nombres parfaits de  0 à un
$n$ donné~:

\begin{lstlisting}[caption={liste des nombres parfaits en impératif}]
Liste_parfait(n):={
local k,L;
L:=NULL;
 for(k:=2;k<=n;k:=k+1){
     if(Parfait(k)=="Parfait !")then{L:=L,k}
   }                                 
return([L])
}:;
\end{lstlisting}

\subsection{En impératif avec Sage}

\sage


La liste des diviseurs:

\begin{lstlisting}[caption={liste des diviseurs d'un entier (Sage)}]
sage: def ListeDiv(n):
....:   L=[1,n]
....:   fin=n
....:   k=2
....:   while k<fin :
....:      if n%k==0 :
....:         fin=n//k;
....:         if k==fin : L+=[k]
....:         else : L+=[k,n//k]
....:      k+=1
....:   return L
....: 
sage: ListeDiv(10)
[1, 10, 2, 5]
\end{lstlisting}



Test \og de perfection\fg{}:

\begin{lstlisting}[caption={test entier parfait (Sage)}]
sage: def parfait(n):
....:   if sum(ListeDiv(n))==2*n : return True
....:   else : return False
....: 
sage: parfait(10)
False
sage: parfait(8128)
True
\end{lstlisting}


Liste des nombres parfaits:

\begin{lstlisting}[caption={Liste des entiers parfaits (Sage)}]
sage: def Liste_parfait(n):
....:   L=[]
....:   for k in [2..n]:
....:      if parfait(k) : L+=[k]
....:   return L
....: 
sage: Liste_parfait(10000)
[6, 28, 496, 8128]
\end{lstlisting}


% \section{Algorithme d'Euclide et conséquences}

\section{PGCD}

Nous allons  voir plusieurs  algorithmes pour calculer  le PGCD  de deux
entiers.

\subsection{Version récursive}

Le plus naturel est la version récursive de l'algorithme d'Euclide~:


\begin{algorithm}[H]
\caption{PGCD : version récursive de l'algorithme d'Euclide}
PGCD1(a,b)\;
\Entree{2 entiers a et b}\;
\Deb{
\eSi{b=0}{\Retour{a}}{\Retour{PGCD1(b,reste(a,b))}}
 } 
\end{algorithm}

\subsubsection{  Avec XCAS}
\xc
\begin{lstlisting}[caption={PGCD en récursif (1)}]
PGCD1(a,b):={
if(b==0){return(a)}
else{return(PGCD1(b,irem(a,b)))}
}
\end{lstlisting}


\subsubsection{  Avec CAML}

\caml

\begin{lstlisting}[caption={PGCD en récursif (1) avec CAML}]
# let rec pgcd (a,b)
        =
        if b=0 
         then a
         else  pgcd(b,a-a/b*b);;
\end{lstlisting}


\subsubsection{Avec Sage}

\sage
\begin{lstlisting}[caption={PGCD en récursif (1) avec Sage}]
sage: def pgcd(a,b):
....:   if b==0 : return a
....:   else : return pgcd(b,a%b)
\end{lstlisting}

\xc

\subsection{  Version impérative}

En version impérative, c'est un peu plus long et moins naturel...



\begin{algorithm}[H]
\caption{PGCD : version impérative de l'algorithme d'Euclide}
\Entree{2 entiers a et b}\;
\Deb{
\Tq{$b\neq0$}{
r\aff reste(a,b)\;
a\aff b\;
b\aff r\;
}
 }
\Retour{a} 
\end{algorithm}

\subsubsection{  Avec XCAS}
\xc
\begin{lstlisting}[caption={PGCD en impératif (1) (XCAS)}]
PGCD2(a,b):={
local r;
while(b!=0){
r:=irem(a,b);
a:=b;
b:=r;
}
return(a)
}:;
\end{lstlisting}


\subsubsection{Avec Sage}
\sage
\begin{lstlisting}[caption={PGCD en impératif (1) (Sage)}]
sage: def pgcd2(a,b):
....:   while b!=0 :
....:      r=a%b
....:      a=b
....:      b=r
....:   return a
\end{lstlisting}


\subsection{  Algorithme des différences}

On     peut    également     utiliser    le     fait     que    $a\wedge
b=a\wedge(b-a)=a\wedge(a-b)$, mais c'est plus (beaucoup trop) long...
Une idée de recherche peut être de comparer les deux algorithmes.


\begin{algorithm}[H]
\caption{PGCD par l'algorithme des différences en version récursive}\label{pgcddiff}
PGCD3(a,b)\;
\Entree{2 entiers a et b}\;
\Deb{
\Si{b=0}{\Retour{a}}
\eSi{a>=b}{\Retour{PGCD3(b,a-b)}}{\Retour{PGCD3(a,b-a)}} 

} 
\end{algorithm}


\subsubsection{  Avec XCAS}
\xc

\begin{lstlisting}[caption={PGCD en récursif (2)}]
PGCD3(a,b):={
if(b==0){return(a)}
if(a>=b){return(PGCD3(b,a-b))}
else{return(PGCD3(a,b-a))}
}
\end{lstlisting}


\subsubsection{  Avec CAML}

\caml

\begin{lstlisting}[caption={PGCD en récursif (2) avec CAML}]
let rec pgcdif (a,b)
        =
        if b=0 
         then a
         else  if a>b 
                then pgcdif(b,a-b)
         else pgcdif(a,b-a);;
\end{lstlisting}

\xc

\begin{figure}[!h]
  \begin{Remarque}[Problèmes de pile]
    CAML comme  LISP, HASKEL et  quelques autres sont de  vrais langages
    fonctionnels donc traitent efficacement les récursions.

L'algorithme précédent est très peu  efficace et la pile de XCAS souffre
énormément avec PGCD3(45678,3) alors que ça passe comme une fleur sur CAML...
    \end{Remarque}
  \end{figure}


\sage

\begin{lstlisting}[caption={PGCD en récursif (2) avec Sage}]
sage: def pgcd3(a,b):
....:   if b==0 : return a
....:   if a>=b : return pgcd3(b,a-b)
....:   else : return pgcd3(a,b-a)
\end{lstlisting}

\section{Algorithme d'Euclide étendu}


Petit rappel sur cet algorithme qui permet de prouver le théorème de
Bézout et d'obtenir des coefficients vérifiant $au+bv=a\wedge b$~:

\begin{center}
\begin{tabular}{|c||c|c|c||c|}
\hline $k$ & $u_k$ & $v_k$ & $r_k$ & $q_k$ \\ 
\hhline{=====} 0 & 1 & 0 &$r_0=a$& /  \\ 
\hline 1 & 0 & 1 &$r_1=b$& $q_1$  \\
\hline 2 & $u_0-u_1q_1$ & $v_0-v_1q_1$ &$r_2=r_0-r_1q_1$& $q_2$  \\ 
\hline 3 & $u_1-u_2q_2$ & $v_1-v_2q_2$ & $r_3=r_1-r_2q_2$&$q_3$  \\ 
\hline $\vdots$ &  &  & $\vdots$ & $\vdots$ \\ 
\hline $p-1$ &  &  & $r_{p-1}=a\wedge b$ & $q_{p-1}$ \\ 
\hline $p$ &  &  &   $r_p=0$ &\\
\hline 
\end{tabular} 
\end{center}

Et le secret tient dans le schéma 

\begin{center}
\begin{tabular}{ccccc}
 & \psframebox[fillstyle=solid,fillcolor=bleu_ciel]{$u_k$} & {\Large{\textbf{$-$}}} &  &    \\
 & & & &  \\ 
{\Large{\textbf{(}}} & \psframebox[fillstyle=solid,fillcolor=bleu_ciel]{$u_{k+1}$} & {\Large{\textbf{$\times$}}} & \psframebox[fillstyle=solid,fillcolor=vert_e]{$q_{k+1}$} & {\Large{\textbf{)}}}   \\
 & & & &  \\ 
{\Large{\textbf{$=$}}} & \psframebox{$u_{k+2}$} &  &  &    \\ 
\end{tabular} 
\end{center}


et pareil pour les $v_k$ et les $r_k$.


Par exemple, pour 19 et 15~:



\begin{center}
\begin{tabular}{|c||c|c|c||c|l}
\hhline{-----} $k$ & $u_k$ & $v_k$ & $r_k$ & $q_k$ &  \\ 
\hhline{=====} 0 & \psframebox[fillstyle=solid,fillcolor=bleu_ciel]{ 1} & \psframebox[fillstyle=solid,fillcolor=bleu_ciel]{ 0} & \psframebox[fillstyle=solid,fillcolor=bleu_ciel]{ 19} & / & $L_0$ \\ 
\hhline{-----} 1 & \psframebox[fillstyle=solid,fillcolor=bleu_ciel]{ 0} & \psframebox[fillstyle=solid,fillcolor=bleu_ciel]{ 1} & \psframebox[fillstyle=solid,fillcolor=bleu_ciel]{ 15} & \psframebox[fillstyle=solid,fillcolor=vert_e]{1} & $L_1$ \\ 
\hhline{-----} 2 & 1 & $-1$ & 4 & 3 & $L_2\leftarrow L_0-\psframebox[fillstyle=solid,fillcolor=vert_e]{1}\times L_1$ \\ 
\hhline{-----} 3 & $-3$ & 4 & 3 & 1 & $L_3\leftarrow L_1-3\times L_2$ \\ 
\hhline{-----} 4 & 4 & $-5$ & 1 & 3 & $L_4\leftarrow L_2-1\times L_3$ \\ 
\hhline{-----} 5 &  &  & 0 &  & $L_5\leftarrow L_3-3\times L_4$ \\ 
\hhline{-----} 
\end{tabular} 
\end{center}

C'est-à-dire $4\times 19-5\times 15=1$ et  $19\wedge 15=1$.

En version récursive, on peut procéder en deux étapes~:


\begin{algorithm}[H]
\caption{algorithme d'Euclide étendu~:~version récursive}
aee(u,v,r,u',v',r')\;
\Entree{6 entiers u, v, r, u', v', r'}
\Deb{
\eSi{r'=0}{\Retour([u,v,r])}
{aee(u',v',r',u-quotient(r,r')$\times$u',v-quotient(r,r')$\times$v',r-quotient(r,r')$\times$r')
 }
}

AEE(a,b)
\Entree{2 entiers a et b}
 \Deb{
aee(1,0,a,0,1,b)
}
\end{algorithm}


En XCAS~:
\xc
\begin{lstlisting}[caption={algorithme d'Euclide étendu en récursif}]
aee(u,v,r,u',v',r'):={
if(r'==0){return([u,v,r])};
aee(u',v',r',u-iquo(r,r')*u',v-iquo(r,r')*v',r-iquo(r,r')*r')
}:;

AEE(a,b):=aee(1,0,a,0,1,b):;
\end{lstlisting}


Par exemple,  \verb+AEE(19,15)+ renvoie \verb+[4,-5,1]+  ce qui signifie
que $4\times 19-5\times 15=1$ et que $19\wedge 15=1$.






En CAML~:

\caml

\begin{lstlisting}[caption={algorithme d'Euclide étendu en récursif (CAML)}]
# let rec aee(u,v,r,u',v',r')
    =
  if r'=0 
   then [u;v;r]
  else aee(u',v',r',u-r/r'*u',v-r/r'*v',r-r/r'*r');;

# let aet(a,b)
      = aee(1,0,a,0,1,b);;
\end{lstlisting}



\medskip


Avec Sage:

\sage

\begin{lstlisting}[caption={algorithme d'Euclide étendu en récursif (Sage)}]
sage: def aee(u,v,r,U,V,R):
....:   if R==0 : return [u,v,r]
....:   else : return aee(U,V,R,u-r//R*U,v-(r//R)*V,r-(r//R)*R)
....: 
sage: def AEE(a,b): 
....:   return aee(1,0,a,0,1,b)
....: 
sage: AEE(19,15)
[4, -5, 1]
\end{lstlisting}


\xc
La version  impérative est  comme d'habitude plus  longue à  écrire mais
suit malgré tout l'algorithme présenté dans le tableau~:




\begin{algorithm}[H]
\caption{algorithme d'Euclide étendu~:~version impérative}
\Entree{2 entiers a et b}\;
\Ini{
liste a\aff (1,0,a)\;
liste b\aff (0,1,b)\;
reste\aff b\;
}
\Deb{
\Tq{reste$\neq$0}{
q\aff quotient(3\up{e}opérande de liste a, reste)\;
liste temp\aff liste a-q$\times$liste b\;
liste a\aff liste b\;
liste b\aff liste temp\;
reste\aff 3\up{e}opérande de liste b
}
 } 
\Retour{liste a}
\end{algorithm}

En XCAS~:


\begin{lstlisting}[caption={algorithme d'Euclide étendu en impératif (XCAS)}]
bezout(a,b):={
local la,lb,lr,q,reste;
la:=[1,0,a];
lb:=[0,1,b];
reste:=b;
while (reste !=0){
q:=quotient(la[2],reste);
lr:=la+(-q)*lb;
la:=lb;
lb:=lr;
reste:=lb[2];
}
return(la);
}
\end{lstlisting}


Avec Sage:
\sage

Nous aurons besoin de définir des opérations sur les listes:
\begin{itemize}
\item somme terme à terme;
\item multiplication par un scalaire.
\end{itemize}

Nous utiliserons la commande \verb+map+:

\begin{lstlisting}[caption={somme de listes terme à terme (Sage)}]
sage: def suml(L1,L2):
....:    return map(lambda x,y:x+y,L1,L2)
\end{lstlisting}



\begin{lstlisting}[caption={multiplication d'une liste par un sclaire (Sage)}]
sage: def scal(L1,q):
....:    return map(lambda x:q*x,L1)
\end{lstlisting}

Revenons à ce cher Bezout:

\begin{lstlisting}[caption={algorithme d'Euclide étendu en impératif (Sage)}]
sage: def bezout(a,b):
....:   la=[1,0,a]
....:   lb=[0,1,b]
....:   rem=b
....:   while rem!=0 :
....:      q=la[2]//rem
....:      lr=suml(la,scal(lb,-q))
....:      la=lb
....:      lb=lr
....:      rem=lb[2]
....:   return(la)
....: 
sage: bezout(19,15)
[4, -5, 1]
\end{lstlisting}

\section{Fractions continues dans  Q}



 \begin{itemize}
  
\item Vous connaissez l'algorithme suivant~:

\begin{eqnarray}
172&=&3\times\textcolor{gray}{51}+\textcolor{0.2white}{19}\\
\textcolor{gray}{51}&=&2\times\textcolor{0.2white}{19}+13\\
19&=&1\times13+6\\
13&=&2\times 6+1\\
6&=&6\times 1+0
\end{eqnarray}

\item On peut donc facilement compléter  la suite d'égalité suivante~:

\[\frac{172}{51}=3+\frac{19}{51}=3+\frac{1}{\frac{51}{19}}=3+\frac{1}{2+\frac{13}{19}}=\dots     \]

\end{itemize}

 \textbf{ Pratique du développement}\\
\begin{itemize}

\item Quand tous les numérateurs sont égaux à 1, on dit qu'on a développé $\frac{172}{51}$ en
  fraction continue, et pour simplifier l'écriture on note~:
\[\frac{172}{51}=[3\pv 2\pv \dots ]\]

\item Par exemple, on peut développer  $\frac{453}{54}$ en fraction continue.

\item Dans l'autre sens on peut écrire $[2\pv 5\pv 4]$ sous la forme d'une fraction irréductible.

  \end{itemize}

Nous allons construire les algorithmes correspondant.


On suppose connus les algorithmes  donnant le reste et le quotient d'une
division euclidienne.


\begin{algorithm}[H]
\caption{fractions continues : version récursive}\label{fc}
fc(a,b)\;
\Deb{
\Si{b=0}{\Retour{liste vide}}\;
 }\;
Retour{[quotient(a,b),fc(b,reste(a,b))]} 
\end{algorithm}


En XCAS~:

\xc
\begin{lstlisting}[caption={fractions continues en récursif (1)}]
fc(a,b):={
if(b==0){return([])};
return(concat(iquo(a,b),fc(b,irem(a,b))))
}:;
\end{lstlisting}


Alors \verb+fc(172,51)+ renvoie \verb+[3,2,1,2,6]+


En CAML

\caml

\begin{lstlisting}[caption={fractions continues en récursif (1) avec CAML}]
# let rec fc (a,b)
        =
        if b = 0
         then []
         else  a/b :: fc(b,a-a/b*b);;
\end{lstlisting}


Pour l'opération inverse, on pourra se reporter au paragraphe~\vref{fci}.

En Sage/Python:

\sage

\begin{lstlisting}[caption={fractions continues en récursif (1) avec Sage}]
sage: def fc(a,b):
....:   if b==0 : return []
....:   else : return [a//b]+fc(b,a%b)
....: 
sage: fc(172,51)
[3, 2, 1, 2, 6]
\end{lstlisting}


\xc

La version impérative~:


\begin{algorithm}[H]
\caption{Fractions continues~:~version impérative}
\Entree{2 entiers a et b}\;
\Ini{\;
num\aff a\;
den\aff b\;
res\aff reste(num,den)\;
Liste\aff vide\;
}\;
\Deb{
\Tq{res$\neq$0}{
Liste\aff Liste,quotient(num,den)\;
num\aff den\;
den\aff res\;
res\aff reste(num,den)\;
}
 }
\Retour{[Liste,quotient(num,den)]} 
\end{algorithm}


Avec XCAS:

\begin{lstlisting}[caption={fractions continues en impératif (1) avec XCAS}]
frac_cont(a,b):={
local num,den,res,Liste;
num:=a;
den:=b;
res:=remain(num,den);
Liste:=NULL;
while(res>0){
    Liste:=Liste,iquo(num,den);
    num:=den;
    den:=res;
    res:=remain(num,den);
}
[Liste,iquo(num,den)];
}:;
\end{lstlisting}


Avec Sage/Python:

\sage

\begin{lstlisting}[caption={fractions continues en impératif (1) avec Sage}]
sage: def fc(a,b):
....:   num=a
....:   den=b
....:   res=num%den
....:   Liste=[]
....:   while res>0 :
....:      Liste+=[num//den]
....:      num=den
....:      den=res
....:      res=num%den
....:   return Liste+[num//den]
....: 
sage: fc(172,51)
[3, 2, 1, 2, 6]
\end{lstlisting}

\section{Fractions continues dans  R}


En  fait,  l'étude précédente  correspond  à  un  cas particulier  d'une
définition plus générale.

Soit $x$ un  réel non entier. On construit une  suite entière $(z_n)$ de
la manière suivante~:


\[x=z_0+\frac{1}{x_1}\qquad          z_0=\lfloor          x\rfloor\qquad
x_1=\frac{1}{x-z_0}\]

puis, tant que $x_k$ n'est pas entier~:


\[x_k=z_k+\frac{1}{x_{k+1}}\qquad          z_k=\lfloor          x_k\rfloor\qquad
x_{k+1}=\frac{1}{x_k-z_k}\]


Le  développement de  $x$ en  fractions  continues est  alors donné  par
$[z_0,z_1,z_2,\dots]$, cette liste pouvant être infinie.

\subsection{ En impératif}

\subsubsection{Avec XCAS}
\xc
\begin{lstlisting}[caption={fractions continues en impératif (2) avec XCAS}]
fcr(x,n):={
X:=evalf(x,n);
L:=floor(X);
for(k:=0;k<n;k:=k+1){
  if(X!=floor(X))
   then{X:=1/(X-floor(X))
        L:=L,floor(X);}
}
return([L])
}:;
\end{lstlisting}

Alors, par exemple~:

\begin{lstlisting}
fcr(pi,12)
\end{lstlisting}

\reponse{[3,7,15,1,292,1,1,1,2,1,3,1,14]}

\begin{lstlisting}
fcr(sqrt(2),20)
\end{lstlisting}

\reponse{[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]}

\subsubsection{Avec Sage}

\sage


\begin{lstlisting}[caption={fractions continues en impératif (2) avec Sage}]
sage: def fcr(x,n):
....:    X=x.n(digits=n)
....:    L=[floor(X)]
....:    for k in [0..n-1]:
....:       if X!=floor(X) : 
....:          X=1/(X-floor(X))
....:          L+=[floor(X)]
....:    return L
....: 
sage: fcr(sqrt(2),20)
[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
\end{lstlisting}






\subsection{ En récursif}

\subsubsection{Avec XCAS}
\xc
\begin{lstlisting}[caption={fractions continues en récursif (2)}]
fcrec(x,n):={
if(n==0)
 then{return([floor(evalf(x))])}
 else{
  if(x==floor(x))then{[x]}
  else{
    concat(floor(evalf(x,n)),fcrec(1/(x-floor(evalf(x,n))),n-1))
  }
 }
}:;
\end{lstlisting}


\subsubsection{ Avec CAML}

\caml
\begin{lstlisting}[caption={fractions continues en récursif (2) avec CAML}]
# let rec fcrec(x,n)=
    if n=0 then [floor(x)]
    else if x=floor(x) then [x]
         else floor(x)::fcrec(1./.(x-.floor(x)),n-1);;
\end{lstlisting}

Alors on obtient pour $\sqrt{2}$~:

\begin{lstlisting}
# fcrec(sqrt(2.),10);;
- : float list = [1.; 2.; 2.; 2.; 2.; 2.; 2.; 2.; 2.; 2.; 2.]
\end{lstlisting}




\subsubsection{Avec Sage}

\sage

\begin{lstlisting}[caption={fractions continues en récursif (2) avec Sage}]
sage: def fcr(x,n):
....:   if n==0 : return [floor(x)]
....:   elif x==floor(x) : return [x]
....:   else : return [floor(x)] + fcr(1/(x-floor(x)),n-1)
....: sage: fcr(pi,12)
[3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14]
\end{lstlisting}










\xc

\section{Tests de primalité}


\subsection{Première version}

Un premier test naïf consiste à diviser le nombre successivement par les
entiers de 2  à la partie entière de  $n$ et de sortir de  la boucle dès
que le reste est nul~:


\begin{algorithm}[H]
\caption{test de primalité 1}
\Entree{un entier n}\;
\Deb{
\Pour{k de 2 jusque partie entière de $\sqrt{n}$}{
\Si{reste de la division de n par k est nul}{\Retour{n n'est pas premier}}
}
\Retour{n est premier}
 } 
\end{algorithm}


\subsubsection{En XCAS}

\begin{lstlisting}[caption={test de primalité en impératif (1)}]
testPrem1(n):={
local k;
pour k de 2 jusque floor(sqrt(n)) faire
  si irem(n,k)==0 alors retourne(n+" n'est pas premier");
  fsi;
fpour;
retourne(n+" est premier");
}:;
\end{lstlisting}


En anglais~:



\begin{lstlisting}[caption={test de primalité en impératif (1) en VO}]
testPrem1(n):={
local k;
 for(k:=2;k<=floor(sqrt(n));k:=k+1){
   if(irem(n,k)==0){return(n+" n'est pas premier")};
 };
return(n+" est premier");
}:;
\end{lstlisting}





Cependant, il  faut parfois être patient~:~\verb|testPrem1(2^(10000)+1)|
a mis  près de 10  minutes avant de  répondre que ce nombre  n'était pas
premier.




\subsubsection{En CAML}




\caml


\begin{lstlisting}[caption={test de primalité en récursif (1) avec CAML}]
# let test_naif n =
     let rec test_local(m,k)=
        if m*m>k then "premier"
	else if k/m*m =k then "compose"
        else test_local(m+1,k)
     in test_local(2,n);;  
\end{lstlisting}



On  note   au  passage  comment  utiliser  une   fonction  localement  à
l'intérieur d'une autre.

On aurait pu tout aussi bien les écrire séparément~:

\begin{lstlisting}[caption={test de primalité en récursif (1bis) avec CAML}]
# let rec  test_local(m,k)=
        if m*m>k then "premier"
	else if k/m*m =k then "compose"
        else test_local(m+1,k);;

# let test_naif n = test_local(2,n);;  
\end{lstlisting}


\subsubsection{Avec Sage}


\sage


\begin{lstlisting}[caption={test de primalité en impératif (1) avec Sage}]
sage: def test_naif(n):
....:    for k in [2..floor(sqrt(n))] :
....:       if n%k==0 : return False
....:    return True
....: 
sage: test_naif(97)
True
sage: test_naif(99)
False
\end{lstlisting}




\begin{lstlisting}[caption={test de primalité en récursif (1) avec Sage}]
sage: def test_local(m,k):
....:   if m*m>k : return True
....:   elif k%m==0 : return False
....:   else : return test_local(m+1,k)
....: 
sage: def test_naif(n):
....:   return test_local(2,n)
....: 
sage: test_naif(97)
True
sage: test_naif(99)
False
\end{lstlisting}


\xc


\subsection{Deuxième version}

Une première  possibilité pour diviser le  nombre de tests par  2 est de
vérifier au départ si le nombre est pair. Dans le cas contraire, on peut
faire des sauts de 2 à partir de 3~:


\begin{algorithm}[H]
\caption{test de primalité 2}
\Entree{un entier n}\;
\Deb{
\Si{n est pair}{\Retour{n n'est pas premier}}
\Pour{k de 2 jusque partie entière de $\sqrt{n}$ avec un pas de 2}{
\Si{reste de la division de n par k est nul}{\Retour{n n'est pas premier}}
}
\Retour{n est premier}
 } 
\end{algorithm}


\subsubsection{Avec XCAS}

\begin{lstlisting}[caption={test de primalité en impératif (2) avec XCAS}]
testPrem1(n):={
local k;
si irem(n,2)==0 alors retourne(n+ " n'est pas premier"); fsi;
pour k de 3 jusque floor(sqrt(n)) pas 2 faire
  si irem(n,k)==0 alors retourne(n+" n'est pas premier");
  fsi;
fpour;
retourne(n+" est premier");
}:;
\end{lstlisting}

En anglais~:

\begin{lstlisting}[caption={test de primalité en impératif (2) en VO}]
testPrem1(n):={
local k;
 if(irem(n,2)==0){return(n+ " n'est pas premier")};
 for(k:=3; k<=floor(sqrt(n));k:=k+2){
    if(irem(n,k)==0){return(n+" n'est pas premier")};
 };
return(n+" est premier");
}:;
\end{lstlisting}


Plus que  291 secondes... On a  bien divisé le temps  de compilation par
deux. 


\subsubsection{En CAML}


\caml
\begin{lstlisting}[caption={test de primalité en récursif (2) avec CAML}]
#  let test_naif_2 n =
     let rec test_local(m,k)=
      if k/2*2=k then "pair"
      else 
        if m*m>k then "premier"
	else if k/m*m =k then "compose"
        else test_local(m+2,k)
     in test_local(3,n);; 
\end{lstlisting}



\subsubsection{Avec Sage}

\sage



\begin{lstlisting}[caption={test de primalité en impératif (2) avec Sage}]
sage: def test2(n):
....:    if n%2==0 : return False
....:    for k in srange(3,floor(sqrt(n)),2):
....:       if n%k==0 : return False
....:    return True
\end{lstlisting}



\begin{lstlisting}[caption={test de primalité en récursif (2) avec Sage}]
sage: def test2local(m,k):
....:    if k%2==0 : return False
....:    elif m*m>k : return True
....:    elif k%m==0 : return False
....:    else : return test2local(m+2,k)
....: 
sage: def test2(n):
....:    return test2local(3,n)
....: 
sage: test2(2**100+1)
False
\end{lstlisting}








\xc



\subsection{Troisième version}

On peut également remarquer  qu'un nombre entier strictement supérieur à
3 et multiple de 3 ne peut pas être premier.



On  doit donc  diviser par  5, $5+2$,  $5+2+4$,  $5+2+4+2$, $5+2+4+2+4$,
$5+2+4+2+4+2$,...


\subsubsection{Avec XCAS}


On introduit une fonction intermédiaire~:

\begin{lstlisting}[caption={reste symétrique}]
reste_sym(n):={
if(irem(n,6)==5){return(2)};
if(irem(n,6)==1){return(4)};
}:;
\end{lstlisting}

Et on l'utilise~:


\begin{lstlisting}[caption={test de primalité en impératif (3)}]
testPrem3(n):={
local k;
 if((irem(n,2)==0)or (irem(n,3)==0)){return(n+ " n'est pas premier")};
 for(k:=5; k<=floor(sqrt(n));k:=k+reste_sym(k)){
    if(irem(n,k)==0){return(n+" n'est pas premier")};
 };
return(n+" est premier");
}:;
\end{lstlisting}



Plus  que  188  secondes...  Les  outils plus  efficaces  dépassent  les
connaissances d'un élève de 2\up{nde}.

\subsubsection{En CAML}


\caml
\begin{lstlisting}[caption={test de primalité en récursif (3)}]
#  let test_naif_3 n =
     let rec test_local(m,k)=
      if k/2*2=k or k/3*3=k then "compose"
      else 
        if m*m>k then "premier"
	else if k/m*m =k then "compose"
        else test_local(m+2,k)
     in test_local(5,n);; 
\end{lstlisting}

\xc




\section{Crible d'Ératosthène}


\subsection{En impératif}

\subsubsection{Avec XCAS}

\begin{lstlisting}[caption={crible d'Ératosthène en impératif}]
erato(n):={
local j,k,P;
P:=[seq(k,k=1..n)];
P[0]:=0;
pour j de 2 jusque floor(sqrt(n)) faire
  si P[j-1]>=1 alors
    pour k de 2 jusque floor(n/j) faire
      P[j*k-1]:=0;
    fpour;
  fsi;
fpour;
retourne(select(x->(x>=1),P));
}:;
\end{lstlisting}

En anglais~:

\begin{lstlisting}[caption={crible d'Ératosthène en impératif (VO)}]
erato(n):={
local j,k,P;
P:=[seq(k,k=1..n)];
P[0]:=0;
for(j:=2;j<=floor(sqrt(n));j:=j+1){
  if(P[j-1]>=1){
     for(k:=2;k<=floor(n/j);k:=k+1){
         P[j*k-1]:=0;
      };
  };
};
return(select(x->(x>=1),P));
}:;
\end{lstlisting}


\subsubsection{Avec Sage}

\sage

\begin{lstlisting}[caption={crible d'Ératosthène en impératif (Sage)}]
sage: def erato(n):
....:   P=[1..n]
....:   P[0]=0
....:   for j in [2..floor(sqrt(n))]:
....:      if P[j-1]>=1 :
....:         for k in [2..floor(n/j)]:
....:            P[j*k-1]=0
....:   return filter(lambda x : x>=1,P)
....: 
sage: erato(100)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
\end{lstlisting}


\subsection{En récursif}


\subsubsection{Avec CAML}

En CAML, la récursion peut se faire en étapes pour plus de lisibilité.

\caml

On fabrique une fonction qui renvoie un intervalle entier dont on a entré les
bornes~:

\begin{lstlisting}[caption={entiers compris entre deux valeurs}]
# let rec  inter(a,b)= if a>b then [] else a::inter(a+1,b);;
\end{lstlisting}


Ainsi~:


\begin{lstlisting}
# inter(2,12);;
- : int list = [2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12]
\end{lstlisting}



Ensuite, on crée une fonction  qui retire les multiples d'un entier dans
une liste donnée~:

\begin{lstlisting}[caption={pour retirer les multiples d'un entier dans une liste donnée (1)}]
# let rec retmultiples(l,n)=
        if l=[] then [] else
              if List.hd(l) mod n = 0 
                      then (retmultiples(List.tl(l),n)) 
                      else List.hd(l)::retmultiples(List.tl(l),n);;
\end{lstlisting}


Ainsi on peut enlever les multiples de 3 compris entre 2 et 12~:

\begin{lstlisting}
# retmultiples(inter(2,12),3);;
- : int list = [2; 4; 5; 7; 8; 10; 11]
\end{lstlisting}



Voici une variante sans utiliser le module \og \texttt{List}\fg{}~:

\begin{lstlisting}[caption={pour retirer les multiples d'un entier dans une liste donnée (2)}]
# let rec retmultiples = function
  | [],n -> []
  | x::l,n -> if x mod n=0 then retmultiples(l,n)
                           else x::retmultiples(l,n);;
\end{lstlisting}



Enfin, voici le c\oe ur de la procédure~:


\begin{lstlisting}[caption={crible d'Ératosthène en récursif}]
# let crible(m)=
      let rec crible_rec(l,n)=
        if n>m then []
        else
          if n*n>m then n::(crible_rec(l,n+1))
	  else n::retmultiples(crible_rec(l,n+1),n)
in crible_rec(inter(2,m),2);;
\end{lstlisting}



L'utilisation est simple~:



\begin{lstlisting}
# crible(100);;
- : int list =
[2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59; 61; 67; 71;
 73; 79; 83; 89; 97]
\end{lstlisting}

\xc

Comparons~:   \verb+erato(10000)+    répond   en   7,83    secondes   et
\verb+crible(10000)+ en 1,70 secondes.

On peut évidemment améliorer chacun des algorithmes avec du savoir-faire.







\section{Décomposition en facteurs premiers}

On  utilise  la  fonction   ou  la  procédure  du  crible  d'Ératosthène
précédemment définie...ce qui va rendre nos algorithmes peu efficaces~!

\subsection{En récursif}

\subsubsection{ Avec XCAS}


\begin{lstlisting}[caption={décomposition   en   facteurs  premiers   en   récursif (XCAS)}]
decompotemp(n,liste):={
 if(n==1)then{[]}
 else{
  if(irem(n,head(liste))==0)
     then{append(decompotemp(n/head(liste),liste),head(liste))}
     else{decompotemp(n,tail(liste))}
 }
}:;
\end{lstlisting}

 puis 

\begin{lstlisting}
decompo(n):={
decompotemp(n,erato(n))
}:;
\end{lstlisting}

alors 

\begin{lstlisting}
decompo(8004)
\end{lstlisting}


\reponse{[29,23,3,2,2]}





\subsubsection{ Avec CAML }


\caml
\begin{lstlisting}[caption={décomposition en facteurs premiers en récursif  avec CAML (1)}]
# let decompo(n)=
  let rec decompotemp(n,liste)=
      if n=1 then []
      else if n mod List.hd(liste) = 0
           then List.hd(liste)::(decompotemp(n/List.hd(liste),liste))
           else decompotemp(n,List.tl(liste))
  in 
  decompotemp(n,crible(n));; 
\end{lstlisting}

ou bien, sans utiliser le module \og \texttt{List}\fg{}~:


\begin{lstlisting}[caption={décomposition en facteurs premiers en récursif  avec CAML (2)}]
# let decompo(n)=
  let rec decompotemp = function
      | 1,l -> []
      | n,tete::queue -> if n mod tete = 0 
           then tete::(decompotemp(n/tete,tete::queue))
           else decompotemp(n,queue)
  in 
  decompotemp(n,crible(n));; 
\end{lstlisting}


Par exemple~:


\begin{lstlisting}
# decompo(8004);;
- : int list = [2; 2; 3; 23; 29]
\end{lstlisting}

\subsubsection{Avec Sage}

\sage




\begin{lstlisting}[caption={décomposition   en   facteurs  premiers   en   récursif (Sage)}]
def tete(L):
    return L[0]

def queue(L):
    del L[0];
    return L

def decompotemp(n,liste):
   if n==1 : return []
   elif n%tete(liste)==0 :
      return [tete(liste)]+ decompotemp(n//tete(liste),liste)
   else :  return decompotemp(n,queue(liste))

def decompo(n):
    return decompotemp(n,erato(n))

sage: decompo(8004)
[2, 2, 3, 23, 29]
\end{lstlisting}




\subsubsection{Variante indiquant la valuation}
\caml
On crée  une fonction  qui compte le  nombre d'occurrences  d'un élément
donné dans une liste~:

\begin{lstlisting}[caption={nombre d'occurrences d'un nombre dans une liste en récursif }]
# let rec ocu = function
	      | (n,[]) -> 0
	      | (n,t::q) -> if n=t then ocu(n,q) + 1
		            else ocu(n,q);;
\end{lstlisting}

Par exemple~:


\begin{lstlisting}
# ocu(2,[1;2;2;2;3;4;5;5;5;5;6;6;7;8;9]);;
- : int = 3
\end{lstlisting}


Ensuite,  on crée une  fonction qui  transforme une  liste en  une liste
contenant des  couples formés  de chaque élément  différent de  la liste
et de leur occurrence.

On utilise la commande \verb+List.nth liste rang+ qui donne l'élément de
rang   \verb+rang+   de   la   liste   \verb+liste+   et   la   commande
\verb+List.length liste+  qui renvoie le  nombre d'éléments de  la liste
\verb+liste+.


\begin{lstlisting}[caption={liste des éléments d'une liste avec leur valuation}]
# let valuation(liste)=
  let rec valu( n) = 
     if n=List.length(liste) then [(List.nth liste (n-1),ocu(List.nth liste (n-1),liste))]
     else if List.nth liste n > List.nth liste (n-1) 
          then  (List.nth liste (n-1),ocu(List.nth liste (n-1),liste))::valu(n+1)
          else  valu(n+1)
  in valu(1);;
\end{lstlisting}

Par exemple~:


\begin{lstlisting}
# valuation([1;2;2;2;3;4;5;5;5;5;6;6;7;8;9;9;9]);;
- : (int * int) list =
[(1, 1); (2, 3); (3, 1); (4, 1); (5, 4); (6, 2); (7, 1); (8, 1); (9, 3)]
\end{lstlisting}


On modifie alors \verb+decompo+

\begin{lstlisting}[caption={décomposition en facteurs premiers en récursif  avec CAML (2)}]
# let decompo(n)=
  let rec decompotemp = function
      | n,[] -> []
      | 1,l -> []
      | n,tete::queue -> if n mod tete = 0 
           then tete::(decompotemp(n/tete,tete::queue))
           else decompotemp(n,queue)
  in 
  valuation(decompotemp(n,crible(n)));; 
\end{lstlisting}


Par exemple~:

\begin{lstlisting}
# decompo(35640);;
- : (int * int) list = [(2, 3); (3, 4); (5, 1); (11, 1)]
\end{lstlisting}

C'est-à-dire $\nombre{35640}=2^3\times3^4\times5\times11$.


\subsection{ En impératif}


\subsubsection{Sans la valuation}
 
\xc
\begin{lstlisting}[caption={décomposition en facteurs premiers en impératif (1)}]
decompo(n):={
local D,L,N,k;
D:=NULL;
L:=erato(n);
N:=n;
 for(k:=0;k<size(L);k:=k+1){
   while(member(N,L)==0){
      if(irem(N,L[k])==0)
        then{D:=D,L[k]; 
             N:=iquo(N,L[k])}
        else{break} 
   }
 }
return(D,N);
}:;        
\end{lstlisting}

Vous noterez  l'utilisation de la commande \texttt{break}  qui permet de
sortir de la boucle \texttt{while} 


Par exemple~:

\begin{lstlisting}
decompo(2800)
\end{lstlisting}

donne~:

\reponse{2,2,2,2,5,5,7}



\subsubsection{Avec la valuation}
 

On rajoute une petite procédure~:

\begin{lstlisting}[caption={décomposotion en facteurs premiers en impératif (2)}]
Valuation(L):={
local LV,val,k,s;
s:=size(L);
LV:="";
k:=0;
val:=[1$s];
 while(k<s-1){
    if(L[k]==L[k+1])
      then{val[k+1]:=val[k]+1; k:=k+1}
      else{LV:=LV+L[k]+"^"+val[k]+"*" ; k:=k+1}
 }
 LV:=LV+L[s-1]+"^"+val[s-1]
return(expr(LV)+"="+LV)
$}:;
\end{lstlisting}


Elle contient une petite touche esthétique...



On modifie ensuite \verb+decompo+ en remplaçant \verb+return(D,N);+ par \verb+return(Valuation(D,N));+

Alors

\begin{lstlisting}
decompo(2800)
\end{lstlisting}

renvoie maintenant~:

\reponse{$2800=2^4*5^2*7^1$}

\section{Avec la bibliothèque arithmétique de XCAS}

\subsection{Nombres premiers jumeaux}


Des  nombres premiers  dont la  différence vaut  2 sont  appelés nombres
premiers jumeaux.

Il  a  été conjecturé  qu'il  en existe  une  infinité.  On utilise  les
commandes \texttt{isprime} et \texttt{nextprime} disponible sur XCAS.

\begin{lstlisting}[caption={nombres jumeaux en impératif}]
twin(A,n):={
if(isprime(A))then{a:=A}else{a:=nextprime(A)}
L:=NULL;
for(k:=a;k<=A+n-2;k:=k+2){
   if((isprime(k)) and (isprime(k+2)))
   then{L:=L,[k,k+2]}
}
return("Il y a "+size(L)+" couple(s) de jumeaux entre "+A+" et "+(A+n)+" :
"+L)
}:;
\end{lstlisting}




\section{En base 10}


\subsection{Nombre de chiffres d'un entier}

On  pense au  logarithme ou  à  la rigueur  à une  ruse informatique  du
style~:\og  je transforme  mon  nombre  en chaîne  de  caractères et  je
demande au logiciel de compter le  nombre de caractères de la chaîne (ce
qu'ils savent tous faire)\fg{}.  La première solution est peu utilisable
en 2\up{nde} et la deuxième peu intéressante mathématiquement.

Alors on \og pense base 10\fg{}~:


\begin{algorithm}[H]
\caption{nombre de chiffres d'un entier naturel}
NbChiffres(n)
\Entree{un entier naturel n}\;
\Deb{
\eSi{n<10}{1}{1+NbChiffres(quotient\_entier(n,10))}
 } 
\end{algorithm}


En XCAS~:

\begin{lstlisting}[caption={nombre de chiffres d'un entier (XCAS)}]
NbChiffres(n):={
if(n<10){1}else{1+NbChiffres(iquo(n,10))}
}:;
\end{lstlisting}

En CAML~:

\caml

\begin{lstlisting}[caption={nombre de chiffres d'un entier (CAML)}]
# let rec NbChiffres n = if n<10 then 1 else 1+NbChiffres(n/10);;
\end{lstlisting}

En Sage/Python:

\sage

\begin{lstlisting}[caption={nombre de chiffres d'un entier (Sage)}]
def NbChiffres(n):
    if n<10 : return 1
    else : return 1+NbChiffres(n//10)
\end{lstlisting}

\xc

\section{Décomposition en base 2}

\subsection{Expérimentation}

Une  méthode  pour  obtenir  l'écriture   en  base  2  d'un  nombre  est
d'effectuer des divisions successives. Par exemple pour 11~:

\begin{center}
\opidiv[remainderstyle=\bfseries\large\color{gray},resultstyle=\color{blue}]{11}{2}\hspace{1cm}
\opidiv[remainderstyle=\bfseries\large\color{gray},resultstyle=\color{blue}]{5}{2}
\hspace{1cm}
\opidiv[remainderstyle=\bfseries\large\color{gray},resultstyle=\color{blue}]{2}{2}
\hspace{1cm}
\opidiv[remainderstyle=\bfseries\large\color{gray},resultstyle=\color{blue}]{1}{2}

\end{center}

\begin{align*}
11 &=\Bigl(2\times5+1\Bigr)
\\ &=\Bigl(2\times\bigl(2\times2+1\bigr)+1\Bigr)
\\ &=\Bigl(2\times\bigl(2\times(2\times 1)+1\bigr)+1\Bigr)
\\ &=\Bigl(2\times (2^2+1)+1\Bigr)
\\ &=2^3+2+1
\\ &=1\times 2^3+0\times 2^2+1\times 2^1+1\times 2^0 
\end{align*}



L'écriture de  11 en base  2 est donc  1011~:~c'est la liste  des restes
obtenus mais dans l'ordre inverse.


La méthode est facilement généralisable.


% \subsection{Retournement d'une liste}

% Nous aurons besoin d'inverser l'ordre  des termes de la liste des restes
% obtenus.

% Fabriquons un petit algorithme pour cela~:


% \begin{algorithm}[H]
% \caption{retournement d'une liste}
% \Entree{une liste L}\;
% \Ini{$n$\aff taille de la liste L\;
% une liste RL composée au départ de $n$ zéro}\;
% \Deb{
% \Pour{k de 0 jusque $n-1$}{
%         RL[k]\aff L[(n-1)-k]}
% \Retour{RL}
%  } 
% \end{algorithm}


% ce qui donne en XCAS~:


% \begin{lstlisting}
% retournement(L):={
% local n,RL,k;
% n:=size(L);
% RL:=[0$n];
% pour k de 0 jusque n-1 faire
%    RL[k]:=L[n-1-k]
% fpour;
% return(RL);
% }:;
% \end{lstlisting}


\subsection{Algorithme}


\begin{algorithm}[H]
\caption{décomposition en base 2}
\Entree{un entier $n$}\;
\Ini{\;
$r$\aff le reste de la division de $n$ par 2\;
$q$\aff le quotient de la division de $n$ par 2\;
R une liste contenant $r$ au départ.
}\;
\Deb{
\Tq{q>0}{
r\aff le reste de la division de $q$ par 2\;
$q$\aff le quotient de la division de $q$ par 2\;
On ajoute r au début de la liste R.
}
\Retour{R}
 } 
\end{algorithm}



\subsection{En impératif}

\subsubsection{Avec XCAS}

Comme dans la plupart des langages de calcul, le reste et le quotient de la division
euclidienne   de   a   par    b   sont   obtenus   respectivement   avec
\texttt{irem(a,b)} et \texttt{iquo(a,b)}.

On concatène deux listes avec \texttt{concat(L1,L2)}.

\begin{lstlisting}[caption={décomposition en base 2 en impératif (XCAS)}]
base_deux(n):={
local r,R,q;
r:=irem(n,2);
q:=iquo(n,2);
R:=[r];
tantque q>0 faire
 r:=irem(q,2);
 q:=iquo(q,2);
 R:=concat([r],R); 
ftantque;
retourne(R);
}:;
\end{lstlisting}


\subsubsection{Avec Sage/Python}

\sage
\begin{lstlisting}[caption={décomposition en base 2 en impératif (Sage)}]
def base2(n):
    r=n%2
    q=n//2
    R=[r]
    while q>0 :
        r=q%2
        q=q//2
        R=[r]+R
    return R


sage: base2(4)
[1, 0, 0]
\end{lstlisting}

On peut bien sûr généraliser ceci à n'importe quelle base.

\subsection{Version récursive}

Notons $q_n$ et $r_n$ le quotient et le reste après $n$ divisions.

$q_{n+1}$ est le quotient entier de  $q_n$ par 2 et on rajoute $r_{n+1}$
à notre liste de restes.




Après  un certain  nombre  de divisions,  le  quotient sera  strictement
inférieur à 2.



\begin{algorithm}[H]
\caption{Conversion binaire : version récursive}
Binaire(n)\;
\Entree{un entier n}\;
\Deb{
\eSi{n<2}{\Retour{n}}{\Retour{Binaire(quotient(n,2)),reste(n,2)}}
 } 
\end{algorithm}

\subsubsection{Avec XCAS}
\xc
\begin{lstlisting}[caption={décomposition en base 2 en récursif (XCAS)}]
Binaire(n):={
    if (n<2){return n}
    else{
      return(Binaire(iquo(n,2)),irem(n,2));
    }
 }:;
\end{lstlisting}


\subsubsection{Avec CAML}

\caml

\begin{lstlisting}[caption={décomposition en base 2 en récursif (CAML)}]
# let rec binaire n =
        if n<2 
          then [n]
        else  binaire(n/2) @ [n mod 2];;
\end{lstlisting}


\begin{figure}[!h]
  \begin{Remarque}[Concaténation de listes en CAML]
    On utilise \verb+liste  1 @ liste 2+ pour  concaténer deux listes et
    \verb+ élément :: liste+ pour rajouter un élément en début de liste.
    \end{Remarque}
  \end{figure}



\subsubsection{avec Sage}

\sage
\begin{lstlisting}[caption={décomposition en base 2 en récursif (Sage)}]
def base2(n):
    if n<2 : return [n]
    else : return base2(n//2)+[n%2]
\end{lstlisting}



\section{Problèmes de calendrier}

\xc
\subsection{Formule de \textsc{Zeller}}

Connaissant  une  date, à  quel  jour  de  la semaine  correspond-elle~?
L'allemand \textsc{Zeller} a proposé une formule en 1885.

On note  $m$ le numéro  du mois  à partir de  janvier, $s$ le  numéro du
siècle, $a$  le numéro de l'année dans  le siècle $s$, $j$  le numéro du
jour.


En fait, $m$ doit être modifié selon le tableau suivant~:

\begin{center}
             \begin{tabularx}{\textwidth}{Y{11}}
	     \whline
             Mois& Jan. & Fév.  & Mars & Avril & Mai & Juin & Juil.  & Août &
             Sep. & Oct. & Nov. & Déc.\\
             \whline
             Rang &13* &14* & 3 &4 &5 &6 &7 &8 &9 &10 &11 &12\\

             \whline
             \end{tabularx}
             \end{center}


Les mois marqués d'une astérisque comptent pour l'année précédente.



Le nom du jour (0 correspondant à samedi) est alors déterminé en prenant le reste dans la division
par 7 de $nj$ donné par la formule~:


\[nj=j+a+{\rm quotient\ entier}(a,4)+(26m-2)[10]+{\rm quotient\ entier}(s,4)-2s \]

Ceci est  valable à partir du 15  octobre 1582, date à  laquelle le pape
Grégoire XIII a modifié le  calendrier~:~on est passé du jeudi 4 octobre
1582  au  vendredi  15  octobre  1582 (en  Grande-Bretagne  il  a  fallu
attendre 1752, au Japon en 1873, en Russie 1918, en Grèce 1924).

 L'année est alors de 365 jours, sauf quand elle est bissextile, i.e., divisible par 4, sauf les années séculaires (divisibles par 100), qui ne sont bissextiles que si divisibles par 400.
 

Avant le changement, il faut remplacer ${\rm quotient\ entier}(s,4)-2s$
par $5-s$.


\subsubsection{Avec XCAS}


\xc
\begin{lstlisting}[caption={calcul du jour de la semaine d'une date donnée (XCAS)}]
jour(j,m,a):={
local mm,aa,s,na,nj,J,greg;
(mm,aa):=if(m<3)then{(m+12,a-1)}else{(m,a)};
s:=iquo(aa,100);
na:=irem(aa,100);
greg:=if((a<1582)or((a==1582)and((m<10)or((m==10)and(j<5)))))then{5-s}else{iquo(s,4)-2*s};
nj:=j+na+iquo(na,4)+iquo(26*(mm+1),10)+greg;
J:=["Samedi","Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi"];

return(J[irem(nj,7)])
}:;
\end{lstlisting}

\medskip


Pour  les  démonstrations, voir  l'article  original de  \textsc{Zeller}
disponible (en allemand...) à l'adresse~:
\begin{center}
   \href{http://www.merlyn.demon.co.uk/zel-86px.htm}{http://www.merlyn.demon.co.uk/zel-86px.htm}

\end{center}


Par exemple, le 14 juillet 1789 était un...

\begin{lstlisting}
jour(14,7,1789)
\end{lstlisting}


\reponse{Mardi}




\subsubsection{Avec Sage/Python}


\sage
\begin{lstlisting}[caption={calcul du jour de la semaine d'une date donnée (Sage)}]
def jour(j,m,a):
    if m<3 : [mm,aa]=[m+12,a-1]
    else : [mm,aa]=[m,a]
    s=aa//100
    na=aa%100
    if ((a<1582)or((a==1582)and((m<10)or((m==10)and(j<5))))) :
        greg=5-s
    else :
        greg=s//4-2*s
    nj=j+na+na//4+(26*(mm+1))//10+greg
    J=['Samedi','Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi']
    return J[nj%7]
\end{lstlisting}




Par exemple:

\begin{lstlisting}[caption={}]
sage: jour(25,12,1)
'Dimanche'
\end{lstlisting}




  \xc










\chapter{Construction d'ensembles de nombres}
\caml


\section{Somme et multiplication d'entiers}


Supposons  que  nous  ne  sachions  que  trouver  le  successeur  ou  le
prédécesseur d'un
entier. Comment additionner deux entiers quelconques~?


\begin{lstlisting}[caption={addition de deux entiers en récursif}]
# let rec add = function
          (0,x) -> x
  |       (x,y) -> add((x-1),y)+1;;
\end{lstlisting}


Additionner  $x$ et  $y$ c'est  prendre le  successeur de  l'addition du
prédécesseur de $x$ et de $y$...c'est-à-dire~:~$x+y=\big((x-1)+y\big)+1$
sachant que $0+x=x$.

\medskip

Pour la multiplication~:


\begin{lstlisting}[caption={multiplication de deux entiers en récursif}]
# let rec mult = function
     (0,x)->0
  | (x,y)->add(mult(x-1,y),y);;
\end{lstlisting}

C'est-à-dire~:~$0\times x=0$ et $x\times y=\big((x-1)\times y\big)+y$


C'est mathématique...

\section{Opérations avec des fractions}


On aura besoin d'un algorithme de calcul du PGCD~:

\begin{lstlisting}[caption={calcul du PGCD en récursif}]
#  let rec pgcd (a,b) =
        if b=0 
         then a
         else  pgcd(b,a-a/b*b);;
\end{lstlisting}




On va représenter une fraction par une liste du type [numérateur;dénominateur].

Pour prévenir toute division par zéro on va créer un opérateur traitant les exceptions qu'on nommera \verb+Division_par_zero+ et qui nous servira de garde-fou :

\begin{lstlisting}
# exception Division_par_zero;;
\end{lstlisting}



On invoquera  cette exception  avec la commande  \verb+raise+ : étant  donné le
niveau d'anglais des élèves, cette commande est naturelle !...



On peut créer un opérateur qui simplifie les fractions~:

\begin{lstlisting}[caption={simplifiaction de fraction}]
# let simp([a;b]) = 
 if b=0  then raise Division_par_zero
 else [a/pgcd(a,b);b/pgcd(a,b)];;
\end{lstlisting}



On crée ensuite une somme simplifiée de fractions~:


\begin{lstlisting}[caption={somme de fractions}]
# let som([a;b],[c;d]) =
  if b=0 or d=0 then raise Division_par_zero else
  simp([a*d+b*c;b*d]);;
\end{lstlisting}



Par exemple~:


\begin{lstlisting}
# som([2;3],[1;6]);;
- : int list = [5; 6]
\end{lstlisting}

Une multiplication~:

\begin{lstlisting}[caption={produit de fractions}]
#  let mul([a;b],[c;d]) =
  if b=0 or d=0 then raise Division_par_zero else
  simp([a*c;b*d]);;
\end{lstlisting}


Par exemple~:

\begin{lstlisting}
# mul([3;2],[2;9]);;
- : int list = [1; 3]
\end{lstlisting}


Un inverse~:


\begin{lstlisting}[caption={inverse d'une fraction}]
#  let inv([a;b]) =
  if b=0 or a=0 then raise Division_par_zero else
  simp([b;a]);;
\end{lstlisting}


Une division~:

\begin{lstlisting}[caption={division de fractions}]
# let div([a;b],[c;d])=mul([a;b],inv([c;d]));;
\end{lstlisting}



Par exemple, comment entrer \[1+\frac{2+\frac{3}{4}}{1-\frac{5}{6}}\]


\begin{lstlisting}
# som([1;1],div(som([2;1],[3;4]),som([1;1],[-5;6])));;
- : int list = [35; 2]
\end{lstlisting}

Évidemment,  c'est moins  pratique  que  de taper  le  résultat sur  une
machine mais  ça permet  de réfléchir aux  différentes opérations,  à la
notion de fonction,...





\section{Fractions continues~:~le retour}

Nous avions vu à l'algorithme~\vref{fc} comment, à partir d'un nombre écrit sous forme
fractionnaire, on  pouvait obtenir son  écriture sous forme  de fraction
continue.

Nous  allons  à  présent  voir comment  effectuer  l'opération  inverse,
c'est-à-dire comment  obtenir une fraction  irréductible à partir  de la
liste du développement en fraction continue.

\label{fci}

Souvenez-vous~:
\[
\frac{172}{51}=3+\frac{19}{51}=3+\frac{1}{\frac{51}{19}}=3+\frac{1}{2+\frac{13}{19}}=
3+\frac{1}{2+\frac{1}{1+\frac{1}{2+\frac{1}{6}}}}=[3;2;1;2;6]
\]

On en déduit l'algorithme suivant~:



\begin{algorithm}[H]
\caption{Fractions continues~:~le retour récursif}
\texttt{frac\_inv(lx)}\;
\Entree{La liste lx du développement en fraction continue}\;
\Deb{
\eSi{lx ne contient qu'un seul élément }{\Retour{cet élément}
}{\Retour{le  premier élément  de  lx  +l'inverse de  {\rm\texttt{frac\_inv}}(lx  privé de  son
  premier élément)}}
 } 
\end{algorithm}

\begin{lstlisting}[caption={développement de fractions continues (1)}]
# let rec frac_inv(lx)=
      if List.length lx=1 then [List.hd(lx);1]
      else som([List.hd(lx);1],inv(frac_inv(List.tl(lx))));;
\end{lstlisting}


ou bien sans \og \texttt{List}\fg{}~:


\begin{lstlisting}[caption={développement de fractions continues (2)}]
# let rec frac_inv = function
      | x::[] -> [x;1]
      | x::l -> som([x;1],inv(frac_inv(l)));;
\end{lstlisting}


Et voici comment l'utiliser~:

\begin{lstlisting}
# frac_inv([3;2;1;2;6]);;
- : int list = [172; 51]
\end{lstlisting}

Une petite curiosité au passage~:

\begin{lstlisting}
# frac_inv([0;3;2;1;2;6]);;
- : int list = [51; 172]
\end{lstlisting}


\xc







\chapter{Algorithmes de calcul plus complexes}

\section{Algorithme de \textsc{Hörner}}

\subsection{Conventions}
Dans la  suite, nous confondrons  polynôme et fonction polynôme,  ce qui
n'est pas  gênant si on travaille  sur $\bbr[X]$. Pour  aller vite, nous
utiliserons un vocabulaire non connu des élèves de 2\up{nde} mais tout à
fait  adaptable car  les notions  sont  simples et  font travailler  les
expressions algébriques et réflechir sur la complexité d'un calcul.


\subsection{Principe}

Prenons   l'exemple   de   $P(x)=3x^5-2x^4+7x^3+2x^2+5x-3$.  Le   calcul
classique nécessite 5 additions et 15 multiplications.




On peut faire pas mal d'économies de calcul en suivant le schéma suivant :

\begin{center}
\begin{arrayl}
P(x)&=&\ds\underbrace{a_nx^n+\cdots+a_2x^2+a_1x}_{\text{on met $x$ en facteur}}+a_0\\
            &=&\left(\ds\underbrace{a_nx^{n-1}+\cdots+a_2x}_{\text{on met $x$ en facteur}}+a_1\right)x+a_0\\
            &=& \cdots\\
            &=& \left(\cdots(((a_nx+a_{n-1})x+a_{n-2})x+a_{n-3})x+\cdots\right)x+a_0\\
\end{arrayl}
\end{center}


Ici   cela   donne   $P(x)=(((((3x)-2)x+7)x+2)x+5)x-3$  c'est-à-dire   5
multiplications et 5 additions. En fait il y a au maximum $2\times$degré
de P opérations (voire moins avec les zéros).

\subsection{Algorithme récursif}

Il faut connaître les coefficients de P. 



\begin{algorithm}[H]
\caption{algorithme de \textsc{Hörner} : version récursive}
horner(P,x)
\Entree{les  coefficients $a_i$ dans  l'ordre décroissant  des exposants
  des monômes, le degré $n$ de P et le nombre $x$}\;
\Deb{
\eSi{P est vide}{\Retour{0}}\;
{\Retour{Tête de P + x$\times$ horner(P privé de sa tête, x)}
}
 } 
\end{algorithm}



\subsubsection{En XCAS}

\begin{lstlisting}[caption={algorithme de Hörner en récursif (XCAS)}]
Horner(P,x):={
if(P=[]){return(0)}
else{return(P[0]+x*Horner(tail(P),x))}
}:;
\end{lstlisting}



\subsubsection{En CAML}

\caml

\begin{lstlisting}[caption={algorithme de Hörner en récursif (CAML)}]
# let rec horner = function
   |([],x) -> 0
   |(tete::queue,x) -> tete + x*horner(queue,x);;
\end{lstlisting}

Ainsi, pour calculer $P(3)$ avec $P(x)=3x^5-2x^4+7x^3+2x^2+5x-3$~:


\begin{lstlisting}
# horner([3;-2;7;2;5;-3],3);;
- : int = -210
\end{lstlisting}

\subsubsection{En Sage/Python}

\sage


\begin{lstlisting}[caption={algorithme de Hörner en récursif (Sage)}]
def queue(L):
    del L[0];
    return L

def horner(P,x):
    if P==[] : return 0
    else :
        return P[0]+x*horner(queue(P),x)
\end{lstlisting}

Par exemple:

\begin{lstlisting}[caption={}]
sage: horner([3,-2,7,2,5,-3],x)
-((((3*x - 5)*x - 2)*x - 7)*x + 2)*x + 3
sage: horner([3,-2,7,2,5,-3],3)
-210
\end{lstlisting}

\xc

\subsection{Algorithme impératif}


Pour la version impérative~:

\begin{algorithm}[H]
\caption{algorithme de \textsc{Hörner} : version impérative}
\Entree{les  coefficients $a_i$ dans  l'ordre décroissant  des exposants
  des monômes, le degré $n$ de P et le monôme $x$}\;
\Ini{Q\aff $a_n$}\;
\Deb{
\Pour{k de 1 à $n$}{
Q\aff $Q\times x+a_k$
}\;
\Retour{Q}\;
 } 
\end{algorithm}

\subsubsection{traduction XCAS}

\begin{lstlisting}[caption={algorithme de Hörner version impérative}]
Horner(C,d,x):={
local Q,k;
Q:=C[0];
pour k de 1 jusque d  faire
   Q:=(Q*x)+C[k];
fpour;
retourne(Q)
}
\end{lstlisting}

Pour notre exemple, on entre~:

\begin{lstlisting}
(Horner([3,-2,7,2,5,-3],5,X))
\end{lstlisting}

et on obtient bien~:

\[((((3*X-2)*X+7)*X+2)*X+5)*X-3\]




\section{Exponentiation rapide}

\subsection{Méthode naïve}


Calculer   $a^{n}$  nécessite   a  priori   $n-1$   multiplications  selon
l'algorithme suivant~:


\subsubsection{En impératif}

\begin{algorithm}[H]
\caption{exponentiation naïve}
\Entree{un réel $a$ et une puissance $n$}\;
\Ini{Résultat\aff a}\;
\Deb{
\Pour{k de 2 à n}{
Résultat\aff Résultat$\times$a}
 } 
\Retour{Résultat}
\end{algorithm}


\subsubsection{Avec XCAS }

\begin{lstlisting}[caption={exponentiation rapide version impérative (XCAS)}]
puissance_naive(a,n):={
local res,k;
res:=a;
pour k de 2 jusque n faire
res:=res*a;
fpour;
retourne(res);
}:;
\end{lstlisting}

\subsubsection{Avec Sage/Python }

\sage

\begin{lstlisting}[caption={exponentiation rapide version impérative (Sage)}]
def puissance_naive(a,n):
    res=a
    for k in [2..n]:
        res*=a
    return res


sage: puissance_naive(2,10)
1024
\end{lstlisting}

\subsubsection{ Version récursive}


\begin{algorithm}[H]
\caption{exponentiation naïve récursive}
\Proc{puissance\_naive\_rec}
\Entree{un réel $a$ et une puissance $n$}
\Deb{
\eSi{$n$ est nul}{\Retour{1}}{
a multiplié par puissance\_naive\_rec(a,n-1)
}
 } 
\end{algorithm}

\subsubsection{Avec XCAS}


\xc
\begin{lstlisting}[caption={exponentiation rapide version récursive (XCAS)}]
puissance_naive_rec(a,n):={
si n==0 alors retourne(1); 
  sinon puissance_naive_rec(a,n-1)*a;
fsi;
}:;
\end{lstlisting}

\subsubsection{Avec CAML}

\caml

\begin{lstlisting}[caption={exponentiation rapide version récursive (CAML)}]
let rec puissance_naive_rec(a,n)=
if n=0 then 1 
  else puissance_naive_rec(a,n-1)*a;;
\end{lstlisting}




\subsubsection{Avec Sage/Python }

\sage

\begin{lstlisting}[caption={exponentiation rapide version récursive (Sage)}]
def puissance_naive_rec(a,n):
    if n==0 : return 1
    else : return puissance_naive_rec(a,n-1)*a
\end{lstlisting}














\xc


\subsection{Avec l'algorithme de \textsc{Hörner}}

 On peut essayer
de faire  mieux, surtout si on  pense aux problèmes  de cryptographie du
style RSA.

Voyons une première méthode  qui utilise l'algorithme de \textsc{Hörner}
étudié précédemment et la décomposition en base 2 de l'exposant.




Par  exemple, $11=1\times 2^3+0\times  2^2+1\times 2^1+1\times  2^0$. On
peut donc associer à cette écriture un polynôme P tel que 11 soit égal à
$P(2)$~:

\[P(X)=1\times X^3+0\times  X^2+1\times X^1+1\times  X^0=((X+0)X+1)X+1\]


Donc    $a^{P(2)}=a^{1+2(1+2(2\times    1+0))}=a\cdot   a^{2(1+2(2\times
  1+0))}=a\cdot\left(a^{1+2(2\times
    1+0)}\right)^2=a^1\cdot\left(a^1\cdot\left(a^0\cdot\left(a^1\right)^2\right)^2\right)^2=\left(\left(\left(a^1\right)^2a^0\right)^2a^1\right)^2a^1$




On en déduit l'algorithme~:


\begin{algorithm}[H]
\caption{exponentiation \og à la \textsc{Hörner}\fg{}}
\Entree{un réel a et un entier n}\;
\Ini{
C\aff décomposition de n en base 2\;
res\aff a\;
}\;
\Deb{
\Pour{j de 1 jusque taille de C -1}{
res\aff res $\times$ res\;
\Si{le j-ème chiffre de la décomposition en base 2 est 1}{res\aff a$\times$res}
}
\Retour{res}
 } 
\end{algorithm}

\subsubsection{Avec XCAS en impératif}



\begin{lstlisting}[caption={exponentiation rapide en récursif \og à la Hörner\fg{}}]
puissance_horner(a,n):={
local C,j,res;
C:=base_deux(n);
res:=a;
pour j de 1 jusque size(C)-1 faire
  res:=res*res;
  si C[j]==1 alors res:=a*res; 
  fsi;
fpour;
retourne(res);
}:;
\end{lstlisting}

Pour  calculer  $a^{11}$  nous  n'avons  donc plus  à  effectuer  que  6
multiplications ou plutôt 5 si on ne compte pas la multiplication par 1.


\subsubsection{Avec Sage/Python en impératif}

\sage

\begin{lstlisting}[caption={exponentiation rapide en récursif \og à la Hörner\fg{}}]
def puissance_horner(a,n):
    C=base2(n)
    res=a
    for j in [1..len(C)-1]:
        res*=res
        if C[j]==1: res*=a
    return(res)
  \end{lstlisting}
  
\subsubsection{Avec CAML en version récursive}

\caml
\begin{lstlisting}[caption={exponentiation rapide en récursif \og à la Hörner\fg{}}]
# let pow_horn(a,n)=
  let rec pow_horn_rec(a,n,k)=
      if k=0 then a
      else if nth(binaire n) k=0 then pow_horn_rec(a,n,k-1)*pow_horn_rec(a,n,k-1)
           else a*pow_horn_rec(a,n,k-1)*pow_horn_rec(a,n,k-1)
  in pow_horn_rec(a,n,length(binaire n)-1);;
\end{lstlisting}

\xc


% \subsection{Variante sans utiliser l'algorithme de \textsc{Hörner}}


% $a^{11}=a^{1\times   2^0+1\times  2^1+0\times   2^2+1\times  2^3}=a\cdot
% \left(a\right)^2\times \left(\left(a^2\right)^2\right)^2$

% On procède donc dans l'ordre~:

% \begin{align*}
% a^2=&a\cdot a\\
% a^4=&a^2\cdot a^2\\
% a^8=&a^4\cdot a^4\\
% a^{10}=&a^8\cdot a^2\\
% a^{11}=&a^{10}\cdot a
% \end{align*}

% soit 5 multiplications.


% \begin{algorithm}[H]
% \caption{exponentiation rapide sans \textsc{Hörner}}
% \Entree{}\;
% \Ini{}\;
% \Deb{

%  } 
% \end{algorithm}



\subsection{Variante sans utiliser l'écriture en base 2}

Voyons comment procéder sur notre exemple habituel~:

$a^{11}=a\cdot   a^{10}=a\cdot   \left(a^5\right)^2=a\cdot  \left(a\cdot
  a^4\right)^2=a\cdot \left(a\cdot \left(a^2\right)^2\right)^2$

Ainsi, on réduit l'exposant $k$ selon sa parité~:
\begin{itemize}
\item si $k$ est pair, on écrit $a^k=\left(a^{\frac{k}{2}}\right)^2$~;
\item sinon, $a^k=a\cdot \left(a^{\frac{k-1}{2}}\right)^2$
\end{itemize}


\begin{algorithm}[H]
\caption{exponentiation rapide sans utiliser la base 2}
\Entree{un réel a et un entier n}\;
\Ini{\;
res\aff 1\;
puissance\aff n\;
temp\aff a}\;
\Deb{
\Tq{puissance non nulle}{
\Si{puissance est impaire}{
res\aff temp$\times$res\;
puissance\aff puissance $-$ 1\;
}
puissance\aff puissance $\div$ 2\;
temp\aff temp$\times$temp
 } 
}
\end{algorithm}

\subsubsection{Avec XCAS en impératif}
\xc
\begin{lstlisting}[caption={exponentiation rapide en impératif (3) (XCAS)}]
expo_rapido(a,n):={
local res,temp,Puissance;
res:=1;
Puissance:=n;
temp:=a;
tantque Puissance >0 faire
   si irem(Puissance,2)==1 alors
      res:=temp*res;
      Puissance:=Puissance-1;
   fsi;
Puissance:=Puissance/2;
temp:=temp*temp;
ftantque;
retourne(res);
}:;
\end{lstlisting}




\subsubsection{Avec Sage/Python en impératif}
\sage
\begin{lstlisting}[caption={exponentiation rapide en impératif (3) (Sage)}]
def expo_rapido(a,n):
    res=1
    Puissance=n
    temp=a
    while Puissance>0:
        if Puissance%2==1 :
            res*=temp
            Puissance+=-1
        Puissance=Puissance/2
        temp*=temp
    return(res)

\end{lstlisting}

\subsubsection{Avec CAML en récursif}

Avec CAML en version récursive c'est immédiat~:

\caml
\begin{lstlisting}[caption={exponentiation rapide en récursif (3)}]
# let rec pow_rap(a,n)=
         if n=0 then a
	 else if n/2*2=n then pow_rap(a,n/2)*pow_rap(a,n/2)
              else a*pow_rap(a,n/2);;
\end{lstlisting}





\subsubsection{Avec Sage/Python en récursif}
\sage
\begin{lstlisting}[caption={exponentiation rapide en récursif (3) (Sage)}]
def pow_rap(a,n):
    if n==0 : return a
    elif n%2==0 :
        return pow_rap(a,n//2)**2
    else :
        return a*pow_rap(a,n//2)
      \end{lstlisting}
      


\xc







\subsection{Comparaison des performances}

Grâce à  la commande  \texttt{time} de XCAS,  nous pouvons  comparer les
temps   de    calcul   des   différents    algorithmes   pour   calculer
$2^{\nombre{1000000}}$~:

\begin{lstlisting}
time(puissance_naive(2,1000000))
\end{lstlisting}

donne 70.23 secondes sur notre ordinateur. 

Avec \texttt{expo\_rapido} le
temps tombe à 0,21 seconde et avec \texttt{puissance\_horner} 0,09 seconde~!



Mais réduire le  nombre d'itérations n'est pas toujours  efficace si les
opérations  engendrées  à chaque  itération  sont  plus compliquées.  Ce
serait  par exemple  le cas  si nous  travaillons avec  des  polynômes à
plusieurs variables... ce qui est loin du programme du lycée~! 

Cependant, il peut être intéressant  (en spécialité de terminale S ou un
futur  clone  quelconque...) d'adapter  cet  algorithme  à la  puissance
modulaire pour travailler par exemple  sur le \og petit\fg{} théorème de
\textsc{Fermat}.




\section{Calculatrice en légo}




Andrew \textsc{Carol} a fabriqué une machine à calculer entièrement constituée de légos.



Par exemple, considérons l'expression~:

\[P(x)=2x^2+3x+5\]

Alors la machine peut calculer  cette expression
en remplaçant $x$ par des nombres entiers.

\subsection{Le principe}

Remplissons le tableau suivant jusqu'à la 4\eme ligne~:

\begin{center}
             \begin{tabularx}{\textwidth}{Y{2}}
	     \whline
             $x$&$P(x)$&première différence&deuxième différence\\
             \hline
             1&10&9&4\\
             \hline
             2&19&13&\\
             \hline
             3&&&\\
             \hline
             4&&&\\
             \hline
             5&&&\\
\hline
             6&&&\\
\hline
             7&&&\\
\hline
             8&&&\\
\hline
             9&&&\\
             \whline
             \end{tabularx}
             \end{center}

sachant que 9 est obtenu en faisant $19-10$ et 4 en faisant $13-9$.

Qu'observez-vous dans la dernière colonne~?

Finissez  alors  de  remplir   le  tableau  en  n'effectuant  que  des
additions : c'est  tout ce que peut faire la machine  en légos grâce à
ses roues dentées.

\subsection{Un exemple}

Soit $Q(x)=4x^2+5*x+1$

Remplissez un  tableau similaire  au précédent en  n'effectuant aucune
multiplication...

\subsection{Généralisation}

Pourquoi   ça   marche~?   Essayez   de  remplir   un   tableau   avec
$R(x)=ax^2+bx+c$, $a$, $b$ et $c$ étant des nombres quelconques.

\subsection{Un petit brin d'informatique}

Faisons calculer l'ordinateur avec uniquement des additions.

\subsubsection{Version récursive avec CAML }

\caml
\begin{lstlisting}[caption={la machine légo en récursif (CAML)}]
#   let lego(n,a,b,c)=
      let rec legotemp(n,p,d1,d2)=
          if n=1 then p
          else legotemp(n-1,p+d1,d1+d2,d2)
      in legotemp(n,a+b+c,a+a+a+b,a+a);;
\end{lstlisting}
\xc


\subsubsection{Version récursive avec XCAS }

\begin{lstlisting}[caption={la machine légo en récursif 1ère étape (XCAS)}]
legotemp(n,p,d1,d2):={
  if(n==1)then{p}
          else{legotemp(n-1,p+d1,d1+d2,d2)}
}:;
\end{lstlisting}

puis 

\begin{lstlisting}[caption={la machine légo en récursif 2ème étape (XCAS)}]
lego(n,a,b,c):={
legotemp(n,a+b+c,a+a+a+b,a+a)
}:;
\end{lstlisting}

Par  exemple,  avec  $P(x)=2x^2+3x+5$,  on peut  calculer  $P(20)$  avec
uniquement des sommes~:

\begin{lstlisting}
lego(20,2,3,5)
\end{lstlisting}

\reponse{865}


\subsubsection{Version impérative avec XCAS }

\begin{lstlisting}[caption={la machine légo en impératif}]
lego(n,a,b,c):={

local p,d1,d2,k;

p:=a+b+c;
d1:=a+a+a+b;
d2:=a+a;

 for(k:=1;k<n;k:=k+1){
   p:=p+d1;
   d1:=d1+d2;}

return(p)
}:;
\end{lstlisting}


\section{Tableaux de signes}

On  veut  étudier le  signe  d'un produit  de  2  facteurs affines.  Par
exemple, en tapant \texttt{signeproduit(-2*x+3,4*x+5)} on veut obtenir~:
  \[
    \left[\begin{array}{lccccc}
\mbox{valeurs de x} & \mbox{  } & -\frac{5}{4} & \mbox{  } & \frac{3}{2} & \mbox{  } \\
\mbox{signe de -2x+3} & \mbox{ + } & \mbox{ } & \mbox{ + } & 0 & \mbox{ - } \\
\mbox{signe de 4x+5} & \mbox{ - } & 0 & \mbox{ + } & \mbox{ } & \mbox{ + } \\
\mbox{signe du produit} & \mbox{ - } & 0 & \mbox{ + } & 0 & \mbox{ - }
\end{array}\right] 
  \]

Pour cela, on divise le tableau en plusieurs zones~:

\begin{center}
             \begin{tabularx}{\linewidth}{Y{4}}
	     \whline
             Valeurs de $x$ & & 1 & & 2 & \\
             \hline
             Signe de $ax+b$&3 & 4 &5 & 6 &7\\
             \hline
             Signe de $cx+d$&8 & 9 &10&11 &12\\
             \hline
             Signe du produit & 13 &14&15 &16&17\\

             \whline
             \end{tabularx}
             \end{center}
Reste à savoir comment remplir les 17 cases numérotées...

Nous aurons besoin de résoudre des équations affines pour déterminer les
zéros.



Voici un petit algorithme qui va nous rendre service~:


\begin{algorithm}[H]
\caption{résolution d'équations affines}
\Entree{expression affine d'inconnue x sous la forme ax+b}\;
\Deb{
\eSi{a=0}{\Retour{il n'y a pas de solution unique}}{
\Retour{-b/a}
}
 } 
\end{algorithm}

XCAS sait résoudre ce genre d'éqtions grâce à la commande \texttt{resoudre}.



Il est  également simple  de déterminer le  minimum et le  maximum entre
deux réels. Par exemple~:


\begin{algorithm}[H]
\caption{minimum d'une liste de deux réels}
\Entree{une liste L de deux réels}\;
\Deb{
\eSi{L[0]<L[1]}{\Retour{L[0]}}{\Retour{L[1]}}
 } 
\end{algorithm}

Ensuite, il ne reste plus qu'à distinguer les cas...



\begin{algorithm}[H]
\caption{étude du signe d'un produit de facteurs affines}
\Entree{deux expressions affines ax+b et cx+d}\;
\Ini{\;
zA\aff solution de ax+b=0;
zB\aff solution de cx+d=0\;
zmin\aff minimum de (zA,zB);
zmax\aff maximum de (zA,zB)\;
}
\Deb{
On construit un tableau\;
\smallskip 
\fbox{1ère ligne : valeurs de x}\;
\smallskip
un vide puis
on affiche zmin puis
un vide puis
on affiche zmax puis
un videpuis 

\smallskip 
\fbox{2ème ligne : signe de f(x)=ax+b}\;
\smallskip
  \eSi{f(zmin-1)>0}{on affiche +}{on affiche -}
  \eSi{f(zmin)=0}{on affiche 0}{on n'affiche rien}
  \eSi{l'image par f du milieu  de zmin et zmax est positive}{on affiche
    +}{on affiche -}\;
  \eSi{f(zmax)=0}{on affiche 0}{on n'affiche rien}
  \eSi{f(zmax-1)>0}{on affiche +}{on affiche -}\;
 \smallskip 
\fbox{3ème ligne : signe de g(x)=cx+d}\;
\smallskip
 idem en remplaçant f par g\;
\smallskip 
\fbox{4ème ligne : signe du produit}\;
\smallskip 
 \eSi{le  signe  du  produit des  images  de  zmin-1  par  f et  g  est
    positif}{on affiche +}{on affiche -}\;
  on affiche 0\;
  \eSi{le signe du produit des images du milieu de zmin et zmax par f et g est
    positif}{on affiche +}{on affiche -}\;
  on affiche 0\;
  \eSi{le  signe  du  produit des  images  de  zmax+1  par  f et  g  est
    positif}{on affiche +}{on affiche -}\;

} 
\end{algorithm}


\begin{lstlisting}[caption={signe d'un produit de facteurs affines}]
signeproduit2(F,G):={
f:=unapply(F,x);
g:=unapply(G,x); \\ on transforme les expressions F et G en fonctions
zA:=resoudre(f(x)=0,x)[0];
zB:=resoudre(g(x)=0,x)[0];
zmin:=min(zA,zB);
zmax:=max(zA,zB);
[ ["valeurs de x","  ",zmin,"  ",zmax,"  "],
     
     ["signe de "+f(x),   si f(zmin-1)>0 alors " + "; sinon " - "; fsi,
                          si f(zmin)==0 alors 0; sinon " ";fsi,
                          si f((zmin+zmax)*.5)>0 alors " + "; sinon " - "; fsi,
                          si f(zmax)==0 alors 0; sinon " ";fsi,
                          si f(zmax+1)>0 alors " + "; sinon " - "; fsi
     ],

     ["signe de "+g(x),   si g(zmin-1)>0 alors " + "; sinon " - "; fsi,
                          si g(zmin)==0 alors 0; sinon " ";fsi,
                          si g((zmin+zmax)*.5)>0 alors " + "; sinon " - "; fsi,
                          si g(zmax)==0 alors 0; sinon " ";fsi,
                          si g(zmax+1)>0 alors " + "; sinon " - "; fsi
     ],
     ["signe du produit", si g(zmin-1)*f(zmin-1)>0 alors " + "; sinon " - "; fsi,
                          0,
                          si g((zmin+zmax)*.5)*f((zmin+zmax)*.5)>0 alors " + "; sinon " - "; fsi,
                          0,
                          si g(zmax+1)*f(zmax+1)>0 alors " + "; sinon " - "; fsi
     ]
]
}:;
\end{lstlisting}

On peut généraliser à un nombre quelconque de facteurs et même à des cas
plus compliqués comme vous pouvez le voir ici à partir de la ligne 1802~:

\href{http://download.tuxfamily.org/tehessinmath/les_sources/tablor.html}{http://download.tuxfamily.org/tehessinmath/les\_sources/tablor.html}



































\chapter{Algorithmes en analyse}


\section{Les réels et le processeur}


Ayez toujours en  tête qu'un ordinateur ne peut  pas travailler avec des
réels~! Par  essence, il a un nombre  fini de bits sur  lesquels il peut
coder des nombres...

Les nombres \textit{flottants} qu'il  manipule sont donc des classes qui
représentent chacune une infinité de  réels (mais tout en constituant un
intervalle cohérent).

Si on n'y fait pas attention, cela peut créer des surprises...

Entrons trois nombres sur XCAS~:
\xc
\begin{lstlisting}
x:=10;
y:=-5;
z:=5.00000001;
\end{lstlisting}


Alors

\begin{lstlisting}
(x*y)+(x*z)
\end{lstlisting}

renvoie~:

\reponse{1.000000012e-07}

Mais 

\begin{lstlisting}
x*(y+z)
\end{lstlisting}


renvoie~:

\reponse{9.999999939e-08}

Le problème est le même avec CAML~:

\caml

\begin{lstlisting}
# let x,y,z=10.,-5.,5.00000001;;
val x : float = 10.
val y : float = -5.
val z : float = 5.00000001

# (x*.y)+.(x*.z);;
- : float = 1.00000001168609742e-07

# x*.(y+.z);;
- : float = 9.99999993922529e-08
\end{lstlisting}



ou avec Sage:

\sage

\begin{lstlisting}[caption={}]
sage: [x,y,z]=[10,-5,5.00000001]
sage: (x*y)+(x*z)
1.00000001168610e-7
sage: x*(y+z)
9.99999993922529e-8
\end{lstlisting}

Ainsi l'addition  n'est pas toujours distributive  sur la multiplication
quand on travaille sur les flottants~!


Ces petites erreurs qui s'accumulent peuvent en créer de grandes~! 

Créons  une fonction  qui renvoie  l'approximation de  la  dérivée d'une
fonction en un nombre donné avec un \og \verb+dx+\fg{} valant $10^{-10}$~:


\caml
\begin{lstlisting}[caption={dérivation numérique}]
# let dernum(f)=function
          x->(f(x+.0.0000000001)-.f(x))/.0.0000000001;;
\end{lstlisting}

Dérivons le sinus  cinq fois de suite et évaluons  la fonction obtenue en
0~:

\begin{lstlisting}
# dernum(dernum(dernum(dernum(dernum(sin)))))(0.);;
- : float = -1.33226762955018773e+25
\end{lstlisting}

Oups !  On obtient  $\cos(0)\approx -10^{25}$...Ce n'est plus de l'ordre
de l'erreur négligeable~!


\section{Tracé de représentations graphiques}


\subsection{Version récursive à pas constant}

\subsubsection{Avec XCAS}
\xc
\begin{lstlisting}[caption={liste de coordonnées de points d'un graphe de fonction en récursif (XCAS)}]
liste_points(f,a,b,h):={
if(a>b)then{[b,f(b)]}
else{[a,f(a)],liste_points(f,a+h,b,h)}
}:;
\end{lstlisting}

On a créé une liste de coordonnées du type $(x,f(x))$ avec un pas de $h$ entre $a$ et $b$.

On relie ces points par des segments avec \texttt{polygonplot(liste de coordonnées)}~:

\begin{lstlisting}
graph(f,a,b,h):={
polygonplot([liste_points(f,a,b,h)])
}:;
\end{lstlisting}


Par exemple, on trace la fonction carrée entre $-2$ et 2 avec un pas de $0,75$~:


\begin{lstlisting}
graph(x->x^2,-2,2,0.75)
\end{lstlisting}

ce qui donne~:



\begin{figure}
\begin{center}
  \includegraphics{carre}
\end{center}
\end{figure}


\subsubsection{Avec Sage}


\sage

\begin{lstlisting}[caption={liste de coordonnées de points d'un graphe de fonction en récursif (Sage)}]
def liste_points(f,a,b,h):
    if a>b : return [[b,f(b)]]
    else : return [[a,f(a)]]+liste_points(f,a+h,b,h)
  \end{lstlisting}
  



Par exemple, on trace la fonction carrée entre $-2$ et 2 avec un pas de $0,75$~:


\begin{lstlisting}[caption={}]
def f(x):
    return x**2

def graph(f,a,b,h):
    l=line(liste_points(f,a,b,h))
    l.show()
\end{lstlisting}


Ce qui donne:


%\begin{figure}
\begin{center}
  \includegraphics{graph_sage_1}
\end{center}
%\end{figure}



\subsection{Version récursive par sondage aléatoire}

On interroge au hasard un réel et on lui demande son image par une certaine fonction~:~cela nous permettra-t-il d'avoir une bonne idée de l'allure de la courbe~?


\subsubsection{Avec XCAS}

\xc

\begin{lstlisting}[caption={liste aléatoire de point du graphe d'une fonction (XCAS)}]
liste_points_hasard(f,a,a0,b,n):={
if(n==0)then{[b,f(b)]}
else{[a0,f(a0)],liste_points_hasard(f,a,a+rand(0,1)*(b-a),b,n-1)}
}:;
\end{lstlisting}


\begin{lstlisting}
graph_hasard(f,a,b,n):={
polygonplot([liste_points_hasard(f,a,a,b,n)])
}:;
\end{lstlisting}


Alors on obtient pour la fonction sinus entre $-5$ et $5$ avec $8$ \og sondés\fg{}~:

\begin{lstlisting}
graph_hasard(x->sin(x),-5,5,8)
\end{lstlisting}


donne~:


\begin{figure}
\begin{center}
  \includegraphics{sinhasard}
\end{center}
\end{figure}

\subsubsection{Avec Sage}

\sage

\begin{lstlisting}[caption={liste aléatoire de point du graphe d'une fonction (Sage)}]
def liste_points_hasard(f,a,b,n):
    if n==0 : return [[b,f(b)]]
    else : return [[a,f(a)]]+liste_points_hasard(f,a+random()*(b-a)/n,b,n-1)

def graph_hasard(f,a,b,n):
    l=line(liste_points_hasard(f,a,b,n))
    l.show()
\end{lstlisting}



Ce qui donne pour le sinus entre $-5$ et 5:

\begin{lstlisting}[caption={}]
def f(x):
    return sin(x)

sage: graph_hasard(f,-5,5,8)
\end{lstlisting}



%\begin{figure}
\begin{center}
  \includegraphics{graph_sage_2}
\end{center}
%\end{figure}


\section{Fonctions définies par morceaux}

Comment faire dessiner une courbe en dents de scie, chaque dent ayant une
largeur  de  2  et  une  hauteur  de  1~?   Peut-on  avoir  une  formule
explicite qui permette de calculer l'image de n'importe quel nombre~?


Les coefficients directeurs valent alternativement $1$ et $-1$.

Les ordonnées s'annulent aux points d'abscisses paires...

\subsection{Avec XCAS}

\xc
\begin{lstlisting}[caption={fonction \og dent de scie\fg{}}]
scie_rec(n):={
if(n==0)then{[0,0]}
  else{[n,(1-(-1)^n)/2],scie_rec(n-1)}  
}:;
\end{lstlisting}


Puis:


\begin{lstlisting}
scie(n):={
polygonplot([scie_rec(n)])
}:;
\end{lstlisting}


Alors 


\begin{lstlisting}
scie(7)
\end{lstlisting}

donne~:



\begin{figure}
\begin{center}
  \includegraphics{scie1}
\end{center}
\end{figure}

Le tracé a été obtenu sans formule explicite pour chaque réel. Cherchons
une telle formulation~:

\begin{lstlisting}[caption={fonction dent de scie (2)}]
f(x):={
   if(irem(floor(x),2)==0)
      then{x-floor(x)}
      else{1-x+floor(x)}
}:;
\end{lstlisting}

sachant que  \texttt{floor} donne la partie entière  et \texttt{irem} le
reste de la division euclidienne.

\subsection{Avec Sage}

\sage
\begin{lstlisting}[caption={fonction \og dent de scie\fg{}}]
def scie_rec(n):
    if n==0 : return [[0,0]]
    else : return [[n,(1-(-1)**n)/2]]+scie_rec(n-1)

def scie(n):
    l=line(scie_rec(n))
    l.show()
\end{lstlisting}



Alors:

\begin{lstlisting}[caption={}]
scie(7)
\end{lstlisting}

donne:



%\begin{figure}
\begin{center}
  \includegraphics{graph_sage_3}
\end{center}
%\end{figure}


\section{Recherche de minimum}


On repère graphiquement qu'une  fonction semble atteindre par exemple un
minimum. Pour  obtenir une  approximation de ce  minimum, on  fournit un
point de départ et une précision.



\subsection{Version récursive}

\subsubsection{En XCAS}
\xc
\begin{lstlisting}[caption={minimum d'une fonction en récursif 1 (XCAS)}]
min_rec(f,xo,h):={
if(f(xo+h)>f(xo)){return(xo)}
else{min_rec(f,xo+h,h)}
}
\end{lstlisting}



\subsubsection{En CAML}


\caml

\begin{lstlisting}[caption={minimum d'une fonction en récursif 1 (CAML)}]
# let rec min_rec(f,xo,h)=
    if f(xo+.h)>f(xo) then xo
    else min_rec(f,xo+.h,h);;
\end{lstlisting}

\subsubsection{En Sage}


\sage

\begin{lstlisting}[caption={minimum d'une fonction en récursif 1 (Sage)}]
def min_rec(f,xo,h):
    if f(xo+h)>f(xo): return xo
    else : return min_rec(f,xo+h,h)
\end{lstlisting}


Par exemple,    pour           la            fonction
$x\mapsto\sqrt{x^{2}+25}+\sqrt{\left(x-18\right)^{2}+49}  $,  il  semble
que le minimum soit vers 7.


Demandons une approximation du minimum à $10^{-1}$ près~:


\begin{lstlisting}[caption={}]
def f(x):
    return sqrt((x)**2+25)+sqrt((x-18)**2+49)

sage: min_rec(f,7,0.1)
7.50000000000000
\end{lstlisting}


\xc




\subsection{Version impérative}

\begin{algorithm}[H]
\caption{approximation d'un minimum}
\Entree{fonction f, point de départ xo et incrément i}
\Ini{
Y\aff f(xo)
X\aff xo+i
}
\Deb{
\Tq{t(X)<Y}{
Y\aff evalf(t(X))
X\aff X+i
}
\Retour{X-i}
 } 
\end{algorithm}

\subsubsection{Avec XCAS}


\begin{lstlisting}[caption={minimum d'une fonction en impératif (XCAS)}]
minimum(f,xo,p):={
local X,Y,compteur;
Y:=f(xo);
X:=xo+10^(-p);
compteur:=0 // on rajoute un compteur pour que la compilation ne dure pas trop longtemps
tantque evalf(f(X))<Y et compteur<10^p faire 
    Y:=evalf(f(X)); 
    X:=X+10^(-p);
    compteur:=compteur+1; 
ftantque:;
 X-10^(-p);
}:;
\end{lstlisting}


Par            exemple,            pour           la            fonction
$x\mapsto\sqrt{x^{2}+25}+\sqrt{\left(x-18\right)^{2}+49}  $,  il  semble
que le minimum soit vers 7.


Demandons une approximation du minimum à $10^{-5}$ près~:

\begin{lstlisting}
minimum(x->sqrt((x)^2+25)+sqrt((x-18)^2+49),7.0,5)
\end{lstlisting}


et on obtient 7.50000

\subsubsection{Avec Sage}

\sage
\begin{lstlisting}[caption={minimum d'une fonction en impératif (Sage)}]
def minimum(f,xo,p):
    Y=float(f(xo))
    X=float(xo+10**(-p))
    compteur=0
    while f(X)<Y and compteur<10**p:
        Y=f(X)
        X+=10**(-p)
        compteur+=1
    return X-10**(-p)
\end{lstlisting}


Par exemple:

\begin{lstlisting}[caption={}]
def f(x):
    return sqrt((x)**2+25)+sqrt((x-18)**2+49)

sage: minimum(f,7,5)
7.4999999999810711
\end{lstlisting}


\subsection{Recherche de minimum avec affinage progressif du pas}



On  peut   améliorer  la  situation   en  affinant  petit  à   petit  le
balayage~:~d'abord $h$ puis $h/10$, etc.



\subsubsection{Avec XCAS}

\xc
\begin{lstlisting}[caption={minimum d'une fonction en récursif 2 (XCAS)}]
min_bis(f,xo,h,p):={
if(abs(h)<p)then{xo}
else{if(f(xo+h)>f(xo))
     then{min_bis(f,xo,-0.1*h,p)}
     else{min_bis(f,xo+h,h,p)}
}
}:;
\end{lstlisting}


\subsubsection{Avec CAML}

\caml

\begin{lstlisting}[caption={minimum d'une fonction en récursif 2 (CAML)}]
# let rec min_bis(f,xo,h,p)=
  if abs_float(h)<p then xo
  else if f(xo+.h)>f(xo)
       then min_bis(f,xo,-.0.1*.h,p)
       else min_bis(f,xo+.h,h,p);; 
\end{lstlisting}



\subsubsection{Avec Sage}

\sage
\begin{lstlisting}[caption={minimum d'une fonction en récursif 2 (Sage)}]
def min_bis(f,xo,h,p):
    if abs(h)<p : return xo
    elif f(xo+h)>f(xo): return min_bis(f,xo,-0.1*h,p)
    else : return min_bis(f,xo+h,h,p)
\end{lstlisting}

\section{Courbe du blanc-manger}


On  note $d(x)$  la  distance de  $x$  à l'entier  le  plus proche  puis
$d_k(x)=\frac{d(2^kx)}{2^k}$                   et                  enfin
$bm(x)=\sum_{k=0}^{+\infty}d_k(x)$.


\subsubsection{Avec XCAS}


On a déjà défini la partie entière d'un réel page~\vpageref{per}~:
\xc
\begin{lstlisting}
pe(r):={
  si(r>=0) et (r<1) 
      alors 0
      sinon si r>0
            alors 1+pe(r-1)
            sinon -1+pe(r+1)
            fsi       
      fsi
}:;
\end{lstlisting}


On va l'utiliser pour définir $d$~:

\begin{lstlisting}[caption={distance d'un réel à l'entier le plus proche}]
d(x):={
  si x-pe(x)<=0.5 
     alors x-pe(x)
     sinon 1+pe(x)-x
  fsi
}:;
\end{lstlisting}


Puis $d_k$~:

\begin{lstlisting}
D(k,x):=d(2.0^k*x)/2.0^k:;
\end{lstlisting}

Pour $bm$, on utilisera bien sûr une somme partielle~:

\begin{lstlisting}[caption={fonction \og blanc-manger\fg{}}]
bm(n,x):={
  si n==0
    alors D(0,x)
    sinon D(n,x)+bm(n-1,x)
  fsi
}:;
\end{lstlisting}


On demande le tracé de la somme partielle jusqu'à $n=10$~:

\begin{lstlisting}
graphe(bm(10,x),x=0..1)
\end{lstlisting}

et on obtient~:


\begin{figure}
\begin{center}
  \includegraphics[width=\textwidth]{bm1}
\end{center}
\end{figure}

On aurait pu utiliser les outils formels de XCAS~:


\begin{lstlisting}
d(k,x):=min(2^k*x-floor(2^k*x),ceil(2^k*x)-2^k*x)/2.0^k
plot(sum(d(k,x),k=0..10),x=0..1)
\end{lstlisting}


Il s'agit d'un exemple de fonction continue et nulle part dérivable.




\subsubsection{Avec Sage}
\sage

\begin{lstlisting}[caption={courbe du blanc-manger avec Sage}]
def d(x):
    if x-floor(x)<=0.5 : return x-floor(x)
    else : return 1+floor(x)-x

def D(k,x):
    return d(x*2.**k)/2.**k

def bm(n,x):
    if n==0 : return D(0,x)
    else : return D(n,x)+bm(n-1,x)

def gbm(n):
    l=line([[x,bm(n,x)] for x in srange(0,1,0.0001)])
    l.show()
\end{lstlisting}


\begin{lstlisting}[caption={}]
sage: gbm(10)
\end{lstlisting}



%\begin{figure}
\begin{center}
  \includegraphics{graph_sage_4}
\end{center}
%\end{figure}




\section{Escalier de \textsc{Cantor}}


\subsection{Cas particulier}

On  part d'une  certaine  fonction  $f_0$ définie  sur  $[0;1]$ puis  on
définit $f_1$ à partir de $f_0$~:

\[
f_{1}(x)=\begin{cases} 
\frac{1}{2}f_{0}(3x)\quad \text{si } x\in \left[0;\frac{1}{3}\right]\\ 
\frac{1}{2}\quad \text{si } x\in \left[\frac{1}{3};\frac{2}{3}\right]\\ 
\frac{1}{2}+\frac{1}{2}f_{0}(3x-2)\quad       \text{si       }      x\in
\left[\frac{2}{3};1\right]\\
\end{cases} 
\]

On prend par exemple $f_0(x)=x$~:

\begin{figure}
\begin{center}
  \includegraphics{cantor.1}
\end{center}
\end{figure}


On réitère sur chaque segment \og oblique\fg{}. On peut faire travailler
les élèves sur les coefficients directeurs.


\subsubsection{Avec XCAS}
\xc
\begin{lstlisting}[caption={escalier de Cantor en récursif (XAS)}]
cantor(a,b,c,d,n):={
 if(n==0)
    then{[a,b],[c,d]} 
    else{cantor(a,b,(2*a+c)/3,(b+d)/2,n-1), 
         cantor((2*a+c)/3,(b+d)/2,(a+2*c)/3,(b+d)/2, n-1),  
         cantor((a+2*c)/3, (b+d)/2, c, d, n-1)}
}:;
\end{lstlisting}


Alors 

\begin{lstlisting}
polygonplot([cantor(0,0,1,1,10)])
\end{lstlisting}

donne~:

\begin{figure}
\begin{center}
  \includegraphics{escalier}
\end{center}
\end{figure}



\subsubsection{Avec CAML}

\caml
\begin{lstlisting}[caption={escalier de Cantor en récursif( CAML)}]
# let rec cantor(n,a,b,c,d)=
      if n=0 then (Graphics.moveto a b;Graphics.lineto c d)
      else (cantor(n-1,a,b,((2*a+c)/3),(b+d)/2);
            cantor(n-1,((2*a+c)/3),((b+d)/2),((a+2*c)/3),((b+d)/2));
            cantor(n-1,((a+2*c)/3),((b+d)/2),c,d););;
\end{lstlisting}

Puis on trace~:

\begin{lstlisting}
# Graphics.open_graph""; cantor(10,0,0,500,500);;
\end{lstlisting}


L'escalier de\textsc{Cantor} est continu, a presque partout une tangente
horizontale, et pourtant il monte~! 



\subsubsection{Avec Sage}

\sage
\begin{lstlisting}[caption={escalier de Cantor en récursif( Sage)}]
def cantor(a,b,c,d,n):
    if n==0 : return [[a,b],[c,d]]
    else : return cantor(a,b,(2*a+c)/3,(b+d)/2,n-1)+cantor((2*a+c)/3,(b+d)/2,(a+2*c)/3,(b+d)/2, n-1)+cantor((a+2*c)/3, (b+d)/2, c, d, n-1)


def gcantor(a,b,c,d,n):
    l=line(cantor(a,b,c,d,n))
    l.show()
\end{lstlisting}

Par exemple:

\begin{lstlisting}[caption={}]
sage: gcantor(0,0,1,1,10)
\end{lstlisting}

donne:

%\begin{figure}
\begin{center}
  \includegraphics{graph_sage_5}
\end{center}
%\end{figure}




\subsection{Généralisation}


On peut prendre un autre coefficient que $\frac{1}{2}$.


\[
f_{1}(x)=\begin{cases} 
tf_{0}(3x)\quad \text{si } x\in \left[0;\frac{1}{3}\right]\\ 
t+(1-2t)f_0(3x-1)\quad \text{si } x\in \left[\frac{1}{3};\frac{2}{3}\right]\\ 
1-t+tf_{0}(3x-2)\quad       \text{si       }      x\in
\left[\frac{2}{3};1\right]\\
\end{cases} 
\]


Par exemple, pour $f_0(x)=x$ et $t=\frac{2}{3}$, on a au départ~:



\begin{figure}
\begin{center}
  \includegraphics{cantor.2}
\end{center}
\end{figure}



\subsubsection{Avec XCAS}

\xc
\begin{lstlisting}[caption={zig-zag de Cantor en récursif)}]
zigzag(a,b,c,d,t,n):={
 if(n==0)
    then{[a,b],[c,d]} 
    else{zigzag(a,b,(2*a+c)/3,(1-t)*b+t*d,t,n-1), 
         zigzag((2*a+c)/3,(1-t)*b+t*d,(a+2*c)/3,t*b+(1-t)*d,t, n-1),  
         zigzag((a+2*c)/3,t*b+(1-t)*d, c, d, t,n-1)}
}:;
\end{lstlisting}


et 

\begin{lstlisting}
polygonplot([zigzag(0,0,1,1,2/3.0,10)])
\end{lstlisting}

donne~:


\begin{figure}
\begin{center}
  \includegraphics[width=\textwidth]{cantor2}
\end{center}
\end{figure}

On   obtient   quelque   chose   qui   s'approche  de   la   courbe   de
\textsc{Bolzano-Lebesgue} qui est continue partout et dérivable nulle part...





\subsubsection{Avec Sage}

\sage
\begin{lstlisting}[caption={zigzag de Cantor en récursif( Sage)}]
def zigzag(a,b,c,d,t,n):
    if n==0 :  return [[a,b],[c,d]]
    else : return zigzag(a,b,(2*a+c)/3,(1-t)*b+t*d,t,n-1)+zigzag((2*a+c)/3,(1-t)*b+t*d,(a+2*c)/3,t*b+(1-t)*d,t, n-1)+zigzag((a+2*c)/3,t*b+(1-t)*d, c, d, t,n-1)


def gzigzag(a,b,c,d,t,n):
    l=line(zigzag(a,b,c,d,t,n))
    l.show()
\end{lstlisting}

Par exemple:

\begin{lstlisting}[caption={}]
sage: gzigzag(0,0,1,1,2/3.,10)
\end{lstlisting}

donne:

%\begin{figure}
\begin{center}
  \includegraphics{graph_sage_6}
\end{center}
%\end{figure}





On adapte facilement avec CAML.
















\section{Dichotomie}


Pour résoudre une équation  du type $f(x)=0$, on recherche graphiquement
un intervalle $[a,b]$ où la fonction semble changer de signe.

On note ensuite $m$ le milieu du segment $[a,b]$. On évalue le signe de $f(m)$.

Si c'est  le même  que celui  de $f(a)$ on  remplace $a$  par $m$  et on
recommence.  Sinon, c'est $b$  qu'on remplace  et on  recommence jusqu'à
obtenir la précision voulue.



\subsection{Version récursive}





\subsubsection{En XCAS}
\xc
\begin{lstlisting}[caption={dichotomie récursive (XCAS)}]
dicho_rec(f,a,b,eps):={
if(evalf(b-a)<eps){return(0.5*(b+a))};
if(f(a)*f(0.5*(b+a))>0){return(dicho(f,0.5*(b+a),b,eps))}
                   else{return(dicho(f,a,0.5*(b+a),eps))}
}:;
\end{lstlisting}

\subsection{En CAML}

\caml

\begin{lstlisting}[caption={dichotomie récursive (CAML)}]
# let rec dicho_rec(f,a,b,eps)=
    if abs_float(b-.a)<eps then 0.5*.(b+.a)
    else if f(a)*.f(0.5*.(b+.a))>0. then dicho_rec(f,0.5*.(b+.a),b,eps)
         else  dicho_rec(f,a,0.5*.(b+.a),eps);;
\end{lstlisting}



ce qui donne~:


\begin{lstlisting}
# dicho_rec( (fun x->(x*.x-.2.)),1.,2.,0.00001);;
- : float = 1.41421127319335938
\end{lstlisting}





\subsection{Avec Sage}


\sage
\begin{lstlisting}[caption={dichotomie en récursif (Sage/Python)}]
def dicho(f,a,b,p,compteur):
   if abs(b-a).n(digits=p)<10**(-p) : return [0.5*(b+a).n(digits=p+len(str(floor(a)))),compteur]
   elif f(a)*f(0.5*(b+a))>0 : return dicho(f,0.5*(b+a).n(digits=p+len(str(floor(a)))),b,p,compteur+1)
   else : return dicho(f,a,0.5*(b+a).n(digits=p+len(str(floor(a)))),p,compteur+1) 
\end{lstlisting}


Alors:

\begin{lstlisting}[caption={}]
sage:def f(x): return x**2-2
....: 
sage: dicho(f,1,2,5,0)
[1.41421, 17]

sage: def f(x): return x**2-153
....: 
sage: dicho(f,10,20,5,0)
[12.36931, 20]
\end{lstlisting}

Le rajout de \verb+len(str(floor(a)))+ permet d'adapter au nombre de chiffres de la partie entière.



\xc



\subsection{Version impérative}

\begin{algorithm}[H]
\caption{dichotomie}
\Entree{une fonction f, les bornes a et b, une précision p}\;
\Ini{aa\aff a, bb\aff b}\;
\Deb{
\Tq{bb-aa>p}{
\eSi{signe  de  f((aa+bb)/2) est  le  même  que  celui de  f(bb)}{bb\aff
  (aa+bb)/2}{aa\aff (aa+bb)/2}
}
\Retour{(aa+bb)/2}
 } 
\end{algorithm}


\subsubsection{Avec XCAS}

Avec XCAS, il faut juste ne pas oublier de régler quelques problèmes de précision~:


\begin{lstlisting}[caption={dichotomie impérative}]
dicho(F,p,a,b):={
local aa,bb,k,f;
aa:=a;
bb:=b;
epsilon:=1e-100; // on regle le "zero" de XCAS a une valeur suffisamment petite
f:=unapply(F,x);// on transforme l'expression f en fonction
k:=0; // on place un compteur
 tantque evalf(bb-aa,p)>10^(-p) faire
    si sign(evalf(f((bb+aa)/2),p))==sign(evalf(f(bb),p))
      alors bb:=evalf((aa+bb)/2,p);
      sinon aa:=evalf((aa+bb)/2,p);
      k:=k+1; // un tour de plus au compteur
    fsi;
 ftantque;
retourne evalf((bb+aa)/2,p)+" est la solution trouvee  apres " +k+ " iterations";
}:;

\end{lstlisting}




\subsubsection{Avec Sage/Python}

\sage

\begin{lstlisting}[caption={dichotomie en impératif (Sage)}]
def dicho(f,a,b,p):
  [aa,bb,compteur,c]=[a,b,0,len(str(floor(a)))]
  while (bb-aa).n(digits=p)>10**(-p):
     if f(0.5*(bb+aa))*f(bb)>0 :
        bb=(0.5*(aa+bb)).n(digits=p+c)
     else :
        aa=(0.5*(aa+bb)).n(digits=p+c)
     compteur=compteur+1
  return [(0.5*(aa+bb)).n(digits=p+c),compteur]
\end{lstlisting}





\section{Méthode des parties proportionnelles}

Il peut  être parfois plus efficace  de ne plus considérer  le milieu de
$[a;b]$ mais l'abscisse  de l'intersection de la droite  passant par les
points $(a,f(a))$ et $(b,f(b))$ avec l'axe des abscisses. Alors~:

\[\frac{x-a}{0-f(a)}=\frac{b-x}{f(b)-0}\]

avec $x$ vérifiant $f(x)=0$.

On obtient~:

\[x=\frac{af(a)-bf(b)}{f(b)-f(a)}\]

Il suffit de remplacer $\frac{a+b}{2}$ par le résultat précédent.


\subsection{Avec CAML en récursif}

\caml
\begin{lstlisting}[caption={partie proportionnelles en récurisf}]
# let rec propor_rec(f,a,b,eps)=
    if abs_float(b-.a)<eps 
       then (a*.f(b)-.b*.f(a))/.(f(b)-.f(a))
       else 
         if f(a)*.f((a*.f(b)-.b*.f(a))/.(f(b)-.f(a)))>0. 
           then propor_rec(f,(a*.f(b)-.b*.f(a))/.(f(b)-.f(a)),b,eps)
           else  propor_rec(f,a,(a*.f(b)-.b*.f(a))/.(f(b)-.f(a)),eps);;
\end{lstlisting}

\subsection{Avec XCAS en impératif}
\xc
\begin{lstlisting}[caption={parties proportionnelles en impératif (XCAS)}]
propor(F,p,a,b):={
local aa,bb,k,f,xo;
aa:=a;
bb:=b;
epsilon:=1e-100; // on règle le "zero" de XCAS a une valeur suffisamment petite
f:=unapply(F,x);// on transforme l'expression f en fonction
k:=0; // on place un compteur
 tantque evalf(bb-aa,p)>10^(-p) faire
    xo:=(aa*f(bb)-bb*f(aa))/(f(bb)-f(aa));
      si evalf(f(xo),p)*evalf(f(bb),p)>0
      alors bb:=evalf(xo,p);
      sinon aa:=evalf(xo,p);
      k:=k+1; // un tour de plus au compteur
    fsi;
 ftantque;
retourne evalf(xo,p)+" est la solution trouvée après " +k+ " itération(s)";
}:;
\end{lstlisting}

On remarque que 

\begin{lstlisting}
propor(x^2-2,10,1,2)
\end{lstlisting}



donne~:

\reponse{1.414213562 est la solution trouvée apres 20 itération(s)}


mais que~:

\begin{lstlisting}
propor(x^2-2,10,-2,-1)
\end{lstlisting}

donne~:

\reponse{-1.414213562 est la solution trouvée apres 1 itération(s)}


La  concavité joue  un  rôle  important pour  cette  méthode (faites  un
dessin...) alors que les résultats 
ne changent pas pour la dichotomie.




\section{Méthode de \textsc{Newton}}

Les  prérequis sont  plus nombreux~!  Il  faut avoir  étudié les  suites
définies   par   une   relation   du   type   $u_{n+1}=f(u_n)$   et   la
dérivation... et ne pas être trop perdu en Analyse...

Voici un exemple de TP possible en terminale.



\subsection{Historique}


La méthode de  résolution des équations numériques que  nous allons voir
aujourd'hui a  été initiée par  Isaac \textsc{Newton} vers 1669  sur des
exmples  numériques mais la  formulation est  fastidieuse. Dix  ans plus
tard, Joseph \textsc{Raphson} met en évidence une formule de récurrence. Un
siècle  plus tard, \textsc{Mouraille}  et \textsc{Lagrange}  étudient la
convergence  des approximations successives  en fonction  des conditions
initiales  par  une  approche  géométrique.  Cinquante  ans  plus  tard,
\textsc{Fourier}  et  \textsc{Cauchy}  s'occupe  de la  rapidité  de  la
convergence. 


\subsection{Principe}

\textsc{Newton} présenta sa méthode en traitant l'équation $x^3-2x-5=0$.

Soit $f$ la fonction $x\mapsto x^3-2x-5$. 
On peut rapidement tracer son graphe à l'aide d'un outil quelconque.

Il coupe l'axe des abscisses pour une valeur comprise entre 2 et 3.

On assimile la courbe à sa tangente au point d'abscisse 2.

Celle-ci a pour équation $y=(x-2)\times f'(2)+f(2)=10(x-2)-1$

Posons $x=2+\e$ alors $f(2+\e)=0\ssi \e^3+6\e^2+10\e-1=0$.

Si on  assimile la courbe à sa  tangente en 2, alors  $\e$ vérifie aussi
$0=10(2+\e-2)-1$ c'est-à-dire $\e=0,1$.

En fait, assimiler la courbe à sa tangente, c'est négliger les termes en
$\e$ d'ordre supérieur à 1 (ici $\e^3+6\e^2$).

Un approximation de la solution est donc 2,1.

On recommence ensuite  en partant de 2,1 au lieu de  2 puis on reprendra
la nouvelle valeur trouvée comme valeur de départ, etc.



% \section{Illustration graphique}

% L'exemple précédent correspond au graphe suivant.

  
% \begin{center}
%   \includegraphics[angle=270,width=.6\linewidth]{newtonmaple01.eps}  
%   \end{center}
  
 \subsection{La formule de récurrence}


On sent  la procédure  algorithmique poindre son  nez. Pour finir  de la
mettre  en évidence,  nous allons  formaliser la  méthode  précédente en
introduisant la suite des approximation successives.  


\begin{itemize}


\item On part d'un nombre  quelconque $x_0$~;
 \item \`a partir de $x_0$, on calcule un nouveau nombre $x_1$ de la
mani\`ere suivante (voir figure )~: on trace la tangente au graphe
de $f$ au point d'abscisse $x_0$, et on d\'etermine le point
d'intersection de cette tangente avec l'axe des abscisses. On
appelle $x_1$ l'abscisse de ce point d'intersection~;
\item et on recommence~: on calcule un nouveau
nombre $x_2$ en appliquant le proc\'ed\'e d\'ecrit au point 2 o\`u
l'on remplace $x_0$ par $x_1$~;
\item etc.
\end{itemize}


\begin{center}
  \includegraphics[width=.9\linewidth]{newton.1}
\end{center}




\`A partir de cette description graphique de
la m\'ethode de \textsc{Newton}, trouver la formule, notée (1), donnant $x_1$ en
fonction de $x_0$, puis $x_{n+1}$ en fonction de $x_n$.\\
Quelles hypoth\`eses doit-on faire sur $f$ et les $x_n$ pour que la
formule ait un sens~?\\

Nous n'irons pas  plus loin pour l'instant concernant  la convergence de
ces suites. Traitons l'exemple de \textsc{Newton}.


\subsection{Étude de la suite associée à l'équation $x^3-2x-5=0$.}


On   veut   résoudre  l'équation   $x^3-2x-5=0$   par   la  méthode   de
\textsc{Newton-Raphson} appelée  aussi méthode  de la tangente.  On note
$f$ la fonction $x\mapsto x^3-2x-5$.


\begin{enumerate}
\item  Montrez  rapidement  que  l'équation $f(x)=0$  admet  une  unique
  solution $\alpha$ sur $\bbr$. Montrez que $2<\alpha<3$.

\item Déterminez la fonction  $\f$ telle que $x_{n+1}=\f(x_n)$, la suite
  $(x_n)$ étant celle décrite au paragraphe précédent en prenant $x_0=3$.
\item Étudiez  le sens de  variation de la  fonction $\f$ puis  celui de
  $\f'$ et déduisez-en que $[\alpha,3]$  est stable par $\f$ et que $\f$
  est strictement croissante sur $[\alpha,3]$.
\item Que pouvez-vous en déduire sur la convergence de la suite $x_n$~?
\end{enumerate}


\subsection{Test d'arrêt}


Afin  de  construire  un  algorithme  donnant  une  approximation  d'une
solution    d'une    équation    numérique    par    la    méthode    de
\textsc{Newton-Raphson},   il  faudrait   déterminer  un   test  d'arrêt
c'est-à-dire savoir à partir de quel rang $n$ $|x_n-\alpha|$ restera 
inférieur à une valeur donnée.

Il suffit  de remarquer que  $f(x_n)=f(x_n)-f(\alpha)$. Nous supposerons
$f$ de classe $\CR^2$ sur un \og bon\fg{} voisinage I de $\alpha$ (ce
critère nous échappe encore à notre niveau).  Alors $f$ est en
particulier dérivable en $\alpha$ donc

$$f(x_n)=f(x_n)-f(\alpha)\sim f'(\alpha)\times(x_n-\alpha)$$

C'est-à-dire, puisque $f'(\alpha)$ est supposé non nul~:

$$x_n-\alpha\sim \frac{f(x_n)}{f'(\alpha)}$$

Or  $f$ étant de  classe $\CR^2$,  on a  $f'$ continue  et non  nulle en
$\alpha$ donc $f'(\alpha)\sim f'(x_n)$.

Finalement



$$x_n-\alpha\sim \frac{f(x_n)}{f'(x_n)}=x_n-x_{n+1}$$


Nous choisirons donc comme test d'arrêt $\left|\frac{f(x_n)}{f'(x_n)}\right|<p$
 avec $p$ la précision choisie.

Il ne reste plus qu'à écrire l'algorithme.

\subsection{Algorithme récursif}


D'abord l'algorithme sous forme récursive.  En fait, tout a déjà été dit
alors traduisons directement.


\subsubsection{Avec XCAS}

On    notera   que   \verb+function_diff(f)+    renvoie   la
\emph{fonction}  dérivée donc  \verb+function_diff(f)(x0)+  désigne 
le \emph{nombre} dérivé de $f$ en $x_0$.

\xc
\begin{lstlisting}[caption={méthode de Newton-Raphson en récursif (XCAS)}]
newton_rec(f,x0,eps):={
if(evalf(abs(f(x0)/function_diff(f)(x0)))<eps){evalf(x0)}
else{newton_rec(f,evalf(x0-f(x0)/function_diff(f)(x0)),eps)}
}:;
\end{lstlisting}


Alors, après avoir fixé par exemple la précision à 100~:

\begin{lstlisting}
DIGITS:=100:;
newton_rec(x->x^2-2,1.0,evalf(10^(-99)))
\end{lstlisting}

On obtient immédiatement~:

\verb+1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415728+

\subsubsection{Avec CAML}
Il y  a  un  petit plus  car  il  faut  définir une  dérivée
approchée.

\caml

\begin{lstlisting}
# let der(f,x,dx)=(f(x+.dx)-.f(x))/.dx;;
\end{lstlisting}


Maintenant la partie Newton~:

\begin{lstlisting}[caption={méthode de Newton-Raphson en récursif (CAML)}]
# let rec newton_rec(f,xo,dx,eps)=
     if abs_float(f(xo)/.der(f,xo,dx))<eps then xo
     else newton_rec(f,xo-.f(xo)/.der(f,xo,dx),dx,eps);;
\end{lstlisting}

Par exemple~:

\begin{lstlisting}
# let k(x)=x*.x-.2.;;

# newton_rec(k,1.,0.0001,0.000000001);;
- : float = 1.41421356245305962
\end{lstlisting}



\subsubsection{Avec Sage}
\sage
\begin{lstlisting}[caption={méthode de Newton-Raphson en récursif (Sage)}]
def der(f,x):
    t=var('t')
    return diff(f(t),t).subs(t=x)

def newton_rec(f,xo,p):
    if abs(f(xo)/der(f,xo)).n(digits=p)<10**(-p) : return xo.n(digits=p)
    else : return newton_rec(f,xo-f(xo)/der(f,xo),p)

sage: newton_rec(f,1.,15)
1.41421356237310
\end{lstlisting}
\xc



\subsection{Algorithme impératif}

Ça se complique un peu~:~évidemment,  car il faut faire de l'informatique
au lieu de se concentrer sur les mathématiques...


\begin{algorithm}[H]
\caption{\textsc{Newton-Raphson}~:~version impérative}
\Entree{\;
fonction $f$\;
 précision $p$\;
premier terme $a0$\;
nombre maximum d'itération \tcp{Pour éviter de \og planter\fg{}  si
  on tombe sur un cas pathologique\;}
}\;
\Ini{
$fp$\aff dérivée de $f$\;
compteur\aff 0 \tcp{le compteur d'itérations}\;
$un$\aff $u0-\frac{f(u0)}{fp(u0)}$\;

}\;
\Deb{
\Tq{$\left|\frac{f(xn)}{fp(xn)}\right|$   est   plus   grand  que   la
  précision $p$ et que $k<N$}{
\Si{$fp(un)=0$}{On sort  de la  boucle avant de  diviser par zéro  et on
  explique pourquoi}
$un$\aff $un-\frac{f(un)}{fp(un)}$\;
compteur\aff compteur+1\;

}
 }

\Retour{L'approximation et la valeur du compteur} 
\end{algorithm}


%Ici encore il faudra faire attention à l'utilisation de \texttt{evalf}.



Comparez ensuite avec les résultats trouvés avec la dichotomie.

Regardez également ce qui  se passe avec l'équation $(x-1)^4=0$~:~quelle
précaution   supplémentaire   faut-il   prendre~?   (La   preuve   n'est
évidemment pas envisageable au Lycée).


\subsubsection{Avec Sage}

\sage

\begin{lstlisting}[caption={\textsc{Newton-Raphson}~:~version   impérative (Sage)}]
def newton_imp(f,xo,p,Nmax):
    def fp(x):
        return der(f,x)
    c=len(str(floor(xo)))
    xn = xo-f(xo)/fp(xo).n(digits=p+c)
    k = 0
    while abs(f(xn)/fp(xn))>=10**(-p) and k<Nmax :
        if fp(xn)==0:
            return 'la dérivee est nulle'
        else:
            xn = (xn - f(xn)/fp(xn)).n(digits=p+c)
            k = k+1
    return [xn,k]
\end{lstlisting}


Ce qui donne pour $x\mapsto x^2-2$:

\begin{lstlisting}[caption={}]
sage: def f(x):
....: return x**2-2
....: 
sage: newton_imp(f,1.,70,100)
[1.4142135623730950488016887242096980785696718753769480731766797379907325,6]

\end{lstlisting}





\section{Fractale de Newton}


Considérons l'équation $z^5-1=0$. Elle admet cinq solutions dans $\bbc$.
\xc

\subsection{Avec XCAS}

Étudiez le programme suivant~:

\begin{lstlisting}
coul(a,b):={
local z,j,c;
z:=a+i*b;
c:=0;
  while((abs(z^n-1)>=0.01) and (c<20))
  {z:=z-(z^n-1)/(n*z^(n-1));
   c:=c+1};
return(c)
}:;
\end{lstlisting}

Ensuite,  on trace  dans  le carré  $[-1;1]\times[-1;1]$  des points  de
coordonnées $(a,b)$ colorés avec la couleur \verb+coul(a,b)+~:~en effet,
chaque couleur peut être représentée par un nombre.



\begin{lstlisting}[caption={}]
seq(seq(couleur(point([a*0.002,b*0.002]),coul(a*0.002,b*0.002)+point_point+point_width_2),a=-500..500),b=-500..500) 
\end{lstlisting}

Cela
nécessite pas mal de calculs et donc prend BEAUCOUP de mémoire.

Voici ce que cela donne~:~c'est beau mais comment interpréter ce graphique~?



\begin{center}
  \includegraphics[width=\linewidth]{fractalenewton}
\end{center}

\subsection{Avec Sage}
\sage
On                  utilise                  la                 commande
\verb+complex_plot(équation,(xmin,xmax),(ymin,ymax),plot_points)+:

\begin{lstlisting}[caption={}]
sage: sage: z=var('z'); p=complex_plot(z^5-1,(-1,1),(-1,1),plot_points=3000)
sage: p.show()
\end{lstlisting}

Ce qui donne:


%\begin{figure}
\begin{center}
  \includegraphics{fractalnewtonsage}
\end{center}
%\end{figure}


\section{Méthode d'\textsc{Euler}}

Supposons qu'on connaisse  $f'(x)$ en fonction de $x$  et de $f(x)$ sous
la forme $f'(x)=u\bigl(f(x),x\bigr)$.

On utilise le fait que $f'(x)\approx \frac{f(x+h)-f(x)}{h}$. Alors

\[f(x+h)\approx h\cdot u\bigl(f(x),x\bigr)+f(x) \]

La traduction algorithmique est alors directe.


\subsection{Version récursive}

\subsubsection{Avec XCAS}


Pour la liste des coordonnées de points~:
\xc

\begin{lstlisting}[caption={méthode d'Euler générale en récursif (XCAS)}]
Euler(u,x,xmax,y,h,liste):={
 if(x>=xmax)
   then{liste}
   else{ Euler(u,x+h,xmax,y+u(y,x)*h,h,[op(liste),[x,y]])}
}:;
\end{lstlisting}


Puis pour le tracé~:

\begin{lstlisting}
trace_euler(u,xo,xmax,yo,h):={
polygonplot([Euler(u,xo,xmax,yo,h,[])])
}:;
\end{lstlisting}


Alors, pour  résoudre graphiquement $y'=-y$ avec  $y(-2)=1$, sur $[-2;2]$
avec un pas de $0,01$ on entre~:

\begin{lstlisting}
trace_euler((y,x)->-y,-2,2,1,0.01)
\end{lstlisting}


et on obtient~:


\begin{figure}
\begin{center}
  \includegraphics{euler}
\end{center}
\end{figure}

\subsubsection{Avec Sage}

\sage

\begin{lstlisting}[caption={méthode d'Euler générale en récursif (Sage)}]
def euler(u,x,xmax,y,h,liste):
    if x>=xmax : return liste
    else : return euler(u,x+h,xmax,y+u(y,x)*h,h,liste+[[x,y]])

def trace_euler(u,xo,xmax,yo,h):
    p=line(euler(u,xo,xmax,yo,h,[]))
    p.show()
\end{lstlisting}

Alors:

\begin{lstlisting}[caption={}]
sage: def e(y,x):
....: return -y
....: 
sage: trace_euler(e,-2,2,1,0.01)
\end{lstlisting}

donne:


\begin{figure}
\begin{center}
  \includegraphics{eulersage}
\end{center}
\end{figure}



\subsection{Version impérative}

\subsubsection{Avec XCAS}

On effectue une division régulière en découpant notre intervalle d'étude
$[a;b]$ en $N$ points~:
\xc
\begin{lstlisting}[caption={méthode d'Euler générale en impératif}]
EulerImp(u,N,a,b,yo):={
S:=NULL; 
X:=a;  
Y:=yo;  
h:=(b-a)/N  
pour k de 0 jusque N pas 1 faire
X:=a+k*h; 
Y:=Y+u(Y,X)*h; 
S:=S,[X,Y];  
fpour  
polygonplot([S]); 
}:;

\end{lstlisting}



Ensuite, pour avoir la solution  de $y'=-y+x$ sur $[-2;2]$ avec $y(-2)=1$
on entre~:

\begin{lstlisting}
EulerExpo((y,x)->-y+x,100,-2,2,1)
\end{lstlisting}


et on obtient~:



\begin{figure}
\begin{center}
  \includegraphics{euler2}
\end{center}
\end{figure}

\subsubsection{Avec Sage}
\sage
\begin{lstlisting}[caption={méthode   d'Euler   générale  en   impératif    (Sage)}]
def eulerimp(u,N,a,b,yo):
    S=[]
    X=a
    Y=yo
    h=(b-a)/N
    for k in [0..N]:
        X+=h
        Y+=u(Y,X)*h
        S+=[[X,Y]]
    P=line(S)
    P.show()
  \end{lstlisting}
  
Alors:

\begin{lstlisting}
sage: def u(y,x):
....: return -y+x
....: 
sage: eulerimp(u,100,-2,2,1)
\end{lstlisting}


donne:


%\begin{figure}
\begin{center}
  \includegraphics{eulersage2}
\end{center}
%\end{figure}









\subsection{En Terminale : introduction de l'exponentielle}

\subsubsection{Avec XCAS}

Voici un petit  programme XCAS qui construit la  courbe approchée par la
méthode d'Euler, c'est-à-dire que l'on va tracer la courbe correspondant
à la fonction vérifiant~: 

\bez
\item $f'= f$ ;
\item $f(xo)=yo$ ;
\item $f$ est définie sur $[xo\pv xfinal]$ ;
\item On va faire des pas de h.
\ez


Sur XCAS,  les coordonnées d'un point  se notent entre  crochets et pour
tracer la ligne polygonale passant par des points dont on a la liste des
coordonnées, on utilise la commande \texttt{polygone\_ouvert([liste des coordonnées])}


\xc
\begin{lstlisting}[caption={méthode  d'Euler   pour  l'exponentielle  en impératif (XCAS)}]
EulerExpo(xo,yo,xfinal,h):={
X:=xo;  // au départ X vaut a
Y:=yo;  // au départ Y vaut yo
ListePoints:=[[X,Y]] // il y a un point au départ dans notre liste

 tantque abs(X) < abs(xfinal) faire // pour tester même si h est négatif
    X:=X+h; // on avance de h 
    Y:=(1+h)*Y; // f(X+h)=(1+h).f(X) 
    ListePoints:=append(ListePoints,[X,Y]); // on rajoute à notre liste [X,Y]
 ftantque // fin de la boucle

polygone_ouvert(ListePoints); // on relie les points de la liste "à la règle"
}:;
\end{lstlisting}


Par exemple, pour avoir le tracé  entre $-2$ et $2$ sachant que $f(0)=1$
et en prenant un pas de $0,01$ on entre~:

\begin{lstlisting}
EulerExpo(0,1,-2,-0.01),EulerExpo(0,1,2,0.01)
\end{lstlisting}


Analysez ce programme plus rapide à écrire~:

\begin{lstlisting}[caption={méthode d'Euler pour l'exponentielle en récursif (XCAS)}]
Euler(x,y,xfinal,h,ListePoints):={
 si abs(x)>=abs(xfinal)
 alors polygone_ouvert(ListePoints)
 sinon Euler(x+h,(1+h)*y,xfinal,h,append(ListePoints,[x,y])) 
 fsi
}:;
\end{lstlisting}

que vous pouvez tester en tapant~:

\begin{lstlisting}
Euler(0,-2,1,-0.01,[]),Euler(0,2,1,0.01,[])
\end{lstlisting}

\subsubsection{Avec Sage}

La même avec Sage:

\sage
\begin{lstlisting}[caption={méthode d'Euler pour l'exponentielle en impératif (Sage)}]
def eulerexpo(xo,yo,xfinal,h):
    X=xo # au départ X vaut a
    Y=yo # au départ Y vaut yo
    ListePoints=[[X,Y]] # il y a un point au départ dans notre liste
    while abs(X)<abs(xfinal): # pour tester même si h est négatif
        X+=h # on avance de h
        Y*=(1+h) # f(X+h)=(1+h).f(X)
        ListePoints+=[[X,Y]] #  on rajoute à notre liste [X,Y]
    return line(ListePoints) # on relie les points de la liste "à la règle"
\end{lstlisting}

Par exemple, pour avoir le tracé  entre $-2$ et $2$ sachant que $f(0)=1$
et en prenant un pas de $0,01$ on entre~:

\begin{lstlisting}[caption={}]
sage: (eulerexpo(0,1,2,0.01)+eulerexpo(0,1,-2,-0.01)).show()
\end{lstlisting}





%\begin{figure}
\begin{center}
  \includegraphics{eulerexposage}
\end{center}
%\end{figure}



En récursif:



\begin{lstlisting}[caption={méthode d'Euler pour l'exponentielle en récursif (Sage)}]
def eulerexporec(x,y,xfinal,h,ListePoints):
    if abs(x)>=abs(xfinal):
        return line(ListePoints)
    else :
        return eulerexporec(x+h,(1+h)*y,xfinal,h,ListePoints+[[x,y]])
      \end{lstlisting}
      

On l'invoque ainsi:

\begin{lstlisting}[caption={}]
sage: (eulerexporec(0,1,2,0.01,[])+eulerexporec(0,1,-2,-0.01,[])).show()
\end{lstlisting}



\subsection{En Terminale : introduction du logarithme}

\subsubsection{Avec XCAS}

Construisons une approximation du graphe de ln sachant que la dérivée de
ln
est la fonction inverse et que $\ln 1=0$


Rappelons brièvement le principe de la méthode.


On utilise le fait que $\frac{1}{x}=f'(x)\approx \frac{f(x+h)-f(x)}{h}$. Alors

\[f(x+h)\approx h\cdot \frac{1}{x}+f(x) \]

La traduction algorithmique est alors directe.

\xc
  \begin{lstlisting}[caption={construction ln (XCAS)}]
EulerLn(x,y,xlimite,h,liste_points):={
if(h>=0)then{condition:=x>=xlimite}else{condition:=x<=xlimite}
if(condition)
   then{liste_points}
   else{ EulerLn(x+h,y+h/x,xlimite,h,[op(liste_points),[x,y]])}
}:;
\end{lstlisting}



Puis pour le tracé~:

\begin{lstlisting}
trace_EulerLn(xo,yo,xlimite,h):={
polygonplot([EulerLn(xo,yo,xlimite,h,[])])
}:;
\end{lstlisting}



Ce qui donne pour le tracé sur $[0,01\,;\,10]$~:

\begin{lstlisting}[caption={}]
trace_EulerLn(1,0,10,0.01),trace_EulerLn(1,0,0.01,-0.01)
\end{lstlisting}



\begin{figure}
\begin{center}
  \includegraphics[height=5cm]{lneuler}
\end{center}
\end{figure}


\subsubsection{Avec Sage}
\sage
\begin{lstlisting}[caption={construction ln (Sage)}]
def eulerln(x,y,xlimite,h,liste_points):
    if h>=0: condition = x>=xlimite
    else : condition = x<=xlimite
    if condition :
        return line(liste_points)
    else :
        return eulerln(x+h,y+h/x,xlimite,h,liste_points+[[x,y]])
\end{lstlisting}


Par exemple:

\begin{lstlisting}[caption={}]
sage: (eulerln(1,0,10,0.01,[])+eulerln(1,0,0.01,-0.01,[])).show()
\end{lstlisting}

donne:


%\begin{figure}
\begin{center}
  \includegraphics{eulerlnsage}
\end{center}
%\end{figure}


\section{Intégration numérique}

\subsection{Méthode des rectangles}



On  veut  calculer une  intégrale  d'une  fonction  par la  méthode  des
rectangles. 

\subsubsection{Version récursive avec CAML}


La définition récursive est assez naturelle~:


\caml

\begin{lstlisting}[caption={méthode des rectangles en récursif (CAML)}]
# let rec integ(f,a,b,dx)=
      if a>b then 0.
      else f(a)*.dx+.integ(f,a+.dx,b,dx);;
\end{lstlisting}

Par exemple~:

\begin{lstlisting}
# let g(x)=x;;

# integ(g,0.,1.,0.0001);;
\end{lstlisting}

donne~:

\begin{lstlisting}
- : float = 0.500049999999960249
\end{lstlisting}

C'est-à-dire $\ds\int_0^1x \mathrm{d}{x}\approx 0.5$


Mais  la  récursion  n'est  pas  terminale.  Introduisons  une  fonction
intermédiaire~:



\begin{lstlisting}[caption={méthode des rectangle en récursif terminal étape 1}]
# let rec integ_temp(f,a,b,dx,res)=
     if a>b then res
     else integ_temp(f,a+.dx,b,dx,res+.f(a)*.dx);;
\end{lstlisting}

Puis~:

\begin{lstlisting}[caption={méthode des rectangles en récursif terminal étape 2}]
# let integrale(f,a,b,dx)=integ_temp(f,a,b,dx,0.);;
\end{lstlisting}


Alors on obtient~:


\begin{lstlisting}
# integrale(g,0.,1.,0.0000001);;
- : float = 0.500000049944005598
\end{lstlisting}


Pour améliorer l'approximation, il faudrait en fait améliorer la méthode
mathématique... 


\subsubsection{Version récursive avec Sage}


\sage

\begin{lstlisting}[caption={méthode des rectangles en récursif (Sage)}]
def integ(f,a,b,dx):
    if a>b : return 0
    else : return f(a)*dx+integ(f,a+dx,b,dx)
\end{lstlisting}


Alors:

\begin{lstlisting}[caption={}]
sage: def g(x):
....: return x
....: 
sage: integ(g,0,1,0.01)
0.495000000000000
\end{lstlisting}

\begin{figure}[!h]
  \begin{Remarque}[nombre limite de récursions avec Python]
    On  arrive  vite  aux  limites  du  nombre  standard  de  récursions  de
Python. Pour l'augmenter:
\begin{lstlisting}[caption={}]
import sys
sys.setrecursionlimit(100000)
\end{lstlisting}
    \end{Remarque}
  \end{figure}


  \begin{lstlisting}[caption={}]
import sys
sys.setrecursionlimit(100000)

sage: integ(g,0,1,0.0001)
0.500049999999960
  \end{lstlisting}




\subsubsection{Version impérative avec XCAS}


\xc

\begin{lstlisting}[caption={méthode des rectangles en impératif (XCAS)}]
integ_rectangle(f,a,b,dx):={
local aa,I;
aa:=a;
I:=0;
 while(aa<b){
 I:=I+f(aa)*dx;
 aa:=aa+dx;
 }
return(I)
}:;
\end{lstlisting}









\subsubsection{Version impérative avec Sage}


\sage

\begin{lstlisting}[caption={méthode des rectangles en impératif (Sage)}]
def integ_rectangle(f,a,b,dx):
    aa=a
    I=0
    while aa<b:
        I+=f(aa)*dx
        aa+=dx
    return I
\end{lstlisting}


Alors par exemple:

\begin{lstlisting}[caption={}]
sage: def g(x):
....: return x
....: 
sage: integ_rectangle(g,0,1,0.000001)
0.499999499999612
\end{lstlisting}




\caml

\subsection{Méthode des trapèzes}

Il faut juste adapter un peu....

\subsubsection{Version récursive avec CAML}

\begin{lstlisting}[caption={méthode des trapèzes en récursif (CAML)}]
# let rec integ_trap(f,a,b,dx)=
      if a>b then 0.
      else 0.5*.dx*.(f(a)+.f(a+.dx))+.integ_trap(f,a+.dx,b,dx);;
\end{lstlisting}

\begin{lstlisting}
# integ_trap(g,0.,1.,0.0001);;
- : float = 0.500100004999960213
\end{lstlisting}



\subsubsection{Version récursive avec Sage}


\sage
\begin{lstlisting}[caption={méthode des trapèzes en récursif (Sage)}]
def integ_trap(f,a,b,dx):
    if a>b : return 0
    else : return 0.5*dx*(f(a)+f(a+dx))+integ_trap(f,a+dx,b,dx)
\end{lstlisting}

Par exemple:

\begin{lstlisting}[caption={}]
sage: def g(x):
....: return x
....: 
sage: integ_trap(g,0,1,0.0001)
0.500100004999960
\end{lstlisting}

\subsubsection{Version impérative avec XCAS}


\xc

\begin{lstlisting}[caption={méthode des trapèzes en impératif (XCAS)}]
integ_trap(f,a,b,dx):={
local aa,I;
aa:=a;
I:=0;
 while(aa<b){
 I:=I+(f(aa)+f(aa+dx))*dx*0.5;
 aa:=aa+dx;
 }
return(I)
}:;
\end{lstlisting}




\subsubsection{Version impérative avec Sage}


\sage

\begin{lstlisting}[caption={méthode des trapèzes en impératif (Sage)}]
def integ_trap(f,a,b,dx):
    aa=a
    I=0
    while aa<b:
        I+=(f(aa)+f(aa+dx))*dx*0.5
        aa+=dx
    return I
\end{lstlisting}

Ce qui donne:

\begin{lstlisting}[caption={}]
sage: def g(x):
....: return x
....: 
sage: integ_trap(g,0,1,0.00001)
0.500010000049675
\end{lstlisting}



\caml

\subsection{Méthode de Simpson}


On cherche une approximation de la courbe par un arc de parabole.
Pour cela, on va déterminer les $c_i$ tels que 
\[\int_a^bf(x)\mathrm{d}{x}=c_0f(a)+c_1f \left(\frac{a+b}{2}\right)+c_2f(b)\]

soit exacte pour $f(x)$ successivement égale à $1$, $x$ et $x^2$.

Posons $h=b-a$ et ramenons-nous au cas $a=0$.
On obtient le système suivant~:


\[
\bsys
c_0+c_1+c_2=h\\
c_1+2c_2=h\\
c_1+4c_3=\frac{4}{3}h
\esys
\]

alors $c_0=c_2=\frac{h}{6}$ et $c_1=\frac{4}{6}h$

\[\int_a^bf(x)\mathrm{d}{x}=\frac{b-a}{6}\left(f(a)+4f \left(\frac{a+b}{2}\right)+f(b)\right)\]



\subsubsection{Version récursive avec CAML}

\caml
\begin{lstlisting}[caption={méthode de Simpson en récurisf (CAML)}]
# let rec integ_sims(f,a,b,dx)=
      if a>b then 0.
      else (f(a)+.4.*.f(a+.dx/.2.)+.f(a+.dx))*.dx/.6.+.integ_sims(f,a+.dx,b,dx);;
\end{lstlisting}



\subsubsection{Version récursive avec Sage}

\sage

\begin{lstlisting}[caption={méthode de Simpson en récurisf (Sage)}]
def integ_sims(f,a,b,dx):
    if a>b : return 0
    else : return (f(a)+4*f(a+dx/2)+f(a+dx))*dx/6+integ_sims(f,a+dx,b,dx)
\end{lstlisting}
  

Par exemple:

\begin{lstlisting}[caption={}]
sage: def g(x):
....: return 4*sqrt(1-x*x)
....: 
sage: integ_sims(g,0,1,0.0001)
3.14159249127822 + 3.60953260836123e-6*I
\end{lstlisting}


\subsubsection{Version impérative avec XCAS}


\xc

\begin{lstlisting}[caption={méthode de Simson en impératif (XCAS)}]
integ_sims(f,a,b,dx):={
local aa,I;
aa:=a;
I:=0;
 while(aa<b){
 I:=I+(f(aa)+4*f(aa+0.5*dx)+f(aa+dx))*dx/6.;
 aa:=aa+dx;
 }
return(I)
}:;
\end{lstlisting}


\subsubsection{Version impérative avec Sage}

\sage

\begin{lstlisting}[caption={méthode de Simpson en impératif (Sage)}]
def integ_simps(f,a,b,dx):
    aa=a
    I=0
    while aa<b:
        I+=(f(aa)+4*f(aa+0.5*dx)+f(aa+dx))*dx/6
        aa+=dx
    return I
\end{lstlisting}


Par exemple:

\begin{lstlisting}[caption={}]
sage: def g(x):
....: return 4*sqrt(1-x*x)
....: 
sage: integ_simps(g,0,1,0.00001)
3.14159264848556 + 1.14141804900498e-7*I
\end{lstlisting}









\chapter{Résolutions de systèmes}

\section{Systèmes de \textsc{Cramer}}
\xc
Soit un système $\bsys a_{11}x+a_{12}y=b_1\\ a_{21}x+a_{22}y=b_2\esys$.

Soit D  le déterminant  du sytème :  $D=a_{11}a_{22}-a_{21}a_{12}$. S'il
est non nul,  il est assez aisé de montrer en  Seconde que les solutions
sont~:

$$x=\frac{b_{1}a_{22}-b_{2}a_{12}}{D}\qquad y=\frac{a_{11}b_{2}-a_{21}b_{1}}{D}$$


Cela   peut  mettre   en   évidence  les   rôles   des  inconnues   (qui
n'apparaissent pas en entrée dans l'algorithme) et des coefficients.

\begin{algorithm}[H]
\caption{système de \textsc{Cramer}}
\Entree{Les coefficients}\;
\Deb{
\eSi{D=0}{pas de solution unique}{$x=\frac{b_{1}a_{22}-b_{2}a_{12}}{D}\qquad y=\frac{a_{11}b_{2}-a_{21}b_{1}}{D}$}
 } 
\end{algorithm}


\subsection{Avec XCAS}

\begin{lstlisting}[caption={système de Cramer en impératif (XCAS)}]
cramer(a11,a12,b1,a21,a22,b2):={
 si a11*a22-a21*a12==0 
   alors retourne("Pas de solution unique")
   sinon retourne((b1*a22-b2*a12)/(a11*a22-a21*a12), (a11*b2-a21*b1)/(a11*a22-a21*a12))
 fsi
}:;
\end{lstlisting}

\subsection{Avec Sage}

\sage
\begin{lstlisting}[caption={système de Cramer en impératif (Sage)}]
def cramer(a11,a12,b1,a21,a22,b2):
    if a11*a22-a21*a12==0 :
        return 'Pas de solution unique'
    else:
        return [(b1*a22-b2*a12)/(a11*a22-a21*a12), (a11*b2-a21*b1)/(a11*a22-a21*a12)]
\end{lstlisting}

Par exemple:

\begin{lstlisting}[caption={}]
sage: cramer(1,2,3,4,5,6)
[-1, 2]
sage: cramer(1,2,3,2,4,6)
'Pas de solution unique'
\end{lstlisting}


\section{Pivot de \textsc{Gauss}}

\subsection{Cas  d'un  système 3x3}
Nous  traiterons le  cas  d'un  système $3\times3$  mais  rien n'empèche  de
généraliser.

Comme nous sommes entre nous, nous \og parlerons matrice\fg{}. 

Nous  disposons donc  d'une matrice  carrée A  de dimension  3  et d'une
matrice   colonne  B  de   longueur  3.   Nous  voulons   résoudre  dans
$\MR_{13}(\bbr)$ le système $A\cdot X=B$.

Nous noterons T le tableau~:

$$
  \left[\begin{array}{ccc|c}
  a_{11}&a_{12}&a_{13}&b_1\\
  a_{21}&a_{22}&a_{23}&b_2\\
  a_{31}&a_{32}&a_{33}&b_3  
  \end{array}\right]
$$




Si  la  matrice est  inversible,  alors,  en  effectuant des  opérations
élémentaires sur  les lignes, on peut  se ramener à  la matrice identité
dans la partie gauche du tableau et on obtient X dans la partie droite.


Pour y arriver, l'idée est de balayer le tableau par colonne.

Étant donné  une colonne, on cherche un  élément non nul. S'il  n'y en a
pas,  la matrice  n'est pas  inversible et  le système  n'admet  pas une
unique solution (on  ne s'occupe pas trop du  rang au lycée...)~;~sinon,
on permute éventuellement  deux lignes pour placer l'élément  non nul de
la colonne  $k$ sur la ligne  $k$ et on  divise tous les éléments  de la
ligne par le nouveau $a_{kk}$ pour obtenir 1.

Il reste ensuite à remplacer chaque ligne (autre que $L_k$) dont l'élément de la colonne
$k$ est non nul par $L_i-a_{ik}\times L_k$.

Cela donne~:


\begin{algorithm}[H]
\caption{pivot de \textsc{Gauss} pour un système $3\times 3$}
\Entree{Le tableau T}\;
\Ini{S\aff T}\;
\Deb{
\Pour{col de 1 jusqu'à 3}{
line\aff col\;
\Tq{S[line][col]=0}{
line\aff line +1\;
\Si{line=4}{\Retour{Le système n'admet pas de solution unique}}
}%fin tant que

\tcp{On échange les lignes "line" et "col"}\;

temp\aff S[ligne]\;
S[line]\aff S[col]\;
S[colonne]\aff 1/temp[colonne]*temp\;

\Pour{k dans $\{1,2,3\} \setminus\{col\} $}
{S[k]\aff S[k]-S[k][col]*S[col]}

}%fin pour col
} 
\Retour{la dernière colonne}
\end{algorithm}



\subsection{Avec XCAS}
\xc
\begin{lstlisting}[caption={pivot de Gauss (XCAS)}]
Gauss(T):={
local S,NoColonne,NoLigne,temp,E,k,j;
S:=T;

pour NoColonne de 0  jusque 2  faire
  NoLigne:=NoColonne;
  tantque S[NoLigne][NoColonne]==0 faire
    NoLigne:=NoLigne+1;
    si NoLigne==3 alors retourne("pas de solution unique");
    fsi; 
  ftantque;
 
 temp:=S[NoLigne];
 S[NoLigne]:=S[NoColonne];
 S[NoColonne]:=1/temp[NoColonne]*temp;

 E:=%{0,1,2%} minus %{NoColonne%};

 pour k in E faire 
   S[k]:=S[k]-S[k][NoColonne]*S[NoColonne];
 fpour;

fpour;

retourne([seq(S[j][3],j=0..2)])
}:;
\end{lstlisting}




\begin{lstlisting}[caption={}]
Gauss([[1,2,3,4],[5,6,7,8],[9,10,9,8]])
\end{lstlisting}

\reponse{[0,-1,2]}


\subsection{Avec Sage}
\sage
\begin{lstlisting}[caption={pivot de Gauss (Sage)}]
def gauss(T):
    S=T
    for NoColonne in [0..2]:
        NoLigne=NoColonne
        while S[NoLigne][NoColonne]==0 :
            NoLigne+=1
            if NoLigne==3:
                return 'Pas de solution unique'
        temp=S[NoLigne]
        S[NoLigne]=S[NoColonne]
        S[NoColonne]=map(lambda x:x/temp[NoColonne],temp)
        E=Set([0,1,2])-Set([NoColonne])
        for k in E:
            S[k]=map(lambda x,y:x-S[k][NoColonne]*y,S[k],S[NoColonne])
    return [S[j][3] for j in [0..2]]
\end{lstlisting}


Par exemple résolvons le système:

\begin{center}
\begin{systeme}[9]
&x&+2&y&+3&z&=&4&\qquad\\
5&x&+6&y&+7&z&=&8&\qquad\\
9&x&+10&y&+9&z&=&8&\qquad\\
\end{systeme}
\end{center}


\begin{lstlisting}[caption={}]
sage: gauss([[1,2,3,4],[5,6,7,8],[9,10,9,8]])
[0, -1, 2]
\end{lstlisting}


et celui-ci:


\begin{center}
\begin{systeme}[9]
&x&+2&y&+3&z&=&4&\qquad\\
5&x&+6&y&+7&z&=&8&\qquad\\
9&x&+10&y&+11&z&=&12&\qquad\\
\end{systeme}
\end{center}



\begin{lstlisting}[caption={}]
sage: gauss([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
'Pas de solution unique'
\end{lstlisting}















\chapter{Approximations d'irrationnels}

\section{Algorithme de \textsc{Héron}}

\textsc{Héron}  d'Alexandrie n'avait pas  attendu \textsc{Newton}  et le
calcul différentiel  pour trouver  une méthode permettant  de déterminer
une approximation  de la racine  carrée d'un nombre positif  puisqu'il a
vécu seize siècles avant Sir Isaac.


Si  $x_n$  est une  approximation  strictement  positive  par défaut  de
$\sqrt{a}$, alors $a/x_n$ est  une approximation par excès de $\sqrt{a}$
(pourquoi~?) et vice-versa.

La    moyenne   arithmétique    de   ces    deux    approximations   est
$\frac{1}{2}\left(x_n+\frac{a}{x_n}\right)$  et constitue  une meilleure
approximation que les deux précédentes.

On  peut  montrer c'est  une  approximation  par  excès (en  développant
$\left(x_n-\sqrt{a}\right)^2$ par exemple).

On obtient naturellement un algorithme~:


\begin{algorithm}[H]
\caption{approximation de $\sqrt{a}$}
\Entree{le réel positif $a$, une première approximation par défaut
  strictement positive xo et une précision eps}
\Ini{
X\aff 0.5(xo+$a$/xo)}
\Deb{
\Tq{|xo-a/xo|<eps}
{X\aff 0.5(X+$a$/X)}

\Retour{X}
 } 
\end{algorithm}


On notera que cette méthode est un cas particulier de la méthode de
\textsc{Newton-Raphson} appliquée à une équation particulière~:~$x^2-a=0$.



\subsection{Avec XCAS en impératif}
\xc
\begin{lstlisting}[caption={algorithme de Héron en impératif (XCAS)}]
heron(a,xo,eps):={
local X;
X:=0.5*(xo+a/xo);
while(abs(evalf(X-a/X))>=eps){
  X:=0.5*(X+a/X);
}
return(X)
}:;
\end{lstlisting}


% \subsection{Avec Sage en impératif}
% \sage
% \begin{lstlisting}[caption={algorithme de Héron en impératif (Sage)}]

% \end{lstlisting}

\subsection{Avec CAML en version récursive}

\caml
\begin{lstlisting}[caption={algorithme de Héron en récursif}]
# let rec heron(a,xo,eps)=
      if abs_float(xo-.a/.xo)<eps then xo
      else heron(a,0.5*.(xo+.a/.xo),eps);;
\end{lstlisting}
\xc








\section{Influence de la première approximation}


Notons  $\e_n$ l'erreur  relative après  $n$ itérations  par  la méthode
précédente.


Alors         $\e_n=\frac{x_n-\sqrt{a}}{\sqrt{a}}$        et        donc
$x_n=\frac{1+\e_n}{\sqrt{a}}$.                                         Or
$x_{n+1}=\frac{1}{2}\left(x_n+\frac{a}{x_n}\right)$. 


On peut montrer qu'alors $$\e_{n+1}=\frac{\e_n^2}{2(1+\e_n)}$$

Si  on  est  trop loin  de  la  solution  au  départ, $\e_n$  n'est  pas
négligeable devant 1 et alors $\e_{n+1}$ est de l'ordre de $\e_n/2$.

Sinon, $\e_{n+1}$ est de l'ordre de $(\e_n)^2/2$.

Ainsi, si on  est loin de la solution, la convergence  est lente au départ
(puisqu'elle est linéaire)  puis elle devient d'ordre 2  (on dit qu'elle
est quadratique).


Le problème, c'est de pouvoir  rapidement calculer un inverse...



\section{Calcul de 300 décimales de e}


Posons $e_n=1+\frac{1}{1!}+\frac{1}{2!}+\cdots+\frac{1}{n!}$

Alors on a aussi
\[e_n=1+1+\frac{1}{2}\left(1+\frac{1}{3}\left(1+\frac{1}{4}\left(\cdots \left(\frac{1}{n-1}\left(1+\frac{1}{n}\right)\right)\right)\right)\right)\]


Un           exercice           classique           montre           que
$e-e_n<\frac{n+2}{n+1}\frac{1}{(n+1)!}$.

Ainsi, pour $n=167$, on obtiendra $300$ bonnes décimales au moins.





\subsection{Version récursive}
\xc
\begin{lstlisting}[caption={décimales de e en récursif}]
expo_rec(n):={
if(n==167)then{1}
else{1+expo_rec(n+1)/n}
}:;
\end{lstlisting}

On obtient la réponse avec~:

\begin{lstlisting}
evalf(expo_rec(1),300)
\end{lstlisting}



\subsection{Version impérative}


\subsubsection{Avec XCAS}
\xc
\begin{lstlisting}[caption={décimale de e en impératif (XCAS)}]
expo():={
local s,k;
s:=1;
for(k:=167;k>0;k:=k-1){
s:=s/k+1;
}
return(s);
}:;
\end{lstlisting}

On obtient la réponse avec~:

\begin{lstlisting}
evalf(expo(),300)
\end{lstlisting}





\subsubsection{Avec Sage}
\sage
\begin{lstlisting}[caption={300 décimales de e en impératif (Sage)}]
def expo():
    s=1
    for k in srange(167,0,-1):
        s=s/k+1
    return s.n(digits=300)
\end{lstlisting}


On obtient:


\begin{lstlisting}[caption={}]
sage: expo()
2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901157383418793070215408914993488416750924476146066808226480016847741185374234544243710753907774499207
\end{lstlisting}


On peut créer une fonction qui fixe le seuil:


\begin{lstlisting}[caption={seuil pour obtenir n décimales de e}]
def seuil_expo(n):
    def fonction_seuil(j):
        return (j+2)/((j+1)*factorial(j+1))
    k=1
    while fonction_seuil(k)>=10**(-n):
        k+=1
    return k
\end{lstlisting}


et l'utiliser pour avoir une précision quelconque:

\begin{lstlisting}[caption={n décimales de e en impératif (Sage)}]
def expo(n):
    s=1
    for k in srange(seuil_expo(n),0,-1):
        s=s/k+1
    return s.n(digits=n)
\end{lstlisting}

\section{Méthode d'\textsc{Euler} pour approcher la racine carrée d'un entier}

\subsection{Le texte d'\textsc{Euler}}


Voici, retranscrit en français, le texte d'Euler datant de 1748, extrait
de « Introduction à l'Analyse des infiniments petits », chapitre XVI.



\begin{figure}
\begin{center}
  \includegraphics[height=8cm]{metheuler}
\end{center}
\end{figure}


\begin{quotation}
Le premier moyen  dont nous parlerons, suppose qu'on  ait déjà déterminé
assez exactement la  valeur d'une racine(*) ; qu'on  sache, par exemple,
qu'une telle valeur surpasse $4$, et qu'elle est plus petite que $5$. 

Dans ce  cas, si l'on  suppose cette valeur  $= 4 + p$,  on est sûr  que $p$
exprime  une fraction.  Or  si $p$  est  une fraction,  et par  conséquent
moindre que l'unité,  le carré de $p$, son cube, et  en général toutes les
puissances  plus hautes  de $p$,  seront  encore beaucoup  plus petites  à
l'égard  de l'unité, et  cela fait  que, puisqu'il  ne s'agit  que d'une
approximation,  on  peut les  omettre  dans  le  calcul. Quand  on  aura
déterminé à peu près la fraction $p$, on connaîtra déjà plus exactement la
racine $4 + p $ ; on partira de là pour déterminer  une valeur encore plus
exacte,  et on  continuera  de la  même  manière, jusqu'à  ce qu'on  ait
approché de la vérité autant qu'on le souhaitait. 

Nous  éclaircirons  cette méthode  d'abord  par  un  exemple facile,  en
cherchant par approximation la racine de l'équation $x^2 = 20$. 

On voit ici  que $x$ est plus grand  que $4$ et plus petit que  $5$ ; en
conséquence de cela, on fera 
$x = 4+p$,  et on aura : $x^2 = 16  + 8p + p^2 = 20$  ; mais comme $p^2$
est très 
petit, on négligera ce terme  pour avoir finalement l'équation : $16+8p =
20$ ce qui donne $p = 1/2$ et  $x = 4+1/2$ ce qui approche déjà beaucoup plus
de la vérité. 

Si donc on suppose à présent $x =  9/2 + p$, on est sûr que $p$ signifie une
fraction  encore beaucoup  plus  petite qu'auparavant,  et qu'on  pourra
négliger $p^2$ à bien plus forte raison. 

On aura  donc $x^2 =  81/4 + 9p =  20$ d'où $p  = -1/36$ donc  $x = 4 +  1/2 -
1/36$. 

Que si  l'on voulait approcher encore  davantage de la  vraie valeur, on
ferait $x = 4$ et $17/36 + p$, et on aurait $x^2 = 10$ et $-1/1296 + 8$ et $34/36p
= 20$ ainsi $p =  -1/11592$, donc $x = 4$ et $17/36$ et $-1/11592$  d'où $x = 4$ et
$5473/11592$, valeur  qui approche si fort  de la vérité,  qu'on peut avec
confiance regarder l'erreur comme nulle. 

(*) cette méthode est celle que  Newton a donnée au commencement de « la
méthode des  fluxions ».  En l'approfondissant, on  la trouve  sujette à
différentes imperfections ; c'est  pourquoi on y sublimera avec avantage
la méthode  que M. de  la Grange a  donnée dans les Mémoires  de Berlin,
pour les années 1767 et 1768. 
\end{quotation}


 
Ainsi,  en partant de  la partie  entière $a_0$  d'une des  solutions de
$x^2=a$, on a $(a_0+p)^2=a$ et donc $$p\approx \frac{a-a_0^2}{2a_0}$$


 On
en       déduit      qu'une       meilleure       approximation      est
$$a_0+p\approx\frac{a_0^2+a}{2a_0}$$

\subsection{Version récursive avec CAML}

Cela donne~:
\caml
\begin{lstlisting}[caption={approximation de $\sqrt{a}$ par la méthode d'Euler en récursif}]
# let rec euleracine(ao,a,n)=
   if n=0 then ao
   else euleracine((ao**2.+.a)/.(2.*.ao),a,n-1);;
\end{lstlisting}


Par exemple, 10 itérations de cette méthode donnent pour $\sqrt{2}$~:

\begin{lstlisting}
# euleracine(1.,2.,10);;
- : float = 1.41421356237309492
\end{lstlisting}





\subsection{Version impérative avec XCAS}
\xc
\begin{lstlisting}[caption={approximation de $\sqrt{a}$ par la méthode d'Euler en impératif}]
euleracine(ao,a,n):={
local k,xo;
xo:=ao;
    for(k:=1;k<n;k:=k+1){
      xo:=xo+(a-xo^2)/(2*xo)
    }
return(xo)
}:;
\end{lstlisting}



\subsection{Version impérative avec Sage}
\sage
\begin{lstlisting}[caption={approximation  de $\sqrt{a}$ par  la méthode d'Euler en impératif (Sage)}]
def euleracine(ao,a,n):
    xo=ao
    for k in [1..n-1]:
        xo+=(a-xo^2)/(2*xo)
    return float(xo)
\end{lstlisting}



Alors:

\begin{lstlisting}[caption={}]
sage: euleracine(1,2,10)
1.4142135623730949
sage: sqrt(2.).n(digits=20)
1.4142135623730951455
\end{lstlisting}




\chapter{Algorithmes géométriques}

%\section{Sommes des carrés des entiers}

\section{Approximations de $\pi$}

\subsection{Méthode d'Archimède}

\subsubsection{La méthode}

\begin{figure}
\begin{center}
  \includegraphics[width=0.6\textwidth]{archimede.1}
\end{center}
\end{figure}

\begin{figure}[!h]
  \begin{Idee}{En classe}
    Vous pourrez vous reporter  à l'activité~\vref{archi} pour un exemple de
travail sur cette méthode en classe de 2\up{nde}.

    \end{Idee}
  \end{figure}





On  encadre  un cercle  entre  des polygones  tels  que  le cercle  soit
respectivement le cercle inscrit et le cercle circonscrit.

On représente le passage de l'étape $n$ à l'étape $n+1$.





On appelle $t_n$ la demi-longueur du côté du $n$-ème polygone extérieur et $s_n$
la demi-longueur d'un côté du polygone intérieur.

On appelle $c_n$ la distance du centre à un côté du polygone intérieur.


Calculons de deux façons l'aire du \og cerf-volant\fg{} $ACBD$~:

\[AB\times CD=AC\times AD\]

c'est-à-dire

\[2s_n=2s_{n+1}\times2c_{n+1}\]

On en déduit la relation \[s_{n+1}=\frac{s_n}{2c_{n+1}}\]



Les triangles OAF et OCE sont isométriques donc $t_n=AF=CE$.


Or~:

\[\frac{EC}{CO}=\frac{t_n}{1}=\frac{AG}{GO}=\frac{s_n}{c_n}\]

On en déduit la relation \[t_n=\frac{s_n}{c_n}\]

Enfin,   dans   le  triangle   rectangle   $DAC$,  $DA^2=DG\times   CD$,
c'est-à-dire $4c_{n+1}^2=(1+c_n)\times 2$. Finalement~:

\[c_{n+1}=\sqrt{\frac{1+c_n}{2}}\]


Le périmètre du polygone intérieur à $2^{n+2}$ côtés vaut donc 

\[S_{n+1}=2^{n+2}s_{n+1}=2^{n+1}\frac{s_n}{c_{n+1}}=\frac{S_n}{c_{n+1}}\]

Pour le périmètre extérieur~:

\[T_{n+1}=2^{n+2}t_{n+1}=2^{n+2}\frac{s_{n+1}}{c_{n+1}}=\frac{S_{n+1}}{c_{n+1}}\]


\subsubsection{Avec CAML en récursif}
\caml

\begin{lstlisting}[caption={approximation de $\pi$ par la méthode d'Archimède en récursif}]
# let rec c(n)=if n=0 then 0.5*.sqrt(3.) else sqrt(0.5*.(1.+.c(n-1)))
  and s(n)=if n=0 then 3. else s(n-1)/.c(n)
  and t(n)=s(n)/.c(n);;
\end{lstlisting}


Alors~:

\begin{lstlisting}
# s(20);;
- : float = 3.14159265358966211
# t(20)-.s(20);;
- : float = 3.91686683087755227e-13
\end{lstlisting}


\subsubsection{Avec XCAS en impératif}


On rajoute un petit compteur d'itérations~:

\xc
\begin{lstlisting}[caption={approximation de $\pi$ par la méthode d'Archimède en impératif}]
archi(d):={
local s,c,t,k,p;
p:=d+3;
epsilon:=1e-300;
s:=3;
c:=sqrt(3)/2;
t:=s/c;
k:=1;
while(evalf((t-s),p)>evalf(10^(-d),p)){
 c:=evalf(sqrt((1+c)/2),p);
 s:=evalf(s/c,p);
 t:=evalf(s/c,p);
 k:=k+1;
 }
s,k
}:;
\end{lstlisting}

Par exemple~:

\begin{lstlisting}
archi(50)
\end{lstlisting}

renvoie~:

\reponse{3.14159265358979323846264338327950288419716939937510472,84}


\subsection{Méthode de Nicolas de Cues}



\subsubsection{La méthode}

On \og cale\fg{} un polygone de $2^n$ côtés et de périmètre 2 entre deux
cercles~:  le cercle  circonscrit de  rayon $r_n$  et le  cercle inscrit
tangent à chaque côté de rayon $h_n$. On a alors~:

\[2\pi h_n\leqslant 2\leqslant 2\pi r_n\]

c'est-à-dire~:

\[\frac{1}{r_n}\leqslant \pi\leqslant \frac{1}{h_n}\]

Il reste à trouver une relation donnant $r_n$ et $h_n$...



\begin{figure}
\begin{center}
  \includegraphics[width=0.6\textwidth]{cuse.1}
\end{center}
\end{figure}


Notons $AB$  un côté  du polygone de  $2^n$ côtés  de périmètre 2  et de
centre  O. Comme  $EF=\frac{AB}{2}$ alors  EF  est le  côté du  polygone
suivant.

Ainsi \[OD=r_n,\qquad OG=h_n,\qquad OE=r_{n+1},\qquad OC=h_{n+1}\]

Comme $OC=\frac{OG+OD}{2}$, alors \[h_{n+1}=\frac{r_n+h_n}{2}\]

Ensuite, $ODE$  est rectangle en E,  on peut faire  démontrer en 2\up{e}
que $OE^2=OH\times OD$ et donc que \[r_{n+1}=\sqrt{r_nh_{n+1}}\]





\subsubsection{Avec CAML en récursif}

\caml

\begin{lstlisting}[caption={approximation de $\pi$ par la méthode de Cues en récursif}]
# let rec h(n)=if n=0 then 0.25 else 0.5*.(r(n-1)+.h(n-1))
      and r(n)=if n=0 then 1./.sqrt(8.) else sqrt(r(n-1)*.h(n));;
\end{lstlisting}

donne~:

\begin{lstlisting}
# 1./.h(20);;
- : float = 3.14159265359038
# 1./.h(20)-.1./.r(20);;
- : float = 8.81517081552374293e-13
\end{lstlisting}


\subsubsection{Avec XCAS en impératif}


\xc
\begin{lstlisting}[caption={approximation de $\pi$ par la méthode de Cues en impératif}]
cues(n):={
local h,r;
h:=0.25;
r:=1/sqrt(8);
 for(k:=1;k<=n;k:=k+1){
    h:=0.5*(r+h);
    r:=sqrt(r*h);
 }
return(1/h,evalf(1/h-1/r))
}:;
\end{lstlisting}


\subsubsection{Avec Sage en impératif}


\sage

\begin{lstlisting}[caption={approximation de $\pi$ par la méthode de Cues en impératif}]
def cues(n):
    h=0.25
    r=1./sqrt(8.)
    for k in xrange(1,n):
        h=0.5*(r+h)
        r=sqrt(r*h)
    return 1/h,(1/h-1/r)
\end{lstlisting}

Par exemple:

\begin{lstlisting}[caption={}]
sage: cues(20)
(3.14159265359214, 3.52473605857995e-12)
\end{lstlisting}

\subsection{Méthode d'Al-Kashi}


\subsubsection{La méthode}

Voir \textit{Tangente} hors-série n°36 \og le cercle\fg{} page 16.

\subsubsection{Avec CAML en récursif}

\caml
\begin{lstlisting}[caption={approximation de $\pi$ par la méthode d'Al-Kashi en récursif}]
# let a(n)=
  let rec b(n)=if n=0 then sqrt(3.) else sqrt(2.+.b(n-1))
  in 3.*.2.**(float_of_int(n))*.sqrt(4.-.b(n)*.b(n));; 
\end{lstlisting}

donne~:

\begin{lstlisting}
# a(20);;
- : float = 3.14167426502175751
\end{lstlisting}


\subsubsection{Avec XCAS en impératif}

\xc
\begin{lstlisting}[caption={approximation de $\pi$ par la méthode d'Al-Kashi en impératif}]
alkashi(n):={
local k,b;
b:=sqrt(3.);
 for(k:=1;k<=n;k:=k+1){
    b:=sqrt(2+b)
 }
return(3*2^n*sqrt(4-b^2))
}:;
\end{lstlisting}

\section{Approximation   de  $\pi$  par   dénombrement  des   points  de
  coordonnées entières d'un disque}


\xc
\section{Flocons fractales}

  On peut définir récursivement le flocon de \textsc{Von Koch}.


Pour simplifier, on se contentera de \og floconiser\fg{} un segment.


\subsection{Avec la tortue}
\begin{lstlisting}[caption={flocon de Von Koch avec la tortue LOGO}]
koch(long,n):={
si (n==0) alors
avance(long);
sinon
koch(long/3,n-1);tourne_gauche(60);
koch(long/3,n-1);tourne_droite(120);
koch(long/3,n-1);tourne_gauche(60);
koch(long/3,n-1);
fsi;
}:;
\end{lstlisting}

Alors 

\begin{lstlisting}
koch(500,3)
\end{lstlisting}

renvoie 

\begin{figure}
\begin{center}
  \includegraphics[width=\textwidth]{koch1}
\end{center}
\end{figure}

et

\begin{lstlisting}
koch(500,6)
\end{lstlisting}

renvoie 

\begin{figure}
\begin{center}
  \includegraphics[width=\textwidth]{koch2}
\end{center}
\end{figure}



\subsection{Avec les outils géométriques de XCAS}
  
\begin{lstlisting}[caption={flocon de Von Koch avec XCAS}]
KochBis(n,A,B):={
 if(n==0){segment(A,B)}
 else{
   KochBis(n-1,A,homothetie(A,1/3,B)),
   KochBis(n-1,homothetie(A,1/3,B),rotation(homothetie(A,1/3,B),pi/3,homothetie(A,2/3,B))),
   KochBis(n-1,rotation(homothetie(A,1/3,B),pi/3,homothetie(A,2/3,B)),homothetie(A,2/3,B)),
   KochBis(n-1,homothetie(A,2/3,B),B)
 }
}:;
\end{lstlisting}

On peut alors s'amuser à dessiner un flocon à partir d'un triangle équilatéral~:

\begin{lstlisting}
KochBis(3,point(0,0),point(10,0)),KochBis(3,point(10,0),point(5,-10*sqrt(3.0)/2)),KochBis(3,point(5,-10*sqrt(3.0)/2),point(0,0))
\end{lstlisting}



\begin{figure}
\begin{center}
  \includegraphics[width=0.8\textwidth]{koch3}
\end{center}
\end{figure}
  

\section{Polygones de \textsc{Sierpinski}}

Waclaw \textsc{Sierpinski}  (1882 - 1969) fut  un mathématicien polonais
qui travailla sur des domaines mathématiques très ardus~:~fondements des
mathématiques,  construction  axiomatique  des ensembles,  hypothèse  du
continu, topologie, théorie des nombres...

Il a  également travaillé sur  les premiers objets  fractals qu'étudiera
plus tard  Benoît \textsc{Mandelbrot}, mathématicien  français d'origine
polonaise connu pour ses travaux dans ce domaine.

\subsection{Jouons aux dés}

Prenez un  dé à  6 faces,  un triangle ABC  et un  point G  quelconque à
l'intérieur du triangle.

Vous lancez le dé~:

\begin{itemize}
\item si la face supérieure est 1  ou 2, vous faites une petite croix au
  niveau du milieu de G et de A~;
\item si la face supérieure est 3  ou 4, vous faites une petite croix au
  niveau du milieu de G et de B~;
\item si la face supérieure est 5  ou 6, vous faites une petite croix au
  niveau du milieu de G et de C~;
\end{itemize}


Ah, zut, on n'a pas de dé dans la salle d'info...mais on a XCAS ou Sage.


\subsubsection{Avec XCAS}


\begin{itemize}
\item \verb+hasard(0,1)+ renvoie un  nombre aléatoirement choisi entre 0
  et 1~;
\item  \verb+hasard(n)+ renvoie  un entier  aléatoirement  choisi entre
  $0$ inclus et $n$ exclus.
\end{itemize}



\xc

\begin{lstlisting}[caption={}]
dede(n):={
local P,r,t,d,G,L,k;
 P:=[[0,0],[1,0],[0.5,0.5*sqrt(3)]];
 t:=hasard(0,1);
 G:=t^2*P[0]+2*t*(1-t)*P[1]+(1-t)^2*P[2];
 L:=G;
  pour k de 1 jusque n faire
      G:=0.5*(G+P[hasard(3)]);
      L:=L,G;
  fpour;
 nuage_points([L]);
}:;  
\end{lstlisting}


ce qui donne en lançant \verb+dede(10000)+~:



\begin{figure}
\begin{center}
  \includegraphics{triserpi}
\end{center}
\end{figure}


\subsubsection{Avec Sage}

\begin{itemize}
\item \verb+random()+ renvoie un  nombre aléatoirement choisi entre 0
  et 1~;
\item  \verb+floor(n*random())+ renvoie  un entier  aléatoirement  choisi entre
  $0$ inclus et $n$ exclus.
\end{itemize}

\sage

\begin{lstlisting}[caption={}]
def dede(n):
    P=[[0,0],[1,0],[0.5,0.5*sqrt(3)]]
    t=random()
    G=map(lambda x,y,z:t^2*x+2*t*(1-t)*y+(1-t)^2*z,P[0],P[1],P[2])
    L=[G]
    for k in [1..n]:
        G=map(lambda x,y:0.5*(x+y),G,P[floor(3*random())])
        L+=[G]
    D=points(L)
    D.show()
\end{lstlisting}

Alors:

\begin{lstlisting}[caption={}]
sage: dede(10000)
\end{lstlisting}

donne:


%\begin{figure}
\begin{center}
  \includegraphics{triserpisage}
\end{center}
%\end{figure}




\subsection{Étoiles et espaces}



Que fait cette procédure~:

\xc
\begin{lstlisting}[caption={Tableau en triangle}]
pascal(n):={
local T,j,i;
 T:=[[0$n]$n];
 pour j de 0 jusque n-1 faire
   pour i de 0 jusque n-1 faire 
     si j>i alors T[i,j]:="" ;
     fsi;
   fpour;
 fpour;
retourne(T);
}:;
\end{lstlisting}




Transformez-la un peu pour obtenir ceci avec $n=10$ par exemple~:


\begin{Verbatim}
        1                                                                                            
        1    1                                                                                       
        1    2    1                                                      
        1    3    3     1                                      
        1    4    6     4      1                               
        1    5    10    10     5      1                        
        1    6    15    20    15      6     1                  
        1    7    21    35    35     21     7     1            
        1    8    28    56    70     56     28    8     1      
        1    9    36    84    126    126    84    36    9    1 

\end{Verbatim}
     

Complétez cette dernière procédure  afin de remplacer chaque nombre pair
par  une  espace \verb+`  `+  et chaque  nombre  impair  par une  étoile
\verb+`*`+. Lancez-la pour $n=48$~: incroyable, non~?





\emph{Solution}~:

\begin{lstlisting}[caption={Triangle de Pascal de Sierpinski}]
PascalT(n):={
local T,j,i;
 T:=[[0$n]$n];
 pour j de 0 jusque n-1 faire
   pour i de 0 jusque n-1 faire 
     si j>i alors T[i,j]:="" ;
     sinon si j==0 alors T[i,j]:=1 ; 
            sinon si i==j alors T[i,j]:=1; 
                   sinon si (i>0) et (j>0) alors  T[i,j]:=T[i-1,j]+T[i-1,j-1];
     fsi;fsi;fsi;fsi;
   fpour;
 fpour;
 pour i de 0 jusque n-1 faire
    pour j de 0 jusque i faire
      si irem(T[i,j],2)==0 alors T[i,j]:="";
      sinon T[i,j]:="*";
      fsi;
    fpour;
 fpour; 
 retourne(T);
}:;
\end{lstlisting}





\subsection{Tapis}

Considérons les huit transformations de $\bbc$ dans $\bbc$ suivantes :
$$ T_1(z)=\frac{1}{3} z \qquad T_2(z)=\frac{1}{3} z+\frac{1}{3} \qquad T_3(z)=\frac{1}{3}
z+\frac{2}{3}\qquad T_4(z)=\frac{1}{3} z+\frac{2}{3} +\frac{1}{3} i$$

$$T_5(z)=\frac{1}{3} z+\frac{2}{3} +\frac{2}{3} i \qquad T_6(z)=\frac{1}{3} z+\frac{1}{3}+\frac{2}{3} i\qquad
T_7(z)=\frac{1}{3} z+\frac{2}{3} i\qquad T_8(z)= \frac{1}{3} z+\frac{1}{3} i$$

Soit $E_0$ le carré unité.

\begin{itemize}
\item Dessinez $E_0$~;

\item Dessinez $E_1=T_1(E_0)\cup T_2(E_0)\cup\cdots \cup T_8(E_0)$~;

\item Identifiez les $T_k$.
\end{itemize}



Comment obtenir ce joli dessin avec XCAS~?



\begin{figure}
\begin{center}
  \includegraphics{tapisserp}
\end{center}
\end{figure}





\emph{Solution~:}


\begin{lstlisting}[caption={Tapis de Sierpinski}]
Tapis(n):={
 local T,P,r,t,d,G,L,k,m,q,R,s,z;
 P:=[0,1,1+i,i];
 t:=hasard(0,1);
 G:=sum(binomial(3,q)*t^q*(1-t)^(3-q)*P[q],q=0..3);//barycentre "intérieur" quelconque
 L:=[re(G),im(G)];
 T:=[z->z/3,z->z/3+1/3,z->z/3+2/3,z->z/3+1/3+2*i/3,z->z/3+2/3+2*i/3,z->z/3+2/3+i/3,z->z/3+i/3,z->z/3+2*i/3]; 
  pour k de 1 jusque n faire
      G:=T[hasard(8)](G);
      L:=L,[re(G),im(G)];
   fpour;
 nuage_points([L]);
}:;  
\end{lstlisting}



\subsection{Les mites de \textsc{Sierpinski}}



Monsieur\textsc{ Sierpinski}  avait ramen\'e d'un voyage en Orient un tapis carr\'e de $1$ m\`etre de
c\^ot\'e dont il \'etait tr\`es content. Jusqu'au jour o\`u les mites s'introduisirent chez lui.

En 24 heures, elles d\'evor\`erent dans le tapis un carr\'e de
c\^ot\'e trois fois plus petit, situ\'e exactement au centre du
tapis. En constatant les d\'egats, Monsieur\textsc{ Sierpinski} entra dans
une col\`ere noire~! Puis il se consola en se disant qu'il lui
restait huit petits carr\'es de tapis, chacun de la taille du
carr\'e disparu. Malheureusement, dans les 12 heures qui
suivirent, les mites avaient attaqu\'e les huit petits carr\'es
restants~: dans chacun, elles avaient mang\'e un carr\'e central
encore trois fois plus petit. Et dans les 6 heures suivantes elles
grignot\`erent encore le carr\'e central de chacun des tout petits
carr\'es restants. Et l'histoire se r\'ep\'eta, encore et encore~;
\`a chaque \'etape, qui se d\'eroulait dans un intervalle de temps
deux fois plus petit que l'\'etape pr\'ec\'edente, les mites
faisaient des trous de taille trois fois plus petite...


\begin{itemize} \item 
 Calculer le nombre total de trous dans le tapis de Monsieur \textsc{Sierpinski}
apr\`es $n$ \'etapes. Calculer la surface $S_n$ de tapis qui n'a
pas encore \'et\'e mang\'ee apr\`es $n$ \'etapes. Trouver la
limite de la suite $(S_n)_{n \geq 0}$. Que reste-t-il du tapis \`a
la fin de l'histoire~?

\item Calculer la dur\'ee totale du festin <<~mitique~>>...

\end{itemize}

{\itshape Merci à \href{http://matexo.smai.emath.fr/exemaalt/exos\_individuels/pdf\_navigable/Tapis-de-Sierpinski.pdf}{Frédéric Le Roux}}






\subsection{Dentelle de Varsovie}

Nous voudrions obtenir le joli napperon en dentelle suivant~:



\begin{figure}
\begin{center}
  \includegraphics[scale=1.1]{pentaserp}
\end{center}
\end{figure}




Déterminez le rapport des similitudes qui transforment le grand pentagone en
un des pentagones plus petit.

En  vous  inspirant   de  ce  qui  a  été  fait   pour  le  triangle  de
\textsc{Sierpinski}, faites tracer à XCAS ou Sage ce joli napperon.



\subsubsection{Avec XCAS}

\emph{En  fait on  peut montrer  que pour  un nombre  $c  \geqslant5$ de
  côtés,       le        rapport       est       de       $\displaystyle
  \frac{1}{2\sum_{k=0}^{\left[\frac{c}{4}\right]}\cos
    \left(\frac{2k\pi}{c}\right)}$}


\emph{Solution~:}


\xc
\begin{lstlisting}[caption={Dentelle de Sierpinski}]
Serp(c,n):={
 local P,r,t,d,G,L,k,m,q,R,s;
 P:=[seq([re(exp(2*i*m*pi/c)),im(exp(2*i*m*pi/c))],m=1..c)]; // sommets du polygone régulier
 t:=hasard(0,1);  // paramètre pour le barycentre
 R:=evalf(1/(2*sum(cos(2*s*pi/c),s,0,floor(c/4)))); // rapport des similitudes
 G:=sum(binomial(c-1,q)*t^q*(1-t)^(c-1-q)*P[q],q,0,c-1); // barycentre "intérieur" quelconque
 L:=G;
  pour k de 1 jusque n faire
      G:=R*(G+P[hasard(c)]);
      L:=L,G;
  fpour;
 nuage_points([L])
}:;
\end{lstlisting}


\subsubsection{Avec Sage}


\sage
\begin{lstlisting}[caption={Dentelle de Sierpinski (Sage)}]
def serp(c,n):
    P=[[cos(2*m*pi/c),sin(2*m*pi/c)] for m in [1..c]]
    G=[0,0] # point de départ à l'intérieur du polygone
    s=var('s')
    R=1./(2.*sum(cos(2.*s*float(pi)/c),s,0,floor(c/4))) # rapport similitude
    L=[G]
    for k in [1..n]:
        G=map(lambda x,y:R*(x+y),G,P[floor(c*random())])
        L+=[G]
    D=points(L)
    D.show(aspect_ratio=1)
\end{lstlisting}


Pour $c=6$:

\begin{lstlisting}[caption={}]
sage: serp(6,5000)
\end{lstlisting}




%\begin{figure}
\begin{center}
  \includegraphics{polyserpsage}
\end{center}
%\end{figure}




\section{Végétation récursive}


\subsection{Avec XCAS}

Analysez cet algorithme~:
\xc
\begin{lstlisting}[caption={L-System (XCAS)}]
arbre(A,B,Rap,Ang,n):={
    si n>0 alors             
      segment(point(A),point(B)),seq(arbre(B,B+Rap[q]*exp(Ang[q]*i)*(B-A),Rap,Ang,n-1),q=0..size(Rap)-1)
      sinon  segment(point(A),point(B))
    fsi
}:;
\end{lstlisting}



sachant que 



\begin{lstlisting}[caption={}]
arbre(0,i,[0.7,0.8],[pi/5.,-pi/5.],7)
\end{lstlisting}




donne


\begin{figure}
\begin{center}
  \includegraphics{arbre1}
\end{center}
\end{figure}



Comment obtenir cette fougère et ce brocolis~?

\begin{minipage}[t]{0.45\textwidth}\vspace{0cm}\begin{flushleft}\includegraphics[width=0.9\linewidth]{arbre2}\end{flushleft}\end{minipage}\hspace{0.5cm}\begin{minipage}[t]{0.45\textwidth}\vspace{-0.7cm}
\hspace{5.5cm}
\begin{flushright}\includegraphics[width=0.9\linewidth]{arbre3}\end{flushright}\end{minipage}


\subsection{Avec Sage}


\sage

\begin{lstlisting}[caption={L-System (Sage)}]
def p_c(A):
    return [A.real(),A.imag()] # Donne les coordonnées de l'image d'un complexe

def arbre2(A,B,Rap,Ang,n):
    if n==0 : return line([p_c(A),p_c(B)])
    else :
        return line([p_c(A),p_c(B)])+arbre2(B,B+Rap[0]*exp(Ang[0]*I)*(B-A),Rap,Ang,n-1)+arbre2(B,B+Rap[1]*exp(Ang[1]*I)*(B-A),Rap,Ang,n-1)
\end{lstlisting}

Par exemple:



\begin{lstlisting}[caption={}]
sage: P=arbre2(0.,1.*I,[0.6,0.8],[float(pi)/5.,-float(pi)/5.],7)
sage: P.show(axes=False)
\end{lstlisting}


%\begin{figure}
\begin{center}
  \includegraphics{fougeresage}
\end{center}
%\end{figure}



\xc

\section{Ensembles de \textsc{Julia} et de \textsc{Mandelbrot}}

\subsection{Ensemble de \textsc{Julia} }

Gaston \textsc{Julia} (1893 - 1978)  est un mathématicien français qui a
travaillé  en particulier  sur les  fonctions à  variable  complexe. Ses
travaux ont été largement  utilisé par Benoît \textsc{Mandelbrot} (né en
1924) au
début des années 1970. Nous  allons survoler certains de leurs résultats
les plus populaires.


Nous  allons  étudier  les   suites  $(z_n)$  définies  par  $z_0$  et
$z_{n+1}=z_n^2+c$  pour  tout entier  naturel  $n$  avec  $c$ un  nombre
complexe quelconque.

Nous  avons  déjà exploré  une  suite  réelle  semblable lors  de  notre
incursion dans la dynamique des populations.


Le cas $c=0$ est assez simple à étudier~:~faites-le~!


\subsubsection{Avec XCAS}

Comment ce que vous avez obtenu est en lien avec cette procédure XCAS et son
utilisation ?


\xc
\begin{lstlisting}[caption={ensembles de Julia}]

julia(n,c,X,Y):= {
local pasx,pasy,L,k,x,y,z,m;
pasx:=2.*X/n;
pasy:=2.*Y/n;
L:=[0$n^2];
k:=0;
pour x de -X jusque X pas pasx faire
   pour y de -Y jusque Y pas pasy faire
       z:=evalf(x+i*y) 
       m:=0;
         tantque (abs(z)<2) et (m<30)  faire
           z:=evalf(z^2+c);
           m:=m+1;
         ftantque;
       L[k]:= couleur(point(x+i*y),m+point_point+epaisseur_point_2)
       k:=k+1;
    fpour;
fpour;
retourne(L)
$}:;

\end{lstlisting}



\begin{lstlisting}[caption={}]
julia(100,0,1.1,1.1)
\end{lstlisting}

\begin{figure}
\begin{center}
  \includegraphics{julia0}
\end{center}
\end{figure}



Testez  différentes  valeurs  de  $c$~:~$-1$,  $0,32+0,043  \mathrm{i}$,
$-0,122561+0,744862 \mathrm{i}$.


Voici par exemple \verb+julia(150,-1,1.7,0.9)+~:

\begin{figure}
\begin{center}
  \includegraphics{julia}
\end{center}
\end{figure}



Quelles sont vos interprétations~?





\subsubsection{Avec Sage}
\sage



\begin{figure}[!h]
  \begin{Idee}{\texttt{for...break...else} sur Python}
Python contient une boucle \texttt{for} particulière :

\begin{lstlisting}[caption={}]
for iteration
   if condition
       break # on sort de la boucle for
   action1 # si condition n'est pas remplie
else action2 # si on sort de for normalement sans break
\end{lstlisting}
    \end{Idee}
  \end{figure}



  \begin{figure}[!h]
    \begin{Remarque}[\texttt{complex}]
Il est plus rapide de calculer avec \verb+complex(re,im)+ qu'avec \verb|re+I*im|
      \end{Remarque}
    \end{figure}


    \begin{lstlisting}[caption={Ensemble de Julia (Sage)}]
def julia(c):
    c=complex(c)
    def juju(z):
        z=complex(z)
        for k in xrange(100):
            if abs(z)>2:
                break
            z=z^2+c
        else:
            return complex(z)
        return complex(0,k)
    return complex_plot(juju, (-2,2), (-1.5,1.5),plot_points=200)
    \end{lstlisting}

Par exemple:

\begin{lstlisting}[caption={}]
julia(-1)
\end{lstlisting}

donne le joli dessin suivant:


%\begin{figure}
\begin{center}
  \includegraphics{juliasage}
\end{center}
%\end{figure}

et:


\begin{lstlisting}[caption={}]
sage: julia(0.32+I*0.043)
\end{lstlisting}


donne:


%\begin{figure}
\begin{center}
  \includegraphics{juliasagebis}
\end{center}
%\end{figure}



\subsection{Ensemble de \textsc{Mandelbrot}}


Plutôt  que  de   testez  les  valeurs  de  $c$   une  par  une,  Benoît
\textsc{Mandelbrot}  a cherché  à  représenter las  valeurs  de $c$  qui
faisaient  converger   la  suite  avec   $z_0=0$~:~c'est  l'ensemble  de
\textsc{Mandelbrot}.

Tracez-le~!


\emph{Solution~:}


\subsubsection{Avec XCAS}
\xc
\begin{lstlisting}[caption={Ensemble de Mandelbrot}]
MB(n):={
local pasx,pasy,L,k,x,y,c,z,m;
pasx:=2.9./n;
pasy:=2.4/n;
L:=[0$n^2];
k:=0;
pour x de -2 jusque 0.9 pas pasx faire
   pour y de -1.2 jusque 1.2 pas pasy faire
       c:=evalf(x+i*y) 
       z:=c;
       m:=0;
         tantque (abs(z)<2) et (m<30)  faire
           z:=evalf(z^2+c);
           m:=m+1;
         ftantque;
       L[k]:= couleur(point(x+i*y),m+point_point+epaisseur_point_2)
       k:=k+1;
    fpour;
fpour;
retourne(L)
$}:;
\end{lstlisting}




\begin{figure}
\begin{center}
  \includegraphics{mandel}
\end{center}
\end{figure}


\subsubsection{Avec Sage}


\sage


    \begin{lstlisting}[caption={Ensemble de Mandelbrot (Sage)}]
def mandelbrot(c):
    z=complex(0,0)
    c=complex(c)
    for k in xrange(100):
        if abs(z)>2:
            break
        z=z^2+c
    else:
        return complex(0,0)
    return complex(0,k)
    \end{lstlisting}


On    utilise    ensuite    
\verb+complex_plot(fonction,(xmin,xmax),(ymin,ymax),plot_points=nombre)+:


\begin{lstlisting}[caption={}]
complex_plot(mandelbrot, (-2,1), (-1.5,1.5),plot_points=200)
\end{lstlisting}




%\begin{figure}
\begin{center}
  \includegraphics{mandelsagemil}
\end{center}
%\end{figure}

\xc

\section{Les vecteurs, le renard et le lapin}

\subsection{Première poursuite}

Un lapin court vers le nord en  ligne droite et un renard le poursuit en
bondissant toujours dans sa direction.

On suppose que le lapin et le renard fond des bonds de longueurs respectives
$bl$ et $br$, que le lapin part du point de coordonnées $(0;0)$ et le renard du
point de coordonnées $(x_0,y_0)$.

On  repérera ensuite  les  animaux par  le  point $R(x;y)$  et le  point
$L(0;z)$.

Calculons  la distance  Renard-Lapin~:~comme $\ve{RL}(-x;z-y)$  alors la
distance $d$ qui les sépare vaut \[d=\sqrt{x^2+(y-z)^2}\]


Il est alors pratique de travailler dans un espace affine. 

La position
suivante du renard, après un bond est $R+\frac{br}{d}\ve{RL}$

Celle du lapin est $L+bl \ve{\jmath}$.  Tout est en ordre pour pouvoir
programmer...


\begin{lstlisting}[caption={poursuite renard/lapin (1)}]
poursuite1(xo,yo,br,bl):={
local R,L,d,pR,Dir,nbsaut;
R:=[xo,yo];
L:=[0,0];
pR:=NULL;
Dir:=NULL;
nbsaut:=0;
d:=evalf(sqrt(xo^2+yo^2));
 while((nbsaut<1000) and (d>0)){
 pR:=R,pR;
 Dir:=Dir,segment(point(R),point(L));
 d:=evalf(sqrt((L[0]-R[0])^2+(L[1]-R[1])^2));
  if(d>br)then{
   R:=R+(br/d)*(L-R);
   L:=L+[0,bl];
  }else{R:=L}
 nbsaut:=nbsaut+1;
 }
print(if(nbsaut<1000)
      then{"Lapin attrapé en "+nbsaut+" bonds"}
      else{"Le lapin court toujours après 1000 bonds"})
return(display(polygonscatterplot([pR]),blue+line_width_3+point_width_3),Dir)
}:;
\end{lstlisting}


Par exemple, avec  des bonds du renard deux fois plus longs que ceux du
lapin~:

\begin{lstlisting}
poursuite1(6,4,1,0.5,7)
\end{lstlisting}


\begin{figure}
\begin{center}
  \includegraphics[width=\linewidth]{lapin1}
\end{center}
\end{figure}


\subsection{Avec un lapin plus malin~?}


Le lapin fait maintenant des bonds en zigue-zagant à angle droit.%  avec la droite
% $(RL)$. Cela demande de  réfléchir à l'action d'une rotation vectorielle
% d'angle $\frac{\pi}{2}$ sur les coordonnées d'un vecteur donné~:~$(a;b)$
% devient $(-b;a)$.


% Notons maintenant $R(x;y)$  et $L(u;v)$ puis $R'$ et  $L'$ les positions
% au bond suivant. On a~:

% \[\ve{RL}(u-x,v-y)\quad\ve{RR'}=\frac{br}{d}(u-x,v-y)\quad
% \ve{LL'}\frac{bl}{d}(-v+y,u-x)\]


\begin{lstlisting}[caption={poursuite renard/lapin (2)}]
poursuite2(xo,yo,br,bl):={
local R,L,d,pR,nbsaut,Dir;
R:=[xo,yo];
L:=[0,0];
pR:=NULL;
pL:=NULL;
Dir:=NULL;
nbsaut:=0;
 d:=evalf(sqrt((L[0]-R[0])^2+(L[1]-R[1])^2));
 while((nbsaut<1000) and (d>0)){
 pR:=R,pR;
 pL:=L,pL;
 Dir:=Dir,segment(point(R),point(L));
 d:=evalf(sqrt((L[0]-R[0])^2+(L[1]-R[1])^2));
  if(d>br)then{
   R:=R+(br/d)*(L-R);
   L:=L+if(irem(nbsaut,2)==0)then{[0,bl]}else{[-bl,0]};
  }else{R:=L}
 nbsaut:=nbsaut+1;
 }
print(if(nbsaut<1000)
      then{"Lapin attrapé en "+nbsaut+" bonds"}
      else{"Le lapin court toujours après 1000 bonds"})
return(display(polygonscatterplot([pR]),blue+line_width_3+point_width_3),
display(polygonscatterplot([pL]),green+line_width_3+point_width_3),
Dir)
}:;
\end{lstlisting}



Le lapin gagne 2 bonds...



\begin{figure}
\begin{center}
  \includegraphics[width=\linewidth]{lapin2}
\end{center}
\end{figure}


\chapter{Algorithmes en probabilité}

\section{Pile ou face}


\subsection{Avec XCAS}

On lance trois fois de suite  une pièce de monnaie. On compte combien de
fois pile (ou face) tombe.

Avec XCAS~:
\xc
\begin{lstlisting}[caption={pile ou face}]
piece(n):={
T:=NULL;
pour k de 1 jusque n faire
  X:=0;
  si hasard(2)==1 alors X:=X+1; fsi;
  si hasard(2)==1 alors X:=X+1; fsi;
  si hasard(2)==1 alors X:=X+1; fsi;
  T:=T,X;
fpour;

retourne(evalf([count_eq(0,[T])/n,count_eq(1,[T])/n,count_eq(2,[T])/n,count_eq(3,[T])/n])
)}:;
\end{lstlisting}


Sachant que~:

\begin{itemize}
\item \texttt{rand(k)}  renvoie un entier aléatoirement compris  entre 0 et
  $k-1$~;
\item  \texttt{count\_eq(entier,liste)}  compte  le  nombre de  fois  ou
  \texttt{entier} apparaît dans \texttt{liste}
\end{itemize}

Par exemple~:

\begin{lstlisting}
piece(5000)
\end{lstlisting}

renvoie \texttt{[0.1262,0.387,0.366,0.1208]}.

En  effet, on  peut vérifier  avec \texttt{binomial(n,k,p)}  qui renvoie
$\binom{n}{k}p^k(1-p)^{n-k}$~:

\begin{lstlisting}
[seq(binomial(3,k,0.5),k=0..3)]
\end{lstlisting}

renvoie \texttt{[0.125,0.375,0.375,0.125]}

On peut faire la  moyenne sur une dizaine de séries de  5000 séries de 3
lancers~:

\begin{lstlisting}
mean([seq(piece(5000),k=0..10)])
\end{lstlisting}

et on obtient \texttt{[0.1272909091,0.3854,0.3637272727,0.1235818182]}


\subsection{Avec Sage}
\sage

\begin{lstlisting}[caption={}]
def count_eq(n,L): # pour compter les occurrences de n dans la liste L
    return len(filter(lambda x:x==n,L))
    
def piece(n):
    T=[]
    for k in xrange(1,n+1):
        X=0
        if floor(2*random())==1 : X+=1
        if floor(2*random())==1 : X+=1
        if floor(2*random())==1 : X+=1
        T+=[X]
    return([(count_eq(j,T)/n).n(digits=3) for j in xrange(0,4) ])
\end{lstlisting}


Par exemple, pour $\numprint{100000}$ lancers:

\begin{lstlisting}[caption={}]
sage: piece(1000000)
[0.125, 0.376, 0.374, 0.125]
\end{lstlisting}



\section{Tirage de boules}


\subsection{Avec XCAS}

On dispose de trois urnes, la  première contenant 7 boules blanches et 4
noires, la deuxième 5 blanches et 2 noires, la troisième 6 blanches et 3
noires.

On  tire une  boule dans  chaque urne  et on  note le  nombre  de boules
blanches obtenues.

On adapte l'algorithme précédent~:
\xc
\begin{lstlisting}[caption={exemple de tirage de boules}]
boules(n):={
T:=NULL;
pour que de 1 jusque n faire
  X:=0;
  si hasard(11)<7 alors X:=X+1; fsi;
  si hasard(7)<5  alors X:=X+1; fsi;
  si hasard(9)<6  alors X:=X+1; fsi;
  T:=T,X;
fpour
retourne(evalf([count_eq(0,[T])/n,count_eq(1,[T])/n,count_eq(2,[T])/n,count_eq(3,[T])/n])
)}:;
\end{lstlisting}

On obtient \texttt{[0.0358,0.2253818182,0.4453272727,0.2934909091]}


Or,      par     exemple,   $\frac{7}{11}\times     \frac{5}{7}\times
\frac{6}{9}\approx 0,303$ et $\frac{4}{11}\times \frac{2}{7}\times
\frac{3}{9}\approx 0,034$.




\subsection{Avec Sage}


\sage

\begin{lstlisting}[caption={exemple de tirage de boules}]
def boules(n):
    T=[]
    for k in xrange(1,n+1):
        X=0
        if floor(11*random())<7 : X+=1
        if floor(7*random())<5 : X+=1
        if floor(9*random())<6 : X+=1
        T+=[X]
    return([(count_eq(j,T)/n).n(digits=3) for j in xrange(0,4) ])
\end{lstlisting}


Par exemple, pour $\numprint{10000}$ lancers:


\begin{lstlisting}[caption={}]
sage: boules(100000)
[0.0345, 0.218, 0.445, 0.302]
\end{lstlisting}



\section{Tirage de boules avec remise}


Simulons le tirage successif de  quatre boules avec remise dans une urne
contenant 7  boules blanches et 3  boules noires. Comptons  le nombre de
tirages contenant 

\begin{itemize}
\item exactement deux boules blanches~;
\item au moins une boule blanche.
\end{itemize}



\subsection{Avec XCAS}

\xc
\begin{lstlisting}[caption={tirage de boules avec remise (XCAS)}]
boule(n,nb):={
local X,k,j,B;
X:=0;
pour k de 1 jusque n faire
  B:=0;
  pour j de 1 jusque 4 faire
    si hasard(10)<7 alors B:=B+1 fsi
  fpour
  si B==nb alors X:=X+1; fsi
fpour
retourne(evalf(X/n))
}:;
\end{lstlisting}


Alors  pour $\numprint{1000000}$  tirages, on  obtient pour  deux boules
blanches~:


\begin{lstlisting}[caption={}]
boule(1000000,2) 
\end{lstlisting}

\reponse{0.264818}

En effet, le tirage se fait sans remise.  La probabilité d'obtenir
  $(N,N,B,B)$ est~:
\[\frac{3}{10}\times        \frac{3}{10}\times        \frac{7}{10}\times
\frac{7}{10}=\frac{441}{\numprint{10000}}\]

 Les tirages  de deux  boules  exactement sont  les anagrammes  de
  $(N,N,B,B)$.

On multiplie donc le résultat précédent par $\frac{4!}{2!\times 2!}=6$.
\[6\times
\frac{441}{\numprint{10000}}=\numprint{0,2646}\]

\medskip

 Obtenir au  moins une boule blanche est  le contraire d'en obtenir
  aucune~:


  \begin{lstlisting}[caption={}]
1-boule(1000000,0)   
  \end{lstlisting}


\reponse{0.991846}

En effet

\[1-\left(\frac{3}{10}\right)^4=\numprint{0,9919}\]

\subsection{Avec Sage}

\sage

\begin{lstlisting}[caption={tirage de boules avec remise (XCAS)}]
def boule(n,nb):
    X=0
    for k in xrange(1,n+1):
        B=0
        for j in xrange(1,5):
            if floor(10*random())<7 : B+=1
        if B==nb : X+=1
    return float(X/n)
\end{lstlisting}


Alors  pour $\numprint{100000}$  tirages, on  obtient pour  deux boules
blanches~:

\begin{lstlisting}[caption={}]
sage: boule(100000,2)
0.26401999999999998
\end{lstlisting}


Obtenir au  moins une boule blanche est  le contraire d'en obtenir
  aucune:

  \begin{lstlisting}[caption={}]
sage: 1-boule(100000,0)
0.99189000000000005
  \end{lstlisting}


\section{Le Monty Hall}


Le jeu oppose un présentateur à un candidat. Ce joueur est placé devant trois portes fermées. Derrière l'une d'elles se trouve une voiture  et derrière chacune des deux autres se trouve une chèvre. Il doit tout d'abord désigner une porte. Puis le présentateur ouvre une porte qui n'est ni celle choisie par le candidat, ni celle cachant la voiture (le présentateur sait quelle est la bonne porte dès le début). Le candidat a alors le droit ou bien d'ouvrir la porte qu'il a choisie initialement, ou bien d'ouvrir la troisième porte.

Les questions qui se posent au candidat sont :

\begin{itemize}
\item Que doit-il faire ?
\item Quelles sont ses chances de gagner la voiture en agissant au mieux ?
\end{itemize}


On peut avoir deux idées contradictoires~:
\begin{itemize}
\item le présentateur  ayant ouvert une porte, le  candidat a une chance
  sur deux de tomber sur la voiture~;
\item  Au départ,  le candidat  a  une probabilité  de $\frac{1}{3}$  de
  tomber sur  la voiture.  Ensuite, s'il garde  son choix initial,  il a
  toujours la même probabilité  $\frac{1}{3}$ de gagner donc s'il change
  d'avis, la probabilité qu'il gagne est donc $1-\frac{1}{3}=\frac{2}{3}$.
\end{itemize}

Qui a raison~?


\subsection{Avec XCAS}

Simulons la situation à l'aide de XCAS.

\xc
\begin{lstlisting}[caption={jeu du Monty Hall (XCAS)}]
monty(n):={
local gagne_sans_changer,gagne_en_changeant,j,voiture,choix,ouverte,changement;
gagne_sans_changer:=0;
gagne_en_changeant:=0;
pour j de 1 jusque n faire

 voiture:=hasard(3);
 choix:=hasard(3);

 si choix==voiture 
 alors ouverte:=irem(voiture + (1+hasard(2)) , 3);
 sinon ouverte:=(0+1+2) - choix - voiture;
 fsi

 changement:=(0+1+2) - choix - ouverte;

 si choix==voiture
 alors   gagne_sans_changer:=gagne_sans_changer+1
 fsi

 si changement==voiture 
 alors gagne_en_changeant:=gagne_en_changeant+1
 fsi
fpour
retourne("Gagne en changeant : "+(100.*gagne_en_changeant/n)+"%  
Gagne sans changer : "+ (100.*gagne_sans_changer/n)+"%")
}:;
\end{lstlisting}


Alors pour $\numprint{1000000}$ de parties~:

\begin{lstlisting}[caption={}]
monty(1000000)  
\end{lstlisting}

\reponse{Gagne en changeant : 66.6898\%  
Gagne sans changer : 33.3102\%}



La deuxième option semble la bonne...il reste à le prouver~!

Dressons un arbre en trois étapes~:

\begin{itemize}

\item Le candidat choisit d'abord une porte de manière
équiprobable~;

\item Le  présentateur, sachant  où se  trouve la  voiture, choisit  une porte
cachant une chèvre~;

\item Le candidat prend ensuite la  décision de garder ou de changer son
  choix initial.

\end{itemize}

\newcommand{\Ch}[1]{\Tr{\psframebox{\text{\small Chèvre #1}}}} % carré
\newcommand{\Vo}{\Tcircle{\text{\small Voiture}}} % rond
% syntaxe : \pstree{le père}{les fils}
{\small
\[
\pstree[treemode=R,levelsep=+3.5cm]{\Tp}{%
        \pstree{\Ch{1}\taput{\color{blue}{1/3}}}{%
               \pstree{\Ch{2}\taput{\color{gray}{1}}}{%
                      \Vo\taput{\text{\small\color{blue!50!black} Change}}
                      \Ch{1}\tbput{\text{\small\color{blue!50!black} Garde}}}}
        \pstree{\Ch{2}\taput{\color{blue}{1/3}}}{%
               \pstree{\Ch{1}\taput{\color{gray}{1}}}{%
                      \Vo\taput{\text{\small\color{blue!50!black} Change}}
                      \Ch{2}\tbput{\text{\small\color{blue!50!black} Garde}}}}
        \pstree{\Vo\taput{\color{blue}{1/3}}}{%
               \pstree{\Ch{1}\taput{\color{gray}{1/2}}}{%
                      \Vo\taput{\text{\small\color{blue!50!black} Garde}}
                      \Ch{2}\tbput{\text{\small\color{blue!50!black} Change}}}
               \pstree{\Ch{2}\taput{\color{gray}{1/2}}}{%
                      \Vo\taput{\text{\small\color{blue!50!black} Garde}}
                      \Ch{1}\tbput{\text{\small\color{blue!50!black} Change}}}}}
\]
}



Nous en déduisons que~:


\begin{itemize}
\item s'il  conserve son choix  initial, la probabilité que  le candidat
  gagne la voiture est~:
\[\frac{1}{3}\times                         \frac{1}{2}+\frac{1}{3}\times
\frac{1}{2}=\frac{1}{3}\]
\item s'il change son choix initial, la probabilité que  le candidat
  gagne la voiture est~:
\[\frac{1}{3}\times1+\frac{1}{3}\times1=\frac{2}{3}\]
\end{itemize}

Il vaut donc mieux pour le candidat changer son choix initial.


\subsection{Avec Sage}

\sage

\begin{lstlisting}[caption={Monty Hall (Sage)}]
def monty(n):
    gagne_sans_changer=0
    gagne_en_changeant=0
    for j in xrange(1,n+1):
        voiture=floor(3*random())
        choix=floor(3*random())
        if choix==voiture:
            ouverte=(voiture+1+floor(2*random())) % 3
        else:
            ouverte=0+1+2-choix-voiture
        changement=0+1+2-choix-ouverte
        if choix==voiture:
            gagne_sans_changer+=1
        if changement==voiture:
            gagne_en_changeant+=1
    return 'Gagne en changeant : '+str(100.*gagne_en_changeant/n)+'%   Gagne sans changer : '+ str(100.*gagne_sans_changer/n)+'%'
\end{lstlisting}

Alors, pour $\numprint{100000}$ expériences:

\begin{lstlisting}[caption={}]
sage: monty(100000)
'Gagne en changeant : 66.3930000000000%   Gagne sans changer : 33.6070000000000%'
\end{lstlisting}

\section{Problème du Duc de Toscane}

Cosme II de Médicis  (Florence 1590-1621), Duc de Toscane, fut le  protecteur de l'illustre Gallilée
(né à Pise le 15 février 1564 et mort à Florence le 8 janvier 1642) son ancien précepteur. Profitant
d'un moment de répit du savant entre l'écriture d'un théorème sur la chute des corps et la création
de la lunette astronomique, le Grand Duc lui soumet le problème suivant~:~il a observé qu'en lançant
trois dés cubiques et en  faisant la somme des numéros des faces, on obtient  plus souvent 10 que 9,
alors qu'il y a autant de façons d'obtenir 9 que 10, à savoir six. 

Après  quelques réflexions,  Galilée  rédigea  un petit  mémoire  sur les  jeux  de  hasard en  1620
expliquant le phénomène. 


\subsection{Avec XCAS}

\subsubsection{Méthode \og naturelle\fg{}}


On utilise une boucle \textit{pour}:



\xc


\begin{lstlisting}[caption={problème du Duc de Toscane (XCAS 1)}]
toscane(n):={
local T,k;
T:=NULL;
pour k de 1 jusque n faire
T:=T,(((3+hasard(6))+hasard(6))+hasard(6))
fpour
retourne("Obtenir 9 :"+count_eq(9,[T])*100.0/n+"%"," Obtenir 10 :"+count_eq(10,[T])*100.0/n+"%")
}:;
\end{lstlisting}


Pour $\numprint{100000}$ simulations sur mon ordinateur, il faut... énormément de temps!




\subsubsection{Utilisation de l'opérateur \texttt{=<}}


L'opérateur permet de stocker une valeur \texttt{dans une liste} déjà existante: on gagne donc du temps  car on ne s'occupe que d'un terme à chaque fois et non pas de toute la liste. 

\begin{lstlisting}[caption={problème du Duc de Toscane (XCAS 2)}]
toscanebis(n):={
local T,k;
T:=[seq(0,k=1..n)];  // on crée un tableau contenant n zéros
pour k de 0 jusque n-1 faire
T[k]=<(((3+hasard(6))+hasard(6))+hasard(6)) // on remplace petit à petit chaque zéro
fpour
retourne("Obtenir 9 :"+count_eq(9,[T])*100.0/n+"%"," Obtenir 10 :"+count_eq(10,[T])*100.0/n+"%")
}:;
\end{lstlisting}
Cette fois il faut 1 seconde pour $\numprint{100000}$ simulations sur mon ordinateur.


\reponse{Evaluation time: 1.38}
\reponse{"Obtenir 9 :11.674\%"," Obtenir 10 :12.56\%"}

\subsubsection{Utilisation de  \texttt{ranm}}


\begin{lstlisting}[caption={problème du Duc de Toscane (XCAS 3)}]
toscaneter(n):={
T:=ranm(1,n,'(((3+hasard(6))+hasard(6))+hasard(6))');
retourne("Obtenir 9 :"+count_eq(9,T)*100.0/n+"%"," Obtenir 10 :"+count_eq(10,T)*100.0/n+"%")
}:;
\end{lstlisting}

Alors, pour $100\,000$ tirages, on obtient en  moins d'une seconde:


\reponse{Evaluation time: 0.52}
\reponse{"Obtenir 9 :11.47\%"," Obtenir 10 :12.477\%"}

On a utilisé \texttt{ranm(lignes,colonnes,'expérience')} qui renvoie une
matrice \texttt{lignes}$\times$\texttt{colonnes} où  chaque terme est un
résultat de \texttt{expérience}.



\subsection{Avec Sage}

\sage

\begin{lstlisting}[caption={problème du Duc de Toscane (Sage)}]
def toscane(n):
    def count_eq(n,L):
        return len(filter(lambda x:x==n,L))
    T=n*[0]
    for k in xrange(0,n):
        T[k]=3+floor(6*random())+floor(6*random())+floor(6*random())
    return 'Obtenir 9 :'+str(count_eq(9,T)*100.0/n)+'% ,  Obtenir 10 :'+str(count_eq(10,T)*100.0/n)+'%'
\end{lstlisting}


Pour $100000$ lancers:

\begin{lstlisting}[caption={}]
sage: toscane(100000)
'Obtenir 9 :11.7440000000000% ,  Obtenir 10 :12.4600000000000%'
\end{lstlisting}

\section{ Lancers d'une pièce et résultats égaux}

On lance  10 fois  de suite une  pièce de  monnaie et on  s'intéresse au
nombre maximal de résultats consécutifs  égaux. On crée un programme qui
simule autant de séries de lancers que l'on désire.

\subsection{Avec XCAS}

\xc
\begin{lstlisting}[caption={pile ou face (2)}]
piece_max(essais):={
local S,k,P,j,H,m,M,s,p,h;
S:=[seq(0,k=1..essais)];
pour k de 1 jusque essais faire 
   s:=NULL; 
   P:=[seq(hasard(2),m=0..9)];
   p:=0;
   tantque p<9 faire
      j:=p+1; 
      tantque (P[j]==P[p] and j<9) faire 
          j+=1
      ftantque;
      s:=s,j-p; 
      p:=j;
   ftantque;
   s:=SortD([s]); 
   h:=head(s); 
   S[k]=<h; 
fpour;
m:=evalf(moyenne(S),2);
retourne("
Sur "+essais+" séries de 10 lancers, la moyenne du nombre maximal de résultats consécutifs égaux est "+m)
}:;
\end{lstlisting}

\begin{itemize}
\item On crée une liste S remplie de \verb+essais+ zéros pour y mettre les max ;
\item on boucle les essais ;
\item on crée une liste s enregistrant le nombre de résultats consécutifs égaux ;
\item on crée une liste P de 10 lancers de 0 ou 1 ;
\item tant  qu'on n'est  pas au bout  de la  liste (p<9), on  regarde le
  suivant (\verb|j=p+1|)
\item tant que le suivant est égal, on continue (\verb|j:=j+1|) ;
\item on  rajoute le nombre  de lancers  égaux et on  enlève p car  on a
  commencé à p+1 (\verb+s:=s,j-p+) ;
\item on va ensuite voir le prochain résultat différent (p:=j) ;
\item on classe dans l'ordre décroissant les résultats (\verb+SortD([s])+) ;
\item on prend le premier de la liste : c'est le plus grand (\verb+head(s)+) ;
\item  on le stocke  dans une  liste avant  de refaire  une série  de 10
  (\verb+S[k]=<h+).

\end{itemize}


Par exemple:

\begin{lstlisting}[caption={}]
piece_max(10000)
\end{lstlisting}


\reponse{Sur 10000 séries de 10 lancers, la moyenne du nombre maximal de résultats consécutifs égaux est 3.51}



\subsection{Avec Sage}

\sage


\begin{lstlisting}[caption={lancers successifs de pièces (Sage)}]
def piece_max(n):
    S=n*[1]
    for k in xrange(0,n):
        s=[]
        P=[floor(2*random()) for z in xrange(0,10)]
        p=0
        while p<9:
            j=p+1
            while (P[j]==P[p] and j<9):
                j+=1
            s+=[j-p]
            p=j
        s.sort(reverse=True)
        S[k]=s[0]
    m=(sum(S)/n).n(digits=3)
    return 'Sur '+str(n)+'  series de 10 lancers, la moyenne du nombre maximal de resultats consecutifs egaux est '+str(m)
\end{lstlisting}


Avec $\numprint{10000}$ lancers:


\begin{lstlisting}[caption={}]
sage: piece_max(10000)
'Sur 10000  series de 10 lancers, la moyenne du nombre maximal de resultats consecutifs egaux est 3.50'
\end{lstlisting}



\section{Le lièvre et la tortue}


On  rappelle le  jeu  bien connu~:~on  dispose  d'un dé  cubique. On  le
lance. Si  un six  sort, le  lièvre gagne sinon  la tortue  avance d'une
case. La tortue a gagné lorsqu'elle a avancé six fois de suite.

Il est aisé de montrer que  la probabilité que la tortue gagne $\bbp(T)$
est égale à $\left(\frac{5}{6}\right)^6\approx 0,335$.

Voici un exemple de simulation de $n$ parties avec XCAS~:

\xc
\begin{lstlisting}[caption={le lièvre et la tortue (1)}]
jeutortue(n):={
local simul,L,T,face,lancer;
L:=0;T:=0;
 pour simul de 1 jusque n faire
   face:=hasard(6)+1; 
   lancer:=1;
   tantque(face<6) et (lancer<6) faire
     face:=hasard(6)+1;
     lancer+=1;
   ftantque
   si face==6
     alors L+=1
     sinon T+=1
   fsi
 fpour
retourne("Tortue :"+T*100.0/n+"% Lièvre : "+L*100.0/n+"%")
}:;
\end{lstlisting}

Alors on peut simuler $100\,000$ parties en entrant~:

\begin{lstlisting}
jeutortue(100000)
\end{lstlisting}

et on obtient par exemple~:

\begin{center}
  \texttt{Tortue :33.639\%    Lievre : 66.361\%}
\end{center}

On peut modifier légèrement  le programme précédent pour déterminer quel
nombre maximum de lancers on doit fixer pour rendre le jeu favorable à la
tortue~:



\begin{lstlisting}[caption={le lièvre et la tortue (2) (XCAS)}]
jeutortue(n,lancer_max):={
local simul,L,T,face,lancer;
L:=0;T:=0;
 pour simul de 1 jusque n faire
   face:=hasard(6)+1; lancer:=1;
   tantque(face<6) et (lancer<lancer_max)faire
     face:=hasard(6)+1;
     lancer:=lancer+1;
   ftantque
   si face==6
     alors L:=L+1
     sinon T:=T+1
   fsi
 fpour

retourne(T*100.0/n)
}:;
\end{lstlisting}

On n'a cette fois en sortie que le pourcentage de parties gagnées par la
tortue.

On    trace    ensuite   le    nuage    de    points   de    coordonnées
\texttt{(lancer\_max,jeutortue(10000,k))} avec \texttt{k} variant de 1 à
10 par exemple.


\begin{lstlisting}
nuage_points([seq([k,jeutortue(10000,k)],k=1..10)]),droite(y=50)
\end{lstlisting}

et on obtient~:


\begin{figure}
\begin{center}
  \includegraphics{tortue}
\end{center}
\end{figure}


\subsection{Avec Sage}


\sage

\begin{lstlisting}[caption={lièvre et tortue 1 (Sage)}]
def jeutortue(n):
    [L,T]=[0,0]
    for simul in xrange(1,n+1):
        face=1+floor(6*random())
        lancer=1
        while face<6 and lancer<6:
            face=1+floor(6*random())
            lancer+=1
        if face==6 : L+=1
        else : T+=1
    return 'Tortue :'+str(T*100.0/n)+'% Lièvre : '+str(L*100.0/n)+'%'
\end{lstlisting}


Sur $\numprint{10000}$ parties:

\begin{lstlisting}[caption={}]
sage: jeutortue(100000)
'Tortue :33.3100000000000% Li\xc3\xa8vre : 66.6900000000000%'
\end{lstlisting}


Quel
nombre maximum de lancers doit-on fixer pour rendre le jeu favorable à la
tortue?

\begin{lstlisting}[caption={lièvre et tortue 2 (Sage)}]
def jeutortuemax(n,lancer_max):
    [L,T]=[0,0]
    for simul in xrange(1,n+1):
        face=1+floor(6*random())
        lancer=1
        while face<6 and lancer<lancer_max:
            face=1+floor(6*random())
            lancer+=1
        if face==6 : L+=1
        else : T+=1
    return T*100.0/n

def trace_tortue():
    L=points([[k,jeutortuemax(10000,k)] for k in xrange(1,11)])
    D=line([[0,50],[10,50]])
    (L+D).show()
\end{lstlisting}



On lance \verb+trace_tortue()+ et on obtient:


%\begin{figure}
\begin{center}
  \includegraphics{tortuesage}
\end{center}
%\end{figure}


\section{Générateurs de nombres aléatoires}


Les    machines     ont    leur    propre     générateur    de    nombre
aléatoire. Pouvons-nous en fabriquer un nous-même~?


\subsection{Méthode  \og  middle   square\fg{}  de  John  \textsc{Von
    Neumann}}


L'un des pères fondateurs de l'informatique avec Alan \textsc{Turing} et
Alonzo  \textsc{Church}...  des  années  avant  l'invention  du  premier
ordinateur.

On prend un nombre  de $n$ chiffres, on l'élève au carré  et on forme un
nouveau nombre avec les $n$  chiffres situés \og au milieu\fg{} du carré
et on recommence.

Les  nombres ainsi  formés appartiennent  à l'intervalle  $\llbracket\; 0\,;\,
10^n-1\rrbracket$. Il suffit alors de  les diviser par $10^n$ pour avoir
des nombres entre 0 et 1.


Premier problème~:~comment extraire $n$ chiffres \og du milieu\fg{}~?

D'ailleurs, on  ne sait même pas  combien il y  aura de chiffres~:~
$2n-1$ ou $2n$.

Prenons par exemple $n=4$.

En XCAS, on va  utiliser exceptionnellement les commandes \texttt{input,
  goto} et \texttt{label}~:
\xc
\begin{lstlisting}[caption={générateur de nombres aléatoires}]
ms(N):={
S:=N;
k:=1;
print(N);
label truc;
N:=N^2;
    if(N>=10^7)
     then{N:=floor(N/10^2);
          N:=N-10^4*floor(N/10^4);
          S:=S+N;k:=k+1;
          afficher(N)
       }
     else{N:=floor(N/10);
          N:=N-10^(4)*floor(N/10^(4));
          S:=S+N;k:=k+1;
          afficher(N)
       }
input("Continuer : o sinon : n",rep);
 if(rep==o)goto truc;
 if(rep==n)return("moyenne : "+evalf(S/k));
}:;
\end{lstlisting}


Une petite fenêtre apparaît à chaque génération pour demander si on doit
continuer. Si on  arrête en répondant \texttt{n}, on  obtient la moyenne
des résultats.






\section{Calcul de $\pi$ avec une pluie aléatoire}

\xc


\subsection{La méthode}

\subsection{Avec XCAS en impératif}

\begin{lstlisting}[caption={calcul de $\pi$ avec une pluie aléatoire en impératif (XCAS)}]
pluie(n):={
local r,k;
 for(k:=1;k<=n;k:=k+1){
   r:=r+1-floor(rand(0,1)^2+rand(0,1)^2)
 }
return(4.0*r/n)
}:;
\end{lstlisting}

\subsection{Avec XCAS en impératif}
\sage
\begin{lstlisting}[caption={calcul de $\pi$ avec une pluie aléatoire en impératif (Sage)}]
def pluie(n):
    r=0
    for k in xrange(1,n+1):
        r+=1-floor(random()**2+random()**2)
    return 4.*r/n
\end{lstlisting}


\begin{lstlisting}[caption={}]
sage: pluie(1000000)
3.14338000000000
\end{lstlisting}

\subsection{Avec CAML en récursif}

\caml

\begin{lstlisting}[caption={calcul de $\pi$ avec une pluie aléatoire en récursif}]
# let pluie(n)=
  let rec pr(n)=
    if n=0 
       then 0 
       else 1+pr(n-1)-int_of_float(Random.float(1.)**2.+.Random.float(1.)**2.)
  in 4.*.float_of_int(pr(n))/.float_of_int(n);;
\end{lstlisting}


\section{Loi normale}


\subsection{Avec XCAS}
\xc
Ne      connaissant     pas      de      primitive     de      $t\mapsto
\frac{1}{\sqrt{2\pi}}\E^{-\frac{t^2}{2}}$,  on  utilise  la méthode  des
rectangles         pour         obtenir        une         approximation
de \[\int_0^X\frac{1}{\sqrt{2\pi}}\E^{-\frac{t^2}{2}}\mathrm{d} t\]

\begin{lstlisting}[caption={approximation d'une probabilité élémentaire (loi normale)}]
normale(T):={
DIGITS:=4;
dt:=0.001;
f:=t->(exp(-0.5*t^2))/sqrt(2*Pi);
t:=0;
S:=0;
while(t<=T){
S:=S+f(t)*dt;
t:=t+dt;
}
return(S)
}:;
\end{lstlisting}


On   s'aperçoit  que  cette   intégrale  \emph{semble}   converger  vers
$\frac{1}{2}$~:

\begin{lstlisting}
normale(10); normale(20);
\end{lstlisting}

\reponse{0.5002,0.5002}



Ça peut se comprendre (mais pas  se démontrer en BTS...) en observant le
graphe correspondant~:

\begin{lstlisting}
graphe((exp(-0.5*t^2))/sqrt(2*Pi),t=-5..5)
\end{lstlisting}


\begin{figure}
\begin{center}
  \includegraphics{normale}
\end{center}
\end{figure}


On   peut  ensuite  utiliser   notre  procédure   \texttt{normale}  pour
construire la table qu'on retrouve sur le formulaire des BTS~:


\begin{lstlisting}[caption={table de la loi normale}]
tablenormale():={
local T,l,L,c;
T:=["",seq(k*0.01,k=0..9)];
 for(l:=0;l<3;l:=l+0.1){
   L:=l;
   for(c:=0;c<=0.09;c:=c+0.01){L:=L,0.5+normale(l+c)} 
   T:=T,[L] 
 }
return([T])
}:;
\end{lstlisting}

et on obtient en 10 secondes~:
{\small
\[\left(\begin{array}{ccccccccccc}
\mathrm{} &      0.0&      0.01&      0.02 &      0.03 &      0.04 &      0.05 &      0.06 &      0.07 &      0.08 &      0.09 \\
0 &      0.500399 &      0.503989 &      0.507978 &      0.511967 &      0.515954 &      0.519939 &      0.523923 &      0.527904 &      0.531882 &      0.535857 \\
     0.1 &      0.539829 &      0.543797 &      0.547760 &      0.551718 &      0.555672 &      0.559620 &      0.563562 &      0.567498 &      0.571427 &      0.575349 \\
     0.2 &      0.579264 &      0.583171 &      0.587069 &      0.590959 &      0.594841 &      0.598712 &      0.602575 &      0.606427 &      0.610269 &      0.614100 \\
     0.3 &      0.617920 &      0.621729 &      0.625526 &      0.629311 &      0.633083 &      0.636842 &      0.640589 &      0.644322 &      0.648041 &      0.651746 \\
     0.4  &      0.655437 &      0.659113 &      0.662774 &      0.666420 &      0.670050 &      0.673664 &      0.677262 &      0.680843 &      0.684408 &      0.687956 \\
     0.5  &      0.691486 &      0.694999 &      0.698493 &      0.701970 &      0.705429 &      0.708868 &      0.712289 &      0.715691 &      0.719074 &      0.722437 \\
     0.6  &      0.725780 &      0.729103 &      0.732406 &      0.735689 &      0.738951 &      0.742192 &      0.745412 &      0.748611 &      0.751789 &      0.754945 \\
     0.7  &      0.758080 &      0.761192 &      0.764283 &      0.767352 &      0.770398 &      0.773422 &      0.776423 &      0.779401 &      0.782357 &      0.785290 \\
     0.8  &      0.788199 &      0.791086 &      0.793949 &      0.796789 &      0.799605 &      0.802398 &      0.805167 &      0.807913 &      0.810634 &      0.813332 \\
     0.9  &      0.816006 &      0.818656 &      0.821282 &      0.823884 &      0.826462 &      0.829016 &      0.831546 &      0.834052 &      0.836533 &      0.838990 \\
     1. 0 &      0.841423 &      0.844072 &      0.846454 &      0.848812 &      0.851146 &      0.853455 &      0.855741 &      0.858002 &      0.860240 &      0.862453 \\
     1.1  &      0.864642 &      0.866808 &      0.868949 &      0.871067 &      0.873160 &      0.875230 &      0.877277 &      0.879300 &      0.881299 &      0.883275 \\
     1.2  &      0.885227 &      0.887156 &      0.889062 &      0.890945 &      0.892804 &      0.894641 &      0.896455 &      0.898246 &      0.900015 &      0.901761 \\
     1.3  &      0.903485 &      0.905186 &      0.906865 &      0.908523 &      0.910158 &      0.911772 &      0.913364 &      0.914934 &      0.916483 &      0.918011 \\
     1.4  &      0.919518 &      0.921003 &      0.922468 &      0.923913 &      0.925336 &      0.926740 &      0.928123 &      0.929486 &      0.930830 &      0.932153 \\
     1.5  &      0.933457 &      0.934742 &      0.936007 &      0.937253 &      0.938480 &      0.939689 &      0.940879 &      0.942050 &      0.943203 &      0.944338 \\
     1.6  &      0.945456 &      0.946555 &      0.947637 &      0.948702 &      0.949749 &      0.950779 &      0.951793 &      0.952789 &      0.953769 &      0.954733 \\
     1.7  &      0.955681 &      0.956613 &      0.957529 &      0.958429 &      0.959314 &      0.960183 &      0.961038 &      0.961878 &      0.962702 &      0.963513 \\
     1.8  &      0.964309 &      0.965090 &      0.965858 &      0.966612 &      0.967352 &      0.968079 &      0.968792 &      0.969492 &      0.970179 &      0.970854 \\
     1.9  &      0.971516 &      0.972165 &      0.972802 &      0.973427 &      0.974040 &      0.974641 &      0.975231 &      0.975809 &      0.976376 &      0.976932 \\
     2. 0 &      0.977476 &      0.978010 &      0.978534 &      0.979047 &      0.979549 &      0.980042 &      0.980524 &      0.980997 &      0.981460 &      0.981913 \\
     2.1  &      0.982357 &      0.982792 &      0.983218 &      0.983634 &      0.984042 &      0.984442 &      0.984832 &      0.985215 &      0.985589 &      0.985955 \\
     2.2  &      0.986314 &      0.986664 &      0.987007 &      0.987342 &      0.987670 &      0.987991 &      0.988304 &      0.988611 &      0.988910 &      0.989203 \\
     2.3  &      0.989490 &      0.989769 &      0.990043 &      0.990310 &      0.990571 &      0.990825 &      0.991074 &      0.991317 &      0.991555 &      0.991787 \\
     2.4  &      0.992013 &      0.992234 &      0.992450 &      0.992660 &      0.992866 &      0.993067 &      0.993262 &      0.993453 &      0.993640 &      0.993821 \\
     2.5  &      0.993999 &      0.994171 &      0.994340 &      0.994504 &      0.994665 &      0.994821 &      0.994973 &      0.995122 &      0.995267 &      0.995408 \\
     2.6  &      0.995545 &      0.995679 &      0.995809 &      0.995937 &      0.996060 &      0.996181 &      0.996298 &      0.996413 &      0.996524 &      0.996632 \\
     2.7  &      0.996738 &      0.996840 &      0.996940 &      0.997038 &      0.997132 &      0.997224 &      0.997314 &      0.997401 &      0.997486 &      0.997568 \\
     2.8  &      0.997648 &      0.997726 &      0.997802 &      0.997876 &      0.997947 &      0.998017 &      0.998085 &      0.998150 &      0.998214 &      0.998276 \\
     2.9  &      0.998337 &      0.998395 &      0.998452 &      0.998507 &      0.998561 &      0.998613 &      0.998664 &      0.998713 &      0.998761 &      0.998807
\end{array}\right) 
\]
}
\subsection{Avec Sage}
\sage


\begin{lstlisting}[caption={loi normale (Sage)}]
def normale(T):
    dt=0.0001
    def f(t):
        return (exp(-0.5*t^2))/sqrt(2*float(pi))
    t=0
    S=0
    while t<=T:
        S+=f(t)*dt
        t+=dt
    return S
\end{lstlisting}



Pour le graphique:

\begin{lstlisting}[caption={}]
sage: t=var('t')
sage: g=plot((exp(-0.5*t^2))/sqrt(2*pi),t,-5,5)
sage: g.show()
\end{lstlisting}



%\begin{figure}
\begin{center}
  \includegraphics{normalesage}
\end{center}
%\end{figure}





\chapter{Statistiques}


\section{Lissage par moyennes mobiles}


On donne  une liste d'abscisses, une  liste d'ordonnées, un  ordre et on
demande le tracé de la courbe initiale et le tracé de la courbe lissée.

\subsection{Avec XCAS en impératif}

On  crée\footnote{Cette commande existe  déjà sur  XCAS mais  on apprend
  ici à programmer quelque soit le langage...} une fonction \verb+som_list(liste,debut,fin)+ qui calcule la somme des
éléments d'une liste du rang \verb+debut+ jusqu'au rang \verb+fin+.

\xc

\begin{lstlisting}[caption={somme des éléments d'une liste en impératif}]
som_list(liste,debut,fin):={
local S,k;
S:=0;
 for(k:=debut;k<=fin;k:=k+1){
    S+=liste[k]
 }
return(S)
}:;
\end{lstlisting}


Ensuite, il  nous faut une commande  \verb+ligne(liste abs,liste ord)+
qui trace la ligne brisée passant  par les points dont on donne la liste
des coordonnées.

\begin{lstlisting}[caption={tracé d'une ligne brisée}]
trace_ligne(X,Y,coul):={
local P,k;
if(size(X)!=size(Y))then{return("Probleme de taille...")}
P:=[seq(0,n=1..size(X))];
 for(k:=0;k<size(X);k:=k+1){
  P[k]=<[X[k],Y[k]];
 }
couleur(polygone_ouvert(P),coul);
}:;
\end{lstlisting}

Sur  XCAS, c'est  \verb+polygone_ouvert+ qui  relie des  points  par une
ligne brisée~; on adapte la commande au langage utilisé.

Voici le programme proprement dit~:


\begin{lstlisting}[caption={lissage par moyenne mobile en impératif (XCAS)}]
lmm(X,Y,k):={
Xm:=NULL;
Ym:=NULL;
n:=size(X);
if(k mod 2==0){
  p:=k/2;
  for(j:=p;j<n-p;j++){
  Ym:=Ym,(0.5*Y[j-p]+som_list(Y,j-p+1,j+p-1)+0.5*Y[j+p])/k;
  Xm:=Xm,X[j];
  }
}else{
p:=(k-1)/2;
  for(j:=p;j<n-p;j++){
  Ym:=Ym,(som_list(evalf(Y),j-p,j+p))/k;
  Xm:=Xm,X[j];
}
}
Xm:=[Xm];
Ym:=[Ym];
C:=trace_ligne(X,Y,red);
Cm:=trace_ligne(Xm,Ym,blue);
return(C,Cm)
}:;

\end{lstlisting}


Par exemple, voici ce que cela donne pour la moyenne lissée d'ordre 7 de
la série de mesure de l'étendue de la banquise au mois de septembre~:

\begin{lstlisting}
lmm([1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,
1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,
2006,2007,2008],[5.3,5.5,4.95,5.13,5.37,4.7,5,5.37,5.3,5.2,4.8,4.62,4.5,
5.05,4.45,4.85,4.4,5.25,4.9,4.26,4.2,4.14,4.55,4.05,4.12,4.3,4.05,4.06,
3.75,3.8],7) 
\end{lstlisting}



On obtient l'alarmant graphique~:


\begin{figure}
\begin{center}
  \includegraphics[width=\linewidth]{banquise}
\end{center}
\end{figure}

\subsection{Avec Sage en impératif}

\sage

On suit la même tactique:

\begin{lstlisting}[caption={lissage par moyenne mobile en impératif (Sage)}]
def som_list(liste,debut,fin):
    S=0
    for k in xrange(debut,fin+1):
        S+=liste[k]
    return S


def trace_ligne(X,Y,coul):
    P=len(X)*[0]
    for k in xrange(0,len(X)):
        P[k]=[X[k],Y[k]]
    return line(P,color=coul)

def lmm(X,Y,k):
    Xm=[]
    Ym=[]
    n=len(X)
    if k%2==0:
        p=k//2
        for j in xrange(p,n-p):
            Ym+=[(0.5*Y[j-p]+som_list(Y,j-p+1,j+p-1)+0.5*Y[j+p])/k]
            Xm+=[X[j]]
    else:
        p=(k-1)//2
        for j in xrange(p,n-p):
            Ym+=[(som_list(Y,j-p,j+p))/k]
            Xm+=[X[j]]
    C=trace_ligne(X,Y,'red')
    Cm=trace_ligne(Xm,Ym,'blue')
    LMM=C+Cm
    LMM.show()
\end{lstlisting}

Alors avec la même série:

\begin{lstlisting}[caption={}]
sage: lmm([1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008],[5.3,5.5,4.95,5.13,5.37,4.7,5,5.37,5.3,5.2,4.8,4.62,4.5,5.05,4.45,4.85,4.4,5.25,4.9,4.26,4.2,4.14,4.55,4.05,4.12,4.3,4.05,4.06,3.75,3.8],7)
\end{lstlisting}


On obtient:


%\begin{figure}
\begin{center}
  \includegraphics{banquisesage}
\end{center}
%\end{figure}


\subsection{Avec CAML en récursif}


Amusons-nous à fabriquer tous nos outils...

D'abord une fonction  qui extrait une liste d'une  liste existante entre
des rangs donnés~:

\caml
\begin{lstlisting}[caption={extraction d'une sous-liste en récursif}]
# let extrait(liste,debut,fin)=
      let rec extract=function
	|([],debut,fin,n)->[]
	|(tete::queue,debut,fin,n)-> 
               if (n>=debut) & (n<=fin)
	          then tete::extract(queue,debut,fin,n+1)
	          else if n<=fin 
		          then extract(queue,debut,fin,n+1)
		          else []
      in extract(liste,debut,fin,0);;
\end{lstlisting}


Par exemple~:

\begin{lstlisting}
# extrait([0;1;2;3;4;5;6;7;8;9],3,7);;
- : int list = [3; 4; 5; 6; 7]
\end{lstlisting}

Ensuite calculons la longueur d'une liste~:

\begin{lstlisting}[caption={longueur d'une liste en récursif}]
# let rec longueur=function
      | [] -> 0
      | tete::queue -> 1+longueur(queue);;
\end{lstlisting}


Puis la somme des éléments d'une liste~:

\begin{lstlisting}[caption={somme des éléments d'une liste en récursif}]
# let rec somme=function
      | [] -> 0.
      | tete::queue -> tete +. somme(queue);;
\end{lstlisting}

Calculons maintenant  la moyenne mobile  d'ordre $k$ d'une  liste donnée
avec $k$ un entier \emph{impair}~:

\begin{lstlisting}[caption={moyenne mobile en récursif}]
# let moyenne_mobile_impaire(y,k)=
    let rec mobile(y,k,n)=
      if n+k/2>=longueur(y) then []
      else somme(extrait(y,n-k/2,n+k/2))/.float_of_int(k)::mobile(y,k,n+1)
    in mobile(y,k,k/2);;
\end{lstlisting}


Par exemple~:

\begin{lstlisting}
# moyenne_lisse_mobile([1.;2.;3.;4.;5.;6.;7.;8.;9.;10.;11.],5);;
- : float list = [3.; 4.; 5.; 6.; 7.; 8.; 9.]

\end{lstlisting}


\section{Intervalle de fluctuation en 2\up{nde}}


\subsection{Le fameux théorème vu par XCAS}

Le document d'accompagnement affirme que pour des échantillons de taille
$n$  obtenus à partir  d'un modèle  de Bernoulli,  95\% des  mesures des
fréquences     mesurées     sont     comprises     dans     l'intervalle
$\left[p-\frac{1}{\sqrt{n}},p+\frac{1}{\sqrt{n}}\right]$   avec  $p$  la
proportion à mesurer.

On simule ici  N échantillons de taille $n$  d'un modèle de Bernoulli
ayant une probabilité $p$. 

On      simule     une      expérience      de     probabilité      $p$:
\verb+evalf(hasard(0,1))<p+.  En effet,  on  tire au  hasard un  décimal
entre 0 et 1 et on compte un point si ce nombre est inférieur à $p$.

On trace le nuage des points d'ordonnées les fréquences d'obtention d'un
résultat favorable.

On trace également les droites d'équations:

\[y=p\pm\frac{1}{\sqrt{n}}\]



\xc

\begin{lstlisting}[caption={intervalle de fluctuation en 2\up{nde} (XCAS)}]
echantillon(n,p,N):={
Freq:=NULL;
pour k de 1 jusque N faire
    S:=0;
    pour j de 1 jusque n faire
       si evalf(hasard(0,1))<p alors S+=1; fsi
    fpour 
    Freq:=Freq,[k,evalf(S/n)];
fpour
P:=affichage(nuage_points([Freq]),epaisseur_point_3);
D1:=affichage(droite(y=p-1./sqrt(n)),bleu+epaisseur_ligne_3);
D2:=affichage(droite(y=p+1./sqrt(n)),rouge+epaisseur_ligne_3);
retourne(P,D1,D2)
}:;
\end{lstlisting}


Par exemple, pour 1000 tirages d'échantillons de taille $n=100$ dans une
urne contenant une proportion $p=0,4$ de boules rouges~:


\begin{lstlisting}[caption={}]
echantillon(100,0.4,1000)
\end{lstlisting}


%\begin{figure}
\begin{center}
  \includegraphics{echantillon1}
\end{center}
%\end{figure}

On observe qu'une immense majorité des fréquences sont entre $p-\frac{1}{\sqrt{n}}$
et $p+\frac{1}{\sqrt{n}}$.

Le programme dit qu'au moins  $95\%$ des fréquences se trouvent dans cet
intervalle. Vérifions-le:


\begin{lstlisting}[caption={intervalle de fluctuation en 2\up{nde} bis (XCAS)}]
echantillon2(n,p,N):={
ok:=0;
pour k de 1 jusque N faire
    S:=0;
    pour j de 1 jusque n faire
       si evalf(hasard(0,1))<p alors S+=1; fsi
    fpour 
    si evalf(S/n)>=(p-1./sqrt(n)) et evalf(S/n)<=(p+1./sqrt(n)) 
       alors ok+=1
    fsi
fpour
retourne ok*100./N
}:;
\end{lstlisting}

\begin{lstlisting}[caption={}]
echantillon(100,0.4,10000)
\end{lstlisting}

\reponse{95.57}

On relance autant  de fois que l'on veut le calcul  pour observer que le
nombre obtenu est supérieur à 95.


Nous  ne discuterons  pas ici  de la  pertinence d'une  telle expérience
devant des élèves de 2\up{nde}...

\subsection{Le fameux théorème vu par SAGE}
\sage

\begin{lstlisting}[caption={intervalle de fluctuation en 2\up{nde} (Sage)}]
def echantillon(n,p,N):
    Freq=[]
    for k in xrange(1,N):
        S=0
        for j in xrange(1,n):
            if random()<p : S+=1
        Freq+=[[k,float(S/n)]]
    P=points(Freq)
    D1=line([[0,p-1./sqrt(n)],[N,p-1./sqrt(n)]])
    D2=line([[0,p+1./sqrt(n)],[N,p+1./sqrt(n)]])
    (P+D1+D2).show()
\end{lstlisting}



\begin{lstlisting}[caption={}]
sage: echantillon(100,0.4,1000)
\end{lstlisting}



%\begin{figure}
\begin{center}
  \includegraphics{echantillonsage}
\end{center}
%\end{figure}




\begin{lstlisting}[caption={intervalle de fluctuation en 2\up{nde} bis (Sage)}]
def echantillon2(n,p,N):
    ok=0
    for k in xrange(1,N):
        S=0
        for j in xrange(1,n):
            if random()<p : S+=1
        if (S/n)>=(p-1/sqrt(n)) and (S/n)<=(p+1/sqrt(n)):
            ok+=1
    return ok*100./N
\end{lstlisting}


\begin{lstlisting}[caption={}]
sage: echantillon2(100,0.4,10000)
95.7700000000000
sage: echantillon2(100,0.4,10000)
95.7900000000000
\end{lstlisting}

\subsection{Un exemple de TD en 2\up{nde}}
\xc


\subsubsection{Sondages et urnes}

\begin{enumerate}

\item  \textbf{Expérience }


Une  urne contient  un  très grand  nombre  de boules  dont $40\%$  sont
rouges. On en tire un échantillon de taille 100 au hasard. 

On mesure la fréquence de boules rouges obtenues.

Un résultat classique  en statistique affirme que la  probabilité que la
fréquence         observée         soit        dans         l'intervalle
$\left[0,40-\frac{1}{\sqrt{100}},0,40+\frac{1}{\sqrt{100}}\right]$    est
au moins supérieure  à une valeur que nous  allons essayer de déterminer
expérimentalement.



\item \textbf{Que voulons-nous que l'ordinateur fasse~?}

Nous allons généraliser le problème.

Nous allons demander à l'ordinateur d'effectuer un grand nombre N de
tirages  d'échantillons de  taille  $n$, sachant  que  la proportion  de
boules rouges est $p$.

Nous allons  représenter le nuage des points  d'ordonnées les fréquences
de boules rouges obtenues par échantillon.

On trace également les droites d'équations:

\[y=p\pm\frac{1}{\sqrt{n}}\]

\item \textbf{Procédure}



Essayez d'analyser la procédure suivante:

\begin{lstlisting}[caption={}]
echantillon(n,p,N):={
Freq:=NULL;
pour k de 1 jusque N faire
    S:=0;
    pour j de 1 jusque n faire
       si evalf(hasard(0,1))<p alors S+=1; fsi
    fpour 
    Freq:=Freq,[k,evalf(S/n)];
fpour
P:=affichage(nuage_points([Freq]),epaisseur_point_3);
D1:=affichage(droite(y=p-1./sqrt(n)),bleu+epaisseur_ligne_3);
D2:=affichage(droite(y=p+1./sqrt(n)),rouge+epaisseur_ligne_3);
retourne(P,D1,D2)
}:;
\end{lstlisting}


puis analyser le résultat.


\item \textbf{À vous de jouer}

Il faudrait légèrement modifier  la procédure précédente pour obtenir le
pourcentage de fréquences observées de boules rouges.


\item \textbf{Le théorème}


Le résultat suivant sera admis :

{\slshape  Lorsqu'on prélève  un échantillon  de taille  $n$  dans une
    population  où la  fréquence  d'un caractère  est  $p$, alors,  sous
    certaines conditions,  la probabilité que  cet échantillon fournisse
    une                       fréquence                      appartenant
    à  \[I=\left[p-\frac{1}{\sqrt{n}},p+\frac{1}{\sqrt{n}}\right]\]  est
    \textbf{au moins égale} à ..... $\%$}

\end{enumerate}

\subsubsection{Sondages et urnes: les élections}

Vu à la radio:
\og  {\itshape  En  perte de  vitesse  ces  derniers  mois, la  cote  du
  président syldave est remontée de $49\%$ à $52\%$ après son mariage avec la princesse
  Carlotta de Bordurie  qui a su séduire par  ses sourires les électeurs
  de Syldavie. }\fg{}

\begin{enumerate}
\item 
La véritable cote  de popularité du président auprès  des 60 millions de
Syldave est inconnue. Désignons-la par $p$. 

On  connaît   deux  fréquences   observées  sur  deux   échantillons  de
$\numprint{1000}$ personnes: $f_1=489\%$ et $f_2=52\%$.


Montrez                             que                            $f_i\in
I_i=\left[p-\frac{1}{\sqrt{n}},p+\frac{1}{\sqrt{n}}\right]$ équivaut à $p\in J_i=\left[f_i-\frac{1}{\sqrt{n}},f_i+\frac{1}{\sqrt{n}}\right]$.

\item 
Écrivez  les  intervalles  $J_1$  et  $J_2$  correspondant  à  $f_1$  et
$f_2$. Représentez-les sur une  droite graduée. Commentez alors l'annonce
faite à la radio.

\end{enumerate}



\subsubsection{Sondage personnel}


Lu à la syldavision:

{\itshape Le président  syldave a affirmé hier lors  de sa conférence de
  presse que sa cote de popularité est de $52\%$.}


\begin{enumerate}
\item Un  groupe dissident soutenu  par la Bordurie effectue  un sondage
  auprès  de 625  personnes et  obtient  une cote  de $47\%$  d'opinions
  favorables: le président syldave aurait-il menti?
\item Un autre sondage effectué auprès de 625 autres personnes donne une
  cote de $49\%$. Cela permet-il de confirmer la cote de $52\%$ annoncée
  par le président syldave?
\end{enumerate}



\subsubsection{Arnaque?}

La princesse  Carlotta anime  un jeu à  la télévision. Elle  annonce que
dans une urne  se trouvent 50 boules noires et  50 boules blanches. Elle
offrira une  photo dédicacée  de son mari  à toute personne  obtenant au
moins 11 boules blanches en tirant 30 boules au hasard de l'urne.

L'ambassadeur bordure participe au jeu.  Il tire 30 boules et obtient 10
blanches  seulement. Furieux,  il  décide  de déclarer  la  guerre à  la
Syldavie  affirmant   que  le   jeu  est  truqué.    Qu'en  pensez-vous?
Parviendrez-vous à éviter la guerre?
























\chapter{Un peu de logique}


\section{Fonction mystérieuse}

Observez ces fonctions et décrivez leur action sachant que \verb+&&+ signifie \og et\fg{} et que \verb+||+ signifie \og ou\fg{}~:

\caml
\begin{lstlisting}[caption={fonction mystérieuse (1)}]
# let rec truc(n)   = n<>1 && ( n=0 || machin(n-1) )
    and   machin(n) = n<>0 && ( n=1 || truc(n-1) ) ;;
\end{lstlisting}

Pour vous  mettre sur  la voie, voici  trois fonctions  plus compliquées
mais aux noms plus explicites... 



\begin{lstlisting}[caption={fonction mystérieuse (2)}]
# let rec multiple_3(n) = n<>1 && n<>2 && ( n=0 || reste_3_2(n-1) )
  and     reste_3_2(n)  = n<>0 && n<>1 && ( n=2 || reste_3_1(n-1) ) 
  and     reste_3_1(n)  = n<>0 && n<>2 && ( n=1 || multiple_3(n-1) );; 
\end{lstlisting}




















\chapter{Problèmes d'optimisation}

\section{Algorithme glouton et rendu de monnaie}

Une première idée pour optimiser une certaine situation est d'effecteur,
étape par  étape un  choix optimum local  dans l'espoir que  le résultat
global   obtenu   soit    optimum~:~l'algorithme   obtenu   est   appelé
\emph{algorithme glouton}.

Une illustration  classique de ce problème  est le rendu  de monnaie qui
est lui-même un cas particulier du problème du sac à dos. On
dispose d'au moins deux types de pièces de valeurs premières entre elles
(pourquoi~?...) et  on veut rendre la  monnaie en utilisant  le moins de
pièces possibles.

Une première  idée est de  répéter le choix  de la pièce de  plus grande
valeur  qui  ne dépasse  pas  la  somme  restante~:~c'est un  algorithme
glouton.


\begin{algorithm}[H]
\caption{algorithme glouton de rendu de monnaie}
\Entree{somme n à rendre et liste L des pièces disponibles}\;
\Ini{\;
somme partielle\aff 0\;
liste des pièces\aff vide\;
}\;
\Deb{
\Tq{somme partielle < n}
   {k\aff taille de la liste\;
      \Tq{k>0 et pièce n° k est supérieure à la somme restante}
         {k\aff k-1 : on regarde la pièce de valeur inférieure}
}
\Retour{liste des pièces}
 } 
\end{algorithm}


En XCAS, cela donne~:

\xc

\begin{lstlisting}[caption={rendu de monnaie par algorithme glouton}]
piece_glouton(n,L):={
local somme_partielle,liste_pieces,k;
somme_partielle:=0;
liste_pieces:=NULL;
while(somme_partielle<n){
  k:=size(L)-1;
   while((k>0) and (L[k]>(n-somme_partielle))){
     k:=k-1
   }
  somme_partielle:=somme_partielle+L[k];
  liste_pieces:=liste_pieces,L[k];  
}
}:;
\end{lstlisting}


Ainsi,  pour   savoir  comment  former  39  centimes   avec  nos  pièces
européennes, on entre~:


\begin{lstlisting}
piece_glouton(39,[1,2,5,10,20,50,100,200])
\end{lstlisting}

et on obtient \verb+20,10,5,2,2+.


Imaginons maintenant un pays dans lequel on dispose uniquement de pièces
de valeur 1, 4 et 5 et  que nous voulions rendre 8 unités monétaires. On
entre donc~:

\begin{lstlisting}
piece_glouton(8,[1,4,5])
\end{lstlisting}


qui répond \verb+5,1,1,1+ alors qu'il aurait été plus simple de rendre 2
pièces de 4 unités~:~{\bf un algorithme glouton n'est pas forcément optimum.}



En fait,  l'algorithme glouton est optimum  si la suite  des valeurs des
pièces est \emph{super-croissante} (on peut s'amuser à le démontrer...), c'est-à-dire si chaque terme est
supérieur à la somme des précédents. 

Par exemple,  $20>10+5+2+1$ mais $5\leqslant  4+1$ et la deuxième  liste n'est
pas super-croissante. 


Pour une  application du problème  du sac à  dos à la  cryptographie, se
reporter au paragraphe~\vref{sac}
\chapter{Manipulation de chaînes de caractères}

\section{Qu'est-ce qu'une chaîne de caractères~?}

Une chaîne  de caractère  est une suite  de caractères dont  l'ordre est
fixé.  Par exemple,  la chaîne  \og  bonjour\fg{} est  différente de  la
chaîne \og jourbon\fg{}.

\begin{figure}[!h]
  \begin{DANGER}[chaîne vide]
    Une espace n'est pas le vide~!
  \end{DANGER}
  \end{figure}



Chaque caractère est en effet associé à un codage binaire, en général
sur 8 bits (un octet) ce qui donne $2^8=256$ caractères possibles.

En fait,  un américain a mis au  point en 1961 l'ASCII  (on prononce \og
aski\fg{})   pour   \og   American   Standard   Code   for   Information
Interchange\fg{}  qui  codait 128  caractères  sur  7  bits ce  qui  est
suffisant pour les américains qui n'ont pas de lettres accentuées.

Il  a ensuite  fallu étendre  ce code  pour les  langues  comportant des
caractères  spéciaux  et là,  les  normes  diffèrent,  ce qui  crée  des
problèmes de compatibilité.

Depuis quelques années, le codage  \emph{Unicode} tente de remédier à ce
problème  en codant  tous  les caractères  existant.  C'est le  standard
utilisé sur les systèmes Linux par exemple.

La plupart des langages de programmation ont une commande qui associe le
code  ASCII  (éventuellement étendu)  à  un  caractère.  On pourra  donc
l'utiliser dans les algorithmes généraux.

\begin{center}
\begin{table}[h!]
\begin{tabularx}{\linewidth}{Il*{19}{|X}I}
\whline
Caractère&  & ! & " & \# & \$ & \% & \& & ' & (  & ) & * & + & , & - & . & / & 0 & 1 & 2 \\
\hline
Code & 32 & 33 & 34 & 35 & 36 & 37 & 38 & 39 & 40 & 41 & 42 & 43 & 44 & 45 & 46 & 47 & 48 & 49 & 50 \\
\hline
\end{tabularx}


\begin{tabularx}{\linewidth}{Il*{19}{|X}I}
\hline
Caractère&3 & 4 & 5 & 6 & 7 & 8 & 9 & : & ; & < & = & > & ? & @ & A & B & C & D & E \\
\hline
Code &51 & 52 & 53 & 54 & 55 & 56 & 57 & 58 & 59 & 60 & 61 & 62 & 63 & 64 & 65 & 66 & 67 & 68 & 69\\
\hline
\end{tabularx}



\begin{tabularx}{\linewidth}{Il*{19}{|X}I}
\hline
Caractère&F & G & H & I & J & K & L & M & N & O & P & Q & R & S & T & U & V & W & X \\
\hline
Code &70 & 71 & 72 & 73 & 74 & 75 & 76 & 77 & 78 & 79 & 80 & 81 & 82 & 83 & 84 & 85 & 86 & 87 & 88\\
\hline
\end{tabularx}





\begin{tabularx}{\linewidth}{Il*{19}{|X}I}
\hline
Caractère& Y & Z & [ & \verb+ \ + & ] & \verb+ ^ + & \verb+ _ + & \verb+ ` + & a & b & c & d & e & f & g & h & i & j & k \\
\hline
Code & 89 & 90 & 91 & 92 & 93 & 94 & 95 & 96 & 97 & 98 & 99 & 100 & 101 & 102 & 103 & 104 & 105 & 106 & 107 \\
\hline
\end{tabularx}



\begin{tabularx}{\linewidth}{Il*{19}{|X}I}

\hline
Caractère& l & m & n & o & p & q & r & s & t & u & v & w & x & y & z & \{ & | & \} & \verb+~+ \\
\hline
Code & 108 & 109 & 110 & 111 & 112 & 113 & 114 & 115 & 116 & 117 & 118 & 119 & 120 & 121 & 122 & 123 & 124 & 125 & 126\\
\whline
\end{tabularx}
\caption{Table des caractères ASCII affichables}
\end{table}

\end{center}




  
\begin{figure}[!h]
  \begin{Idee}{Au lycée}
    L'un des intérêts majeurs de la manipulation de chaînes de caractères au
lycée est  son application en  cryptographie mais un autre  domaine très
friand de ces chaînes est la génétique : chaîne d'ADN, protéines...

    \end{Idee}
  \end{figure}



\section{Quelques exercices basiques sur les chaînes}

\begin{enumerate}
\item \textsl{Écrire un algorithme qui transforme un entier entre 20 et 59 en sa transcription littérale.}

\subsection{Algorithme}

\begin{algorithm}[H]
  \caption{écriture littérale d'un entier}
\Entree{Saisir n : entier entre 20 et 59}\;
\Deb{

\Si{n<20  ou  n>  59}{\Retour{Il  faut  entrer un  entier  entre  20  et
    59}}\tcp{petite précaution en option...}\;
unite $\leftarrow$ [" ","-et-un","-deux","-trois","-quatre","-cinq","-six","-sept","-huit","-neuf"]\;
dizaine $\leftarrow$ ["vingt","trente","quarante","cinquante"]\;
N $\leftarrow$  chaîne(n) \tcp{On transforme  le nombre n en  une chaîne
  formée de deux caractères}\;
\Retour{concaténation(dizaine[N[0]-2],unite[N[1]])}
}
\end{algorithm}

Concaténer deux  chaînes c'est les mettre  bout à bout  pour n'en former
qu'une seule.



\subsection{Traduction XCAS}

\begin{lstlisting}[caption={écriture littérale d'un entier}]
litt(n):={
local unite,dizaine,N;

si (n<20)or(n>59) alors retourne("Il  faut  entrer un  entier  entre  20  et 59");fsi;

unite:=[" ","-et-un","-deux","-trois","-quatre","-cinq","-six","-sept","-huit","-neuf"];
dizaine:=["vingt","trente","quarante","cinquante"];
N:=string(n);

retourne(dizaine[expr(N[0])-2]+unite[expr(N[1])])
}:;
\end{lstlisting}


Sur  XCAS, la commande  \texttt{string()} retourne  l'expression évaluée
sous  forme  de chaîne  de  caractères  et  la commande  \texttt{expr()}
transforme une chaîne en une commande ou un nombre.

\begin{lstlisting}
litt(59)
\end{lstlisting}

retourne \verb+cinquante-neuf+.


\subsection{Variante}

\textsl{Donner un algorithme qui conjugue  à toutes les personnes de l'imparfait
du subjonctif
un verbe régulier du premier groupe...}





\item \textsl{Donner un algorithme qui  reçoit un mot non accentué en majuscules
  et le renvoie en minuscules sauf la première lettre.}


\subsection{Algorithme}

\begin{algorithm}[H]
  \caption{mise en minuscules}
\Entree{C : chaîne de caractères}\;
\Ini{c $\leftarrow$ chaîne vide\;}
\Deb{
\Pour{j de 1 jusqu'à taille(C)-1}{
concatène(c, chaîne(code(C[j])+32)
}\;
\Retour(concatène(C[0],c))\tcp{On garde la première lettre en majuscule}\;
}
\end{algorithm}

Une minuscule a pour code ASCII le code de la majuscule correspondant plus 32.


\subsection{Traduction XCAS}



\begin{lstlisting}[caption={mise en minuscules}]
capitale(C):={
c:="";
pour j de 1 jusque size(C)-1 faire
  c:=c+char(asc(C[j])+32);
fpour;
retourne(C[0]+c);
}:;
\end{lstlisting}

et \verb+capitale(MAMAN)+ donne bien \verb+Maman+.

\end{enumerate}







\chapter{Algorithmes de tri}

\section{Test de croissance}

\subsection{Niveau} À partir de la seconde.

\subsection{Prérequis} Test-Boucles-Procédures-Listes.

\subsection{Principe} On entre  une liste et on  voudrait créer un algorithme  qui permette de
tester si cette liste est croissante.
\subsection{Intérêt} Outre l'aspect technique informatique, on
  travaille sur la notion de \emph{négation}. On doit comprendre que a négation de l'assertion
  \og  la suite  est croissante\fg{}  est \og  il existe  au  moins deux
  termes consécutifs classés dans l'ordre décroissant\fg{}.
\subsection{Algorithme}   Voici   un  exemple   en   utilisant  une   boucle
  \texttt{pour} et on sort de la boucle dès qu'un contre-exemple apparaît. 

\begin{algorithm}[H]
\caption{test de croissance}
\Entree{
Saisir L : liste\;
}\;
\Ini{T $\leftarrow$ "croissante" \tcp{La  liste est croissante tant qu'on n'a
  pas prouvé le contraire}\;}

\Deb{\;



\Pour{k de 0 jusque taille(L)-2}{
   \Si{L[k]>L[k+1]}{
        T $\leftarrow$ "pas croissante" \tcp{un contre-exemple suffit}\;
        \Retour{T} \tcp{On sort tout de suite de la boucle}\; 
    }\;
}\;
 \Retour{T}\;
}
\end{algorithm}

\subsection{Traduction XCAS} 

On utilise d'abord le code en français.


\begin{lstlisting}[caption={croissance d'une liste en impératif}]
test(L):={
local k,T;
T:="croissante";
pour k de 0 jusque size(L)-2 do
      si L[k]>L[k+1] alors T:= "pas croissante"; retourne(T); fsi;
fpour;
retourne(T);
}:;
  \end{lstlisting}


La même chose avec un langage plus standard~:

\begin{lstlisting}[caption={croissance d'une liste en impératif (VO)}]
test(L):={
local k,T;
T:="croissante";
for(k:=0;k<size(L)-1;k:=k+1){
      if(L[k]>L[k+1]){T:= "pas croissante"; return(T)};
};
return(T);
}:;
\end{lstlisting}


\subsection{Version récursive avec CAML}

\caml

\begin{lstlisting}[caption={croissance d'une liste en récursif (1)}]

# let rec contient_terme_avec_successeur_inferieur (lx)
        =
        if lx = []
         then false
         else if List.tl (lx) = []
               then false
               else if List.hd (lx) > List.hd (List.tl (lx))
                     then true
                     else contient_terme_avec_successeur_inferieur (List.tl (lx))

# let est_sans_decroissance (lx)
        =
        not (contient_terme_avec_successeur_inferieur (lx))

\end{lstlisting}

(Merci à René THORAVAL)


ou bien sans recours au module \og \texttt{List}\fg{}


\begin{lstlisting}[caption={croissance d'une liste en récursif (2)}]
let rec croissante = function
  | [] -> true
  | x::[] -> true
  | x::y::queue -> if x > y
                     then false
                     else croissante (y::queue);;
\end{lstlisting}



alors on obtient~:


\begin{lstlisting}
# croissante([1;2;3;4;5;6;4;7]);;
- : bool = false
# croissante([1;2;3;4;5;6;7]);;
- : bool = true
\end{lstlisting}










\xc

\section{Tri à bulles}


\subsection{Niveau} À partir de la seconde.

\subsection{Prérequis} Test-Boucles-Procédures-Listes.


\subsection{Principe}  On veut trier  une liste  de nombre  par ordre
croissant.


\subsection{Intérêt}          Comprendre          le         principe
d'incrémentation.    Comprendre    le    facteur   chronologique    d'un
algorithme~:~les affectations ne doivent  pas être faites dans n'importe
quel ordre. Découvrir l'\og astuce\fg{}
informatique consistant à introduire une variable temporaire. Étoffer sa
culture scientifique en découvrant les algorithmes de tri.


\subsection{Algorithme impératif}

\begin{algorithm}[H]
\caption{tri à bulles}
\Entree{
Saisir L : liste\;
}



\Ini{LT $\leftarrow$ L\;
compteur $\leftarrow$ 0\;
}
\Deb{
  \Pour{k de 0 à taille(L) avec un pas de 1}{
     \Si{LT[k]>LT[k+1]}{
         temp $\leftarrow$ LT[k]\;
         LT[k] $\leftarrow$ LT[k+1]\;
         LT[k+1] $\leftarrow$ temp\;
         k $\leftarrow$ -1 \tcp{Pour revenir à zéro après incrémentation}\;
         compteur $\leftarrow$ compteur+1\;
}
}
\Retour{LT,compteur}
}
\end{algorithm}

\subsection{Version impérative avec XCAS}

En français~:

\begin{lstlisting}[caption={tri à bulle}]
bulle(L):={
LT:=L;
compteur:=0; // pour compter les permutations
pour k de 0 jusque size(LT)-1 faire
  si LT[k]>LT[k+1] alors
       temp:=LT[k]; // on stocke L[k]
       LT[k]:=LT[k+1]; // le deuxieme devient premier
       LT[k+1]:=temp; // et vice versa
       k:=-1; // on recommence au debut
       compteur:=compteur+1; // une permutation de plus
  fsi;
fpour;

retourne(LT,compteur);
}:;
\end{lstlisting}


Voici le  même algorithme en anglais  et avec la  liste des permutations
effectuées~:




\begin{lstlisting}[caption={tri à bulle (VO)}]
bulle(L):={
LT:=L;
compteur:=0;
T:=LT; // la liste sans permutation
for(k:=0;k<size(LT)-1;k:=k+1){
  if(LT[k]>LT[k+1]){
       temp:=LT[k];
       LT[k]:=LT[k+1];
       LT[k+1]:=temp;      
       k:=-1;
       compteur:=compteur+1;
       T:=T,LT; // on rajoute la permutation effectuee dans la liste
  }
}
return([T]); // une liste de listes est un tableau (une matrice)
}:;
\end{lstlisting}


Ce qui  permet de  visualiser les permutations  permettant de  passer de
[4,3,2,1] à [1,2,3,4].

\begin{lstlisting}
bulle([4,3,2,1])
\end{lstlisting}

\[\left[\begin{array}{cccc}
4 & 3 & 2 & 1 \\
3 & 4 & 2 & 1 \\
3 & 2 & 4 & 1 \\
2 & 3 & 4 & 1 \\
2 & 3 & 1 & 4 \\
2 & 1 & 3 & 4 \\
1 & 2 & 3 & 4
\end{array}\right] \]


\begin{figure}[!h]
  \begin{Idee}{Commandes XCAS}
    Des  algorithmes  beaucoup  plus  efficaces sont  déjà  implémentés  dans
    XCAS~:~il    s'agit    des    commandes   \texttt{sort(liste)}    et
    \texttt{SortA(liste)}   qui  trient   dans   l'ordre  croissant   et
    \texttt{SortD(liste)} qui trie dans l'ordre décroissant.

En fait, \texttt{sort()}  est beaucoup plus puissant car  on peut mettre
en deuxième  argument une  fonction de tri  (qui doit  remplir certaines
propriétés).

    \end{Idee}
  \end{figure}




\subsection{Version récursive avec CAML}


\caml

Nous allons  d'abord créer  une fonction qui  extrait le  k-eme opérande
d'une liste~:


\begin{lstlisting}[caption={k-eme opérande d'une liste avec CAML}]
# exception Liste_Vide;;

# let rec op = function
  | (0,x::liste) -> x
  | (k,x::liste) -> op(k-1,liste)
  | (_,[]) -> raise Liste_Vide;;
\end{lstlisting}


Par exemple~:

\begin{lstlisting}
# op(2,[0;10;20;30;40;50]);;
- : int = 20
\end{lstlisting}


On crée ensuite une fonction qui calcule la longueur d'une liste~:

\begin{lstlisting}[caption={longueur d'une liste avec CAML}]
# let rec longueur = function
  | [] -> 0
  | _::queue -> 1+longueur(queue);;
\end{lstlisting}

Puis une fonction qui concatène deux listes~:

\begin{lstlisting}[caption={concaténation de deux listes}]
# let rec concate = function
  | [],liste2 -> liste2
  | (tete1::queue1),liste2 -> tete1::(concate(queue1,liste2));;
\end{lstlisting}


On crée une fonction qui  extrait une sous-liste en indiquant le premier
et le dernier opérande~:

\begin{lstlisting}[caption={extraction d'une sous-liste avec CAML}]
# let rec extrait(liste,debut,fin) =
      if debut=fin then [op(fin,liste)]
      else concate([op(debut,liste)],extrait(liste,debut+1,fin));;
\end{lstlisting}

Par exemple~:

\begin{lstlisting}
# extrait([0;1;2;3;4;5;6;7],2,6);;
- : int list = [2; 3; 4; 5; 6]
\end{lstlisting}


Ensuite, on crée une fonction qui échange deux opérandes successifs~:

\begin{lstlisting}[caption={échange de 2 opérandes successifs avec CAML}]
# let echange(liste,k)=
  if k=0 
  then concate([op(1,liste)],concate([op(0,liste)],extrait(liste,2,longueur(liste)-1)))
  else if k=longueur(liste)-2 
       then concate(concate(extrait(liste,0,k-1),[op(k+1,liste)]),[op(k,liste)])
       else concate(concate(extrait(liste,0,k-1),[op(k+1,liste)]),concate([op(k,liste)],extrait(liste,k+2,longueur(liste)-1)));;
\end{lstlisting}

Il ne reste plus qu'à buller~:


\begin{lstlisting}[caption={tri à bulle avec CAML}]
# let rec bulle(liste,k)=
    if k >= longueur(liste)-1 then liste
    else if op(k,liste) > op(k+1,liste) then bulle(echange(liste,k),0)
         else bulle(liste,k+1);;
\end{lstlisting}


Et alors~:

\begin{lstlisting}
# bulle([4;3;2;1],0);;
- : int list = [1; 2; 3; 4]  
\end{lstlisting}








\section{Tri par insertion}

C'est le plus  naturel~:~dans une collection déjà classée,  on insère un
nouvel élément à sa place. C'est un algorithme naturellement récursif...


\subsection{Avec CAML}

D'abord on apprend comment insérer un nouvel élément dans une liste~:

\caml
\begin{lstlisting}[caption={tri par insertion}]
# let rec insere element = function
   | [] -> [element]
   | tete::queue -> if element <= tete
                then element::tete::queue 
                else tete::(insere element queue);;
\end{lstlisting}


Par exemple, pour  insérer $7$ dans $ [1;  2; 4; 5; 7; 9;  13]$ (qui est
déjà classée...)~:

\begin{lstlisting}
# insere 7 [1;2;4;5;9;13];;
- : int list = [1; 2; 4; 5; 7; 9; 13]
\end{lstlisting}



Quand on sait insérer, on prend les  éléments 1 par 1 dans la liste et on
les insère au reste~:

\begin{lstlisting}
# let rec tri_insertion = function
   |  [] -> []
   | tete::queue -> insere tete (tri_insertion queue);;
\end{lstlisting}

\xc

\subsection{Avec XCAS}

\begin{lstlisting}[caption={tri par insertion (XCAS)}]
insere(element,liste):={
if(liste==[])
  then{[element]}
  else{if(element<=head(liste))
          then{prepend(liste,element)}
          else{prepend(insere(element,tail(liste)),head(liste))}
      }
}:;
\end{lstlisting}


Puis~:


\begin{lstlisting}
tri_insertion(liste):={
if(liste==[])
   then{[]}
   else{insere(head(liste),tri_insertion(tail(liste)))}
}:;
\end{lstlisting}





\section{Tri rapide}


\subsection{Principe}


On choisit un  nombre de la liste (le pivot) et  on permute les éléments
pour avoir les  plus petits que le  pivot à gauche et les  plus grands à
droite   et   on   recommence   sur  chacune   des   sous-listes~:~c'est
très...récursif~!



\subsection{Algorithme récursif avec CAML}
\caml

Une première fonction qui met les plus petits que le pivot à gauche et
les autres à droite~:

\begin{lstlisting}[caption={partition d'une liste en  récursif}]
# let rec partition n = function
  | [] -> []
  | tete::queue -> if tete<= n 
                      then tete::(partition n queue)
                      else (partition n queue)@[tete];;    
\end{lstlisting}

On sépare les petits et les grands dans deux listes à partir d'une liste
\og partitionnée\fg{}~:

\begin{lstlisting}[caption={partition d'une liste en récursif (suite)}]
# let rec grand n = function
          | [] -> []
	  | tete::queue -> if tete > n  then tete::queue
	                                else grand n queue;; 
     
# let rec petit n = function
          | [] -> []
	  | tete::queue -> if tete > n  then []
	                                else tete::(petit n queue);; 
      
\end{lstlisting}


On résume~:

\begin{lstlisting}
# let grande_partition n liste = grand n (partition n liste);;

# let petite_partition n liste = petit n (partition n liste);;
\end{lstlisting}


Par exemple~:

\begin{lstlisting}
# grand_partition 5 [5;2;45;7;4;5;8;2;1;5;3;4;5;7;9;9;6;5;3;8;2;4;5;2];;
- : int list = [8; 6; 9; 9; 7; 8; 7; 45]
# petite_partition 5 [5;2;45;7;4;5;8;2;1;5;3;4;5;7;9;9;6;5;3;8;2;4;5;2];;
- : int list = [5; 2; 4; 5; 2; 1; 5; 3; 4; 5; 5; 3; 2; 4; 5; 2]
\end{lstlisting}


et pour finir, le tri rapide lui-même~:

\begin{lstlisting}[caption={tri rapide en récursif}]
#  let rec rapide = function
    | [] -> []
    | pivot::reste -> rapide (petite_partition pivot reste) @ [pivot] @ rapide (grande_partition pivot  reste);;
\end{lstlisting}


alors~:

\begin{lstlisting}
# rapide [5;2;45;7;4;5;8;2;1;5;3;4;5;7;9;9;6;5;3;8;2;4;5;2];;
- : int list =
[1; 2; 2; 2; 2; 3; 3; 4; 4; 4; 5; 5; 5; 5; 5; 5; 6; 7; 7; 8; 8; 9; 9; 45]
\end{lstlisting}


Trop fortement mathématique !!...

\xc








\chapter{Cryptographie}


\section{Codage de César}

Le codage de César, on connaît.  On va créer un algorithme qui prend une
chaîne de caractère et une clé de \og décalage\fg{} en argument.

\subsection{En récursif avec CAML}


La  commande \verb+int_of_char+  renvoie  le code  ASCII d'un  caractère
(non accentué~:~A comme \emph{american}...).

Il y a 95 caractères qui commencent  à 32 et finissent à 126 (les autres
codes  correspondent  à  des   touches  d'action  comme  le  \og  retour
chariot\fg{}).

Nous allons donc ajouter la clé  au code des caractère modulo 95 mais il
faudra avant enlever  32 puis le rajouter à la  fin pour travailler avec
des caractères et non pas des actions.

Travailler  avec des  chaînes de  caractères est  moins pratique  que la
manipulation des listes. Nous  pouvons créer une fonction \og queue\fg{}
qui donne la chaîne de caractère privée de sa \og tête\fg{} et la donner
toute faite aux  élèves car elle n'est pas  intéressante à construire en
elle-même~:

\caml

\begin{lstlisting}[caption={queue d'un chaîne}]
# let queue(chaine) = String.sub chaine 1 (String.length(chaine)-1);;
\end{lstlisting}

On  utilise  \verb+String.sub chaine  debut  longueur+  qui remplace  la
chaîne  \verb+chaine+  par la  sous-chaîne  extraite  à  partir du  rang
\verb+debut+ et de longueur \verb+longueur+.


Ensuite, on a besoin de transformer le caractère (type \verb+char+) renvoyé par
\verb+char_of_int+  pour   en  faire  une  chaîne   de  caractère  (type
\verb+string+).  On utilise  \verb+String.make  longueur caractere+  qui
fabrique  une chaine  de longueur  \verb+longueur+ remplie  du caractère
\verb+caractere+.

Pour notre situation, cela donne~:


\begin{lstlisting}[caption={codage numérique d'une chaîne}]
# let code(car,cle) = 
   String.make 1 (char_of_int(((int_of_char(car)-32+cle) mod 95)+32));;
\end{lstlisting}


Enfin, voici  le programme principal. On utilise  \verb+^+ qui concatène
des chaînes  et \verb+mot.[0]+ qui renvoie  le caractère numéro  0 de la
chaîne \verb+mot+~:

\begin{lstlisting}[caption={codage de César en récursif}]
# let rec cesar(mot,cle) =
   if mot="" then ""
   else  (code(mot.[0],cle))^cesar(queue(mot),cle);;
\end{lstlisting}


On code avec la clé $3$~:

\begin{lstlisting}
# cesar("Essayons de coder cette phrase de plus 8 mots !",3);;
- : string = "Hvvd|rqv#gh#frghu#fhwwh#skudvh#gh#soxv#;#prwv#$"
$
\end{lstlisting}


On décode avec la clé $-3$~:

\begin{lstlisting}
# cesar("Hvvd|rqv#gh#frghu#fhwwh#skudvh#gh#soxv#;#prwv#$",-3);;
- : string = "Essayons de coder cette phrase de plus 8 mots !"
$
\end{lstlisting}




\subsection{En impératif avec XCAS}

Voici le code proposé par Bernard Parisse dans l'aide de XCAS~:


\xc
\begin{lstlisting}[caption={codage de César en impératif}]
code:= (c)->{ return(asc(c)-32) }:;

decode:= (k)->{return(char(k+32)) }:;

jules_cesar:= (message,cle)-> 
{ local s,j,messcode; 
  s:=size(message);  
  messcode:="";  
  for (j:=0;j<s;j:=j+1) { 
      messcode:=append(messcode,decode(irem(cle+code(message[j]),95)));  
    };  
  return(messcode);  
}:;
\end{lstlisting}



\section{RSA}

Nos  amis   Ronald  \textbf{R}ivest,  Adi   \textbf{S}hamir  et  Leonard
\textbf{A}dleman  mirent au  point en  1977 un  système de  codage alors
qu'ils essayaient au départ de montrer que ce qu'ils allaient développer
étaient une impossibilité logique :  aah, la beauté de la recherche...Et
savez-vous quel est la base du système~?... le
petit théorème  de Fermat,  si cher  au programme de  spé maths  en TS~!
Mais replaçons dans son contexte les
résultats  de  R, S  et  A.  Jusqu'il y  a  une  trentaine d'années,  la
cryptographie était l'apanage des  militaires et des diplomates. Depuis,
les  banquiers,  les  mega  business  men et  women,  les  consommateurs
internautes, les barons  de la drogue et j'en passe ont  de plus en plus
recours  aux messages  codés. Oui,  et alors  ? Le  problème,  c'est que
jusqu'ici, l'envoyeur et le destinataire partageaient une même clé secrète
qu'il fallait faire voyager à l'insu  de tous : les états et l'armée ont
la valise diplomatique, mais les autres~?

C'est ici que Whitfield Diffie  et Martin Hellman apparaissent avec leur
idée  de principe qu'on  peut résumer  ainsi :  votre amie  Josette veut
recevoir de  vous une  lettre d'amour  mais elle a  peur que  le facteur
l'intercepte et la  lise. Elle fabrique donc dans  son petit atelier une
clé et un cadenas. Elle vous envoie le cadenas, ouvert mais sans la clé,
par  la poste,  donc  à la  merci du  facteur  : le  cadenas est  appelé
\textit{clé publique}. Vous recevez le cadenas et l'utilisez pour fermer
une boîte contenant  votre lettre : le facteur ne  peut pas l'ouvrir car
il n'a pas la clé. Josette reçoit donc la boîte fermée : elle utilise sa
clé, qu'elle seule possède, pour ouvrir  la boîte et se pâmer devant vos
élans epistolaires.

\sm

En  termes plus  mathématiques, cela  donne :  je fabrique  une fonction
$\pi$ définie sur $\bbn$ qui possède une réciproque $\sigma$. On suppose
qu'on peut fabriquer de telles fonctions mais que si l'on ne connaît que
$\pi$, il est (quasiment)  impossible de retrouver $\sigma$. La fonction
$\pi$  est  donc  la  clé  publique  :  vous  envoyez  $\pi$(message)  à
Josette.     Celle-ci     calcule    $\sigma\bigl(\pi($message$)\bigr)=$
message. Josette est  la seule à pouvoir décoder  car elle seule connaît
$\sigma$.

Tout  ceci  était   très  beau  en  théorie,  mais   Diffie  et  Hellman
n'arrivèrent pas à proposer  de telles fonctions. Mais voici qu'arrivent
Ronald, Adi et Leonard...

\subsection{En impératif avec XCAS}

Nous  aurons  tout  d'abord   besoin  d'un  programme  \texttt{code}  qui
transforme  un message  écrit en  majuscule en  un nombre  entier  et un
programme \texttt{decode} qui effectuera  la démarche inverse. 

On choisit  les majuscules pour être  sûrs d'avoir des codes  ASCII de 2
chiffres pour pouvoir décoder...


\begin{lstlisting}[caption={codage numérique d'une chaîne en impératif}]
code(c):={
local L,C,k;
L:=asc(c);
C:="";
 for(k:=0;k<size(L);k:=k+1){
    C:=cat(C,string(L[k]));
 }
return(expr(C))
}:;
\end{lstlisting}

On a adapté un peu ce qui a  été fait pour César mais cette fois on veut
transformer la  liste des codes en  un nombre entier  en concaténant les
chiffres qui la composent.

La   commande  \verb+string(expression)+  transforme   n'importe  quelle
\verb+expression+ en une chaîne de caractère.

La commande \verb+cat(chaîne,caractère)+ concatène \verb+caractère+ à
droite de la \verb+chaîne+.


La commande \verb+expr(chaîne)+ est la réciproque de \verb+string+.


\smallskip

Passons  à \verb+decode+  qui  transforme  un entier  en  une chaîne  de
caractère~:

\begin{lstlisting}[caption={décodage d'un entier en chaîne de caractères}]
decode(n):={
local L,C,k;
L:=string(n);
C:="";
for(k:=0;k<size(L)-1;k:=k+2){
  C:=cat(C,char(expr(cat(L[k],L[k+1]))))
}
return(C)
}:;
\end{lstlisting}



Par exemple~:


\begin{lstlisting}
code("I LOVE YOU")
\end{lstlisting}

\reponse{73327679866932897985}


Vérifiez que \verb+decode+ décode bien~:

\begin{lstlisting}
decode(code("I LOVE YOU"))
\end{lstlisting}



\bigskip

Ceci étant dit, je vais vous montrer comment quelqu'un peut m'envoyer un
message  crypté en  utilisant le  protocole  RSA, que  personne ne  peut
comprendre sauf moi, puis comment je vais décrypter ce message.

Avant  de  m'envoyer  un  message,  on  doit  connaître  ma  \textit{clé
publique}, connue de tous et constituée d'un couple de nombres $(n,e)$.

Et  avant  de  connaître  cette  clé,  il faut  que  je  la  fabrique  -
secrètement - de la manière suivante~:



\begin{itemize}
\item je  commence par  fabriquer  un  nombre  premier quelconque  mais
suffisamment  grand. J'utilise \verb+nextprime(n)+  qui renvoie  le plus
petit  entier premier  (ou  supposé tel...)  supérieur  à \verb+n+.  Par
exemple~: 

\begin{lstlisting}
p:=nextprime(857452321345678945615348675153785313513545313135435153):;
\end{lstlisting}



\item puis un autre

\begin{lstlisting}
q:=nextprime(9574138786465743137483136984548364156838461638468343648634):;
\end{lstlisting}


Ces deux nombres ne sont connus que de moi !



\item je forme le produit de ces deux nombres


\begin{lstlisting}
n:=p*q:;
\end{lstlisting}

Ce nombre \verb+n+ est mon module public. Il reste à former le nombre \verb+pui+ qui
est  ma puissance  de cryptage  publique. Là  encore, cela  se  fait par
étapes.

\item je  commence par former le  nombre \verb+phi_n+ (tiens,  tiens...) de la
manière suivante~:

\begin{lstlisting}
phi_n:=(p-1)*(q-1):;
\end{lstlisting}



\item c'est  là qu'il  faut jouer avec  la chance  : je dois  choisir un
nombre \verb+pui+ premier avec \verb+phi_n+.  En pratique, je choisis un grand nombre
premier au hasard~:

\begin{lstlisting}
pui:=nextprime(4568531538443156358743168741353):;
\end{lstlisting}


Je vérifions quand même que \verb+pui+ et \verb+phi_n+ sont premiers entre eux~:

\begin{lstlisting}
gcd(pui,phi_n);
\end{lstlisting}


\reponse{1}

Ouf!...Au fait, pouvais-je en être sûr~?...


\item il  me reste à  calculer ma puissance  de décryptage secrète  : je
l'obtiens en  cherchant l'inverse  de \verb+pui+ modulo  \verb+phi_n+, c'est-à-dire
en déterminant  un coefficient de Bézout grâce  à l'algorithme d'Euclide
étendu.

Le  problème,  c'est que  nos  nombres sont  un  peu  grands pour  faire
l'algorithme à la main, mais...heureusement,  il y a XCAS. Il existe en
effet une  fonction \verb+igcdex(x,y)+ qui  renvoie le PGCD de  $x$ et
$y$, ainsi que des coefficients de  Bézout $u$ et $v$ qui vérifient donc
$ux+vy=x\wedge y$~:



\begin{lstlisting}
igcdex(pui,phi_n)
\end{lstlisting}

Ceci  veut dire  que $u$\verb+pui+ $+v$\verb+phi_n+$=1$,  avec $u$  le  premier nombre
renvoyé  par  XCAS  et   $v$  le  deuxième.  Ainsi  $u$\verb+pui+$\equiv
1$[\verb+phi_n+] mais
$u$  n'est  pas  forcément  l'inverse  de  \verb+pui+  modulo  \verb+phi_n+  car  il
n'appartient      pas      forcément      à     l'intervalle      entier
$[\![0,$\verb+phi_n+$-1]\!]$.  Il suffit  de calculer  sa  classe modulo
\verb+phi_n+ c'est-à-dire le reste de sa division par \verb+phi_n+~:


\begin{lstlisting}
d:=irem(ans()[0],phi_n):;
\end{lstlisting}

\end{itemize}



Je  suis  maintenant prêt  à  recevoir  des  messages cryptés  selon  le
protocole  RSA  et vous  êtes  prêt(e) à  m'en  envoyer  car j'ai  rendu
publique ma clé \verb+(pui,n)+.


\begin{itemize}
\item d'abord vous \og numérisez\fg{} votre message.

\begin{lstlisting}
text_num:=code("ESSAYE DONC DE DECRYPTER CE MESSAGE"):;
\end{lstlisting}

\item  comme nous  allons  calculer  modulo \verb+n+,  il  faut vérifier  que
\verb+text_num+   est  plus   petit  que   \verb+n+,  en   utilisant   par  exemple
\texttt{length}\footnote{Et qu'est-ce qu'on  peut faire si text\_num est
trop grand~?}.

\begin{lstlisting}
text_num<n
\end{lstlisting}

\item ensuite,  vous calculez ce  nombre puissance \verb+pui+ et  vous regardez
quelle est sa classe  modulo \verb+n+. On utilise \verb+powermod(a,m,p)+
qui calcule la classe de $a^m$ modulo $p$~:

\begin{lstlisting}
crypte:=powermod(text_num,pui,n):;
\end{lstlisting}

\item je reçois ce message et je  le décrypte grâce à ma clé secrète $d$
que  je  suis  le seul  à  connaître  dans  tout l'univers.  Je  calcule
\verb+crypte+\textsuperscript{\texttt{d}}[\verb+n+]~:

\begin{lstlisting}
decrypte:=powermod(crypte,d,n):;
\end{lstlisting}


\item il ne  me reste plus qu'à retrouver mon texte  original grâce à la
procédure \verb+decode+~:

\begin{lstlisting}
decode(decrypte)
\end{lstlisting}

\reponse{ESSAYE DONC DE DECRYPTER CE MESSAGE}

Ça marche~!!
\end{itemize}

Il reste à prouver  notre méthode (indicateur d'Euler, théorème d'Euler,
etc.), à voir si on peut casser le code.

Au fait, on a failli parler du RSA en classe de Seconde...

\section{Cryptosystème du sac à dos}\label{sac}


\chapter{Graphes}

\chapter{Suites définies par une relation de récurrence}

\section{Suite de Fibonacci}

Léonard  de Pise, fils  de Bonacci,  s'est intéressé  en 1202  au fameux
problème des  lapins~:~un couple donne  naissance, à partir  du deuxième
mois à un  couple chaque mois, les nouveaux couples  suivant la même loi
de reproduction~; combien y  aura-t-il de lapins (supposés immortels...)
au bout de $n$ mois~?

Il s'agit donc d'étudier la suite $(F_n)$ définie par~:

\[F_0=F_1=1\qquad F_{n+2}=F_n+F_{n+1}\]

\subsection{VersionS récursives}



On peut écrire la (double !) récursion directement~:

\caml

\begin{lstlisting}[caption={suite de Fibonnacci en récursif (1)}]
# let rec fibo(n)=
  if n<2
       then 1
       else fibo(n-1)+fibo(n-2);;
\end{lstlisting}

\xc

\begin{lstlisting}[caption={suite de Fibonnacci en récursif (1) avec XCAS}]
fibo(n):={
if(n<2)
   then{1}
   else{fibo(n-1)+fibo(n-2)}  
}:;
\end{lstlisting}

Très facile....mais peu efficace car il faut une vingtaine de secondes à
XCAS pour calculer \verb+fibo(30)+ (une seconde avec CAML).

En  effet, la  récursion  est double  et  nécessite une  pile bien  plus
importante.

Mieux vaut recourir  à une fonction auxiliaire pour  avoir une récursion
terminale~:

\caml

\begin{lstlisting}[caption={suite de Fibonnacci avec une récursion terminale}]
# let fibr(n)=
    let rec fkplus2(n,fk,fkplus1)=
          if n<2 then fkplus1
          else fkplus2(n-1,fkplus1,fk+.fkplus1)
    in fkplus2(n,1.,1.);;
\end{lstlisting}

Nous avons de plus choisi  de travailler avec des flottants pour pouvoir
parler ensuite du Nombre d'Or.


\medskip

Voici  un  autre moyen  utilisant  l'itération  d'une  fonction de  deux
variables.


\begin{lstlisting}[caption={itération polymorphe d'une fonction}]
# let rec iter n f x =
     if n=0 then x
     else f(iter (n-1) f x);;
\end{lstlisting}


On crée une fonction qui renvoie la première composante d'un couple~:


\begin{lstlisting}[caption={}]
# let projx (x,y)=x;;
\end{lstlisting}




Enfin,    sachant    que    $(u_{n+2},u_{n+1}=f(u_{n+1},f(u_n))$    avec
$f(x,y)=(x+y,x)$ et $(u_1,u_0)=(1,0)$ définit la suite de Fibonnacci, on
obtient~:

\begin{lstlisting}[caption={suite de Fibonnacci : troisième version}]
# let fib3(n)=
      projx( iter n (fun(x,y)->(x+.y,x)) (1.,0.) );;
\end{lstlisting}

Alors~:

\begin{lstlisting}[caption={}]
# fib3(1000);;
- : float = 7.03303677114227653e+208
\end{lstlisting}







\subsection{Version impérative}



\xc
\begin{lstlisting}[caption={suite de Fibonnacci en impératif}]
fibi(n):={
local fk,fkplus1,k;
 if(n<2)
  then{return(1)}
  else{
      fk:=1;
      fkplus1:=1;
        for(k:=1;k<n;k:=k+1){
          fkplus1:=fk+fkplus1;
          fk:=fkplus1-fk;
         }
      return(fkplus1)
  }
}:;
\end{lstlisting}


Alors par exemple~:


\begin{lstlisting}
seq(fibi(j),j=0..10)
\end{lstlisting}

donne les onze premiers termes de la suite~:


\reponse{1,1,2,3,5,8,13,21,34,55,89}



\subsection{Suite des quotients}

L'étude  de  la  suite  $q_n=\frac{F_{n+1}}{F_n}$ permet  d'obtenir  une
approximation du nombre d'or $\varphi$. En effet~:

\[q_n=\frac{F_{n+1}}{F_n}=\frac{F_n+F_{n-1}}{F_n}=1+\frac{1}{q_{n-1}}\]

Après  avoir montré  que la  suite $(q_n)$  converge, sa  limite vérifie
$\ell=1+\frac{1}{\ell}$ et donc $\ell=\varphi$.

Version récursive avec CAML~:

\caml

\begin{lstlisting}[caption={quotients des termes d'une suite de Fibonnacci en récursif}]
# let rec nbdor(n)=
  if n=0
       then 1.
       else 1.+.1./.nbdor(n-1);;
\end{lstlisting}

Notez que la  récursion est terminale en utilisant  la nouvelle relation
de récurrence définissant $(q_n)$.  Pour avoir des approximations, il ne
faut pas oublier de travailler avec des flottants.

\xc

Version impérative avec XCAS~:

\begin{lstlisting}[caption={quotients des termes d'une suite de Fibonnacci en impératif (1)}]
nbdor(n):={
local fk,fkplus1,k,qk;
 if(n==0)then{return(1.0)}
 else{
  fk:=1.0;
  fkplus1:=1.0;
    for(k:=0;k<=n;k:=k+1){
      qk:=fkplus1/fk;
      fkplus1:=fk+fkplus1;
      fk:=fkplus1-fk;
      }
  return(qk)
 }
}:;
\end{lstlisting}

ou plus simplement~:

\begin{lstlisting}[caption={quotients des termes d'une suite de Fibonnacci en impératif (2)}]
nbdorbis(n):={
local k,qk;
qk:=1.0;
 if(n==0)then{return(qk)}
 else{
    for(k:=1;k<=n;k:=k+1){
      qk:=1+1/qk;
      }
  return(qk)
 }
}:;
\end{lstlisting}


\section{Suite de Syracuse}

On ne la présente plus....

Avec CAML, on  demande d'afficher tous les termes  avec une espace entre
chaque jusqu'à obtenir 1~:

\caml
\begin{lstlisting}[caption={suite de Syracuse en récursif}]
# let rec syracuse(n)=
     print_int(n);
     print_string(" ");
     if n>1 then syracuse(if n mod 2=0 then n/2 else 3*n+1);;
\end{lstlisting}

Pour $187\,514$~:

\begin{lstlisting}
# syracuse(187514);;
\end{lstlisting}

on obtient~:

\begin{lstlisting}
187514 93757 281272 140636 70318 35159 105478 52739 158218 79109 237328 118664 59332 29666 14833 44500 22250 11125 33376 16688 8344 4172 2086 1043 3130 1565 4696 2348 1174 587 1762 881 2644 1322 661 1984 992 496 248 124 62 31 94 47 142 71 214 107 322 161 484 242 121 364 182 91 274 137 412 206 103 310 155 466 233 700 350 175 526 263 790 395 1186 593 1780 890 445 1336 668 334 167 502 251 754 377 1132 566 283 850 425 1276 638 319 958 479 1438 719 2158 1079 3238 1619 4858 2429 7288 3644 1822 911 2734 1367 4102 2051 6154 3077 9232 4616 2308 1154 577 1732 866 433 1300 650 325 976 488 244 122 61 184 92 46 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1 - : unit = ()
\end{lstlisting}


Avec XCAS en impératif~:


\xc


\begin{lstlisting}[caption={suite de Syracuse en impératif}]
syracuse(n):={
S:=n;
N:=n;
while(N>1){
  N:=if(irem(N,2)==0)then{N/2}else{3*N+1}
  S:=S,N;
}
return(S)
}:;
\end{lstlisting}


\section{Encore des approximations de $\pi$}


\subsection{Suite de \textsc{Viète}}

François \textsc{Viète} proposa au XVI\up{e} siècle une approximation de
$\pi$ qui revient en langage moderne à étudier la suite~:

\[u_0=\frac{1}{\sqrt{2}}\qquad u_n=\sqrt{\frac{1}{2}+\frac{1}{2}u_{n-1}}\]

Alors \[ \pi=\frac{2}{\prod\limits_{n=0}^{+\infty}u_n}\]



\caml

\begin{lstlisting}[caption={suite de Viète en récursif}]
# let rec viete(n)=
      if n=0 then 1./.sqrt(2.)
      else sqrt(0.5*.(1.+.viete(n-1)));;

# let rec produit_viete(n)=
      if n=0 then viete(0)
      else viete(n)*.produit_viete(n-1);;

# let pi_viete(n)=2./.produit_viete(n);;
\end{lstlisting}

Alors~:

\begin{lstlisting}
# pi_viete(20);;
- : float = 3.1415926535895
\end{lstlisting}


\subsubsection{En impératif avec XCAS}
\xc

\begin{lstlisting}[caption={suite de Viète en impératif}]
viete(n):={
local u,P,k;
u:=1/sqrt(2.);
P:=u;
for(k:=1;k<=n;k:=k+1){
u:=sqrt(0.5+0.5*u)
P:=P*u
}
return(2/P)
}:;
\end{lstlisting}



\subsection{\textsc{Euler} et la suite des inverses des carrés}


Chacun connaît la formule~:

\[\sum_{n=1}^{+\infty}\frac{1}{n^2}=\frac{\pi^2}{6}\]


\subsubsection{En récursif avec CAML}

\caml

\begin{lstlisting}[caption={suite des inverses des carrés en récursif}]
# let rec somme_euler(n)=
      if n=1 then 1.
      else 1./.(float_of_int(n))**2. +. somme_euler(n-1);;

# let pi_euler(n)=sqrt(6.*.somme_euler(n));;
\end{lstlisting}


La convergence n'est pas très rapide...

\begin{lstlisting}
# pi_euler(20000);;
- : float = 3.14154490793769403
\end{lstlisting}


\subsubsection{En impératif avec XCAS}
\xc

\begin{lstlisting}[caption={suite des inverses des carrés en impératif}]
pi_euler(n):={
local S,k;
S:=0.;
 for(k:=1;k<=n;k:=k+1){
 S:=S+1/k^2;
 }
return(sqrt(6*S))
}:;
\end{lstlisting}

\section{Suites logistiques}


\subsection{L'effet papillon}

Vers 1950, le météorologiste américain Edward \textsc{Lorenz} étudie la circulation atmosphérique. Reprenant
  les   travaux   des   mathématiciens   français   \textsc{Hadamard}   et   \textsc{Poincaré}   sur
  l'imprédictibilité des systèmes  simples. Même en modélisant l'atmosphère en  un système ayant une
  dizaine de  degrés de liberté, il montre  la sensibilité exponentielle par  rapport aux conditions
  initiales. Il illustre son propos en montrant que le battement d'aile d'un papillon en un point de
la Terre  est suffisant pour  déclencher deux semaines  plus tard une tornade  à l'autre bout  de la
planète. Au même moment, le  russe Vladimir \textsc{Arnold}, disciple de \textsc{Kolmogorov}, modélise
le  mouvement d'un  fluide parfait  comme celui  d'un point  sur une  «~hypersurface~»  de dimension
infinie.  Il part  lui aussi  de travaux  d'\textsc{Hadamard} sur  les trajectoires  d'une  bille sur
certaines surface~:~par exemple, si on lâche une bille sur un paraboloïde hyperbolique (une selle de
cheval), sa trajectoire va  dépendre énormément de sa position de départ,  à tel point qu'il s'avère
impossible de prévoir sa trajectoire au-delà d'un temps très court. \\
Bref,  l'effet papillon  envahit  les esprits  et nombres  de  disciplines pour  imposer une  vision
chaotique d'un monde complexe et imprédictible. 
C'est ce phénomène que nous allons observer et commenter aujourd'hui, non pas en étudiant le domaine
des turbulences atmosphériques «~physiquement~» hors de  notre portée, mais en explorant, de manière
très simplifiée, la
\emph{dynamique des populations}.\\
Nous évoquerons  en conclusion les  apports récents de  la \emph{mécanique statistique}  qui replace
dans leur contexte les travaux de \textsc{Lorenz} et \textsc{Arnold}.




\subsection{Le Zräjdz}

Comme vous le savez tous, le Zräjdz commun à ailette mouchetée est l'animal emblématique de la Syldavie. Aussi paisible que les
habitants de ce bucolique pays, le Zräjdz se nourrit exclusivement des baies du bleurtschzrn, arbre qui pousse en abondance dans les
verts sous-bois syldaves. Si l'on ne considérait que cette idéale situation, la population $u$ de Zräjdzs suivrait la loi suivante $$
u_{n+1}=R u_n$$ Cette relation traduit le fait que la population de l'année $n+1$ est proportionnelle à l'année $n$ : on applique à $u_n$
le taux de natalité et le taux de mortalité. Le coefficient $R$ résume ces proportions.

On prend $R=1,5$ et on suppose qu'il y avait \numprint{10000} couples de
Zräjdzs au départ de notre étude. On exprimera la population en centaine
de milliers d'individus.


La  suite étant  définie  par récurrence,  la  première idée  est de  la
définir de la même manière sur XCAS~:

\begin{lstlisting}
u(n):={
 si n=0 alors 0.2;
  sinon R*u(n-1);
 fsi;
}:;
\end{lstlisting}


On fixe R~:

\begin{lstlisting}
R:=1.5:
\end{lstlisting}

On demande par exemple les 15 premiers termes de la suite~:

\begin{lstlisting}
seq(u(k),k=0..15);
\end{lstlisting}


et on trace la représentation graphique associée~:

\begin{lstlisting}
nuage_points([seq([n,u(n)],n=0..15)]);
\end{lstlisting}



\section{Trop de Zräjdzs nuit aux Zräjdzs}

Il est assez aisé d'objecter au modèle précédent que l'évolution ne peut pas rester proportionnelle à la population de l'année
précédente~: au bout d'un moment la nourriture et  l'espace vital, par exemple, viennent à manquer. On peut alors modéliser l'évolution
de la population selon la loi $$u_{n+1}=R\,u_n(1-u_n)$$ 

\begin{enumerate}

\item Définissez $u(n)$ comme cela a été fait au paragraphe précédent et
  calculez les 25 premiers termes de la suite. On prendra encore $R=1,5$
  et $u_0=0,2$. 



  \begin{lstlisting}[caption={}]
u(n):={
 si n=0 alors 0.2;
  sinon R*u(n-1)*(1-u(n-1));
 fsi;
}:;    
  \end{lstlisting}


On préfèrera sur XCAS une procédure impérative~:

\begin{lstlisting}[caption={}]
u(n):={
 local u;
 u:=0.2;
 pour k de 1 jusque n faire
  u:=R*u*(1-u);
 fpour;
retourne(u)
}:;
\end{lstlisting}

\item Tracez également la graphique donnant la population en fonction de
  l'année. On observera le phénomène sur une cinquantaine d'années.

  \begin{lstlisting}[caption={}]
nuage_points([seq([n,u(n)],n=0..50)]);
  \end{lstlisting}


\item Observez maintenant ce qui se passe pour ces  graphiques quand on fait varier le coefficient R. On regardera en particulier les graphiques correspondant à  R=2,0; R=0,9; R=3,44; R=3,5; R=3, 544; R=3, 831874048.

\item Ce n'est pas tout! Regardons maintenant ce qui se passe pour une même valeur de R lorsqu'on fait varier de manière infime $u(0)$. On prendra par exemple $R=3,\,831874048$ et $u(0)$ successivement égal à $0,2$ puis à $0,20001$.


C'est l'illustration du fameux <<~effet papillon~>>: un battement d'aile de papillon à Rezé est susceptible de déclencher beaucoup plus tard une tornade au Texas. La très faible perturbation créée par le vol d'un papillon pourrait en principe faire varier les conditions initiales du système atmosphérique et engendrer plus tard un changement climatique en un endroit quelconque de notre planète.

\item  On peut  avoir une  vision plus  spectaculaire  avec l'habituelle
  représentation des suites définies par une relation de récurrence.

On rajoute un curseur pour faire varier R.

On ouvre une fenêtre de géométrie en tapant \Alt + \keystroke{G}.


\begin{lstlisting}[caption={}]
R:=element(0 .. 4,0.01) // R varie de 0 à 4 avec un pas de 0,01
f:=x->R*x*(1-x);
graphe_suite(f(x),0.75,2500) // 2500 termes représentés avec uo=0,75
\end{lstlisting}


Pour $R=3,28$~:




\begin{figure}
\begin{center}
  \includegraphics{kao0}
\end{center}
\end{figure}


Pour $R=3,85$~:



\begin{figure}
\begin{center}
  \includegraphics{kao1}
\end{center}
\end{figure}


Pour $R=3,86$~:


\begin{figure}
\begin{center}
  \includegraphics{kao2}
\end{center}
\end{figure}





\item   Ce  phénomène   est  mis   plus  clairement   en  évidence   par  un   \textbf{diagramme  de
    bifurcation}. Cette fois, le travail est inversé~:~je vous livre le programme et vous essayez de
  le commenter et de  découvrir à quoi correspond le graphique obtenu.  Qu'est-ce que représente r~?
  res~? ligne~? tmp~? 

\begin{lstlisting}
Feig(R,N):={
 local k,r,tmp,ligne;
 tmp:=floor(R*N);
//comme on avance de pas=1/N, il y aura R*N points tracés
 res:=[0$tmp];
//il y aura 20 points par ligne car on fait varier k de 100 à 120
 ligne:=[0$20];
 for (r:=0;r<R;r+=1/N){
   tmp:=0.2;
   // calcul de u100
   for (k:=0;k<100;k++){ 
     tmp:=r*tmp*(1-tmp);
   }
   // calcul des suivants et stockage
   for (k:=0;k<20;k++){
     ligne[k] := point(r,tmp);
     tmp:=r*tmp*(1-tmp);        }
   res[r*N] =< ligne;
 }
 return res;
}:; 
\end{lstlisting}

Ensuite, observez ce qui se passe pour $0\ie R<3$, $3\ie R<3,45$, $3,45\ie R<3,57$, $3,57\ie R\ie 4$.

\end{enumerate}




\begin{figure}
\begin{center}
  \includegraphics[width=0.7\linewidth]{feig}
\end{center}
\end{figure}





\section{Exposant de Lyapounov}

Pour  mesurer  la  sensibilité  d'un système  dynamique  aux  conditions
initiales, on  mesure l'exposant de \textsc{Lyapounov}  introduit par le
mathématicien russe  Alexandre \textsc{Lyapounov} à la  fin du XIX\up{e}
siècle.

On considère une suite définie par la relation $u_{n+1}=f(u_n)$.  Quelle est l'influence d'un
écart $e_0$ sur $u_0$ pour la suite des itérés~?

Après une itération,  l'écart absolu vérifie $|e_1|=|f(u_0+e_0)-f(u_0)|$
et                  l'écart                 relatif                 vaut
$\frac{|e_1|}{|e_0|}=\frac{|f(u_0+e_0)-f(u_0)|}{|e_0|}\approx    \left|f'(u_0)\right|$
pour $|e_0|$ suffisamment petit.


Après $n$ itérations, l'écart relatif vaut 

$$\frac{|e_n|}{|e_0|}=\frac{|e_1|}{|e_0|}\times
\frac{|e_2|}{|e_1|}\times\cdots\times \frac{|e_n|}{|e_{n-1}|}=\prod_{k=1}^n\left|f'(u_{k-1})\right|$$


Si un des écarts devient nul, notre étude est sans intérêt.
Comme effectuer un produit  est une opération coûteuse, informatiquement
parlant, nous allons pouvoir considérer le logarithme de ce produit.

Notre  problème est  de savoir  si les  écarts s'amplifient  et  donc le
produit est supérieur à  1, ou bien si le système est  stable et donc le
produit est inférieur à 1.

$$\prod_{k=1}^nf'(u_{k-1})<1\ssi                          \sum_{k=1}^n\ln
\left|f'(u_{k-1})\right|<0$$

Pour relativiser le rôle du choix de $n$, nous allons normer cette somme
en la divisant par $n$.


On définit alors l'exposant de \textsc{Lyapounov}~:


$$\lambda=\lin \frac{1}{n}\sum_{k=1}^n\ln\left|f'(u_{k-1})\right|$$



Écrivez  une procédure  \verb+lyapounov(u0,R,n)+  qui calcule  une
approximation  numérique de  l'exposant de  Lyapounov qui  dépend  de la
donnée de $u_0$, $R$ et le nombre $n$ d'itérations.


\emph{Solution :}

\begin{lstlisting}[caption={Exposant de Lyapounov}]
lyapounov(u0,R,n):={
local u,lyap,derivee,tmp,k;
u:=u0;
lyap:=0;
 pour k de 1 jusque n faire
   derivee:=evalf(R-2*R*u);
   si derivee==0 
      alors retourne(-infinity);
      sinon lyap:=lyap+ln(abs(derivee));
   fsi;
   u:=R*u*(1-u);
 fpour;
retourne(lyap/n)
}:;
\end{lstlisting}

Ensuite, vous l'utiliserez pour représenter l'exposant en fonction de R.

Par exemple, avec $u_0=0,45$ et 50 itérations~:

\begin{lstlisting}
ligne_polygonale([seq([r*0.001,lyapounov(0.45,r*0.001,50)],r=3000..4000)]);
\end{lstlisting}




\begin{center}
  \includegraphics[width=\linewidth]{lyap}
\end{center}

Comment interpréter ce graphique~?





\chapter{Quelques particularités de CAML...}


\caml


\section{Toutes sortes de fonctions}

Par exemple, la longueur d'une liste~:

\begin{lstlisting}[caption={longueur d'une liste}]
let rec longueur = function
        | [] -> 0
        | _::queue -> 1+longueur(queue);;
\end{lstlisting}


Par exemple~:


\begin{lstlisting}
# longueur(["machin";"truc"]);;
- : int = 2
\end{lstlisting}



Concaténation de 2 listes~:

\begin{lstlisting}[caption={concaténation de deux listes}]
let rec concate = function
        | [],liste2->liste2
        |(tete1::queue1),liste2->tete1::(concate(queue1,liste2));;
\end{lstlisting}

Alors~:

\begin{lstlisting}
# concate(["machin";"truc"],["bidule";"chose"]);;
- : string list = ["machin"; "truc"; "bidule"; "chose"]
\end{lstlisting}


Je ne m'en lasse pas....


Retournons une liste~:


\begin{lstlisting}[caption={retournement d'une liste}]
let rec retourne = function
       | [] -> []
       | tete::queue -> concate(retourne(queue),[tete]);;
\end{lstlisting}

Trop fun :

\begin{lstlisting}
# retourne([1;2;3;4;5]);;
- : int list = [5; 4; 3; 2; 1]
\end{lstlisting}

Appliquons une fonction aux éléments d'une liste~:


\begin{lstlisting}[caption={application d'une fonction aux éléments d'une liste}]
let rec applique f = function
        | [] -> []
        | tete::queue -> (f(tete))::(applique f queue);;
\end{lstlisting}


Et hop~:

\begin{lstlisting}
# applique (function x->x*x) [1;2;3;4;5];;
- : int list = [1; 4; 9; 16; 25]
\end{lstlisting}


\section{Fonctions d'ordre supérieur}

\subsection{Somme}



On peut  créer une fonction somme  qui calcule la somme  des $f(x)$ avec
$x$ un élément d'une certaine liste.


\begin{lstlisting}[caption={somme des images par une fonction des éléments d'une liste}]
let rec somme(f) = function
    | [] -> 0
    | x :: l -> f(x) + somme(f)(l);;
\end{lstlisting}


Par  exemple, on  peut l'utiliser  pour avoir  la somme  des  carrés des
éléments de la liste $[1;3;5;7]$~:


\begin{lstlisting}
# somme(function x->x*x)([1;3;5;7]);;
- : int = 84
\end{lstlisting}

Si on veut travailler avec des flottants, il faut arranger un peu~:

\begin{lstlisting}
# let rec somme_r(f) = function
    | [] -> 0.
    | x :: l -> f(x) +. somme_r(f)(l);;
\end{lstlisting}

Pour avoir  la somme des  inverses des carrés  des éléments de  la liste
$[1;3;5;7]$~:

\begin{lstlisting}
# somme_r(function x->1./.(x*.x))([1.;3.;5.;7.]);;
- : float = 1.17151927437641712
\end{lstlisting}


Pour avoir la somme de leurs sinus~:


\begin{lstlisting}
# somme_r(function x->sin(x))([1.;3.;5.;7.]);;
- : float = 0.680653316923414353
\end{lstlisting}



\subsection{Composée}

On définit une fonction composant deux fonctions~:

\begin{lstlisting}[caption={composée de deux fonctions}]
# let rond(f,g)=function x->f(g(x));;
\end{lstlisting}


Définissons la fonction \og carré\fg{}~:


\begin{lstlisting}[caption={fonction carré}]
# let carre=function x->x*x;;
\end{lstlisting}

Petit jeu : comment interprétez-vous le résultat suivant~?

\begin{lstlisting}
# rond(carre,somme(carre))([1;2;3;4;5]);;
- : int = 3025
\end{lstlisting}


Rigolo...

Continuons  à nous  amuser. Définissons  l'iterée de  la  composée d'une
fonction~:

\begin{lstlisting}[caption={itérée de la composée d'une fonction }]
# let rec iteree f n = 
    if n = 0 then function x -> x 
    else rond(f, (iteree f (n - 1)));;
\end{lstlisting}

On a  omis les parenthèses pour  les variables (ce qui  est courant sous
CAML) pour ne pas se perdre....


Par exemple, on calcule $\sin\circ\sin\circ\cdots\circ \sin(1)$~:

\begin{lstlisting}
# iteree sin 15 1.;;
- : float = 0.395376546988834565
\end{lstlisting}







\section{Dérivée formelle}

On va fabriquer assez simplement une machine à dériver formellement.


On créé  d'abord un type de  variable (en plus des  types existant comme
\verb+int+, \verb+float+, \verb+list+, etc.) qu'on appelle \verb+formel+ par exemple et
qui va faire la liste et définir les expressions formelles que l'on veut
dériver~:

\begin{lstlisting}[caption={dérivée formelle - les types de dérivations}]
# type formel =
    | Int of int 
    | Var of string
    | Add of formel * formel
    | Sous of formel*formel
    | Mul of formel * formel
    | Div of formel*formel
    | Ln of formel
    | Cos of formel
    | Sin of formel
    | Puis of int*formel
    | Rac of formel
    | Exp of formel;;
\end{lstlisting}


Par exemple,  Var (comme variable...)   sera de type  \verb+formel+ mais
prendra comme argument une chaîne de caractère (\verb+string+). On entrera
donc 
les variables à l'aide de guillemets.

De même, \verb+Add+ est de type \verb+formel*formel+, c'est-à-dire que c'est
un objet formel qui prend comme argument un couple d'objets formels.


\medskip

On définit  ensuite récursivement une  fonction \verb+deriv+ qui  va dériver
nos expressions selon des règles que nous allons établir~:

\begin{lstlisting}[caption={méthodes de dérivation formelle }]
# let rec deriv(f, x) =
    match f with
    | Var y when x=y -> Int 1
    | Int _ | Var _ -> Int 0
    | Add(f, g) -> Add(deriv(f, x), deriv(g, x))
    | Sous(f, g) -> Sous(deriv(f, x), deriv(g, x))
    | Mul(f, g) -> Add(Mul(f, deriv(g, x)), Mul(g, deriv(f, x)))
    | Div(f,g) -> Div(Sous(Mul(deriv(f,x),g),Mul(f,deriv(g,x))),Mul(g,g))
    | Ln(f) -> Div(deriv(f,x),f)
    | Cos(f) -> Mul(deriv(f,x),Mul(Sin(f), Int(-1)))
    | Sin(f) -> Mul(deriv(f,x),Cos(f))
    | Puis(n,f) -> Mul(deriv(f,x),Mul(Int(n),Puis(n-1,f)))
    | Rac(f) -> Mul(deriv(f,x),Div(Int(1),Mul(Int(2),Rac(f))))
    | Exp(f) -> Mul(deriv(f,x),Exp(f));;
\end{lstlisting}

Par exemple, quand la variable \verb+Var+ est en fait la \emph{variable}
au sens mathématique, sa dérivée  est 1. En effet, \verb+Var+ regroupe à
la  fois  la  variable  de  la  fonction  mathématique  mais  aussi  les
paramètres formels éventuels.


La ligne suivante dit que toute autre variable (donc paramètre) et toute
constante numérique entière (\verb+Int+) a pour dérivée 0.

Ensuite  on  explique comment  dériver  une  somme,  une différence,  un
cosinus, etc.


\medskip

Par exemple, dérivons $x\mapsto kx^2$.

On définit deux variables $k$ et $x$~:

\begin{lstlisting}
# let x , k = Var "x", Var "k";;
\end{lstlisting}


Puis on demande la dérivée~:

\begin{lstlisting}
# deriv(Mul(k,Puis(2,x)),"x");;
\end{lstlisting}

On obtient~:

\begin{lstlisting}
- : formel =
Add (Mul (Var "k", Mul (Int 1, Mul (Int 2, Puis (1, Var "x")))),
 Mul (Puis (2, Var "x"), Int 0))
\end{lstlisting}

qu'il reste à \og déchiffrer\fg{}...

\[k\times 1\times 2\times x^1+ x^2\times 0 =2kx\]

Pour $\ln \left(\frac{1}{x}\right)$~:

\begin{lstlisting}
# deriv(Ln(Div(Int(1),x)),"x");;
\end{lstlisting}


On obtient~:

\begin{lstlisting}
- : formel =
Div
 (Div (Sous (Mul (Int 0, Var "x"), Mul (Int 1, Int 1)),
   Mul (Var "x", Var "x")),
 Div (Int 1, Var "x"))
\end{lstlisting}


C'est-à-dire~:

\[\frac{\frac{0\times x-1\times 1}{x\times x}}{\frac{1}{x}}\]


Just for fun : dérivons $\ln\Big(\ln\big(\ln(x)\big)\Big)$


\begin{lstlisting}
# deriv(Ln(Ln(Ln(x))),"x");;
\end{lstlisting}


On obtient~:

\begin{lstlisting}
- : formel = Div (Div (Div (Int 1, Var "x"), Ln (Var "x")), Ln (Ln (Var "x")))
\end{lstlisting}

C'est-à-dire~:


\[\frac{\frac{\frac{1}{x}}{\ln(x)}}{\ln\big(\ln(x)\big)}\]

On devrait  être extrêmement impressionné  par ce qui vient  d'être fait
ici~! À partir  de la définition d'un type  de variable \verb+formel+ et
d'une fonction \verb+deriv+, on a  pu calculer de manière symbolique des
dérivées de toutes les fonctions étudiées  au lycée~! Et on est parti de
pratiquement  rien sur  les fonctions  numériques~! On  a  juste précisé
quelle était la règle de dérivation basique pour chacune d'elles et leur
somme/produit/rapport. 

La  seule  petite  entorse  à  notre règle  ascétique  est  la  fonction
\verb+Puis+ qui utilise la somme des entiers. On aurait pu l'écrire~:

\begin{lstlisting}
| Puis(n,f) -> Mul(d(f,x),Mul(Int(n),Puis(Sous(Int(n),Int(1)),f)))
\end{lstlisting}

ou ne  pas la définir  du tout et  se contenter de  \verb+Mul(x,x)+ mais
bon, on a un peu gagné en lisibilité...

Il reste d'ailleurs  à effectuer un traitement informatique  de ces deux
fonctions  pour  qu'elles  affichent  leurs résultats  de  manière  plus
lisible. Cependant,  cela prendrait du temps et  l'exercice consistant à
décrypter les réponses peut être formateur mathématiquement.



%%%% Annexes : exemples


\chapter{Exemples de TP d'algorithmique}


\section{Fractions et PGCD en 2\up{nde}}




\subsection{Division}

\subsubsection{Comme en primaire}

Vous voulez  diviser 37 par 4~:~à  l'école primaire, vous  avez appris à
vous poser la question~:

\begin{center}
  \emph{En 37 combien de fois 4~?}
\end{center}

Puis vient le temps du calcul~:

\begin{itemize}
\item \emph{une fois 4, 4~:~trop petit...}
\item \emph{2 fois 4, 8~:~trop petit...}
\item \emph{3 fois 4, 12~:~trop petit...}
\item $\cdots$
\item  \emph{9 fois 4, 36~:~trop petit...}
\item \emph{10 fois 4, 40~:~Ah~! Trop grand~!}
\end{itemize}


\og Il y va\fg{} donc 9 fois mais on n'y est pas encore~:~il me reste un
petit pas à faire de 36 jusqu'à 37.

\begin{center}
  \includegraphics[width=.75\linewidth]{Nombres}
\end{center}



Comment traduire cette division à l'aide d'une somme et d'un produit~?

Comment s'appelle chaque membre de cette division~?

\subsubsection{Parlons à l'ordinateur}

Imaginez maintenant que  vous devez expliquer ce calcul  à un ordinateur
en l'imaginant comme un petit lutin se promenant sur la droite des nombres.


Vous pourriez commencer par lui dire~:~

\og  tu pars  de 0  et tu  vas
compter tes enjambées\fg{}, 

puis 

\og
tu avances de 4 unités tant que tu n'auras pas dépassé 37\fg{}.

 Enfin,

 \og
dès  que tu  as dépassé  37, tu  t'arrêtes~:~le quotient  est  le nombre
d'enjambées moins une\fg{}.


Il  ne  reste plus  qu'à  lui dire  dans  sa  langue... Nous  étudierons
principalement deux  langues informatiques  cette année~:~le XCAS  et le
CAML.


Par exemple, en XCAS, cela donne~:

\xc
\begin{lstlisting}[caption={quotient euclidien naïf en impératif}]
quotient(dividende,diviseur):={ 
enjambees:=0;
 while(enjambees*diviseur<=dividende){
  enjambees:=enjambees+1
 }
return(enjambees-1)
}
\end{lstlisting}


\textbf{Écrivez  un  script  qui  renvoie  cette fois  le  reste  de  la
  division euclidienne de deux nombres.}


\subsubsection{Parlons à un ordinateur plus malin}

Les mathématiques,  c'est pour les  fainéants... Le problème,  c'est que
pour  pouvoir  se  payer  le  luxe  d'être fainéant,  il  faut  pas  mal
réfléchir~!

Par exemple, je  suis malin et passablement fainéant.  Je dois diviser a
par b donc savoir \og en a combien de fois b\fg{}. Je me dis~:

\begin{center}
  \emph{Ben  déjà, si  a  est  plus petit  que  b, en  a  il  y va  zéro
    fois~:~le quotient vaut donc zéro}
\end{center}


Puis je me dis~:

\begin{center}
  \emph{Si je  recule de  b, il  ira une fois  de moins  b dans  a. Cela
    signifie que quotient(a,b)=1+quotient(a-b,b)}
\end{center}


Eh ben, avec ça, un ordinateur intelligent va se débrouiller...

On lui demande le quotient de 37 par 4~:~

\begin{itemize}
\item  est-ce que  37 est  plus petit  que 4~?   Non, donc  je  garde en
  mémoire que 
quotient(37,4)=1+quotient(37-4,4) et je m'occupe de quotient(33,4)~;
\item  est-ce que  33 est  plus petit  que 4~?   Non, donc  je  garde en
  mémoire que 
 quotient(33,4)=1+quotient(33-4,4) et je m'occupe de quotient(29,4)~;
\item etc.
\item  est-ce que  5 est  plus petit  que 4~?   Non, donc  je  garde en
  mémoire que 
 quotient(5,4)=1+quotient(5-4,4) et je m'occupe de quotient(1,4)~;
\item est-ce que 1 est plus petit que 4~?  Oui, donc je sais que 
 quotient(1,4)=0~;
\item  donc je  vais pouvoir  calculer quotient(5,4)  puis quotient(9,4)
  puis etc.
\end{itemize}


Ça paraît  plus long mais  ce sale boulot  de gestion de la  mémoire est
fait  par des  logiciels intelligents.  Nous pouvons  nous  contenter de
donner juste  à l'ordinateur un cas  simple et un moyen  pour aller d'un
cas compliqué vers le cas simple. 

Regardez plutôt~!

\begin{lstlisting}[caption={quotient euclidien en récursif}]
quotient_malin(dividende,diviseur):={
 if(dividende<diviseur)
   then{0}
   else{1+quotient_malin(dividende-diviseur,diviseur)} 
}
\end{lstlisting}


CAML parle à peu près le même langage~:

\caml
\begin{lstlisting}[caption={quotient euclidien en récursif (CAML)}]
let rec quotient_malin(dividende,diviseur)=
   if dividende<diviseur 
     then 0
     else 1+quotient_malin(dividende-diviseur,diviseur)
\end{lstlisting}



\textbf{Écrivez un script qui renvoie cette fois le reste malin de la
  division euclidienne de deux nombres.}


\subsection{PGCD}

\subsubsection{Diviseur}

Le PéGéCéDé de deux nombres, c'est leur plus grand diviseur commun.

D'abord, qu'est-ce qu'on appelle un diviseur dans ce contexte~?

Par exemple, 4  divise 80 car le reste  de la division de 80  par 4 vaut
0~:~\og la division tombe juste\fg{} comme vous disiez en CM1.

On  peut aussi  dire  que 4  divise  32~:~4 est  donc un  \emph{diviseur
  commun} de 32 et 80. Mais est-ce le plus grand~?

\subsubsection{Euclide}

Euclide, c'est un savant  grec qui a eu beaucoup de bonnes  idées il y a
2300 ans. On utilise encore largement ses résultats au lycée.

Bon, vous voulez connaître le plus grand diviseur commun de deux nombres
$a$ et $b$.

Est-ce qu'il en existe au moins un~?


L'idée d'Euclide a été  d'effectuer la division...euclidienne de $a$ par
$b$. Soit $a$ le plus grand des deux.

\[a=b\times q+r\qquad{\rm avec }\quad 0\ie r<b\]


Appelons $d$ un diviseur commun de $a$ et $b$.

Pourquoi $d$ est aussi un diviseur commun de $b$ et $r$~? 

Et vice-versa
et dans l'autre sens~?

Donc chercher le PGCD  de $a$ et $b$ revient à chercher  celui de $b$ et
$r$.

Quel est  l'avantage~? Qu'est-ce  qui se passe  au bout d'un  moment~? Y
a-t-il un cas simple~? Peut-on utiliser notre méthode de fainéant~?


Testez vos conjectures sur la machine.


\subsection{Opérations sur les nombres rationnels}


\subsubsection{Fraction simplifiée}


Quelle différence existe-t-il entre $\frac{7}{3}$ et $\frac{21}{9}$~?

Quel rôle peut jouer le PGCD dans cette histoire~?

On va créer un programme simplifiant les fractions.

Au  lieu  d'écrire  un  nombre  rationnel  sous  la  forme  $\dfrac{{\rm
    numérateur}}{{\rm  dénominateur}}$, on va  l'entrer dans  la machine
sous la forme \texttt{[numérateur,dénominateur]}.

Ainsi $\frac{21}{9}$ s'écrira \texttt{[21,9]}.


On peut alors créer un programme qui simplifiera une fraction donnée.

Par exemple sur XCAS~:

\xc

\begin{lstlisting}[caption={simplification de fractions}]
simp(Fraction):={
a:=Fraction[0]; // le premier terme de la fraction
b:=Fraction[1]; // le second
  if(b==0)
    then{"On peut pô  diviser par 0"}
    else{[a/pgcd(a,b),b/pgcd(a,b)]}
}:;
\end{lstlisting}

Des commentaires~?


Sur CAML, on procède à quelques aménagements.

\caml
Pour prévenir toute division par zéro on va créer un opérateur traitant les exceptions qu'on nommera \verb+Division_par_zero+ et qui nous servira de garde-fou :

\begin{lstlisting}
# exception Division_par_zero;;
\end{lstlisting}



On invoquera cette exception avec la commande \verb+raise+ : étant donné
votre 
niveau d'anglais, cette commande est naturelle !...




On peut créer un opérateur qui simplifie les fractions~:

\begin{lstlisting}
# let simp([a;b]) = 
 if b=0  then raise Division_par_zero
 else [a/pgcd(a,b);b/pgcd(a,b)];;
\end{lstlisting}



\subsubsection{Opérations sur les fractions}


On crée ensuite une somme simplifiée de fractions~:


\begin{lstlisting}
# let som([a;b],[c;d]) =
  if b=0 or d=0 then raise Division_par_zero else
  simp([a*d+b*c;b*d]);;
\end{lstlisting}



Par exemple~:


\begin{lstlisting}
# som([2;3],[1;6]);;
- : int list = [5; 6]
\end{lstlisting}


Bon~:~occupez-vous de la multiplication, du calcul de l'inverse et de la
division.



Quand tout sera prêt, comment entrer \[1+\frac{2+\frac{3}{4}}{1-\frac{5}{6}}\]

et 

\[
3+\frac{1}{2+\frac{1}{1+\frac{1}{2+\frac{1}{6}}}}
\]




\section{Suite de Fibonacci en 2\up{nde}}

\subsection{Des animaux, des plantes et des nombres}

\subsubsection{Des lapins}

Voici l'énigme des lapins qui fut proposée en 1202 par Léonard  de Pise, fils  de Bonacci~:

%\begin{figure}[!h]
  \begin{Probleme}[Lapins de Fibonacci]
    Partant d'un couple, combien de couples de lapins obtiendrons-nous après
un nombre donné de mois sachant que chaque couple produit chaque mois un
nouveau couple, lequel ne devient productif qu'après deux mois. 

    \end{Probleme}
 % \end{figure}


Alors...le mois n°0, il y a 1  couple de bébés lapin...le mois n°1 encore le
même couple...le  mois n°2,  hop, un  couple de bébés  naît, ça  fait deux
couples en tout...le mois n°3, un couple de plus, ça fait 3 couples...

\subsubsection{Des fourmis et des abeilles}


%\begin{figure}[!h]
  \begin{Probleme}[arbre généalogique]
    Les  abeilles et les  fourmis ne  naissent pas  comme nous  dans les
    roses ou les choux mais sortent du ventre de leur reine qui passe sa
    vie à pondre.

Lorsque l'\oe  uf est fécondé,  le bébé est  femelle, sinon, ce  sera un
mâle.

Ainsi, une  femelle a un papa et  une maman alors qu'un  mâle n'a qu'une
maman.

On voudrait compter les ancêtres d'un mâle de la septième génération.

    \end{Probleme}
 % \end{figure}


Bon, alors,  un mâle a  une seule  maman, cette maman  a un papa  et une
maman et... vaudrait  mieux dresser un arbre généalogique,  ce sera plus
clair.

Appelons $A(n)$  le nombre d'ancêtres de la  génération $n$, $F(n)$
le nombre de femelles et $M(n)$ le nombre de mâles.


\subsubsection{Des tournesols}


\begin{figure}
\begin{center}
  \includegraphics[height=8cm]{tournesol}
\end{center}
\end{figure}


Comptez les spirales....



\subsubsection{Des pommes de pin}


\begin{figure}
\begin{center}
  \includegraphics[height=8cm]{pommedepin}
\end{center}
\end{figure}

Comptez les spirales...





\subsubsection{Des ordinateurs}

\begin{Probleme}[Fibonacci~:~le retour]

On appelle suite de Fibonacci la \og séquence\fg{} de nombres~:

\[1 - 1 - 2 - 3 - 5 - 8 - 13 - 21 - 34 - 55 - 89 - \cdots \]

Quel est le suivant~?
\end{Probleme}



Essayez de trouver un algorithme  malin afin que CAML puisse calculer le
$n$-eme nombre de cette séquence.


Utilisez cet algorithme pour étudier le quotient d'un terme de cette
séquence par le précédent.



\subsection{Des hommes et un nombre}


\subsubsection{Un rectangle}

\begin{Probleme}[un rectangle en or]
\begin{itemize}
\item Tracez un segment~;
\item tracez un autre segment, perpendiculaire au premier et de longueur
  double. On obtient ainsi un triangle rectangle~;
\item prolongez le premier segment à partir de son extrémité libre d'une
  longueur égale à l'hypoténuse du triangle précédemment tracé~;
\item on obtient  à présent un rectangle. Calculez  de manière exacte le
  quotient  entre  la  largeur  et  la longueur  de  ce  rectangle  puis
  donnez-en une valeur approchée. 
\end{itemize}  
\end{Probleme}

Cela vous rappelle-t-il quelque chose~?


\subsubsection{Une spirale}

\begin{Probleme}[une spirale en or]
  On reprend le rectangle précédent.  On trace à l'intérieur le carré de
  côté  la largeur  du  rectangle. Que  pensez-vous  de petit  rectangle
  restant~? Et si on continuait~?
\end{Probleme}


À partir  du coin supérieur droit du  carré, tracez un arc  de cercle de
rayon le  côté du  carré et d'extrémités  les coins supérieur  gauche et
inférieur droit puis réitérez le processus pour obtenir une spirale.


\begin{figure}
\begin{center}
  \includegraphics[height=6cm]{ammonite}
\end{center}
\end{figure}


\subsubsection{Le Parthénon}


  \begin{Probleme}[Parthénon en or]
    Retrouvez des proportions d'Or dans le Parthénon.
    \end{Probleme}
  

\begin{figure}
\begin{center}
  \includegraphics[height=8cm]{parthenon}
\end{center}
\end{figure}


\subsubsection{Khéops}

 \begin{Probleme}[Pyramide en or]
La hauteur de  la pyramide de Khéops est de  $\nombre{148,2}$m. Le côté de
sa base carré mesure $\nombre{232,8}$m. Calculez la hauteur d'une de ses
faces triangulaires. Retrouvez alors une proportion en or...
\end{Probleme}


\subsubsection{Strasbourg}


  \begin{Probleme}[Parthénon en or]
    Retrouvez des proportions d'Or dans la cathédrale de Strasbourg.
    \end{Probleme}
  

\begin{figure}
\begin{center}
  \includegraphics[height=8cm]{strasbourg}
\end{center}
\end{figure}


\subsubsection{Rezé}


\begin{Probleme}[Le Corbusier]
  L'architecte Le Corbusier qui a conçu notre Maison Radieuse municipale
  a  conçu les  dimensions  de  ses appartements  selon  le principe  du
  \emph{Modulor} représenté dans la figure suivante. Où se cache l'or~?...
\end{Probleme}

\begin{center}
  \includegraphics[height=8cm]{modulor}
\end{center}

\subsection{Des calculs et un nombre}



\subsubsection{Sans calculatrice}

\begin{Probleme}[$\Phi$]
On note $\Phi$ le nombre d'or. Simplifiez l'écriture de $1+\frac{1}{\Phi}$. Que remarquez-vous~?
Simplifiez l'écriture de $\Phi^2$ puis simplifiez l'écriture de
  $1+\Phi$.  Que remarquez-vous~?

\end{Probleme}


\subsubsection{Avec ordinateur}


\begin{Probleme}[racines]
  Donnez une approximation de 
\begin{enumerate}
\item $a_0=1$
\item $a_1=\sqrt{1+\sqrt{1}}$
\item  $a_2=\sqrt{1+\sqrt{1+\sqrt{1}}}$
\item $a_3=\sqrt{1+\sqrt{1+\sqrt{1+\sqrt{1}}}}$
\item $a_4=\sqrt{1+\sqrt{1+\sqrt{1+\sqrt{1+\sqrt{1}}}}}$
\end{enumerate}
\end{Probleme}

Que pensez-vous des algorithmes suivant~:



\caml
\begin{lstlisting}[caption={suite $u_n{n+1}=\sqrt{u_n+1}$}]
# let rec racor(n)=
    if n=0 then 1.
    else sqrt(1. +. racor(n-1));; 
\end{lstlisting}


\xc
\begin{lstlisting}[caption={suite $u_n{n+1}=\sqrt{u_n+1}$} avec XCAS]
racor(n):={
r:=1.;
 for(k:=1;k<=n;k:=k+1){
     r:=sqrt(1+r)
 } 
return(r)
}:;
\end{lstlisting}


\begin{Probleme}[inverses]
  Donnez une approximation de 
  \begin{enumerate}
\item $b_0=1$
   \item $b_1=1+\frac{1}{1}$
  \item $b_2=1+\frac{1}{1+\frac{1}{1}}$
  \item $b_3=1+\frac{1}{1+\frac{1}{1+\frac{1}{1}}}$
  \item  $b_4=1+\frac{1}{1+\frac{1}{1+\frac{1}{1+\frac{1}{1}}}}$
  \item $b_5=1+\frac{1}{1+\frac{1}{1+\frac{1}{1+\frac{1}{1+\frac{1}{1}}}}}$
  \end{enumerate}
\end{Probleme}


Trouvez  un  algorithme  malin  pour  calculer $b_n$  avec  CAML  et  un
algorithme impératif avec XCAS.







\section{L'approximation de $\pi$ d'Archimède en 2\up{nde}}\label{archi}




\subsection{Dodécagone}

À  partir  de l'hexagone  régulier  $ABCDEF $ inscrit  dans le  cercle  de
rayon 1 et de centre $O$ que nous avons étudié précédemment, nous
voudrions tracer un polygone inscrit  à 12 côtés (dodécagone) pour avoir
un peu plus de précision.

\smallskip

Commencez d'abord par zoomer sur le triangle$ AOB$.

\sm

Le nouveau sommet $A'$ du dodécagone  est bien sûr sur le cercle et nous
le choisissons tel que $A'A=A'B$~:~pourquoi~?

\sm

Que représente la droite $(OA')$ pour le segment $[AB]$~? Pourquoi~?

\sm

La droite $(OA')$  coupe la droite $[AB]$ en  $I$~:~que pouvez-vous dire
sur I~?

\sm

Calculez les  distances $OI$ puis $IA'$  puis $AA'$ puis  le périmètre du
dodécagone.

\sm

Quelle nouvelle valeur approchée de $\pi$ obtient-on~?





\subsection{Tétraicosagone}

On double encore le nombre de  côtés. Zoomez comme tout à l'heure sur le
triangle  $OAA'$ et  essayez de  vous inspirer  de la  méthode  que nous
venons  d'employer  pour calculer  le  périmètre  du tétraicosagone.  On
appellera $J$ le milieu de $[AA']$.


\subsection{96 côtés... et plus}

\subsubsection{Un vieux théorème}

Reprenez la  figure du dodécagone en  traçant le cercle en  entier et en
rajoutant le point $K$, milieu de $[BA']$.

Notons $A_d$ le point diamétralement opposé à $A'$.

Que pensez-vous des segments $[OK]$ et $[A_dB]$~?


\subsubsection{Un nouveau théorème}


On considère  un triangle $TRI$  rectangle en $R$  et $H$ le pied  de la
hauteur issue de $R$.

Combien de triangles rectangles sont maintenant dessinés sur la figure~?

Appliquez le théorème de Pythagore à chacun de ces triangles.

On voudrait montrer que $TR^2=TH\times TI$. 

Dans une des trois équations
écrites grâce au théorème de Pythagore, isolez $TR^2$ à gauche puis
débrouillez-vous  avec les deux  autres équations  pour n'avoir  que des
$TH$ et des $TI$ à droite.


\sm

Retournez vers notre cercle et essayez de montrer que $OJ=\sqrt{\dfrac{1+OI}{2}}$.

\subsubsection{Un cerf-volant}

Un  cerf-volant, c'est un  quadrilatère non  croisé dont  les diagonales
sont perpendiculaires.

Soit $ABCD$ un  cerf-volant. Calculez l'aire de $ABCD$  de deux manières
différentes.

\sm

Revenez au cercle. Trouvez un cerf-volant caché dans la figure. Calculez
son   aire    de   deux   manières   différentes    pour   montrer   que
$AA'=\frac{AB}{2OJ}$.


\subsubsection{Héritage}

On suppose connus $OI$ et $AB$~:~comment calculer $OJ$ et $AA'$~?




En quoi cela peut nous aider à continuer à nous approcher du cercle~?



\subsubsection{Un ordinateur}


Tout ça nous demande beaucoup  de calculs or un ordinateur sait calculer
donc nous allons  lui laisser faire la sale  besogne. Le problème, c'est
qu'un ordinateur  est stupide~:~il faut lui  expliquer précisément quels
calculs il doit effectuer.

Appelons l'étape $0$  le cas étudié avec l'hexagone,  l'étape $1$ le cas
du dodécagone, l'étape $2$ le cas du tetraicosagone, etc.

Nous venons de voir comment,  connaissant les dimensions des côtés et la
distance du centre  au côté à une certaine  étape, nous pouvons calculer
les dimensions  des côtés  et la  distance du centre  au côté  à l'étape
suivante. 


Appelons $c(n)$ la longueur du côté du polygone de l'étape $n$ et $d(n)$
la distance de $O$ à un côté du polygone de l'étape $n$.

Que valent $c(0)$ et $d(0)$~?


Combien le polygone de l'étape $n$ a-t-il de côtés~?

Calculez $d(n+1)$  en fonction  de $d(n)$ puis  $c(n+1)$ en  fonction de
$c(n)$ et de $d(n+1)$.

Voici à l'aide  de CAML un algorithme malin  qui permet de calculer
$d(n)$ à n'importe quelle étape $n$~:


\caml

\begin{lstlisting}
# let rec d(n)=
   if n=0 then 0.5*.sqrt(3.)
   else sqrt(0.5*.(1.+.d(n-1)));;
\end{lstlisting}

Comment  dit-on carré  en anglais~?  Et racine~?  À votre  avis,  à quoi
correspond la commande \verb+sqrt+.

À vous de trouver un programme pour calculer $c(n)$ puis pour donner une
valeur approchée par défaut de $\pi$...















\lstlistoflistings



%%% biblio et fin

% \nocite{gac}
% \nocite{guide}
% \nocite{vei}
% \nocite{leroyref}
% \nocite{cousineau}
\nocite{*}
\bibliography{PafAlgo}


\end{document}
%%% Local Variables: 
%%% mode: latex
%%% TeX-master: t
%%% End: 

% LocalWords:  Cantor
