Algorithmes Python pour le baccalauréat

On trouvera ci-dessous les différents types d'algorithmes utilisés dans des sujets de baccalauréat. Dans chaque cas est donné un exemple concret ainsi que les explications associées.
Algorithmes pour les suites Calcul d'un terme Soit (un)(u_n) la suite définie par u0=100u_0=100 et pour tout entier nn, un+1=1,03un10u_{n+1}=1,03u_n-10.
L'algorithme ci-dessous permet de calculer et d'afficher u10u_{10} u = 100 for i in range(1,11): u = 1.03*u-10 print(u) L'instruction range(1,11) crée la liste de nombre [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].
À chaque étape de la boucle for la nouvelle valeur de u est calculée à partir de l'ancienne valeur de u, et ceci à dix reprises.
La valeur finale de la variable u est bien celle de u10u_{10}.

Si on veut afficher toutes les valeurs des termes de u1u_1 à u10u_{10}, on doit écrire print(u) à l'intérieur de la boucle for. u = 100 for i in range(1,11): u = 1.03*u-10 print(u) Si on veut afficher tous les termes de u0u_0 jusqu'à u10u_{10}, il y a deux façons de procéder.
Soit on affiche u0u_0 en écrivant print(u) juste après la première affection, et ensuite on procède comme précédemment : u = 100 print(u) for i in range(1,11): u = 1.03*u-10 print(u) Soit on affiche les valeurs successives de u à l'intérieur de la boucle avant de faire le calcul de u. Il manquera alors l'affichage du résultat du dernier calcul. On ajoute donc print(u) à la sortie de la boucle u = 100 for i in range(1,11): print(u) u = 1.03*u-10 print(u)

