Les boucles while#

En programmation, il y a des ensembles d’instructions qu’il faut répéter plusieurs fois. Par exemple, si vous voulez réaliser une même tâche sur tous les éléments d’une liste.

Quand vous avez besoin de répéter un ensemble d’instructions, parfois vous savez combien de fois vous allez le répéter, d’autres fois vous ne savez pas. Parfois, le nombre de répétitions n’est pas important, et vous voulez répéter le code jusqu’à ce qu’une certaine condition soit remplie.

Pour tous ces usages, vous allez utiliser des boucles.

Le rôle d’une boucle while est d’exécuter un bloc de code, c’est-à-dire un certain nombre d’instructions, tant qu’une condition est vraie.

Une boucle while en Python commence donc toujours par un test logique. Python vérifie si une condition est vraie : si elle ne l’est pas, on ne rentre même pas dans la boucle ! En revanche, si la condition est vraie, Python exécute le bloc de code qui est juste en dessous.

Une fois la première itération effectuée, Python vérifie à nouveau si la condition est vraie ou non. Tant que la condition est vraie, Python exécute une nouvelle fois le bloc de code.

La boucle while s’arrête lorsque le test logique n’est plus vérifié. Alors, il n’exécute pas le bloc de code en dessous, et sort de la boucle. La suite du programme prend le relais.

Lorsqu’on écrit une boucle WHILE, il faut faire attention à deux choses :

  • la première ligne se termine toujours par deux points “:”

  • le bloc de code qui contient les instructions doit être indiqué par une indentation. C’est comme ça que Python fait la différence entre ce qui est inclus dans la boucle while, et le reste du programme.

Exécutez la cellule suivante et observez le résultat :

n = 1

while n <= 5:
    print(n)
    n = n + 1 
1
2
3
4
5

Nous avons réalisé un programme permettant de compter de 1 à 5.

Exercice 1 : première boucle while#

  • Exécutez la cellule suivante :

n = 1
a = 5
while n <= a:
    print(n)
    n += 1 
1
2
3
4
5
  • Modifiez la valeur de a ci-dessus pour obtenir :

  • Exactement 1 affichage

  • Exactement 0 affichage

  • Exactement 4 affichages

Exercice 2 : Panique dans le noir#

Notre fourmi est perdue dans un labyrinthe plongé dans le noir. Elle panique! Avant chaque pas, elle tourne aléatoirement vers la gauche ou vers la droite. Va-t-elle trouver la sortie?

À vous de le découvrir en programmant ce comportement de la fourmi!

Pour simuler le noir, nous avons écrit une fonction qui place la porte de façon aléatoire. Exécutez les deux cellules suivantes. À chaque création du labyrinthe, la porte est placée dans un endroit différent. Le même programme doit toujours fonctionner !

Indications:

  • Vous pouvez utiliser la condition regarde() != Sortie;

  • Pour tirer à pile ou face si la fourmi va tourner à gauche ou à droite, vous pouvez utiliser la fonction random.randint(0,1) qui renvoie aléatoirement 0 ou 1.

import random
def porteAleatoire():
    s = "o o o o o o o\n"
    s += "o → . . . . o\n"
    ligne = random.randint(0, 3)
    col = random.randint(0, 4)
    for i in range(4):
        s += "o "
        for j in range(5):
            if ( i == ligne and j == col ):
                s += "x "
            else:
                s += ". "
        s += "o\n"
    s += "o o o o o o o\n"
    return s

from laby.global_fr import *
Laby(carte = porteAleatoire())
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[3], line 18
     15     s += "o o o o o o o\n"
     16     return s
---> 18 from laby.global_fr import *
     19 Laby(carte = porteAleatoire())

ModuleNotFoundError: No module named 'laby'
debut()
### BEGIN SOLUTION
while ( regarde() != Sortie ):
    if ( random.randint(0,1) == 0 ):
        gauche()
    else:
        droite()
    avance()
ouvre()
### END SOLUTION

Exercice 3 : division euclidienne par soustraction#

  • Observez les cellules suivantes et donnez des valeurs à \(b\) et \(c\) avec \(b > c\) telles que, à la fin de la boucle, on ait \(b=3\) :

b = 0 #Remplacez les 0
c = 0
### BEGIN SOLUTION
b = 18;
c = 5;
### END SOLUTION
while ( b >= c ):
    b = b - c
b

Test automatique (ne doit rien afficher) :

