Algorithmie (un peu)

Introduction

Un algorithme est une suite finie d’opérations ou d’instructions permettant de résoudre une problèmes. Pour résoudre un problème, on peut écrire différents algotithmes. Certains seront plus efficaces que d’autres. Lorsque l’on code, il faut se poser différentes questions :

  • Comment faire une tache rapidement ?

  • Peut-on utiliser la récurrence ?

  • Peut-on couper le problème en deux ?

Les principaux éléments que l’on va aborder dans ce chapitre concernent les tests, les boucles et les fonctions. Couplés aux variables, nous aurons alors assez d’éléments pour écrire des programmes. Le plus difficile n’est pas de comprendre les instructions mais plutôt d’arriver à les découper pour qu’un gros code deviennent une suite de petit code efficaces.

Tout programme peut se résumer à trois concepts: test, saut et séquence. Prenons un exemple pour calculer une moyenne :

t = [0, 1, 2, 3, 4]
N = 5
m = (t[0] + t[1] + t[2] + t[3] + t[4])/N

Cette façon de calculer une moyenne ne fonctionne uniquement lorsque la liste à 4 éléments. Que faire lorsqu’on est en présence d’une liste plus importante?

t = [0, 1, 2, 3, 4]
N = 5
m = 0
for i in range(0,N):
    m = m + t[i]           
m = m/N
print(m)
2.0
  • ligne 1 : initialisation de la variable m à 0

  • ligne 2 : initialisation de la variable i à 0

  • ligne 3 : m reçoit m + ni

  • ligne 4 : i reçoit i + 1

  • ligne 5 : si i est inférieur ou égal à N alors aller à la ligne 3

  • ligne 6 : m reçoit m / N

On a utiliser des mot-clefs qui apparaissent en vert gras. On peut retrouver l’ensenble des mots-clefs avec la commande suivante.

import keyword
print(", ".join(keyword.kwlist))
False, None, True, and, as, assert, async, await, break, class, continue, def, del, elif, else, except, finally, for, from, global, if, import, in, is, lambda, nonlocal, not, or, pass, raise, return, try, while, with, yield

On a aussi utiliser ce qu; on appelle des opérateurs.

  • + - * ** / // % (opérateurs arithmétiques)

  • < > == <= >= != (opérateurs de comparaison)

  • = += -= *= /= //= %= **= (opérateurs d’affectations)

  • ( ) [ ] { } " '

  • , : . (opérateurs de syntaxes)

Remarques : les espaces entre les opérateurssontà la convenance de l’utilisateur même si il existe une norme pour “bien écrire en Python”.

Les tests

Les tests permettent d’exécuter des instructions différentes selon la valeur d’une condition logique définie à l’aide des opérateurs logique. On utilise if pour Si, else pour Sinon et elif pour Sinon Si.

Syntaxe :

   actions à faire
else :
   autres actions à faire

Les opérateurs de comparaisons permettent de comparer entre eux des objets de tous les types de base. Le résultat d’un test de comparaison produit des valeurs booléennes.

Opérateur

Opérateur en Python

Description

\(=\)

==

Égal à

\(\ne\)

!=

Différent de

\(>\)

>

Supérieur à

\(\geq\)

>=

& Supérieur ou égal à

\(<\)

<

Inférieur à

\(\leq\)

<=

Inférieur ou égal à

\(\in\)

in

Dans

\(\notin\)

not in

Exclu

Remarques :

  • else n’est pas obligatoire

  • L’indentation est TRÈS importante

  • elif peut permettre d’enchainer plusieurs test. Ex : est-ce que j’ai asssez de pommes ? Non. Sinon est-ce que j’ai assez de poire ?

  • Lorsqu’on rédige son code, il est pratique d’utiliser des instructions conditionnelles if pour évaluer ou non certaines parties du code. Exemples :

note = 8
if note > 10:
    print("Félicitations ! ")
else:
    print("Dommage ! ")
Dommage ! 
note = 11
if note > 10:
    print("Félicitations ! ")
else:
    note = 9
print("Dommage ! ")
Félicitations ! 
Dommage ! 
note = 16
mention = ""
if note < 12 and note >= 10:
  mention = "Passable"
elif note < 14 and note >= 12:
  mention = "AB"
elif note < 16 and note >= 14:
  mention = "Bien"
else:
  mention = "TB"
print("Votre mention est " + mention)
Votre mention est TB

La priorité des opérations numériques est respectée: puissance => multiplication/division => addition/soustraction. Ces opérations sont prioritaires sur les opérateurs de comparaisons qui sont aussi prioritaires sur les opérateurs logiques not, and, or.

Le mot-clé in permet aussi de faire des tests :

l = [2, 3,10, 2]
if 2 in l: 
    print("youpi")
youpi

Les boucles

Les boucles permettent de faire de la récurrence ou répéter plusieurs fois la même opération. On a vu dans l’introduction l’utilisation de la boucle for qui peut se traduire par :

pour i allant de a à b: 
    faire ces actions

