Programmer en Python en 2nde

Boucle inconditionnelle : for, exercices

Crédits

Toute la structure html/css/js et une partie du contenu ont été réalisés par Nicolas Buyle-Bodin professeur au lycée Lacassagne, avec l'aide de Jean-Manuel Mény, professeur au lycée de la plaine de l'Ain. Ils ont travaillé pendant plusieurs centaines d'heures pour créer un site de formation à destination des enseignants du secondaire de l'académie de Lyon d'une grande qualité visible sur le portail Mathématiques du site académique. Ils ont eu la gentillesse de placer leur code source sous licence Creative Commons BY-NC-SA Respect de la Paternité - Pas d'utilisation commerciale - Partage des conditions initiales à l'identique..

Nous les en remercions chaleureusement.

Tables de multiplication

  1. Le script ci-dessous affiche-t-il tous les multiples de 7 compris entre 7 et 70 ?
    
    for k in range(1, 10):
        print("7 * ", k, " = ", 7 * k)
    
  2. Écrire une fonction table(n) qui affiche la table des multiples d'un entier n pour des multiplicateurs variant entre 1 et 10.
  3. On veut afficher toutes les tables de mutiplications des entiers compris entre 1 et m avec des multiplicateurs variant entre 1 et 10.
    • Écrire une première version punition_table1(m) qui n'utilise pas la fonction table(n) définie dans la question précédente.
    • Écrire une seconde version punition_table2(m) qui utilise la fonction table(n) définie dans la question précédente.

					
					
  • Solution Question 1
  • Solution Question 2
  • Solution Question 3

for k in range(1, 10):
    print("7 * ", k, " = ", 7 * k)

La boucle n'affiche que $10-1=9$ multiples de $7$ pour les multiplicateurs variant de $1$ à $10$ exclu avec un pas de $1$ donc de $1$ à $9$ inclus :

7 * 1 = 7
7 * 2 = 14
7 * 3 = 21
7 * 4 = 28
7 * 5 = 35
7 * 6 = 42
7 * 7 = 49
7 * 8 = 56
7 * 9 = 63

def table(n):
    for k in range(1, 11):
    	print(n, " * ", k ," = ", n * k)
        
table(6)
        

et l'affichage de la table de 6 :

6 * 1 = 6
6 * 2 = 12
6 * 3 = 18
6 * 4 = 24
6 * 5 = 30
6 * 6 = 36
6 * 7 = 42
6 * 8 = 48
6 * 9 = 54
6 * 10 = 60

Une première version avec deux boucles imbriquées.


def punition_table1(m):
    for n in range(1, m + 1):
        print("Table de ", n)
        for k in range(1, 11):
    	   print(n, " * ", k ," = ", n * k)
        print('*' *  12)
        
punition_table1(3)
        
Table de 1
1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
1 * 4 = 4
1 * 5 = 5
1 * 6 = 6
1 * 7 = 7
1 * 8 = 8
1 * 9 = 9
1 * 10 = 10
************
Table de 2
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
2 * 7 = 14
2 * 8 = 16
2 * 9 = 18
2 * 10 = 20
************
Table de 3
3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
3 * 4 = 12
3 * 5 = 15
3 * 6 = 18
3 * 7 = 21
3 * 8 = 24
3 * 9 = 27
3 * 10 = 30
************

Une seconde version avec la boucle interne factorisée dans une fonction.


def table(n):
    for k in range(1, 11):
    	print(n, " * ", k ," = ", n * k)
        
def punition_table2(m):
    for n in range(1, m + 1):
        print("Table de ", n)
        table(n)
        print('*' *  12)
        
punition_table2(3)
        

Des sommes

  1. Écrire une fonction somme(n) qui pour un entier naturel $n >0$ retourne la valeur de la somme d'entiers consécutifs $1+2+3+ \ldots +n$.
  2. Écrire une fonction somme_carre(n) qui pour un entier naturel $n > 0$ retourne la valeur de la somme $1^{2}+2^{2}+3^{2}+ \ldots +n^{2}$.
  3. Écrire une fonction somme_puissance(n, m) qui pour un entier naturel $n > 0$ retourne la valeur de la somme $1^{m}+2^{m}+3^{m}+ \ldots +n^{m}$.
  4. Écrire une fonction somme_binaire(n) qui pour un entier naturel $n$ retourne la somme $1+0,5^{2}+0,5^{3}+ \ldots +0,5^{n}$. Tester la fonction pour des valeurs de $n$ croissantes, que remarque-t-on ?

					
					
  • Solution Question 1
  • Solution Question 2
  • Solution Question 3
  • Solution Question 4

