Aller au contenu

Boucles bornées

Boucles bornées

Lorsque l'on doit répéter un nombre défini à l'avance de fois la même suite d'instructions, on utilise une boucle bornée ou boucle for pour en anglais.

La syntaxe Python est:

for i in range(n):
    bloc_instructions_1
bloc_instructions_2
La variable i va prendre successivement les valeurs 0, 1, 2 jusqu'à \(n-1\). Pour chacune des valeurs de i le bloc d'instructions bloc_instructions_1 est exécuté. Ensuite, s'il existe, le bloc d'instructions bloc_instructions_2 est exécuté.

Exemple

Voici deux programmes qui affichent quatre fois "Bonjour".

print("Bonjour")
print("Bonjour")
print("Bonjour")
print("Bonjour")

À l'aide d'une boucle:

for  i in range(4):
    print("Bonjour")

Exemple

La procédure table a pour paramètre un entier et affiche la table de multiplication de cet entier.

###
def table(nombre: int):bksl-nl """ bksl-nl Cette procédure affiche la table de multiplicationbksl-nl du paramètre nombre qui est un entier.bksl-nl """bksl-nl for i in range(11):bksl-nl # i prend successivement les valeurs de 0 à 10bksl-nl print(i,"fois", nombre, "égal", i py-str nombre)bksl-nl

La fonction range

Lorsqu'on utilise for i in range(a, b), i prend successivement les valeurs de a compris jusqu'à b non compris :

for i in range(6, 11):
    print(i)

Affiche:

6
7
8
9
10

Si on ne précise qu'une valeur, cette valeur correspond à b et a est considéré égal à 0 :

for i in range(4):
    print(i)

Affiche:

0
1
2
3

On peut aussi préciser une troisième valeur : le pas qui indique de combien on incrémente (augmente) ou décrémente (diminue) i à chaque passage dans la boucle. Par exemple pour faire augmenter i de deux en deux :

for i in range(3,10,2):
    print(i)

Affiche:

3
5
7
9

On peut aussi faire diminuer i en précisant un pas négatif :

for i in range(20,10,-3):
    print(i)

Affiche:

20
17
14
11

Avec le module tortue

Nous allons utiliser le module turtle tortue en anglais qui permet de faire se déplacer une tortue sur l'écran.

Pour l'utiliser vous devez commencer par écrire:

from turtle import *

Les commandes dont nous allons avoir besoin sont:

  • forward(pas) : la tortue avance de pas pixels.
  • left(degre) : la tortue tourne sur place de degre degrés vers la gauche.
  • right(degre) : la tortue tourne sur place de degre degrés vers la droite.

Pour plus de détails sur l'utilisation de ce module vous pouvez acceder au mémo du module turtle

Exemple

Ce programme définie une procédure carre qui lors de son appel fait tracer à la tortue un carré de coté 100.

###
from turtle import py-strbksl-nlbksl-nldef carre():bksl-nl for i in range(4): # Répète 4 fois:bksl-nl forward(100) # Avance de 100 pixelsbksl-nl left(90) # Tourne de 90 degrés vers la gauchebksl-nlbksl-nlcarre()bksl-nlbksl-nl

Boucle bornée et accumulateur