Pour pouvoir calculer n'importe quel terme (et pas seulement u10u_{10}) on utilise généralement une fonction à l'aide de l'instruction def. def u(n): u = 100 for i in range(1,n+1): u = 1.03*u-10 return u Si on exécute ce programme rien ne s'affiche, et c'est normal, on a juste définit une fonction qui se charge dans la mémoire de l'ordinateur (dans la RAM) mais qui n'est pas encore utilisée.
On voit que la fonction u est construite sur le même principe que les programmes précédents mais avec une valeur générique n plutôt que 1010.
Lorsque la fonction est appelée la valeur finale de la variable u est retournée (return u). def u(n): u = 100 for i in range(1,n+1): u = 1.03*u-10 return u print(u(10)) Il faut bien-sûr utiliser l'instruction print pour afficher le résultat de u(10) sinon nous n'aurions pas pu connaître la valeur retournée par la fonction u.
On peut effectuer d'autres calculs en appelant la fonction u : def u(n): u = 100 for i in range(1,n+1): u = 1.03*u-10 return u print(u(100)) Ou encore : def u(n): u = 100 for i in range(1,n+1): u = 1.03*u-10 return u s = u(0)+u(1)+u(2)+u(3) print(s) Ce type d'algorithme peut être utilisé dans les sujets de baccalauréat pour demander au candidat d'émettre une conjecture sur la suite considérée. Les conjectures doivent porter sur le sens de variation de la suite ainsi que sur son éventuelle limite. Il y a certains QCM où il faut que le candidat fasse la différence entre les deux algorithmes ci-dessous : u = 50 for i in range(0,10): u = u*1.1 print(u)
u = 50 for i in range(0,10): u = u*1.1 print(u) La différence porte sur l'indentation du print. Dans le premier cas il n'y a qu'un seul affichage car le print est à l'extérieur de la boucle (puisqu'il est collé à la marge gauche). Dans le deuxième cas le print fait partie de la boucle et donc à chaque itération de celle-ci l'affichage s'exécute. D'où le fait qu'ici nous ayons un seul affichage dans le premier algorithme et onze dans le deuxième. Calcul de la somme des termes d'une suite Dans le dernier exemple, on peut voir qu'il serait très long d'ajouter un à un tous les termes de la suite (un)(u_n) de u0u_0 jusqu'à u100u_{100} par exemple.
La méthode est de calculer la somme à l'intérieur de la boucle for.
On considère maintenant la suite géométrique (vn)(v_n) de premier terme v0=1v_0=1 et de raison 12\dfrac{1}{2}.
Le programme suivant permet de calculer v0+v1++v20v_0+v_1+\cdots+v_{20} == k=020vk\displaystyle{\sum_{k=0}^{20}v_k}. La somme est obtenue à l'aide de la variable s. v = 1 s = 1 for i in range(1,21): v = 0.5*v s = s+v print(s) Pour pouvoir calculer la somme jusqu'à un terme choisi, on définit une fonction : def somme(n): v = 1 s = 1 for i in range(1,n+1): v = 0.5*v s = s+v return s print(somme(30)) Recherche de seuil Lorsqu'on sait qu'une suite est convergente, ou divergente vers ±\pm\infty, des algorithmes de recherche de seuil permettent de déterminer le premier rang où les termes de la suite sont à une certaine distance de la limite, ou dépasse une certaine valeur.
On admet que la suite (un)(u_n) définie par u0=500u_0=500 et pour tout entier nn, un+1=0,8un+10u_{n+1}=0,8u_n+10, est décroissante et converge vers 5050.
L'algorithme ci-dessous permet de déterminer le premier terme n0n_0 à partir duquel, pour tout nn0n\geq n_0, un<51u_n<51. u = 500 n = 0 while u >= 51: n = n+1 u = 0.8*u+10 print(n) La boucle while permet d'effectuer les calculs des termes u et de leur rang n tant que le résultat de u est supérieur ou égale à 5151.
Lorsqu'on sort de la boucle while la condition n'est plus vérifiée et donc pour la valeur de n affichée on a u<51.
Pour cette suite on a donc, pour tout n28n\geq28, que un<51u_n <51 (puisque (un)(u_n) est décroissante).

On peut utiliser une fonction pour généraliser cette méthode.
Dans l'algorithme ci-dessous la fonction seuil utilise un paramètre p pour retourner la valeur du premier entier nn tel que un<50+10pu_n<50+10^{-p}.
C'est-à-dire le rang du premier terme qui soit une valeur approchée à 10p10^{-p} de la limite. def seuil(p): u = 500 n = 0 while u>= 50+10**(-p): n = n+1 u = 0.8*u+10 return n L'utilisation ci-dessous permet d'afficher le premier rang à partir du quel les termes sont à 10610^{-6} de la limite de la suite : def seuil(p): u = 500 n = 0 while u>= 50+10**(-p): n = n+1 u = 0.8*u+10 return n print(seuil(6)) Pour les suites divergeant vers ++\infty le principe est quasiment le même.
On admet que la suite (vn)(v_n) définie par v0=50v_0=50 et pour tout entier nn, vn+1=1.01vnv_{n+1}=1.01v_n est croissante et diverge vers ++\infty.
L'algorithme suivant permet de définir une fonction qui retourne le rang du premier terme où la suite dépasse 10p10^p. def seuil(p): v = 50 n = 0 while v < 10**p: n = n+1 v = 1.01*v return n Un exemple d'utilisation pour déterminer le rang du premier terme qui dépasse le milliard : def seuil(p): v = 50 n = 0 while v < 10**p: n = n+1 v = 1.01*v return n print(seuil(9)) Dans certains sujet de baccalauréat, après avoir déterminer la valeur de la limite d'une suite convergente, on demande au candidat de travailler sur un algorithme de recherche de seuil où on s'intéresse à la distance entre les termes de la suite et cette limite.
Considérons par exemple une suite (un)(u_n) définie par u0=5u_0=5 et pour tout entier nn, un+1=un+1u_{n+1} = \sqrt{u_n+1}.
On admet ici que (un)(u_n) converge vers =1+52\ell = \dfrac{1+\sqrt{5}}{2}. L'algorithme ci-dessous permet de déterminer le rang du premier terme de la suite qui sera à une distance inférieure à 10n10^{-n} de la limite \ell. from math import* def seuil(n): u = 5 i = 0 l = (1+sqrt(5))/2 while abs(u-l) > 10**(-n): u = sqrt(u+1) i = i+1 return i En effet, la fonction abs permet de calculer la valeur absolue d'un nombre. Ici donc abs(u-l) calcule la distance entre u et i soit la distance entre unu_n et \ell. La boucle s'exécute tant que cette distance n'est pas inférieure à 10n10^{-n}. Les suites doubles On peut définir des suites « interdépendantes » comme dans l'exemple ci-dessous:

(un)(u_n) et (vn)(v_n) sont deux suites définies par u0=20u_0=20, v0=60v_0=60 et pour tout entier naturel nn :

un+1=2un+vn4u_{n+1}=\dfrac{2u_n+v_n}{4} et vn+1=un+2vn4v_{n+1}=\dfrac{u_n+2v_n}{4}. L'algorithme ci-dessous définit une fonction qui retourne les valeurs de unu_n et vnv_n pour nn donné. def suites(n): u = 20.0 v = 60.0 for i in range(1,n+1): w = u u = (2*u+v)/4 v = (u+2*v)/4 return u,v print(suites(10)) Les premiers termes de la suite sont donnés avec une « virgule » (u=20.0 et v=60.0) seulement pour cette version de Python. Dans un sujet de bac il n'y aura pas obligation de faire apparaître cette écriture.
La subtilité d'un tel algorithme réside ici dans l'utilisation de la variable w. En effet lorsqu'on effectue le calcul u = (2*u+v)/4 la valeur de u est modifiée et on ne peut plus utiliser son ancienne valeur pour le calcul suivant v = (u+2*v)/4.
On avait donc besoin de sauvegarder la précédente valeur de u pour le calcul de v, et nous avons utilisé pour cela ici une troisième variable w. Récurrence double Une suite définie par une double récurrence est une suite où pour calculer un terme on a besoin des deux précédents.
Observons cela dans l'exemple ci-dessous :

Soit (un)(u_n) la suite définie par u0=1u_0=1, u1=1u_1=1 et pour tout entier nn : un+1=un+1+un.u_{n+1}=u_{n+1}+u_n. On a par exemple que u2=u1+u0u_2=u_1+u_0 == 1+11+1 == 22, ou encore u3=u2+u1u_3=u_2+u_1 == 2+12+1 == 33, etc.

L'algorithme ci-dessous définit une fonction qui permet de calculer un terme quelconque de la suite pour n1n\geq1. def u(n): u = 1 v = 1 for i in range(2,n+1): w = u+v u = v v = w return v print(u(2)) print(u(3)) print(u(4)) print(u(5)) La variable u joue ici le rôle de unu_n, la variable v celui de un+1u_{n+1}, et le résultat de un+1+unu_{n+1}+u_n est stocké dans la variable w.
À chaque itération il faut donc que l'ancienne valeur de v devienne la nouvelle valeur de u et que v prenne la valeur de w. Utilisation des listes avec les suites Des listes peuvent parfois être utilisées dans les algorithmes pour les suites.
En effet tous les algorithmes rencontrés dans ce tutoriel ont le désavantage d'oublier à chaque itération la valeur du terme précédent.
Par contre l'algorithme suivant permet de conserver tous les termes (de u0u_0 jusqu'à u10u_10) de la suite (un)(u_n) définie par u0=500u_0 = 500 et pour tout entier nn par un+1=1,05un3u_{n+1}=1,05u_n- 3. u = 500 L = [u] for i in range(0,10): u = 1.05*u-3 L.append(u) print(L) On rappelle qu'une liste se définit avec des crochets et que l'instruction L.append(u) permet d'ajouter le terme u à la fin de la liste L.

