Instructions conditionnelles

\(\newcommand{\ds}{\displaystyle}\) \(\newcommand{\Frac}{\ds\frac}\) \(\renewcommand{\r}{\mathbb{ R}}\) \(\newcommand{\C}{\mathbb{ C}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\z}{\mathbb{ Z}}\) \(\newcommand{\Q}{\mathbb{ Q}}\) \(\newcommand{\N}{\mathbb{ N}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\ol}{\overline}\) \(\newcommand{\abs}[1]{\left| \,{#1} \right|}\) \(\newcommand{\pv}{\;;\;}\) \(\newcommand{\ens}[1]{\left\{ {#1} \right\}}\) \(\newcommand{\mens}[1]{\setminus\left\{ {#1} \right\}}\) \(\newcommand{\Par}[1]{\left({#1}\right)}\) \(\newcommand{\pe}[1]{\left\lfloor {#1} \right\rfloor}\) \(\newcommand{\trans}[1]{\,^t\!{#1}}\)

Instructions conditionnelles

Cours

Instruction if

L’instruction if permet de coder un schéma logique du type

si … alors …

Illustration

On veut coder un programme qui :

  • définit une variable x référant un entier,

  • affiche la valeur de x,

  • teste si x est strictement négatif et, si c’est le cas, affiche :

    • le message : x est négatif,
    • l’opposé de x (c’est-à-dire -x),
  • se termine en affichant le message Fin du programme.

Voilà ce que pourrait afficher le programme si la variable x dans le code-source vaut 10 :

-10
x est négatif
10
Fin du programme

Le programme sera intitulé instruction_if.py.

Implémentation en Python

Le programme instruction_if.py doit afficher un message et un nombre si une certaine condition est vérifiée. Pour cela, en Python, on utilise

  • une instruction if pour exprimer l’idée de condition si … alors …
  • un booléen pour exprimer la condition si.

Le problème posé admet la solution suivante :

instruction_if1.py

1
2
3
4
5
6
7
8
x = -10
print(x)

if x < 0:
    print("x est négatif")
    print(-x)

print("Fin du programme")
 9
10
11
12
-10
x est négatif
10
Fin du programme

Examinons maintenant le même code que instruction_if1.py où on a remplacé x = -10 par x = 42 en ligne 1 :

instruction_if2.py

1
2
3
4
5
6
7
8
x = 42
print(x)

if x < 0:
    print("x est négatif")
    print(-x)

print("Fin du programme")
 9
10
42
Fin du programme

L’édition d’une instruction if

On reprend le code ci-dessus :

instruction_if1.py

1
2
3
4
5
6
7
8
x = -10
print(x)

if x < 0:
    print("x est négatif")
    print(-x)

print("Fin du programme")
  • Lignes 4-6 : une instruction conditionnelle. Elle utilise le mot-clé if.

  • Ligne 4 : la condition testée est x < 0. Cette condition est toujours suivie du séparateur : (deux-points). La ligne qui s’étend du mot-clé if jusqu’au séparateur s’appelle l”en-tête de l’instruction if.

  • Lignes 5-6 : le corps de l’instruction if est le bloc situé aux lignes 5 et 6. Ce corps, la plupart du temps :

    • commence sous l’en-tête (il faut donc sauter une ligne) ;
    • est indenté par rapport à l’en-tête.

Exécution d’une instruction if

On reprend les codes ci-dessus :

instruction_if1.py

1
2
3
4
5
6
7
8
x = -10
print(x)

if x < 0:
    print("x est négatif")
    print(-x)

print("Fin du programme")

ainsi que

instruction_if2.py

1
2
3
4
5
6
7
8
x = 42
print(x)

if x < 0:
    print("x est négatif")
    print(-x)

print("Fin du programme")
  • Ligne 1 : très souvent, la condition de l’instruction if dépend d’une variable définie avant l’instruction if. Ici, la variable s’appelle x.

  • Ligne 4 : lorsque l’exécution du code arrive face à une condition if, la condition if est testée : vaut-elle True ? vaut-elle False ?

  • Lignes 5-6 :

    • si la condition vaut True (cf. instruction_if1.py), les instructions du corps de if sont exécutées
    • si la condition vaut False (cf. instruction_if2.py), les instructions du corps de if sont ignorées et l’exécution passe directement à la suite du code (ligne 8)
  • Ligne 8 : Une fois l’instruction if exécutée, l’exécution continue normalement.

Indentation d’une instruction composée

Soit le code d’une instruction if typique :

1
2
3
4
5
6
7
x = -100

if x < 0:
    print("x est negatif")
    print(-x)

print("Fin du programme")

Le programme ci-dessus contient trois instructions :

  • Ligne 1 : une instruction simple (affectation)
  • Lignes 3-5 : l’instruction if qui est une instruction composée.
  • Ligne 7 : une instruction simple (instruction d’affichage)

Ces trois instructions sont indentées avec la même valeur d’indentation qui est de 0 espace par rapport à la marge gauche du code.

On observe toutefois (lignes 4-5) que certaines lignes du code sont indentées.

Règles fondamentales de l’indentation

L’instruction if (lignes 3-5) est une instruction composée et son indentation doit respecter deux règles fondamentales :

  • Règle 1 : si le corps de l’instruction if est placé sur plusieurs lignes, ce corps est indenté par rapport à la ligne d’en-tête ;
  • Règle 2 : toutes les instructions dans le corps de l’instruction sont à la même indentation. Autrement dit, si par exemple la 1ère instruction du corps de l’instruction if (ici ligne 4) est indentée de 4 espaces par rapport à l’en-tête, toutes les autres instructions du corps de l’instruction if, par exemple ici la ligne 5, seront aussi indentées de 4 espaces par rapport à l’en-tête.

Non-respect des règles

Règle 1

Le code ci-dessous ne respecte pas la règle 1 :

1
2
3
4
5
6
7
x = -100

if x < 0:
print("x est negatif")
print(-x)

print("Fin du programme")
  • Lignes 4-5 : ces deux lignes devraient être indentées.

et l’exécution va générer un message d’erreur d’indentation au niveau de la ligne 4 :

 7
 8
 9
10
  File "if_erreur1_indentation.py", line 4
    print("x est negatif")
        ^
IndentationError: expected an indented block
  • Lignes 8-11 : Le message d’erreur.
  • Lignes 8 : Le nom du fichier-source et le numéro de ligne à l’origine de l’erreur sont fournis.
  • Lignes 9-10 : La ligne à l’origine de l’erreur et un marqueur (le signe circonflexe ^) signalant où l’erreur est rencontré dans la ligne.
  • Ligne 11 : Le type d’erreur, ici IndentationError (erreur d’indentation) et une description sommaire de la raison de cette erreur.
Règle 2

Le code ci-dessous ne respecte pas la règle 2 :

if_erreur2_indentation.py

1
2
3
4
5
6
7
x = -100

if x < 0:
     print("x est negatif")
    print(-x)

print("Fin du programme")
  • Lignes 4-5 : ces deux lignes devraient être à un même niveau d’indentation. Or la ligne 4 est indentée de 5 espaces et la ligne suivante de 4 espaces au lieu de 5.

et l’exécution va générer un message d’erreur d’indentation au niveau de la ligne 5:

if_erreur2_indentation.py

 7
 8
 9
10
  File "if_erreur2_indentation.py", line 5
    print(-x)
            ^
IndentationError: unindent does not match any outer indentation level
  • Ligne 10 : Le message explique que l’indentation n’est pas uniforme. L’indentation de la ligne 4 est acceptée pas celle de la ligne 5.

Noter que la règle d’indentation s’applique aussi à une instruction if emboîtée :

1
2
3
4
5
n = 3000
if n % 10 == 0:
    q = n // 10
    if q % 10 == 0:
        print("n est multiple de 100")
  • Lignes 4-5 : instruction composée emboîtée.

Instruction if/else

L’instruction if/else permet de coder un schéma du type

si … alors … sinon …

Soit un programme qui à partir d’un nombre \(\mathtt{x}\) affiche plus si \(\mathtt{x > 42}\) et qui sinon affiche moins. En Python, cela donne :

if_else.py

1
2
3
4
5
6
7
x=10
if x > 42:
    print("plus")
else:
    print("moins")

print("FIN")
8
9
moins
FIN
  • Ligne 2 : comme dans une instruction if simple, la condition est testée

  • Lignes 2-5 : l’instruction if/else

  • Ligne 4 : si la condition N’est PAS vérifiée,

    • la partie sous le if N’est PAS examinée
    • le bloc sous le else est exécuté
  • Ligne 7 : l’exécution du programme continue alors normalement.

Inversement, si la condition suivant le if est vérifiée la partie else n’est pas examinée :

if_else_bis.py

1
2
3
4
5
6
7
x=50
if x > 42:
    print( "plus")
else:
    print("moins")

print("FIN")
8
9
plus
FIN
  • Ligne 2 : ici, la condition x > 42 est vérifiée donc seule la ligne 3 est examinée
  • Lignes 4-5 : ces lignes ne sont pas examinées durant l’exécution.

Le mot else doit être compris comme sinon. Une instruction if/else propose une alternative. Ainsi, le programme if_else.py doit être compris comme codant l’alternative suivante :

  • si \(\mathtt{x > 42 }\) alors le programme affiche plus
  • sinon, le programme affiche moins

Le mot else est un mot-clé du langage Python. Dans le cadre d’une instruction if/else, le mot else doit toujours être suivi du signe deux-points (:). Sous la ligne figurant else se trouve un bloc indenté. La ligne contenant else ainsi que le bloc indenté forment ce qu’on appelle une clause else de l’instruction if. Le corps de la clause else est le bloc indenté. Ce corps peut être constitué de n’importe quel type d’instructions.

C’est une erreur courante chez les débutants de vouloir placer une condition après le else, par exemple else x<42. Une clause else est toujours suivie immédiatement du signe :.

Quand on écrit une instruction if/else, prendre garde que le mot if et le mot else soient à la même indentation et rien d’autre ne doit être à la même indentation entre if et else.

Le terme d’instruction if/else est un abus de langage. En fait, il s’agit d’une instruction if contenant une clause else.

if/else pour un booléen : complication inutile

On rencontre souvent des situations où on doit créer une variable booléenne, disons flag, qui vaut True si une condition est vraie et False sinon.

Par exemple, on se donne un entier n et flag doit évaluer si n est pair ou pas. Un code courant est alors le suivant :

n=42

if n%2==0:
    flag=True
else:
    flag=False

print(flag)
True

Mais ce code est maladroit et à éviter. En effet, flag a toujours la même valeur que la condition n%2==0, donc un code équivalent est

n=42
flag = n%2==0

print(flag)
True

C’est un idiome à connaître et valable dans deux nombreux langages de programmation.

Indentation d’une instruction composée avec clause

Une instruction composée est constituée au minimum d’un en-tête et d’un corps, typiquement :

1
2
3
if 42 > 421:
    print("hello!")
    print("OK!")
  • Ligne 1 : l’en-tête
  • Lignes 2-3 : corps composé de deux instructions.

Mais, certaines instructions composées peuvent être composées aussi d’une, voire de plusieurs, « clauses ».

Le cas suivant d’une instruction if/else est typique de la structure générale d’une instruction composée avec clause:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
x=50
if x > 42:
    print( "plus")
    if x > 100:
        print("plus plus")
else:
    print(x)
    print("moins")

print("FIN")
  • Lignes 2-8 : une instruction if
  • Lignes 6-8 : une clause else de l’instruction if
  • Lignes 3-5 : le corps de l’instruction if. Ce corps est constitué de deux instructions : une instruction simple (ligne 3) et une instruction composée (if, lignes 4-5)
  • Lignes 6-8 : le corps de la clause else.

Les clauses font partie de l’instruction composée. Chaque clause contient un en-tête placé sur une seule ligne et qui se termine toujours par le signe deux-points. Le signe deux-points est suivi d’un ensemble d’instructions appelé « corps » de la clause.

Règles d’indentation

Soit une instruction composée contenant une ou plusieurs clauses. Alors,

  • l’en-tête de l’instruction composée et chacune des clauses sont sur des lignes différentes et à la même indentation ;
  • les instructions figurant dans le corps de l’instruction composée sont à la même indentation ;
  • les instructions figurant dans le corps de n’importe quelle clause de l’instruction composée sont à la même indentation ;
  • le corps de l’instruction composée ou de l’une de ses clauses peut contenir des instructions de n’importe quel type, simples ou composées. Ces instructions suivent les règles générales de l’indentation en Python.

Instructions if imbriquées

Le corps d’une instruction if peut être n’importe quelle instruction, en particulier une nouvelle instruction if.

Exemple :

n = 3000
if n % 10 == 0:
    q = n // 10
    if q % 10 == 0:
        print(n, "est multiple de 100")
3000 est multiple de 100

Une instruction if est une instruction multiple. Le corps d’une instruction if peut être de taille quelconque et contenir tout type d’instructions.

Dans certains cas, deux instructions if imbriquées s’écrivent plus simplement avec une seule instruction if et une expression and. En nous basant sur l’exemple précédent, le code

n = 3000
if n % 10 == 0:
    if (n // 10) % 10 == 0:
        print(n, "est multiple de 100")
3000 est multiple de 100

sera plutôt ré-écrit ainsi :

n = 3000
if n % 10 == 0 and (n // 10) % 10 == 0:
        print(n, "est multiple de 100")
3000 est multiple de 100

Instruction if/elif

L’instruction if/elif permet de coder un schéma du type

si … alors … sinon si …

Voici un exemple typique d’utilisation d’une instruction if/elif

if_elif.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
m = 2
print(m)

if m == 1:
    print("Or")
elif m == 2:
    print("Argent")
elif m == 3:
    print("Bronze")

print("bonjour !")
12
13
14
2
Argent
bonjour !

L’exécution est la suivante :

  • Au départ, m vaut 2 et la valeur de m est affichée
  • Le programme passe à la ligne 4 et teste (à cause du if) si m vaut 1.
  • Comme ce n’est pas le cas, le programme passe à la ligne 6 (à cause du elif) et teste si m vaut 2.
  • Comme c’est le cas, la ligne 7 est exécutée et Argent est affiché.
  • Les lignes 8-9 sont alors ignorées.
  • Finalement, l’exécution passe à la ligne 11.

Le mot elif est un mot-clé du langage Python.

Une clause elif (lignes 6-7 ou encore 8-9) est constituée de deux parties :

  • un en-tête placé sur une ligne et terminé par deux-points
  • un corps, le plus souvent indenté par rapport à l’en-tête.

L’en-tête contient obligatoirement une condition qui sera testée à l’exécution.

Le mot-clé elif d’une instruction if est toujours aligné verticalement avec le mot-clé if.

Les clauses elif constituent des blocs de code qui sont à la même indentation que le corps de l’instruction if.

elif est un mot-valise construit de la manière suivante :

elif = else + if.

Il faut comprendre elif comme voulant signifier sinon si.

On dit que les parties du code contenant un bloc elif sont des clauses elif. Parler d’instruction if/elif est un abus de langage, il s’agit en fait d’une instruction if contenant une ou plusieurs clauses elif.

Suite de if vs suite de if/elif

Comparons une suite d’instructions if/elif à une suite d’instructions où elif est remplacé par if.

Par exemple, comparons les codes suivants :

if_elif.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
m = 1
print(m)

if m == 1:
    print("Or")
elif m == 2:
    print("Argent")
elif m == 3:
    print("Bronze")

print("bonjour !")

suite_if.py

12
13
14
15
16
17
18
19
20
21
22
m = 1
print(m)

if m==1:
    print("Or")
if m==2:
    print("Argent")
if m==3:
    print("Bronze")

print("bonjour!")

Les deux codes affichent la même chose :

1
2
3
1
Or
bonjour !

Pourtant, les deux exécutions de code ne sont pas équivalentes :

  • code if_elif.py : les conditions lignes 6 et 8 ne sont même pas examinées car les lignes 4-5 sont exécutées ;
  • code suite_if.py, les trois conditions (lignes 15, 17 et 19) sont toujours testées ce qui n’est pas pertinent puisque les différentes conditions testées s’excluent mutuellement.

Il se pourrait d’ailleurs que dans certains cas, les affichages ne soient pas identiques. Pour cela comparer les deux codes suivants.

Premier code

1
2
3
4
5
m=0
if m>=0:
    print("m est positif")
if m<=0:
    print("m est negatif")
6
7
m est positif
m est negatif
  • Lignes 2-3 : l’affichage est exécuté car 0 >= 0 est True
  • Lignes 4-5 : l’affichage est exécuté car 0 <= 0 est aussi True
  • Lignes 6-7 : deux lignes sont affichées

Deuxième code :

1
2
3
4
5
m=0
if m>=0:
    print("m est positif")
elif m<=0:
    print("m est negatif")
6
m est positif
  • Lignes 2-3 : l’affichage est exécuté car 0 >= 0 est True
  • Ligne 4 : la condition n’est pas testée car la condition ligne 2 a été testée
  • Ligne 6 : une seule ligne est affichée.

Les conditions if/elif

Exclusion mutuelle ?

Soit le code if_elif.py :

if_elif.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
m = 2
print(m)

if m == 1:
    print("Or")
elif m == 2:
    print("Argent")
elif m == 3:
    print("Bronze")

print("bonjour !")

Les différentes conditions if/elif du code if_elif.py (ici m == 1, m == 2, m == 3) s’excluent mutuellement ce qui est le cas le plus fréquent en pratique ; mais ce n’est pas obligatoire. Par exemple, soit l’extrait de code suivant qui teste le signe d’un nombre x :

1
2
3
4
if x>=0:
    print("positif")
elif x<= 0:
    print("negatif")

Ici, les conditions x>=0 et x<=0 ne sont pas incompatibles puisque x=0 vérifie les deux. Si on exécute le code avec x=0, on obtient :

1
2
3
4
5
x=0
if x>=0:
    print("positif")
elif x<= 0:
    print("negatif")
6
positif

Comme la condition ligne 2 est vérifiée, la ligne 4 n’est pas testée.

Cas où aucun corps if/elif n’est exécuté

Il se peut d’autre part que le corps d’AUCUNE instruction if ou elif ne soit exécuté, par exemple :

1
2
3
4
5
6
7
8
9
m=5
if m==1:
    print ("Or")
elif m==2:
    print("Argent")
elif m==3:
    print("Bronze")

print("bonjour !")
10
bonjour !
  • La ligne 2 est testée.
  • Comme la condition est fausse, la ligne 3 est sautée
  • L’instruction elif ligne 4 est testée. A nouveau, elle est fausse
  • Donc, l’instruction elif de la ligne 6 est testée. Comme elle est encore fausse, la ligne 7 est sautée et aucun nom de médaille n’est affiché.
  • L’exécution passe à la ligne 9.

Instruction if/elif/else

L’instruction if/elif/else correspond au schéma suivant :

si … alors … sinon si … alors sinon ….

Il est possible d’associer à une instruction if

  • un ou plusieurs elif,
  • un else unique.

Voici un exemple basique

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
m=5
if m==1:
    print("Or")
elif m==2:
    print("Argent")
elif m==3:
    print("Bronze")
else :
    print("Sans médaille")

print("FIN")
12
13
Sans médaille
FIN
  • Ligne 1 : l’exécution de l’instruction if/elif/else aux lignes 2-9 dépend de la valeur initiale de m.
  • Lignes 2-7 : les conditions ligne 2, ligne 4 et ligne 6 sont testées dans cet ordre tant qu’elles sont fausses. Le corps de la première (éventuelle) condition vraie est exécuté.
  • Lignes 8-9 : si aucune des conditions n’est vraie alors le corps du else (ligne 9) est exécuté. C’est le cas ici puisque m = 5 (cf. la ligne 1).

La clause else est unique et doit apparaître après les clauses elif.

A la différence d’une instruction if simple ou d’une instruction if/elif, dans une instruction if/elif/else, comme dans une instruction if/else, au moins un des corps de l’instruction sera exécutée.

Exercice type : Le plus grand, le plus petit

Cet exercice est corrigé en vidéo : ICI

On donne deux entiers \(\mathtt{a}\) et \(\mathtt{b}\). Ecrire un code qui calcule le plus petit et le plus grand des deux entiers \(\mathtt{a}\) et \(\mathtt{b}\). Les valeurs calculées seront placées dans des variables mini et maxi.

Solution

Il suffit de comparer les deux nombres pour savoir qui est mini et qui est maxi, d’où le code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
a = 42
b = 17

if a < b:
    mini=a
    maxi=b
else:
    mini=b
    maxi=a

print(a, b)
print("mini =", mini, "maxi =", maxi)
13
14
42 17
mini = 17 maxi = 42

Il est intéressant de remarquer que des variables mini et maxi sont créées à la fin du code sans que pour autant on ait en tout début de code (comme pour a et b) une définition par affectation de ces variables : dans le corps d’une instruction if on peut placer n’importe quel type d’instruction qu’on aurait placée en début de code.

On pouvait aussi écrire le code suivant qui évite le else :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
a = 42
b= 17

maxi=a
mini=b

if a < b:
    mini=a
    maxi=b

print(a, b)
print("mini =", mini, "maxi =", maxi)

Exercice type : Régler un montant avec des coupures de même valeur

On vous donne la valeur b d’un billet en euros, par exemple b = 10 et un montant m, nombre entier représentant un montant en euros à régler, par exemple, m = 8181. Déterminer le nombre minimum N de billets de b euros pour être en mesure de régler le montant m.

Par exemple,

  • si b = 10 et m = 8181 alors N = 819
  • si b = 10 et m = 800 alors N = 80

Solution

Il y a deux cas selon que le montant peut être réglé de manière exacte avec des billets de montant b. Par exemple, si b=10 et m=8181, le montant ne peut être réglé de manière exacte (sans rendu de monnaie). Le nombre exact de billets est clairement 819 car avec 818 billets on peut régler jusqu’à 8180 euros (et il manque 1 euro) et avec un billet de plus, on peut régler le montant (et il restera neuf euros) ; ce dernier nombre (819) est une unité de plus que le quotient entier de m par b. D’où le code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
b= 10
m=8181
N=m//b
r=m%b
if r!=0:
    N=N +1
print("b = ", b, "m =", m, "->", N)
print("->", N)

print()

b= 10
m=800
N=m//b
r=m%b
if r!=0:
    N=N +1
print("b = ", b, "m =", m, "->", N)
print("->", N)
20
21
22
23
24
b =  10 m = 8181 -> 819
-> 819

b =  10 m = 800 -> 80
-> 80
  • Lignes 16 et 17 : s’il est possible de payer exactement la somme m avec des billets b alors la condition ligne 16 est fausse et c’est N qui donne la réponse attendue.

On peut aussi utiliser else:

if m%b!=0:
    N=m//b +1
else:
    N=m//b

Exercices

Ordonner trois entiers

On donne trois entiers a, b et c et on demande d’écrire un programme qui affiche ces trois entiers dans l’ordre croissant.

Nombre d’éléments distincts

On donne trois variables a, b, c référant des entiers et on demande de donner le nombre N de valeurs distinctes parmi les trois.

Voici quelques exemples d’affichages possibles

a = 1, b = 1, c = 1 -> N = 1
a = 2, b = 4, c = 3 -> N = 3
a = 2, b = 2, c = 3 -> N = 2

Afficher l’écart entre deux nombres

On donne deux entiers a et b et on demande d’afficher un message comme ci-dessous :

L'écart entre a et b est de e

où a, b et e sont remplacées par les valeurs adaptées. Voici quelques exemples de comportement :

82 , 42 -> L'écart entre 82 et 42 est de 40
1970 , 2038 -> L'écart entre 1970 et 2038 est de 68
42 , 42 -> L'écart entre 42 et 42 est de 0
42 , -10 -> L'écart entre 42 et -10 est de 52

Nombre intermédiaire

Cet exercice est corrigé en vidéo : ICI

On donne trois entiers \(a\), \(b\) et \(c\), par exemple \(a=42\), \(b=100\) et \(c=10\). On demande de déterminer et d’afficher le nombre qui est encadré par les deux autres. Dans l’exemple précédent, on a \(c\leq a\leq b\) donc le nombre demandé est \(a=42\).

Dans un deuxième temps, on pourra essayer de chercher un code qui minimise le nombre de comparaisons.

Date valide (if\elif)

On donne une date en utilisant deux variables jour et mois deux entiers strictement positifs et on demande d’écrire un booléen estDateValide qui dise si la date jour/mois définit une date valide du calendrier. Par exemple :

Jour, mois Valide Explication
18, 3 True 18 mars
31, 12 True 31 décembre
35, 3 False un mois n’a pas 35 jours
31, 11 False pas de 31 novembre

Pour simplifier, on supposera que le mois de février a 28 jours.

Indication : utiliser une condition testant si le mois est en 31, 30 ou 28 jours.

Placer entre deux nombres

On donne deux entiers a et b. On donne un troisième entier x. Ecrire un programme qui détermine l’entier y suivant :

  • si x est plus petit que a et b alors y est le plus petit des deux entiers a et b
  • si x est plus grand que a et b alors y est le plus grand des deux entiers a et b
  • dans les autres cas, y vaut x

Voici quelques exemples de comportement du programme en fonction de a, b et x :

42 10 33 -> 33
10 42 33 -> 33
42 10 0 -> 10
10 42 0 -> 10
42 10 30 -> 30
10 42 60 -> 42

ensureRange

On donne trois nombres a, b et x. On demande d’écrire une variable z valant l’élément le plus proche de x situé dans l’intervalle d’extrémités a et b. Voici quelques exemples de comportements :

a = 0, b = 5, x = 2 -> 2
a = 5, b = 0, x = 2 -> 2
a = 0, b = 5, x = 5 -> 5
a = 5, b = 0, x = 5 -> 5
a = 0, b = 5, x = 6 -> 5
a = 5, b = 0, x = 6 -> 5
a = 0, b = 5, x = -1 -> 0
a = 5, b = 0, x = -1 -> 0
a = 0, b = 0, x = 5 -> 0
a = 0, b = 0, x = -1 -> 0
a = 0, b = 0, x = 0 -> 0

Équation du second degré

L’exercice consiste à écrire un code permettant de résoudre dans l’ensemble des réels une équation du second degré \(ax^2+bx+c=0\). On supposera que \(a,b,c\) sont des entiers, que \(a\) est non nul et que l’inconnue \(x\) est un nombre réel.

Rappels : résolution de l’équation du second degré

On rappelle la résolution de l’équation. On calcule \(\Delta=b^2-4ac\). Il y a alors trois cas :

  • 1er cas: \(\Delta>0\). L’équation admet deux solutions réelles, données par les formules

\(x_1= \frac{-b-\sqrt\Delta}{2a}\quad{et}\quad x_2=\frac{-b+\sqrt\Delta}{2a}.\)

  • 2ème cas : \(\Delta=0\). L’équation admet une seule solution réelle, \(x= \frac{-b}{2a}\), donnée par n’importe laquelle des deux formules du 1er cas.
  • 3ème cas : \(\Delta < 0\). L’équation n’admet aucune solution réelle.
  1. Écrire un code Python qui détermine le nombre de solutions d’une équation du second degré.

  2. Affiner le code précédent pour résoudre complètement dans les réels l’équation \(ax^2+bx+c=0\) et afficher les solutions éventuelles sous forme de nombres flottants (et pas de fractions). Tester les trois équations suivantes :

    Equation Solutions

    \(6x^2-5x+1=0\)

    \(1/2\) et \(1/3\)
    \(4x^2-12x+9=0\) \(3/2\)
    \(6x^2+7x+7=0\) Aucune

Jeu à deux nombres

Dans cet exercice, on appellera combinaison la donnée de deux entiers a et b. Ainsi, on peut parler de :

  • la combinaison 42, 17;
  • la combinaison 81, 81.

À partir d’une combinaison, on a les règles suivantes :

  • Si a=b, la combinaison rapporte 10 points.
  • Si a et b sont consécutifs (comme a=5 et b=4), alors la combinaison rapporte 3 points.
  • sinon la combinaison ne rapporte rien.

Écrire un code Python qui, étant donné une combinaison de deux entiers a et b, affiche le nombre de points que rapporte la combinaison.

Combien de pairs et d’impairs ?

On donne 4 entiers a, b, c et d. Construire des variables pairs et impairs qui comptent le nombre d’entiers pairs et le nombre d’entiers impairs parmi les 4.

Exemples de comportement :

a = 15, b = 10, c = 12, d = 13
pairs = 2
impairs = 2

a = 18, b = 10, c = 14, d = 12
pairs = 4
impairs = 0

a = 15, b = 10, c = 11, d = 13
pairs = 1
impairs = 3

On pourra introduire un variable pairs valant initalement 0 et référençant le nombre d’éléments pairs.

Répartion équitable de pièces de monnaie

Soit un ensemble de pièces de monnaie constitué de N1 pièces de 1 euro et N2 pièces de 2 euros. On se demande s’il est possible de répartir ces pièces entre deux personnes A et B en sorte que chacune reçoive exactement le même montant (voir les exemples ci-dessous).

  1. Définir un booléen possible valant True ou False selon que la répartition est possible ou non. Voici quelques exemples de comportement (et qui traduisent en fait tous les cas possibles) :

    • si N1 = 81 et N2 = 42 alors la répartition est impossible
    • si N1 = 42 et N2 = 100 alors la répartition est possible
    • si N1 = 42 et N2 = 11 alors la répartition est possible
    • si N1 =0 et N2 = 42 alors la répartition est impossible.
  2. Lorsque la répartition est possible, déterminer

    • les nombres A1 et B1 de pièces de 1 euro reçues par A et B
    • les nombres A2 et B2 de pièces de 2 euros reçues par A et B
    • un booléen verif qui vérifie la validité de la répartition.

    Voici quelques exemples :

    • si N1 = 42 et N2 = 100 alors la répartition est possible avec A1 = 21, A2 = 50, B1 = 21 et B2 = 50 puisque le montant total est de 242 euros et A a reçu 21+100 = 121 euros, B en a reçu 21+100=121 euros et qui en est la moitié ;
    • si N1 = 42 et N2 = 11 alors la répartition est possible avec A1 = 22, A2 = 5, B1 = 20 et B2 = 6 puisque le montant total est de 64 euros et A a reçu 22+10 = 32 euros, B a reçu 20+12 euros qui en est la moitié.

    L’idée de exercice est inspirée d’un problème de Codeforces.

Articles dans un magasin

(D’après un exercice du Cours de Caml de mon collègue Thierry Montaut)

Un article est vendu :

  • 10 euros pièce quand on en achète 10 ou moins
  • 8 euros entre le 11ème et le 50ème
  • 6 euros à partir du 51ème.

Soit N le nombre d’articles achetés. Ecrire une variable prix donnant le prix de la commande en fonction de N.

Exemples :

  • pour N=42, on trouvera un prix de 356 euros. En effet \(\mathtt{10\times 10+ 32\times 8=100+256=356}\)
  • pour N=120, on trouvera un prix de 840 euros. En effet \(\mathtt{10\times 10+ 40\times 8+ 70\times 6=100+320+420=840}\)

Catégories en sports

Le tableau ci-dessous définit les catégories de participants en athlétisme en fonction de l’âge, donné en années (d’après Wikipédia):

Catégorie Début (années) Fin (années)
Eveil   9
Poussin 10 11
Benjamin 12 13
Minime 14 15
Cadet 16 17
Junior 18 19
Espoir 20 22
Sénior 23 39
Vétéran 40  

Écrire une programme qui à partir d’un âge donné sous forme d’entier positif détermine une variable chaîne de caractères représentant la catégorie correspondante.

Quelle saison sommes-nous ?

Le tableau ci-dessous donne les dates de début des quatre saisons :

Saison Début
printemps 20 mars
été 21 juin
automne 22 septembre
hiver 21 décembre

Une date est donnée par deux variables j, le jour du mois et m, le numéro de mois entre 1 et 12. On donne une date et on demande de déterminer la saison correspondant à cette date. On définira une variable nommée saison.

Voici quelques exemples de comportement :

j =  1, m =  1 : saison = hiver
j =  1, m =  3 : saison = hiver
j = 13, m =  3 : saison = hiver
j = 20, m =  3 : saison = printemps
j = 21, m =  3 : saison = printemps
j = 20, m =  6 : saison = printemps
j = 21, m =  6 : saison = été
j = 16, m =  7 : saison = été
j =  1, m =  9 : saison = été
j = 21, m =  9 : saison = été
j = 22, m =  9 : saison = automne
j = 23, m =  9 : saison = automne
j = 11, m = 11 : saison = automne
j = 21, m = 12 : saison = hiver
j = 25, m = 12 : saison = hiver
j = 31, m = 12 : saison = hiver

Catégoriser un triangle

On donne un triplet de nombres entiers positifs, \(\mathtt{A, B, C}\), représentant les angles en degrés d’un éventuel triangle, par exemple

A = 42, B = 68, C = 70

On rappelle que la somme des angles d’un triangle vaut 180°.

Un triangle est dit isocèle s’il admet deux angles égaux et on dit qu’il est équilatéral si ses trois angles sont égaux. Un triangle est rectangle si un de ses angles vaut 90°

Ecrire une variable natureTriangle qui à partir des angles aux sommets \(\mathtt{A}\), \(\mathtt{B}\) et \(\mathtt{C}\) d’un éventuel triangle s’évalue en la chaîne suivante:

  • "invalide" s’il existe aucun tel triangle,
  • "equilatéral" si le triangle \(\mathtt{ABC}\) est équilatéral,
  • "isocèle" si le triangle \(\mathtt{ABC}\) est isocèle,
  • "rectangle" si le triangle \(\mathtt{ABC}\) est rectangle,
  • "rectangle-isocèle" si le triangle \(\mathtt{ABC}\) est rectangle-isocèle,
  • "quelconque" sinon.

Voici quelques exemples de comportement :

42 42 33 → invalide
40 60 80 → quelconque
40 40 100 → isocèle
50 40 90 → rectangle
45 45 90 → rectangle-isocèle
60 60 60 → équilatéral

Zones de couleurs

Soit la figure ci-dessous :

../../../_images/carre_zone_couleurs.png

qui montre un quadrillage avec des zones de couleur lavande, saumon ou orange. On donne une case par son numéro de ligne lig et son numéro de colone col et on veut connaître la couleur de la case. Ecrire un code Python qui définisse une variable couleur valant une chaîne de caractères parmi :

"lavande", "saumon", "orange" ou "aucune"

selon la position de la case.

Voici quelques exemples de comportements :

lig = 8, col = 3 : lavande
lig = 10, col = 10 : lavande
lig = 3, col = 6 : lavande
lig = 5, col = 5 : orange
lig = 10, col = 6 : saumon
lig = 9, col = 9 : saumon
lig = 42, col = 81 : aucune

Cet exercice est directement inspiré d’un exercice de France-IOI intitulé zones de couleurs.

Opérateur xor

Étant donné deux assertions p et q, construire une expression xor_p_q qui vaut

  • True si exactement une des deux assertions p ou q vaut True
  • False sinon.

Par exemple, dans le code ci-dessous :

p = 2 * k + 1 >= 100
q = k % 10 == 0

l’affichage sera le suivant :

k = 42, p = False, q = False -> xor_p,q = False
k = 81, p = True, q = False -> xor_p,q = True
k = 20, p = False, q = True -> xor_p,q = True
k = 420, p = True, q = True -> xor_p,q = False

On pourra envisager différents types de solution :

  • utilisant des opérateurs booléens
  • utilisant if/else
  • n’utilisant ni booléens ni if/else

Généraliser à trois assertions p, q, r : xor_p_q_r vaut True si et seulement si exactement une seule des trois assertions vaut True.

Envisager une solutions basée sur la propriété suivante : dans un contexte arithmétique, True est converti en 1 et False en 0, par exemple, une expression comme 4*True - 3*False + 10 s’évalue en 14.

Distance d’un point à un rectangle

Dans le plan rapporté à deux axes perpendiculaires, on donne un rectangle \(ABCD\), donné par ses 4 cotés d’équations x = gauche, x = droite, y = bas et y = haut. Soit un point M de coordonnées \((x, y)\) intérieur au rectangle \(ABCD\).

  1. Écrire un programme qui calcule la distance la plus courte de \(M\) aux côtés du rectangle \(ABCD\).

  2. Faites une représentation graphique, en dessinant le segment représentant la distance minimale trouvée

    ../../../_images/distanceRectangle.png

Transport en bus

Un bus peut contenir \(p\) passagers. Déterminer le nombre k de bus nécessaires au transport de \(n\) passagers. Par exemple, si p=50 alors si n = 500 on aura k = 10 et si n = 542 on aura k = 11.

Ecrire un code qui, partant de p et de n, détermine la variable k puis vérifier sur différents exemples. On utilisera une instruction if, avec ou sans else, au choix.

Facteur minimal pour dépasser un entier donné

Soient des entiers \(\mathtt{n, d>0}\). On cherche le plus petit entier \(\mathtt{N\geq 0}\) tel que \(\mathtt{Nd\geq n}\). Exemples avec \(\mathtt{d=10}\) :

  • si \(\mathtt{n=42}\) alors \(\mathtt{N=5}\) puisque \(\mathtt{40<n}\) mais \(\mathtt{50\geq n}\) ;
  • si \(\mathtt{n=40}\) alors \(\mathtt{N=4}\) puisque \(\mathtt{30<n}\) mais \(\mathtt{40\geq n}\).

Ecrire un code qui détermine \(\mathtt{N}\) en fonction de \(\mathtt{n}\) et \(\mathtt{d}\).

On pourra remarquer que \(\mathtt{N}\) se déduit facilement du quotient entier de \(\mathtt{n}\) par \(\mathtt{d}\).

Reprographie au format grand livret

Une feuille au format A3 peut contenir côte à côte deux feuilles au format A4. Reproduire un ouvrage de \(n\) pages (format A4) en mode livret consiste à reproduire les pages en en plaçant 4 par feuille, chaque feuille étant au format A3 les feuilles étant imprimées, autant que possible, en recto-verso. Par exemple, une reprographie de 42 pages nécessite dans ce format 11 feuilles A3, les 10 premières feuilles sont complètement remplies (cela fait 40 pages) et la onzième n’est remplie qu’à moitié (il y aura deux pages blanches de taille A4 sur cette dernière feuille).

On donne un nombre \(n\) de pages et on demande le nombre \(N\) de feuilles pour effectuer une impression de ces \(n\) pages. Par exemple, si \(n=42\) alors \(N=11\).

Durée de sommeil

On donne une heure de la journée, qui correspond à l’heure d’endormissement, et une autre heure dans la journée, qui correspond à l’heure de réveil. On suppose que la personne ne dort jamais plus de 24 heures. Chacune des heures de la journée est donnée par deux variables, une pour le nombre d’heures et l’autre pour le nombre de minutes. Par exemple, he = 23 et me = 48 traduit une heure d’endormissement de 23 h 48. Les variables seront he et me pour le moment d’endormissement, hr et mr pour le moment de réveil.

On demande d’écrire un programme qui calcule la durée de sommeil avec deux variables hs (nombre d’heures) et ms (nombre de minutes). Voici quelques exemples de comportement du programme :

Dort : 23 h 48
Lève : 7 h 42
Sommeil : 7 h 54
----------------
Dort : 22 h 48
Lève : 11 h 52
Sommeil : 13 h 4
----------------
Dort : 23 h 48
Lève : 23 h 59
Sommeil : 0 h 11
----------------
Dort : 2 h 48
Lève : 9 h 42
Sommeil : 6 h 54
----------------
Dort : 18 h 59
Lève : 7 h 0
Sommeil : 12 h 1

On fera le calcul de la manière suivante : on regarde si minuit est entre les deux heures ou pas :

  • si c’est le cas, on rajoute à l’heure de réveil l’écart à minuit ; par exemple, si le coucher est à 22h48 et le lever à 11h52, l’écart à minuit est de 1 heure et 12 minutes qui rajouté à 11h52 donne 13 h 4 min ;
  • sinon, on regarde si on peut faire la différence des minutes et, si ce n’est pas le cas, on retient 60 minutes ; par exemple, si le coucher est à 2 h 48 et le lever à 9 h 42, l’écart en minutes est 60+42-48=54 et l’écart d’heures est 8-1-2=5 donc la durée de sommeil est 5h 54 min.

Pierre, papier, ciseaux

Enzo et Laura jouent au jeu pierre-papier-ciseaux. On dispose du choix de chacun des joueurs dans des variables enzo et laura, le choix étant donné par une chaîne de caractères minuscules, par exemple "ciseaux". On demande d’écrire un programme qui définit puis affiche une variable quiGagne contenant le nom de la personne qui a gagné ou la chaîne Match nul si personne n’a gagné. Par exemple, si

enzo = "papier"
laura = "ciseaux"

le programme doit afficher

Laura gagne

ou encore si

enzo = "papier"
laura = "papier"

le programme doit afficher

Match nul

Les règles sont rappelées dans le tableau ci-dessous :

choix choix vainqueur
papier ciseaux ciseaux
ciseaux pierre pierre
pierre papier papier

Excédent payé

Soit à régler un montant de m euros avec des billets de 20 euros. Par exemple,

  • si m = 85 alors il faut 5 billets de 20 euros
  • si m = 120 alors il faut 6 billets de 20 euros

On demande de calculer le nombre exc représentant l’excédent payé en fonction de m. Par exemple,

  • si m = 85 alors exc = 15.
  • si m = 120 alors exc = 0.

Arrondir l’heure

  1. On donne un entier \(n\geq 0\). Construire une variable N valant le multiple de 5 le plus proche de \(n\). Vous raisonnerez en fonction la valeur du reste de la division de n par 5.

    Par exemple :

    • si \(n=42\) alors \(N=40\)
    • si \(n=15\) alors \(N=15\)
    • si \(n=64\) alors \(N=65\)
    • si \(n=90\) alors \(N=90\)
    • si \(n=0\) alors \(N=0\)
  2. Cette question fait appel à la question précédente. Si vous n’avez pas réussi à la résoudre, vous pourrez utiliser le code ci-dessous qui donne le multiple de 5, appelé m, le plus proche de l’entier n :

    m = round(n/5)*5
    

    Vous allez devoir écrire un code qui arrondit une heure donnée aux 5 minutes les plus proches. Une heure de la journée sera codée par deux nombres entiers \(h\) et \(m\), où \(h\) est le nombre d’heures (\(0\leq h< 24\)) et \(m\) le nombre de minutes (\(0\leq m < 60\)). Par exemple, 14 h 05 est codée par \(h=14\) et \(m=5\) ou encore 4 h sera codée par \(h=4\) et \(m=0\).

    On se donne une heure de la journée, représentée par deux nombres entiers \(h\) et \(m\). Écrire une code qui calcule l’heure arrondie à 5 minutes près. Plus précisément, votre code devra construire deux variables H et M correspondant à l’heure arrondie. Voici quelques exemples de comportements attendus :

    14h 53m -> [14, 55]
    18h 31m -> [18, 30]
    02h 10m -> [2, 10]
    01h 02m -> [1, 0]
    09h 58m -> [10, 0]
    23h 58m -> [0, 0]
    23h 57m -> [23, 55]
    

    On fera attention de ne pas écrire des nombres de minutes ou d’heures avec un zéro initial (comme 02), Python 3 considérant cette syntaxe comme une erreur.

Carré parfait le plus proche

On appelle carré parfait un entier qui a la propriété d’être le carré d’un entier. Par exemple, \(100\) est un carré parfait car \(100=10^2\). En revanche, \(42\) n’est pas un carré parfait.

On donne un entier \(\mathtt{k\geq 0}\) et on cherche le carré parfait le plus proche de \(\mathtt{k}\). Par exemple,

  • le carré le plus proche de \(42\) est \(36\),
  • le carré le plus proche de \(43\) est \(64\),
  • le carré le plus proche de \(100\) est \(10\).

Un entier \(k\geq 0\) étant donné, écrire un code calculant le carré parfait le plus proche de \(k\).

On utilisera la partie entière d’un nombre \(\mathtt{x\geq 0}\) et qui, en Python, est donnée par \(\mathtt{int(x)}\). Par exemple, la partie entière de 3,14 est 3.

Cet exercice est inspiré de cette question.

Nombre d’entiers impairs entre deux entiers donnés

On donne deux entiers \(a\) et \(b\) avec \(a\leq b\). On demande de déterminer le nombre d’entiers impairs \(n\) entre \(a\) et \(b\), c’est-à-dire, vérifiant \(a\leq n\leq b\). On pourra utiliser que si \(A\) et \(B\) sont des entiers tels que \(A\leq B\) alors le nombre d’entiers entre \(A\) et \(B\), au sens large, est \(B-A+1\). On prendra en compte les 4 cas suivant la parité de \(a\) et \(b\).

Voici quelques exemples de comportement :

Entre 42 et 50 : 4
Entre 42 et 51 : 5
Entre 43 et 50 : 4
Entre 43 et 51 : 5
Entre 42 et 42 : 0
Entre 42 et 43 : 1
Entre 43 et 43 : 1
Entre 43 et 44 : 1
Entre 123456789 et 987654321 : 432098767

Nombre de carrés dans une figure (condition)

On considère une figure carrée composée de disques alignés, comme ci-dessous :

../../../_images/carre_jetons.png

Le côté du carré est formé de \(n\) disques. La figure est formée d’une succession de \(p\) carrés concentriques, tracés ici avec des couleurs différentes pour qu’ils soient bien identifiables. Dans le modèle ci-dessus, on a \(n=13\) et \(p=7\).

On demande d’écrire une condition if/else exprimant \(p\) en fonction de \(n\) (si nécessaire, réaliser à la main plusieurs figures pour comprendre le lien entre \(n\) et \(p\)).

Raccourcir une suite de conditions

Soit x une variable référençant un entier et soit le code suivant

if 0 <= x < 10:
    ok = True
elif x > 100:
    ok = (x %2) == 0
else:
    ok= False

Remplacer le code prédédent par un code totalement équivalent (donnant quelque soit la valeur de x la même valeur pour la variable ok) mais tenant sur une seule ligne.

Ramener if/else à un booléen

Soit le code suivant où i et j sont des entiers que l’on peut choisir librement :

from random import randrange
i=randrange(0,5) # juste un exemple
j=randrange(0,5) # juste un exemple
if i < j:
    if i % 2 ==0 and j == i + 1:
        v= True
    else:
        v=False
else:
    if j % 2 == 0 and i == j + 1:
        v= True
    else:
        v= False
print(i, j, v)

Simplifier ce code sous la forme suivante

from random import randrange
i=randrange(0,5) # juste un exemple
j=randrange(0,5) # juste un exemple
if i < j:
    v= COMPLETER
else:
    v= COMPLETER
print(i, j, v)

puis encore sous la forme :

from random import randrange
i=randrange(0,5) # juste un exemple
j=randrange(0,5) # juste un exemple
v= COMPLETER
print(i, j, v)

ou le COMPLETER sera remplacé par une expression booléenne.

Bien sûr, les codes produits doivent rester équivalents au code initial