def somme(n):
    s = 0
    for k in range(1, n + 1):
        s = s + k
    return s

def somme_carre(n):
    s = 0
    for k in range(1, n + 1):
        s = s + k ** 2
    return s

def somme_puissance(n, m):
    s = 0
    for k in range(1, n + 1):
        s = s + k ** m
    return s

def somme_binaire(n):
    s = 1
    for k in range(1, n + 1):
        s = s + 0.5 ** k
    return s

for  n in range(5, 51, 5):
    print(n, somme_binaire(n))

Le script ci-dessus donne cet affichage :

(5, 1.96875)
(10, 1.9990234375)
(15, 1.99996948242)
(20, 1.99999904633)
(25, 1.9999999702)
(30, 1.99999999907)
(35, 1.99999999997)
(40, 2.0)
(45, 2.0)
(50, 2.0)

On observe que plus n est grand, plus la valeur retournée par somme_binaire(n) est proche de 2. On démontrera en classe de première que la somme $1+\frac{1}{2} + \frac{1}{2^{2}} + \frac{1}{2^{3}} + \ldots + \frac{1}{2^{n}}$ converge vers $2$ lorsque $n$ tend vers $+\infty$. C'est lié au développement de $2$ en base $2$, dont une écriture non canonique est $1,111111\ldots$ avec une infinité de $1$ après la virgule, qui sont les coefficients des puissances de $\frac{1}{2}$.

Des petits trous, des petits trous encore des petits trous ...

Pour afficher une chaîne de caractères constituée de onze caractères 'o' on peut utiliser l'opérateur * des chaînes de caractères qui concatène onze fois de suite le caractère 'o' comme une mutplication :


print('o' * 11)
ooooooooooo
  1. Écrire un script qui affiche le motif ci-dessous :
    o
    oo
    ooo
    oooo
    ooooo
    oooooo
    ooooooo
    oooooooo
    ooooooooo
    oooooooooo
  2. Écrire un script qui affiche le motif ci-dessous :
    ooooooooo
    oooooooo
    ooooooo
    oooooo
    ooooo
    oooo
    ooo
    oo
    o
  3. Écrire un script qui affiche le motif ci-dessous :
             o
            oo
           ooo
          oooo
         ooooo
        oooooo
       ooooooo
      oooooooo
     ooooooooo
    oooooooooo
  4. Écrire un script qui affiche le motif ci-dessous :
         o     
        ooo    
       ooooo   
      ooooooo  
     ooooooooo 
    ooooooooooo
  5. Écrire un script qui affiche le motif ci-dessous :
         o     
        ooo    
       ooooo   
      ooooooo  
     ooooooooo 
    ooooooooooo
     ooooooooo 
      ooooooo  
       ooooo   
        ooo    
         o

					
					
  • Solution Question 1
  • Solution Question 2
  • Solution Question 3
  • Solution Question 4
  • Solution Question 5

for k in range(1, 11):
    print('o' * k)
        

for k in range(1, 11):
    print('o' * (10 - k))
        

for k in range(1, 11):
    print(' ' * (10 - k) + 'o' * k)
        