La boucle for nécessite la connaissance des bornes. Si on ne connait pas ces bornes, on peut utiliser les boucles while qui peut se traduire par :

tant que la condition est vraie: 
    faire ces actions

Les boucles for

Présentation

La syntaxe Python d’une boucle for est la suivante :

for i in valeurs:
    instructions

i est une variable locale, il est courrant d’appeler i cette variable mais tout autre nom peut être utilisé. valeurs un objet comprenant \(n\) éléments définissant les valeurs que prendra i pour chacun des \(n\) tours. Cela peut-être des string ou des nombres dans une liste. Pour obtenir une liste d’entiers en Python, on utiliser range(start,stop), qui prend les paramètres deux paramètres, start et stop. start étant facultatif.

print(list(range(0, 10))) # 
print(list(range(10))) # 
print(list(range(4, 10))) # 
print(list(range(0, 10, 2))) # 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[4, 5, 6, 7, 8, 9]
[0, 2, 4, 6, 8]
n=10
somme = 0 
for i in range(0, n+1):
    somme = somme + i
print("La somme des "+ str(n)+ " premiers entiers est " + str(somme)) 

s = "La somme des {} premiers entiers est {}"
somme = 0
for i in range (0,n+1):
    somme = somme + i
print(s.format(n,somme))
La somme des 10 premiers entiers est 55
La somme des 10 premiers entiers est 55
n=10
n_c = []
for i in range(0, n+1):
  n_c.append(i**2)
print(n_c)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
m = "Il y a {} qui fait grève contre la LPPR"
for univ in ["Rennes", "Lille", "Besançon"]:
  print(m.format(univ))
Il y a Rennes qui fait grève contre la LPPR
Il y a Lille qui fait grève contre la LPPR
Il y a Besançon qui fait grève contre la LPPR

Plusieurs boucles

Il est possible d’imbriquer des boucles for :

m = "i vaut {} et j vaut {}"
for i in range(5):
    for j in range(5): 
        print(m.format(i,j))
i vaut 0 et j vaut 0
i vaut 0 et j vaut 1
i vaut 0 et j vaut 2
i vaut 0 et j vaut 3
i vaut 0 et j vaut 4
i vaut 1 et j vaut 0
i vaut 1 et j vaut 1
i vaut 1 et j vaut 2
i vaut 1 et j vaut 3
i vaut 1 et j vaut 4
i vaut 2 et j vaut 0
i vaut 2 et j vaut 1
i vaut 2 et j vaut 2
i vaut 2 et j vaut 3
i vaut 2 et j vaut 4
i vaut 3 et j vaut 0
i vaut 3 et j vaut 1
i vaut 3 et j vaut 2
i vaut 3 et j vaut 3
i vaut 3 et j vaut 4
i vaut 4 et j vaut 0
i vaut 4 et j vaut 1
i vaut 4 et j vaut 2
i vaut 4 et j vaut 3
i vaut 4 et j vaut 4

Plusieurs variables de boucle

Il est possible d’itérer sur plusieurs variables

l_de_t = [(1, 1, 1), (2, 0, 5), (3, 2, 1)]
for i in l_de_t:
    print(i)
    
m = "i vaut {}, j vaut {} et k vaut {}"    
for i,j,k in l_de_t:
    print(m.format(i,j,k))
(1, 1, 1)
(2, 0, 5)
(3, 2, 1)
i vaut 1, j vaut 1 et k vaut 1
i vaut 2, j vaut 0 et k vaut 5
i vaut 3, j vaut 2 et k vaut 1

Boucles while()

Contrairement à la boucle for(), on ne connait pas les bornes d’itérations avec la boucle while(). Les instructions seront répétées tant que une condition est respectée. Dès que la condition est fausse, on sortira de la boucle. La syntaxe est la suivante :

  instructions
l = ['chamois', 'chamois', 'chamois', 'belette', 'belette'] 
x = l[0]
count = 0
while x == 'chamois':
    count += 1
    print('c\'est un {}'.format(x)) 
    x = l[count]

print('On a trouvé la {}'.format(x)) 
c'est un chamois
c'est un chamois
c'est un chamois
On a trouvé la belette

Fonctions

Une fonction est un élément du langage infomatique qui permet d’effectuer une action sans devoir recoder cette action à chaque utilisation. Un module Python contient entre autre des fonctions. On a déjà utilisé des fonctions upper(), format()… Il existe énormément de modules mais il se peut qu’une ce que l’on cherche à faire ne soit pas déjà codé. Il va falloir créer ses propres fonctions.

Remarques :

  • A force de coder, on va alors créer de plus en plus de fonctions que l’on pourra regrouper en module.

  • On peut aussi créer ce qu’on nomme une class. Une classe est un ensemble d’objet qui possède ses propres méthodes et propriétés (attributs). On en parlera pas durant ce cours mais il peut-être intéressant de creuser cette partie de la programmation

Définition

Une fonction est déclarée à l’aide d’u mot clé et renvoie (comme en maths) un ou plusieurs éléments à l’aide de return.