Il est bien-sûr possible d'utiliser cette forme d'algorithme dans une fonction pour choisir jusqu'à quel terme de la suite va aller la liste : def suite_u(n): u = 500 L = [u] for i in range(0,n): u = 1.05*u-3 L.append(u) return L print(suite_u(20)) Une telle liste qui contient tous les premiers termes d'une suite permet facilement de calculer la somme de ces premiers termes.
Considérons toujours la même suite unu_n et cherchons à écrire une algorithme qui calcule k=0nuk\displaystyle{\sum_{k=0}^n u_k} pour toute valeur nn de notre choix.
Il faudrait pour cela réutiliser la fonction de l'algorithme précédent puis en écrire une autre pour calculer la somme des termes. Cependant, dans les sujets de baccalauréat on ne propose généralement que la fonction qui calcule la somme des termes d'une liste comme ci-dessous : def somme(L): S = 0 n = len(L) for i in range(0,n): S = S+L[i] return S On rappelle que l'instruction len(L) permet d'obtenir le nombre de termes d'une liste.
Voici un exemple d'application sur la suite arithmétique de premier terme 55 et de raison 3,33,3. def somme(L): S = 0 n = len(L) for i in range(0,n): S = S+L[i] return S U = [5+3.3*i for i in range(0,10)] print(U) print(somme(U)) Les listes permettent également de pouvoir déterminer le plus grand ou le plus petit terme d'une suite parmi les premiers de celle-ci.
Les algorithmes des sujets de baccalauréat proposent là aussi généralement seulement des fonctions permettant de déterminer le plus grand ou le plus petit terme d'une liste comme dans l'exemple ci-dessous : def maxListe(L): n = len(L) maxL = L[0] for i in range(1,n): if L[i] > maxL: maxL = L[i] return maxL
Dans ce genre d'algorithme on parcourt un à un tous les termes de la liste. On initialise le max de cette liste au premier de terme de la liste et ensuite on regarde si le terme suivant est plus grand que ce max. Si oui on modifie le max en le remplaçant par ce terme de la liste et on passe au suivant pour faire à nouveau la même comparaison et ceci jusqu'au dernier.
Cet algorithme permet donc d'obtenir la valeur du plus grand terme de la liste, mais on aimerait aussi avoir son rang : def maxListe(L): n = len(L) maxL = L[0] nMax = 0 for i in range(1,n): if L[i] > maxL: maxL = L[i] nMax = i return [nMax,maxL] La réponse renvoyée est une liste composée du rang du maximum et de la valeur de ce maximum.
Regardons un exemple d'utilisation.
On considère la suite unu_n définie par un=n0,01n2e0,1nu_n=\dfrac{n-0,01n^2}{\text{e}^{0,1n}}. On cherche le rang et la valeur de son plus grand terme parmi ses 5050 premiers. from math import* def maxListe(L): n = len(L) maxL = L[0] nMax = 0 for i in range(1,n): if L[i] > maxL: maxL = L[i] nMax = i return [nMax,maxL] U = [(i-0.01*i**2)/exp(0.1*i) for i in range(0,50)] print(maxListe(U)) Algorithmes pour les fonctions Définir une fonction Python permet de définir des fonctions à l'aide de def.
Par exemple, l'algorithme ci-dessous permet de définir la fonction ff définie sur R\mathbb{R} par f(x)=x4+1f(x)=\sqrt{x^4+1} : from math import* def f(x): return sqrt(x**4+1) La première ligne from math import* est nécessaire car sinon la fonction sqrt n'est pas reconnue par Python.
Pour pouvoir utiliser la fonction f on peut afficher quelques images de la sorte : from math import* def f(x): return sqrt(x**4+1) print(f(0)) print(f(10)) print(f(-50)) On peut utiliser une liste définie par compréhension pour afficher un tableau de valeurs de la fonction ff. from math import* def f(x): return sqrt(x**4+1) L = [f(i) for i in range(0,10)] print(L) La liste L contient les images f(i) pour i compris entre 0 et 9.     Concernant le logarithme népérien Pour utiliser la fonction logarithme népérien il faut dans la premier ligne d'un algorithme écrire l'instruction from math import*.
Cependant, en Python le logarithme népérien, la fonction notée ln\ln en français, s'obtient avec l'instruction log.
Généralement dans un sujet de baccalauréat il peut y avoir autant écrit log que ln ou alors, de façon plus rigoureuse, le sujet peut écrire au début de l'algorithme l'instruction from math import log as ln ce qui permet d'utiliser l'écriture ln sans erreur. from math import* print(log(10)) from math import* print(ln(10)) from math import log as ln print(ln(10)) Approximation des solutions d'une équation On considère la fonction ff définie sur R\mathbb{R} par f(x)=x5+x1f(x)=x^5+x-1.
On admet que ff est strictement croissante sur R\mathbb{R} et que l'équation f(x)=0f(x)=0 admet une unique solution α\alpha sur [0;1][0\,;1].
L'algorithme ci-dessous permet d'obtenir un encadrement à 10210^{-2} de α\alpha. def f(x): return x**5+x-1 x = 0 while f(x) < 0: x = x+0.01 print(x) Le résultat affichée, 0,76, correspond à la première valeur de x pour laquelle f(x) est positif.
Ainsi, grâce à cette algorithme on peut affirmer que : 0,75<α<0,760,75 < \alpha < 0,76. Cet algorithme peut être écrit sans définir la fonction ff : x = 0 while x**5+x-1 < 0: x = x+0.01 print(x)

