\chapter{Python en classe de Seconde}

\newpage

\section*{Extrait du programme de Seconde\\"Algorithmique et programmation"}

La démarche algorithmique est, depuis les origines, une composante essentielle de l'activité mathématique. Au cycle 4, en mathématiques et en technologie, les élèves ont appris à
écrire, mettre au point et exécuter un programme simple. Une consolidation des acquis du cycle 4 est proposée autour de deux idées essentielles :
\begin{itemize}
\item la notion de fonction;
\item la programmation comme production d'un texte dans un langage informatique.
\end{itemize}
Dans le cadre de cette activité, les élèves s'exercent à :
\begin{itemize}
\item décrire des algorithmes en langage naturel ou dans un langage de programmation;
\item en réaliser quelques-uns à l'aide d'un programme simple écrit dans un langage de programmation textuel;
\item interpréter, compléter ou modifier des algorithmes plus complexes.
\end{itemize}
Un langage de programmation simple d'usage est nécessaire pour l'écriture des programmes informatiques. Le langage choisi est Python, langage interprété, concis, largement répandu et pouvant fonctionner dans une diversité d'environnements. Les élèves sont entraînés à passer du langage naturel à Python et inversement.

L'algorithmique a une place naturelle dans tous les champs des mathématiques et les problèmes ainsi traités doivent être en relation avec les autres parties du programme (fonctions, géométrie, statistiques et probabilité, logique) mais aussi avec les autres disciplines ou la vie courante.

À l'occasion de l'écriture d'algorithmes et de petits programmes, il convient de transmettre aux élèves l'exigence d'exactitude et de rigueur, et de les entraîner aux pratiques systématiques de vérification et de contrôle. En programmant, les élèves revisitent les notions de variables et de fonctions sous une forme différente.

\newpage

\section{Les coordonnées}
\index{Point (représentation en Python)@Point (représentation en Python)}

Un point peut être représenté, tout comme un vecteur, par un couple de nombres: ses coordonnées.

En Python, on pourra alors définir un point à l'aide d'une liste de deux nombres (définie par des crochets) ou d'un 2-uplet (défini par des parenthèses).

\begin{exemple}
Le point $A\coord{-3}{2}$ peut être représenté en Python par la syntaxe suivante :
\begin{console}
>>> A = [ -3 , 2 ]
\end{console}

Mais il peut aussi être représenté par:
\begin{console}
>>> A = (-3, 2)
\end{console}

Dans un cas comme dans l'autre, l'abscisse est stockée dans \texttt{A[0]} et son ordonnée dans \texttt{A[1]}.
\end{exemple}
\index{Vecteur (representation en Python)@Vecteur (représentation en Python)}

Cette façon de représenter un point ou un vecteur est bien plus pratique dans bon nombre de cas.

\begin{exemple}
On souhaite écrire une fonction \texttt{f} qui renvoie les coordonnées de $k\vv{u}$, connaissant les coordonnées de $\vv{u}$.

On sait que si $\vv{u}\dbinom{x}{y}$ alors le vecteur $k\vv{u}$ a pour coordonnées $\dbinom{kx}{ky}$.

Une première façon de faire est la suivante:
\begin{python}
def f(k,x,y):
    return (k*x , k*y)
\end{python}

Une autre façon de faire est:
\begin{python}
def f(k,u):
    return (k*u[0] , k*u[1])
\end{python}
qui donne en mode console:
\begin{console}
>>> u = (-3, 2)
>>> f(-3,u)
(9, -6)
\end{console}
\end{exemple}

L'avantage ne se voit pas nécessairement dans cet exemple, mais dès qu'il faudra passer en arguments plusieurs vecteurs ou plusieurs points, la lisibilité de la fonction n'en sera que meilleure (voir les exercices portant sur le repérage dans le plan et ceux sur les vecteurs).