for k in range(6):
    print(' ' * ((11 - 1 - 2 * k)//2) + 'o' * (1 + 2 *k) + ' ' * ((11 - 1 - 2 * k)//2))
        

for k in range(6):
    print(' ' * ((11 - 1 - 2 * k)//2) + 'o' * (1 + 2 *k) + ' ' * ((11 - 1 - 2 * k)//2))
for k in range(4, -1, -1):
    print(' ' * ((11 - 1 - 2 * k)//2) + 'o' * (1 + 2 *k) + ' ' * ((11 - 1 - 2 * k)//2))
        

Une probabilité

Un jeu à deux joueurs

Le joueur 1 et le joueur 2 lancent chacun un dé (dé classique, équilibré, à six faces). Le joueur qui obtient une valeur strictement supérieure à celle obtenue par l'autre joueur gagne. En cas d'égalité, la partie est nulle.

Un programme

  1. Écrire une fonction en Python qui respecte la spécification suivante :
    Paramètres /
    Définition simule le lancer de deux dés
    Valeur renvoyée 1 si le joueur 1 gagne, 2 si le joueur 2 gagne, 0 en cas de partie nulle.
  2. Écrire une fonction en Python qui respecte le cahier des charges suivant :
    Paramètre un entier naturel n
    Valeur renvoyée la fréquence de parties gagnées par le joueur 1 lors de n parties.

					
					

Interprétation

Observer les valeurs obtenues pour la fréquence de parties gagnées par le joueur 1 pour de grandes valeurs de n. Expliquer ces valeurs.

  • Rappel : module random
  • Une solution
  • Interprétation

Les fonctions qui génèrent du pseudo-aléatoire sont contenues dans le module random. Exécutez plusieurs fois le programme ci-dessous afin de bien saisir les résultats obtenus par deux d'entre elles :


			
			

from random import randint

def jeu() :
    de1 = randint(1,6)
    de2 = randint(1,6)
    if de1 > de2 :
        return 1
    elif de2 > de1 :
        return 2
    else :
        return 0
	

def frequence(n) :
    compteur = 0
    for k in range(n) :		
        if jeu() == 1 :		 
            compteur = compteur + 1	
    return compteur/n
	
	
print(frequence(10**6))
print(15/36)
		

Sur les 36 couples possibles, 15 correspondent à une victoire du joueur 1, 6 à un match nul, 15 à la victoire du joueur 2.

La probabilité de gagner du joueur 1 est donc égale à \( \frac{15}{36} \).

Paradoxe du duc de Toscane

A la cour de Florence, le Duc de Toscane, qui avait sans doute observé un grand nombre de lancers de 3 dés (équilibrés, 6 faces), avait constaté que la somme 10 était obtenue légèrement plus souvent que la somme 9 (en ajoutant les faces supérieures des trois dés) ce qu’il trouvait paradoxal puisqu’il existe six façons d’écrire 10 ou 9 comme sommes de trois entiers entre 1 et 6 : \( 10=6+3+1=6+2+2=5+4+1=5+3+2=4+4+2=4+3+3 \) et \(9=6+2+1=5+3+1=5+2+2=4+4+1=4+3+2=3+3+3 \), on trouve quatre décompositions en trois entiers distincts pour $10$ et $9$ mais deux décompositions .

  1. Écrire un script qui détermine les probabilités d'obtenir $10$ ou $9$ lorsqu'on lance trois dés (équilibrés, 6 faces) et qu'on calcule la somme des faces supérieures.
  2. Qu'auriez-vous répondu au duc de Toscane pour résoudre son paradoxe ?

					
					
  • Solution Question 1
  • Solution Question 2

somme9 = 0				#compteur de sommes égales à 9
somme10 = 0			    #compteur de sommes égales à 10
for de1 in range(1, 7):
    for de2 in range(1, 7):
        for de3 in range(1, 7):
            somme = de1 + de2 + de3
            if somme == 9:
                somme9 = somme9 + 1
            elif somme == 10:
                somme10 = somme10 + 1
print("Sur 6 * 6 * 6 = 216 triplets  de trois des on a " + str(somme9) + " egales a 9")
print("Sur 6 * 6 * 6 = 216 triplets  de trois des on a " + str(somme10) + " egales a 10")
        
Sur 6 * 6 * 6 = 216 triplets  de trois des on a 25 egales a 9
Sur 6 * 6 * 6 = 216 triplets  de trois des on a 27 egales a 10

L'univers $\Omega$ est constitué de $6 \times 6 \times 6 = 216$ issues élémentaires équiprobables qui sont les triplets de faces observées. On a $25$ décompositions de $9$ en somme de trois entiers compris entre $1$ et $6$, et $27$ décompositions pour $10$, donc la probabilité d'obtenir une somme des trois faces égale à $9$ est de $\frac{25}{216}$ et celle d'obtenir une somem égale à $10$ est de $\frac{27}{216}$. Il est donc plus probable d'obtenir une somme égale à $10$ qu'une somme égale à $9$.

Sur les six décompositions données par le duc :

  • $10=6+3+1=6+2+2=5+4+1=5+3+2=4+4+2=4+3+3 $
  • $9=6+2+1=5+3+1=5+2+2=4+4+1=4+3+2=3+3+3$
on trouve quatre décompositions avec trois entiers distincts pour $10$ et $9$ mais deux décompositions avec deux entiers identiques pour $10$ contre une décomposition avec deux entiers identiques et une décomposition avec trois entiers identiques pour $9$. Or il existe trois façons d'écrire une somme de trois nombres dont deux sont identiques et une seule façon lorsque les trois sont identiques : $4 + 4 + 2 = 4 + 2 + 4 = 2 + 4 + 4$ mais $3 + 3 + 3$ ne peut s'écrire autrement.

Intervalle de fluctuation

Une expérience aléatoire consisye à lancer un dé équilibré à six faces numérotées de 1 à 6.

  1. Le code Python ci-dessous permet d'afficher la face supérieure du dé lors de dix lancers successifs d'un dé à 6 faces. On commence par importer la fonction randint du module random. Cette fonction prend deux paramètres : par exemple randint(1, 6) retourne un entier aléatoire compris entre 1 et 6, les bornes sont incluses.
    
    from random import randint
    for k in range(10):
        print(randint(1, 6))
    
    5
    4
    3
    2
    6
    3
    5
    6
    6
    2    
            
    Écrire une fonction freqMult3(n) qui retourne la fréquence de multiples de 3 obtenus sur un échantillon de n lancers de dés.
  2. Déterminer la probabilité p d'obtenir un mutiple de 3 lorsqu'on lance un dé équilibré à 6 faces numérotées de 1 à 6, puis un intervalle de fluctuation au seuil de $95$ % de la fréquence de multiples de 3 obtenus sur un échantillon de $n$ lancers.
  3. Écrire une fonction freqInterFluct(m, n) qui calcule les fréquences de réalisations du caractère " multiple de 3" obtenus sur m échantillons de n lancers de dés et qui retourne le pourcentage de fréquences qui se trouvent dans l'intervalle de fluctuation au seuil de $95$ % pour des échantillons de taille $n$ : $[p-\frac{1}{\sqrt{n}};p + \frac{1}{\sqrt{n}}]$. Pour utiliser la fonction racine carrée, on l'importe du module math avec from math import sqrt.
  4. Tester plusieurs fois cette fonction avec $(m,n)=(500,100)$ et $(m,n)=(500,400)$. Les résultats sont-ils conformes à ce que prévoit le cours de mathématiques ?

					
					
  • Fréquence sur un échantillon
  • Probabilité et intervalle de fluctuation
  • Proportion de fréquences dans l'intervalle de fluctuation
  • Expérimentation vs cours

On importe la fonction randint du module random afin de générer un entier aléatoire compris entre 1 et 6.


from random import randint

def freqMult3(n):
    compteur = 0
    for k in range(n):
        de = randint(1, 6)        
        if de == 3 or de == 6:
            compteur = compteur + 1
    return compteur / n

Pour n assez grand, freqMult3(n) retourne une fréquence proche de $\frac{1}{3}$ qui est la probabilité d'obtenir un multiple de $3$ lorsqu'on lance un dé équilibré à 6 faces numérotées de 1 à 6.

La probabilité d'obtenir un multiple de $3$ lorsqu'on lance un dé équilibré à 6 faces numérotées de 1 à 6 est $\frac{2}{6}=\frac{1}{3}$. Un intervalle de fluctuation au seuil de $95$ % de la fréquence de multiples de 3 obtenus sur un échantillon de $n$ lancers est $[\frac{1}{3}-\frac{1}{\sqrt{n}};\frac{1}{3}+\frac{1}{\sqrt{n}} ]$.

On importe la fonction randint du module random afin de générer un entier aléatoire compris entre 1 et 6, et la fonction sqrt du module math pour calculer une racine carrée.


from random import randint
from math import sqrt

def freqMult3(n):
    compteur = 0
    for k in range(n):
        de = randint(1, 6)        
        if de == 3 or de == 6:
            compteur = compteur + 1
    return compteur / n

def freqInterFluct(m, n):
    compteur = 0
    binf = 1/3 - 1/sqrt(n)
    bsup = 1/3 + 1/sqrt(n) 
    for echantillon in range(m):
        f = freqMult3(n)
        if binf <= f and f <= bsup:
            compteur = compteur + 1
    return compteur / m
On obtient des résultats conformes au cours avec des pourcentages de fréquences d'échantillonnage dans l'intervalle de fluctuation qui sont majoritairement supérieurs à $95$ %.

for k in range(10):
	print(freqInterFluct(500, 400))
0.976
0.958
0.976
0.972
0.966
0.976
0.952
0.972
0.974
0.964