Pour gagner en précision on peut définir une fonction avec le pas en paramètre. La fonction equation ci-dessous possède un paramètre p qui correspond à un pas de 10p10^{-p}. def f(x): return x**5+x-1 def equation(p): x = 0 while f(x) < 0: x = x+10**(-p) return x Mais cette algorithme présente un problème. Si on donne un pas très petit (donc une valeur importante pour p) il sera très lent. En effet, x part de 00 pour avancer de très peu à chaque itération. def f(x): return x**5+x-1 def equation(p): x = 0 while f(x) < 0: x = x+10**(-p) return x print(equation(6)) On peut résoudre cet écueil en donnant un autre paramètre à la fonction en plus de p pour la valeur initiale de xx.
Ainsi, en donnant des valeurs successives à p de plus en plus grandes et en exploitant les résultats affichés on gagne du temps d'exécution. def f(x): return x**5+x-1 def equation(p,a): x = a while f(x) < 0: x = x+10**(-p) return x print(equation(1,0)) def f(x): return x**5+x-1 def equation(p,a): x = a while f(x) < 0: x = x+10**(-p) return x print(equation(2,0.7)) def f(x): return x**5+x-1 def equation(p,a): x = a while f(x) < 0: x = x+10**(-p) return x print(equation(3,0.75)) def f(x): return x**5+x-1 def equation(p,a): x = a while f(x) < 0: x = x+10**(-p) return x print(equation(4,0.754)) def f(x): return x**5+x-1 def equation(p,a): x = a while f(x) < 0: x = x+10**(-p) return x print(equation(5,0.7548)) def f(x): return x**5+x-1 def equation(p,a): x = a while f(x) < 0: x = x+10**(-p) return x print(equation(6,0.75487))
Cette dernière exécution nous donne : 0,754877<α<0,7548780,754\,877 < \alpha < 0,754\,878.