On s'intéresse à une fonction score_mot qui vérifie la spécification suivante : - prototype : - paramètre : une chaîne de caractères ch - valeur renvoyée : un nombre entier s

  • préconditions :

    • ch est composée de quatre caractères choisis parmi 'a' ou 'b' (par exemple 'babb'
  • postconditions :

    • la valeur renvoyée n correspond au score de ch où chaque 'a' vaut 1 point et chaque 'b' vaut 3 points.

Version n° 1

Cette fonction score_mot utilise quatre variables s0, s1, s2, s3 qui comptent les points de chacun des quatre caractères (grâce à la fonction score_lettre). Puis à la fin on effectue la somme de ces quatre variables pour avoir le score total.

Version 1

###
def scorepy-undlettre(car: str) -> int:bksl-nl if car == 'a':bksl-nl return 1bksl-nl else:bksl-nl return 3bksl-nlbksl-nldef scorepy-undmot(ch: str) -> int:bksl-nl s0 = scorepy-undlettre(ch[0]) #<------------- 4 variables s0, s1, s2, s3bksl-nl s1 = scorepy-undlettre(ch[1]) #<-bksl-nl s2 = scorepy-undlettre(ch[2]) #<-bksl-nl s3 = scorepy-undlettre(ch[3]) #<- bksl-nl score = s0 + s1 + s2 + s3 #<------------- qu'on additionne à la finbksl-nl return scorebksl-nlbksl-nls = scorepy-undmot('babb')bksl-nlprint(s)bksl-nl

Cette méthode ne serait pas généralisable avec un mot ch qui aurait un nombre quelconque de caractères (et pas exactement 4 caractères) car elle utilise une variable pour chaque caractère : c'est un défaut majeur.

Version n° 2 "Courte"

Cette version n’est pas plus générale mais permet d’utiliser moins de variables, est très courte et tout aussi compréhensible

Versions 2

###
def scorepy-undlettre(car : str) -> int:bksl-nl if car == 'a':bksl-nl return 1bksl-nl else:bksl-nl return 3bksl-nlbksl-nldef scorepy-undmot(ch: str) -> int:bksl-nl return scorepy-undlettre(ch[0]) + scorepy-undlettre(ch[1]) + scorepy-undlettre(ch[2]) + scorepy-undlettre(ch[3])bksl-nlbksl-nlbksl-nls = scorepy-undmot('babb')bksl-nlprint(s)bksl-nl

Version n°3 avec accumulateur

On utilise l'algorithme naturel que l'on utiliserait à la main et qui utilise un «accumulateur». Par exemple pour calculer le score de 'babb' de tête on ferait : - 'b' : score = 3 points - 'a' : score = 3 + 1 = 4 points - 'b' : score = 4 + 3 = 7 points - 'b' : score = 7 + 3 = 10 points

Lorsqu'on effectue ce calcul de tête on utilise donc un «accumulateur» qui stocke les points au fur et à mesure qu'on lit le mot 'babb'.
On peut également utiliser cette méthode avec notre fonction score_mot. Ce qui donne alors :

Version 3

###
def scorepy-undlettre(car: str) -> int:bksl-nl if car == 'a':bksl-nl return 1bksl-nl else:bksl-nl return 3bksl-nlbksl-nldef scorepy-undmot(ch: str) -> int:bksl-nl score = 0bksl-nl score = score + scorepy-undlettre(ch[0]) #<------------- 1 seule variable scorebksl-nl score = score + scorepy-undlettre(ch[1]) #<- qui accumule les points bksl-nl score = score + scorepy-undlettre(ch[2]) #<- au fur et à mesurebksl-nl score = score + scorepy-undlettre(ch[3]) #<- bksl-nl return scorebksl-nlbksl-nls = scorepy-undmot('babb')bksl-nlprint(s)bksl-nl

Cette façon de coder a deux avantages : - d'une part elle traduit simplement ce que nous ferions «de tête», - et surtout (ce que nous verrons plus bas) elle permet de mettre en évidence une même instruction répétée quatre fois ce qui va nous être utile pour calculer le score d'un mot ayant un nombre quelconque de caractères.

Remarque

Ici la variable score est initialisée à 0 puis sert à y accumuler des points qu'on additionne au fur et à mesure. On parle d'un accumulateur : c'est un concept qui est très souvent utilisé en programmation (c'est justement parce qu'il est souvent utilisé qu'on lui a donné un nom).

Version 4

Dans la version précédente, on a donc quatre fois la même instruction avec seule- ment l’indice du caractère qui varie de 0 (compris) à 4 (non compris). Or tous les langages de programmation permettent de répéter une instruction avec un in- dice i qui varie. En python les quatre instructions ci-dessus peuvent ainsi être remplacées par :

for i in range(4): 
    score = score + score_lettre(ch[i])

Ce qui donne:

Version 4

###
def scorepy-undlettre(car: str) -> int:bksl-nl if car == 'a':bksl-nl return 1bksl-nl else:bksl-nl return 3bksl-nlbksl-nldef scorepy-undmot(ch: str) -> int:bksl-nl score = 0bksl-nl for i in range(0, 4):bksl-nl score = score + scorepy-undlettre(ch[i])bksl-nl return scorebksl-nlbksl-nls = scorepy-undmot('babb')bksl-nlprint(s)bksl-nl

Le code est plus court, mais l’intérêt principal est qu’il est facilement généralisable à une chaîne de caractères ch de taille quelconque. Il suffit de faire varier La fonction range i entre 0 et len(ch) et pour cela de remplacer for i in range(0,4): par for i in range(0,len(ch)):

Version finale

###
def scorepy-undlettre(car: str) -> int:bksl-nl if car == 'a':bksl-nl return 1bksl-nl else:bksl-nl return 3bksl-nlbksl-nlbksl-nldef scorepy-undmot(ch : str) -> int:bksl-nl score = 0bksl-nl for i in range(0, len(ch)): #<-- remarquer le changement icibksl-nl score = score + scorepy-undlettre(ch[i])bksl-nl return scorebksl-nlbksl-nls = scorepy-undmot('abbabaabaaabbbaabbaba')bksl-nlprint(s)bksl-nlprint(scorepy-undmot('aaaaaaaaaabbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'))bksl-nlprint(scorepy-undmot('aba'))bksl-nlbksl-nl

Cette amélioration est fondamentale en algorithmique puisque :

  • On travaille souvent sur des données composées de plein d’éléments (ici un mot est composé de plein de caractères) ;
  • La taille de ces données est souvent variable.

Une “boucle for” permet donc de faire des algorithmes qui s’adaptent à la taille des données qui lui sont fournies. Dans cet exemple il est important de comprendre que c’est la démarche naturelle.

À chaque tour de “boucle” :

  • On lit un caractère
  • On traite l’information ( on retourne 1 si la lettre est “a” et 3 sinon)
  • On ajoute cette information à l’accumulateur (on ajoute l’information à l’accumulateur score )

Lorsqu’on « lit » les uns après les autres tous les éléments d’une donnée composée, on dit qu’on « parcourt » cette donnée composée. On peut ainsi : - parcourir tous les caractères d’une chaîne de caractères; - parcourir tous les chiffres d’un nombre; - parcourir tous les éléments d’une liste, ce que nous verrons plus tard.

Lorsqu’on initialise puis « accumule » plein d’informations dans une même variable, on dit que cette variable est un « accumulateur ».