La syntaxe est la suivante :

def une_fonction(parametres):
    ensemble_instructions

Une fonction commence toujours par def. Entre parenthèses, ce sont les paramètres. Ce qui suit le mot-clé return est le résultat de la fonction (ou sa sortie). Parmi les fonctions, il y a celles qui existent déjà et celles que vous écrivez. On peut alors appeler la fonction à l’aide de la commande

une_fonction(10)
def factoriel(x):
    f = x
    while x!=1:
        f = f*(x-1)
        x = x-1
    return f

print(factoriel(4))
24

Remarques :

  • Il est possible d’ajouter une description de ce que la fonction fait en adoptant des conventions (https://www.python.org/dev/peps/pep-0257/)

  • Il faut, dans la mesure du possible, utiliser les fonctions déjàs existantes : elles sont optimisées

  • On peut, si besoin, retourner plusieurs variables en les séparant avec une virgule

Paramètres

Une fonction peut avoir besoin de plusieurs paramètres. Il faut les séparer par une virgule. Nous avons besoin d’une fonction nous renseignant quel livre l’utilisateur à emprunter à la bibliothèque :

def emprunt(utilisateur, livre, auteur ): 
    return '{} a emprunté {} de {}'.format(utilisateur,livre,auteur)

print(emprunt('Benji', ' A la Recherche du Temps Perdu', 'Marcel Proust'))
Benji a emprunté  A la Recherche du Temps Perdu de Marcel Proust

Le nom des paramètres n’a pas été mentionné ici. La valeur du 1er paramètre a été attribué à utilisateur, le 2nd à livre et le 3ème à auteur dans l’ordre.

print(emprunt(livre = 'A la Recherche du Temps Perdu', utilisateur = 'Benji', auteur = 'Marcel Proust'))
Benji a emprunté A la Recherche du Temps Perdu de Marcel Proust

A l’intérieur d’une fonction, on peut définir des paramètres par défaut (paramètres par mots-clés), il ne faudra alors rentrer au minimum uniquement les paramètres dit positionnels :

def emprunt(livre, auteur, utilisateur='Benji' ): 
    return '{} a emprunté {} de {}'.format(utilisateur,livre,auteur)

print(emprunt('A la Recherche du Temps Perdu', 'Marcel Proust'))
print(emprunt('A la Recherche du Temps Perdu', 'Marcel Proust', 'Romain'))
print(emprunt('A la Recherche du Temps Perdu'))
Benji a emprunté A la Recherche du Temps Perdu de Marcel Proust
Romain a emprunté A la Recherche du Temps Perdu de Marcel Proust
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-18-afaa456f30f7> in <module>
      4 print(emprunt('A la Recherche du Temps Perdu', 'Marcel Proust'))
      5 print(emprunt('A la Recherche du Temps Perdu', 'Marcel Proust', 'Romain'))
----> 6 print(emprunt('A la Recherche du Temps Perdu'))

TypeError: emprunt() missing 1 required positional argument: 'auteur'

Variables d’une fonction

Les variables d’une fonction ne sont utilisables qu’à l’intérieur de cette fonction. Ce sont des variables local :

oops =  10
def f(x):
    un_entier = 3
    s = 'hey '
    print(s+str(un_entier))
    print(oops)
    return x + un_entier

un_entier = 5
print(f(un_entier))
print(un_entier)
print(s)
hey 3
10
8
5
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-20-4003109d1786> in <module>
     10 print(f(un_entier))
     11 print(un_entier)
---> 12 print(s)
     13 

NameError: name 's' is not defined
  • oops n’est pas défini dans la fonction mais existe dans l’environnement global qui est parent à celui de la fonction, on peut donc l’utiliser dans la fonction

  • s est définie localement, elle est donc inutilisable globalement

  • un_entier est défini localement et globalement. Il prend donc deux valeurs

Exercices

  1. Écrire un programme minmax.py, qui demande de saisir 2 valeurs et qui affiche la plus grande des 2 valeurs.

  2. Initialisez deux variables : a = 0 et b = 5.

    1. Dans une boucle, afficher la valeur de a et l’incrémenter. Continuer la boucle tant que a est inférieur à b.

    2. Écrire une autre boucle affichant la valeur de b si elle est paire tant que b est non nul.

  3. Initialisez la chaine de caractère suivante : J'adore mon cours de Python. Affichez chaque caractère d’une chaîne en utilisant une boucle for.

  4. Affichez les entiers de 0 à 10 non compris, de 2 en 2, en utilisant une boucle for et range().

  5. Écrire un script qui permet d’effectuer une conversion euros en dollars.

    1. On demande à l’utilisateur de rentrer la monnaie d’origine ainsi que le montant

    2. Le programme exécutera une action conditionnelle pour convertir en euros ou en dollars

  6. Écrire un programme, qui affiche 20 fois ”Je reste chez moi et je ne sors pas ! ” à l’aide de l’instruction for.

  7. Écrire une fonction, nommé pair qui returne un booléen lorsqu’on lui indique un entier.