La méthode de dichotomie apparaît parfois dans des sujets de baccalauréat.
La méthode de la dichotomie se rapproche de celle à employer dans le jeu du « juste prix » où il faut deviner un prix et où le présentateur répond par « plus grand » ou « plus petit ».
Il faut alors choisir le centre de l'intervalle dans lequel se trouve le prix. Par exemple si on sait que le prix est compris entre 00 et 1000010\,000 €, il faut proposer au départ 50005\,000, puis si par exemple l'animateur dit « plus grand » on doit annoncer 75007\,500 etc.

Pour une fonction dont on sait qu'elle s'annule sur [0;1][0\,;1] par exemple, on calcule f(0,5)f(0,5) en fonction du signe trouvé et et du sens de variation de ff, la solution de f(x)=0f(x)=0 sera soit dans [0;0,5][0\,;0,5] soit dans [0,5;1][0,5\,;1].
Dans l'animattion ci-dessous les points rouge sur l'axe des abscisses correspondent à l'intervalle initiale. Le point vert correspond au centre de l'intervalle délimité par les points rouge.
À l'étape suivante (en faisant augmenter k de 11), le nouvel intervalle dépend du signe que l'on avait pour l'image du point vert. Xmin = -1 Xmax = 2 Ymin = -1.2 Ymax = 2.2 function base(){ couleur = noir peinture = blanc transparence = 1 rectangle([-5,5],20,20) traceX() traceY() couleur = bleu graphe(f,0,10) couleur = rouge } function f(x){ return Math.pow(x,5)+x-1 } function dicho(n){ base() a = 0 b = 1 for(i = 0; i < n-1; i++){ c = (a+b)/2 if( f(c) < 0){ a = c } else{ b = c } } point([a,0]) point([b,0]) segment([a,0],[a,f(a)],[5,2]) segment([0,f(a)],[a,f(a)],[5,2]) segment([b,0],[b,f(b)],[5,2]) segment([0,f(b)],[b,f(b)],[5,2]) c = (a+b)/2 if( f(c) < 0){ a = c } else{ b = c } couleur = vert point([c,0]) segment([c,0],[c,f(c)],[5,2]) segment([0,f(c)],[c,f(c)],[5,2]) couleur = noir texte(c,[-0.5,1]) } base() curseur("k",1,1,10,1) dicho({k}) Appliquons cette méthode à notre fonction ff précédente. def f(x): return x**5+x-1 def dicho(n): a = 0 b = 1 for i in range(0,n): c = (a+b)/2 if f(c) < 0: a = c else: b = c return [a,b] print(dicho(10)) Dans la fonction dicho on répète n fois le principe exposé précédemment.
Si l'image du centre de l'intervalle [a;b][a\,;b] est négative l'intervalle [a;b][a\,;b] devient [c;b][c\,;b] (avec c le centre de l'intervalle).
Sinon, (si l'image du centre de l'intervalle [a;b][a\,;b] est positive) l'intervalle [a;b][a\,;b] devient [a;c][a\,;c].
La fonction dicho retourne les bornes du dernier intervalle [a;b][a\,;b] calculé.