assert( b == 3 )
  • Modifiez la cellule ci-dessous pour que la variable \(k\) compte le nombre d’exécutions de la boucle;

  • Donnez des valeurs à \(b\) et \(c\) telles que l’on ait \(b=3\) et \(k=5\) à la fin de la boucle.

k = 0
b = 0
c = 0
### BEGIN SOLUTION
b = 23;
c = 4;
k = 0;
### END SOLUTION
while ( b >= c ):
    b = b - c
    ### BEGIN SOLUTION
    k = k + 1
    ### END SOLUTION
b     # doit afficher 3
k     # doit afficher 5

Tests automatiques :

assert( b == 3 )
assert( k == 5 )

Exercice 4 : suite de Syracuse#

  • Exécutez, sans la modifier, la cellule ci-dessous puis trois fois la deuxième cellule :

d = 5
if ( d % 2 == 0):
    d = d / 2;
else:
    d = 3 * d + 1
print(d)

Vous noterez que lorsque le nombre \(d\) est pair, on le divise par 2. Lorsqu’il est impair, on le multiplie par 3 et on ajoute 1.

  • Réécrivez la cellule en la complétant pour que l’on répète cette action tant que le nombre \(d\) est supérieur à 1. On veut afficher la valeur de \(d\) à chaque fois. Si votre code est correct, il doit afficher 16 8 4 2 1 (en partant de d=5).

### BEGIN SOLUTION
d = 5
while d > 1:
    if d % 2 == 0:
        d = d / 2;
    else:
        d = 3 * d + 1
    print(d)
### END SOLUTION

Exercice 5#

  • Obervez la fonction suivante et essayez de comprendre ce qu’elle calcule en lisant le code et en essayant plusieurs valeurs d’appel :

def mystere(n):
    k = 1
    while k * k < n:
        k = k + 1
    return k
mystere(5)
  • Déterminez une valeur de n tel que la valeur renvoyée soit 6 :

n = 0
### BEGIN SOLUTION
n = 36
### END SOLUTION
mystere(n)
assert( mystere(n) == 6 )

La boucle while : d’autres exemples#

Cas particulier : condition toujours fausse#

Si la valeur de la condition est fausse dès le départ, alors le bloc d’instructions ne sera jamais exécuté!

n = 1

while n <= 0:
    print(n)   ## Affiche la valeur de n
    n = n + 1;

Cas particulier : condition toujours vraie#

Si la valeur de la condition est toujours vraie, alors le bloc d’instructions sera exécuté indéfiniment!

Avertissement

Attention ⚠️ L’exemple suivant ne va pas s’arrêter! Il faudra redémarrer le noyau (menu Noyau) ⚠️

int n = 1

while True:
    print(n)    # Affiche la valeur de n
    n = n + 1

Erreur classique : fin de boucle#

Que vaut \(n\) à la fin du programme suivant?

n = 1

while n <= 5:
    n = n + 1

print(n)

À retenir :

  • On sort de la boucle quand la condition vaut «Faux»; le compteur est donc «un cran trop loin».

Bilan#

Vous pouvez à présent vous entraîner sur des exercices supplémentaires en exécutant la cellule suivante, ou retourner à l’index et passer à la feuille sur les boucles for. Vous pourrez, par la suite, aborder l’exercice plus avancé ci-dessous.

Exercices supplémentaires#

from glob import glob
from jupylates import Exerciser
Exerciser(glob("../Exercices/boucles-while/*"), lrs_url="../Exercices/.lrs.json", mode="train")

Exercice 6 ♣#

  • Complétez le code de la fonction suivante pour qu’elle détermine si \(n\) est un carré parfait. Dans ce cas, elle doit renvoyer true; sinon elle doit renvoyer false.

    Rappel: un carré parfait est un nombre qui peut s’écrire \(k\times k\) avec \(k\) un entier. Par exemple \(16\) est un carré parfait car \(16 = 4 \times 4\), mais \(20\) n’est pas un carré parfait.

def carreParfait(n):
    ### BEGIN SOLUTION
    k = 0
    while ( k * k < n ):
        k = k + 1
    return k*k == n
    ### END SOLUTION
  • Essayez votre fonction sur les exemples suivants :

carreParfait(16)  # doit renvoyer true
carreParfait(20)  # doit renvoyer false
  • Vérifiez que votre fonction passe les tests automatiques suivants :

assert( carreParfait(0) )
assert( carreParfait(1) )
assert( not carreParfait(2) )
assert( not carreParfait(50) )
assert( carreParfait(100) )
assert( not carreParfait(250) )

Retourner à l’index