\section{\'Equations de droites}
\index{Droite (représentation en Python)@Droite (représentation en Python)}

Il existe deux types d'équations de droites:
\begin{itemize}
\item l'équation réduite, de la forme $y=mx+p$;
\item les équations cartésiennes, de la forme $ax+by+c=0$.
\end{itemize}

De même que pour les points et les vecteurs, on pourra définir une droite à partir de son équation réduite en écrivant:
\begin{console}
>>> D = (m, p)
\end{console}
ou à partir d'une équation cartésienne, en écrivant:
\begin{console}
>>> D = (a, b, c)
\end{console}

\begin{exemple}
La droite d'équation $y=-2x+3$ pourra être représentée par:
\begin{console}
>>> D = (-2, 3)
\end{console}

Cette droite admet pour équation cartésienne $-2x-y+3=0$, ou encore (en multipliant tous les coefficients par $-1$): $2x+y-3=0$, et pourra être représentée par:
\begin{console}
>>> D = (2, 1, -3)
\end{console}
\end{exemple}

\begin{rem}
Dans cet exemple, on peut voir que la première variable \texttt{D} peut aussi être interprétée comme un point. Si vous souhaitez lever toute ambiguïté, vous pouvez donner un nom explicite à la variable:
\begin{console}
>>> droite_reduite = (-2, 3)
>>> droite_cartesienne = (2, 1, -3)
\end{console}
\end{rem}

\newpage

\section{Fonctions}

\subsection{La fonction lambda}
\index{lambda (fonction Python)}

En Python, il y a une chose bien pratique: la fonction \textit{lambda}.

Pour définir la fonction $f\;:\;x\mapsto3x+5$, on peut procéder ainsi:

\begin{console}
>>> def f(x):
		return 3*x + 5
>>> f(3)
14
\end{console}

Mais on peut aussi écrire:

\begin{console}
>>> f = lambda x: 3*x + 5
>>> f(3)
14
\end{console}

Bien que très pratique, cette syntaxe n'est que peu retenue par les élèves et les enseignants. Je ne l'utiliserai donc pas dans les exercices.

\subsection{Tracé de courbes}
\index{matplotlib (trace de courbes)@matplotlib (tracé de courbes)}
\index{Courbes representatives@Courbes représentatives}

Pour tracer la représentation graphique d'une fonction, il sera bien utile de faire appel au module \texttt{matplotlib}, et tout particulièrement sa bibliothèque \textit{pyplot}.

\begin{exemple}
On souhaite tracer la courbe représentative de la fonction $f\;:\;x\mapsto0,05x^3-3x+1$ sur \intervFF{-5}{5}.
\begin{python}
from matplotlib.pyplot import plot, show

X = [ x/10 for x in range(-50,51) ]
Y = [ 0.05*x**3 - 3*x + 1 for x in X ]

plot(X, Y)
show()
\end{python}

\begin{itemize}
\item \textbf{Ligne 1:} on commence par importer les fonctions qui nous seront utiles (ici, \texttt{plot} pour tracer et \texttt{show} pour voir le résultat dans une fenêtre).

\item \textbf{Ligne 2:} on construit une liste de valeurs de $x$. Dans la mesure où \texttt{range} n'accepte en aucun cas des pas décimaux, on ne peut pas aller de 0,1 en 0,1 donc j'ai décidé d'aller de $x=-50$ à $x=51$ et de diviser toutes les valeurs par 10. 

Ainsi, je crée une liste \texttt{[-5.0, -4.9, -4.8, ... , 5.0]}.

\newpage

\item \textbf{Ligne 3:} on construit une liste des images par la fonction qui nous intéresse. On calcule ici les images de toutes les valeurs contenues dans la liste \texttt{X} précédemment construite.

$\to$ On calcule $0,05x^3-3x+1$ pour tous les $x$ contenus dans \texttt{X}.

\item \textbf{Lignes 4 et 5:} on trace la courbe et on l'affiche dans une fenêtre.
\end{itemize}
Ce code produit le graphique ci-dessous:

\medskip

\begin{center}
\includegraphics[width=0.75\linewidth]{courbe-2nde-cours.jpg}
\end{center}
\end{exemple}


Il ne faut surtout pas s'attendre à obtenir un repère \og classique \fg{} avec \texttt{matplotlib}. 

Si l'exemple vous paraît trop compliqué, peut-être qu'en faisant appel au module \texttt{numpy}, les choses vous sembleront plus simples:

\begin{exemple}[avec le module numpy]
\begin{minipage}{0.5\linewidth}
\begin{python}
from matplotlib.pyplot import plot, show, grid
from numpy import linspace

x = linspace(-5, 5, 100)
y = 0.05*x**3 - 3*x + 1

plot(x,y)
grid()
show()
\end{python}
\end{minipage}
\begin{minipage}{0.5\linewidth}
\begin{center}
\includegraphics[height=5cm]{courbe-2nde-cours-2.jpg}
\end{center}
\end{minipage}
\end{exemple}

Il est vrai que la syntaxe est plus simple: le troisième argument de la fonction \texttt{linspace} est le pas des $x$. Ici, je suis allé de 0,01 en 0,01.

\medskip

Le module \texttt{numpy} contient des fonctions mathématiques; on peut donc tracer des fonctions plus complexes (comme les fonctions \textit{sinus} et \textit{cosinus}). 

\begin{exemple}[tracé deux courbes]
\begin{python}
from matplotlib.pyplot import plot, show, grid, axhline, axvline, gca
import matplotlib.pyplot as plt

X = [x/10 for x in range(-50, 51)]
Y = [0.05*x**3 - 3*x + 1 for x in X]
Z = [-0.5*x**2 + x - 1 for x in X]

plot(X, Y)
plot(X, Z)
grid()
axhline(y=0, color='black', linestyle='-')
axvline(x=0, color='black', linestyle='-')

ax = gca()

ax.set_xlim(left=-5, right=5)
ax.set_ylim(bottom=-10, top=10)
ax.plot((1), (0), ls="", marker=">", ms=10, color="k", transform=ax.get_yaxis_transform(), clip_on=False)
ax.plot((0), (1), ls="", marker="^", ms=10, color="k", transform=ax.get_xaxis_transform(), clip_on=False)

show()
\end{python}

\begin{center}
\includegraphics[width=0.75\linewidth]{courbe-2nde-cours-3.jpg}
\end{center}
\end{exemple}

\begin{exemple}
\begin{python}
from matplotlib.pyplot import plot, show, grid, axhline, axvline, gca
from numpy import linspace

x = linspace(-3, 3, 100)
y = 1/x

plot(x, y)
grid()
axhline(y=0, color='black', linestyle='-')
axvline(x=0, color='black', linestyle='-')

ax = gca()

ax.set_xlim(left=-3, right=3)
ax.set_ylim(bottom=-5, top=5)
ax.plot((1), (0), ls="", marker=">", ms=10, color="k", transform=ax.get_yaxis_transform(), clip_on=False)
ax.plot((0), (1), ls="", marker="^", ms=10, color="k", transform=ax.get_xaxis_transform(), clip_on=False)

show()
\end{python}
\begin{center}
\includegraphics[width=0.75\linewidth]{courbe_inverse_cours.jpg}
\end{center}
\end{exemple}

\newpage

\section{Statistiques}
\index{Statistiques}

\subsection{Les calculs}

Afin d'effectuer des calculs sur les séries statistiques, on peut faire appel au module \texttt{statistics} de Python.

Les fonctions qui pourront alors nous intéresser sont :

\begin{itemize}
\item \texttt{mode(L)} pour calculer le mode de la série représentée par la liste \texttt{L};
\begin{console}
>>> from statistics import mode
>>> mode([1, 2, 2, 3, 3, 4, 4, 4, 4, 5])
4
\end{console}

\item \texttt{median(L)} pour déterminer la médiane de la série représentée par la liste \texttt{L};
\begin{console}
>>> from statistics import median
>>> median([1, 2, 2, 3, 3, 4, 4, 4, 4, 5])
3.5
\end{console}

\item \texttt{quantiles(L,n=4)} pour déterminer les quartiles et la médiane de la série représentée par la liste \texttt{L};
\begin{console}
>>> from statistics import quantiles
>>> quantiles([1, 2, 2, 3, 3, 4, 4, 4, 4, 5] , n=4)
[2.0, 3.5, 4.0]
\end{console}

\item \texttt{mean(L)} pour calculer la moyenne de la série représentée par la liste \texttt{L};
\begin{console}
>>> from statistics import mean
>>> mean([1, 2, 2, 3, 3, 4, 4, 4, 4, 5])
3.2
\end{console}

\item \texttt{pvariance(L)} pour calculer la variance de la série représentée par la liste \texttt{L};
\begin{console}
>>> from statistics import pvariance
>>> pvariance([1, 2, 2, 3, 3, 4, 4, 4, 4, 5])
1.3599999999999999
\end{console}
\begin{attention}
Il existe également une fonction \texttt{variance(L)}, mais elle ne retourne pas le même nombre... Sur l'exemple donné, elle retourne \og \texttt{1.511111111111111} \fg{} alors que la réelle variance est bien 1,36.
\end{attention}

\newpage

\item \texttt{pstdev(L)} pour calculer l'écart-type de la série représentée par la liste \texttt{L};
\begin{console}
>>> from statistics import pstdev
>>> pstdev([1, 2, 2, 3, 3, 4, 4, 4, 4, 5])
1.16619037896906
\end{console}
\begin{attention}
Il existe là aussi une autre fonction \texttt{stdev}, mais il ne retourne pas la même valeur. Sur l'exemple donné, elle renvoie \og \texttt{1.2292725943057183} \fg.
\end{attention}
\end{itemize}


\subsection{Les diagrammes en barres}
\index{matplotlib (diagrammes en barres)}
\index{Diagrammes en barre}

Les diagrammes en barres peuvent être tracés à l'aide du module \texttt{matplotlib}.

\begin{exemple}
\begin{minipage}{0.6\linewidth}
\begin{python}
from matplotlib.pyplot import bar,show

X = ['rouge' , 'bleu' , 'vert' , 'jaune']
V = [ 5 , 2 , 7 , 3 ]

bar(X, V, color='g') 
# 'g' pour 'green'
show()
\end{python}
\end{minipage}
\hfill
\begin{minipage}{0.35\linewidth}
\includegraphics[scale=0.4]{histogramme-cours.jpg}
\end{minipage}

\begin{minipage}{0.6\linewidth}
\begin{python}
from matplotlib.pyplot import bar,show

X = ['rouge' , 'bleu' , 'vert' , 'jaune']
V = [ 5 , 2 , 7 , 3 ]
C = [ 'r' , 'b' , 'g' , 'y' ]

bar(X, V, color=C)
show()
\end{python}
\end{minipage}
\hfill
\begin{minipage}{0.35\linewidth}
\includegraphics[scale=0.4]{histogramme-cours-2.jpg}
\end{minipage}
\end{exemple}

\newpage

\subsection{Les histogrammes}

Les histogrammes sont utilisés lorsque les caractères sont des \textit{classes} (des intervalles).

\texttt{matplotlib} dispose bien d'une fonction \texttt{hist}, mais elle ne fait pas le job demandé...

\begin{exemple}
\begin{minipage}{0.6\linewidth}
\begin{python}
from matplotlib.pyplot import hist,show, xlabel, ylabel, title

X = [1, 2, 2, 3, 4, 4, 4, 4, 4, 5, 5]
hist(X, range = (0,5) , bins = 5, color = 'y' , edgecolor = 'r')
xlabel('valeurs')
ylabel('nombres')
title('Exemple')
show()
\end{python}
\end{minipage}
\hfill
\begin{minipage}{0.35\linewidth}
\includegraphics[scale=0.4]{histogramme-cours-3.jpg}
\end{minipage}
\end{exemple}


\section{Probabilités}
\index{Probabilités (module random)}
\index{random (module)}

Il est très souvent pratique de simuler une expérience aléatoire.

Pour cela, on pourra faire appel au module \texttt{random}. Parmi les fonctions utiles, il y a :

\begin{itemize}
\item \texttt{randrange(a,b)} ou \texttt{randint(a,b)} qui renvoie un nombre entier aléatoire compris entre $a$ et $b$ (inclus).
\begin{console}
>>> from random import randint
>>> randint(45,62)
52
\end{console}

\item \texttt{choice(L)} qui renvoie un élément choisi au hasard dans la liste \texttt{L}.
\begin{console}
>>> from random import choice
>>> choice([45,62,18,27])
62
\end{console}

\item \texttt{choices(L,k)} qui renvoie $k$ éléments choisis au hasard dans la liste \texttt{L}.
\begin{console}
>>> from random import choices
>>> choices([12,36,25,84,102],k=2)
[102, 12]
\end{console}

\newpage

\item \texttt{shuffle(L)} qui mélange la liste \texttt{L}.
\begin{console}
>>> from random import shuffle
>>> L = [12,36,25,84,102]
>>> shuffle(L)
>>> L
[25, 102, 12, 36, 84]
\end{console}

\item \texttt{random()} qui renvoie un nombre pseudo-aléatoire compris entre 0 (inclus) et 1 (exclus).
\begin{console}
>>> from random import random
0.8158474753065126
\end{console}
\end{itemize}

\section{\'Echantillonnage}
\index{Echantillonnage@Échantillonnage}

Considérons l'expérience $E$ consistant à choisir un nombre au hasard entre 1 et 6 (inclus): simulation d'un lancer de dé cubique équilibré. 

On répète 100 fois cette expérience $E$ et on compte le nombre de fois où l'on obtient la face \og 1 \fg. Cette répétition constitue une expérience $R$. On calcule alors la fréquences d'apparition du \og 1 \fg sur ces 100 lancers.

Répétons alors 200 fois l'expérience $R$ et reportons sur un graphique les fréquences obtenues, à l'aide du programme suivant.


\begin{python}
from random import randint
from matplotlib.pyplot import axis, plot, show, axhline

L = [] # liste des fréquences
delta = 1/10 # 1/sqrt(100)
p = 1/6 # probabilité d'obtenir la face "1"

for _ in range(200):
    n = 0
    for _ in range(100):
        face = randint(1, 6)
        if face == 1: # si face est "1"
            n = n + 1
            
    L.append(n/100)

axis([0,200,0,0.5])
plot(L, marker='+', linestyle='')
axhline(y=p-delta, color='r', linestyle='--')
axhline(y=p+delta, color='r', linestyle='--')
show()
\end{python}

\medskip

\begin{minipage}{0.45\linewidth}
On obtient le graphique ci-contre.

\medskip

La variable \texttt{p} joue le rôle du pourcentage de multiples de 3 obtenus lors d'une expérience $R$. On peut ainsi visualiser que ce pourcentage fluctue dans une sorte de \og couloir \fg{}: c'est l'\textit{intervalle de fluctuations}. 
\end{minipage}
\hfill
\begin{minipage}{0.5\linewidth}
\includegraphics[width=0.95\linewidth]{simulation-cours.jpg}
\end{minipage}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\exercices

\section*{Arithmétique}

\subsection*{Multiples et diviseurs}

\begin{exocor}{}[1]
Expliquer ce qu'affiche le programme suivant:
\begin{python}
for n in range(1,100):
    if n % 7 == 0:
        print(n)
\end{python}

\tcblower

La ligne 1 définit une boucle itérative qui signifie que l'on va considérer tous les nombres entiers $n$ de 1 à 99.

Dans cette boucle, on effectue le test \og \texttt{if n \% 7 == 0} \fg{} c'est-à-dire que l'on vérifie si $n$ est divisible par 7. Si tel est le cas, on affiche $n$ (\texttt{print(n)}).

\medskip

Ainsi, ce programme affiche tous les multiples de 7 compris entre 1 et 99.
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[1]
Expliquer ce qu'affiche le programme suivant:
\begin{python}
n = 480

for k in range(2,n+1):
    if n % k == 0:
        print(k)
\end{python}

\tcblower

On commence par définir une variable : on affecte à la variable \texttt{n} la valeur 480.

Ensuite, on définit une boucle itérative : on fait varier la variable $k$ de 2 à $n$, donc ici de 2 à 480.

Dans cette boucle, on teste si le reste de la division euclidienne de $n$ par $k$ est nul, c'est-à-dire si $n$ est divisible par $k$. Si tel est le cas, on affiche la valeur de $k$. $k$ est donc un diviseur de $n$.

Finalement, le programme affiche tous les diviseurs de $n$.
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%
\enlargethispage*{2em}
\begin{exocor}{}[1]
On considère le programme suivant:
\begin{python}
a = 450
b = 186
r = -1
while r !=0 :
    q = a // b
    r = a - b*q
    a = b
    b = r
      
print(a)
\end{python}
\newpage
\begin{enumerate}
\item Tester ce programme \og à la main \fg{} en écrivant toutes les étapes dans le tableau suivant:
\begin{center}
\begin{tabular}{|Sl|*2{Sc|}}
\hline
Test $r \neq 0$ & \diagbox{}{} & $\cdots$ \\\hline
Valeurs de q & \diagbox{}{} & $\cdots$ \\\hline
Valeurs de r & $-1$ & $\cdots$\\\hline
Valeurs de a & 450 & $\cdots$ \\\hline
Valeurs de b & 186 & $\cdots$ \\
\hline
\end{tabular}
\end{center}

\item À quoi correspond la valeur affichée ?
\end{enumerate}

\tcblower

\begin{enumerate}
\item Le tableau complété est le suivant:
\begin{center}
\begin{tabular}{|Sl|*8{Sc|}}
\hline
Test $r \neq 0$ & \diagbox{}{} & vrai & vrai & vrai & vrai & vrai & vrai & faux\\\hline
Valeurs de q & \diagbox{}{} & 2 & 2 & 2 & 1 & 1 & 2 & \diagbox{}{} \\\hline
Valeurs de r & $-1$ & 78 & 30 & 18 & 12 & 6 & 0& \diagbox{}{} \\\hline
Valeurs de a & 450 & 186 & 78 & 30 & 18 & 12 & 6& \diagbox{}{} \\\hline
Valeurs de b & 186 & 78 & 30 & 18 & 12 & 6 & 0& \diagbox{}{}\\
\hline
\end{tabular}
\end{center}

Le programme affiche donc la valeur \og 6 \fg, dernière valeur de \texttt{a} trouvée. 

\item En construisant le tableau précédent, on a pu s'apercevoir que \texttt{q} et \texttt{r} étaient les valeurs successives des quotients et restes obtenus dans la division euclidienne de 450 par 186. La dernière valeur de $a$ correspond au dernier reste non nul. 

Par conséquent, la valeur affichée correspond au PGCD de 450 et 186.
\end{enumerate}


Le programme proposé n'est pas optimal, mais il a été présenté ici pour être compris par le plus grand nombre de personnes. On aurait pu aussi écrire :
\begin{python}
a, b, r = 450, 186, -1
while r !=0 :
    r = a % b
    a = b
    b = r
    
print(a)
\end{python}

ou encore, une forme dite \textit{récursive} (bien plus compliquée pour des élèves de Seconde):

\begin{python}
def pgcd(a,b):
    if b == 0:
        return a
    else:
        return pgcd(b , a%b)

print( pgcd(480,186) )
\end{python}
\end{exocor}

\subsection*{Nombres premiers}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[2]
On considère la fonction Python suivante:
\begin{python}
def is_it(a):
    # a est un nombre entier

    for k in range(2,a):
        if a % k == 0:
            return False

    return True
\end{python}

\medskip

\begin{enumerate}
\item Que renvoie \texttt{is\_it(18)} ?

\item Que renvoie \texttt{is\_it(15)} ?

\item Que renvoie \texttt{is\_it(7)} ?

\item Que fait alors ce programme ?
\end{enumerate}

\tcblower

\begin{enumerate}
\item Ici, \texttt{a = 18}.

Au premier passage dans la boucle itérative, $k=2$. On teste alors si le reste de la division euclidienne de 18 par 2 est nul: c'est le cas car  18 est divisible par 2. Ainsi, la fonction renvoie \texttt{False}.

\item Ici, \texttt{a = 15}.

Au premier passage dans la boucle itérative, $k=2$. On teste alors si le reste de la division euclidienne de 15 par 2 est nul, ce qui n'est pas le cas car 15 n'est pas divisible par 2. On n'exécute donc pas l'instruction \og \texttt{return False} \fg.

À l'itération suivante, $k=3$. Comme 15 est divisible par 3, l'instruction \texttt{return False} est exécutée..

La fonction renvoie donc \texttt{False}. 

\item Ici, \texttt{a = 7}.

On effectue alors le test \og  est-ce que 7 est divisible par $k$ \fg, pour $k=2$, $k=3$, $k=4$, $k=5$ et $k=6$, ce qui n'est jamais le cas, donc l'instruction \og \texttt{return False} \fg{} n'est jamais exécutée.

On sort alors de la boucle itérative et on effectuela dernière instruction.

\medskip

Finalement, la fonction renvoie \texttt{True}. 

\item On s'aperçoit alors que la fonction est chargée de voir si le nombre \texttt{a} est divisible par chacun des entiers compris entre 1 et $a-1$. S'il existe un tel entier, elle renvoie \texttt{False}; sinon, elle renvoie \texttt{True}.

Il semblerait donc que cette fonction nous dise si le nombre \texttt{a} est un nombre premier (auquel cas, elle renvoie \texttt{True}) ou pas (auquel cas, elle renvoie \texttt{False}).
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newpage

\begin{exocor}{}[2]
On considère la fonction Python suivante:
\begin{python}
def f(n):
    d = 2
    while n > 1:
        while n % d == 0:
            print(d)
            n = n // d
        d = d + 1
\end{python}
\begin{enumerate}
\item Qu'affiche \texttt{f(20)} ?
\item Quel rôle a cette fonction ?\vspace*{-2em}
\end{enumerate}

\tcblower	

\begin{enumerate}
\item Regardons pas à pas ce que fait la fonction Python pour $n=20$.

\begin{center}
\begin{tabular}{|Sl|*7{Sc|}}
\hline
Condition $n>1$                & \diagbox{}{} & vraie & vraie & vraie  & vraie  & vraie & fausse\\\hline
Condition \texttt{n \% d == 0} & \diagbox{}{} & vraie & vraie & fausse & fausse & vraie & - \\\hline
Valeur de $n$                  & \diagbox{}{} & 10    & 5     & 5      & 5      & 1     & -\\\hline
Affichage                      & \diagbox{}{} & 2     & 2     & -      & -      & 5     & -\\\hline
Valeur de $d$                  & 2            & 2     & 3     & 4      & 5      & 6     & -\\\hline
\end{tabular}
\end{center}

\newpage
Finalement, \texttt{f(20)} affiche :
\begin{console}
>>> f(20)
2
2
5
\end{console}

\item Sur l'exemple précédent, on peut voir que la fonction affiche les facteurs qui interviennent dans la décomposition en produit de facteurs premiers de $n$, et que chaque facteur s'affiche autant de fois que son exposant. 

Ici, $20=2^2\times5$ et \og 2 \fg{} apparaît deux fois, alors que \og 5 \fg{} ne s'affiche qu'une fois.
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[2]
Expliquer ce qu'affiche le programme suivant:
\begin{python}
for n in range(2,100):
    if n == 2:
        print(n)
    else:
        p = True
        k = 2
        while k < n and p == True:
            if n % k == 0:
                p = False
            k = k + 1
        
        if p == True:
            print(n)
\end{python}

\tcblower

Ce programme est avant tout constitué d'une boucle itérative sur une variable \texttt{n}: cette variable prend les valeurs entières de 2 à 99. Pour chacune de ces valeurs :
\begin{itemize}
\item on commence par tester si elle est égale à 2: si c'est le cas, on affiche \og 2 \fg{}, sinon on passe à la suite ;

\item si $n\neq2$, on initialise une variable \texttt{p} à \og \texttt{True} \fg{} (variable booléenne) et une autre variable \texttt{k} à 2. On entre alors dans une boucle conditionnelle tant que $k<n$ et que \texttt{p} vaut \texttt{True}.

\item si le reste de la division euclidienne de $n$ par $k$ vaut 0 (c'est-à-dire si $k$ divise $n$), \texttt{p} vaut \texttt{False}, ce qui a pour conséquence que la boucle conditionnelle est terminée (car elle n'est exécutée que si \texttt{p} vaut \texttt{True});

La valeur de \texttt{k} est augmentée de 1 à chaque passage dans la boucle conditionnelle. Donc si \texttt{p} reste toujours à \texttt{False}, la boucle conditionnelle s'arrêtera dès lors que la condition \og $k<n$ \fg{} n'est plus vérifiée, c'est-à-dire quand $k=n$;

\item une fois la boucle conditionnelle terminée, si \texttt{p} vaut encore \texttt{True}, la valeur de $n$ est affichée.
\end{itemize}

Ainsi, on n'affiche que les valeurs de $n$ qui n'ont pas de diviseurs inférieurs à $n$, ce qui correspond aux nombres premiers inférieurs à 100.
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\subsection*{Divers}

\begin{exocor}{}[2]
\'Ecrire une fonction Python \texttt{somme(n)} qui calcule et retourne la somme des chiffres du nombre $n$.

\tcblower

Il y a plusieurs façons de calculer la somme des chiffres d'un entier.

\medskip

Pour voir ces différentes façons, vous pouvez consulter la page :
\begin{center}
\url{https://www.mathweb.fr/euclide/2021/04/19/somme-des-chiffres-dun-nombre-en-python/}
\end{center}

\medskip

Je ne présenterai ici que la solution la plus abordable en Seconde, celle qui repose sur les mathématiques, bien qu'elle ne soit pas la plus performante.

\begin{python}
def somme(n):
    s = 0
    while n > 0:
        s = s + n % 10 # on ajoute à s le chiffre des unités
        n = n // 10 # n devient son quotient euclidien par 10
    
    return s
\end{python}

Regardons sur un exemple ce que fait la fonction: prenons $n=5478$.

\begin{center}
\begin{tabular}{|>{\ttfamily}Sc|*6{Sc|}}
\hline
n > 0   & \diagbox{}{} &  oui    & oui      & oui       & oui & non \\
\hline
n \% 10 & \diagbox{}{} &  8      & 7        & 4         & 5 & \diagbox{}{} \\
\hline
s       & 0    & $0+8=8$ & $8+7=15$ & $15+4=19$ & $19+5=24$ & \diagbox{}{} \\
\hline
n       & \numprint{5478} & 547     & 54       & 5         & 0 & \diagbox{}{} \\
\hline
\end{tabular}
\end{center}

La variable \texttt{s} contient au final la somme $8+7+4+5$, qui est bien la somme demandée.
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[2]
On se demande quels sont les nombres entiers $n$ qui ont le même chiffre des unités que leur carré $n^2$ (comme $n=11$ et $n^2=121$).

Pour cela, on considère que tous les nombres entiers $n$ peuvent s'écrire sous la forme \mbox{$n=10x + u$}, où $u$ est un entier compris entre 0 et 9 (inclus).

\begin{enumerate}
\item \'Ecrire $n=37$ sous la forme $10x+u$.
\item \'Ecrire $n=146$ sous la forme $10x+u$.
\item En développant $(10x+u)^2$, énoncer une condition sur $u$ pour que $n$ et $n^2$ aient le même chiffre des unités.
\item \'Ecrire une fonction Python \texttt{unite(n)} qui affiche les nombres compris entre 0 et $n$ (inclus) dont le chiffre des unités est le même que celui de leur carré.
\end{enumerate}

\tcblower

\begin{enumerate}
\item $n = 30 + 7 = 10\times3 + 7$. Donc $x=3$ et $u=7$.
\item $n = 140 + 6 = 10\times14 + 6$. Donc $x=14$ et $u=6$.
\item $(10x+u)^2 = 100x^2 + 20xu + u^2 = 10(10x^2+2xu) + u^2$.

Ainsi, $u^2$ et $n^2$ ont le même chiffre des unités.

Or, $u<10$ donc nous avons 10 possibilités :

\begin{itemize}
\item $u=0$ : $u^2=0$ et donc $n$ et $n^2$ ont le même chiffre des unités;
\item $u=1$ : $u^2=1$ et donc $n$ et $n^2$ ont le même chiffre des unités;
\item $u=2$ : $u^2=4$ et donc $n$ et $n^2$ n'ont pas le même chiffre des unités;
\item $u=3$ : $u^2=9$ et donc $n$ et $n^2$ n'ont pas le même chiffre des unités;
\item $u=4$ : $u^2=16$ et donc $n$ et $n^2$ n'ont pas le même chiffre des unités;
\item $u=5$ : $u^2=25$ et donc $n$ et $n^2$ ont le même chiffre des unités;
\item $u=6$ : $u^2=36$ et donc $n$ et $n^2$ ont le même chiffre des unités;
\item $u=7$ : $u^2=49$ et donc $n$ et $n^2$ n'ont pas le même chiffre des unités;
\item $u=8$ : $u^2=64$ et donc $n$ et $n^2$ n'ont pas le même chiffre des unités;
\item $u=9$ : $u^2=81$ et donc $n$ et $n^2$ n'ont pas le même chiffre des unités.
\end{itemize}

\item Une fonction Python possible est celle proposée page suivante.
\begin{python}
def fct(n):
    for k in range(n+1):
        u = k % 10 # chiffre des unités de k
        v = k**2 % 10 # chiffre des unités du carré de k
        if u == v:
            print(k, end = ' ')
\end{python}

Explications:
\begin{itemize}
\item on crée une boucle itérative qui nous permet de parcourir tous les entiers de 0 à $n$;

\item pour chaque entier $k$ compris entre 0 et $n$, on définit \texttt{u} et \texttt{v} comme étant le chiffre des unités respectivement de $k$ et de $k^2$;

\item si ces deux chiffres sont égaux (ligne 6) alors on l'affiche; ici, l'instruction \og \texttt{print(k, end=' '} \fg{} spécifie que les nombres seront affichés en ligne (en non avec un retour à la ligne à chaque itération). 
\end{itemize}

Cela donne par exemple :

\begin{console}
>>> fct(20)
0 1 5 6 10 11 15 16 20
\end{console}
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\begin{exocor}{}[2]
\'Ecrire une fonction Python \texttt{fct(n)} qui affiche les nombres entiers $x$ compris entre 0 et $n$ (inclus) tels que la somme des chiffres de $x^2$ est égale à $x$.

\begin{rem}
Si $x=12$ alors $x^2=144$ et la somme des chiffres de $x^2$ est égale à $1+4+4=9$, somme différente de $x$ donc $12$ ne sera pas dans la liste.
\end{rem}

\tcblower

\begin{python}
def fct(n):
    for k in range(n+1):
        s = 0
        x = k**2
        while x > 0:
            u = x % 10
            s = s + u
            x = x // 10
            
        if s == k:
            print(k, end=' ')
\end{python}

On obtient par exemple:

\begin{console}
>>> fct(2000)
0 1 9
\end{console}

Si on essaie avec d'autres valeurs de $n$ supérieures, on obtient toujours la même liste; on peut alors conjecturer que les seuls nombres correspondant à notre recherche sont 0, 1 et 9.

\vspace*{5cm}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[2]
On considère un nombre entier $x$. On note $d = 2x$ et $c = x^2$.

\'Ecrire une fonction Python \texttt{fct(n)} qui affiche tous les nombres $x$ tels que la somme des chiffres de $d$ est égale à celle des chiffres de $c$ (comme par exemple $x=11$ car $d=22$ et $c=121$, et $2+2=1+2+1$).

\bigskip

Donner alors la liste des nombres compris entre 0 et 100 retournée par la fonction Python.

\tcblower

\begin{python}
def fct(n):
    for k in range(n+1):
        double = 2 * k
        carre = k ** 2
        somme_d, somme_c = 0, 0
        while double > 0:
            somme_d += double % 10
            double = double // 10
            
        while carre > 0:
            somme_c += carre % 10
            carre = carre // 10
            
        if somme_c == somme_d:
            print(k, end = ' ')
\end{python}

On obtient alors :

\begin{console}
>>> fct(100)
0 2 9 11 18 20 29 38 45 47 90 99 
\end{console}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newpage

\section*{Repérage dans le plan}

\begin{exocor}{}[1]
On considère la fonction Python suivante:
\begin{python}
def f(A,B):
    return ( (A[0] + B[0])/2 , (A[1] + B[1])/2 )
\end{python}
\begin{enumerate}
\item On tape en mode console :
\begin{console}
>>> A = (-3,2)
>>> B = (5,-1)
>>> f(A,B)
(1.0, 0.5)
\end{console}

Expliquer alors ce que fait la fonction Python.

\item Qu'affiche alors la séquence d'instructions suivantes:
\begin{console}
>>> A = (9,1)
>>> B = (3,-5)
>>> f(A,B)
\end{console}
\end{enumerate}

\tcblower

\begin{enumerate}
\item En mode console, on définit la variable \texttt{A} par un couple de nombres : \texttt{(-3,2)}. Cela peut représenter les coordonnées d'un point $A$.

Dans ce cas, \texttt{A[0]} représenterait son abscisse (ici, $-3$) et \texttt{A[1]} son ordonnée (ici, $2$).

La fonction Python renvoie donc le couple $\coord{\dfrac{x_A+x_B}{2}}{\dfrac{y_A+y_B}{2}}$, c'est-à-dire les coordonnées du milieu de $[AB]$.

En l'occurrence, $\coord{\dfrac{x_A+x_B}{2}}{\dfrac{y_A+y_B}{2}}=\coord{\dfrac{-3+5}{2}}{\dfrac{2+(-1)}{2}}=\coord{1}{\dfrac{1}{2}}$.

Cela correspond bien au résultat affiché en mode console.

\newpage

\item La séquence d'instructions données dans l'énoncé signifie que l'on cherche les coordonnées du milieu de $[AB]$, avec $A\coord{9}{1}$ et $B\coord{3}{-5}$. On trouve:
\[
\coord{\dfrac{x_A+x_B}{2}}{\dfrac{y_A+y_B}{2}}=\coord{\dfrac{9+3}{2}}{\dfrac{1+(-5)}{2}}=\coord{6}{-2}.
\]
Ainsi, la fonction renvoie le résultat  suivant:
\begin{console}
>>> A = (9,1)
>>> B = (3,-5)
>>> f(A,B)
(6.0, -2.0)
\end{console}
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[1]
On considère la fonction Python suivante:
\begin{python}
def f(A,B):
    return ( (B[0] - A[0])**2 + (B[1] - A[1])**2 ) ** 0.5
\end{python}

\begin{enumerate}
\item On tape en mode console:
\begin{console}
>>> A = (-3,2)
>>> B = (5,-1)
>>> f(A,B)
8.54400374531753
\end{console}

Exécuter pas à pas la fonction Python et vérifier la valeur du résultat affiché.

\item À quoi correspond le résultat renvoyé par cette fonction ?
\end{enumerate}

\tcblower

\begin{enumerate}
\item Rappelons que \texttt{**0.5} signifie \og prendre la racine carrée \fg{} et que \texttt{**2} signifie \og prendre le carré \fg.

\medskip

On commence par définir la variable \texttt{A} par un couple de nombres \texttt{(-3,2)} qui peut correspondre à ses coordonnées. Il en est de même pour la variable \texttt{B}.

La fonction Python admet deux arguments \texttt{A} et \texttt{B}, et fait intervenir dans le calcul renvoyé les valeurs \texttt{A[0]} et \texttt{A[1]}, qui correspondent aux valeurs $-3$ et 2, ainsi que les valeurs \texttt{B[0]} et \texttt{B[1]}, qui correspondent aux valeurs $5$ et $-1$. Le calcul fait dans la fonction est donc:
\[
\sqrt{\big(5-(-3)\big)^2 + (-1-2)^2} = \sqrt{8^2+(-3)^2}=\sqrt{64+9}=\sqrt{73}\approx8,54400374531753.
\]
Ce résultat correspond bien à celui renvoyé par la fonction en mode console.

\item Nous avons vu à la question précédente que le nombre renvoyé correspondait à:
\[
\sqrt{(x_B-x_A)^2 + (y_B-y_A)^2}
\]
qui est la longueur $AB$.

\medskip

Ainsi, cette fonction renvoie la longueur $AB$, où les coordonnées de $A$ et $B$ sont mis en arguments.
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[1]
Le programme suivant affiche un couple de coordonnées \coord{x}{y}:
\begin{python}
def coord(A,B,C):
    return ( C[0] - B[0] + A[0] , C[1] - B[1] + A[1] )

A = (-3,2)
B = (2,-1)
C = (6,3)

print( coord(A,B,C) )
\end{python}

\begin{enumerate}
\item Quelles sont les valeurs $x$ et $y$ affichée ?
\item À quoi correspondent ces coordonnées ?
\end{enumerate}

\tcblower

\begin{enumerate}
\item Nous avons :

\vspace*{-2em}
\begin{center}
\begin{tabular}{|*6{>{\ttfamily}Sc|}}
\hline
A[0] & A[1] & B[0] & B[1] & C[0] & C[1] \\
\hline
-3 & 2 & 2 & -1 & 6  &3\\
\hline
\end{tabular}
\end{center}

La fonction calcule et affiche donc :

\begin{itemize}
\item \texttt{C[0] - B[0] + A[0] = 6 - 2 + (-3) = 1};
\item \texttt{C[1] - B[1] + A[1] = 3 - (-1) + 2 = 6}.
\end{itemize}

Le programme affiche donc : \texttt{(1, 6)}.

\item Appelons $D\coord{1}{6}$. En plaçant les points A, B, C et D dans un repère, on peut remarquer que ABCD semble être un parallélogramme, résultat que l'on peut démontrer en calculant les coordonnées des vecteurs :

\begin{itemize}
\item $\vv{AB}\dbinom{x_B-x_A}{y_B-y_A}\iff\vv{AB}\dbinom{5}{-3}$;
\item $\vv{DC}\dbinom{x_C-x_D}{y_C-y_D}\iff\vv{DC}\dbinom{5}{-3}$.
\end{itemize}

\medskip

L'égalité $\vv{AB}=\vv{DC}$ s'écrit aussi en coordonnées:
\[
\dbinom{x_B-x_A}{y_B-y_A} = \dbinom{x_C-x_D}{y_C-y_D}
\]
ou encore en égalités:
\[
\begin{cases}
x_B-x_A = x_C-x_D\\
y_B-y_A = y_C-y_D
\end{cases}
\]
ou encore:
\[
\begin{cases}
x_D = x_C - x_B + x_A\\
y_D = y_C - y_B + y_A
\end{cases}
\]
\og $x_C - x_B + x_A$ \fg{} correspond justement à \og \texttt{C[0] - B[0] + A[0]} \fg{} et \og $y_C - y_B + y_A$ \fg{} à \og \texttt{C[1] - B[1] + A[1]} \fg.

\medskip

Ainsi, la fonction renvoie les coordonnées d'un point $D$, où $ABCD$ est un parallélogramme.
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[1]
On considère la fonction Python suivante:
\begin{python}
def zone(A,B,r):
    return ( (B[0] - A[0])**2 + (B[1] - A[1])**2 )**0.5 <= r
\end{python}
\pagebreak
\begin{enumerate}
\item On tape en mode console:
\begin{console}
>>> A = (-3,5)
>>> B = (2,-1)
>>> zone(A,B,10)
True
>>> zone(A,B,5)
False
\end{console}

Expliquer par le calcul ces deux résultats.

\item Quel est le rôle de la fonction \texttt{zone(A,B,r)} ?
\end{enumerate}
\vspace*{-2em}

\tcblower

\begin{enumerate}
\item Commençons par définir les différentes valeurs:
\begin{center}
\begin{tabular}{|*4{>{\ttfamily}Sc|}}
\hline
A[0] & A[1] & B[0] & B[1]\\
\hline
-3&5&2&-1\\
\hline
\end{tabular}
\end{center}
On a alors:
\begin{center}
\begin{tabular}{*2{>{\ttfamily}Sl}}
& ( (B[0] - A[0])**2 + (B[1] - A[1])**2 )**0.5\\
= & ( (2-(-3))**2 + (-1-5)**2 )**0.5\\
= & (25 + 36)**0.5\\
= & 61**0.5\\
$\approx$ & 7.810249675906654
\end{tabular}
\end{center}

Ainsi, le test :
\begin{center}
\og \texttt{( (B[0] - A[0])**2 + (B[1] - A[1])**2 )**0.5 <= r} \fg{}
\end{center}
donne le résultat \og \texttt{True} \fg{} pour \texttt{r = 10}  car \texttt{7.810249675906654 <= 10}.

En revanche, le test renvoie \og \texttt{False} \fg{} pour \texttt{r = 5} car \texttt{7.810249675906654 > 5}.

\item La fonction renvoie le résultat du test:
\begin{center}
\texttt{( (B[0] - A[0])**2 + (B[1] - A[1])**2 )**0.5 <= r},
\end{center}
c'est-à-dire du test :
\begin{center}
\og $\sqrt{(x_B-x_A)^2+(y_B-y_A)^2}\leqslant r$ \fg,
\end{center}
 et donc du test:
 \begin{center}
 $AB \leqslant r$
 \end{center}
 
 La fonction a donc pour objectif de renvoyer \og \texttt{True} \fg{} si la longueur $AB$ est inférieure ou égale au nombre $r$, et \og \texttt{False} \fg{} dans le cas contraire.
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newpage

\begin{exocor}{}[2]
On considère la fonction suivante:
\begin{python}
def f(A,B,C):
    x = (B[0]-A[0])**2 + (B[1]-A[1])**2
    y = (C[0]-A[0])**2 + (C[1]-A[1])**2
    z = (C[0]-B[0])**2 + (C[1]-B[1])**2
    
    return (x + y == z) or (x + z == y) or (y + z == x)
\end{python}

\begin{enumerate}
\item En mode console, on tape:
\begin{console}
>>> A = (-3,-1)
>>> B = (4,5)
>>> C = (10,-2)
>>> f(A,B,C)
True
\end{console}

Expliquer ce résultat.

\item Quel est le rôle de cette fonction Python ?

\item Modifier cette fonction afin qu'elle renvoie la nature du triangle $ABC$ sous forme de chaîne de caractères (par exemple, \og Le triangle est rectangle isocèle \fg.
\end{enumerate}

\tcblower

\begin{enumerate}
\item En mode console, on définit trois points par leurs coordonnées.

Dans la fonction \texttt{f(A,B,C)}, on a :
\begin{itemize}
\item $x = (x_B-x_A)^2+(y_B-y_A)^2 = (4-(-3))^2 +(5-(-1))^2 = 49+36=85$;
\item $y = (x_C-x_A)^2+(y_C-y_A)^2 = (10-(-3))^2 +(-2-(-1))^2 = 169+1=170$;
\item $z = (x_C-x_B)^2+(y_C-y_B)^2 = (10-4)^2 +(-2-5)^2 = 36+49=85$.
\end{itemize}

\begin{itemize}
\item Le test \og \texttt{x + y == z} \fg{} donne \og \texttt{85 + 170 == 85} \fg{} et renvoie \og \texttt{False} \fg.
\item Le test \og \texttt{x + z == y} \fg{} donne \og \texttt{85 + 85 == 170} \fg{} et renvoie \og \texttt{True} \fg{} car l'égalité est vraie.
\item Le test \og \texttt{y + z == x} \fg{} donne \og \texttt{170 + 85 == 85} \fg{} et renvoie \og \texttt{False} \fg{} car l'égalité est fausse.
\end{itemize}

Ainsi, le test : {\ttfamily (x + y == z) or (x + z == y) or (y + z == x) }

est équivalent au test: {\ttfamily False or True or False}

et renvoie \og \texttt{True} \fg{} car au moins un test est vrai.

\item Dans l'exemple précédent, on peut remarquer que $x$, $y$ et $z$ représentent respectivement les longueurs $AB^2$, $AC^2$ et $BC^2$.

Le test effectué vérifie donc si $AB^2+AC^2=BC^2$, ou si $AB^2+BC^2=AC^2$ ou si\linebreak $AC^2+BC^2 =AB^2$ et renvoie \og \texttt{True} \fg{} si tel est le cas. 

Le rôle de la fonction Python est donc de vérifier si le triangle $ABC$ est rectangle.

\item Dans cette question, on souhaite modifier la fonction afin qu'elle affiche la nature du triangle ABC. Voici une proposition:
\begin{python}
def square(A,B,C):
    nature = 'Le triangle est'
    
    x = (B[0]-A[0])**2 + (B[1]-A[1])**2
    y = (C[0]-A[0])**2 + (C[1]-A[1])**2
    z = (C[0]-B[0])**2 + (C[1]-B[1])**2
    
    if (x + y == z) or (x + z == y) or (y + z == x):
        nature = nature + ' rectangle'
        
    if (x == y) and (x == z) and (y == z):
        nature  = nature + ' équilatéral'
        
    if (x == y) or (x == z) or (y == z):
        nature = nature + ' isocèle'
        
    if nature == 'Le triangle est':
        nature = nature + ' quelconque'
        
    return nature
\end{python}
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[3]
\'Ecrire une fonction Python \texttt{symétrique(A,O)} renvoyant les coordonnées du symétrique d'un point A par rapport à un autre point O.

\medskip

Tester cette fonction avec les points $A\coord{-3}{4}$ et $O\coord{0}{0}$.

\vspace*{-1em}

\tcblower

Notons $A'$ le symétrique de $A$ par rapport à $O$. Alors, $O$ est le milieu de [AA'] et donc:
\[
x_O = \frac{x_A + x_{A'}}{2} \qquad \text{soit}\qquad 2x_O = x_A + x_{A}\quad\text{soit}\quad x_{A'} = 2x_O - x_A.
\]
Il en est de même pour $y_{A'}$, d'où la fonction Python suivante:

\begin{python}
def symetrique(A,O):
    return (2 * O[0] - A[0] , 2 * O[1] - A[1] )
\end{python}

On a alors par exemple, en mode console:
\begin{console}
>>> A = (-3,4)
>>> O = (0,0)
>>> symetrique(A,O)
(3, -4)
\end{console}
\end{exocor}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newpage


\section*{Vecteurs}

\begin{exocor}{}[1]
On considère la fonction Python suivante:
\begin{python}
def f(A,B,C):
    AB = ( B[0] - A[0] , B[1] - A[1] )
    AC = ( C[0] - A[0] , C[1] - A[1] )
    
    k = AC[0] / AB[0]
    
    return k * AB[1] == AC[1]
\end{python}

\begin{enumerate}
\item En mode console, on tape:
\begin{console}
>>> A = (-3,-1)
>>> B = (3,2)
>>> C = (7,4)
>>> f(A,B,C)
True
\end{console}

Expliquer ce résultat.

\item Quel est le rôle de cette fonction ?
\end{enumerate}
\vspace*{-2em}

\tcblower

\begin{enumerate}
\item Commençons par voir la valeur des variables:
\begin{center}
\begin{tabular}{|*6{>{\ttfamily}Sc|}}
\hline
A[0] & A[1] & B[0] & B[1] & C[0] & C[1] \\
\hline
-3&-1&3&2&7&4\\
\hline
\end{tabular}
\end{center}
Ainsi,
\begin{itemize}
\item La variable \texttt{AB} vaut : 
\begin{center}
\ttfamily
AB = ( B[0] - A[0] , B[1] - A[1] ) = (3-(-3) , 2-(-1)) = (6, 3).
\end{center}

\item La variable \texttt{AC} vaut : 
\begin{center}
\ttfamily\small
AC = ( C[0] - A[0] , C[1] - A[1] ) = (7-(-3) , 4-(-1)) = (10, 5).
\end{center}

\item La variable \texttt{k} vaut donc:
\begin{center}
\ttfamily
k = AC[0] / AB[0] = 10 / 6 = 5 / 3.
\end{center}
\end{itemize}

Donc,
\begin{center}
\ttfamily
k * AB[1] = $\dfrac{5}{3} \times 3 = 5$ = AC[1]
\end{center}
donc le test
\begin{center}
\ttfamily
k * AB[1] == AC[1]
\end{center}
renvoie \og \texttt{True} \fg.

\item À travers l'exemple précédent, on peut voir que la variable \texttt{AB} représente les coordonnées du vecteur $\vv{AB}$ et que \texttt{AC}, celles de $\vv{AC}$.

Le test \og \texttt{k * AB[1] == AC[1]} \fg{} vérifie quant à lui si les coordonnées sont proportionnelles, et donc si les vecteurs sont colinéaires, auquel cas la fonction renvoie \og \texttt{True} \fg. Et si tel est le cas, cela signifie que les points $A$, $B$ et $C$ sont alignés.

\medskip

Ainsi, la fonction a pour rôle de dire si les points $A$, $B$ et $C$ sont alignés. 
\end{enumerate}
\end{exocor}

%%%

\begin{exocor}{}[1]
On considère le programme suivant:
\begin{python}
A = (0,2)   # point A, de coordonnées (0;2)
B = (5,-1)  # point B, de coordonnées (5;-1)
C = (10,-4) # point C, de coordonnées (10;-4)
AB = ( B[0] - A[0] , B[1] - A[1] )
AC = ( C[0] - A[0] , C[1] - A[1] )
d = AB[0] * AC[1] - AB[1] * AC[0]

if d == 0:
    print('Les points A, B et C sont alignés.')
else:
    print('Les points A, B et C ne sont pas alignés.')
\end{python}

\begin{enumerate}
\item Expliquer ce que représente les variables \texttt{AB} et \texttt{AC}.
\item Expliquer alors ce que représente la variable \texttt{d}.
\item Qu'affiche alors ce programme ?
\end{enumerate}
\vspace*{-2em}

\tcblower

\begin{enumerate}
\item La variable \texttt{AB} est définie par un couple de nombres : d'une part \texttt{B[0] - A[0]}, d'autre part \texttt{B[1] - A[1]}, c'est-à-dire respectivement $x_B-x_A$ et $y_B-y_A$.

Ainsi, \texttt{AB} représente le vecteur $\vv{AB}$ à l'aide de ses coordonnées.

De même, \texttt{AC} représente le vecteur $\vv{AC}$ à l'aide de ses coordonnées.

\item Notons $\vv{AB}\dbinom{x}{y}$ et $\vv{AC}\dbinom{x'}{y'}$. La variable \texttt{d} prend donc la valeur $xy'-x'y$, c'est-à-dire $\det\big(\vv{AB};\vv{AC}\big)$.

\item Le programme teste donc si $\det\big(\vv{AB};\vv{AC}\big)=0$ (ligne 10), auquel cas il affiche \og Les points A, B et C sont alignés. \fg) ou si $\det\big(\vv{AB};\vv{AC}\big)\neq0$ (ligne 12), auquel cas il affiche \og Les points A, B et C ne sont pas alignés. \fg.

\medskip

En l'occurrence, $\det\big(\vv{AB};\vv{AC}\big)=5\times(-6) - (-3)\times10 = -30+30=0$, donc il affiche :
\begin{console}
Les points A, B et C sont alignés.
\end{console}
\end{enumerate}
\end{exocor}

%%%

\begin{exocor}{}[1]
On considère le programme suivant:
\begin{python}
def isit(A,B,C,D):
    AB = ( B[0] - A[0] , B[1] - A[1] )
    DC = ( C[0] - D[0] , C[1] - D[1] )
    
    return AB == DC
\end{python}

\begin{enumerate}
\item Qu'obtient-on en tapant en mode console ce qui suit ?
\begin{console}
>>> A = (-5,1)
>>> B = (-2,3)
>>> C = (3,3)
>>> D = (0,1)
>>> isit(A,B,C,D)
\end{console}

\item À quoi correspond le résultat affiché ?
\end{enumerate}
\vspace*{-2em}

\tcblower

\begin{enumerate}
\item Dans cette question, on définit quatre points : A\coord{-5}{1}, B\coord{-2}{3}, C\coord{3}{3} et D\coord{0}{1}.

On a alors:

\begin{center}
\begin{tabular}{|*8{>{\ttfamily}Sc|}}
\hline
A[0] & A[1] & B[0] & B[1] & C[0] & C[1] & D[0] & D[1] \\
\hline
-5&1&-2&3&3&3&0&1\\
\hline
\end{tabular}
\end{center}

D'où:

\begin{center}
\begin{tabular}{|*4{>{\ttfamily}Sc|}}
\hline
AB[0] & AB[1] & DC[0] & DC[1] \\
\hline
3&2&3&2\\
\hline
\end{tabular}
\end{center}

Ainsi, les variables \texttt{AB} et \texttt{AD} contiennent les mêmes valeurs. Le programme affiche donc:
\begin{console}
True
\end{console}

\item Le test de la fonction est basé sur la valeur des coordonnées des deux vecteurs $\vv{AB}$ et $\vv{DC}$. Si les deux vecteurs sont égaux, la fonction retourne \og True \fg, sinon elle retourne \og False \fg. Or, $\vv{AB}=\vv{DC} \iff ABCD \text{ est un parallélogramme}$.

Ainsi, la fonction \texttt{isit(A,B,C,D)} retourne \og True  \fg{} si $ABCD$ est un parallélogramme, et \og False \fg{}  dans le cas contraire.
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[2]
On considère le vecteur $\vv{u}\dbinom{-3}{2}$ et le point A\coord{5}{2}. On cherche à placer un point B, d'abscisse 20, de sorte que $\vv{AB}$ et $\vv{u}$ soient colinéaires. Pour cela, on considère le programme Python suivant :

\begin{python}
u, A = (-3,2), (5,2) # vecteur u(-3,2) et point A(5,2)

def colinear(v,w):
    return v[0]*w[1] - v[1]*w[0] == 0

def vect(M,N):
    return ( N[0]-M[0] , N[1]-M[1] )

y = 2

while not colinear(u,vect(A,(20,y))):
    y = y - 1
    
print(y)
\end{python}

\begin{enumerate}
\item Expliquer ce que renvoie la fonction \texttt{colinear(v,w)}.

\item Expliquer ce que renvoie la fonction \texttt{vect(M,N)}.

\item Expliquer la boucle conditionnelle de la ligne 11.
\end{enumerate}
\vspace*{-2em}

\tcblower

\begin{enumerate}
\item Dans la fonction \texttt{colinear(v,w)}, la variable \texttt{v[0]*w[1] - v[1]*w[0]} représente le déterminant des vecteurs représentés par \texttt{v} et \texttt{w}.

La fonction renvoie le résultat du test \og \texttt{v[0]*w[1] - v[1]*w[0] == 0} \fg, dont retourne \og True \fg{} si ce déterminant est nul, c'est-à-dire si les vecteurs sont colinéaires. Elle renvoie \og False \fg{} dans le cas contraire.

\medskip

Ainsi, la fonction teste si les vecteurs sont colinéaires et renvoie le résultat.

\item La fonction \texttt{vect(M,N)} renvoie un couple de nombres: \texttt{N[0]-M[0]} et \texttt{N[1]-M[1]}, qui correspondent respectivement à l'abscisse et à l'ordonnée du vecteur $\vv{MN}$.

Ainsi, cette fonction renvoie les coordonnées de $\vv{MN}$.

\item À la ligne 13, la condition de la boucle est que $\vv{u}$ et $\vv{AB}$ ne doivent pas être colinéaires.

Ainsi, les instructions de cette boucle sont exécutées tant que $\vv{u}$ et $\vv{AB}$ ne sont pas colinéaires. Dans ce cas, on enlève \og 1 \fg{} à la valeur de la variable \texttt{y}.

Finalement, le programme affiche \og \texttt{-8} \fg, ce qui signifie que pour B\coord{20}{-8}, $\vv{AB}$ et $\vv{u}$ sont colinéaires.
\end{enumerate} 
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[3]
On considère trois points A\coord{x_A}{y_A}, B\coord{x_B}{y_B} et C\coord{x_C}{y_C}. On cherche une formule permettant de trouver les coordonnées du point D tel que ABCD est un parallélogramme. On part du principe que si tel est le cas, alors $\vv{AB}=\vv{DC}$.

\begin{enumerate}
\item Montrer alors que $\begin{cases}
x_D & = x_C + x_A - x_B\\
y_D & = y_C + y_A - y_B
\end{cases}$.

\item \'Ecrire alors une fonction Python nommée \texttt{sommet(A,B,C)} qui renvoie les coordonnées du point D, où les arguments \texttt{A}, \texttt{B} et \texttt{C} sont définis par leurs coordonnées (par exemple, \texttt{A = (-3,2)}).

\item Tester avec les points A\coord{-3}{2}, B\coord{5}{-2} et C\coord{4}{1}.
\end{enumerate}

\tcblower

\begin{enumerate}
\item $\begin{aligned}[t]
\vv{AB}=\vv{DC} & \iff \dbinom{x_B-x_A}{y_B-y_A}=\dbinom{x_C-x_D}{y_C-y_D}\\
& \iff \begin{cases}
x_B-x_A=x_C-x_D\\
y_B-y_A=y_C-y_D
\end{cases}\\
& \iff \begin{cases}
x_B-x_A-x_C=-x_D\\
y_B-y_A-y_C=-y_D
\end{cases}\\
& \iff
\begin{cases}
x_D = x_C+x_A-x_B\\
y_D = y_C+y_A-y_B
\end{cases}\\
&\text{(en multipliant par $-1$ de part et d'autre du signe \og $=$ \fg)} 
\end{aligned}$

\item On peut alors écrire la fonction demandée en nous aidant de ce qui vient d'être obtenu:

\begin{python}
def sommet(A,B,C):
    return ( C[0] + A[0] - B[0] , C[1] + A[1] - B[1] )
\end{python}

\begin{rem}
Les parenthèses ne servent pas à grand-chose lors du renvoi des coordonnées du point D. On peut les mettre où ne pas les mettre.
\end{rem}
\newpage
\item Testons avec les points A\coord{-3}{2}, B\coord{5}{-2} et C\coord{4}{1}.

\begin{console}
>>> A = (-3,2)
>>> B = (5,-2)
>>> C = (4,1)
>>> sommet(A,B,C)
(-4, 5)
\end{console}

On vérifie que ces coordonnées sont correctes car si D\coord{-4}{5} alors $\vv{DC}\dbinom{8}{-4}$ et $\vv{AB}\dbinom{8}{-4}$.
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[1]
\'Ecrire une fonction Python \texttt{somme(u,v)} qui renvoie les coordonnées du vecteur $\vv{u}+\vv{v}$, où \texttt{u} et \texttt{v} sont définis par leurs coordonnées (par exemple, \texttt{u = (5,-2)} pour le vecteur $\vv{u}\dbinom{5}{-2}$).

\tcblower

Une fonction possible est la suivante :

\begin{python}
def somme(u,v):
    return u[0]+v[0] , u[1]+v[1]
\end{python}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section*{\'Equations de droites}

\begin{exocor}{}[2]
Le programme suivant retourne les valeurs de $m$ et $p$ de l'équation $y=mx+p$, équation de la droite $(AB)$:
\begin{python}
def reduite(A,B):
    m = ( B[1] - A[1] ) / ( B[0] - A[0] )
    p = A[1] - m*A[0]
    
    return m, p
\end{python}

\begin{enumerate}
\item Expliquer les deux premières lignes de cette fonction.

On suppose ici que les arguments de la fonction représentent les points  définis par leurs coordonnées (par exemple, \texttt{A = (-3,2)} représente le point A\coord{-3}{2}).


\item En déduire une fonction \texttt{cartesienne(A,B)} qui renvoie $a$, $b$ et $c$ de l'équation $ax+by+c=0$ représentant la droite $(AB)$ (on pourra donc faire appel à la fonction \texttt{reduite(A,B)}).
\end{enumerate}

\tcblower

\begin{enumerate}
\item Pour connaître l'équation réduite d'une droite $(AB)$ connaissant les coordonnées des points $A$ et $B$, on doit d'abord calculer sa \textit{pente} $m$ avec la formule du cours:
\[
m = \dfrac{y_B-y_A}{x_B-x_A}.
\]
En python, cette formule se traduit par :
\begin{console}
m = ( B[1] - A[1] ) / ( B[0] - A[0] )
\end{console}
car \texttt{B[0]} et \texttt{B[1]} représentent respectivement $x_B$ et $y_B$ (de même pour le point $A$).

\medskip

Une fois la pente connue, on remplace $x$ et $y$ par les coordonnées d'un point ($A$ par exemple) dans l'équation réduite :
\[
y_A = mx_A + p \iff p = y_A - mx_A
\]
qui se traduit en Python par:
\begin{console}
p = A[1] - m*A[0]
\end{console}


\item Connaissant l'équation réduite $y=mx+p$ d'une droite, il est facile d'obtenir une équation cartésienne en écrivant:
\[
y=mx+p \iff mx - y + p = 0
\]
Ainsi, $a=m$, $b=-1$ et $c=p$ et on peut alors avoir la fonction suivante:
\begin{python}
def cartesienne(A,B):
     m, p = reduite(A,B)
     return m, -1, p
\end{python}
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[2]
On souhaite écrire une fonction Python \texttt{cartesienne(u,A)} qui renvoie une équation cartésienne de la droite $(d)$ passant par $A$, représenté par une variable \texttt{A = ( A[0] , A[1] )}, et de vecteur directeur $\vv{u}$, représenté par une variable \texttt{u = ( u[0] , u[1] )}.

Pour cela, on exploite le fait que pour tout point $M$ du plan, $\vv{u}$ et $\vv{AM}$ sont colinéaires, et donc que leur déterminant est nul.

\begin{enumerate}
\item Exprimer alors les nombres $a$, $b$ et $c$ dans l'équation $ax+by+c=0$ de $(d)$ en fonction des coordonnées de $A$ et $\vv{u}$.
\item \'Ecrire alors la fonction Python \texttt{cartesienne(u,A)} demandée.
\end{enumerate}
\vspace*{-2em}

\tcblower

\begin{enumerate}
\item Posons $A\coord{x_A}{y_A}$ et $\vv{u}\dbinom{\alpha}{\beta}$. On considère alors $M\coord{x}{y}\in(d)$.

\begin{align*}
\vv{u}\text{ et }\vv{AM}\text{ colinéaires }
& \iff \begin{vmatrix}
\alpha & x-x_A\\
\beta  & y-y_A
\end{vmatrix}=0\\
& \iff \alpha(y-y_A) - \beta(x-x_A)=0\\
& \iff \alpha y - \alpha y_A - \beta x + \beta x_A = 0\\
& \iff -\beta x + \alpha y + \beta x_A - \alpha y_A = 0
\end{align*}

Ainsi, $a=-\beta$, $b=\alpha$ et $c=\beta x_A - \alpha y_A$.

\item À l'aide de ces égalités, on peut écrire la fonction Python suivante:

\begin{python}
def cartesienne(u,A):
     a = -u[1]
     b = u[0]
     c = u[1]*A[0] - u[0]*A[1]
     
     return a, b, c
\end{python}
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[2]
On donne le programme suivant:
\begin{python}
def det(u,v):
    return u[0]*v[1] - u[1]*v[0]

def intersection(D,d):
    # D = (a , b, c) représente la droite d'équation ax + by + c = 0
    # d = (a' , b' , c') représente la droite d'équation a'x + b'y + c' = 0
    u = ( d[0] , d[1] )
    v = ( D[0] , D[1] )
    determinant = det(u,v)
    if determinant == 0:
        if d[0] / D[0] == d[2] / D[2]:
            return 'Droites confondues'
        else:
            return 'Droites strictement parallèles'
    else:
        vx = (D[0],d[0])
        vy = (D[1],d[1])
        vc = (-D[2] , -d[2])
        x = det( vy , vc ) / determinant
        y = -det( vx , vc ) / determinant
        return x,y
\end{python}

On considère les droites $(D)$ d'équation cartésienne $x+y+3=0$, et $(d)$ d'équation cartésienne $6x-7y+7=0$.
\enlargethispage*{7em}
\begin{enumerate}
\item Déterminer les coordonnées du point d'intersection de ces droites.
\item \begin{minipage}[t]{0.75\linewidth}
En mode console, on tape:
\begin{console}
>>> D = (1,1,3)
>>> d = (6,-7,7)
>>> intersection(D,d)
(-2.1538461538461537, -0.8461538461538461)
\end{console}
\end{minipage}
\hfill
\begin{minipage}[t]{0.2\linewidth}
Interpréter ce\\ résultat.
\end{minipage}
\vspace*{-2em}
\end{enumerate}

\tcblower

\begin{enumerate}
\item Pour déterminer les coordonnées du point d'intersection des droites, on peut résoudre le système formé par les deux équations cartésiennes.
\begin{itemize}
\item Pour trouver $y$:
\begin{align*}
\systeme{x+y=-3@(E_1),6x-7y=-7@(E_2)}
& \iff \systeme{-6x-6y=18@(L_1)\leftarrow-6(E_1),6x-7y=-7@(L_2)\leftarrow(E_2)}\\
& \iff \systeme{x+y=-3@(E_1),-13y=11@(L_1)+(L_2)}\\
& \iff \systeme{x+y=-3,y=-\frac{11}{13}}
\end{align*}

\item Pour trouver $x$:
\begin{align*}
\systeme{x+y=-3@(E_1),6x+7y=-7@(E_2)}
& \iff \systeme{7x-7y=-21@(L_1)\leftarrow7(E_1),6x-7y=-7@(L_2)\leftarrow(E_2)}\\
& \iff \systeme{x+y=-3@(E_1),13x=-28@(L_1)+(L_2)}\\
& \iff \systeme{x+y=-3,x=-\frac{28}{13}}
\end{align*}
\end{itemize}

Finalement, le point d'intersection des droites a pour coordonnées \coord{-\dfrac{28}{13}}{-\dfrac{11}{13}}.

\item $-\dfrac{28}{13}\approx-2,1538\ldots$ et $-\dfrac{11}{13}\approx-0,846154\ldots$, ce qui correspond aux valeurs renvoyées par la fonction.

On peut donc supposer que cette fonction renvoie les valeurs approchées des coordonnées du point d'intersection de deux droites.

\begin{rem}
Cette fonction a en effet été écrite pour répondre à cette problématique. Elle permet de vérifier si deux droites sont strictement parallèles ou confondues (en calculant le déterminant de leur vecteur directeur) et , dans la négative, de calculer les coordonnées de leur point d'intersection à l'aide de formules que l'on appelle \textit{formules de Cramer} (qui ne sont pas du tout au programme du lycée).
\end{rem}

On peut utiliser cette fonction pour résoudre n'importe quel autre système de deux équations à deux inconnues. Par exemple, si on souhaite résoudre le système:
\[
\systeme{3x-5y=8,7x+3y=4}
\]
il suffira d'écrire:
\begin{console}
>>> D = (3,-5,-8)
>>> d = (7,3,-4)
>>> intersection(D,d)
(1.0, -1.0)
\end{console}
qui signifie que $\coord{1}{-1}$ est la solution au système.
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[2]
\begin{enumerate}
\item En Python, on souhaite définir une droite dont on connaît un vecteur directeur $\vv{u}\dbinom{-3}{2}$ et passant par le point $A\coord{1}{-5}$. Pour cela, on écrit:
\begin{console}
>>> u = (-3, 2)
>>> A = (1, -5)
>>> d = (u, A)
>>> d
((-3, 2), (1, -5))
>>> d[...][...]
1
\end{console} 

Que doit-on écrire à la place des pointillés pour obtenir \og 1 \fg{}  ?

\item On souhaite désormais écrire une fonction \texttt{appartient(droite,point)} qui renvoie \og True \fg{} si le point mis en argument appartient à la droite mise en argument, droite définie comme précédemment.

Proposer une telle fonction.

\item Tester la fonction avec les points $B\coord{4}{-7}$ et $C\coord{6}{-8}$.
\end{enumerate}

\tcblower

\begin{enumerate}
\item La variable \texttt{d} est un 2-uplet, mais la première composante \texttt{d[0]} est aussi un 2-uplet: les coordonnées du vecteur. De même, \texttt{d[1]} est un 2-uplet: les coordonnées du point.

Ainsi, l'abscisse du point $A$ est la première composante de \texttt{d[1]}: c'est donc \texttt{d[1][0]}.

Le tableau suivant nous donne les différentes valeurs:
\begin{center}
\begin{tabular}{|*4{>{\ttfamily}Sc|}}
\hline
d[0][0] & d[0][1] & d[1][0] & d[1][1] \\
\hline
-3 & 2 & 1 & -5\\
\hline
\end{tabular}
\end{center}

\item Avant d'écrire la fonction, il faut se demander à quelle condition le point mis en argument appartient à la droite.

Supposons, comme dans la question précédente, que l'on ait défini une droite $(d)$ à partir d'un vecteur directeur $\vv{u}\dbinom{x}{y}$ et d'un point $A\coord{x_A}{y_A}$ par lequel elle passe.

Pour qu'un point $B\dbinom{x_B}{y_B}$ appartienne à $(d)$, il faut que $\vv{u}$ et $\vv{AB}$ soient colinéaires, et donc que leur déterminant soit nul.

Cela donne lieu au code suivant:
\begin{python}
def appartient(d, B):
    vecteur_AB = ( B[0]-d[1][0] , B[1]-d[1][1] )
    vecteur_u = ( d[0][0] , d[0][1] )
    determinant = vecteur_AB[0]*vecteur_u[1] - vecteur_AB[1]*vecteur_u[0]
    return determinant == 0
\end{python}

\begin{itemize}
\item On commence par définir le vecteur $\vv{AB}$. \texttt{B[0]} est l'abscisse de $B$ et \texttt{d[1][0]}, celle de $A$ donc \texttt{B[0]-d[1][0]} représente $x_B-x_A$, c'est-à-dire l'abscisse du vecteur $\vv{AB}$. Il en est de même pour les ordonnées.

\item Ensuite, on définit le vecteur directeur de la droite, en reprenant les données mises en argument de la fonction Python. On aurait pu s'en passer, mais j'ai préféré définir cette variable pour un peu plus de compréhension dans le calcul du déterminant à la ligne suivante.

\item Le calcul du déterminant s'effectue à l'aide de la formule $\begin{vmatrix}x & x'\\y & y'\end{vmatrix}=xy'-yx'$.

\item On finit par renvoyer le résultat du test \og \texttt{determinant == 0} \fg: si le déterminant est nul, c'est-à-dire si l'égalité est vraie (donc si le point appartient à la droite), alors la fonction renvoie \og True \fg, sinon elle renvoie \og False \fg.
\end{itemize}

\item Testons cette fonction avec les deux points donnés dans l'énoncé:
\begin{console}
>>> B = (4, -7)
>>> appartient(d,B)
True
>>> C = (6, -8)
>>> appartient(d,C)
False
\end{console}

Le point $B$ appartient bien à $(d)$, mais pas le point $C$.
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section*{Fonctions}

\begin{exocor}{}[1]
\'Ecrire, à l'aide d'une boucle, un programme Python permettant d'afficher les images des nombres entiers de 0 à 10 par la fonction $f$ définie par $f(x)=3x+5$.

\tcblower

Les entiers de 0 à 10 sont représentés par \texttt{range(11)}. Pour obtenir leur image par la fonction $f(x)=3x+5$, on peut donc écrire:
\begin{python}
for x in range(11):
    print(3*x+5)
\end{python}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[1]
\'Ecrire, à l'aide d'une boucle, un programme Python permettant d'afficher les images des nombres entiers de $-10$ à 10 par la fonction $f$ définie par $f(x)=3x+5$.

\tcblower

Il y a très peu de changements par rapport à la solution proposée dans l'exercice précédent:

\begin{python}
for x in range(-10,11):
    print(3*x+5)
\end{python}

On aurait aussi pu utiliser une boucle conditionnelle:
\begin{python}
x = -10
while x <= 10:
    print(3*x+5)
    x = x + 1
\end{python}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[2]
\'Ecrire, à l'aide d'une boucle, un programme Python permettant d'afficher les images des nombres de $-1$ à 1, avec un pas de 0,1, par la fonction $f$ définie par $f(x)=3x+5$.

\tcblower

%La difficulté réside ici dans le fait que le pas entre chaque antécédent n'est pas \og 1 \fg{} mais \og 0,1 \fg. Or, 
On ne peut pas ici utiliser la fonction \texttt{range} pour laquelle les nombres sont entiers.

On peut donc passer par une boucle conditionnelle:

\begin{python}
x = -1
while x <= 1:
    print(3*x+5)
    x = x + 0.1
\end{python}

Remarquons toutefois que les résultats obtenus sont quelques fois étranges :

\begin{multicols}{3}
\begin{console}
2
2.3
2.5999999999999996
2.9
3.1999999999999997
3.4999999999999996
3.8
\end{console}

\columnbreak

\begin{console}
4.1
4.3999999999999995
4.699999999999999
5.0
5.3
5.6
5.8999999999999995
\end{console}

\columnbreak

\begin{console}
6.199999999999999
6.5
6.8
7.1
7.3999999999999995
7.699999999999999
7.999999999999999
\end{console}
\end{multicols}

À chaque fois qu'un résultat est affiché avec une partie décimale comportant beaucoup de \og 9 \fg, cela signifie qu'il y a une erreur d'approximation (due à la façon donc Python représente les nombres flottants, donc avec une virgule).

%Il faut donc garder à l'esprit que les résultats sont des \textit{représentations} de nombres...
%\begin{center}
%\begin{minipage}{0.73\linewidth}
%\includegraphics[width=0.97\linewidth]{magritte}
%\end{minipage}
%\begin{minipage}{0.26\linewidth}
%René Magritte,\\
%\textit{La Trahison des Images}, 1928
%\end{minipage}
%\end{center}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newpage
\begin{exocor}{}[2]
On considère les fonctions $f\;:\;x\mapsto -0,2x^3 + 0,1x^2 - 0,3x + 2$ et $g\;:\;x\mapsto 0,3x^3 - 0,5x -1$.

Pour tracer la représentation graphique de ces deux fonctions, on utilise le code suivant :
\begin{python}
from matplotlib.pyplot import plot, show, grid, subplots, axhline, axvline
from numpy import linspace

x = linspace(-5, 5, 100)
y = -0.2*x**3 + 0.1*x**2- 0.3*x + 2
z = 0.3*x**3 - 0.5*x - 1

fig, ax = subplots(figsize=(5, 5))
ax.set_ylim(-5,5)
plot(x,y)
plot(x,z)
grid(linestyle='--')

axhline(y=0, color='black', linestyle='-')
axvline(x=0, color='black', linestyle='-')

show()
\end{python}
qui produit l'image suivante:
\begin{center}
\includegraphics[scale=0.8]{courbe-2nde-exo.jpg}
\end{center}
Que faut-il changer à ce code pour produire une représentation de ces fonctions sur \intervFF{1}{3} afin d'avoir une meilleure vue du point d'intersection des deux courbes ?

\tcblower

Je propose le code suivant:

\begin{python}
from matplotlib.pyplot import plot, show, grid, subplots, axhline, axvline
from numpy import linspace

x = linspace(1, 3, 100)
y = -0.2*x**3 + 0.1*x**2- 0.3*x + 2
z = 0.3*x**3 - 0.5*x - 1

fig, ax = subplots(figsize=(2, 1))
ax.set_ylim(0,1)
plot(x,y)
plot(x,z)
grid(linestyle='--')

axhline(y=0, color='black', linestyle='-')
axvline(x=0, color='black', linestyle='-')

show()
\end{python}
qui produit:
\begin{center}
\includegraphics[scale=1]{courbe-2nde-exo-corrige.jpg}
\end{center}
J'ai ici changé les nombres à la ligne 4 pour signifier que je ne voulais trouver les images que des valeurs comprises entre 1 et 3 (avec un pas de 1 centième), puis la ligne 9 pour spécifier que je ne voulais tracer les deux courbes que pour des $y$ de 0 à $1$.

Bien sûr, vous pouvez mettre les nombres que vous voulez. 

\vspace*{1cm}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newpage

\section*{Fonctions de référence}

\begin{exocor}{}[2]
Le code Python suivant :
\begin{python}
from matplotlib.pyplot import plot, show, grid, axhline, axvline
from numpy import linspace

x = linspace(-10, 10, 100)
y = x**2

plot(x,y)
grid()
show()
\end{python}

permet d'obtenir la courbe représentative de la fonction carré sur \intervFF{-10}{10}.
\begin{center}
\includegraphics[scale=1]{courbe_carre_exo.jpg}
\end{center}

\begin{enumerate}
\item Compléter ce programme afin de visualiser la partie de la courbe telle que $x^2 \leqslant 49$ (on la représentera en rouge).
\item Compléter ce programme afin de visualiser la partie de la courbe telle que $x^2 \geqslant 25$ (on la représentera en rouge).
\end{enumerate}

\tcblower

\begin{enumerate}
\item La partie de la courbe telle que $x^2\leqslant49$ est la partie de la courbe telle que $-7 \leqslant x \leqslant 7$, d'où le programme suivant:


\begin{python}
from matplotlib.pyplot import plot, show, grid, axhline, axvline
from numpy import linspace

x = linspace(-10, 10, 100)
y = x**2

plot(x,y)
grid()

# partie de la courbe telle que x*x < 49

x = linspace(-7, 7, 100)
y = x**2

plot(x,y,color='red')

# fin de la représentation de la partie de la courbe

axhline(y=0, color='black', linestyle='-')
axvline(x=0, color='black', linestyle='-')

show()
\end{python}

qui affiche:

\begin{center}
\includegraphics[scale=0.8]{courbe_carre_exo_corr.jpg}
\end{center}

\newpage

\item La partie de la courbe telle que $x^2\geqslant25$ est la partie de la courbe telle que $x \leqslant -5$ et $x \geqslant 5$, d'où le programme suivant:
\begin{python}
from matplotlib.pyplot import plot, show, grid, axhline, axvline
from numpy import linspace

x = linspace(-10, 10, 100)
y = x**2

plot(x,y)
grid()

# partie de la courbe telle que x*x > 25

x1 = linspace(-10, -5, 100)
y1 = x1**2
x2 = linspace(5, 10, 100)
y2 = x2**2
plot(x1,y1,color='red')
plot(x2,y2,color='red')

# fin de la représentation de la partie de la courbe

axhline(y=0, color='black', linestyle='-')
axvline(x=0, color='black', linestyle='-')
show()
\end{python}
qui affiche:
\begin{center}
\includegraphics[scale=0.8]{courbe_carre_exo_corr2.jpg}
\end{center}
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newpage
\begin{exocor}{}[2]
Modifier programme de l'exercice précédent afin qu'il affiche la courbe représentative de la fonction inverse sur \intervFF{-3}{3}, ainsi que la partie correspondant à $-2<\dfrac{1}{x}<2$.

\tcblower

Pour le tracé de la fonction inverse, je choisis de limiter l'affichage en $y$ (car quand on est proche de 0, $\frac{1}{x}$ est très grand dans les positifs comme dans les négatifs).

Pour cela, je fais appel à la fonction \texttt{ylim(a,b)} de sorte que les images affichées soient entre $a$ et $b$.

\medskip

Pour que $-2 < \dfrac{1}{x} < 2$, il faut que $-\dfrac{1}{2}<x<\frac{1}{2}$.

\begin{python}
from matplotlib.pyplot import plot, show, grid, axhline, axvline, ylim
from numpy import linspace

x = linspace(-3, 3, 100)
y = 1/x
plot(x, y)
grid()

x = linspace(-0.5, 0.5, 100)
y = 1/x
plot(x, y, color='red')

# Limiter l'affichage des y entre -5 et 5
ylim(-5, 5)

axhline(y=0, color='black', linestyle='-')
axvline(x=0, color='black', linestyle='-')
show()
\end{python}
qui affiche:
\begin{center}
\includegraphics[scale=0.9]{courbe_inverse_exo.jpg}
\end{center}

\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section*{Statistiques}

\begin{rem}
Les listes ne sont pas officiellement au programme de maths en Seconde. Cependant, nous allons les utiliser dans cette section ainsi que dans la suivante.
\end{rem}

\begin{exocor}{}[3]
Voici un algorithme:
\begin{center}
\fbox{\begin{minipage}{0.6\linewidth}
\ttfamily
L est la liste de nombres [ 3, 5, 1 ]\\
N est un nombre entier\\
i est un nombre entier\\
j est un nombre entier\\
a est un nombre réel\\
m est un nombre réel\\
indice est un nombre entier\\
N $\leftarrow$ longueur de L\\
Pour i variant de 0 à N-1:\\
\hspace*{5mm} m $\leftarrow$ L[i]\\
\hspace*{5mm} indice $\leftarrow$ i\\
\hspace*{5mm} Pour j variant de i+1 à N-1:\\
\hspace*{10mm} Si L[j]<m:\\
\hspace*{15mm} m $\leftarrow$ L[j]\\
\hspace*{15mm} indice $\leftarrow$ j\\
\hspace*{10mm} Fin du Si\\
\hspace*{5mm} Fin du Pour j\\
\hspace*{5mm} a $\leftarrow$ L[i]\\
\hspace*{5mm} L[i] $\leftarrow$ L[indice]\\
\hspace*{5mm} L[indice] $\leftarrow$ a\\
Fin du Pour i\\
Afficher L
\end{minipage}}
\end{center}
\begin{enumerate}
\item \'Ecrire le programme Python qui correspond à cet algorithme.

\item En exécutant ce programme, il affiche: \og \texttt{[1, 3, 5]} \fg.

Que semble-t-il faire ?

\item Modifier ce programme afin de déterminer et d'afficher la médiane de la série statistique entrée dans L.
\end{enumerate}

\tcblower


\begin{enumerate}
\item Le programme Python correspondant à l'algorithme est par exemple le suivant:

\begin{python}
L = [ 3,5,1 ]
for i in range(len(L)):
    m = L[i]
    indice = i
    for j in range(i+1,len(L)):
        if L[j] < m:
            m = L[j]
            indice = j
    a = L[i]
    L[i] = L[indice]
    L[indice] = a
    
print(L)
\end{python}

\texttt{len(L)} désigne la longueur de la liste \texttt{L}.

\item Le programme affiche la liste :
\begin{console}
[1,3,5]
\end{console}
Il semble donc trier dans l'ordre croissant les données de la liste entrée.

\item  Un programme possible est :
\begin{python}
L = [ 8 , 6 , 2 , 2 , 9 , 2 , 7 , 10 ]
for i in range(len(L)):
    m = L[i]
    indice = i
    for j in range(i+1,len(L)):
        if L[j] < m:
            m = L[j]
            indice = j
    a = L[i]
    L[i] = L[indice]
    L[indice] = a

if len(L) % 2 == 1:
    mediane = L[ len(L) // 2 ]
else:
    mediane = ( L[ len(L) // 2 ] + L[ len(L) // 2 + 1 ] ) / 2
    
print(L)
print('Médiane : ',mediane)
\end{python}

\newpage

Le début reste inchangé (lignes 1 à 11). Ensuite, pour calculer la médiane, on regarde si la longueur de la liste est paire ou impaire : si elle est impaire \mbox{(\texttt{if len(L)\%2 == 1})} alors la médiane est l'élément central de la liste ordonnée \mbox{(\texttt{mediane = L[ len(L) // 2 ]})}. Notons ici que j'ai utilisé la division \underline{entière} pour trouver l'indice du terme central (car un indice ne peut être qu'entier, et faire \texttt{len(L)/2} retourne un nombre réel, et non entier).

Si au contraire la liste compte un nombre pair d'éléments, alors la médiane est la moyenne des éléments centraux, ceux-ci étant \texttt{L[len(L)//2]} et \texttt{L[len(L)//2+  1]}.
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[3]
On considère la fonction Python suivante:
\begin{python}
def f(L):
    # L est une liste de la forme [ (x1,n1) , (x2,n2) , ... , ]
    somme_produits = 0
    effectif_total = 0
    for x in L: # on parcourt la liste L --> x est un couple de nombres de la forme ( x[0], x[1] )
        somme_produits = somme_produits + x[0]*i[1]
        effectif_total = effectif_total + x[1]
        
    return somme_produits / effectif_total
\end{python}

\begin{enumerate}
\item Exécuter à la main et pas-à-pas cette fonction pour:
\begin{console}
>>> f( [ (1,2) , (3,4) ] )
\end{console}
en complétant le tableau suivant:
\begin{center}
\begin{tabular}{|Sl|*3{Sc|}}
\hline
x & - & (1,2) & (3,4) \\
\hline
somme\_produits & 0 &  & \\
\hline
effectif\_total & 0 &  & \\
\hline
\end{tabular}
\end{center}

\item À quoi correspond la valeur renvoyée par cette fonction ?

\item En s'inspirant de cette fonction, écrire une fonction \texttt{var(L)} qui renvoie la variance de la série statistique représentée par la liste \texttt{L}.
\end{enumerate}
\vspace*{-2em}

\tcblower

\begin{enumerate}
\item Le tableau complété est le suivant:
\begin{center}
\begin{tabular}{|Sl|*3{Sc|}}
\hline
x & - & (1,2) & (3,4) \\
\hline
somme\_produits & 0 & $0+1\times2=2$ & $2+3\times4=14$\\
\hline
effectif\_total & 0 & $0+2=2$ & $2+4=6$\\
\hline
\end{tabular}
\end{center}
Ainsi, la valeur renvoyée est égale à $14\div6\approx2.333\ldots$

\item À l'aide de l'exemple précédent, on s'aperçoit que pour une série statistique $(x_i;n_i)$, on ajoute dans la boucle tous les $x_i \times n_i$ (en effet, \texttt{x[0]} correspond à $x_i$ et \texttt{x[1]} correspond à $n_i$).

De plus, on ajoute aussi tous les effectifs (ligne 7).

Ainsi, lorsque la boucle est finie, on divise la somme des $x_i\times n_i$ par la somme des effectifs, ce qui correspond à la formule de la moyenne:
\[
\overline{x}=\dfrac{1}{N}\sum_{i} x_i \times n_i,
\]
où $N$ est l'effectif total.

\underline{La fonction Python renvoie donc la moyenne de la série mise en argument.}

\item La variance est la moyenne des $(x_i-\overline{x})^2$. Une fonction Python renvoyant la variance est donc très similaire à la fonction précédente:
\begin{python}
def var(L):
    m = moyenne(L)
    s = 0
    effectif_total = 0
    for x in L:
        s = s + ( x[0] - m )**2
        effectif_total = effectif_total + x[1]
        
    return s / effectif_total
\end{python}
\end{enumerate}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\enlargethispage*{4em}
\begin{exocor}{}[3]
\begin{enumerate}
\item Compléter la fonction Python suivante de sorte qu'elle renvoie une liste correspondant aux effectifs cumulés croissants de la liste \texttt{L}, liste de la forme \texttt{[ (x1,ecc1) , (x2,ecc2) , ... ]}.
\begin{python}
def ecc(L):
    # L est une liste de la forme [ (x1,n1) , (x2,n2) , ... ] où les ni sont les effectifs
    E = []
    for i in range( len(L) ):
        if i == 0:
            E.append( ... )
        else:
            E.append( ... )
            
    return E
\end{python}

\begin{rem}
Je rappelle que la fonction \texttt{E.append(x)} ajoute la valeur de \texttt{x} à la fin de la liste \texttt{E}.

De plus, \texttt{len(L)} est le nombre d'éléments contenus dans la liste \texttt{L}.
\end{rem}


\item Compléter la fonction Python suivante qui renvoie la médiane de la série représentée par la liste \texttt{L}.
\begin{python}
def mediane(L):
    E = ecc(L)
    N = E[-1][1] # effectif total
    
    if N % 2 == 0:
        moitie = ... # moitié de l'effectif total
    else:
        moitie = ...

    for i in range( len(E) ):
        if E[i][1] > moitie:
            return ...
        if E[i][1] == moitie:
            return ...       
\end{python}
\end{enumerate}

\tcblower

\begin{enumerate}
\item La fonction complétée est la suivante:

\begin{python}
def ecc(L):
    # L est une liste de la forme [ (x1,n1) , (x2,n2) , ... ] où les ni sont les effectifs
    E = []
    for i in range( len( L ) ):
        if i == 0:
            E.append( L[i] )
        else:
            E.append( ( L[i][0] , E[i-1][1] + L[i][1] ) )
            
    return E
\end{python}

Explications:
\begin{itemize}
\item Ligne 4 : la boucle signifie ici que l'on parcourt la liste \texttt{L} à l'aide des indices (\texttt{i}) de ses éléments.
\item Ligne 5 : si l'indice est égal à 0, c'est-à-dire si l'on est sur le premier élément de la liste, ...
\item Ligne 6 : on insère dans la liste \texttt{E} le premier effectif (\texttt{L[0]} représente le premier couple de nombres de la liste \texttt{L}, donc \texttt{L[0][1]} représente le deuxième nombre dans ce couple de nombres).
\item Ligne 7: si nous ne sommes pas sur le premier élément de \mbox{\texttt{L}...}
\item Ligne 8: on prend le deuxième nombre de l'élément précédent dans \texttt{E} (qui est un couple) et on lui ajoute l'effectif de l'élément de \texttt{L} sur lequel nous sommes.
\end{itemize}

Regardons sur l'exemple où \texttt{L = [ (1,2) , (3,4) , (5,6) ]}:
\begin{center}
\begin{tabular}{|>{\ttfamily}Sl|*4{Sc|}}
\hline
i & - & 0 & 1 & 2\\
\hline
L[i] & - & (1,2) & (3,4) & (5,6) \\
\hline
L[i][1] & - & 2 & 4 & 6\\
\hline
E[i][1] & 0 & $0+2=2$ & $2+4=6$ & $6+6=12$ \\
\hline
\end{tabular}
\end{center}
Au final, \texttt{E = [ (1,2), (3,6) , (5,12)]}.

\item La fonction complétée est celle présentée page suivante.

On retrouve à la ligne 5 le test pour savoir si l'effectif total est pair (\texttt{N \% 2 == 0}, auquel cas on le divise par 2 (ligne 6), ou impair (ligne 7), auquel cas on ajoute \og 1 \fg{} à l'effectif total et on divise par 2.

Ensuite, on parcourt la liste \texttt{E} (qui contient les effectifs cumulés croissants, abrégés en e.c.c.): si l'e.c.c. dépasse la moitié de l'effectif total, c'est que l'on a atteint la médiane et on la renvoie. Si, au contraire, l'e.c.c. est exactement égal à la moitié alors on retourne la moyenne entre la valeur courante (\texttt{E[i][0]}) et la suivante (\texttt{E[i+1][0]}). 

\newpage

\begin{python}
def mediane(L):
    E = ecc(L)
    N = E[-1][1] # effectif total 
    
    if N % 2 == 0:
        moitie = N / 2 # moitié de l'effectif total
    else:
        moitie = (N +1) / 2
        
    for i in range( len(E) ):
        if E[i][1] > moitie:
            return E[i][0]
        if E[i][1] == moitie:
            return ( E[i][0] + E[i+1][0] ) / 2
\end{python}
\end{enumerate}
\end{exocor}

\section*{Probabilités}

\begin{exocor}{}[2]
Le programme suivant effectue une simulation. Laquelle ?
\begin{python}
from random import randint

N = [0,0,0,0,0,0]

for k in range(1000):
    n = randint(1,6)
    N[n-1] = N[n-1] + 1
    
print(N)
\end{python}

\tcblower

L'instruction \texttt{randint(1,6)} choisit un nombre entier entre 1 et 6.

La ligne 7 affecte à la valeur \texttt{N[n-1]} la valeur qu'il y avait, augmentée de 1.

Prenons un exemple: si \og 3 \fg{}  est choisi lors du premier passage dans la boucle, alors \texttt{N[3-1]}, c'est-à-dire \texttt{N[2]} vaudra $0+1$ au premier passage dans la boucle.

Ainsi, à l'issue de la boucle, la liste \texttt{N} contiendra le nombre de fois que que l'on aura obtenu les nombres entiers de 1 à 6.

On peut alors imaginer que ce programme simule \numprint{1000} lancers d'un dé à six faces.

Voici quelques exemples de simulations à l'aide de ce programme:
\begin{console}
[177, 151, 159, 179, 168, 166]
[157, 176, 155, 160, 174, 178]
[189, 156, 166, 179, 159, 151]
[163, 160, 161, 182, 168, 166]
[163, 164, 152, 183, 170, 168]
[169, 163, 170, 148, 179, 171]
\end{console}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newpage
\begin{exocor}{}[3]
Un kangourou se trouve à un point donné, que l'on définira comme l'origine d'un repère orthonormé \og posé au sol \fg{}.

Chaque seconde, il fait un bond. Ce bond peut être en avant, en arrière, à gauche ou à droite.

Voici un exemple de trajet pendant 8 secondes:
\begin{center}
\includegraphics[scale=1]{kangourou.jpg}
\end{center}

\'Ecrire une fonction Python \texttt{trajet(n)} permettant de simuler un trajet de $n$ secondes qui renvoie les coordonnées finales du kangourou.

\tcblower

\textbf{Réflexions préliminaires:}
\begin{itemize}
\item \textit{Comment choisir au hasard la direction du kangourou ?}

Dès qu'il s'agit de faire un choix au hasard, il faut penser au module \texttt{random}. Ici, nous avons quatre directions possibles, que l'on peut modéliser par les nombres 1, 2, 3 et 4 (par exemple), avec la fonction \texttt{randint(1,4)}.

\item \textit{Tenir compte du nombre de secondes.}

$n$ représente le nombre de secondes, donc le nombre de fois que l'on devra faire un choix aléatoire de direction. Il faudra utiliser une boucle itérative \og for \fg.
\end{itemize}

\newpage

Une fonction possible est alors:

\begin{python}
from random import randint

def trajet(n):
    x, y = 0, 0 # position initiale du kangourou
    for k in range(n):
        direction = randint(1,4) # 1='droite', 2='gauche', 3='haut', 4='bas'
        if direction == 1:
            x = x + 1
        elif direction == 2:
            x = x - 1
        elif direction == 3:
            y = y + 1
        else:
            y = y - 1
    
    return x, y
\end{python}
On a par exemple:
\begin{console}
>>> trajet(20)
(2, -4)
\end{console}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[3]
On dispose d'un dé cubique (6 faces) et d'un dé tétraédrique (4 faces). Une expérience consiste à lancer ces deux dés et à regarder la somme des faces obtenues. Par exemple, si le dé cubique montre la face \og 5 \fg{} et le dé tétraédrique repose sur la face \og 1 \fg, le résultat de l'expérience est : $5+1=6$.

\'Ecrire une fonction Python \texttt{simulation(n)} qui simule \numprint{1000} expériences et qui retourne la somme moyenne obtenue.

\tcblower

L'issue d'un lancer de dé cubique peut être simulée à l'aide de la fonction \texttt{randint(1,6)} du module \texttt{random}.

De même, l'issue d'un lancer de dé tétraédrique peut être simulée à l'aide de la fonction \texttt{randint(1,4)}.

Pour effectuer $n$ simulations, on doit faire une boucle itérative \og for \fg. Cela donne par exemple:
\begin{python}
from random import randint

def simulation(n):
    somme = 0
    for k in range(n):
        a = randint(1,6)
        b = randint(1,4)
        somme = somme + a + b # somme précédente + résultat de l'expérience (a+b)
    
    return somme / n
\end{python}

L'idée ici est de définir une variable \texttt{somme} qui contiendra la somme des résultats de toutes les expériences.
Pour avoir la somme moyenne, il suffit de diviser cette somme totale par le nombre de simulations. 

On obtient:
\begin{console}
>>> for i in range(5):
		print( simulation(1000) )

5.77
6.025
6.033
5.934
6.006
\end{console}

Sur 5 simulations de \numprint{1000} expériences, on s'aperçoit que la somme moyenne est d'environ~6.
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{exocor}{}[3]
Dans les locaux d'une société, le responsable des achats sait que dans un rouleau de papier\linebreak toilette de la marque \og Toudou \fg, très appréciée dans l'entreprise, il y a en moyenne 500 feuilles (il les a compté un jour où il s'ennuyait).

Selon un sondage (qu'il a effectué auprès des personnes des locaux), chaque individu utilise entre 5 et 15 feuilles par passage aux commodités. 

\'Ecrire une fonction Python \texttt{pq(n)} qui simule le passage aux toilettes de $n$ personnes et qui renvoie le nombre de feuilles restantes. Cette fonction renverra un nombre négatif s'il manque des feuilles.

\tcblower

Une fonction possible est la suivante:

\begin{python}
from random import randint

def pq(n):
    feuilles = 500
    for k in range(n):
        nombre = randint(5,15)
        feuilles = feuilles - nombre
    
    return feuilles
\end{python}

La variable \texttt{feuilles} contiendra le nombre de feuilles restantes. 

Ainsi, au début, elle vaut 500 (car il y a 500 feuilles par rouleau).
Ensuite, on simule le passage de $n$ personnes à l'aide d'une boucle itérative ($n$ passages dans la boucle : $n$ itérations). À chaque itération, \texttt{nombre} représente le nombre de feuilles utilisées (soit un nombre aléatoire entre 5 et 15). On soustrait donc au nombre de feuilles restantes ce nombre.

À la fin de la boucle, la fonction renvoie la valeur stockée dans \texttt{feuilles} qui correspond bien au nombre de feuilles restantes après le passage de $n$ personnes.

On a par exemple:
\begin{console}
>>> pq(20)
308
>>> pq(50)
-49
>>> pq(50)
-2
\end{console}
\end{exocor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\corriges