Après exécution nous voyons ici que la solution α\alpha vérifie :
0,75390625<α<0.75488281250,753\,906\,25 < \alpha < 0.754\,882\,812\,5 Approximation d'un extremum Lorsqu'on connaît les variations d'une fonction sur un intervalle on peut vouloir y déterminer une valeur approchée de l'extremum que présente la fonction sur celui-ci.
On admet que la fonction ff définie pour tout réel xx par f(x)=x4x3+10x+1f(x)=-x^4-x^3+10x+1 est croissante puis décroissante sur [0;2][0\,;2].
On cherche à déterminer sa valeur maximale sur [0;2][0\,;2].
Pour cela on va avancer d'un pas constant à partir de 00 et regarder les images successives pour en retenir la plus grande. def f(x): return -x**4-x**3+10*x+1 x = 0 sup = f(x) while x < 2: x = x+0.01 if f(x)>sup: sup = f(x) print(sup) Si on veut connaître la valeur de x pour laquelle le maximum est atteint lors de ce balayage, on ajoute une variable xmax comme suit : def f(x): return -x**4-x**3+10*x+1 x = 0 xmax = 0 sup = f(x) while x < 2: x = x+0.01 if f(x)>sup: sup = f(x) xmax =x print(xmax, sup) Dans l'algorithme ci-dessous, on définit une fonction qui prend en paramètre une variable p correspondant à un pas de 10p10^{-p} et deux paramètres a et b correspond aux bornes de l'intervalle sur lequel on cherche une approximation de maximum de la fonction. def f(x): return -x**4-x**3+10*x+1 def maximum(p,a,b): x = a sup = f(a) xmax = a while x < b: x = x+10**(-p) if f(x)>sup: sup = f(x) xmax = x return xmax, sup print(maximum(6,1.14,1.15)) On a utilisé les valeurs 1,14 et 1,15 à l'aide de l'algorithme précédent (sinon l'exécution à partir de 00 aurait été longue). Algorithmes pour les probabilités Pour les algorithmes probabilistes, le module random devra être chargé à chaque fois.
Les deux fonctions que l'on utilisera sont random() qui fournit un nombre aléatoire de [0;1[[0\,;1[ et randint(a,b) qui fournit un entier aléatoire entre aa et bb.
Dans les exemples ci-dessous on pourra appuyer plusieurs fois sur Exécuter pour voir l'effet de ces instructions. from random import* print(random()) from random import* print(randint(1,6)) Schéma de Bernoulli ∼ Loi binomiale On considère ici une variable aléatoire XX suivant la loi binomiale de paramètres 8080 et 0,120,12.
Par exemple :
La valeur finale de XX après exécution de l'algorithme suivant, correspond aux nombres de succès parmi les 8080 éléments de l'échantillon. from random import* X = 0 for i in range(0,80): e = randint(1,100) if e <= 12: X = X+1 print(X) La variable e définie à la ligne 4 retourne un entier aléatoire entre 11 et 100100. La probabilité qu'il soit inférieur à 1212 est bien de 0,120,12. Ainsi, la probabilité que la ligne 6 s'exécute est de 0,120,12.
Cette manière de faire est par contre peu pratique si on veut généraliser la méthode. On va plutôt générer un nombre aléatoire entre 00 et 11 à l'aide de random() puis de regarder si le résultat est inférieur à 0,120,12. from random import* X = 0 for i in range(0,80): e = random() if e <= 0.12: X = X+1 print(X) De cette façon on peut généraliser cet algorithme à toutes variables aléatoires suivant une loi binomiale de paramètres quelconques nn et pp. from random import* def vaBinom(n,p): X = 0 for i in range(0,n): e = random() if e <= p: X = X+1 return X print(vaBinom(1000,0.5)) Expériences aléatoires avec plus de deux issues possibles Il est possible qu'une expérience aléatoire possède au moins trois issues, comme par exemple dans un lancé de dé à 66 faces.
L'algorithme ci-dessous simule 500500 lancés d'un dé à 66 faces équilibré. Il affiche en retour le face « moyenne » obtenue. from random import* s = 0 for i in range(0,500): s = s+randint(1,6) print(s/500) On peut dans cette situation également définir une fonction permettant de choisir le nombre de lancés du dé : from random import* def de(n): s = 0 for i in range(0,n): s = s+randint(1,6) return s/n print(de(20))

Une autre situation que l'on peut rencontrer est celle de jeux à base de roue.
Par exemple, dans une fête foraine une roue est constituée de 66 secteurs angulaires de même surface, chacun portant un numéro distinct entre 11 à 66. En fonction du secteur obtenu après avoir fait tourner la roue, le joueur possède les gains suivants :
Numéro du secteur 11 22 33 44 55 66
Gain 00 00 11 11 22 1010
Le prix de la participation au jeu est de 55 €.
L'algorithme suivant permet de simuler 10001\,000 parties de ce jeu et affiche le gain moyen. from random import* s = 0 for i in range(0,1000): j = randint(1,6) if j == 3 or j == 4: s = s+1 if j == 5: s = s+2 if j == 6: s = s+10 gainMoyen = s/1000-5 print(gainMoyen)

On peut utiliser les fonctions aléatoires de Python dans des situations de tirages aléatoires comme dans l'exemple ci-dessous.

Parmi les 2323 joueurs d'une équipe de football, trois sont tirés au hasard pour subir un contrôle antidopage à la fin d'un match.
On suppose que les joueurs sont numérotés de 11 jusqu'à 2323. L'algorithme ci-dessous permet d'obtenir les numéros des trois joueurs devant subir le contrôle. from random import* a = 0 b = 0 c = 0 while a == b or a == c or b == c: a = randint(1,23) b = randint(1,23) c = randint(1,23) print(a,b,c) Cet algorithme effectue un tirage aléatoire de trois nombres entre 11 et 2323 et tant qu'au moins deux résultats sont identiques on recommence le tirage. Ainsi lorsqu'on sort de la boucle while on est assuré que les trois valeurs de a, b et c sont distinctes. Algorithmes pour le dénombrement Coefficients binomiaux La factorielle d'un entier naturel peut-être utilisée pour calculer les coefficients binomiaux. Les deux algorithmes ci-dessous définissent chacun une fonction permettant de calculer la factorielle d'un entier donné.
Le premier plus classique le fait à l'aide d'une boucle for, alors que le deuxième le fait par récursivité. C'est-à-dire qu'au sein de la fonction on effectue un appel vers cette même fonction mais pour une autre valeur du paramètre. def facto(n): f = 1 for i in range(2,n+1): f = f*i return f print("1! = ",facto(1)) print("2! = ",facto(2)) print("3! = ",facto(3)) print("4! = ",facto(4)) print("10! = ",facto(10)) def facto(n): if n == 1: f = 1 else: f = n*facto(n-1) return f print("1! = ",facto(1)) print("2! = ",facto(2)) print("3! = ",facto(3)) print("4! = ",facto(4)) print("10! = ",facto(10))

Pour calculer les coefficients binomiaux on peut, maintenant que l'on a la fonction factorielle, utilisée la formule suivante :
pour tout entier naturel nn et knk\leq n, (nk)=n!k!(nk)!\displaystyle{ {n \choose k} }=\dfrac{n!}{k!(n-k)!}. def facto(n): f = 1 for i in range(2,n+1): f = f*i return f def coefBinom(n,k): return facto(n)/(facto(k)*facto(n-k)) print("3 parmi 5 : ",coefBinom(5,3)) print("4 parmi 9 : ",coefBinom(9,4))

On peut également calculer les coefficients binomiaux à l'aide de la formule de Pascal :
pour tout entier b1b\geq1 et pour tout knk\leq n : (n1k1)+(n1k)=(nk){n-1 \choose k-1}+{n-1 \choose k}={n \choose k}. def coefBinom(n,k): if n == 1 and (k ==0 or k ==1): f = 1 else: f = 0 if n > 1: f = coefBinom(n-1,k-1)+coefBinom(n-1,k) return f print("3 parmi 5 : ",coefBinom(5,3)) print("4 parmi 9 : ",coefBinom(9,4))
En combinatoire on s'intéresse également aux arrangements des éléments d'un ensemble.
L'algorithme ci-dessous permet d'obtenir la liste des arrangements composés de deux éléments d'un ensemble qui est donné sous la forme d'une liste. def arr2(A): n = len(A) for i in range(0,n): for j in range(0,n): if j != i: print(A[i],A[j]) arr2([1,2,3,4]) La ligne 5 if j != i: est importante, puisque dans un arrangement il ne peut y avoir de répétitions.
L'algorithme suivant est basé sur le même principe, et affiche la liste des arrangements de trois éléments d'un ensemble donné. def arr3(A): n = len(A) for i in range(0,n): for j in range(0,n): for k in range(0,n): if k != j and k !=i and i != j: print(A[i],A[j],A[k]) arr3(['a','b','c','d'])