diff --git a/T1_Demarrer_en_Python/1.5_Fonctions/cours/index.html b/T1_Demarrer_en_Python/1.5_Fonctions/cours/index.html index afb65a56..986c4b1a 100644 --- a/T1_Demarrer_en_Python/1.5_Fonctions/cours/index.html +++ b/T1_Demarrer_en_Python/1.5_Fonctions/cours/index.html @@ -92,7 +92,7 @@
File: T1_Demarrer_en_Python/1.5_Fonctions/cours.md
Line 499 in Markdown file: expected token ',', got 'string' -
"""
+1.5 Fonctions⚓︎
+
+La notion de fonction est essentielle en programmation.
+Elle permet de construire des codes modulaires, plus faciles à lire et à modifier.
+En Python, une fonction se crée avec le mot-clé def
.
+1. Fonctions sans paramètre, sans valeur renvoyée⚓︎
+
+
+Exemple fondateur n°1
+1
+2
+3
def accueil():
+ print("bonjour")
+ print("comment allez-vous ?")
+
+
+Lorsque l'interpréteur Python parcourt cette fonction, rien ne s'affiche : la fonction est maintenant prête à être appelée, mais n'est pas exécutée tant que l'utilisateur ne le demande pas explicitement.
+Ce sera le cas pour toutes les fonctions : elles doivent être appelées pour s'exécuter.
+>>> accueil()
+bonjour
+comment allez-vous ?
+
+Dans ce cas d'utilisation, la fonction accueil
n'est qu'un raccourci, une factorisation d'un ensemble d'instructions.
+2. Fonction avec paramètre(s), sans valeur renvoyée⚓︎
+
+2.1 Paramètre simple⚓︎
+
+Exemple fondateur n°2
+1
+2
+3
def chat_penible(n):
+ for k in range(n):
+ print("meoww")
+
+
+>>> chat_penible(3)
+meoww
+meoww
+meoww
+
+
+Vocabulaire
+
+- La valeur
n
est appelée paramètre de la fonction chat_penible
.
+- On dit qu'on passe le paramètre
n
à la fonction chat_penible
.
+- Dans l'exemple ci-dessus, on dit qu'on a appelé la fonction
chat_penible
avec l'argument 3.
+
+
+Remarques :
+
+- là encore, notre fonction ne renvoie rien : on peut encore la considérer comme un ensemble d'instructions factorisé dans un même bloc. À la différence de la fonction sans paramètre, ces instructions ne sont pas toujours les mêmes, grâce à l'utilisation du paramètre demandé à l'utilisateur.
+- la fonction bien connue
print()
est une fonction à paramètre, qui affiche dans la console le contenu du paramètre.
+
+2.2 Paramètres multiples⚓︎
+Une fonction peut avoir de multiples paramètres :
+
+Exemple fondateur n°2
+1
+2
+3
def repete(mot, k):
+ for i in range(k):
+ print(mot)
+
+
+>>> repete("NSI", 3)
+NSI
+NSI
+NSI
+
+L'ordre des paramètres passés est alors important ! Le code ci-dessous est incorrect.
+>>> repete(3, "test")
+---------------------------------------------------------------------------
+
+TypeError Traceback (most recent call last)
+
+<ipython-input-9-a84914f8a6c6> in <module>()
+----> 1 repete(3, "test")
+
+
+<ipython-input-8-7dc8032e3f17> in repete(mot, k)
+ 1 def repete(mot, k) :
+----> 2 for i in range(k):
+ 3 print(mot)
+ 4
+ 5 repete("NSI", 5)
+
+
+TypeError: 'str' object cannot be interpreted as an integer
+
+3. Fonction avec paramètre(s) et avec valeur renvoyée⚓︎
+
+On retrouve ici la notion classique de fonction rencontrée en mathématiques : un procédé qui prend un nombre et en renvoie un autre. En informatique, l'objet renvoyé ne sera pas forcément un nombre (cela pourra être aussi une liste, un tableau, une image...).
+Le renvoi d'une valeur se fait grâce au mot-clé return
.
+
+Exemple fondateur n°3
+La fonction mathématique \(f : x \longmapsto 2x+3\) se codera par :
+
1
+2
def f(x):
+ return 2*x + 3
+
+
+>>> f(10)
+23
+
+4. Autour du return
⚓︎
+4.1 La force du return
⚓︎
+
+Différence fondamentale entre return
et print
+Le mot-clé return
de l'exemple précédent fait que l'expression f(10)
est égale à 23.
+On peut d'ailleurs écrire en console :
+
>>> f(10) + 5
+28
+
+Imaginons (avant de l'oublier très vite) le code affreux ci-dessous :
+1
+2
def g(x):
+ print(2*x + 3)
+
+On pourrait avoir l'illusion que la fonction g
fait correctement son travail :
+>>> g(10)
+23
+
+Mais g
se contente d'afficher sa valeur calculée, et non pas de la renvoyer. En effet :
+>>> g(10) + 5
+23
+Traceback (most recent call last):
+File "<pyshell>", line 1, in <module>
+TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
+
+En résumé :
+
+
+4.2 Le return
est un siège éjectable⚓︎
+Le mot-clé return
provoque une éjection du code : tout ce qui est situé après le return
ne sera pas exécuté.
+Observez la différence entre les fonctions g
et h
.
+1
+2
+3
def g(x):
+ print("ce texte sera bien affiché")
+ return 2*x+3
+
+>>> g(4)
+ce texte sera bien affiché
+11
+
+1
+2
+3
def h(x):
+ return 2*x+3
+ print("ceci ne sera jamais affiché")
+
+>>> h(4)
+11
+
+4.3 Les fonctions sans return
sont-elles des fonctions ?⚓︎
+
+-
+
Pour les puristes, une fonction sans valeur renvoyée sera plutôt appelée procédure. Le mot fonction est alors réservé aux fonctions qui ont effectivement un return
.
+
+-
+
On peut doter artificiellement à toutes les fonctions d'un return
, en renvoyant la valeur None
:
+
1
+2
+3
+4
def chat_penible(n):
+ for k in range(n):
+ print("meoww")
+ return None
+
+
+
+5. Variables locales, variables globales⚓︎
+5.1 Notion d'espace de noms⚓︎
+
+Définitions
+
+- Les variables définies dans le corps d'une fonction sont appelées variables locales.
+- Les variables définies dans le corps du programme (sous-entendu : pas à l'intérieur d'une fonction) sont appelées variables globales.
+
+
+On dit que les fonctions créent leur «espace de noms» (espace est à prendre au sens d'univers), un espace qui leur est propre.
+Quelles sont les règles régissant ces espaces de noms ? Les frontières entre ces espaces sont elles poreuses ?
+5.2 Règles d'accès en lecture et en modification d'une variable suivant son espace d'origine⚓︎
+
+Règles d'accès aux variables locales et globales
+
+- règle 1 : une variable locale (définie au cœur d'une fonction) est inaccessible hors de cette fonction.
+- règle 2 : une variable globale (définie à l'extérieur d'une fonction) est accessible en lecture à l'intérieur d'une fonction.
+- règle 3 : une variable globale (définie à l'extérieur d'une fonction) ne peut pas être modifiée à l'intérieur d'une fonction.
+
+
+
+
+Exercice
+On considère les 3 codes ci-dessous. Pour chacun, dire sans l'exécuter s'il est valide ou non. S'il ne l'est pas, identifier la règle (parmi celles énoncées ci-dessus) qui est bafouée.
+code A
+
1
+2
+3
+4
+5
+6
points = 0
+def verdict(reponse):
+ if reponse > 10:
+ points += 3
+
+verdict(12)
+
+
+Correction
+Ce code n'est pas valide, car il contrevient à la règle 3.
+ligne 4
: la modification de la variable globale points
est interdite.
+
+code B
+
1
+2
+3
+4
+5
def bouge(x, decalage):
+ x += decalage
+
+bouge(100, 5)
+print(x)
+
+
+Correction
+Ce code n'est pas valide, car il contrevient à la règle 1.
+ligne 5
: l'accès à la variable locale x
est interdit.
+
+code C
+
1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
def test_bac(moyenne):
+ if moyenne >= 10:
+ print("admis !")
+
+def coup_de_pouce(note):
+ return note + bonus
+
+bonus = 0.6
+ma_moyenne = 9.5
+ma_moyenne = coup_de_pouce(ma_moyenne)
+test_bac(ma_moyenne)
+
+
+Correction
+Ce code est valide.
+ligne 6
: l'accès à la variable globale bonus
est autorisé, selon la règle 2.
+
+
+
+
+À propos de la règle n°3
+(toute la vérité, rien que la vérité)
+Pour certains types de variables (listes, dictionnaires...), la modification d'une variable globale à l'intérieur du corps d'une fonction est en fait possible (contrairement à ce qu'énonce la règle 3). Mais cela reste très fortement déconseillé.
+Pour les autres types de variables, on peut même forcer pour avoir cette possibilité en utilisant le mot global
à l'intérieur de la fonction.
+Mais il faut essayer d'éviter ceci. Une fonction ne doit (mais ceci est plus un conseil appuyé qu'une obligation légale...) modifier que les variables qu'elle crée (ses variables locales) ou bien les variables qu'on lui a données en paramètres.
+Une fonction qui ne respecte pas cette règle présente des effets de bord : on peut peut-être arriver à les gérer sur un «petit» code, mais cela devient illusoire sur un code utilisant de multiples fonctions.
+ .
+En résumé
+Ne pas faire cela :
+
1
+2
+3
+4
+5
+6
+7
+8
# PAS BIEN
+score = 0
+def ramasse_objet(objet):
+ global score
+ if objet == "champignon":
+ score += 20
+ if objet == "banane":
+ score -= 300
+
+>>> ramasse_objet("champignon")
+>>> score
+20
+Faire plutôt ceci :
+1
+2
+3
+4
+5
+6
+7
+8
# BIEN
+score = 0
+def ramasse_objet(objet, score): # ma fonction veut modifier score ?
+ if objet == "champignon": # -> ok, je mets score dans ses paramètres
+ score += 20
+ if objet == "banane":
+ score -= 300
+ return score # je renvoie le nouveau score
+
+>>> score = ramasse_objet("champignon", score)
+>>> score
+20
+
+
+6. Documenter une fonction⚓︎
+
+6.1 Help !⚓︎
+Si une fonction peut être assimilée à un outil, il est normal de se demander si cet outil possède un mode d'emploi.
+Observons les fonctions pré-définies par Python, et notamment une des premières que nous avons rencontrées : la fonction print()
. Son mode d'emploi est accessible grâce à la commande help(print)
.
+>>> help(print)
+Help on built-in function print in module builtins:
+
+print(...)
+ print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
+
+ Prints the values to a stream, or to sys.stdout by default.
+ Optional keyword arguments:
+ file: a file-like object (stream); defaults to the current sys.stdout.
+ sep: string inserted between values, default a space.
+ end: string appended after the last value, default a newline.
+ flush: whether to forcibly flush the stream
+
+Pensez à utiliser cette fonction help()
(en d'autres termes, RTFM)
+6.2 Créer le mode d'emploi de ses propres fonctions : les docstrings⚓︎
+
+Il est possible, voire souhaitable (dès qu'on créé un code comportant plusieurs fonctions, et/ou qui sera amené à être lu par d'autres personnes), de créer un mode d'emploi pour ses fonctions. On appelle cela écrire la docstring de la fonction, et c'est très simple : il suffit de l'encadrer par des triples double-quotes """
.
+
+Exemple
+1
+2
+3
+4
+5
+6
def chat_penible(n):
+ """
+ Affiche n fois la chaine de caractères "meoww"
+ """
+ for k in range(n):
+ print("meoww")
+
+On peut donc maintenant demander de l'aide pour cette fonction :
+>>> help(chat_penible)
+Help on function chat_penible in module __main__:
+
+chat_penible(n)
+ Affiche n fois la chaine de caractères "meoww"
+
+
+Plus de renseignements sur les docstrings ici
+7. Jeux de tests pour une fonction⚓︎
+
+Les exercices de cette feuille sont (presque) tous livrés avec un jeu de tests. Il s'agit d'une fonction, souvent appelée test_nom_de_la fonction()
, qui va regrouper les différents tests qu'on pourrait faire en console pour vérifier que la fonction a le comportement désiré.
+Ces tests reposent sur le mot-clé assert
, qui va lever une erreur lorsqu'il est suivi d'une expression évaluée à False
:
+>>> assert 3 > 2
+>>> assert 3 > 5
+Traceback (most recent call last):
+ File "<pyshell>", line 1, in <module>
+AssertionError
+>>> assert True
+>>> assert False
+Traceback (most recent call last):
+ File "<pyshell>", line 1, in <module>
+AssertionError
+
+
+Exemple d'un jeu de tests
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
def maxi(n1, n2):
+ if n1 < n2 :
+ return n2
+ else :
+ return n1
+
+def test_maxi():
+ assert maxi(3,4) == 4
+ assert maxi(5,2) == 5
+ assert maxi(7,7) == 7
+ print("tests ok")
+
+
+Il faut vérifier que les tests couvrent toutes les situations possibles, mais ce n'est pas toujours facile !
+
+Exercice
+On considère (à nouveau !) le jeu du FizzBuzz.
+Rappel des règles
+
+- si le nombre est divisible par 3, on ne le dit pas et on le remplace par Fizz.
+- si le nombre est divisible par 5, on ne le dit pas et on le remplace par Buzz.
+- si le nombre est divisible par 3 et par 5, on ne le dit pas et on le remplace par FizzBuzz.
+
+On souhaite écrire la fonction fizzbuzz
qui renverra soit le nombre n
(passé en paramètre), soit le mot par lequel il faut le remplacer.
+Q1. Écrire la fonction test_fizzbuzz
qui testera la fonction fizzbuzz
.
+
+Correction
+1
+2
+3
+4
+5
+6
def test_fizzbuzz():
+ assert fizzbuzz(4) == 4
+ assert fizzbuzz(6) == 'fizz'
+ assert fizzbuzz(10) == 'buzz'
+ assert fizzbuzz(15) == 'fizzbuzz'
+ print('tests ok !')
+
+
+Q2. Écrire la fonction fizzbuzz
. (Vous pouvez vous inspirer fortement du code de l'exercice 2 du chapitre précédent )
+
+Correction
+```python linenums='1'
+def fizzbuzz(n):
+ if n % 3 == 0 and n % 5 == 0:
+ return 'fizzbuzz'
+ elif n % 3 == 0:
+ return 'fizz'
+ elif n % 5 == 0:
+ return 'buzz'
+ else:
+ return n
+
+
@@ -4097,7 +4728,7 @@ Macro Syntax Error
- 10 octobre 2024
+ 12 octobre 2024
diff --git a/search/search_index.json b/search/search_index.json
index eaddc104..f4052615 100644
--- a/search/search_index.json
+++ b/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["fr"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Accueil","text":""},{"location":"#themes-en-cours-detude","title":"Th\u00e8mes en cours d'\u00e9tude :","text":" - Fonctions
- Exercices sur les Fonctions
Anciens th\u00e8mes trait\u00e9s
- Boucle
while
- Exercices sur
while
- Instruction conditionnelle
if
- Exercices sur les
if
- Boucle
for ... in ...
- Exercices
for ... in ...
- Variables
"},{"location":"T1_Demarrer_en_Python/sommaire/","title":"Th\u00e8me 1 : Bases de Python","text":" - Variables
- Boucle For
- Boucle While
- Instruction conditionnelle If
- Fonctions
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/","title":"1.1 Variables","text":""},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#a-pourquoi-des-variables","title":"A. Pourquoi des variables ?","text":""},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#a1-introduction","title":"A.1 Introduction","text":"De la m\u00eame mani\u00e8re que dans votre chambre chaque objet a (normalement) une place attitr\u00e9e, un ordinateur (dont le r\u00f4le peut se r\u00e9sumer \u00e0 \u00abmanipuler tr\u00e8s vite des donn\u00e9es\u00bb) va assigner \u00e0 chaque objet une place particuli\u00e8re dans son espace-m\u00e9moire. Et il lui assignera un nom (choisi par l'utilisateur) afin de pouvoir acc\u00e9der \u00e0 cette valeur.
Nous ne rentrerons pas dans le d\u00e9tail du processus d'allocation-m\u00e9moire, nous retiendrons juste ceci : pour manipuler un objet, il faut qu'il d\u00e9j\u00e0 qu'il ait un nom. C'est par cela que nous allons commencer :
Premi\u00e8re variable
Consid\u00e9rons la phrase \u00abnous allons stocker le prix du spectacle dans une variable a
, qui vaudra au d\u00e9part 32.\u00bb
Il y a plusieurs commentaires \u00e0 faire sur une telle annonce :
- Dans le probl\u00e8me que l'on cherche \u00e0 mod\u00e9liser, le prix du spectacle est une donn\u00e9e importante, qui va peut-\u00eatre \u00e9voluer (ou pas !).
- Pour la manipuler plus simplement, on va la d\u00e9signer par un nom, le nom de la variable (ici, le nom
a
est particuli\u00e8rement mal choisi, voir D. Bonnes pratiques de nommage) - Comme en math\u00e9matiques, le nom de cette variable va d\u00e9signer une valeur qui peut changer (varier) au cours du temps (encore une fois : ou pas).
- Cette valeur est fix\u00e9e au d\u00e9part \u00e0 32. On dira en informatique qu'elle est initialis\u00e9e \u00e0 32.
- Si cette valeur ne change pas, on dira qu'elle est constante. Cela peut para\u00eetre inutile de donner un nom \u00e0 quelque chose qui ne change pas, mais cela est tr\u00e8s utile de d\u00e9finir les constantes au d\u00e9but d'un programme.
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#a2-on-code","title":"A.2 On code !","text":"La phrase pr\u00e9c\u00e9dente donnera donc lieu \u00e0 la ligne Python suivante :
>>> a = 32\n
Attention
Le symbole =
ici utilis\u00e9 n'a rien \u00e0 voir avec le symbole = utilis\u00e9 en math\u00e9matique. On dit qu'on a affect\u00e9 \u00e0 a
la valeur 32, et il faut se repr\u00e9senter mentalement cette action par l'\u00e9criture a \u2190 32
.
Comparaison de la syntaxe dans diff\u00e9rents langages
PythonCPHPJavaJavascriptRustGo a = 32\n
int a = 32;\n
$a = 32;\n
int a = 32;\n
var a = 32;\n
let a = 32;\n
a := 32\n
Une fois la valeur 32 stock\u00e9e dans la variable a
, on peut alors utiliser cette variable :
>>> a\n32\n>>> a + 5\n37\n>>> b\nTraceback (most recent call last):\n File \"<pyshell>\", line 1, in <module>\nNameError: name 'b' is not defined\n
Remarquez bien l'erreur lorsqu'on a fait appel \u00e0 une variable b
qui n'avait jamais \u00e9t\u00e9 d\u00e9finie, comme le dit explicitement le message NameError: name 'b' is not defined
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b-le-fonctionnement-interne","title":"B. Le fonctionnement interne","text":""},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b1-explication-simplifiee","title":"B.1 Explication simplifi\u00e9e","text":"En premi\u00e8re intention, il est possible d'expliquer le fonctionnement interne de l'affectation des variables par la m\u00e9taphore des tiroirs :
\u00c9crire l'instruction :
>>> a = 2\n
va provoquer chez l'ordinateur le comportement suivant :
- Est-ce que je poss\u00e8de d\u00e9j\u00e0 un tiroir appel\u00e9
a
? - si oui, je me positionne devant.
- si non, je cr\u00e9e un tiroir appel\u00e9
a
. - J'ouvre le tiroir et j'y d\u00e9pose la valeur num\u00e9rique 2. Si le tiroir contenait d\u00e9j\u00e0 une valeur, celle-ci dispara\u00eet (on dit qu'elle est \u00e9cras\u00e9e).
Cette explication est suffisante pour aborder la notion de variable : c'est un mot (ou une lettre) qui va d\u00e9signer une valeur.
Partie difficile (optionnelle) La m\u00e9taphore du tiroir est malheureusement un peu trop simplificatrice.
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b2-une-realite-bien-plus-complexe","title":"B.2 Une r\u00e9alit\u00e9 bien plus complexe...","text":""},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b21-la-commande-id-ladresse-du-tiroir","title":"B.2.1 La commande id()
: l'adresse du tiroir ?","text":"Python poss\u00e8de une fonction qui renvoie l'adresse m\u00e9moire de la variable donn\u00e9e en argument.
>>> b = 7\n>>> id(b)\n9788800\n
Faites le test avec votre propre IDE Python (vous n'obtiendrez pas forc\u00e9ment la m\u00eame valeur d'adresse m\u00e9moire)
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b22-cela-se-complique","title":"B.2.2 Cela se complique.","text":"Sans refermer notre IDE, \u00e9crasons la valeur de b
avec une nouvelle valeur :
>>> b = 12\n
et redemandons l'adresse de b
: >>> id(b)\n9788960\n
Tr\u00e8s mauvaise nouvelle : l'adresse de la variable b
a chang\u00e9. Ceci invalide notre m\u00e9taphore du \u00abtiroir\u00bb, une place unique qui serait r\u00e9serv\u00e9e pour y stocker les valeurs successives d'une variable.
La modification de la valeur de b
ne s'est pas faite \u00aben place\u00bb, la variable b
s'est d\u00e9plac\u00e9e : que s'est-il donc pass\u00e9 ?
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b23-tentative-dexplication","title":"B.2.3 Tentative d'explication","text":"L'affectation
>>> b = 9\n
ne provoque pas la r\u00e9servation d\u00e9finitive d'un espace-m\u00e9moire pour la variable b
, mais la cr\u00e9ation d'un lien vers un espace-m\u00e9moire qui contient la valeur 9. Ce lien consiste en l'adresse-m\u00e9moire de cette valeur 9. Cette adresse-m\u00e9moire vaut (sur ma configuration personnelle) 9788864
.
>>> id(b)\n9788864\n
Comme le pr\u00e9sente le ruban ci-dessus, Python pr\u00e9-positionne les entiers (de -5 \u00e0 256) sur des petites adresses-m\u00e9moires, car il consid\u00e8re que ces entiers servent souvent, et doivent donc \u00eatre rapidement accessibles.
Si on cr\u00e9\u00e9 une nouvelle variable tokyo
aussi \u00e9gale \u00e0 9, elle va aussi pointer vers la m\u00eame adresse-m\u00e9moire :
>>> tokyo = 9\n>>> id(tokyo)\n9788864\n
Les variables tokyo
et b
renvoient vers la m\u00eame adresse-m\u00e9moire. Affectons maintenant \u00e0 tokyo
la valeur 2020 et observons son adresse-m\u00e9moire :
>>> tokyo = 2020\n>>> id(tokyo)\n139762979309936\n
L'adresse-m\u00e9moire est (bien) plus grande : elle a \u00e9t\u00e9 choisie sur le moment par Python pour y stocker 2020 (car 2020 > 256).
De mani\u00e8re plus surprenante, si on cr\u00e9\u00e9 une nouvelle variable jo
qui vaut aussi 2020, Python va ouvrir une autre adresse-m\u00e9moire pour y stocker 2020, alors qu'il l'a d\u00e9j\u00e0 stock\u00e9e ailleurs :
>>> jo = 2020\n>>> id(jo)\n139762979310064\n
En r\u00e9sum\u00e9, une variable n'est pas le nom d'un tiroir mais plut\u00f4t le nom d'une fl\u00e8che qui pointe vers un espace-m\u00e9moire de l'ordinateur. - La fl\u00e8che peut pointer vers un nouvel espace-m\u00e9moire sans que le nom de la variable change. - Deux variables peuvent pointer vers le m\u00eame espace-m\u00e9moire.
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b3-une-histoire-en-2-temps-evaluation-affectation","title":"B.3 Une histoire en 2 temps : \u00e9valuation, affectation","text":"Observons l'instruction
>>> a = 2 + 3\n
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b31-etape-1-levaluation","title":"B.3.1 \u00c9tape 1 : l'\u00e9valuation","text":"Python va prendre la partie \u00e0 droite du signe \u00e9gal et va l'\u00e9valuer, ce qui signifie qu'il va essayer de lui donner une valeur. Dans nos exemples, cette valeur sera num\u00e9rique, mais elle peut \u00eatre d'un autre type (voir plus loin)
Ici, Python effectue le calcul 2 + 3 et l'\u00e9value \u00e0 la valeur 5.
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b32-etape-2-laffectation","title":"B.3.2 \u00c9tape 2 : l'affectation","text":"Une fois \u00e9valu\u00e9e l'expression \u00e0 droite du signe =, il ne reste plus qu'\u00e0 l'affecter \u00e0 la variable (d\u00e9j\u00e0 existante ou pas) situ\u00e9e \u00e0 gauche du signe =.
Comme expliqu\u00e9 pr\u00e9c\u00e9demment, un \u00ablien\u00bb est fait entre le nom de la variable et l'adresse-m\u00e9moire qui contient la valeur \u00e9valu\u00e9e. a
sera donc li\u00e9 \u00e0 la valeur 5. Plus simplement, on dira que \u00aba
vaut 5\u00bb
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b32-lincrementation-dune-variable","title":"B.3.2 L'incr\u00e9mentation d'une variable.","text":"\u00abIncr\u00e9menter\u00bb une variable signifie l'augmenter.
Imaginons une variable appel\u00e9e compteur
. Au d\u00e9marrage de notre programme, elle est initialis\u00e9e \u00e0 la valeur 0.
>>> compteur = 0\n
Consid\u00e9rons qu'\u00e0 un moment du programme, cette variable doit \u00eatre modifi\u00e9e, par exemple en lui ajoutant 1.
En Python, cela s'\u00e9crira :
>>> compteur = compteur + 1\n
Observ\u00e9e avec des yeux de math\u00e9maticien, la pr\u00e9c\u00e9dente instruction est une horreur.
Vue avec des yeux d'informaticien, voil\u00e0 comment est interpr\u00e9t\u00e9e la commande
>>> compteur = compteur + 1\n
- On \u00e9value la partie droite de l'\u00e9galit\u00e9, donc l'expression
compteur + 1
. - On va donc chercher le contenu de la variable
compteur
. Si celle-ci n'existe pas, un message d'erreur est renvoy\u00e9. - On additionne 1 au contenu de la variable
compteur
. - On \u00e9crase le contenu actuel de la variable
compteur
avec la valeur obtenue au 3.
\u00c0 la fin de ces op\u00e9rations, la variable compteur
a bien augment\u00e9 de 1.
Cette proc\u00e9dure d'incr\u00e9mentation est tr\u00e8s tr\u00e8s classique, il faut la ma\u00eetriser parfaitement !
Syntaxe classique et syntaxe Pythonesque
L'incr\u00e9mentation d'une variable compteur
s'\u00e9crira donc en Python :
>>> compteur = compteur + 1\n
Mais il existe aussi une syntaxe particuli\u00e8re, un peu plus courte : >>> compteur += 1\n
Cette syntaxe peut se ranger dans la cat\u00e9gorie des sucres syntaxiques : c'est bien de la conna\u00eetre, c'est amusant de s'en servir, mais son utilisation n'est en rien obligatoire et peut avoir un effet n\u00e9faste, celui d'oublier r\u00e9ellement ce qu'il se passe derri\u00e8re. Exercice 1
\u00c9crire le code \u00abclassique\u00bb et le code \u00abPythonesque\u00bb pour l'instruction suivante :
On initialise une variable score
\u00e0 100 et on l'augmente de 15.
Correction >>> score = 100\n>>> score = score + 15\n
ou encore >>> score = 100\n>>> score += 15\n
Exercice 2
\u00c9crire le code \u00abclassique\u00bb et le code \u00abPythonesque\u00bb pour l'instruction suivante :
On initialise une variable cellule
\u00e0 1 et on la multiplie par 2.
Correction >>> cellule = 1\n>>> cellule = cellule * 2\n
ou bien >>> cellule = 1\n>>> cellule *= 2\n
Exercice 3
\u00c9crire le code \u00abclassique\u00bb et le code \u00abPythonesque\u00bb pour l'instruction suivante.
On initialise une variable capital
\u00e0 1000 et on lui enl\u00e8ve 5%.
Correction >>> capital = 1000\n>>> capital = capital - capital * 5/100\n
ou bien >>> capital = 1000\n>>> capital *= 0.95\n
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b33-lechange-de-variables","title":"B.3.3 L'\u00e9change de variables","text":"Apr\u00e8s l'incr\u00e9mentation, une autre technique de base reviendra fr\u00e9quemment dans nos codes : l'\u00e9change de variables.
Imaginons les variables suivantes :
>>> a = 3\n>>> b = 5\n
Le but est d'\u00e9changer les valeurs de a
et de b
. \u25b8 M\u00e9thode na\u00efve
>>> a = b\n>>> b = a\n
Que valent a
et b
maintenant ?
Malheureusement :
>>> a\n5\n>>> b\n5\n>\n
La variable a
a \u00e9t\u00e9 \u00e9cras\u00e9e d\u00e8s qu'on lui a donn\u00e9 la valeur de la variable b
.
Comment la pr\u00e9server ?
La situation est similaire au probl\u00e8me suivant : comment \u00e9changer le contenu de ces deux verres ?
La m\u00e9thode est \u00e9vidente : il nous faut un troisi\u00e8me verre.
Nous allons faire de m\u00eame pour nos variables. Nous allons utiliser une variable temporaire (on parle aussi de variable tampon) pour conserver la m\u00e9moire de la valeur de a
(par exemple) avant que celle-ci ne se fasse \u00e9craser :
>>> a = 3\n>>> b = 5\n>>> temp = a\n>>> a = b\n>>> b = temp\n
Vous pouvez v\u00e9rifier maintenant que les valeurs de a
et de b
ont bien \u00e9t\u00e9 \u00e9chang\u00e9es.
Syntaxe classique et syntaxe Pythonesque
L'\u00e9change de deux variables a
et de b
s'\u00e9crit donc :
>>> temp = a\n>>> a = b\n>>> b = temp\n
Mais il existe aussi une syntaxe particuli\u00e8re \u00e0 Python, bien plus courte : >>> a, b = b, a\n
C'est de nouveau un sucre syntaxique. Cette syntaxe nous dispense de cr\u00e9er nous-m\u00eame une troisi\u00e8me variable. Mais pas de miracle : en interne, Python cr\u00e9e lui-m\u00eame cette variable temporaire. La simultan\u00e9it\u00e9 n'existe pas en informatique. Exercice 4
Une petite erreur s'est gliss\u00e9e \u00e0 Poudlard :
>>> maison_Harry = \"Serpentard\"\n>>> maison_Malfoy = \"Gryffondor\"\n
Corriger cette erreur, de deux mani\u00e8res diff\u00e9rentes. Correction >>> t = maison_Harry\n>>> maison_Harry = maison_Malfoy\n>>> maison_Malfoy = t\n
ou plus rapidement : >>> maison_Harry, maison_Malfoy = maison_Malfoy, maison_Harry\n
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#c-differents-types-de-variables","title":"C. Diff\u00e9rents types de variables","text":"Pour l'instant, les variables que nous avons manipul\u00e9es contiennent toutes des nombres entiers.
Sauf les maisons de Poudlard, qui sont des mots cha\u00eenes de caract\u00e8res.
Pour diff\u00e9rencier la nature de ce que peut contenir une variable, on parle alors de type de variable.
En voici quelques uns, que nous d\u00e9couvrirons au fil de l'ann\u00e9e :
Types de base
Voici les types Python les plus fr\u00e9quemment utilis\u00e9s cette ann\u00e9e:
Type Python Traduction Exemple int
entier 42
float
flottant (d\u00e9cimal) 3.1416
str
cha\u00eene de caract\u00e8res (string) \"NSI\"
bool
bool\u00e9en (True ou False) True
tuple
p-uplet (255, 127, 0)
list
liste [0, 1, 2, 3, 4, 5]
dict
dictionnaire {'Homer':43, 'Marge':41, 'Bart':12, 'Lisa':10, 'Maggie':4}
function
fonction print
Comment conna\u00eetre le type d'une variable ? Il suffit dans la console d'utiliser la fonction type
.
>>> a = 1\n>>> type(a)\n<class 'int'>\n
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#c1-python-et-le-typage-dynamique","title":"C.1 Python et le typage dynamique","text":"Jusqu'\u00e0 pr\u00e9sent, nous ne nous sommes pas occup\u00e9s de pr\u00e9ciser \u00e0 Python le type de notre variable.
a = 3\n
Mais dans certains langages, c'est obligatoire. En C par exemple, il faut \u00e9crire :
int a = 3;\n
Cela signifie (pour le langage C) que notre variable a
n'aura pas le droit de contenir autre chose qu'un nombre entier. Si on \u00e9crit ensuite
a = \"test\";\n
Le compilateur C renverra une erreur : on ne peut pas stocker une cha\u00eene de caract\u00e8res dans une variable qu'on a cr\u00e9\u00e9e comme \u00e9tant de type entier.
Et en Python ?
>>> a = 3\n>>> type(a)\n<class 'int'>\n>>> a = \"test\"\n>>> type(a)\n<class 'str'>\n
Python a chang\u00e9 tout seul le type de notre variable, sans intervention. On parle de typage dynamique.
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#d-bonnes-pratiques-de-nommage","title":"D. Bonnes pratiques de nommage","text":""},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#d1-ce-qui-est-autorise-et-ce-qui-ne-lest-pas","title":"D.1 Ce qui est autoris\u00e9 et ce qui ne l'est pas","text":"Pour nommer correctement une variable, il existe des r\u00e8gles \u00e0 respecter.
Les r\u00e8gles
-
le nom de la variable peut contenir les caract\u00e8res suivants :
- des lettres non accentu\u00e9es. Attention, minuscule et majuscule sont des caract\u00e8res diff\u00e9rents. Les accents sont en fait tol\u00e9r\u00e9s mais sont \u00e0 \u00e9viter.
- des chiffres (mais pas comme premier caract\u00e8re)
- le tiret du bas _ (underscore, tiret du 8)
-
le nom de la variable ne doit pas commencer par un chiffre
- le nom de la variable ne doit pas contenir d'espace
- le nom de la variable ne doit pas \u00eatre un mot-cl\u00e9 du langage.
Liste des mots-cl\u00e9s r\u00e9serv\u00e9s par Python andas assert break class continue def del elif else except False finally for from global if import in is lambda None not or pass raise return True try while with yield
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#d2-du-sens-du-sens-du-sens","title":"D.2 Du sens, du sens, du sens","text":"Hormis pour les indices (de boucles, de tableaux...) un nom de variable (dans un programme destin\u00e9 \u00e0 \u00eatre lu, par vous ou quelqu'un d'autre) doit imp\u00e9rativement avoir du sens :
# PAS BIEN\nif d == 1:\n cep += vm\n\n# BIEN\nif date == 1:\n compte_epargne += versement_mensuel\n
R\u00e8gle d'or
On ne donne jamais un nom de variable au hasard, on le choisit pour qu'il soit explicite.
Oui mais pour donner du sens, il faut souvent plusieurs mots... La longueur du nom de la variable (\u00abc'est trop long \u00e0 taper\u00bb) n'est plus un probl\u00e8me depuis que la grande majorit\u00e9 des IDE propose la compl\u00e9tion automatique. Mais comment former ces longs mots ?
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#d3-syntaxe-des-noms-a-rallonge","title":"D.3 Syntaxe des noms \u00e0 rallonge","text":"Comment accoler des mots
- S'il est compos\u00e9, le nom peut \u00eatre de la forme:
snake_case
: les mots sont s\u00e9par\u00e9s par des underscores. Conseill\u00e9 en Python. camelCase
: les mots sont s\u00e9par\u00e9s par des majuscules mais la 1\u00e8re lettre est minuscule. Conseill\u00e9 en Javascript. PascalCase
: les mots sont s\u00e9par\u00e9s par des majuscules et la 1\u00e8re lettre est majuscule. Conseill\u00e9 en C. kebab-case
: les mots sont s\u00e9par\u00e9s par des tirets courts. Conseill\u00e9 en HTML - CSS.
Sans surprise, en Python, nous utiliserons donc le snake_case
.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/","title":"1.2 Boucle for ... in ...
","text":""},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#1-les-enumerables","title":"1. Les \u00e9num\u00e9rables","text":"En math\u00e9matiques, on dit qu'un ensemble est d\u00e9nombrable lorsqu'on peut associer \u00e0 chaque \u00e9l\u00e9ment de l'ensemble un nombre (traditionnellement 1, 2, 3 ...)
- les fraises Tagada d'un paquet sont d\u00e9nombrables.
- les voitures qui roulent sur l'autoroute sont d\u00e9nombrables.
- l'eau qui coule d'un robinet n'est pas d\u00e9nombrable.
En informatique, il existe un concept similaire qui va d\u00e9signer les objets que l'on peut \u00e9num\u00e9rer, c'est-\u00e0-dire les d\u00e9composer en une succession ordonn\u00e9e d'\u00e9l\u00e9ments. On les appelle les \u00e9num\u00e9rables ou les it\u00e9rables (Python utilise le mot anglais iterable
).
- la variable
\"NSI\"
(qui est de type String
) est \u00e9num\u00e9rable : on peut la d\u00e9composer en N
, S
, I
. - la variable
[4, 3, 17]
(qui est de type List
) est \u00e9num\u00e9rable : on peut la d\u00e9composer en 4
, 3
, 17
. - la variable
5
(qui est de type Int
) n'est PAS \u00e9num\u00e9rable : on ne peut pas la d\u00e9composer.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#2-iterer-sur-les-iterables-la-boucle-for-in","title":"2. It\u00e9rer sur les it\u00e9rables : la boucle for ... in ...
","text":""},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#21-iterer-sur-une-chaine-de-caracteres","title":"2.1 It\u00e9rer sur une cha\u00eene de caract\u00e8res","text":"La principale caract\u00e9ristique d'un ordinateur est d'exceller dans les op\u00e9rations r\u00e9p\u00e9titives.
(je vous laisse retrouver la citation de G\u00e9rard Berry, professeur au Coll\u00e8ge de France, commen\u00e7ant par \u00abl'ordinateur est...\u00bb)
Il existe donc une instruction permettant de faire une (ou plusieurs) action(s) \u00e0 chaque it\u00e9ration sur un \u00e9l\u00e9ment \u00e9num\u00e9rable.
Exemple fondateur n\u00b01
Le programme suivant :
for k in 'NSI':\n print(k)\n
va donner ceci : N\nS\nI\n
Analyse gr\u00e2ce \u00e0 PythonTutor
\u00c9tudions, gr\u00e2ce \u00e0 PythonTutor, le d\u00e9tail de cette ex\u00e9cution.
Cliquez sur Next et observez bien l'\u00e9volution de la variable k
.
La variable k
prend donc successivement toutes les lettre de la cha\u00eene de caract\u00e8re \"NSI\"
.
Pour chaque valeur de k
, la ou les instruction(s) situ\u00e9es de mani\u00e8re indent\u00e9e sous la ligne du for
seront ex\u00e9cut\u00e9es.
Ici, il y a simplement un print(k)
, donc chaque lettre de \"NSI\"
s'affiche l'une apr\u00e8s l'autre.
Exercice 1
Que donne le script suivant ?
for m in 'NASA':\n print(\"bonjour\")\n
Correction bonjour\nbonjour\nbonjour\nbonjour\n
Dans cet exercice, la variable de boucle m
est muette : elle n'appara\u00eet dans les instructions indent\u00e9es sous le for
.
La variable m
prend successivement les valeurs 'N
, 'A'
, 'S'
et 'A'
, mais on ne la voit pas.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#23-lindentation","title":"2.3 L'indentation","text":"L'indentation est primordiale en Python : c'est elle qui indique les blocs de code. Dans d'autres langages, ils peuvent \u00eatre d\u00e9limit\u00e9s par des accolades {
et }
.
Dans une boucle, tout ce qui sera indent\u00e9 sous le for
sera r\u00e9p\u00e9t\u00e9 un certain nombre de fois. Puis le code continuera : on dit qu'on sera sorti de la boucle.
Observez la diff\u00e9rence entre l'ex\u00e9cution des codes suivants :
for m in 'NASA':\n print(\"bonjour\")\n print(\"au revoir\")\n
et
for m in 'NASA':\n print(\"bonjour\")\nprint(\"au revoir\")\n
et persuadez-vous de l'importance d'\u00eatre vigilant sur l'indentation !
Comment \u00e9viter les erreurs classiques
Quand vous \u00e9crivez une boucle for ... in ...
, veillez bien \u00e0 :
- finir la ligne du
for
par les deux points :
- indenter sous le
for
les instructions qui doivent \u00eatre r\u00e9p\u00e9t\u00e9es. Si l'indentation ne s'est pas faite automatiquement apr\u00e8s appui sur la touche Entr\u00e9e
, c'est que vous avez oubli\u00e9 les :
.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#23-iterer-sur-une-liste","title":"2.3 It\u00e9rer sur une liste","text":"Exemple fondateur n\u00b02
Le programme suivant :
for jour in [\"lundi\", \"mardi\", \"mercredi\", \"jeudi\", \"vendredi\"]:\n print(\"je vais au lyc\u00e9e le\", jour)\n
va donner ceci : je vais au lyc\u00e9e le lundi\nje vais au lyc\u00e9e le mardi\nje vais au lyc\u00e9e le mercredi\nje vais au lyc\u00e9e le jeudi\nje vais au lyc\u00e9e le vendredi\n
Analyse gr\u00e2ce \u00e0 PythonTutor
Attention: tr\u00e8s souvent, l'objet \u00e9num\u00e9rable que la boucle va parcourir aura \u00e9t\u00e9 au pr\u00e9alable stock\u00e9 dans une variable :
Exemple fondateur n\u00b03
Le programme pr\u00e9c\u00e9dent est \u00e9quivalent \u00e0 :
semaine = [\"lundi\", \"mardi\", \"mercredi\", \"jeudi\", \"vendredi\"]\nfor jour in semaine:\n print(\"je vais au lyc\u00e9e le\", jour)\n
Notez l'importance d'avoir choisi des noms de variables explicites : ils aident grandement \u00e0 la lisibilit\u00e9 du code.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#3-comment-repeter-n-fois-la-meme-action","title":"3. Comment r\u00e9p\u00e9ter n
fois la m\u00eame action ?","text":"Scratch dispose du (tr\u00e8s pratique) bloc suivant :
Comment effectuer la m\u00eame chose en Python ?
Comment r\u00e9p\u00e9ter 10 fois la phrase \"We're up all night to get lucky\"
?
Nous pourrions nous en sortir par
for k in \"blablablab\": #(1) \n print(\"We're up all night to get lucky\")\n
- n'importe quel mot de 10 caract\u00e8res ferait l'affaire...
mais il doit clairement y avoir mieux...
Il y a mieux !
L'ensemble range
Le programme suivant :
for i in range(5):\n print(\"We're up all night to get lucky\")\n
va donner ceci : We're up all night to get lucky\nWe're up all night to get lucky\nWe're up all night to get lucky\nWe're up all night to get lucky\nWe're up all night to get lucky\n
L\u00e0 encore, le i
est une variable muette.
Le _
comme variable muette
Lorsque la variable de boucle est muette et ne sert qu'\u00e0 effectuer \\(n\\) fois la m\u00eame action, on utilise souvent le caract\u00e8re _
(appel\u00e9 underscore)comme variable de boucle.
Il faut le comprendre comme un avertissement au lecteur du code : \u00abcette boucle ne sert qu'\u00e0 faire \\(n\\) fois la m\u00eame chose\u00bb
for _ in range(5):\n print(\"Tout \u00e7a est tr\u00e8s r\u00e9p\u00e9titif\")\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#4-tout-sur-le-range","title":"4. Tout sur le range
.","text":""},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#41-retour-sur-lexemple-precedent","title":"4.1 Retour sur l'exemple pr\u00e9c\u00e9dent.","text":"Si nous rendions la variable i
moins muette ?
for i in range(5):\n print(i, \"We're up all night to get lucky\")\n
va donner ceci : 0 We're up all night to get lucky\n1 We're up all night to get lucky\n2 We're up all night to get lucky\n3 We're up all night to get lucky\n4 We're up all night to get lucky\n
i
prend donc successivement toutes les valeurs enti\u00e8res entre 0 et 4. Il y en a bien 5."},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#42-utilisation-minimale-de-lobjet-range","title":"4.2 Utilisation minimale de l'objet range()
","text":"Syntaxe minimale de range()
Le programme suivant :
for k in range(4):\n print(k)\n
va donner ceci : 0\n1\n2\n3\n
Interpr\u00e9tation : faire parcourir \u00e0 une variable k
l'ensemble range(n)
va faire prendre \u00e0 k
les valeurs 0, 1, 2, ..., n-1. "},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#43-utilisation-avancee-de-lobjet-range","title":"4.3 Utilisation avanc\u00e9e de l'objet range()
","text":"Syntaxe compl\u00e8te de range()
Le programme suivant :
for k in range(5, 15, 2):\n print(k)\n
va donner ceci : 5\n7\n9\n11\n13\n
Interpr\u00e9tation : faire parcourir \u00e0 k
l'ensemble range(start, stop, step)
fait : - d\u00e9marrer
k
\u00e0 la valeur start
, - progresser
k
de step
en step
tant que k
est strictement inf\u00e9rieur \u00e0 stop
.
Remarques :
- si le
step
est omis, il vaut 1 par d\u00e9faut. - l'objet
range(5)
n'est pas \u00abtechniquement\u00bb \u00e9gal \u00e0 la liste [0, 1, 2, 3, 4]
, car ce n'est pas un objet de type List
:
>>> type(range(5))\n<class 'range'>\n
Si n\u00e9cessaire, on peut le convertir en liste : >>> list(range(5))\n[0, 1, 2, 3, 4]\n
Il faut donc garder en t\u00eate que l'objet renvoy\u00e9 par range()
est un it\u00e9rable assimilable \u00e0 une liste de nombres.
Exercice 2
Faire afficher les s\u00e9ries de nombres suivantes.
On utilisera la syntaxe print(k, end = ' ')
) pour afficher les nombres horizontalement.
A. 0 1 2 3 4 5
Correction for k in range(6):\n print(k, end = ' ')\n
B. 10 11 12 13 14 15
Correction for k in range(10,16):\n print(k, end = ' ')\n
C. 3 6 9 12
Correction for k in range(3,13,3):\n print(k, end = ' ')\n
D. 10 9 8 7 6 5 4 3 2 1 0
Correction for k in range(10,-1,-1):\n print(k, end = ' ')\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#5-une-situation-classique-la-double-boucle","title":"5. Une situation classique : la double boucle","text":"Il est tr\u00e8s souvent utile d'imbriquer une boucle dans une autre, notamment lors du parcours de tous les pixels d'une image. Prenons pour l'instant un exemple num\u00e9rique.
Exemple fondateur
Le programme suivant :
for a in range(1,5):\n for b in range(1,4):\n p = a * b\n print(a, '*', b, '=', p)\n
va donner ceci : 1 * 1 = 1\n1 * 2 = 2\n1 * 3 = 3\n2 * 1 = 2\n2 * 2 = 4\n2 * 3 = 6\n3 * 1 = 3\n3 * 2 = 6\n3 * 3 = 9\n4 * 1 = 4\n4 * 2 = 8\n4 * 3 = 12\n
Analyse gr\u00e2ce \u00e0 PythonTutor
Exercice 3
\u00c9crire un programme qui affiche :
Papa dit : \u00ab et une cuill\u00e8re pour Riri ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re pour Fifi ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re pour Loulou ! \u00bb\nMaman dit : \u00ab et une cuill\u00e8re pour Riri ! \u00bb\nMaman dit : \u00ab et une cuill\u00e8re pour Fifi ! \u00bb\nMaman dit : \u00ab et une cuill\u00e8re pour Loulou ! \u00bb\nMamie dit : \u00ab et une cuill\u00e8re pour Riri ! \u00bb\nMamie dit : \u00ab et une cuill\u00e8re pour Fifi ! \u00bb\nMamie dit : \u00ab et une cuill\u00e8re pour Loulou ! \u00bb\n
Correction adultes = ['Papa', 'Maman', 'Mamie']\nenfants = ['Riri', 'Fifi', 'Loulou']\n\nfor parent in adultes:\n for enfant in enfants:\n print(parent, 'dit : \u00ab et une cuill\u00e8re pour', enfant, '! \u00bb') \n
Exercice 4
Rajouter \u00e0 la phrase pr\u00e9c\u00e9dente le contenu de la cuill\u00e8re (pur\u00e9e puis compote).
Exemple :
Papa dit : \u00ab et une cuill\u00e8re de pur\u00e9e pour Riri ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re de compote pour Riri ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re de pur\u00e9e pour Fifi ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re de compote pour Fifi ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re de pur\u00e9e pour Loulou ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re de compote pour Loulou ! \u00bb\nMaman dit : \u00ab et une cuill\u00e8re de pur\u00e9e pour Riri ! \u00bb\nMaman dit : \u00ab et une cuill\u00e8re de compote pour Riri ! \u00bb\n...\n
Correction for parent in ['Papa', 'Maman', 'Mamie']:\n for enfant in ['Riri', 'Fifi', 'Loulou']:\n for nourriture in ['pur\u00e9e', 'compote']:\n print(parent, 'dit : \u00ab et une cuill\u00e8re de', nourriture, 'pour', enfant, '! \u00bb')\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#6-pour-conclure","title":"6. Pour conclure","text":"\u00c0 retenir
- La boucle
for ... in ...
s'utilise lorsque : - on veut parcourir un \u00e0 un les \u00e9l\u00e9ments d'un objet it\u00e9rable (une cha\u00eene de caract\u00e8re, une liste, un tuple, un dictionnaire...)
- on veut r\u00e9p\u00e9ter une action un nombre de fois connu \u00e0 l'avance. On parle de boucle born\u00e9e.
-
Les instructions r\u00e9p\u00e9t\u00e9es peuvent - mais ce n'est pas obligatoire - faire appel \u00e0 la variable de boucle, mais il ne faut pas que ces instructions la modifient.
-
Ne pas oublier les :
et l'indentation !
range(n)
g\u00e9n\u00e8re une s\u00e9quence de n
nombres entiers: on s'en servira d\u00e8s qu'on aura besoin de r\u00e9p\u00e9ter n
fois des instructions.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exercices/","title":"Exercices sur la boucle for ... in
","text":"Exercice 1
On donne une liste d'acteurs :
liste_acteurs = ['Tahar', 'Omar', 'Guillaume', 'Swann', 'Alex', 'Roschdy']\n
Utilisez cette liste pour produire la sortie suivante:
Tahar a eu le C\u00e9sar du meilleur acteur\nOmar a eu le C\u00e9sar du meilleur acteur\nGuillaume a eu le C\u00e9sar du meilleur acteur\nSwann a eu le C\u00e9sar du meilleur acteur\nAlex a eu le C\u00e9sar du meilleur acteur\nRoschdy a eu le C\u00e9sar du meilleur acteur\n
Correction liste_acteurs = ['Tahar', 'Omar', 'Guillaume', 'Swann', 'Alex', 'Roschdy']\n\nfor acteur in liste_acteurs:\n print(acteur, 'a eu le C\u00e9sar du meilleur acteur')\n
Concat\u00e9nation de caract\u00e8res
Il est possible de coller (le vrai mot est concat\u00e9ner) deux cha\u00eenes de caract\u00e8res par l'op\u00e9rateur +
:
>>> \"a\" + \"b\"\n'ab'\n
Exercice 2
Dans l'extrait de code suivant:
chaine
est une variable initialis\u00e9e avec un str
vide : \"\"
; - on veut qu'en sortie de programme cette variable contienne la valeur
'bravo'
.
L'id\u00e9e est d'ajouter une par une les lettres \u00e0 la variable chaine
.
\u00c0 l'ex\u00e9cution, le programme doit afficher uniquement bravo
.
Compl\u00e9ter le code.
chaine = \"\"\nfor ... in ['b', 'r', 'a', 'v', 'o']:\n ...\nprint(chaine)\n
Cette variable chaine
est appel\u00e9e un accumulateur.
Correction chaine = ''\nfor lettre in ['b', 'r', 'a', 'v', 'o']:\n chaine = chaine + lettre #(1)\n\nprint(chaine)\n
- Ou bien
chaine += lettre
Exercice 3
En Python, la fonction ord
renvoie le code Unicode d'un caract\u00e8re et la fonction chr
le contraire: elle renvoie le caract\u00e8re correspondant \u00e0 un code Unicode.
Par exemple:
>>> ord('a')\n97\n>>> chr(97)\n'a'\n
Voici une liste contenant les codes Unicode des lettres d'un mot secret... \u00c0 vous d'\u00e9crire un programme o\u00f9 en sortie, la variable mot_secret
contiendra la cha\u00eene de caract\u00e8res de ce mot.
mystere = [111, 107, 44, 32, 98, 105, 101, 110, 32, 106, 111, 117, 233]\nmot_secret = \"\"\n\n# \u00e0 vous !\n
Correction mystere = [111, 107, 44, 32, 98, 105, 101, 110, 32, 106, 111, 117, 233]\nmot_secret = \"\"\n\nfor nombre in mystere:\n lettre = chr(nombre)\n mot_secret = mot_secret + lettre\n\nprint(mot_secret)\n
Exercice 4
On souhaite calculer la somme des 1000 premiers nombres entiers naturels, c'est-\u00e0-dire:
\\(1+2+3+4+5+ \\dots +999+1000\\)
\u00c9crire un programme avec une variable somme
accumulateur (comme \u00e0 l'exercice 3) qui contiendra la valeur souhait\u00e9e en fin de programme.
Correction somme = 0\nfor k in range(1001):\n somme += k\nprint(somme)\n
Exercice 5
Calculer \\(1\\times 2 \\times 3 \\times \\dots 99 \\times 100\\).
Correction produit = 1\nfor k in range(1,101):\n produit = produit * k\nprint(produit) \n
Exercice 6
Proposer un code qui \u00e9crit la table de multiplication de 7, de 8 et de 9.
La sortie doit ressembler \u00e0 :
7*1 = 7\n\n7*2 = 14\n\n... \n...\n\n9*9 = 81 \n
Correction for a in range(7, 10):\n for b in range(1, 10):\n print(a, '*', b, '=', a*b)\n
Exercice 7
Sur un jeu d'\u00e9checs, les cases sont rep\u00e9r\u00e9es par une lettre (de A jusqu'\u00e0 H) et par un chiffre (de 1 jusqu'\u00e0 8).
Les cases sont donc A1, A2, A3, ..., H7, H8.
Proposer un code qui \u00e9crit toutes les cases possibles.
Correction for lettre in 'ABCDEFGH':\n for chiffre in '12345678':\n case = lettre + chiffre\n print(case)\n
Autre solution utilisant la conversion d'un entier en chaine de caract\u00e8res, gr\u00e2ce \u00e0 la fonction str
:
for lettre in 'ABCDEFGH':\n for chiffre in range(1, 9):\n case = lettre + str(chiffre)\n print(case)\n
Exercice 8
Travail sur ipythonblocks
:
Exercice \u00e0 faire sur Capytale : https://capytale2.ac-paris.fr/web/c/8869-1863952
Correction Ex. 1 grid = BlockGrid(10, 10, fill=(125,234,231))\n\nfor k in range(10):\n grid[k,2].set_colors(0,0,0)\ngrid.show()\n
Correction Ex. 2 grid = BlockGrid(10, 10, fill=(125, 234, 231))\n\nfor col in range(0, 10, 2):\n for lig in range(10):\n grid[lig, col].set_colors(0, 0, 0)\n\ngrid.show()\n
Correction Ex. 3 grid = BlockGrid(10, 10, fill=(125,234,231))\n\nfor col in range(0, 10, 2):\n for lig in range(0, 10, 2):\n grid[lig, col].set_colors(0, 0, 0)\n\nfor col in range(1, 10, 2):\n for lig in range(1, 10, 2):\n grid[lig, col].set_colors(0, 0, 0) \n\ngrid.show()\n
ou bien (plus difficile):
grid = BlockGrid(10, 10, fill=(125,234,231))\n\nfor x in range(10):\n for y in range(10):\n if (x + y) % 2 == 1: #on teste si la somme abscisse + ordonn\u00e9e est impaire\n grid[x, y].set_colors(0, 0, 0) \n\ngrid.show()\n
Correction Ex. 4 grid = BlockGrid(10, 10, fill=(125,234,231))\n\nfor y in range(10):\n for x in range(y, 10):\n grid[x, y].set_colors(0, 0, 0) \ngrid.show()\n
Exercice 9
Dans ma trousse je dispose de 5 feutres de couleur :
- jaune (J)
- vert (V)
- noir (N)
- bleu (B)
- orange (O)
Pour un exercice, je dois colorier 3 pastilles en choissant sans aucune contrainte des couleurs parmi les 5 disponibles. Je peux tout colorier en jaune (JJJ
) ou bien colorier la 1\u00e8re en orange, la 2\u00e8me en bleu, la 3\u00e8me en vert (OBV
)
Faire afficher la totalit\u00e9 des combinaisons possibles.
Correction couleurs = 'JVNBO'\nfor c1 in couleurs:\n for c2 in couleurs:\n for c3 in couleurs:\n print(c1 + c2 + c3)\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/","title":"Exercices sous Processing","text":""},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#1-presentation-de-processing","title":"1. Pr\u00e9sentation de Processing","text":" Processing est un outil de cr\u00e9ation multim\u00e9dia utilisant le code informatique. Simple de prise en main, il a \u00e9t\u00e9 cr\u00e9\u00e9 par des artistes pour des artistes. On peut utiliser le langage Python pour entrer les instructions.
Nous l'utiliserons pour ajouter du graphisme \u00e0 nos cr\u00e9ations. Dans tous les exercices de cette page, les dessins r\u00e9alis\u00e9s seront statiques. Nous verrons plus tard comment Processing permet tr\u00e8s facilement de faire des animations.
Documentation - Le site officiel (anglais)
- Un manuel d'utilisation (fran\u00e7ais)
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#2-les-bases-de-processing","title":"2. Les bases de Processing","text":""},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#21-repere","title":"2.1 Rep\u00e8re","text":"\u00c0 l'ex\u00e9cution de tout script Processing, une fen\u00eatre s'affiche avec une zone de dessin. Sa taille se d\u00e9finit \u00e0 l'aide de la fonction size
. Par exemple, pour cr\u00e9er une zone de dessin de 300 pixels sur 200 pixels, on utilisera:
size(300, 200)\n
Chaque pixel de cette zone est rep\u00e9r\u00e9e par des coordonn\u00e9es dans le rep\u00e8re suivant, dont l'origine se situe en haut \u00e0 gauche et l'axe des ordonn\u00e9es est orient\u00e9 vers le bas.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#22-traces","title":"2.2 Trac\u00e9s","text":"Trac\u00e9s de base
point
: permet de dessiner un point (pixel). En param\u00e8tre, les coordonn\u00e9es du point. line
: permet de tracer une ligne entre deux points. En param\u00e8tres, les coordonn\u00e9es des deux points. rect
: permet de tracer un rectangle. En param\u00e8tres, les coordonn\u00e9es du sommet haut-gauche, puis la largeur et la hauteur du rectangle. ellipse
: permet de tracer une ellipse. En param\u00e8tres, les coordonn\u00e9es du centre, puis la largeur et la hauteur (mettre la m\u00eame valeur pour un cercle).
Exemples Copier-coller le code suivant et faire varier les param\u00e8tres pour bien les comprendre.
size(200, 200)\npoint(10, 60)\nline(10, 10, 100, 150)\nrect(80, 10, 20, 50)\nellipse(150, 100, 80, 40)\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#23-couleurs","title":"2.3 Couleurs","text":"Pinceau
background
: permet de d\u00e9finir la couleur du fond de la zone de dessin. En param\u00e8tres, les trois composantes RGB de la couleur. stroke
: permet de d\u00e9finir la couleur du pinceau (noir par d\u00e9faut) pour le contour de la forme. En param\u00e8tres, les trois composantes RGB de la couleur. noStroke
: permet de dessiner une forme sans coutour (pas de param\u00e8tre). strokeWeight
: permet de d\u00e9finir la largeur du pinceau. En param\u00e8tre, le nombre de pixel. fill
: permet de d\u00e9finir la couleur de remplissage de la forme. En param\u00e8tres, les trois composantes RGB de la couleur.
Exemples Copier-coller le code suivant et faire varier les param\u00e8tres pour bien les comprendre.
size(200, 200)\nbackground(255, 255, 255)\nstroke(255, 0, 0)\npoint(10, 60)\nline(10, 10, 100, 150)\nstroke(0, 127, 255)\nstrokeWeight(5)\nrect(80, 10, 20, 50)\nnoStroke()\nfill(204, 153, 204)\nellipse(150, 100, 80, 40)\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#3-exercices-sur-la-simple-boucle","title":"3. Exercices sur la simple boucle","text":"Tous les exercices sont \u00e0 faire dans une fen\u00eatre de 300 pixels sur 300 pixels.
Exercice 1
\u00c9nonc\u00e9Correction en ProcessingCorrection en p5 L'objectif est d'obtenir dix lignes al\u00e9atoires, de couleur al\u00e9atoire et d'\u00e9paisseur 10.
Aide
- la fonction
random(a,b)
permet d'obtenir un entier pseudo al\u00e9atoire entre a
et b
.
size(300,300)\nbackground(0)\nfor k in range(10):\n Ax = random(0,300)\n Ay = random(0,300)\n Bx = random(0,300)\n By = random(0,300)\n strokeWeight(10)\n stroke(random(0,255), random(0,255), random(0,255))\n line(Ax,Ay,Bx,By)\n
from p5 import *\n\ndef setup():\n createCanvas(300, 300)\n noLoop()\n\ndef draw():\n background(0)\n for k in range(10):\n Ax = random(0,300)\n Ay = random(0,300)\n Bx = random(0,300)\n By = random(0,300)\n strokeWeight(10)\n stroke(random(0,255), random(0,255), random(0,255))\n line(Ax,Ay,Bx,By)\n\nrun()\n
Exercice 2 difficile
\u00c9nonc\u00e9Correction en ProcessingCorrection en p5 Reprendre l'exercice pr\u00e9c\u00e9dent en faisant en sorte que chaque ligne commence l\u00e0 o\u00f9 une autre s'arr\u00eate (hormis la premi\u00e8re)
size(300,300)\nbackground(0)\nAx = random(0,300)\nAy = random(0,300)\nfor k in range(10):\n Bx = random(0,300)\n By = random(0,300)\n strokeWeight(10)\n stroke(random(0,255), random(0,255), random(0,255))\n line(Ax,Ay,Bx,By)\n Ax = Bx\n Ay = By\n
from p5 import *\n\ndef setup():\n createCanvas(300, 300)\n noLoop()\n\ndef draw():\n background(0)\n Ax = random(0,300)\n Ay = random(0,300)\n for k in range(10):\n Bx = random(0,300)\n By = random(0,300)\n strokeWeight(10)\n stroke(random(0,255), random(0,255), random(0,255))\n line(Ax,Ay,Bx,By)\n Ax = Bx\n Ay = By\n\nrun()\n
Exercice 3
\u00c9nonc\u00e9Correction en ProcessingCorrection en p5 Tracer 50 disques de position, diam\u00e8tre, couleur et transparence al\u00e9atoires.
Aide
- la transparence s'obtient en rajoutant un 4\u00e8me param\u00e8tre (entre 0 et 255) \u00e0 la suite de RGB. On appelle ce param\u00e8tre le canal Alpha. Ex : (255,0,0,200) est un rouge tr\u00e8s transparent.
size(300,300)\nbackground(0)\nfor k in range(50):\n Ax = random(0,300)\n Ay = random(0,300)\n diametre = random(0,50)\n noStroke()\n r = random(0,255)\n g = random(0,255)\n b = random(0,255)\n a = random(0,255)\n fill(r, g, b, a)\n ellipse(Ax,Ay,diametre, diametre)\n
from p5 import *\n\ndef setup():\n createCanvas(300, 300)\n noLoop()\n\ndef draw():\n background(0)\n for k in range(50):\n Ax = random(0,300)\n Ay = random(0,300)\n diametre = random(0,50)\n noStroke()\n r = random(0,255)\n g = random(0,255)\n b = random(0,255)\n a = random(0,255)\n fill(r, g, b, a)\n ellipse(Ax,Ay,diametre, diametre)\n\nrun()\n
Exercice 4 \u00e0 faire sur Capytale : activit\u00e9 55f1-63735
Lire obligatoirement au pr\u00e9alable la page \u00abComment passer d'un code Processing \u00e0 un code p5\u00bb
\u00c9nonc\u00e9 Proposer un code r\u00e9alisant la figure suivante. Votre code devra obligatoirement comporter une boucle for
.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#4-exercices-sur-la-double-boucle","title":"4. Exercices sur la double boucle","text":"La structure de double boucle va permettre (par exemple) de parcourir l'int\u00e9gralit\u00e9 des pixels d'une image.
Exercices \u00e0 faire sur Capytale : activit\u00e9 38d9-68425
Exercice 5
Construire une image o\u00f9 tous les points ont une couleur al\u00e9atoire.
Exercice 6
Construire une image constitu\u00e9e de carr\u00e9s de 20 pixels de cot\u00e9, de couleur al\u00e9atoire. L'image est toujours un carr\u00e9 de c\u00f4t\u00e9 300 pixels.
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/","title":"1.3 Boucle While","text":""},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#1-premiers-exemples","title":"1. Premiers exemples","text":"\u00c0 la diff\u00e9rence essentielle des boucles for
, dont on peut savoir \u00e0 l'avance combien de fois elles vont \u00eatre ex\u00e9cut\u00e9es, les boucles while
sont des boucles dont on ne sort que lorsqu'une condition n'est plus satisfaite.
Avec donc le risque de rester infiniment bloqu\u00e9 \u00e0 l'int\u00e9rieur !
Exemple fondateur n\u00b01
Le programme suivant :
a = 0\nwhile a < 3:\n print(\"ok\")\n a = a + 1\nprint(\"fini\")\n
va donner ceci : ok\nok\nok\nfini\n
Analyse gr\u00e2ce \u00e0 PythonTutor
Question
le code ci-dessous va-t-il donner un r\u00e9sultat diff\u00e9rent ?
a = 0\nwhile a < 3:\n a = a + 1\n print(\"ok\")\nprint(\"fini\")\n
R\u00e9sultat du programme \u23ec ok\nok\nok\nfini\n
Conclusion : l'\u00e9valuation de la condition ne se fait pas \u00e0 chaque ligne mais bien au d\u00e9but de chaque tour de boucle. Si la variable qui d\u00e9clenchera la sortie de boucle atteint sa valeur de sortie au milieu des instructions, les lignes restantes sont quand m\u00eame ex\u00e9cut\u00e9es.
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#2-syntaxe-generale","title":"2. Syntaxe g\u00e9n\u00e9rale","text":"\u00c9criture d'une boucle while
while condition:\n instruction1\n instruction2\n ...\n instructionN\n
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#21-la-condition","title":"2.1 La condition","text":"La condition
est un bool\u00e9en, c'est-\u00e0-dire une expression que Python \u00e9valuera \u00e0 True
ou \u00e0 False
.
Prenons une variable a
\u00e9gale \u00e0 10.
>>> a = 10\n>>> a\n10\n
Voici diff\u00e9rents tests sur cette variable a
. Chacun de ces tests va donner un bool\u00e9en, qui sera \u00e9gal \u00e0 True
ou \u00e0 False
.
La syntaxe de ces tests est \u00e0 conna\u00eetre par c\u0153ur.
>>> a > 8\nTrue\n>>> a > 12\nFalse\n>>> a == 10\nTrue\n>>> a != 7\nTrue\n>>> a != 10\nFalse\n>>> a >= 10\nTrue\n
Un cours sur les bool\u00e9ens aura lieu ici.
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#22-les-instructions","title":"2.2 Les instructions","text":"Les instructions instruction1
jusqu'\u00e0 instructionN
sont ex\u00e9cut\u00e9es dans cet ordre \u00e0 chaque tour de boucle.
Attention : ces instructions doivent obligatoirement avoir un impact sur la condition
\u00e9valu\u00e9e apr\u00e8s le while
(dans le cours sur la dichotomie, nous \u00e9voquerons la notion de variant de boucle).
Voir le pi\u00e8ge n\u00b01 ...
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#3-les-pieges","title":"3. Les pi\u00e8ges ...","text":""},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#31-piege-n1-ne-jamais-sortir-de-la-boucle","title":"3.1 pi\u00e8ge n\u00b01 : ne JAMAIS SORTIR de la boucle","text":"Exemple fondateur n\u00b02
Le programme suivant :
a = 0\nwhile a < 3:\n print(\"ok\")\n a = a + 1\n a = a * 0\nprint(\"ce texte ne s'\u00e9crira jamais\")\n
va \u00e9crire une suite infinie de ok
et ne jamais s'arr\u00eater"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#32-piege-n2-ne-jamais-entrer-dans-la-boucle","title":"3.2 pi\u00e8ge n\u00b02 : ne JAMAIS ENTRER dans la boucle","text":"Exemple fondateur n\u00b03
Le programme suivant :
a = 0\nwhile a > 10:\n print(\"ce texte non plus ne s'\u00e9crira jamais\")\n a = a + 1\n\nprint(\"fini\") \n
va \u00e9crire fini
et s'arr\u00eater.
Exercice 1
Trouver le plus petit nombre entier \\(n\\) tel que \\(2^n\\) soit sup\u00e9rieur \u00e0 1 milliard.
Correction n = 1\nwhile 2**n < 10**9:\n n = n + 1\nprint('trouv\u00e9 : ',n)\n
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#4-quelques-remarques","title":"4. Quelques remarques","text":""},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#41-lien-entre-while-et-for","title":"4.1 Lien entre while
et for
","text":"La boucle born\u00e9e for
que nous avons \u00e9tudi\u00e9e est tr\u00e8s pratique.
Mais nous pourrions nous en passer : toutes les boucles for
peuvent en fait \u00eatre r\u00e9-\u00e9crites en utilisant while
. (alors que la r\u00e9ciproque est fausse)
Exercice 2
On consid\u00e8re le code ci-dessous :
for k in range(5):\n print(\"scooby-doo\")\n
R\u00e9-\u00e9crire ce code en utilisant une boucle while
. Correction k = 0\nwhile k < 5:\n print('scooby-doo')\n k = k + 1\n
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#42-les-boucles-infinies-volontaires","title":"4.2 Les boucles infinies volontaires","text":"La boucle infinie a \u00e9t\u00e9 pr\u00e9sent\u00e9e comme un danger qu'il faut \u00e9viter.
Pourtant, dans quelques situations, il est d'usage d'enfermer volontairement l'utilisateur dans une boucle infinie.
Observez et ex\u00e9cutez le code suivant :
while True:\n reponse = input(\"tapez sur la lettre S du clavier pour me sortir de cet enfer : \")\n if reponse == 's':\n break\n\nprint(\"merci, j'\u00e9tais bloqu\u00e9 dans une boucle infinie\")\n
- le d\u00e9but du code :
while True
est typique des boucles infinies volontaires. On aurait tout aussi bien pu \u00e9crire while 3 > 2
(on rencontre m\u00eame parfois des while 1
) - vous avez d\u00e9couvert l'expression
break
qui comme son nom l'indique permet de casser la boucle (cela marche pour while
comme pour for
) et donc d'en sortir. Son emploi est controvers\u00e9 parmi les puristes de la programmation. Nous dirons juste que c'est une instruction bien pratique.
Exercice 3
Reprendre l'exemple pr\u00e9c\u00e9dent en faisant deviner un mot de passe (pr\u00e9alablement stock\u00e9 dans une variable).
Correction mdp = 'supermotdepasse'\n\nwhile True:\n rep = input('mot de passe ?')\n if rep == mdp:\n break\nprint('acc\u00e8s autoris\u00e9')\n
mieux :
import hashlib\nhsh = '696cebb8f23e45f3c3d8e6582bc1a8182abc0119ed3dd89b7de069a9ea8957ab'\n\nwhile True:\n rep = input(\"mot de passe \")\n if hashlib.sha256(rep.encode(\"utf-8\")).hexdigest() == hsh:\n break\nprint(\"acc\u00e8s autoris\u00e9\")\n
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/exercices/","title":"Exercices sur la boucle while
","text":"Exercice 1
Pour chaque code, \u00e9crire ce qui va s'afficher en console.
Code A
c = 0\nwhile c <= 3:\n print(\"ok\")\n c += 1\n
Correction ok\nok\nok\nok\n
Code B
k = 0\nwhile k > 3:\n print(\"ok\")\n k += 1\nprint(\"fini\")\n
Correction fini\n
Code C
n = 0\nwhile n < 4:\n print(\"ok\")\n n += 2\n
Correction ok\nok\n
Exercice 2
Que va afficher le code ci-dessous ?
c = 0\nmot = 'a'\nwhile mot != 'aaaa':\n mot += 'a'\n c += 1\nprint(c)\n
Correction Il va afficher 4.
Exercice 3
Un capital de 10 000 \u20ac est plac\u00e9 au taux annuel de 4 %.
\u00c9crire le code permettant d'afficher au bout de combien d'ann\u00e9es le capital va d\u00e9passer 14 000 \u20ac.
On rappelle qu'une augmentation de 4 % correspond \u00e0 une multiplication par 1,04.
Correction capital = 10000\nannee = 0\nwhile capital < 14000:\n annee += 1\n capital = capital * 1.04 #(1)\nprint(annee)\n
- ou
capital *= 1.04
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/","title":"1.4 Instruction conditionnelle if","text":"L'instruction conditionnelle if
permet de soumettre l'ex\u00e9cution d'instructions \u00e0 une condition donn\u00e9e. Cette condition sera une expression bool\u00e9enne, comme pour la boucle while
.
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/#1-exemples-fondateurs","title":"1. Exemples fondateurs","text":"Dans les exemples ci-dessous, changez la valeur affect\u00e9e \u00e0 la variable age
afin d'observer les modifications de comportement du programme.
Exemple fondateur n\u00b01
L'exemple minimal ci-dessous ne contient que le mot-cl\u00e9 if
.
age = 20\nif age >= 18:\n print(\"Tu as le droit de vote\")\n
Exemple fondateur n\u00b02
La structure qu'on rencontrera le plus souvent est la structure if ... else ...
age = 20\nif age >= 18:\n print(\"Tu as le droit de vote\")\nelse:\n print(\"D\u00e9sol\u00e9, il faudra attendre\", 18 - age, \"ans avant de pouvoir voter\")\n
Syntaxe g\u00e9n\u00e9rale
if expression bool\u00e9enne:\n *instructions \u00e0 effectuer si l'expression est vraie*\nelse:\n *instructions \u00e0 effectuer si l'expression est fausse*\n
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/#2-levaluation-de-la-condition","title":"2. L'\u00e9valuation de la condition","text":"Comme pour la boucle while
, on dit que l'expression qui suit le if
est \u00e9valu\u00e9e par Python lors de l'ex\u00e9cution du programme.
Cette \u00e9valuation renvoie un bool\u00e9en, True
ou False
.
Les symboles de comparaison (ou d'appartenance) permettant d'\u00e9crire une condition sont :
Op\u00e9rateurs de comparaison
Op\u00e9rateur Signification ==
est \u00e9gal \u00e0 !=
est diff\u00e9rent de <
inf\u00e9rieur \u00e0 >
sup\u00e9rieur \u00e0 <=
inf\u00e9rieur ou \u00e9gal \u00e0 >=
sup\u00e9rieur ou \u00e9gal \u00e0 in
appartient \u00e0 not in
n'appartient pas \u00e0 Exemples
>>> a = 2\n\n>>> a == 3\nFalse\n\n>>> a == 2\nTrue\n\n>>> a != 1\nTrue\n\n>>> a > 2\nFalse\n\n>>> a >= 2\nTrue\n\n>>> a <= 2\nTrue\n\n>>> a <= 5\nTrue\n\n>>> 'e' in 'abracadabra'\nFalse\n\n>>> 'b' in 'abracadabra'\nTrue\n\n>>> 'A' not in 'abracadabra'\nTrue\n\n>>> not True\nFalse\n
Comme nous le verrons dans le cours sur les bool\u00e9ens, ces conditions peuvent \u00eatre combin\u00e9es avec (par exemple) les mots-cl\u00e9s and
ou or
:
>>> b = 20\n>>> b > 15 and b < 30\nTrue\n>>> b > 2000 or b < 30\nTrue\n
Exercice 1
Compter le nombre de voyelles de la phrase 'cet exercice est prodigieusement ennuyeux'
phrase = 'cet exercice est prodigieusement ennuyeux'\nvoyelles = 'aeiouy'\n
Correction phrase = 'cet exercice est prodigieusement ennuyeux'\nvoyelles = 'aeiouy'\n\ncompteur = 0\n\nfor lettre in phrase:\n if lettre in voyelles:\n compteur += 1\n\nprint(compteur)\n
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/#3-un-test-tres-frequent-le-test-de-divisibilite","title":"3. Un test tr\u00e8s fr\u00e9quent : le test de divisibilit\u00e9","text":"Exemple fondateur n\u00b03
Pour tester si un nombre n
est divisible par un nombre d
, on teste si le reste de la division euclidienne de n
par d
est \u00e9gal \u00e0 0 :
n = 17\nif n % 2 == 0:\n print(n, \"est un nombre pair\")\nelse:\n print(n, \"est un nombre impair\")\n
Exercice 2
Afficher la liste de tous les nombres entre 1 et 100 qui sont divisibles \u00e0 la fois par 2 et par 7.
Correction for n in range(1,101):\n if n % 2 == 0 and n % 7 == 0:\n print(n)\n
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/#4-les-cas-multiples-utilisation-de-elif","title":"4. Les cas multiples : utilisation de elif
","text":"Dans les situations o\u00f9 l'on veut effectuer des instructions diff\u00e9rentes selon les diff\u00e9rentes valeurs prises par une variable, on peut imbriquer les instructions if
... else
.
Observer par exemple le code ci-dessous :
moyenne = 13\n\nif moyenne < 8:\n print(\"rat\u00e9\")\nelse:\n if moyenne < 10:\n print(\"rep\u00eachage\")\n else:\n if moyenne < 12:\n print(\"admis\")\n else:\n if moyenne < 14:\n print(\"mention AB\")\n else:\n if moyenne < 16:\n print(\"mention B\")\n else:\n print(\"mention TB\")\n
Mais cela est vite long et peu lisible, et les diff\u00e9rents niveaux d'indentation peuvent devenir pi\u00e9geux.
Il existe alors une instruction qui contracte else
et if
: elif
(sinon si).
Ce code devient alors
moyenne = 7\n\nif moyenne < 8:\n print(\"rat\u00e9\")\nelif moyenne < 10:\n print(\"rep\u00eachage\")\nelif moyenne < 12:\n print(\"admis\")\nelif moyenne < 14:\n print(\"mention AB\")\nelif moyenne < 16:\n print(\"mention B\")\nelse:\n print(\"mention TB\")\n
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/#4-recreation-a-vous-dobeir","title":"4. R\u00e9cr\u00e9ation : \u00e0 vous d'ob\u00e9ir !","text":"Le site https://compute-it.toxicode.fr/ vous demande d'ex\u00e9cuter mentalement les instructions affich\u00e9es, \u00e0 l'aide des touches directionnelles de votre clavier. Attention, ce site est tr\u00e8s addictif !
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/exercices/","title":"Exercices","text":"Exercice 1
\u00c9crire un programme qui demande deux nombres et qui affiche le plus grand des deux.
Aide : pour stocker dans une variable n
un nombre tap\u00e9 au clavier par l'utilisateur, on utilise le code suivant :
n = int(input('Entrez un nombre'))\n
Exemples d'utilisation du programme :
Premier nombre ? 12\nDeuxi\u00e8me nombre ? 45\nle nombre le plus grand est 45\n
Premier nombre ? 17\nDeuxi\u00e8me nombre ? 17\nles deux nombres sont \u00e9gaux\n
Correction n1 = int(input('Premier nombre ?'))\nn2 = int(input('Deuxi\u00e8me nombre ?'))\n\nif n1 > n2:\n print('le nombre le plus grand est', n1)\nelif n2 > n1:\n print('le nombre le plus grand est', n2)\nelse:\n print('les deux nombres sont \u00e9gaux')\n
Exercice 2
Le jeu du FizzBuzz : il s'agit de compter \u00e0 partir de 1 en rempla\u00e7ant certains nombres par Fizz, Buzz ou Fizzbuzz :
- si le nombre est divisible par 3, on ne le dit pas et on le remplace par Fizz.
- si le nombre est divisible par 5, on ne le dit pas et on le remplace par Buzz.
- si le nombre est divisible par 3 et par 5, on ne le dit pas et on le remplace par FizzBuzz.
\u00c9crire un code qui joue au FizzBuzz jusqu'\u00e0 20.
Exemple d'utilisation du programme :
1\n2\nfizz\n4\nbuzz\nfizz\n7\n8\n...\n
Correction for k in range(1, 21):\n if k % 3 == 0 and k % 5 == 0:\n print('fizzbuzz')\n elif k % 3 == 0:\n print('fizz')\n elif k % 5 == 0:\n print('buzz')\n else:\n print(k)\n
Exercice 3
Une ann\u00e9e est d\u00e9clar\u00e9e bissextile (et compte donc 366 jours au lieu de 365) si elle est :
- soit divisible par 400.
- soit divisible par 4 mais pas divisible par 100.
\u00c9crire un code qui d\u00e9termine si une ann\u00e9e est bissextile ou non.
Explication : la Terre faisant le tour du Soleil en un peu plus que 365 jours, on s'est dit qu'on allait rajouter un jour tous les 4 ans, mais c'\u00e9tait trop, alors on a enlev\u00e9 un jour tous les 100 ans, mais c'\u00e9tait plus assez, alors on a rajout\u00e9 un jour tous les 400 ans, ce qui donne une approximation convenable.
Correction annee = int(input(\"ann\u00e9e ? \"))\n\nif annee % 400 == 0:\n print(annee, 'est bissextile')\nelif annee % 4 == 0 and annee % 100 != 0:\n print(annee, 'est bissextile')\nelse:\n print(annee, \"n'est pas bissextile\")\n
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/","title":"Macro Syntax Error","text":"File: T1_Demarrer_en_Python/1.5_Fonctions/cours.md
Line 499 in Markdown file: expected token ',', got 'string'
\"\"\"\n
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/exercices/","title":"Exercices","text":"Exercice 1
\u00c9nonc\u00e9Tester sa fonction \u00c9crire une fonction maxi
qui prend comme param\u00e8tres deux nombres n1
et n2
et qui renvoie le plus grand \u00e9l\u00e9ment entre n1
et n2
.
Exemple d'utilisation
>>> maxi(3,1)\n3\n
Vous pouvez utiliser la fonction de tests ci-dessous :
def test_maxi():\n assert maxi(3,4) == 4\n assert maxi(5,2) == 5\n assert maxi(7,7) == 7\n print(\"tests ok\")\n
Correction def maxi(n1, n2):\n if n1 < n2 :\n return n2\n else :\n return n1\n
Exercice 2
\u00c9crire une fonction moyenne
qui prend en param\u00e8tres trois nombres a
, b
et c
et qui renvoie la moyenne de ces trois nombres.
Exemple d'utilisation
>>> moyenne(6, 15, 9)\n10\n
Correction def moyenne(a, b, c):\n return (a + b + c) / 3 \n
Exercice 3
\u00c9crire une fonction somme
qui prend en param\u00e8tre un entier positif n
et qui renvoie la somme de tous les entiers de 1 \u00e0 n
.
\\(S = 1+2+3+4+5+ \\dots +(n-1) + n\\)
Exemple d'utilisation
>>> somme(10)\n55\n
Correction def somme(n):\n s = 0\n for k in range(1, n+1):\n s += k\n return s\n
Exercice 4
\u00c9nonc\u00e9Tester sa fonction \u00c9crire une fonction nb_voyelles
qui prend en param\u00e8tre la chaine de caract\u00e8res mot
renvoie le nombre de voyelles de mot
.
Exemple d'utilisation
>>> nb_voyelles(\"bonjour\")\n3\n
Vous pouvez utiliser la fonction de tests ci-dessous :
def test_nb_voyelles():\n assert nb_voyelles(\"bonjour\") == 3\n assert nb_voyelles(\"fdjgdhk\") == 0\n assert nb_voyelles(\"au\") == 2\n print(\"tests ok\")\n
Exercice 5
\u00c9nonc\u00e9Tester sa fonction D\u00e9finissez une fonction decale
qui d\u00e9cale de 3 rangs dans l'alphabet la lettre majuscule lettre
pass\u00e9e en param\u00e8tre (apr\u00e8s Z, on recommencera \u00e0 A..)
Aide
>>> ord('A')\n65\n>>> chr(65)\n'A'\n
Exemple d'utilisation
>>> decale('F')\n'I'\n
Vous pouvez utiliser la fonction de tests ci-dessous :
def test_decale():\n assert decale('A') == 'D'\n assert decale('Z') == 'C'\n print('tests ok !')\n
Exercice 6
\u00c9nonc\u00e9Tester sa fonction Rajoutez un param\u00e8tre n
\u00e0 la fonction pr\u00e9c\u00e9dente pour pouvoir d\u00e9caler la lettre de n
rangs.
Exemple d'utilisation
>>> decale('B', 5)\n'G'\n
Vous pouvez utiliser la fonction de tests ci-dessous :
def test_decale():\n assert decale('A', 3) == 'D'\n assert decale('A', 5) == 'F'\n assert decale('Z', 1) == 'A'\n print('tests ok !')\n
Exercice 7
Utilisez la fonction pr\u00e9c\u00e9dente pour cr\u00e9er la fonction decale_phrase
qui prend en param\u00e8tres une phrase p
et un nombre n
et qui d\u00e9cale toutes les lettres de p
de n
rangs. On laissera les espaces intacts.
Exemple d'utilisation
>>> decale_phrase(\"PAS MAL DU TOUT\", 4)\n'TEW QEP HY XSYX'\n
Exercice 8
D\u00e9codez la phrase RT BTHHPVT CT RDCIXTCI GXTC S XCITGTHHPCI
.
Exercice 9
La conjecture de Syracuse (ou de Collatz) postule ceci :
Prenons un nombre \\(n\\) : si \\(n\\) est pair, on le divise par 2, sinon on le multiplie par 3 puis on ajoute 1. On recommence cette op\u00e9ration tant que possible. Au bout d'un certain temps, on finira toujours par tomber sur le nombre 1.
Q1. \u00c9crire une fonction suivant
qui prend en param\u00e8tre un nombre n
renvoie le successeur den
, suivant les r\u00e8gles \u00e9nonc\u00e9es ci-dessus.
Q2. \u00c9crire une fonction syracuse
qui affiche tous les termes de la suite de Syracuse depuis un nombre n
pass\u00e9 en param\u00e8tre jusqu'\u00e0 (on l'esp\u00e8re !) 1.
Exercice 10
Q1. \u00c9crire une fonction temps_de_vol
qui prend un nombre n
en param\u00e8tre et qui renvoie le nombre d'\u00e9tapes pour arriver \u00e0 1, en partant de n
.
Q2. \u00c9crire une fonction temps_max(nmax)
qui affiche le plus grand temps de vol pour un nombre entre 1 et nmax
.
Q3. Modifier cette fonction pour afficher aussi le nombre de d\u00e9part donnant ce plus grand temps de vol.
"},{"location":"T2_Representation_des_donnees/sommaire/","title":"Th\u00e8me 2 : Repr\u00e9sentation des donn\u00e9es","text":" - Listes
- Tuples
- Dictionnaires
- Bases
- Bool\u00e9ens
- Codage des caract\u00e8res
- Codage des entiers
- Codage des non-entiers
- Cha\u00eenes de caract\u00e8res
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/","title":"2.1 Listes","text":"Les listes font partie de ce qu'on appelle les donn\u00e9es composites (nous verrons plus tard les tuples et les dictionnaires). Elles permettent de regrouper de mani\u00e8re structur\u00e9e un ensemble de valeurs (et non plus une valeur unique). On les appelle listes en Python, ou bien tableaux de mani\u00e8re plus g\u00e9n\u00e9rale.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#1-declaration-dune-liste","title":"1. D\u00e9claration d'une liste","text":"Exemple fondateur n\u00b01
Une variable de type liste sera d\u00e9limit\u00e9e par des crochets, et ses \u00e9l\u00e9ments s\u00e9par\u00e9s par des virgules :
>>> maliste = [\"riri\", \"fifi\", \"loulou\"]\n
On peut observer le type de la variable ainsi cr\u00e9\u00e9e :
>>> type(maliste)\n<class 'list'>\n
Remarques :
-
M\u00eame si cela n'a ici un grand int\u00e9r\u00eat, les \u00e9l\u00e9ments d'une liste peuvent donc \u00eatre de types diff\u00e9rents : ici, tous les \u00e9l\u00e9ments de ma liste sont des cha\u00eenes de caract\u00e8res (str
), mais la liste [\"riri\", 5, \"fifi\", \"loulou\"]
est aussi une liste valide.
-
Une liste vide se d\u00e9clarera avec []
.
>>> copies_corrigees = []\n
Nous verrons plus tard qu'il est fr\u00e9quent dans les exercices de partir d'une liste vide et d'ajouter progressivement des \u00e9l\u00e9ments.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#2-acces-aux-elements-dune-liste","title":"2. Acc\u00e8s aux \u00e9l\u00e9ments d'une liste","text":"Exemple fondateur n\u00b02
On acc\u00e8de \u00e0 un \u00e9l\u00e9ment d'une liste en mettant entre crochets l'indice de l'\u00e9l\u00e9ment (qui commence \u00e0 z\u00e9ro).
>>> famille = [\"Bart\", \"Lisa\", \"Maggie\"] # (1)\n>>> famille[0]\n'Bart'\n>>> famille[1]\n'Lisa'\n>>> famille[2]\n'Maggie'\n>>> famille[3]\nTraceback (most recent call last):\n File \"<pyshell>\", line 1, in <module>\nIndexError: list index out of range\n
- Nous prendrons souvent l'exemple de la famille Simpsons.
Remarques :
-
Un indice qui d\u00e9passe la valeur \u00a0longueur de la liste -1
provoquera donc une erreur list index out of range
. C'est une erreur tr\u00e8s fr\u00e9quente lorsqu'on manipule des listes.
-
Il est par contre possible d'utiliser des indices n\u00e9gatifs. On utilise par exemple tr\u00e8s souvent l'indice -1 pour acc\u00e9der au dernier \u00e9l\u00e9ment de la liste, sans avoir \u00e0 conna\u00eetre la longueur de celle-ci :
>>> famille[-1]\n'Maggie'\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#3-longueur-dune-liste","title":"3. Longueur d'une liste","text":"Exemple fondateur n\u00b03
La longueur d'une liste sera donn\u00e9e par la fonction len()
, qui renvoie donc un nombre entier positif ou nul.
>>> len(famille)\n3\n
Remarques :
- La liste vide a pour longueur 0 :
>>> len([])\n0\n
- Le dernier \u00e9l\u00e9ment d'une liste
maliste
(non vide) sera donc toujours l'\u00e9l\u00e9ment d'indice len(maliste)-1
. >>> famille[len(famille) - 1]\n'Maggie'\n
- Comme indiqu\u00e9 pr\u00e9c\u00e9demment, ce dernier \u00e9l\u00e9ment est aussi accessible par l'indice -1.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#4-parcours-des-elements-dune-liste","title":"4. Parcours des \u00e9l\u00e9ments d'une liste","text":"Il existe deux m\u00e9thodes pour parcourir s\u00e9quentiellement tous les \u00e9l\u00e9ments d'une liste. Ces deux m\u00e9thodes sont \u00e0 ma\u00eetriser imp\u00e9rativement.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#41-parcours-par-elements","title":"4.1 Parcours \u00abpar \u00e9l\u00e9ments\u00bb","text":"C'est la m\u00e9thode la plus naturelle, celle d\u00e9j\u00e0 vue lors de la pr\u00e9sentation de la boucle for
. Nous allons simplement it\u00e9rer sur les \u00e9l\u00e9ments de la liste.
Exemple fondateur n\u00b04
Le code :
famille = [\"Bart\", \"Lisa\", \"Maggie\"]\n\nfor membre in famille:\n print(membre)\n
renverra : Bart\nLisa\nMaggie\n
Remarque :
- Penser \u00e0 donner un nom signifiant \u00e0 la variable qui parcourt la liste. Il aurait par exemple \u00e9t\u00e9 tr\u00e8s maladroit d'\u00e9crire
for k in famille:\n print(k)\n
En effet le nom de variable k
est habituellement utilis\u00e9 pour les nombres (les indices, les compteurs...).
Exercice 1
\u00c9nonc\u00e9Correction Apr\u00e8s un r\u00e9f\u00e9rendum, la liste urne
contient uniquement des 'oui'
ou des 'non'
. D\u00e9terminer le vainqueur de ce r\u00e9f\u00e9rendum.
urne = ['oui', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'non', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'non', 'oui', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'oui']\n
urne = ['oui', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'non', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'non', 'oui', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'oui']\n\nnb_oui = 0\nnb_non = 0\nfor vote in urne:\n if vote == 'oui':\n nb_oui += 1\n else:\n nb_non += 1\nprint('pourcentage de oui', 100*nb_oui/len(urne), '%')\nprint('pourcentage de non', 100*nb_non/len(urne), '%')\nprint('-'*10)\nif nb_oui > nb_non:\n print('le oui est vainqueur')\nelif nb_oui < nb_non:\n print('le non est vainqueur')\nelse:\n print('le oui et le non sont \u00e0 \u00e9galit\u00e9')\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#42-parcours-par-indice","title":"4.2 Parcours \u00abpar indice\u00bb","text":"Chaque \u00e9l\u00e9ment \u00e9tant accessible par son indice (de 0
\u00e0 len(liste) - 1
), il suffit de faire parcourir \u00e0 une variable i
l'ensemble des entiers de 0
\u00e0 len(liste) - 1
, par l'instruction range(len(liste))
:
Exemple fondateur n\u00b05
Le code :
famille = [\"Bart\", \"Lisa\", \"Maggie\"]\n\nfor i in range(len(famille)):\n print(famille[i])\n
renverra : Bart\nLisa\nMaggie\n
Bonne habitude \u00e0 prendre : nommer sa variable d'indice i
, j
, k
ou indice
mais pas autre chose !
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#43-avantages-et-inconvenients-de-chaque-methode","title":"4.3 Avantages et inconv\u00e9nients de chaque m\u00e9thode","text":""},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#431-parcours-par-element","title":"4.3.1 Parcours par \u00e9l\u00e9ment","text":" for membre in famille:\n print(membre)\n
Les avantages
- la simplicit\u00e9 : un code plus facile \u00e0 \u00e9crire, avec un nom de variable explicite.
- la s\u00e9curit\u00e9 : pas de risque d'
index out of range
!
Les inconv\u00e9nients
- m\u00e9thode rudimentaire : lorsqu'on est \u00abpositionn\u00e9\u00bb sur un \u00e9l\u00e9ment, il n'est pas possible d'acc\u00e9der au pr\u00e9c\u00e9dent ou au suivant. (et c'est parfois utile).
- on ne peut pas modifier l'\u00e9l\u00e9ment sur lequel on est positionn\u00e9 :
>>> lst = [1, 2, 3]\n>>> for nb in lst:\n nb = nb * 2 # (1)\n\n>>> lst \n[1, 2, 3] # (2)\n
- On veut multiplier par 2 chaque \u00e9l\u00e9ment de la liste
- La liste
lst
n'a pas chang\u00e9...
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#432-parcours-par-indice","title":"4.3.2 Parcours par indice","text":" for i in range(len(famille)):\n print(famille[i])\n
Les avantages
- le contr\u00f4le : en parcourant par indice, on peut s'arr\u00eater o\u00f9 on veut, on peut acc\u00e9der au suivant/pr\u00e9c\u00e9dent...
- pour les tableaux \u00e0 deux dimensions, on retrouve la d\u00e9signation classique d'un \u00e9l\u00e9ment par num\u00e9ro de ligne / num\u00e9ro de colonne.
Les inconv\u00e9nients
- la complexit\u00e9 : il faut conna\u00eetre le nombre d'\u00e9l\u00e9ments de la liste (ou le r\u00e9cup\u00e9rer par la fonction
len()
) - le risque d'erreur : encore et toujours le
index out of range
...
Exercice 1
\u00c9nonc\u00e9Correction On donne la liste :
lst = [3, 1, 4, 1, 5, 9]\n
En utilisant un parcours par indice : - Afficher un \u00e0 un les \u00e9l\u00e9ments de cette liste.
- Afficher un \u00e0 un les \u00e9l\u00e9ments de cette liste dans l'ordre inverse (en commen\u00e7ant par 9)
for i in range(len(lst)):\n print(lst[i])\n
2.
lst = [3, 1, 4, 1, 5, 9]\n\nfor i in range(len(lst)-1, -1, -1):\n print(lst[i])\n
Exercice 2
\u00c9nonc\u00e9Correction 1.Correction 2. Trouvez le nombre qui est exactement \u00e0 la m\u00eame place dans la liste list1
et dans la liste list2
, sachant que les deux listes ont la m\u00eame taille.
- En utilisant une boucle
for
(une seule !). - En utilisant une boucle
while
. Quel est l'avantage de la boucle while
?
list1 = [8468, 4560, 3941, 3328, 7, 9910, 9208, 8400, 6502, 1076, 5921, 6720, 948, 9561, 7391, 7745, 9007, 9707, 4370, 9636, 5265, 2638, 8919, 7814, 5142, 1060, 6971, 4065, 4629, 4490, 2480, 9180, 5623, 6600, 1764, 9846, 7605, 8271, 4681, 2818, 832, 5280, 3170, 8965, 4332, 3198, 9454, 2025, 2373, 4067]\nlist2 = [9093, 2559, 9664, 8075, 4525, 5847, 67, 8932, 5049, 5241, 5886, 1393, 9413, 8872, 2560, 4636, 9004, 7586, 1461, 350, 2627, 2187, 7778, 8933, 351, 7097, 356, 4110, 1393, 4864, 1088, 3904, 5623, 8040, 7273, 1114, 4394, 4108, 7123, 8001, 5715, 7215, 7460, 5829, 9513, 1256, 4052, 1585, 1608, 3941]\n
list1 = [8468, 4560, 3941, 3328, 7, 9910, 9208, 8400, 6502, 1076, 5921, 6720, 948, 9561, 7391, 7745, 9007, 9707, 4370, 9636, 5265, 2638, 8919, 7814, 5142, 1060, 6971, 4065, 4629, 4490, 2480, 9180, 5623, 6600, 1764, 9846, 7605, 8271, 4681, 2818, 832, 5280, 3170, 8965, 4332, 3198, 9454, 2025, 2373, 4067]\nlist2 = [9093, 2559, 9664, 8075, 4525, 5847, 67, 8932, 5049, 5241, 5886, 1393, 9413, 8872, 2560, 4636, 9004, 7586, 1461, 350, 2627, 2187, 7778, 8933, 351, 7097, 356, 4110, 1393, 4864, 1088, 3904, 5623, 8040, 7273, 1114, 4394, 4108, 7123, 8001, 5715, 7215, 7460, 5829, 9513, 1256, 4052, 1585, 1608, 3941]\n\nfor i in range(len(list1)):\n if list1[i] == list2[i]:\n print(list1[i])\n
list1 = [8468, 4560, 3941, 3328, 7, 9910, 9208, 8400, 6502, 1076, 5921, 6720, 948, 9561, 7391, 7745, 9007, 9707, 4370, 9636, 5265, 2638, 8919, 7814, 5142, 1060, 6971, 4065, 4629, 4490, 2480, 9180, 5623, 6600, 1764, 9846, 7605, 8271, 4681, 2818, 832, 5280, 3170, 8965, 4332, 3198, 9454, 2025, 2373, 4067]\nlist2 = [9093, 2559, 9664, 8075, 4525, 5847, 67, 8932, 5049, 5241, 5886, 1393, 9413, 8872, 2560, 4636, 9004, 7586, 1461, 350, 2627, 2187, 7778, 8933, 351, 7097, 356, 4110, 1393, 4864, 1088, 3904, 5623, 8040, 7273, 1114, 4394, 4108, 7123, 8001, 5715, 7215, 7460, 5829, 9513, 1256, 4052, 1585, 1608, 3941]\n\ni = 0\nwhile list1[i] != list2[i]:\n i += 1\nprint(list1[i])\n
Avantage : on s'arr\u00eate d\u00e8s qu'on a trouv\u00e9 ! Inconv\u00e9nient : on part du principe que ce nombre existe vraiment. Si on ne le trouve pas, on aura une erreur...
Exercice 3
\u00c9nonc\u00e9Correction Dans la liste
lst = [2428970, 1518306, 4971405, 1690994, 7918102, 4030834, 8830131, 7514856, 7903128, 6307569, 6624056, 5260490, 6447835, 4598783, 9108626, 5045240, 4128269, 4460134, 2497873, 5076659, 8104003, 7604887, 7451976, 4136924, 5691945, 8726293, 7855592, 3562473, 8849129, 6488474, 5303587, 2606124, 5484044, 4559758, 7592232, 2211406, 9974334, 7988936, 7582946, 7668748, 1799997, 3837917, 3196209, 7064342, 2543765, 1182013, 7253381, 1153735, 1037391, 4375946, 4445821, 5965587, 6001887, 4162629, 5235783, 8716582, 4901175, 5445422, 1120005, 8332321, 7075046, 2194175, 5557300, 2887907, 5103214, 2520744, 5104399, 2065665, 3035703, 7890213, 1758301, 3407982, 1355453, 4896338, 7979392, 9671602, 9690721, 7423779, 7423780, 3080825, 6785783, 3836837, 7310931, 1857470, 3492507, 2823231, 1492310, 1911148, 9620515, 5564910, 7009452, 7464745, 9608747, 7267383, 6939140, 6556578, 3592267, 8135497, 4881660, 5346884, 6859150]\n
se cachent deux nombres cons\u00e9cutifs (comme les nombres 4 et 5 dans la liste [6, 2, 4, 5, 3]
). Pouvez-vous les trouver ? lst = [2428970, 1518306, 4971405, 1690994, 7918102, 4030834, 8830131, 7514856, 7903128, 6307569, 6624056, 5260490, 6447835, 4598783, 9108626, 5045240, 4128269, 4460134, 2497873, 5076659, 8104003, 7604887, 7451976, 4136924, 5691945, 8726293, 7855592, 3562473, 8849129, 6488474, 5303587, 2606124, 5484044, 4559758, 7592232, 2211406, 9974334, 7988936, 7582946, 7668748, 1799997, 3837917, 3196209, 7064342, 2543765, 1182013, 7253381, 1153735, 1037391, 4375946, 4445821, 5965587, 6001887, 4162629, 5235783, 8716582, 4901175, 5445422, 1120005, 8332321, 7075046, 2194175, 5557300, 2887907, 5103214, 2520744, 5104399, 2065665, 3035703, 7890213, 1758301, 3407982, 1355453, 4896338, 7979392, 9671602, 9690721, 7423779, 7423780, 3080825, 6785783, 3836837, 7310931, 1857470, 3492507, 2823231, 1492310, 1911148, 9620515, 5564910, 7009452, 7464745, 9608747, 7267383, 6939140, 6556578, 3592267, 8135497, 4881660, 5346884, 6859150]\n\nfor i in range(len(lst)-1): # Il faut s'arr\u00eater \u00e0 l'avant-dernier \u00e9l\u00e9ment de la liste\n if lst[i] + 1 == lst[i+1]:\n print(lst[i], lst[i+1])\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#5-modification-dune-liste","title":"5. Modification d'une liste","text":"En Python, les objets de type List
sont modifiables (on emploie le mot mutables). Et c'est souvent une bonne chose, car des listes peuvent \u00e9voluer apr\u00e8s leur cr\u00e9ation. Lorsqu'on souhaitera figer le contenu d'une liste (pour des raisons de s\u00e9curit\u00e9 du code essentiellement), on utilisera alors le type Tuple
, qui sera vu ult\u00e9rieurement.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#51-modification-dun-element-existant","title":"5.1 Modification d'un \u00e9l\u00e9ment existant","text":"Il suffit d'\u00e9craser la valeur actuelle avec une nouvelle valeur
Exemple fondateur n\u00b06
>>> famille = [\"Bart\", \"Lisa\", \"Maggie\"]\n>>> famille[0] = \"Bartholomew\" # oui, c'est son vrai nom\n>>> famille\n['Bartholomew', 'Lisa', 'Maggie'] \n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#52-ajout-dun-element-a-la-fin-dune-liste-la-methode-append","title":"5.2 Ajout d'un \u00e9lement \u00e0 la fin d'une liste : la m\u00e9thode append()","text":"Exemple fondateur n\u00b07
>>> famille = [\"Bart\", \"Lisa\", \"Maggie\"]\n>>> famille.append(\"Milhouse\")\n>>> famille\n['Bart', 'Lisa', 'Maggie', 'Milhouse'] \n
Remarques :
- La m\u00e9thode
append()
rajoute donc un \u00e9l\u00e9ment \u00e0 la fin de la liste. - Dans beaucoup d'exercices, on part d'une liste vide
[]
que l'on remplit peu \u00e0 peu avec des append()
. - (HP) Il est possible d'ins\u00e9rer un \u00e9l\u00e9ment \u00e0 la position
i
avec la m\u00e9thode insert
: >>> famille = [\"Bart\", \"Lisa\", \"Maggie\"]\n>>> famille.insert(1, \"Nelson\") # on ins\u00e8re \u00e0 la position 1\n>>> famille\n['Bart', 'Nelson', 'Lisa', 'Maggie']\n
Exercice 4
\u00c9nonc\u00e9Correction Construire une liste contenant tous les nombres inf\u00e9rieurs \u00e0 100 qui sont divisibles par 7.
lst = []\nfor n in range(1, 101):\n if n % 7 == 0:\n lst.append(n)\n
Exercice 5
\u00c9nonc\u00e9Correction On consid\u00e8re la liste temp = [4, -5, 8, 10, -1, -2, 7, 13]
. Construire la liste temp_pos
qui ne contient que les \u00e9l\u00e9ments positifs de temp
.
temp = [4, -5, 8, 10, -1, -2, 7, 13]\n\ntemp_pos = []\nfor t in temp:\n if t > 0:\n temp_pos.append(t)\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#53-suppression-dun-element-dune-liste","title":"5.3 Suppression d'un \u00e9l\u00e9ment d'une liste ...","text":""},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#531-par-la-methode-remove","title":"5.3.1 ... par la m\u00e9thode remove()","text":"Exemple fondateur n\u00b07
>>> famille = ['Bart', 'Nelson', 'Lisa', 'Maggie']\n>>> famille.remove(\"Nelson\")\n>>> famille\n['Bart', 'Lisa', 'Maggie']\n
Remarques :
- Attention,
remove
n'enl\u00e8ve que la premi\u00e8re occurrence de l'\u00e9l\u00e9ment d\u00e9sign\u00e9. S'il y en a d'autres apr\u00e8s, elles resteront dans la liste : >>> lst = [3, 1, 4, 5, 1, 9, 4]\n>>> lst.remove(4)\n>>> lst\n[3, 1, 5, 1, 9, 4]\n
- Si l'\u00e9l\u00e9ment \u00e0 supprimer n'est pas trouv\u00e9, un message d'erreur est renvoy\u00e9 :
>>> lst = [3, 1, 4, 5, 1, 9]\n>>> lst.remove(2)\nTraceback (most recent call last):\n File \"<pyshell>\", line 1, in <module>\nValueError: list.remove(x): x not in list\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#532-par-linstruction-del","title":"5.3.2 ... par l'instruction del
","text":"L'instruction del
(qui n'est pas une fonction) permet de supprimer un \u00e9l\u00e9ment en donnant son indice.
>>> maliste = [8, 4, 2, 5, 7]\n>>> del maliste[3]\n>>> maliste\n[8, 4, 2, 7]\n
Exercice 6
\u00c9nonc\u00e9 Exercice de la BNS.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#6-construction-dune-liste-delements-identiques","title":"6. Construction d'une liste d'\u00e9l\u00e9ments identiques","text":"Il est souvent pratique d'initialiser une liste de taille donn\u00e9e, souvent en la remplissant de 0.
Imaginons par exemple que nous souhaitions une liste de taille 26 remplie de 0. Il est possible de faire comme ceci :
lst = []\nfor _ in range(26):\n lst.append(0)\n
mais on pr\u00e9f\u00e8rera ce code :
Exemple fondateur n\u00b08
>>> lst = [0]*26\n
qui produira la liste [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Exercice 7
\u00c9nonc\u00e9Correction Que fait le code ci-dessous ?
texte = \"cet texte est prodigieusement ennuyeux\"\n\ndef rang(lettre):\n return ord(lettre) - 97\n\ncompt = [0]*26\nfor lettre in texte :\n if lettre != \" \" :\n compt[rang(lettre)] += 1\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#7-construction-dune-liste-en-comprehension","title":"7. Construction d'une liste en compr\u00e9hension","text":"C'est une grande caract\u00e9ristique du langage Python (m\u00eame si ce n'est pas une exclusivit\u00e9) : la m\u00e9thode de liste en compr\u00e9hension propose une mani\u00e8re \u00e9l\u00e9gante, rapide et naturelle pour cr\u00e9er des listes.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#71-en-comprehension-pourquoi","title":"7.1 \u00aben compr\u00e9hension\u00bb, pourquoi ?","text":"Cette expression vient des math\u00e9matiques. On dit qu'on d\u00e9finit un sous-ensemble par compr\u00e9hension lorsqu'on part d'un ensemble plus grand dont on ne garde que les \u00e9l\u00e9ments v\u00e9rifiant une certaine propri\u00e9t\u00e9.
On pourrait par exemple d\u00e9finir les \u00e9l\u00e8ves de Premi\u00e8re NSI de cette mani\u00e8re :
\u00ab\u00e9l\u00e8ves du lyc\u00e9e inscrits en classe de Premi\u00e8re ayant choisi la sp\u00e9cialit\u00e9 NSI\u00bb
On part d'un ensemble large (les \u00e9l\u00e8ves du lyc\u00e9e) qu'on va ensuite r\u00e9duire par des caract\u00e9risations sp\u00e9cifiques : \u00eatre un \u00e9l\u00e8ve de Premi\u00e8re, puis avoir choisi la sp\u00e9cialit\u00e9 NSI.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#72-premier-exemple","title":"7.2 Premier exemple","text":"Exemple fondateur n\u00b09
Imaginons que nous poss\u00e9dons une liste data
de temp\u00e9ratures, dont nous ne voulons garder que celles strictement sup\u00e9rieures \u00e0 20.
>>> data = [17, 22, 15, 28, 16, 13, 21, 23]\n>>> good = [t for t in data if t > 20]\n>>> good\n[22, 28, 21, 23]\n
Explications :
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#721-le-filtre-eventuel","title":"7.2.1 le filtre \u00e9ventuel","text":"C'est lui qui donne tout son sens \u00e0 cette m\u00e9thode : il permet de ne garder que certaines valeurs. Il est pourtant \u00e9ventuel : que se passe-t-il s'il n'y a pas de filtre ?
>>> data = [17, 22, 15, 28, 16, 13, 21, 23]\n>>> good = [t for t in data]\n>>> good\n[17, 22, 15, 28, 16, 13, 21, 23]\n
On se retrouve \u00e9videmment avec une nouvelle liste qui contient exactement les \u00e9l\u00e9ments de la liste de d\u00e9part, ce qui n'est pas tr\u00e8s int\u00e9ressant. Pourtant les listes en compr\u00e9hension sans filtre sont tr\u00e8s fr\u00e9quentes, nous le verrons plus loin. Exercice 8
\u00c9nonc\u00e9Correction On consid\u00e8re la variable phrase = 'Bonjour les vacances sont finies'
et la variable voyelles = 'aeiouy'
.
Construire en compr\u00e9hension la liste liste_voyelles
qui contient toutes les voyelles pr\u00e9sentes dans la variable phrase
.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#722-lensemble-de-depart","title":"7.2.2 l'ensemble de d\u00e9part","text":"C'est \u00e0 partir de lui que va se construire notre liste. Pour l'instant, cet ensemble de d\u00e9part a toujours \u00e9t\u00e9 de type list
.
Cet ensemble peut \u00eatre aussi donn\u00e9 \u00e0 partir de l'instruction range()
. Souvenons-nous de l'exercice 4 : \u00abConstruire une liste contenant tous les nombres inf\u00e9rieurs \u00e0 100 qui sont divisibles par 7.\u00bb.
Une solution possible \u00e9tait :
lst = []\nfor n in range(1, 101):\n if n % 7 == 0:\n lst.append(n)\n
Ce code peut maintenant s'\u00e9crire tr\u00e8s simplement en une seule instruction :
Exemple fondateur n\u00b010
>>> lst = [n for n in range(1,101) if n % 7 == 0]\n>>> lst\n[7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98]\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#723-la-valeur-a-garder","title":"7.2.3 la valeur \u00e0 garder","text":"Pour l'instant, nous avons proc\u00e9d\u00e9 \u00e0 des filtres sur des ensembles existants, sans modifier la valeur filtr\u00e9e (la valeur \u00e0 garder). Les listes en compr\u00e9hension deviennent encore plus int\u00e9ressantes lorsqu'on comprend qu'il est possible de modifier la valeur filtr\u00e9e :
Exemple fondateur n\u00b011
>>> lst_carres = [t**2 for t in range(1,10)]\n>>> lst_carres\n[1, 4, 9, 16, 25, 36, 49, 64, 81]\n
Exercice 9
\u00c9nonc\u00e9Correction - On consid\u00e8re la fonction math\u00e9matique \\(f : x \\mapsto 2x+3\\). Coder la fonction
f
. - Cr\u00e9er (en compr\u00e9hension) une liste contenant l'image des entiers de 1 \u00e0 10 par la fonction \\(f\\).
def f(x):\n return 2*x + 3\n\nlst = [f(x) for x in range(1, 11)]\n
Exercice 10
\u00c9nonc\u00e9Correction On consid\u00e8re la liste lst = [51, 52, 66, 91, 92, 82, 65, 53, 86, 42, 79, 95]
. Seuls les nombres entre 60 et 90 ont une signification : ce sont des codes ASCII (r\u00e9cup\u00e9rables par la fonction chr
). Cr\u00e9er (en compr\u00e9hension) une liste sol
qui contient les lettres correspondants aux nombres ayant une signification.
>>> lst = [51, 52, 66, 91, 92, 82, 65, 53, 86, 42, 79, 95]\n>>> decode = [chr(k) for k in lst if k > 60 and k < 90]\n>>> decode\n['B', 'R', 'A', 'V', 'O']\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#8-un-phenomene-inquietant-la-copie-de-liste","title":"8. Un ph\u00e9nom\u00e8ne inqui\u00e9tant : la copie de liste","text":"une copie un peu trop parfaite
Observez le code ci-dessous, r\u00e9alis\u00e9 sans trucage.
>>> listA = [1, 2, 3]\n>>> listB = listA\n>>> listA.append(7)\n>>> listB\n[1, 2, 3, 7]\n>>> listB.append(8)\n>>> listA\n[1, 2, 3, 7, 8]\n
Tout se passe comme si les listes listA
etlistB
\u00e9taient devenus des clones \u00absynchronis\u00e9s\u00bb depuis l'affectation listB = listA
.
Analyse gr\u00e2ce \u00e0 PythonTutor
L'illustration de PythonTutor nous donne la cl\u00e9 de l'\u00e9nigme :
listA
etlistB
sont en fait un seul et m\u00eame objet.
Comment en avoir le c\u0153ur net ? En observant leur adresse-m\u00e9moire, disponible gr\u00e2ce \u00e0 la fonction id
:
>>> id(listA)\n140485841327616\n>>> id(listB)\n140485841327616\n
Ceci met en \u00e9vidence que la m\u00e9taphore du tiroir dont on se sert pour expliquer ce qu'est une variable est malheureusement inexacte. Une variable est une r\u00e9f\u00e9rence vers une adresse-m\u00e9moire. Si deux variables font r\u00e9f\u00e9rence \u00e0 la m\u00eame adresse-m\u00e9moire, alors elles sont totalement identiques: toute modification de l'une entra\u00eene une modification de l'autre.
Pour en savoir plus sur les variables, vous pouvez revenir sur la partie optionnelle du cours sur les variables.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#mais-alors-comment-copier-le-contenu-dune-liste-vers-une-autre-sans-creer-un-clone","title":"Mais alors, comment copier le contenu d'une liste vers une autre sans cr\u00e9er un clone ?","text":"Exemple fondateur n\u00b012
>>> listA = [3, 4, 5]\n>>> listB = list(listA)\n
D'autres possibilit\u00e9s existent, comme listA.copy()
, ou encore listA[::]
... Exercice 11
\u00c9nonc\u00e9Correction Effectuer les tests n\u00e9cessaires pour prouver que l'exemple pr\u00e9c\u00e9dent a bien produit deux objets diff\u00e9rents.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#9-tableaux-a-plusieurs-dimensions-listes-de-listes","title":"9. Tableaux \u00e0 plusieurs dimensions : listes de listes","text":"Nous avons vu qu'une liste pouvait contenir des \u00e9l\u00e9ments de tous types : des entiers, des chaines des caract\u00e8res... et pourquoi pas une liste qui contient des listes ?
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#91-syntaxe","title":"9.1 Syntaxe","text":"Exemple fondateur n\u00b012
La liste tab
ci-dessous est compos\u00e9e de 3 listes qui elles-m\u00eames contiennent trois nombres :
tab = [[3, 5, 2],\n [7, 1, 4], \n [8, 6, 9]]\n
tab[0][0] = 3
tab[0][1] = 5
tab[2][1] = 6
tab[1] = [7, 1, 4]
La liste a
est compos\u00e9e de 3 \u00e9l\u00e9ments qui sont eux-m\u00eame des listes de 3 \u00e9l\u00e9ments.
Exercice 12
\u00c9nonc\u00e9Correction On consid\u00e8re le jeu du Morpion (ou Tic-Tac-Toe) dont la surface de jeu vierge est represent\u00e9e par le tableau : tab = [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]
Les premiers coups jou\u00e9s sont ceux-ci :
tab[1][1] = 'X'
tab[2][1] = 'O'
tab[2][2] = 'X'
tab[0][0] = 'O'
Quel coup doit maintenant jouer le joueur 'X'
pour s'assurer la victoire ?
tab[0][2] = 'X'\n# ou\ntab[1][2] = 'X'\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#92-parcours-dune-liste-de-listes","title":"9.2 Parcours d'une liste de listes","text":"Exemple fondateur n\u00b013
-
Parcours par \u00e9l\u00e9ments :
for ligne in tab:\n for elt in ligne:\n print(elt)\n
-
Parcours par indice :
for i in range(3):\n for j in range(3):\n print(tab[i][j])\n
Exercice 13
\u00c9nonc\u00e9Correction On consid\u00e8re la liste m
('m' comme matrice) suivante :
m = [[1, 9, 4], [4, 1, 8], [7, 10, 1]]
Quelle est la somme de tous les nombres de la matrice m
?
m = [[1, 9, 4], [4, 1, 8], [7, 10, 1]]\n\nsomme = 0\nfor ligne in m:\n for elt in ligne:\n somme += elt\n\nprint(somme)\n
ou bien
m = [[1, 9, 4], [4, 1, 8], [7, 10, 1]]\n\nsomme = 0\nfor i in range(3):\n for j in range(3):\n somme += m[i][j]\n\nprint(somme)\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/exercices/","title":"Exercices","text":"Exercice 1
\u00c9nonc\u00e9Correction R\u00e9solvez le Pyd\u00e9fi propos\u00e9 \u00e0 cette adresse
Vous pouvez vous cr\u00e9er un compte pour valider vos r\u00e9sultats, ce site (g\u00e9r\u00e9 par l'Acad\u00e9mie de Poitiers) est remarquable.
Exercice 2
\u00c9nonc\u00e9 On donne la liste jours
suivante :
jours = [\"lundi\", \"mardi\", \"mercredi\", \"jeudi\", \"vendredi\", \"samedi\", \"dimanche\"]\n
On rappelle que la fonction len
permet d'obtenir le nombre de caract\u00e8res d'une chaine de caract\u00e8res :
>>> len(\"test\")\n4\n
Q1. Cr\u00e9er en compr\u00e9hension une liste lst1
contenant uniquement les jours comportant 5 lettres.
Correction lst1 = [day for day in jours if len(day) == 5]\n
Q2. Cr\u00e9er en compr\u00e9hension une liste lst2
contenant uniquement les jours comportant la lettre a
dans leur nom.
Correction lst2 = [day for day in jours if 'a' in day]\n
Q3a. Cr\u00e9er une fonction compte_e
qui prend en param\u00e8tre une chaine de caract\u00e8res et qui renvoie le nombre de e
que contient cette chaine de caract\u00e8res.
Correction def compte_e(mot):\n compteur = 0\n for lettre in mot:\n if lettre == 'e':\n compteur += 1\n return compteur\n
Q3b. Cr\u00e9er en compr\u00e9hension une liste lst4
contenant uniquement les jours comportant deux fois la lettre e
dans leur nom.
Correction lst4 = [day for day in jours if compte_e(day) == 2]\n
Exercice 3
\u00c9nonc\u00e9Correction On donne le tableau m
suivant :
m = [[17, 71, 75, 89, 45, 10, 54, 26, 59, 47, 57, 64, 44], \\\n [67, 25, 47, 49, 28, 40, 10, 17, 77, 35, 87, 15, 68], \\\n [66, 89, 28, 43, 16, 14, 12, 21, 68, 22, 14, 18, 59], \\\n [60, 35, 30, 23, 22, 37, 49, 89, 82, 80, 85, 28, 17], \\\n [61, 42, 39, 46, 29, 38, 85, 72, 44, 60, 47, 35, 52], \\\n [44, 28, 24, 40, 71, 71, 46, 25, 78, 54, 66, 84, 52], \\\n [29, 71, 7, 38, 71, 60, 71, 60, 16, 82, 35, 39, 23], \\\n [18, 61, 38, 7, 8, 32, 67, 43, 23, 28, 29, 16, 30], \\\n [45, 30, 74, 9, 84, 78, 11, 80, 42, 64, 9, 39, 26], \\\n [78, 57, 54, 66, 57, 63, 10, 42, 61, 19, 26, 25, 53], \\\n [38, 87, 10, 64, 75, 26, 14, 68, 19, 33, 75, 50, 18], \\\n [52, 81, 24, 67, 37, 78, 17, 19, 61, 82, 57, 24, 54]]\n
Afficher successivement chaque ligne du tableau en respectant les r\u00e8gles suivantes : - si le nombre est divisible par 7, afficher
*
, sinon afficher une espace
- sur une m\u00eame ligne, on affichera tous les symboles c\u00f4te \u00e0 c\u00f4te, en rajoutant le param\u00e8tre
end = ''
\u00e0 la fonction print
. (exemple : print('*', end = '')
) - on ira \u00e0 la ligne \u00e0 la fin de chaque ligne, par l'instruction
print()
m = [[17, 71, 75, 89, 45, 10, 54, 26, 59, 47, 57, 64, 44], \\\n [67, 25, 47, 49, 28, 40, 10, 17, 77, 35, 87, 15, 68], \\\n [66, 89, 28, 43, 16, 14, 12, 21, 68, 22, 14, 18, 59], \\\n [60, 35, 30, 23, 22, 37, 49, 89, 82, 80, 85, 28, 17], \\\n [61, 42, 39, 46, 29, 38, 85, 72, 44, 60, 47, 35, 52], \\\n [44, 28, 24, 40, 71, 71, 46, 25, 78, 54, 66, 84, 52], \\\n [29, 71, 7, 38, 71, 60, 71, 60, 16, 82, 35, 39, 23], \\\n [18, 61, 38, 7, 8, 32, 67, 43, 23, 28, 29, 16, 30], \\\n [45, 30, 74, 9, 84, 78, 11, 80, 42, 64, 9, 39, 26], \\\n [78, 57, 54, 66, 57, 63, 10, 42, 61, 19, 26, 25, 53], \\\n [38, 87, 10, 64, 75, 26, 14, 68, 19, 33, 75, 50, 18], \\\n [52, 81, 24, 67, 37, 78, 17, 19, 61, 82, 57, 24, 54]]\n\nfor ligne in m:\n for elt in ligne:\n if elt % 7 == 0:\n print('*', end = '')\n else:\n print(' ', end = '')\n print('')\n
Exercice 4
\u00c9nonc\u00e9Correction Pyd\u00e9fi Insaisissable matrice (version originale \u00e0 cette adresse)
On consid\u00e8re la matrice suivante :
-------------------------------\n| 17 | 3 | 4 | 14 | 5 | 17 |\n-------------------------------\n| 8 | 16 | 3 | 17 | 14 | 12 |\n-------------------------------\n| 13 | 5 | 15 | 4 | 16 | 3 |\n-------------------------------\n| 14 | 7 | 3 | 16 | 3 | 2 |\n-------------------------------\n| 6 | 1 | 16 | 10 | 5 | 13 |\n-------------------------------\n| 11 | 1 | 9 | 11 | 18 | 8 |\n-------------------------------\n
M = [[17, 3, 4, 14, 5, 17], [8, 16, 3, 17, 14, 12], [13, 5, 15, 4, 16, 3], [14, 7, 3, 16, 3, 2], [6, 1, 16, 10, 5, 13], [11, 1, 9, 11, 18, 8]]\n
Cette matrice va \u00e9voluer au cours du temps, et le contenu k
d'une case est transform\u00e9, \u00e0 chaque \u00e9tape en (9*k + 3) % 19
.
Rappelons que a % b
donne le reste de la division enti\u00e8re de a
par b
.
\u00c0 chaque \u00e9tape de calcul, tous les nombres de la matrice sont simultan\u00e9ment modifi\u00e9s. L'entr\u00e9e du probl\u00e8me est le nombre d'\u00e9tapes \u00e0 appliquer (ici : 39). Vous devez r\u00e9pondre en donnant la somme des valeurs contenues dans la matrice apr\u00e8s application de toutes les \u00e9tapes.
M = [[17, 3, 4, 14, 5, 17], [8, 16, 3, 17, 14, 12], [13, 5, 15, 4, 16, 3], [14, 7, 3, 16, 3, 2], [6, 1, 16, 10, 5, 13], [11, 1, 9, 11, 18, 8]]\n\ndef f(k):\n return (9*k + 3) % 19\n\ndef tour():\n for i in range(6):\n for j in range(6):\n M[i][j] = f(M[i][j])\n\nfor _ in range(39):\n tour()\n\nsomme = 0\nfor i in range(6):\n for j in range(6):\n somme += M[i][j]\n\nprint(somme)\n
Exercice 5
\u00c9nonc\u00e9Correction D'apr\u00e8s Advent Of Code 2021, day02
Un sous-marin peut se d\u00e9placer horizontalement (toujours vers la droite) gr\u00e2ce \u00e0 l'instruction forward
suivie d'un nombre.
Il peut aussi monter ou descendre, gr\u00e2ce aux instructions up
ou down
, elles aussi suivies d'un nombre.
Un grand nombre d'instructions successives sont donn\u00e9es. Le but de l'exercice est de trouver le produit final de l'abscisse du sous-marin et de sa profondeur.
Exemple :
forward 5\ndown 5\nforward 8\nup 3\ndown 8\nforward 2\n
Apr\u00e8s ces d\u00e9placements, le sous-marin se trouve \u00e0 l'abscisse 15 et \u00e0 la profondeur 10. La r\u00e9ponse \u00e0 l'\u00e9nigme serait donc 150.
-
\u00e9nonc\u00e9 orginal
-
T\u00e9l\u00e9chargez le fichier input.txt. Votre fichier .py
de travail doit se situer dans le m\u00eame r\u00e9pertoire que le fichier input.txt
.
Parsing des donn\u00e9es
Parser des donn\u00e9es consiste \u00e0 les r\u00e9cup\u00e9rer et les rendre exploitables. C'est quelque chose de souvent p\u00e9nible (dans les \u00e9nigmes de code ET dans la vraie vie). Pourtant de la qualit\u00e9 du parsing (et surtout de la structure de stockage choisie) va d\u00e9pendre la difficult\u00e9 (ou non) de l'exploitation des donn\u00e9es.
Proposition de parsing :
data_raw = open('input.txt').read().splitlines()\nlst_raw = [d.split(' ') for d in data_raw]\nlst = [[l[0], int(l[1])] for l in lst_raw]\n
Ex\u00e9cutez ce code et observez ce que contient la liste lst
.
R\u00e9solution de l'\u00e9nigme
\u00c0 la fin de toutes ses man\u0153uvres, quel est le produit de l'abscisse du sous-marin et de sa profondeur ?
data_raw = open('input.txt').read().splitlines()\nlst_raw = [d.split(' ') for d in data_raw]\nlst = [[l[0], int(l[1])] for l in lst_raw]\n\nx = 0\ny = 0\n\nfor couple in lst:\n direction = couple[0]\n valeur = couple[1]\n if direction == 'forward':\n x += valeur\n if direction == 'down':\n y += valeur\n if direction == 'up':\n y -= valeur\n\nprint(x*y)\n
La r\u00e9ponse est donc 1746616.
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/","title":"2.2 Tuples","text":""},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#1definition-des-tuples","title":"1.D\u00e9finition des tuples","text":"Les tuples (appel\u00e9s p-uplets dans le programme officiel de NSI) sont une collection d'objets ordonn\u00e9e mais NON MODIFIABLE. Pour rappel :
- chaine de caract\u00e8res : ordonn\u00e9e et non modifiable
- liste : ordonn\u00e9e et modifiable
- tuple : ordonn\u00e9e et non modifiable
Quel peut \u00eatre l'int\u00e9r\u00eat d'un tuple par rapport \u00e0 une liste ?
- Justement son caract\u00e8re prot\u00e9g\u00e9 : jamais une portion de code ne pourra venir modifier les informations contenues dans le tuple.
- L'utilisation des tuples est \u00e9conome en ressources-syst\u00e8me par rapport \u00e0 une liste (en particulier, parce que sa taille est fixe).
>>> monPremierTuple = (3, 5, 6)\n
Un tuple se diff\u00e9rencie d'une liste par l'utilisation des parenth\u00e8ses au lieu des crochets.
>>> type(monPremierTuple)\ntuple\n
\u00c0 noter qu'un tuple peut \u00eatre d\u00e9clar\u00e9 sans parenth\u00e8ses. C'est toutefois \u00e0 \u00e9viter.
>>> taille = 600, 800\n>>> type(taille)\ntuple\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#2-acces-aux-elements-dun-tuple","title":"2. Acc\u00e8s aux \u00e9l\u00e9ments d'un tuple","text":"Comme pour une liste ou une cha\u00eene de caract\u00e8re, l'acc\u00e8s se fait par un indice entre crochets.
>>> a = (12, 25, 6)\n>>> a[0]\n12\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#3-tentative-de-modification-dun-tuple","title":"3. Tentative de modification d'un tuple","text":">>> a[0] = 4\n ---------------------------------------------------------------------------\n TypeError Traceback (most recent call last)\n\n <ipython-input-7-5fe525706b2b> in <module>()\n ----> 1 a[0] = 4\n\n\n TypeError: 'tuple' object does not support item assignment\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#4-parcours-dun-tuple","title":"4. Parcours d'un tuple","text":"On retrouve bien \u00e9videmment les deux m\u00e9thodes utilisables pour les listes :
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#41-parcours-par-indice","title":"4.1 Parcours par indice","text":">>> for k in range(len(a)):\n print(a[k])\n12\n25\n6\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#41-parcours-par-element","title":"4.1 Parcours par \u00e9l\u00e9ment","text":">>> for k in a :\n print(k)\n12\n25\n6\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#5-construction-dune-fonction-renvoyant-un-tuple","title":"5. Construction d'une fonction renvoyant un tuple","text":"def division(a, b):\n # fonction renvoyant le tuple (quotient, reste) de la division euclidienne de a par b.\n q = a // b\n r = a % b\n return (q, r)\n
>>> division(49,12)\n(4,1)\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#6-exercice","title":"6. Exercice","text":"Exercice
\u00c9nonc\u00e9Correction On consid\u00e8re deux points A et B d'un rep\u00e8re quelconque. Leurs coordonn\u00e9es sont des tuples \u00e0 deux \u00e9l\u00e9ments. \u00c9crire une fonction qui prend en argument les coordonn\u00e9es de deux points et qui renvoie le milieu de ces deux points.
La fonction doit fonctionner de cette mani\u00e8re :
>>> C = (45, 12)\n>>> D = (49, 32)\n>>> milieu(C,D)\n(47, 22)\n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/","title":"2.3 Dictionnaires","text":""},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#1-les-dictionnaires-premiers-exemples","title":"1. Les dictionnaires : premiers exemples","text":"Une liste est un ensemble d'\u00e9l\u00e9ments accessibles par leur indice. Cet indice est en quelque sorte la \u00abplace\u00bb de l'\u00e9l\u00e9ment dans la liste. On peut dire que cet indice est la cl\u00e9 qui permet d'acc\u00e9der \u00e0 l'\u00e9l\u00e9ment.
Dans un dictionnaire, chaque \u00e9l\u00e9ment est accessible par une cl\u00e9 qui n'est plus forc\u00e9ment un nombre : une chaine de caract\u00e8re, un nombre, ou autre chose, peut \u00eatre une cl\u00e9.
Imaginons que je fasse l'inventaire de mon dressing :
habits quantit\u00e9 pantalons 3 pulls 4 tee-shirts 8 Exemple fondateur n\u00b01
- La cr\u00e9ation du dictionnaire repr\u00e9sentant mon dressing se fera par :
>>> dressing = {\"pantalons\":3, \"pulls\":4, \"tee-shirts\":8}\n
- L'acc\u00e8s \u00e0 une valeur se fera par :
>>> dressing[\"pulls\"]\n 4\n
-
On dit que \"pulls\"
est la cl\u00e9 et que 4 est la valeur associ\u00e9e \u00e0 la cl\u00e9.
-
Un dictionnaire est un ensemble cl\u00e9s / valeurs.
Attention : une cl\u00e9 peut aussi \u00eatre un nombre :
>>> myst = {9:4, 1:2, 6:3, 7:4} \n>>> myst[1]\n2\n>>> myst[7]\n4 \n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#2-definitions-et-proprietes-dun-dictionnaire","title":"2. D\u00e9finitions et propri\u00e9t\u00e9s d'un dictionnaire","text":""},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#21-definitions","title":"2.1 D\u00e9finitions","text":"D\u00e9finition
Un dictionnaire est une donn\u00e9e composite qui n'est pas ordonn\u00e9e (\u00e0 la diff\u00e9rence des listes !) Il fonctionne par un syst\u00e8me de cl\u00e9:valeur
. Les cl\u00e9s, comme les valeurs, peuvent \u00eatre de types diff\u00e9rents. Un dictionnaire est d\u00e9limit\u00e9 par des accolades.
Rappel :
- crochets
[ ]
-> listes - parenth\u00e8ses
( )
-> tuples - accolades
{ }
-> dictionnaires
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#22-methodes-keys-et-values","title":"2.2 M\u00e9thodes .keys()
et .values()
","text":"Exemples fondateurs n\u00b02
- Pour lister les cl\u00e9s d'un dictionnaire :
>>> dressing.keys()\ndict_keys(['pantalons', 'pulls', 'tee-shirts'])\n
- Pour lister les valeurs d'un dictionnaire :
>>> dressing.values()\ndict_values([3, 4, 8])\n
Ces m\u00e9thodes sont importantes (elles figurent explicitement au programme de NSI) mais sont en pratique peu utilis\u00e9es. On leur pr\u00e9f\u00e8rera tr\u00e8s largement la m\u00e9thode de parcours suivante :
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#23-parcours-dun-dictionnaire","title":"2.3 Parcours d'un dictionnaire","text":"Exemple fondateur n\u00b03
>>> for habit in dressing:\n print(dressing[habit])\n3\n4\n8\n
Observation gr\u00e2ce \u00e0 PythonTutor
Exercice 1
Faire afficher la sortie suivante :
pantalons -> 3\npulls -> 4\ntee-shirts -> 8\n
Correction dressing = {'pantalons':3, 'pulls':4, 'tee-shirts':8}\n\nfor habit in dressing:\n print(habit, '->', dressing[habit]) \n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#24-creation-dun-dictionnaire-vide","title":"2.4 Cr\u00e9ation d'un dictionnaire vide","text":"Exemple fondateur n\u00b04
Deux m\u00e9thodes existent pour cr\u00e9er un dictionnaire : dict()
et {}
>>> mondico = dict()\n>>> mondico\n{}\n>>> mondico['john'] = 12\n>>> mondico\n{'john': 12}\n
>>> contacts = {}\n>>> contacts['bob'] = '06 12 17 21 32'\n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#25-ajout-modification-dun-element-dans-un-dictionnaire","title":"2.5 Ajout / Modification d'un \u00e9l\u00e9ment dans un dictionnaire","text":"Exemple fondateur n\u00b05
Pas besoin d'une m\u00e9thode append()
, il suffit de rajouter une paire cl\u00e9 : valeur
>>> dressing[\"chaussettes\"] = 12\n
On peut aussi modifier un dictionnaire existant.
dressing[\"chaussettes\"] = 11\n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#26-suppression-dune-valeur","title":"2.6 Suppression d'une valeur","text":"Exemple fondateur n\u00b06
On utilise l'instruction del
(d\u00e9j\u00e0 rencontr\u00e9e pour les listes)
del dressing[\"chaussettes\"]\n
Exercice 2
Reprenons notre dictionnaire dressing
:
dressing = {\"pantalons\":3, \"pulls\":4, \"tee-shirts\":8}\n
Cr\u00e9er une fonction achat(habit)
qui augmente de 1 le nombre d'habits (pantalon, pull ou tee-shirt) de mon dressing. Exemple d'utilisation :
>>> dressing[\"pulls\"]\n4\n>>> achat(\"pulls\")\n>>> dressing[\"pulls\"]\n5\n
Correction dressing = {'pantalons':3, 'pulls':4, 'tee-shirts':8}\n\ndef achat(habit):\n dressing[habit] += 1\n
Remarque : Petit probl\u00e8me si on essaie d'acheter un v\u00eatement pour la 1\u00e8re fois
>>> achat(\"chemises\")\n ---------------------------------------------------------------------------\n\n KeyError Traceback (most recent call last)\n\n <ipython-input-28-fd9d1ac5f62d> in <module>\n ----> 1 achat(\"chemises\")\n\n\n <ipython-input-27-feb173444189> in achat(habit)\n 1 def achat(habit):\n ----> 2 dressing[habit] = dressing[habit] + 1\n\n\n KeyError: 'chemises'\n
Nous allons r\u00e9soudre ce probl\u00e8me gr\u00e2ce \u00e0 :
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#27-test-dappartenance-a-un-dictionnaire","title":"2.7 Test d'appartenance \u00e0 un dictionnaire","text":"Exemple fondateur n\u00b07
Le mot in
permet de tester l'appartenance d'une cl\u00e9 \u00e0 un dictionnaire. Un bool\u00e9en est renvoy\u00e9.
>>> \"cravates\" in dressing\n False\n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#3-exercices","title":"3. Exercices","text":"Exercice 3
Am\u00e9liorer la fonction achat(habit)
en y incluant un test pour prendre en compte les nouveaux habits.
Exemple d'utilisation :
>>> dressing\n{'pantalons': 3, 'pulls': 4, 'tee-shirts': 8}\n>>> achat('pulls')\n>>> achat('chapeau')\n>>> dressing\n{'pantalons': 3, 'pulls': 5, 'tee-shirts': 8, 'chapeau': 1}\n
Correction def achat(habit):\n if habit in dressing:\n dressing[habit] += 1\n else:\n dressing[habit] = 1\n
Exercice 4
On consid\u00e8re la liste suivante :
lst = ['Samuel', 'Pauline', 'Lina', 'Lina', 'Louis', 'Wa\u00ebll', 'Cl\u00e9ment', 'Khaled', 'Alexandre', 'Elie', 'Khaled', 'Khaled', 'Armand', 'Lina', 'Louis', 'Lina', 'Lina', 'Elie', 'Jules', 'Louis', 'Cl\u00e9ment', 'Khaled', 'Jules-Evan', 'Lina', 'Jules', 'Hadzo', 'Zoran', 'Cl\u00e9ment', 'Armand', 'Louis', 'Elie', 'Lina', 'Alexandre', 'Khaled', 'Iris', 'Gianni', 'Gianni', 'Pauline', 'Gianni', 'Elie', 'Iris', 'Armand', 'Louis', 'Cl\u00e9ment', 'Pauline', 'Zoran', 'Khaled', 'Zoran', 'Elie', 'Wa\u00ebll', 'Pauline', 'Lina', 'Alexandre', 'Khaled', 'Mehmet', 'Khaled', 'Hadzo', 'Zoran', 'Gianni', 'Jules', 'Paul', 'Pauline', 'Cl\u00e9ment', 'Alexandre', 'Iris', 'Khaled', 'Gianni', 'Elie', 'Jules', 'Khaled', 'Louis', 'Jules-Evan', 'Jules-Evan', 'Louis', 'Gianni', 'Elie', 'Cl\u00e9ment', 'Khaled', 'Louis', 'Louis', 'Emrys', 'Jules', 'Pauline', 'Armand', 'Elie', 'Jules', 'Elie', 'Khaled', 'Cl\u00e9ment', 'Louis', 'Khaled', 'Emrys', 'Samuel', 'Hadzo', 'Elie', 'Cl\u00e9ment', 'Alexandre', 'Hadzo', 'Lina', 'Iris', 'Alexandre', 'Mehmet', 'Elie', 'Jules', 'Khaled', 'Pauline', 'Samuel', 'Armand', 'Mehmet', 'Cl\u00e9ment', 'Jules', 'Armand', 'Mehmet', 'Lina', 'Armand', 'Cl\u00e9ment', 'Hadzo', 'Cl\u00e9ment', 'Emrys', 'Samuel', 'Zoran', 'Zoran', 'Zoran', 'Mehmet', 'Jules', 'Khaled', 'Khaled', 'Elie', 'Armand', 'Jules', 'Alexandre', 'Alexandre', 'Louis', 'Armand', 'Zoran', 'Iris', 'Cl\u00e9ment', 'Mehmet', 'Armand', 'Armand', 'Khaled', 'Lina', 'Lina', 'Jules', 'Louis', 'Paul', 'Pauline', 'Pauline', 'Pauline', 'Khaled', 'Lina', 'Wa\u00ebll', 'Zoran', 'Hadzo', 'Emrys', 'Gianni', 'Jules', 'Samuel', 'Gianni', 'Pauline', 'Wa\u00ebll', 'Cl\u00e9ment', 'Khaled', 'Jules', 'Jules', 'Louis', 'Zoran', 'Alexandre', 'Iris', 'Paul', 'Emrys', 'Armand', 'Wa\u00ebll', 'Zoran', 'Jules', 'Lina', 'Elie', 'Paul', 'Elie', 'Armand', 'Jules-Evan', 'Zoran', 'Alexandre', 'Zoran', 'Elie', 'Elie', 'Elie', 'Lina', 'Armand', 'Louis', 'Zoran', 'Lina', 'Armand', 'Alexandre', 'Samuel', 'Iris', 'Zoran', 'Paul', 'Pauline', 'Jules', 'Armand', 'Jules', 'Iris', 'Iris', 'Jules', 'Alexandre', 'Jules-Evan', 'Jules', 'Iris', 'Iris', 'Armand', 'Lina', 'Pauline', 'Zoran', 'Zoran', 'Pauline', 'Mehmet']\n
Cr\u00e9er un dictionnaire qui associera \u00e0 chaque pr\u00e9nom son nombre d'occurrences dans la liste.
Correction occurrence = {}\n\nfor prenom in lst:\n if prenom in occurrence:\n occurrence[prenom] += 1\n else:\n occurrence[prenom] = 1\n
Exercice 5
On consid\u00e8re la liste suivante : lst = ['5717', '1133', '5545', '4031', '6398', '2734', '3070', '1346', '7849', '7288', '7587', '6217', '8240', '5733', '6466', '7972', '7341', '6616', '5061', '2441', '2571', '4496', '4831', '5395', '8584', '3033', '6266', '2452', '6909', '3021', '5404', '3799', '5053', '8096', '2488', '8519', '6896', '7300', '5914', '7464', '5068', '1386', '9898', '8313', '1072', '1441', '7333', '5691', '6987', '5255']
Quel est le chiffre qui revient le plus fr\u00e9quemment dans cette liste ?
Correction lst = ['5717', '1133', '5545', '4031', '6398', '2734', '3070', '1346', '7849', '7288', '7587', '6217', '8240', '5733', '6466', '7972', '7341', '6616', '5061', '2441', '2571', '4496', '4831', '5395', '8584', '3033', '6266', '2452', '6909', '3021', '5404', '3799', '5053', '8096', '2488', '8519', '6896', '7300', '5914', '7464', '5068', '1386', '9898', '8313', '1072', '1441', '7333', '5691', '6987', '5255']\n\nocc = {}\nmaxi = 0\nfor nombre in lst:\n for chiffre in nombre:\n if chiffre in occ:\n occ[chiffre] += 1\n else:\n occ[chiffre] = 1\n if occ[chiffre] > maxi:\n maxi = occ[chiffre]\n chiffre_max = chiffre\n\nprint(chiffre_max, 'est le chiffre le plus fr\u00e9quent')\nprint('il apparait', maxi, 'fois')\n
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/","title":"2.4 Repr\u00e9sentation d'un entier positif dans diff\u00e9rentes bases","text":"Hormis la base 10, deux bases sont utilis\u00e9es en informatique :
- la base 2 (le syst\u00e8me binaire)
- la base 16 (le syst\u00e8me hexad\u00e9cimal)
Dans toute la suite, la base dans laquelle le nombre est \u00e9crit sera pr\u00e9cis\u00e9e en indice. Exemple : \\(13_{10}=1101_2=\\rm{D}_{16}\\)
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#1-le-systeme-binaire","title":"1. Le syst\u00e8me binaire","text":"En base 2, on ne dispose que des chiffres 0
et 1
. Le syst\u00e8me binaire est un syst\u00e8me de num\u00e9ration de position (comme le syst\u00e8me d\u00e9cimal, hexad\u00e9cimal... mais pas comme le syst\u00e8me romain). \u00c0 chaque rang correspond une puissance de 2.
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#11-du-binaire-vers-le-decimal","title":"1.1 Du binaire vers le d\u00e9cimal :","text":"... 128 64 32 16 8 4 2 1 ... \\(2^7\\) \\(2^6\\) \\(2^5\\) \\(2^4\\) \\(2^3\\) \\(2^2\\) \\(2^1\\) \\(2^0\\) ... 1 1 0 1 0 0 1 0 \\(11010010_2=1 \\times 2^7+ 1 \\times 2^6+0 \\times 2^5+1 \\times 2^4+0 \\times 2^3+0 \\times 2^2+1 \\times 2^1+0 \\times 2^0=128+64+32+2=210_{10}\\)
Le nombre binaire 11010010 correspond donc au nombre d\u00e9cimal 210.
Code Python
En Python, on peut utiliser la fonction int(\"nombre\", base)
.
>>> int(\"11010010\", 2)\n210\n
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#12-du-decimal-vers-le-binaire","title":"1.2 Du d\u00e9cimal vers le binaire :","text":"Principe : dans chaque nombre d\u00e9cimal, il existe une plus grande puissance de 2 qui est inf\u00e9rieure au nombre.
Par exemple, dans 243, il y a 128. Donc \\(243=128 + (115)\\) \\(243=128+64+(51)\\) \\(243=128+64+32+(19)\\) \\(243=128+64+32+16+(3)\\) \\(243=128+64+32+16+2+1\\) \\(243=1 \\times 2^7+ 1 \\times 2^6+1 \\times 2^5+1 \\times 2^4+0 \\times 2^3+0 \\times 2^2+1 \\times 2^1+1 \\times 2^0\\)
Donc \\(243_{10}=11110011_2\\)
M\u00e9thode des divisions successives
Code Python
En Python, on peut utiliser la fonction bin(nombre)
. Elle renvoie une cha\u00eene de caract\u00e8re o\u00f9 le nombre binaire est pr\u00e9c\u00e9d\u00e9 de '0b'
.
>>> bin(243)\n'0b11110011'\n
Exercice 1
\u00c9nonc\u00e9Correction Quelle est la valeur maximale d'un octet (un octet = 8 chiffres binaires) ?
\\(11111111_2=255\\). On retrouve ce nombre comme \u00e9tant la valeur maximale d'une composante de couleur dans le codage RGB, ce qui signifie que chaque composante est cod\u00e9e sur un octet.
Exercice 2
\u00c9nonc\u00e9Correction Cr\u00e9er une fonction binaire(n)
qui renvoie l'\u00e9criture binaire de n
, en utilisant les divisions successives.
def restes_successifs(n):\n ''' renvoie la liste des restes successifs lors des divisions de n par 2'''\n restes = []\n while n != 0 :\n restes.append(n % 2)\n n = n // 2\n return restes\n\ndef binaire(n) :\n ''' recompose le mot binaire en mettant dans l'ordre les restes successifs'''\n liste = restes_successifs(n)\n liste.reverse() #permet d'inverser l'ordre des \u00e9l\u00e9ment d'une liste\n mot = \"\"\n for k in liste :\n mot += str(k)\n return mot\n
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#2-le-systeme-hexadecimal","title":"2. Le syst\u00e8me hexad\u00e9cimal","text":"L'inconv\u00e9nient essentiel du syst\u00e8me binaire est la longueur de l'\u00e9criture des nombres qu'il g\u00e9n\u00e8re. Pour cette raison, le syst\u00e8me hexad\u00e9cimal, ou syst\u00e8me de base 16 est tr\u00e8s souvent employ\u00e9.
-
Pour \u00e9crire en base 2, il faut 2 chiffres diff\u00e9rents : le 0 et le 1.
-
Pour \u00e9crire en base 10, il faut 10 chiffres diff\u00e9rents: 0,1,2,3,4,5,6,7,8,9.
-
Pour \u00e9crire en base 16, il faut donc 16 chiffres diff\u00e9rents : 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F.
On a donc la correspondance :
- A repr\u00e9sente 10
- B repr\u00e9sente 11
- C repr\u00e9sente 12
- D repr\u00e9sente 13
- E repr\u00e9sente 14
- F repr\u00e9sente 15
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#21-de-lhexadecimal-vers-le-decimal","title":"2.1 De l'hexad\u00e9cimal vers le d\u00e9cimal :","text":"256 16 1 \\(16^2\\) \\(16^1\\) \\(16^0\\) 1 D 2 \\(\\rm{1D2}_{16}=1 \\times 16^2+ 13 \\times 16^1+2 \\times 16^0=256+208+2=466_{10}\\)
Le nombre hexad\u00e9cimal 1D2
correspond donc au nombre d\u00e9cimal 466.
En pratique, l'hexad\u00e9cimal est surtout utilis\u00e9 pour sa capacit\u00e9 \u00e0 repr\u00e9senter la valeur de n'importe quel octet sur 2 chiffres (\"chiffres\" \u00e9tant \u00e0 prendre au sens large = chiffres ou lettres !).
Exercice 3
\u00c9nonc\u00e9Correction - Donner la valeur des octets
FF
, 3A
, B2
. - Expliquer pourquoi la couleur RGB (138,255,51) a pour code html
#8AFF33
. - Quelle est la couleur
html
du blanc ?
- FF = 255 ; 3A = 58 ; B2 = 178
- 138 a pour code hexa 8A, 255 a pour code hexa 255, 51 a pour code hexa 33.
- #FFFFFF
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#22-en-python","title":"2.2 En python :","text":""},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#221-pour-passer-du-decimal-a-lhexadecimal","title":"2.2.1 Pour passer du d\u00e9cimal \u00e0 l'hexad\u00e9cimal :","text":"On peut utiliser la fonction hex(nombre)
. Elle renvoie une cha\u00eene de caract\u00e8re o\u00f9 le nombre hexad\u00e9cimal est pr\u00e9c\u00e9d\u00e9 de '0x'
.
>>> hex(125)\n'0x7d'\n
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#222-pour-passer-de-lhexadecimal-au-decimal","title":"2.2.2 Pour passer de l'hexad\u00e9cimal au d\u00e9cimal :","text":"On peut utiliser la fonction int(\"nombre\",base)
.
>>> int(\"FF\", 16)\n 255\n
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#3-du-binaire-inattendu","title":"3. Du binaire inattendu","text":"Le message secret de Perseverance
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/","title":"Les op\u00e9rateurs bool\u00e9ens","text":""},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#1-reperes-historiques","title":"1. Rep\u00e8res historiques","text":"En 1847, le britannique George BOOLE inventa un formalisme permettant d'\u00e9crire des raisonnements logiques : l'alg\u00e8bre de Boole. La notion m\u00eame d'informatique n'existait pas \u00e0 l'\u00e9poque, m\u00eame si les calculs \u00e9taient d\u00e9j\u00e0 automatis\u00e9s (penser \u00e0 la Pascaline de 1642).
Bien plus tard, en 1938, les travaux de l'am\u00e9ricain Claude SHANNON prouva que des circuits \u00e9lectriques peuvent r\u00e9soudre tous les probl\u00e8mes que l'alg\u00e8bre de Boole peut elle-m\u00eame r\u00e9soudre. Pendant la deuxi\u00e8me guerre mondiale, les travaux d'Alan TURING puis de John VON NEUMANN poseront d\u00e9finitivement les bases de l'informatique moderne.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#2-algebre-de-boole","title":"2. Alg\u00e8bre de Boole","text":"L'alg\u00e8bre de Boole d\u00e9finit des op\u00e9rations dans un ensemble qui ne contient que deux \u00e9l\u00e9ments not\u00e9s 0 et 1, ou bien FAUX et VRAI ,ou encore False et True (en Python)
Les op\u00e9rations fondamentales sont :
- la conjonction (\"ET\")
- la disjonction (\"OU\")
- la n\u00e9gation (\"NON\").
Dans toute la suite, x
et y
d\u00e9signeront des Bool\u00e9ens (\u00e9l\u00e9ments d'une alg\u00e8bre de Boole) quelconques, F
d\u00e9signera FAUX et V
d\u00e9signera VRAI.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#21-conjonction-and","title":"2.1 Conjonction (AND)","text":" - symbole usuel : & (appel\u00e9 esperluette en fran\u00e7ais et ampersand en anglais)
- fran\u00e7ais : ET
- anglais (et Python) :
and
- notation logique : \\(\\wedge\\)
- notation math\u00e9matique :
.
C'est l'op\u00e9ration d\u00e9finie par:
x & F = F
x & V = x
Puisque l'alg\u00e8bre de Boole ne contient que deux \u00e9l\u00e9ments, on peut \u00e9tudier tous les cas possibles et les regrouper dans un tableau appel\u00e9 table de v\u00e9rit\u00e9:
Table de v\u00e9rit\u00e9 de AND
x
y
x & y
F F F F V F V F F V V V On repr\u00e9sente souvent les op\u00e9rateurs bool\u00e9ens \u00e0 l'aide de portes logiques:
Notation usuelle en \u00e9lectronique : \\(Q=A \\wedge B\\)
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#exemples-en-python","title":"Exemples en Python","text":">>> n = 20\n>>> (n % 10 == 0) and (n % 7 == 0)\nFalse\n>>> (n % 4 == 0) and (n % 5 == 0)\nTrue\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#levaluation-paresseuse","title":"L'\u00e9valuation paresseuse","text":"Pouvez-vous pr\u00e9voir le r\u00e9sultat du code ci-dessous ?
>>> (n % 4 == 0) and (n % 0 == 0)\n ---------------------------------------------------------------------------\n\n ZeroDivisionError Traceback (most recent call last)\n\n <ipython-input-3-d8a98dcba9be> in <module>\n ----> 1 (n % 4 == 0) and (n % 0 == 0)\n\n\n ZeroDivisionError: integer division or modulo by zero\n
\u00c9videmment, la division par 0 provoque une erreur. Mais observez maintenant ce code :
>>> (n % 7 == 0) and (n % 0 == 0)\nFalse\n
On appelle \u00e9valuation paresseuse le fait que l'interpr\u00e9teur Python s'arr\u00eate d\u00e8s que sa d\u00e9cision est prise : comme le premier bool\u00e9en vaut False et que la conjonction and
est appel\u00e9e, il n'est pas n\u00e9cessaire d'\u00e9valuer le deuxi\u00e8me bool\u00e9en.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#22-disjonction-or","title":"2.2 Disjonction (OR)","text":" - symbole usuel : | appel\u00e9 pipe en anglais
- fran\u00e7ais : OU
- anglais (et Python) :
or
- notation logique : \\(\\vee\\)
- notation math\u00e9matique : \\(+\\)
C'est l'op\u00e9ration d\u00e9finie par:
C'est l'op\u00e9ration d\u00e9finie par:
x | V = V
x | F = x
On en d\u00e9duit la table suivante:
Table de v\u00e9rit\u00e9 de OR
x
y
x or y
F F F F V V V F V V V V Notation usuelle en \u00e9lectronique : \\(Q=A \\vee B\\)
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#exemples-en-python_1","title":"Exemples en Python","text":">>> n = 20\n>>> (n % 10 == 0) or (n % 7 == 0)\nTrue\n>>> (n % 4 == 0) or (n % 5 == 0)\nTrue\n>>> (n % 7 == 0) or (n % 3 == 0)\nFalse\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#levaluation-paresseuse-retour","title":"L'\u00e9valuation paresseuse (retour)","text":"Pouvez-vous pr\u00e9voir le r\u00e9sultat du code ci-dessous ?
>>> (n % 5 == 0) or (n % 0 == 0)\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#23-negation-not","title":"2.3 N\u00e9gation (NOT)","text":" - symbole usuel : ~
- fran\u00e7ais : NON
- anglais (et Python) :
not
- notation logique : \\(\\neg\\)
- notation math\u00e9matique : \\(\\overline{x}\\)
C'est l'op\u00e9ration d\u00e9finie par:
~V = F
~F = V
On en d\u00e9duit la table suivante:
Table de v\u00e9rit\u00e9 de NOT
x
~x
F V V F Notation usuelle en \u00e9lectronique : \\(Q=\\neg A\\)
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#exemples-en-python_2","title":"Exemples en Python","text":">>> n = 20\n>>> not(n % 10 == 0)\nFalse\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#24-exercice","title":"2.4 Exercice","text":"Exercice 1
Comprendre ce m\u00e8me :
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#25-exercice","title":"2.5 Exercice","text":"Exercice 2
Ouvrir le simulateur de circuits et cr\u00e9er pour chaque op\u00e9ration AND, OR, NOT un circuit \u00e9lectrique illustrant ses propri\u00e9t\u00e9s.
Exemple (inint\u00e9ressant) de circuit :
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#3-fonctions-composees","title":"3. Fonctions compos\u00e9es","text":""},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#31-disjonction-exclusive-xor","title":"3.1 Disjonction exclusive XOR","text":"(en fran\u00e7ais OU EXCLUSIF)
x ^ y = (x & ~y) | (~x & y)
Table de v\u00e9rit\u00e9 de XOR
x
y
x ^ y
F F F F V V V F V V V F Le XOR joue un r\u00f4le fondamental en cryptographie car il poss\u00e8de une propri\u00e9t\u00e9 tr\u00e8s int\u00e9ressante : \\((x\\wedge y)\\wedge y=x\\)
Si \\(x\\) est un message et \\(y\\) une cl\u00e9 de chiffrage, alors \\(x\\wedge y\\) est le message chiffr\u00e9. Mais en refaisant un XOR du message chiffr\u00e9 avec la cl\u00e9 \\(y\\), on retrouve donc le message \\(x\\) initial.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#32-fonction-non-et-nand","title":"3.2 Fonction Non Et (NAND)","text":"x \u2191 y = ~(x & y)
Table de v\u00e9rit\u00e9 de NAND
x
y
x \u2191 y
F F V F V V V F V V V F "},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#33-fonction-non-ou-nor","title":"3.3 Fonction Non Ou (NOR)","text":"x \u2193 y = ~(x & y)
Table de v\u00e9rit\u00e9 de NOR
x
y
x \u2193 y
F F V F V F V F F V V F Il est temps de se reposer un peu et d'admirer cette vid\u00e9o :
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#remarque","title":"Remarque :","text":"Les fonctions NAND ET NOR sont dites universelles : chacune d'entre elles peut g\u00e9n\u00e9rer l'int\u00e9gralit\u00e9 des autres portes logiques. Il est donc possible de coder toutes les op\u00e9rations uniquement avec des NAND (ou uniquement avec des NOR).
Exercice 3
Nous allons r\u00e9utiliser le simulateur de circuits mais en n'utilisant QUE DES PORTES NAND.
Q1. R\u00e9aliser la porte AND (avec que des NAND...)
Correction Q2. R\u00e9aliser la porte OR (avec que des NAND...)
Correction Vous pouvez trouver d'autres renseigements sur Wikipedia.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#34-exercice-4","title":"3.4 Exercice 4","text":"Exercice 4
\u00c9nonc\u00e9Correction Effectuer les op\u00e9rations suivantes.
1011011\n& 1010101\n----------\n\n\n 1011011\n| 1010101\n----------\n\n\n 1011011\n^ 1010101\n----------\n
1011011\n&1010101\n----------\n 1010001\n\n 1011011\n|1010101\n----------\n 1011111\n\n 1011011\n^1010101\n----------\n 0001110\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#35-calculs-en-python","title":"3.5 Calculs en Python","text":"les op\u00e9rateurs &
, |
et ^
sont utilisables directement en Python
# calcul A\n>>> 12 & 7\n4\n
# calcul B\n>>> 12 | 7\n15\n
# calcul C\n>>> 12 ^ 5\n9\n
Pour comprendre ces r\u00e9sultats, il faut travailler en binaire. Voici les m\u00eames calculs :
# calcul A\n>>> bin(0b1100 & 0b111)\n '0b100'\n
# calcul B\n>>> bin(0b1100 | 0b111)\n '0b1111'\n
# calcul C\n>>> bin(0b1100 ^ 0b111)\n '0b1011'\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#exercice-5-cryptographie","title":"Exercice 5 : Cryptographie","text":"Exercice 5
On souhaite chiffrer (chiffrer est le mot utilis\u00e9 en cryptographie pour crypter) le mot \"BONJOUR\"
avec la cl\u00e9 \"MAURIAC\"
. Le chiffrement retenu est un chiffrement par XOR, ce qui signifie qu'on va effectuer un XOR entre les deux nombres associ\u00e9s aux lettres.
Exemple :
- la lettre
'B'
va \u00eatre chiffr\u00e9e gr\u00e2ce au 'M'
. - Le code ASCII de
'B'
est 66. (on le sait car ord('B')
renvoie 66 ) - Le code ASCII de
'M'
est 77. (on le sait car ord('M')
renvoie 77 ) - 66 ^ 77 vaut 15.
- Le \u00abcaract\u00e8re\u00bb associ\u00e9 \u00e0 15 est
'\\x0f'
(on le sait car chr(15)
renvoie '\\x0f'
)
Le premier caract\u00e8re du mot chiffr\u00e9 sera donc '\\x0f'
Q1. \u00c9crire une fonction chiffre
qui prendra en param\u00e8tre un mot mot_clair
et un mot de passe cle
de m\u00eame taille que mot_clair
et qui renvoie la cha\u00eene de caract\u00e8res obtenue en XORant mot_clair
avec cle
.
Correction def chiffre(mot_clair, cle):\n mot_chiffre = ''\n for i in range(len(mot_clair)):\n code = ord(mot_clair[i]) ^ ord(cle[i])\n mot_chiffre += chr(code)\n return mot_chiffre\n
Q2. Chiffrer le mot \"BONJOUR\"
avec la cl\u00e9 \"MAURIAC\"
.
Correction >>> chiffre('BONJOUR', 'MAURIAC')\n'\u000f\u000e\u001b\u0018\u0006\u0014\u0011'\n
Q3. Reprendre la cha\u00eene de caract\u00e8res pr\u00e9c\u00e9demment obtenue et la rechiffrer \u00e0 nouveau avec la cl\u00e9 \"MAURIAC\"
. Que constate-t-on ? Etait-ce pr\u00e9visible ?
Correction >>> chiffre('\u000f\u000e\u001b\u0018\u0006\u0014\u0011', 'MAURIAC')\n'BONJOUR'\n
C'\u00e9tait pr\u00e9visible car c'est une propri\u00e9t\u00e9 remarquable du XOR : (a^b)^b = a
Q4. R\u00e9soudre le Pyd\u00e9fi La cl\u00e9 endommag\u00e9e
Correction msg = [255, 87, 255, 93, 254, 112, 98, 239, 146, 205, 59, 198, 173, 65, 50, 174, 200, 218, 189, 130, 96, 4, 57, 173, 143, 8, 175, 19, 2, 109, 216, 2, 65, 14, 36, 206, 32, 157, 181, 22, 248, 119, 153, 204, 8, 137, 7, 203, 0, 89, 251, 16, 79, 214, 52, 15, 249, 42, 115, 67, 241, 175, 160, 65, 217, 40, 36, 68, 205, 234, 14, 21, 73, 172, 70, 81, 37, 83, 1, 113, 180, 8, 194, 90, 46, 239, 194, 122, 244, 15, 24, 14, 86, 72, 43, 246, 241, 24, 182, 91, 220, 48, 92, 147, 16, 82, 139, 169, 104, 236, 88, 106, 192, 76, 23, 72, 233, 130, 92, 67, 235, 199, 149, 108, 180, 217, 156, 175, 175, 234, 177, 145, 242, 17, 245, 94, 113, 16, 88, 170, 71, 226, 13, 122, 189, 56, 44, 48, 185, 159, 73, 160, 84, 147, 231, 21, 86, 81, 238, 196, 137, 133, 222, 174, 208, 9, 105, 83, 80, 60, 49, 191, 19, 220, 231, 196, 172, 10, 72, 237, 211, 163, 23, 119, 247, 37, 177, 3, 246, 136, 82, 222, 93, 245, 202, 24, 164, 177, 167, 174, 203, 247, 101, 201, 32, 99, 83, 189, 241, 46, 208, 125, 167, 111, 217, 84, 120, 5, 158, 50, 180, 129, 202, 116, 149, 226, 195, 6, 56, 221, 54, 1, 233, 119, 186, 113, 87, 194, 240, 244, 29, 195, 251, 186, 54, 175, 66, 8, 193, 189, 143, 151, 101, 153, 25, 100, 151, 75, 71, 176, 55, 183, 66, 28, 119, 90, 142, 60, 100, 170, 46, 231, 149, 131, 139, 249, 247, 209, 60, 206, 40, 121, 175, 78, 246, 189, 88, 33, 46, 147, 11, 30, 65, 208, 131, 163, 37, 44, 77, 220, 148, 101, 101, 167, 34, 68, 179, 117, 200, 234, 91, 170, 134, 203, 240, 164, 71, 220, 122, 77, 249, 76, 39, 145, 217, 151, 36, 96, 249, 61, 105, 52, 59, 231, 86, 166, 88, 42, 134, 182, 74, 166, 106, 36, 194, 160, 92, 69, 84, 74, 15, 217, 189, 28, 89, 41, 212, 60, 49, 30, 225, 95, 196, 36, 199, 0, 126, 127, 251, 23, 76, 182, 66, 213, 119, 28, 187, 173, 239, 27, 97, 196, 17, 95, 124, 4, 95, 222, 191, 238, 152, 142, 208, 122, 139, 135, 12, 212, 96, 4, 126, 210, 7, 71, 225, 202, 106, 79, 206, 156, 216, 22, 163, 159, 49, 248, 120, 100, 2, 88, 41, 145, 234, 38, 196, 189, 77, 247, 71, 172, 109, 215, 134, 37, 145, 236, 6, 198, 217, 89, 94, 98, 158, 165, 99, 17, 99, 246, 90, 161, 76, 159, 194, 75, 208, 234, 18, 51, 205, 227, 167, 199, 1, 128, 68, 112, 25, 10, 66, 202, 255, 243, 163, 16, 3, 72, 43, 143, 76, 241, 108, 239, 216, 30, 236, 224, 7, 1, 222, 6, 244, 70, 151, 110, 175, 49, 153, 253, 241, 160, 117, 232, 42, 68, 77, 253, 64, 142, 11, 88, 234, 251, 20, 1, 239, 39, 157, 181, 106, 47, 180, 26, 227, 121, 164, 183, 124, 180, 238, 42, 89, 75, 19, 244, 245, 116, 82, 124, 85, 12, 7, 22, 1, 25, 118, 126, 36, 209, 22, 226, 252, 6, 72, 26, 101, 127, 23, 124, 151, 185, 184, 203, 231, 56, 26, 128, 110, 216, 94, 202, 174, 211, 210, 125, 145, 220, 185, 43, 204, 215, 210, 224, 54, 111, 217, 202, 47, 31, 224, 46, 177, 165, 31, 68, 127, 206, 99, 11, 213, 192, 46, 222, 34, 115, 16, 73, 131, 221, 218, 180, 4, 249, 207, 74, 155, 84, 87, 242, 58, 133, 248, 61, 205, 9, 158, 226, 21, 216, 80, 154, 153, 79, 98, 105, 190, 56, 134, 187, 37, 10, 224, 82, 97, 126, 246, 24, 190, 173, 21, 62, 236, 10, 180, 242, 144, 244, 145, 117, 67, 62, 246, 57, 96, 192, 92, 126, 27, 67, 168, 223, 222, 247, 236, 224, 240, 243, 100, 150, 193, 79, 223, 143, 208, 133, 125, 80, 107, 106, 245, 118, 248, 79, 199, 116, 190, 54, 236, 81, 106, 244, 212, 241, 16, 179, 245, 238, 185, 89, 199, 175, 54, 218, 86, 84, 184, 177, 174, 92, 171, 176, 43, 149, 46, 202, 151, 181, 98, 86, 18, 58, 46, 163, 117, 33, 149, 87, 248, 235, 0, 181, 136, 16, 188, 110, 20, 108, 213, 104, 165, 45, 86, 19, 208, 48, 153, 186, 163, 221, 165, 39, 70, 200, 98, 235, 68, 167, 252, 42, 102, 52, 228, 210, 187, 151, 178, 242, 221, 44, 143, 79, 230, 159, 164, 253, 25, 90, 24, 182, 142, 122, 140, 115, 45, 182, 104, 132, 22, 109, 55, 205, 185, 27, 27, 77, 224, 184, 199, 121, 21, 250, 254, 78, 158, 215, 245, 187, 143, 211, 110, 228, 18, 36, 68, 168, 100, 126, 85, 238, 208, 98, 241, 34, 235, 254, 184, 39, 182, 239, 34, 242, 232, 6, 187, 18, 113, 176, 228, 2, 103, 135, 52, 28, 183, 9, 19, 142, 156, 242, 21, 253, 48, 21, 67, 138, 207, 131, 72, 191, 198, 107, 233, 202, 227, 108, 186, 124, 165, 23, 247]\n\ncle = [111, 22, 12, 177, 12, 199, 78, 21, 175, 181, 64, 73, 174, 101, 212, 225, 63, 106, 248, 91, 175, 48, 247, 245, 51, 250, 160, 111, 23, 4, 70, 167, 177, 49, 17, 53, 17, 73, 85, 89]\n\ndef decrypt(dec):\n l = ''\n for i in range(len(cle)):\n c = msg[i + dec] ^ cle[i]\n l = l + chr(c)\n return l\n\nfor i in range(0, len(msg)-len(cle)):\n print(decrypt(i))\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#complement-mathematique-proprietes-des-operateurs-logiques","title":"Compl\u00e9ment math\u00e9matique: propri\u00e9t\u00e9s des op\u00e9rateurs logiques","text":"Les propri\u00e9t\u00e9s suivantes sont facilement d\u00e9montrables \u00e0 l'aide de tables de v\u00e9rit\u00e9s: (source : G.Connan)
Toutes ces lois sont ais\u00e9ment compr\u00e9hensibles si on les transpose en math\u00e9matiques :
- & \u00e9quivaut \u00e0 \\(\\times\\)
- \\(|\\) \u00e9quivaut \u00e0 \\(+\\)
- \\(\\neg\\) \u00e9quivaut \u00e0 \\(-\\)
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/","title":"\u00c9nigme","text":"Vous pouvez faire cette \u00e9nigme sur Thonny (pensez \u00e0 bien travailler dans le dossier qui contient vos deux images) ou bien sur Capytale https://capytale2.ac-paris.fr/web/c/5912-1397991
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#1-a-la-recherche-du-personnage-mystere","title":"1. \u00c0 la recherche du personnage myst\u00e8re","text":"Vous avez trouv\u00e9 une image bien \u00e9trange :
Un visage semble se deviner derri\u00e8re un champ de fleurs... mais quel est ce visage ?
L'image du champ de fleurs ne vous est pas inconnue, d'ailleurs en cherchant bien vous l'avez retrouv\u00e9e dans vos dossiers :
On dirait que le personnage-myst\u00e8re a voulu se fondre dans le champ de fleurs...
XORez-vous d\u00e9couvrir qui est ce personnage-myst\u00e8re ?
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#2-aide-pour-la-manipulation-dimages-et-lextraction-de-pixels","title":"2. Aide pour la manipulation d'images et l'extraction de pixels","text":""},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#21-code-de-demarrage","title":"2.1 Code de d\u00e9marrage","text":"from PIL import Image\n\nimg_myst = Image.open(\"mystere.bmp\")\nimg_mask = Image.open(\"mask.jpg\")\n\nlargeur = img_myst.width\nhauteur = img_myst.height\n\nimg_new = Image.new('RGB', img_myst.size)\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#22-manipulation-de-pixels","title":"2.2 Manipulation de pixels","text":"Les expressions ci-dessous sont \u00e0 tester pour en comprendre le fonctionnement.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#221-recuperer-le-code-rgb-un-pixel","title":"2.2.1 R\u00e9cup\u00e9rer le code RGB
un pixel","text":">>> img_myst.getpixel((125, 80))\n(54, 217, 174)\n
Le pixel de coordonn\u00e9es (125, 80) a pour composantes RGB (54, 217, 174)."},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#222-modifier-la-couleur-dun-pixel","title":"2.2.2 Modifier la couleur d'un pixel","text":">>> img_new.putpixel((30,70), (255,0,0))\n>>> \n
Le pixel de coordonn\u00e9es (30, 70) est maintenant un pixel rouge."},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#223-afficher-une-image","title":"2.2.3 Afficher une image","text":">>> img_mask.show()\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#224-sauvegarder-une-image","title":"2.2.4 Sauvegarder une image","text":">>> img_new.save(\"solution.png\")\n
Correction from PIL import Image\n\nimg_myst = Image.open('mystere.bmp')\nimg_mask = Image.open('mask.jpg')\n\nlargeur = img_myst.width\nhauteur = img_myst.height\n\nimg_new = Image.new('RGB', img_myst.size)\n\nfor x in range(largeur):\n for y in range(hauteur):\n pix_myst = img_myst.getpixel((x, y))\n pix_mask = img_mask.getpixel((x, y))\n new_pix = (pix_myst[0] ^ pix_mask[0], pix_myst[1] ^ pix_mask[1], pix_myst[2] ^ pix_mask[2])\n img_new.putpixel((x,y), new_pix)\n\nimg_new.show() \n
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/","title":"2.6 Codage des caract\u00e8res","text":"Tout pour comprendre et \u00c3\u00a9viter les erreurs d'encodage
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#1-au-commencement-etait-lascii","title":"1. Au commencement \u00e9tait l'ASCII","text":"pour American Standard Code for Information Interchange, cr\u00e9\u00e9 en 1960 aux \u00c9tats-Unis.
En ASCII, 127 \u00abpoints de code\u00bb (nombres associ\u00e9s aux caract\u00e8res) sont disponibles. Les caract\u00e8res sont donc cod\u00e9s sur 7 bits.
Exercice
\u00c9nonc\u00e9Aide D\u00e9coder l'expression suivante, \u00e9crite en ASCII :
1101100 1100101 1110011 100000 1001110 1010011 1001001 100000 1100011 100111 1100101 1110011 1110100 100000 1101100 1100101 1110011 100000 1101101 1100101 1101001 1101100 1101100 1100101 1110101 1110010 1110011
- la fonction
split(\" \")
permet de d\u00e9composer une chaine de caract\u00e8res en une liste, en se servant de l'espace \" \"
comme caract\u00e8re s\u00e9parateur. int(\"1101100\",2)
permet de r\u00e9cup\u00e9rer facilement la valeur en base 10 du nombre binaire 1101100
.
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#2-et-le-reste-du-monde","title":"2. Et le reste du monde ?","text":"Lorsque d'autres personnes que des americains ou des anglais ont voulu s'\u00e9changer des donn\u00e9es faisant intervenir du texte, certains caract\u00e8res (\u00e9, \u00e8, \u00e0, \u00f1, \u00d8, \u00d6, \u03b2, \u6f22...) \u00e9taient manquants. Les 127 caract\u00e8res de l'ASCII \u00e9taient largement insuffisants. Il a donc \u00e9t\u00e9 d\u00e9cid\u00e9 de passer \u00e0... 256 caract\u00e8res ! Il suffisait pour cela de coder les caract\u00e8res non plus sur 7 bits mais sur 8 bits.
Ainsi naqu\u00eet, apr\u00e8s de nombreuses modifications successives (la derni\u00e8re en date rajoutant par exemple le symbole \u20ac), la c\u00e9l\u00e8bre table ISO 8859-15, dite aussi Latin-9 :
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#utilisation","title":"Utilisation :","text":"Les codes sont donn\u00e9s en hexad\u00e9cimal :
- le caract\u00e8re \u20ac correspond au code hexad\u00e9cimal A4, donc au nombre d\u00e9cimal 164.
- le caract\u00e8re A correspond au code hexad\u00e9cimal 41, donc au nombre d\u00e9cimal 65.
65... comme en ASCII ! Oui, la (seule) bonne id\u00e9e aura \u00e9t\u00e9 d'inclure les caract\u00e8res ASCII avec leur m\u00eame code, ce qui rendait cette nouvelle norme r\u00e9tro-compatible.
Exemple :
Le fichier test.txt
contient un texte enregistr\u00e9 avec l'encodage Latin-9. Ce fichier est ensuite ouvert avec un \u00e9diteur hexad\u00e9cimal, qui permet d'observer la valeur des octets qui composent le fichier. (Comme le fichier est un .txt, le fichier ne contient que les donn\u00e9es et rien d'autre.)
Parfait, mais comment font les Grecs pour \u00e9crire leur alphabet ? Pas de probl\u00e8me, il leur suffit d'utiliser... une autre table, appel\u00e9e ISO-8859-7 :
On retrouve les caract\u00e8res universels h\u00e9rit\u00e9s de l'ASCII, puis des caract\u00e8res sp\u00e9cifiques \u00e0 la langue grecque... oui mais les Tha\u00eflandais alors ?
Pas de probl\u00e8me, ils ont la ISO-8859-11 :
\u00c9videmment, quand tous ces gens veulent discuter entre eux, les probl\u00e8mes d'encodage surviennent imm\u00e9diatement : certains caract\u00e8res sont remplac\u00e9s par d'autres.
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#3-que-fait-un-logiciel-a-louverture-dun-fichier-texte","title":"3. Que fait un logiciel \u00e0 l'ouverture d'un fichier texte ?","text":"Il essaie de deviner l'encodage utilis\u00e9... Parfois cela marche, parfois non.
Normalement, pour un navigateur, une page web correctement cod\u00e9e doit contenir dans une balise meta
le charset
utilis\u00e9.
Mais parfois, il n'y a pas d'autre choix pour le logiciel d'essayer de deviner l'encodage qui semble \u00eatre utilis\u00e9.
Exercice
\u00c9nonc\u00e9Correction Le mot repr\u00e9sent\u00e9 par les octets ci-dessous est-il encod\u00e9 en ASCII ou en Latin-9 ?
C'est du Latin-9, et c'est le mot \"v\u00e9lo\"
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#4-enfin-une-normalisation-larrivee-de-lutf","title":"4. Enfin une normalisation : l'arriv\u00e9e de l'UTF","text":"En 1996, le Consortium Unicode d\u00e9cide de normaliser tout cela et de cr\u00e9er un syst\u00e8me unique qui contiendra l'int\u00e9gralit\u00e9 des caract\u00e8res dont les \u00eatres humains ont besoin pour communiquer entre eux.
Ils cr\u00e9ent l'Universal character set Transformation Format : l'UTF. Ou plut\u00f4t ils en cr\u00e9ent... plusieurs :
- l'UTF-8 : les caract\u00e8res sont cod\u00e9s sur 1, 2, 3 ou 4 octets.
- l'UTF-16 : les caract\u00e8res sont cod\u00e9s sur 2 ou 4 octets.
- l'UTF-32 : les caract\u00e8res sont cod\u00e9s sur 4 octets.
Pourquoi est-ce encore si compliqu\u00e9 ? En UTF-32, 32 bits sont disponibles, soit \\(2^{32}=4294967296\\) caract\u00e8res diff\u00e9rents encodables.
C'est largement suffisant, mais c'est surtout tr\u00e8s tr\u00e8s lourd ! D'autres encodages plus l\u00e9gers, mais plus complexes, sont donc propos\u00e9s :
Arr\u00eatons-nous sur l'UTF-8 :
Le principe fondateur de l'UTF-8 est qu'il est adaptatif : les carac\u00e8res les plus fr\u00e9quents sont cod\u00e9s sur un octet, qui est la taille minimale (et qui donne le 8 de \"UTF-8\"). Les autres caract\u00e8res peuvent \u00eatre cod\u00e9s sur 2, 3 ou 4 octets au maximum.
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#5-la-reponse-a-une-question-existentielle","title":"5. La r\u00e9ponse \u00e0 une question existentielle","text":"Pourquoi le caract\u00e8re \u00e9
en UTF-8 devient-il \u00c3\u00a9
en ISO 8859-15 ?
Q1. Gr\u00e2ce \u00e0 la fonction ord
puis \u00e0 la fonction bin
, \u00e9crire en binaire le nombre associ\u00e9 au caract\u00e8re \u00e9
en UTF-8.
Correction >>> ord('\u00e9')\n233\n>>> bin(233)\n'0b11101001'\n
Donc en UTF-8, \u00e9
est associ\u00e9 au nombre 11101001
. Q2. D'apr\u00e8s l'explication de fonctionnement de l'encodage adaptatif de l'UTF-8 (voir ci-dessus), les 8 bits n\u00e9cessaires \u00e0 l'encodage de \u00e9
en UTF-8 vont \u00eatre \u00abencapsul\u00e9s\u00bb dans 2 octets de la forme 110XXXXX 10XXXXXX
, o\u00f9 les 11 X
repr\u00e9sentent les 11 bits d'information disponibles. \u00c9crire ces 2 octets en compl\u00e9tant si n\u00e9cessaire avec des 0
\u00e0 gauche.
Correction Sur 11 bits, le nombre 11101001
va s'\u00e9crire 00011101001
. En s\u00e9parant ces 11 bits en deux groupes de 5 bits et 6 bits (00011
et 101001
), et en les encapsulant, on obtient les deux octets 11000011 10101001
.
Q3. Convertir les deux octets obtenus en notation d\u00e9cimale (gr\u00e2ce \u00e0 int
) puis en hexad\u00e9cimal (gr\u00e2ce \u00e0 hex
).
Correction >>> int('11000011', 2)\n195\n>>> hex(195)\n'0xc3'\n>>> int('10101001', 2)\n169\n>>> hex(169)\n'0xa9'\n
Q4. Si un logiciel consid\u00e8re \u00e0 tort que les deux octets servant \u00e0 encoder le \u00e9
en UTF-8 servent \u00e0 encoder deux caract\u00e8res en ISO 8859-15, quels seront ces deux caract\u00e8res ?
Correction Le premier octet, c3
en hexad\u00e9cimal, sera per\u00e7u en ISO 8859-15 comme le caract\u00e8re \u00c3
. Le deuxi\u00e8me octet, a9
en hexad\u00e9cimal, sera per\u00e7u en ISO 8859-15 comme la lettre \u00a9
.
Finalement, ce qui aurait d\u00fb \u00eatre un \u00e9
en UTF-8 se retrouvera \u00eatre un \u00c3\u00a9
en ISO 8859-15.
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#utilisation-grandissante-de-lencodage-utf-8","title":"Utilisation grandissante de l'encodage UTF-8","text":"La majorit\u00e9 des sites internet utilisent maintenant l'UTF-8, tout comme les syst\u00e8mes d'exploitation r\u00e9cents.
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/","title":"2.7 Codage des entiers","text":" Attention
La mani\u00e8re dont les nombres (entiers, non-entiers, positifs, n\u00e9gatifs...) sont trait\u00e9s par un langage de programmation est sp\u00e9cifique \u00e0 ce langage.
Dans toute la suite de ce cours, pour simplifier, nous consid\u00e9rerons que les nombres sont cod\u00e9s sur 1 octet seulement. Ce qui ne correspond pas \u00e0 la r\u00e9alit\u00e9, mais permet de comprendre les notions essentielles.
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#1-les-nombres-entiers-en-binaire-non-signe","title":"1. Les nombres entiers en binaire non sign\u00e9","text":"L'expression \"non sign\u00e9\" signifie que la contrainte du signe n'existe pas : tous les nombres sont consid\u00e9r\u00e9s comme \u00e9tant positifs.
Nous avons d\u00e9j\u00e0 vu comment ces nombres se codaient en binaire.
Sur un octet, le nombre minimal qu'on puisse coder est 00000000
. C'est l'entier naturel 0. Le nombre maximal qu'on puisse coder est 11111111
. C'est l'entier naturel 255.
Exercice 1
- Quel est le plus grand entier non sign\u00e9 codable sur 16 bits ?
- ... sur 32 bits ?
- ... \\(n\\) bits ?
Correction - \\(N=1+2+2^2+2^3+\\dots+2^{15}= 65535\\)
- \\(N=1+2+2^2+2^3+\\dots+2^{31}= 4294967295\\)
- Pour tout \\(n \\in \\mathbb{N}\\), \\(1+2+2^2+2^3+\\dots+2^{n-1}=2^{n}-1\\) (formule de la somme des termes d'une suite g\u00e9om\u00e9trique de raison 2).
Python et les entiers
Depuis la version 3 du langage Python, il n'y a plus de taille maximale pour les entiers en Python.
Ceci implique que la taille n\u00e9cessaire au codage de l'entier est allou\u00e9e dynamiquement par Python (avec pour seule limite celle de la m\u00e9moire disponible).
Exercice 2
- Effectuer la somme des deux nombres binaires
00001101
et 00001011
. - V\u00e9rifier que le r\u00e9sultat est coh\u00e9rent en base 10.
Correction - Cette addition correspond \u00e0 \\(13+11=24\\)
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#2-les-nombres-entiers-en-binaire-signe","title":"2. Les nombres entiers en binaire sign\u00e9","text":"ou Comment repr\u00e9senter des nombres n\u00e9gatifs ???
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#21-la-partiellement-fausse-bonne-idee","title":"2.1 La (partiellement) fausse bonne id\u00e9e","text":"Comment diff\u00e9rencier les nombres positifs des nombres n\u00e9gatifs ? L'id\u00e9e naturelle est de r\u00e9server 1 bit pour le signe, et de coder le reste du nombre \u00abnaturellement\u00bb.
Par exemple, on peut d\u00e9cr\u00e9ter que le premier bit (appel\u00e9 bit de poids fort) sera le bit de signe :
- 0 pour un nombre positif
- 1 pour un nombre n\u00e9gatif
Dans ce cas, 00000011
serait le nombre \\(+3\\) et 10000011
serait le nombre \\(-3\\).
Probl\u00e8mes :
- le z\u00e9ro serait repr\u00e9sent\u00e9 \u00e0 la fois par
00000000
et 10000000
, ce qui n'est pas tr\u00e8s \u00e9conome. - plus grave :
Exercice 3
Avec cette convention, effectuer l'addition \\((+3)+(-3)\\) en binaire.
Correction L'addition \\((+3)+(-3)\\) serait \u00e9gale \u00e0 \\(-6\\) !
Moralit\u00e9 :
Ce syst\u00e8me d'\u00e9criture ne marche pas bien.
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#22-a-la-recherche-de-loppose-dun-nombre","title":"2.2 \u00c0 la recherche de l'oppos\u00e9 d'un nombre","text":"Id\u00e9e :
Plut\u00f4t que de chercher \u00e0 \u00e9crire directement le nombre \\(-3\\), nous allons chercher \u00e0 d\u00e9terminer ce qu'il faut ajouter \u00e0 \\((+3)\\) pour obtenir 0.
Que faut-il ajouter au nombre \\((+3)\\) pour obtenir 0 ?
L'id\u00e9e naturelle est de commencer par la droite, en essayant de \u00abfabriquer du z\u00e9ro\u00bb en choisissant le bon bit \u00e0 ajouter :
On arrive bien \u00e0 fabriquer des 0 sur tout notre octet, mais que devient la retenue (en anglais carry) de 1 qui d\u00e9borde de notre octet ?
R\u00e9ponse : rien ! Elle sera perdue et c'est une tr\u00e8s bonne nouvelle. Ce nombre sera donc consid\u00e9r\u00e9 comme un 0 : nous avons trouv\u00e9 comment coder \\(-3\\).
Le nombre \\(-3\\) s'\u00e9crit donc 11111101
.
Comment, \u00e0 partir du nombre 00000011
, aurait-on pu le trouver directement (sans raisonner de proche en proche) ?
On peut remarquer qu'en inversant chaque bit du nombre de d\u00e9part 00000011
, on obtient 11111100
, qui appel\u00e9 le compl\u00e9ment \u00e0 2 du nombre 00000011
.
Il ne reste donc plus qu'\u00e0 ajouter 1
\u00e0 ce nombre 11111100
pour obtenir le nombre cherch\u00e9, 11111101
ce nombre 11111101
repr\u00e9sente 253 en codage non sign\u00e9. Il est donc n\u00e9cessaire, lorsqu'on repr\u00e9sente un nombre, de savoir si les nombres manipul\u00e9s seront des entiers naturels (non sign\u00e9s) ou bien relatifs (sign\u00e9s).
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#23-tableau-des-entiers-en-binaire-signe","title":"2.3 Tableau des entiers en binaire sign\u00e9","text":"Tableau binaire base 10 10000000 -128 10000001 -127 10000010 -126 10000011 -125 10000100 -124 10001001 -123 ... ... 11111100 -4 11111101 -3 11111110 -2 11111111 -1 00000000 0 00000001 1 00000010 2 00000011 3 00000100 4 ... ... 01111100 124 01111101 125 01111110 126 01111111 127"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#24-conclusion-ecriture-loppose-dun-nombre-positif","title":"2.4 Conclusion : \u00e9criture l'oppos\u00e9 d'un nombre positif","text":"Consid\u00e9rons que ce nombre positif s'\u00e9crit sur 7 bits, donc qu'il est de la forme 0XXXXXXX
.
\u00c9criture de l'oppos\u00e9 d'un nombre positif
- On prend le compl\u00e9ment \u00e0 2 de chacun des 8 bits du nombre de d\u00e9part
- On ajoute 1 au nombre obtenu.
Exercice 4
Donner l'\u00e9criture binaire sur un octet du nombre \\(-13\\).
Correction Commen\u00e7ons par \u00e9crire le nombre 13 en binaire. Il s'\u00e9crit \u00a000001101
.
- en prenant le compl\u00e9ment \u00e0 2 de chaque bit, on obtient
11110010
. - en ajoutant 1 \u00e0 ce dernier nombre, on obtient
11110011
.
Le nombre \\(-13\\) s'\u00e9crit donc 11110011
.
Remarque Les nombres n\u00e9gatifs commenceront donc toujours par le bit 1, et les nombres positifs par le bit 0. Cela revient \u00e0 suivre partiellement notre fausse bonne id\u00e9e du 2.1. Et cela donne surtout une m\u00e9thode tr\u00e8s pratique pour savoir qui est positif et qui est n\u00e9gatif !
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#3-travail-inverse-passage-du-binaire-signe-au-nombre-relatif","title":"3. Travail inverse : passage du binaire sign\u00e9 au nombre relatif","text":"Consid\u00e9rons le nombre 11101101
, cod\u00e9 en binaire sign\u00e9. \u00c0 quel nombre relatif correspond-il ?
- On observe son bit de poids fort : ici 1, donc ce nombre est n\u00e9gatif. Si ce bit est \u00e9gal \u00e0 0, le nombre cod\u00e9 est positif, il suffit d'op\u00e9rer une conversion binaire classique.
- Comme ce nombre est n\u00e9gatif, il va falloir inverser le protocole pr\u00e9c\u00e9dent. On commence donc par enlever 1 au nombre propos\u00e9. On trouve
11101100
. - On prend ensuite le compl\u00e9ment \u00e0 2 de chaque bit. On trouve
00010011
. - On convertit en base 10 le nombre obtenu, qui \u00e9tait donc 19.
- Le nombre initial \u00e9tait donc \\(-19\\).
Exercice
Q1. En binaire sign\u00e9, \u00e0 quel nombre correspond 11110001
?
Correction 11110001
- 1
= 11110000
. En prenant le compl\u00e9ment \u00e0 2, on trouve 00001111
, qui vaut 15. Le nombre 11110001
repr\u00e9sente donc \\(-15\\).
Q2. En binaire sign\u00e9, quel est le plus grand nombre que l'on puisse \u00e9crire sur un octet ?
Correction Le plus grand nombre est 01111111
, soit \\(+127\\).
Q3. Quel est le plus petit nombre ?
Correction Le plus petit nombre est 10000000
. 10000000
- 1
= 01111111
. Le compl\u00e9ment est 10000000
, qui est \u00e9gal \u00e0 128. Donc le nombre minimal est \\(-128\\).
Q4. Au total, combien de nombres diff\u00e9rents peuvent \u00eatre \u00e9crits en binaire sign\u00e9 ?
Correction Il y a 128 nombres n\u00e9gatifs (de \\(-128\\) \u00e0 \\(-1\\)), le nombre 0, puis 127 nombres positifs (de 1 \u00e0 127). Il y a donc 256 nombres au total, comme en binaire non sign\u00e9.
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#4-le-codage-des-entiers-une-source-intarissable-derreurs","title":"4. Le codage des entiers, une source intarissable d'erreurs...","text":""},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#41-le-vol-501-dariane-5","title":"4.1 Le vol 501 d'Ariane 5","text":"Le 04 juin 1996, le vol inaugural d'Ariane 5 a malheureusement fini dans une gerbe d'\u00e9tincelles.
En cause : un code pr\u00e9vu pour Ariane 4 avait \u00e9t\u00e9 gard\u00e9 pour le nouveau mod\u00e8le Ariane 5. Dans ce \u00abvieux\u00bb code, une donn\u00e9e issue d'un capteur (le capteur de vitesse horizontale) \u00e9tait cod\u00e9 sur 8 bits. La valeur maximale acceptable de cette donn\u00e9e \u00e9tait donc 255.
Or, Ariane 5 \u00e9tant beaucoup plus puissante, le capteur de vitesse horizontale a renvoy\u00e9, au bout de 30 secondes, la valeur 300 : cette valeur a provoqu\u00e9 un d\u00e9passement des 8 bits pr\u00e9vus et a donn\u00e9 un r\u00e9sultat absurde. L'ordinateur de bord a cru que la fus\u00e9e \u00e9tait en train de se coucher et a violemment orient\u00e9 les tuy\u00e8res de propulsion pour redresser Ariane 5, alors que celle-ci s'\u00e9levait pourtant bien verticalement... Ariane 5 a alors brusquement pivot\u00e9 avant d'exploser.
Cette catastrophe (150 millions d'euros et des ann\u00e9es de travail perdus) a fait prendre conscience \u00e0 la communaut\u00e9 scientifique de l'importance de faire des tests logiciels toujours plus pouss\u00e9s : ce n'est pas parce qu'un code marche dans un environnement donn\u00e9 qu'il marchera de la m\u00eame mani\u00e8re dans d'autres conditions...
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#42-le-bug-de-lannee-2038","title":"4.2 Le bug de l'ann\u00e9e 2038","text":"Expliquons ce (superbe) gif issu de la page Wikipedia Bug de l'an 2038.
Lorsqu'on demande \u00e0 Python l'heure qu'il est, par la fonction time()
du module time
, voici ce qu'il r\u00e9pond :
>>> import time\n>>> time.time()\n1653855138.398177\n
Il nous renvoie le nombre de secondes \u00e9coul\u00e9es depuis le 1er janvier 1970 \u00e0 00h00. On appelle cela l'heure POSIX ou l'heure UNIX l'heure UNIX. Au 29 mai 2022, il s'en donc \u00e9coul\u00e9 environ 1,6 milliards.
Dans beaucoup de syst\u00e8mes informatiques, ce nombre de secondes est cod\u00e9 par un entier sign\u00e9 sur 32 bits. Le nombre maximum de secondes qui peut \u00eatre repr\u00e9sent\u00e9 est donc 01111111 11111111 11111111 11111111
>>> int('01111111111111111111111111111111', 2)\n2147483647\n
Ce nombre repr\u00e9sente un peu plus de 2 milliards de secondes... En les comptant depuis le 01/01/1970 00h00m00s, on arrive au 19/01/2038 \u00e0 03h14m07s.
\u00c0 la seconde d'apr\u00e8s, la repres\u00e9ntation binaire du temps sera 10000000 00000000 00000000 00000000
, qui sera interpr\u00e9t\u00e9 comme le nombre n\u00e9gatif \u22122147483648, et qui ram\u00e8nera donc les horloges au 13 d\u00e9cembre 1901...
Vous pourrez lire sur la page Wikipedia cit\u00e9e plus haut plus d'informations sur ce probl\u00e8me.
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/","title":"2.8 Codage des non-entiers","text":"Le principe est l'extension du syst\u00e8me d\u00e9j\u00e0 rencontr\u00e9 pour les nombres entiers. La partie d\u00e9cimale (\u00e0 droite de la virgule) correspondra aux puissances n\u00e9gatives de 2.
... 8 4 2 1 0.5 0.25 0.125 ... ... \\(2^3\\) \\(2^2\\) \\(2^1\\) \\(2^0\\) \\(2^{-1}\\) \\(2^{-2}\\) \\(2^{-3}\\) ... ... 0 1 1 0, 1 0 1 ... Exemple : \\(110,101_2=1 \\times 2^2 + 1 \\times2^1 +0 \\times 2^0 + 1 \\times 2^{-1} +0 \\times 2^{-2}+1 \\times 2^{-2} =4+2+0,5+0,125=6,625\\)
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#1-tentatives-de-conversion","title":"1. Tentatives de conversion","text":""},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#11-theoreme-de-decomposition-en-puissances-de-2","title":"1.1 Th\u00e9or\u00e8me de d\u00e9composition en puissances de 2","text":"Tout commence bien, avec un r\u00e9sultat math\u00e9matique rassurant : tous les nombres r\u00e9els peuvent s'\u00e9crire comme une somme de puissances de 2 (puissances positives et n\u00e9gatives).
Th\u00e9or\u00e8me
Pour tout r\u00e9el \\(x \\in \\mathbb{R}^+\\), il existe \\(p \\in \\mathbb{N}\\) et \\((a_p,a_{p-1},...,a_0,a_{-1},a_{-2},...)\\) tels que \\(x = \\sum_{i=0}^pa_i2^i+\\sum_{i=1}^{+\\infty}a_{-i}2^{-i}\\)
\u00c9crire un nombre en binaire revient \u00e0 calculer les coefficients \\(a_k\\) (ils sont \u00e9gaux \u00e0 0 ou 1). Il y en a un nombre fini pour la partie enti\u00e8re, mais un nombre potentiellement infini pour la partie d\u00e9cimale.
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#12-methode-de-conversion","title":"1.2 M\u00e9thode de conversion","text":"Consid\u00e9rons le nombre \\(3,6875\\). Il se d\u00e9compose en une partie enti\u00e8re (3) et une partie d\u00e9cimale (\\(0,6875\\)).
- partie enti\u00e8re : \\(3=11_2\\)
- partie d\u00e9cimale : la conversion de \\(0,6875\\) se fait en plusieurs \u00e9tapes. \\(0,6875 \\times 2 = \\textbf{1},375\\) \\(0,375 \\times 2 = \\textbf{0},75\\) \\(0,75 \\times 2 = \\textbf{1},5\\) \\(0,5 \\times 2 = \\textbf{1}\\)
On prend ensuite le chiffre des unit\u00e9s de tous les nombres obtenus : 1011
Donc \\(3,6875=11,1011_2\\)
Exercice 1
Donner l'\u00e9criture binaire de 20,875.
Correction - partie enti\u00e8re : \\(20 = 10100_2\\)
- partie d\u00e9cimale :
- \\(0,875 \\times 2 = \\textbf{1},75\\)
- \\(0,75 \\times 2 = \\textbf{1},5\\)
- \\(0,5 \\times 2 = \\textbf{1}\\)
Donc \\(20,875=10100,111_2\\)
Exercice 2
Donner l'\u00e9criture binaire de 0,2.
Correction - partie enti\u00e8re : \\(0 = 0_2\\)
- partie d\u00e9cimale :
- \\(0,2 \\times 2 = \\textbf{0},4\\)
- \\(0,4 \\times 2 = \\textbf{0},8\\)
- \\(0,8 \\times 2 = \\textbf{1},6\\)
- \\(0,6 \\times 2 = \\textbf{1},2\\)
- \\(0,2 \\times 2 = \\textbf{0},4\\)
- et cela continue...
Le nombre 0,2 n'admet pas d'\u00e9criture binaire finie.
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#conclusion","title":"Conclusion","text":"Certains nombres n'admettent pas une \u00e9criture binaire finie. Or la m\u00e9moire d'un ordinateur, quelqu'il soit, est toujours finie. Certains nombres ne peuvent donc pas \u00eatre repr\u00e9sent\u00e9s correctement en machine : c'est une impossibilit\u00e9 th\u00e9orique. Cela am\u00e8ne \u00e0 des comportements \u00e9tranges :
>>> 0.1 + 0.2\n0.30000000000000004\n
Remarque : parmi les nombres d\u00e9cimaux \u00e0 un chiffre apr\u00e8s la virgule (0,1 0,2 0,3 ...) seul 0,5 admet une \u00e9criture binaire finie ! Tous les autres ont une repr\u00e9sentation en machine qui n'en donne qu'une valeur approch\u00e9e. Vous pouvez avoir un aper\u00e7u de la repr\u00e9sentation des nombres flottants sur ce site.
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#2-consequences-la-difficile-manipulation-des-flottants","title":"2. Cons\u00e9quences : la difficile manipulation des flottants","text":"En python, les nombres non entiers sont du type float.
>>> type(0.1)\n<class 'float'>\n
Ces flottants (traduction fran\u00e7aise) sont \u00e0 manipuler avec une extr\u00eame pr\u00e9caution. Il faut garder en t\u00eate que les calculs sont potentiellement faux, du moins impr\u00e9cis, lorsque des flottants interviennent.
>>> 0.5 - 0.2 - 0.2 - 0.1\n-2.7755575615628914e-17\n
En 1991, durant la Guerre du Golfe, un missile anti-missile am\u00e9ricain a rat\u00e9 sa cible de 500 m\u00e8tres car son ordinateur interne \u00e9mettait un signal toutes les 0.1 secondes. Au bout de 100 heures de fonctionnement, l'approximation du nombre flottant 0.1 a conduit \u00e0 un d\u00e9calage de 0,34 secondes, ce qui lui a fait rater sa cible. (source)
Hormis ce cas tragique, est-ce si grave de devoir travailler avec des valeurs approch\u00e9es ? Non, pas vraiment : par exemple, la valeur de Pi utilis\u00e9e par la NASA pour faire ses calculs (g\u00e9n\u00e9ralement tr\u00e8s, tr\u00e8s, tr\u00e8s pr\u00e9cis) est 3.141592653589793
, donc \u00abjuste\u00bb 15 chiffres apr\u00e8s la virgule. (source)
Un bug int\u00e9ressant : on a enfin compris pourquoi dans Minecraft les barques tombant d'une certaine hauteur cassaient, et pas d'autres. La raison ? Les nombres flottants bien s\u00fbr ! (vid\u00e9o)
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#3-comment-faire-des-tests-degalite-sur-les-flottants","title":"3. Comment faire des tests d'egalit\u00e9 sur les flottants ?","text":"Premi\u00e8re r\u00e9ponse : ON N'EN FAIT PAS.
Si a
et b
sont deux flottants, le test classique
if a == b :\n print(\"a et b sont \u00e9gaux\")\n
a de grandes chances d'\u00e9chouer :
Le script
a = 0.1\nb = 0.3 - 0.2\nif a == b :\n print(\"a et b sont \u00e9gaux\")\nelse :\n print(\"a et b sont diff\u00e9rents\")\n
renverra
a et b sont diff\u00e9rents\n
Si vraiment un test d'\u00e9galit\u00e9 est n\u00e9cessaire, on ne va pas tester l'\u00e9galit\u00e9 entre a
et b
mais leur proximit\u00e9, gr\u00e2ce \u00e0 la valeur absolue de leur diff\u00e9rence.
La fonction abs(a-b)
renvoie un nombre positif \u00e9gal \u00e0 la distance entre a
et b
. Il faut alors d\u00e9cider d'un \u00e9cart minimal e
en dessous duquel on consid\u00e8rera que a
et b
sont \u00e9gaux.
Le script
a = 0.1\nb = 0.3 - 0.2\ne = 10**(-12)\nif abs(a - b) < e :\n print(\"a et b sont \u00e9gaux\")\nelse :\n print(\"a et b sont diff\u00e9rents\")\n
renverra
a et b sont \u00e9gaux\n
car notre code les aura consid\u00e9r\u00e9s comme \u00absuffisamment proches\u00bb. Exercice 3
On consid\u00e8re la fonction \\(f(x)=x^3-6x+2\\). L'\u00e9quation \\(f(x)=1\\) admet une solution unique dans l'intervalle \\([0;1]\\). Trouver une valeur approch\u00e9e de cette solution \u00e0 \\(10^{-5}\\) pr\u00e8s. On prendra e
\\(=0,001\\).
Correction def f(x):\n return x**3 - 6*x + 2\n\ne = 10**(-3)\na = 0\nwhile abs(f(a) - 1 ) > e :\n a += 10**(-5)\nprint(a)\n
"},{"location":"T2_Representation_des_donnees/2.9_Chaines_caracteres/cours/","title":"2.9 Cha\u00eenes de caract\u00e8res","text":"La manipulation des cha\u00eenes de caract\u00e8res n'est pas au programme, mais quelques astuces sont tr\u00e8s utiles \u00e0 conna\u00eetre.
"},{"location":"T3_Architecture_materielle/sommaire/","title":"Th\u00e8me 3 : Architecture mat\u00e9rielle","text":" - Microbit
- Architecture Von Neumann
- Architecture r\u00e9seau
- Protocoles de communication dans un r\u00e9seau
- D\u00e9couverte des commandes Linux
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/","title":"Micro:bit","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#0-presentation-de-la-carte-bbc-microbit","title":"0. Pr\u00e9sentation de la carte BBC micro:bit","text":"BBC micro:bit est une carte \u00e0 microcontr\u00f4leur con\u00e7ue en 2015 au Royaume-Uni pour d\u00e9velopper l'apprentissage de l'algorithmique et de la programmation.
La carte micro:bit dispose des sp\u00e9cificit\u00e9s techniques suivantes :
- 25 LEDs programmables individuellement
- 2 boutons programmables
- Broches de connexion
- Capteurs de lumi\u00e8re et de temp\u00e9rature
- Capteurs de mouvements (acc\u00e9l\u00e9rom\u00e8tre et boussole)
- Communication sans fil, via Radio et Bluetooth
- Interface USB
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#1-hello-world-virtuellement-ou-irl","title":"1. \"Hello world !\", virtuellement ou IRL...","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#11-a-distance-pas-de-microbit-le-simulateur-est-la","title":"1.1 \u00c0 distance ? Pas de micro:bit ? le simulateur est l\u00e0 !","text":"Rendez-vous sur la page https://python.microbit.org/v/3
Effacez le code existant et collez-le code ci-dessous :
from microbit import *\n\nwhile True:\n display.scroll('Hello, World!')\n display.show(Image.HEART)\n sleep(2000)\n
Cliquez sur le bouton Play de la micro:bit virtuelle. C'est parti !
Pour \u00e9viter des erreurs, fermez la fen\u00eatre de droite (le simulateur) \u00e0 chaque fois que vous modifiez votre code de la partie gauche.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#12-avec-une-microbit-reelle","title":"1.2 Avec une micro:bit r\u00e9elle","text":"La manipulation suivante ne marche que sur le navigateur Google Chrome.
- Branchez la carte sur un port USB. Un lecteur MICROBIT apparait dans les p\u00e9riph\u00e9riques USB.
- Rendez-vous sur l'adresse https://python.microbit.org/v/3
- Modifiez le code pr\u00e9sent puis cliquez sur le bouton Play de la micro:bit virtuelle.
- Cliquer sur le bouton violet \u00abSend to micro:bit\u00bb.
Cette proc\u00e9dure est \u00e0 r\u00e9p\u00e9ter \u00e0 chaque nouveau code.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#2-decouverte-des-fonctionnalites","title":"2. D\u00e9couverte des fonctionnalit\u00e9s","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#21-commandes-de-base-de-lafficheur-matrice-de-5x5-leds","title":"2.1 Commandes de base de l'afficheur, matrice de 5x5 LEDs","text":"voir vid\u00e9o explicative (en anglais)
LED signifie Light Emitting Diode, Diode \u00e9lectroluminescente. La carte micro:bit en dispose de 25, toutes programmables individuellement, ce qui permet d'afficher du texte, des nombres et des images.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#211-afficher-un-texte-defilant-displayscrollstring-delay400","title":"2.1.1 Afficher un texte \"d\u00e9filant\" display.scroll(string, delay=400)
","text":"from microbit import *\ndisplay.scroll(\"NSI\")\n
La premi\u00e8re ligne de ce programme importe la biblioth\u00e8que de fonctions micro:bit. La deuxi\u00e8me ligne fait d\u00e9filer un message \u00e0 l\u2019\u00e9cran. Cela n'arrive qu'une seule fois.
La vitesse de d\u00e9filement peut \u00eatre ralentie ou acc\u00e9l\u00e9r\u00e9e \u00e0 l'aide du param\u00e8tre delay
. L'unit\u00e9 est la milliseconde.
from microbit import *\ndisplay.scroll(\"mauriac\", delay=20)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#212-afficher-une-image-displayshowimage","title":"2.1.2 Afficher une \"image\" display.show(image)
","text":"Ex\u00e9cuter le programme suivant:
from microbit import *\ndisplay.show(Image.SAD)\n
Liste des images disponibles Image.HEART\nImage.HEART_SMALL\nImage.HAPPY\nImage.SMILE\nImage.SAD\nImage.CONFUSED\nImage.ANGRY\nImage.ASLEEP\nImage.SURPRISED\nImage.SILLY\nImage.FABULOUS\nImage.MEH\nImage.YES\nImage.NO\nImage.CLOCK12\nImage.CLOCK11\nImage.CLOCK10\nImage.CLOCK9\nImage.CLOCK8\nImage.CLOCK7\nImage.CLOCK6\nImage.CLOCK5\nImage.CLOCK4\nImage.CLOCK3\nImage.CLOCK2\nImage.CLOCK1\nImage.ARROW_N\nImage.ARROW_NE\nImage.ARROW_E\nImage.ARROW_SE\nImage.ARROW_S\nImage.ARROW_SW\nImage.ARROW_W\nImage.ARROW_NW\nImage.TRIANGLE\nImage.TRIANGLE_LEFT\nImage.CHESSBOARD\nImage.DIAMOND\nImage.DIAMOND_SMALL\nImage.SQUARE\nImage.SQUARE_SMALL\nImage.RABBIT\nImage.COW\nImage.MUSIC_CROTCHET\nImage.MUSIC_QUAVER\nImage.MUSIC_QUAVERS\nImage.PITCHFORK\nImage.XMAS\nImage.PACMAN\nImage.TARGET\nImage.TSHIRT\nImage.ROLLERSKATE\nImage.DUCK\nImage.HOUSE\nImage.TORTOISE\nImage.BUTTERFLY\nImage.STICKFIGURE\nImage.GHOST\nImage.SWORD\nImage.GIRAFFE\nImage.SKULL\nImage.UMBRELLA\nImage.SNAKE\n
Exercice 1
Cr\u00e9er un code qui permet d'afficher la totalit\u00e9 des images, pendant une demi-seconde chacune (gr\u00e2ce \u00e0 l'instruction sleep(500)
). On utilisera la liste
lst = [Image.HEART, Image.HEART_SMALL, Image.HAPPY, Image.SMILE,\n Image.SAD, Image.CONFUSED, Image.ANGRY, Image.ASLEEP, Image.SURPRISED, Image.SILLY,\n Image.FABULOUS, Image.MEH, Image.YES, Image.NO, Image.CLOCK12,\n Image.CLOCK11, Image.CLOCK10, Image.CLOCK9, Image.CLOCK8, Image.CLOCK7,\n Image.CLOCK6, Image.CLOCK5, Image.CLOCK4, Image.CLOCK3, Image.CLOCK2,\n Image.CLOCK1, Image.ARROW_N, Image.ARROW_NE, Image.ARROW_E, Image.ARROW_SE,\n Image.ARROW_S, Image.ARROW_SW, Image.ARROW_W, Image.ARROW_NW, Image.TRIANGLE,\n Image.TRIANGLE_LEFT, Image.CHESSBOARD, Image.DIAMOND, Image.DIAMOND_SMALL, Image.SQUARE,\n Image.SQUARE_SMALL, Image.RABBIT, Image.COW, Image.MUSIC_CROTCHET, Image.MUSIC_QUAVER,\n Image.MUSIC_QUAVERS, Image.PITCHFORK, Image.XMAS, Image.PACMAN, Image.TARGET, Image.TSHIRT,\n Image.ROLLERSKATE, Image.DUCK, Image.HOUSE, Image.TORTOISE, Image.BUTTERFLY, Image.STICKFIGURE,\n Image.GHOST, Image.SWORD, Image.GIRAFFE, Image.SKULL, Image.UMBRELLA, Image.SNAKE]\n
Correction from microbit import *\n\nlst = [Image.HEART, Image.HEART_SMALL, Image.HAPPY, Image.SMILE,\n Image.SAD, Image.CONFUSED, Image.ANGRY, Image.ASLEEP, Image.SURPRISED, Image.SILLY,\n Image.FABULOUS, Image.MEH, Image.YES, Image.NO, Image.CLOCK12,\n Image.CLOCK11, Image.CLOCK10, Image.CLOCK9, Image.CLOCK8, Image.CLOCK7,\n Image.CLOCK6, Image.CLOCK5, Image.CLOCK4, Image.CLOCK3, Image.CLOCK2,\n Image.CLOCK1, Image.ARROW_N, Image.ARROW_NE, Image.ARROW_E, Image.ARROW_SE,\n Image.ARROW_S, Image.ARROW_SW, Image.ARROW_W, Image.ARROW_NW, Image.TRIANGLE,\n Image.TRIANGLE_LEFT, Image.CHESSBOARD, Image.DIAMOND, Image.DIAMOND_SMALL, Image.SQUARE,\n Image.SQUARE_SMALL, Image.RABBIT, Image.COW, Image.MUSIC_CROTCHET, Image.MUSIC_QUAVER,\n Image.MUSIC_QUAVERS, Image.PITCHFORK, Image.XMAS, Image.PACMAN, Image.TARGET, Image.TSHIRT,\n Image.ROLLERSKATE, Image.DUCK, Image.HOUSE, Image.TORTOISE, Image.BUTTERFLY, Image.STICKFIGURE,\n Image.GHOST, Image.SWORD, Image.GIRAFFE, Image.SKULL, Image.UMBRELLA, Image.SNAKE]\n\nfor img in lst:\n display.show(img)\n sleep(500)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#creer-sa-propre-image","title":"Cr\u00e9er sa propre image","text":"Chaque pixel LED sur l\u2019affichage physique peut prendre une parmi dix valeurs. Si un pixel prend la valeur 0 c\u2019est qu\u2019il est \u00e9teint. Litt\u00e9ralement, il a une luminosit\u00e9 de z\u00e9ro. En revanche, s\u2019il prend la valeur 9 il est \u00e0 la luminosit\u00e9 maximale. Les valeurs de 1 \u00e0 8 repr\u00e9sentent des niveaux de luminosit\u00e9 entre \u00e9teint (0) et \u00ab au maximum \u00bb (9).
from microbit import *\n\nbateau = Image(\"05050:\"\n \"05050:\"\n \"05050:\"\n \"99999:\"\n \"09990\")\n\ndisplay.show(bateau)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#213-les-pixels-displayset_pixelx-y-val","title":"2.1.3 Les pixels (display.set_pixel(x, y, val)
)","text":"Vous pouvez r\u00e9gler la luminosit\u00e9 des pixels de l'affichage individuellement de 0 (d\u00e9sactiv\u00e9) \u00e0 9 (luminosit\u00e9 maximale). Pour des informations sur les coordonn\u00e9es de l'affichage, voir le guide pour matrice \u00e0 LED.
Ex\u00e9cuter le programme suivant:
from microbit import *\ndisplay.set_pixel(1, 4, 9)\n
Exercice 2
Faire clignoter le pixel central.
Correction from microbit import *\n\nwhile True:\n display.set_pixel(2, 2, 9)\n sleep(200)\n display.set_pixel(2, 2, 0)\n sleep(200)\n
Exercice 3
Faire afficher en boucle un pixel al\u00e9atoire pendant 200 ms.
Pour obtenir un entier pseudo-al\u00e9atoire, on utilisera la fonction randint
du module random
. Par exemple, l'instruction randint(2, 8)
va renvoyer un nombre (pseudo-)al\u00e9atoire entre 2 et 8 inclus.
On pourra aussi utiliser l'instruction display.clear()
pour \u00e9teindre tout l'affichage.
Correction from microbit import *\nfrom random import randint\n\nwhile True:\n x = randint(0,4)\n y = randint(0,4)\n display.set_pixel(x, y, 9)\n sleep(200)\n display.clear()\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#24-les-entrees-boutons-a-b-et-ab-programmation-evenementielle-video-explicative","title":"2.4 Les entr\u00e9es boutons A, B et A+B - programmation \u00e9v\u00e9nementielle (vid\u00e9o explicative)","text":"Il y a deux boutons sur la face avant du micro:bit (\u00e9tiquet\u00e9s A et B). On peut d\u00e9tecter quand ces boutons sont press\u00e9s, ce qui permet de d\u00e9clencher des instructions sur l'appareil.
Exemples avec le boutton A:
button_a.is_pressed()
: renvoie True si le bouton sp\u00e9cifi\u00e9 est actuellement enfonc\u00e9 et False sinon. button_a.was_pressed()
: renvoie True ou False pour indiquer si le bouton a \u00e9t\u00e9 appuy\u00e9 depuis le d\u00e9marrage de l'appareil ou la derni\u00e8re fois que cette m\u00e9thode a \u00e9t\u00e9 appel\u00e9e.
Exemple : Essayer le programme suivant qui fait d\u00e9filer le texte \"NSI\" ind\u00e9finiment. D\u00e8s qu'un bouton est press\u00e9, on sort de la boucle break
et le programme s'ach\u00e8ve.
from microbit import *\nwhile True:\n display.scroll(\"NSI\")\n sleep(200)\n if button_a.was_pressed():\n break\ndisplay.clear()\ndisplay.show(Image.SAD)\n
Exercice 4
Cr\u00e9er le code permettant de basculer d'un visage triste \u00e0 un visage heureux suivant qu'on appuie sur A ou sur B.
Correction from microbit import *\nwhile True:\n if button_a.was_pressed():\n display.show(Image.SAD)\n if button_b.was_pressed():\n display.show(Image.HAPPY)\n
Exercice 5
Cr\u00e9er le code permettant de d\u00e9placer un point vers la gauche ou vers la droite en appuyant sur A ou sur B.
Exercice 6
M\u00eame \u00e9nonc\u00e9 que l'exercice pr\u00e9c\u00e9dent, mais en faisant parcourir tout l'\u00e9cran au pixel :
- si on sort \u00e0 droite, on se d\u00e9cale d'une ligne vers le bas et on revient tout \u00e0 gauche.
- si on sort \u00e0 gauche, on se d\u00e9cale d'une ligne vers le haut et on revient tout \u00e0 droite.
- arriv\u00e9 tout en bas \u00e0 droite, on r\u00e9appara\u00eet en haut \u00e0 gauche (et r\u00e9ciproquement).
Exercice 7
On veut cr\u00e9er le jeu suivant :
- au d\u00e9marrage, un pixel al\u00e9atoire est plac\u00e9 sur l'\u00e9cran.
- il faut ensuite se d\u00e9placer un point vers la gauche ou vers la droite en appuyant sur A ou sur B.
- lorsque qu'on a rejoint le point al\u00e9atoire, un emoji HAPPY apparait.
Exercice 8
Rajout d'un temps limit\u00e9
La fonction tick_ms
du module utime
renvoie le nombre de millisecondes \u00e9coul\u00e9es depuis le d\u00e9marrage de la carte. Pour mesurer le temps \u00e9coul\u00e9 dans un programme, on fixe le temps du d\u00e9but du programme dans une variable t0
. Il suffit d'observer ensuite la valeur de tick_ms() - t0
pour savoir combien de temps (en millisecondes) s'est \u00e9coul\u00e9 depuis le d\u00e9but du programme.
Exemple (\u00e0 ex\u00e9cuter pour comprendre !) :
from microbit import *\nfrom utime import *\n\ndisplay.show(Image.HAPPY)\nt0 = ticks_ms()\n\nwhile True:\n if ticks_ms() - t0 > 5000:\n display.show(Image.SAD)\n break\n
Reprendre l'exercice pr\u00e9c\u00e9dent en rajoutant une difficult\u00e9 suppl\u00e9mentaire avec un temps limit\u00e9.
Exercice 9
Cr\u00e9er un jeu de Pierre-Feuille-Ciseaux qui se d\u00e9clenchera lorsqu'on secoue la Microbit. (Vous pouvez cr\u00e9er vos propres images de pierre, de feuille et de ciseaux)
La d\u00e9tection du \"secouage\" de la carte se fera avec l'instruction suivante :
if accelerometer.was_gesture('shake'):\n ...\n
Correction from microbit import *\nfrom random import randint\n\npierre = Image('09990:'\n '09009:'\n '09990:'\n '09000:'\n '09000')\n\nfeuille = Image('09999:'\n '09000:'\n '09990:'\n '09000:'\n '09000')\n\nciseaux = Image('00999:'\n '09000:'\n '09000:'\n '09000:'\n '00999')\n\n\nwhile True:\n if accelerometer.was_gesture('shake'):\n v = randint(1,3)\n if v == 1:\n display.show(pierre)\n if v == 2:\n display.show(feuille)\n if v == 3:\n display.show(ciseaux)\n
Exercice 10
En utilisant les fonctions accelerometer.get_x()
et accelerometer.get_y()
de l'acc\u00e9l\u00e9rom\u00e8tre, cr\u00e9er un code qui allumera la LED du centre lorsque la carte est \u00e0 l'horizontale, puis qui fera bouger cette LED en fonction de l'inclinaison de la carte.
from microbit import *\n\ndef move(x, y):\n incx = accelerometer.get_x()\n if incx > 500:\n x += 1\n x = min(..., ...)\n if incx < -500:\n x -= 1\n x = max(..., ...)\n incy = accelerometer.get_y()\n if incy > 500:\n y += 1\n y = min(..., ...)\n if incy < -500:\n y -= 1\n y = max(..., ...)\n return x, y\n\nx = 2\ny = 2\nwhile True:\n display.clear()\n ..., ... = move(..., ...)\n display.set_pixel(..., ..., 9)\n sleep(200) \n
Exercice 11
Communication radio
Voici un code proposant une communication radio entre deux cartes. Inspirez-vous de ce code pour (par exemple) faire un \u00abvrai\u00bb Pierre-Feuille-Ciseaux entre deux cartes.
from microbit import *\nimport radio\n\nradio.on()\nradio.config(channel=12)\nradio.config(power=7)\n\nwhile True:\n message = radio.receive()\n if message:\n if message == 'yes':\n display.show(Image.YES)\n sleep(500)\n display.clear()\n elif message == 'no':\n display.show(Image.NO)\n sleep(500)\n display.clear()\n if button_a.was_pressed():\n radio.send('yes')\n display.show(Image.YES)\n sleep(500)\n display.clear()\n if button_b.was_pressed():\n radio.send('no')\n display.show(Image.NO)\n sleep(500)\n display.clear()\n
Plus de renseignements ici
Exercice 12
En utilisant l'exercice 10 et la communication radio, faire \u00abpasser\u00bb une led d'une carte \u00e0 l'autre en inclinant la carte.
video "},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/","title":"3.1 Microbit","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#0-presentation-de-la-carte-bbc-microbit","title":"0. Pr\u00e9sentation de la carte BBC micro:bit","text":"BBC micro:bit est une carte \u00e0 microcontr\u00f4leur con\u00e7ue en 2015 au Royaume-Uni pour d\u00e9velopper l'apprentissage de l'algorithmique et de la programmation.
La carte micro:bit dispose des sp\u00e9cificit\u00e9s techniques suivantes :
- 25 LEDs programmables individuellement
- 2 boutons programmables
- Broches de connexion
- Capteurs de lumi\u00e8re et de temp\u00e9rature
- Capteurs de mouvements (acc\u00e9l\u00e9rom\u00e8tre et boussole)
- Communication sans fil, via Radio et Bluetooth
- Interface USB
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#1-hello-world-virtuellement-ou-irl","title":"1. \"Hello world !\", virtuellement ou IRL...","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#11-a-distance-pas-de-microbit-le-simulateur-est-la","title":"1.1 \u00c0 distance ? Pas de micro:bit ? le simulateur est l\u00e0 !","text":"Rendez-vous sur la page https://create.withcode.uk/
Effacez le code existant et collez-le code ci-dessous :
from microbit import *\n\nwhile True:\n display.scroll('Hello, World!')\n display.show(Image.HEART)\n sleep(2000)\n
Cliquez sur le triangle vert en bas \u00e0 droite. C'est parti !
Pour \u00e9viter des erreurs, fermez la fen\u00eatre de droite (le simulateur) \u00e0 chaque fois que vous modifiez votre code de la partie gauche.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#12-avec-une-microbit-reelle","title":"1.2 Avec une micro:bit r\u00e9elle","text":" - Branchez la carte sur un port USB. Un lecteur MICROBIT apparait dans les p\u00e9riph\u00e9riques USB.
- Rendez-vous sur l'adresse https://create.withcode.uk/
- Modifiez le code pr\u00e9sent puis cliquez sur la fl\u00e8che verte.
- Vous pouvez t\u00e9l\u00e9charger le fichier .hex en cliquant sur Download HEX.
- Transf\u00e9rez (par copier-coller, ou \"envoyer vers\") ce fichier .hex dans votre lecteur micro:bit.
Cette proc\u00e9dure est \u00e0 r\u00e9peter \u00e0 chaque nouveau code.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#2-decouverte-des-fonctionnalites","title":"2. D\u00e9couverte des fonctionnalit\u00e9s","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#21-commandes-de-base-de-lafficheur-matrice-de-5x5-leds","title":"2.1 Commandes de base de l'afficheur, matrice de 5x5 LEDs","text":"voir vid\u00e9o explicative (en anglais)
LED signifie Light Emitting Diode, Diode \u00e9lectroluminescente. La carte micro:bit en dispose de 25, toutes programmables individuellement, ce qui permet d'afficher du texte, des nombres et des images.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#211-afficher-un-texte-defilant-displayscrollstring-delay400","title":"2.1.1 Afficher un texte \"d\u00e9filant\" display.scroll(string, delay=400)
","text":"from microbit import *\ndisplay.scroll(\"NSI\")\n
La premi\u00e8re ligne de ce programme importe la biblioth\u00e8que de fonctions micro:bit. La deuxi\u00e8me ligne fait d\u00e9filer un message \u00e0 l\u2019\u00e9cran. Cela n'arrive qu'une seule fois.
La vitesse de d\u00e9filement peut \u00eatre ralentie ou acc\u00e9l\u00e9r\u00e9e \u00e0 l'aide du param\u00e8tre delay
. L'unit\u00e9 est la milliseconde.
from microbit import *\ndisplay.scroll(\"mauriac\", delay=20)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#212-afficher-une-image-displayshowimage","title":"2.1.2 Afficher une \"image\" display.show(image)
","text":"Ex\u00e9cuter le programme suivant:
from microbit import *\ndisplay.show(Image.SAD)\n
Liste des images disponibles Image.HEART\nImage.HEART_SMALL\nImage.HAPPY\nImage.SMILE\nImage.SAD\nImage.CONFUSED\nImage.ANGRY\nImage.ASLEEP\nImage.SURPRISED\nImage.SILLY\nImage.FABULOUS\nImage.MEH\nImage.YES\nImage.NO\nImage.CLOCK12\nImage.CLOCK11\nImage.CLOCK10\nImage.CLOCK9\nImage.CLOCK8\nImage.CLOCK7\nImage.CLOCK6\nImage.CLOCK5\nImage.CLOCK4\nImage.CLOCK3\nImage.CLOCK2\nImage.CLOCK1\nImage.ARROW_N\nImage.ARROW_NE\nImage.ARROW_E\nImage.ARROW_SE\nImage.ARROW_S\nImage.ARROW_SW\nImage.ARROW_W\nImage.ARROW_NW\nImage.TRIANGLE\nImage.TRIANGLE_LEFT\nImage.CHESSBOARD\nImage.DIAMOND\nImage.DIAMOND_SMALL\nImage.SQUARE\nImage.SQUARE_SMALL\nImage.RABBIT\nImage.COW\nImage.MUSIC_CROTCHET\nImage.MUSIC_QUAVER\nImage.MUSIC_QUAVERS\nImage.PITCHFORK\nImage.XMAS\nImage.PACMAN\nImage.TARGET\nImage.TSHIRT\nImage.ROLLERSKATE\nImage.DUCK\nImage.HOUSE\nImage.TORTOISE\nImage.BUTTERFLY\nImage.STICKFIGURE\nImage.GHOST\nImage.SWORD\nImage.GIRAFFE\nImage.SKULL\nImage.UMBRELLA\nImage.SNAKE\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#creer-sa-propre-image","title":"Cr\u00e9er sa propre image","text":"Chaque pixel LED sur l\u2019affichage physique peut prendre une parmi dix valeurs. Si un pixel prend la valeur 0 c\u2019est qu\u2019il est \u00e9teint. Litt\u00e9ralement, il a une luminosit\u00e9 de z\u00e9ro. En revanche, s\u2019il prend la valeur 9 il est \u00e0 la luminosit\u00e9 maximale. Les valeurs de 1 \u00e0 8 repr\u00e9sentent des niveaux de luminosit\u00e9 entre \u00e9teint (0) et \u00ab au maximum \u00bb (9).
from microbit import *\n\nbateau = Image(\"05050:\"\n \"05050:\"\n \"05050:\"\n \"99999:\"\n \"09990\")\n\ndisplay.show(bateau)\n
Comment dessiner une image? Chaque ligne de l\u2019affichage physique est repr\u00e9sent\u00e9e par une ligne de nombres se terminant par :
et entour\u00e9e de guillemets doubles \"
. Chaque nombre indique une luminosit\u00e9. Il y a cinq lignes de cinq nombres donc il est possible de sp\u00e9cifier la luminosit\u00e9 individuelle de chacune des cinq LED sur chacune des cinq lignes sur l\u2019affichage physique. C\u2019est ainsi que l'on cr\u00e9e une image.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#213-les-pixels-displayset_pixelx-y-val","title":"2.1.3 Les pixels (display.set_pixel(x, y, val)
)","text":"Vous pouvez r\u00e9gler la luminosit\u00e9 des pixels de l'affichage individuellement de 0 (d\u00e9sactiv\u00e9) \u00e0 9 (luminosit\u00e9 maximale). Pour des informations sur les coordonn\u00e9es de l'affichage, voir le guide pour matrice \u00e0 LED.
Ex\u00e9cuter le programme suivant:
from microbit import *\ndisplay.set_pixel(1, 4, 9)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#22-boucle-while","title":"2.2 Boucle while
","text":"Le programme suivant utilise une boucle while
pour faire clignoter le pixel central de mani\u00e8re r\u00e9p\u00e9t\u00e9e sur l\u2019\u00e9cran. La boucle while
se r\u00e9p\u00e8te tant que la condition sp\u00e9cifi\u00e9e est vraie (True
). Dans ce cas, nous avons dit que la condition est vraie. Cela cr\u00e9e une boucle infinie.
L'instruction de veille sleep()
provoque la pause du micro:bit pendant un nombre d\u00e9fini de millisecondes choisi entre parenth\u00e8ses.
L'instruction display.clear()
\u00e9teint l'affichage.
Ex\u00e9cuter le programme ci-dessous:
from microbit import *\nwhile True:\n display.set_pixel(2, 2, 9)\n sleep(500)\n display.clear()\n sleep(500)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#avec-un-peu-daleatoire-voir-documentation-sur-le-hasard","title":"Avec un peu d'al\u00e9atoire (voir documentation sur le hasard)","text":"Dans le programme suivant que vous ex\u00e9cuterez, on importe randint
du module random
de MicroPython et on l'utilise pour afficher un pixel au hasard sur la matrice.
from microbit import *\nfrom random import randint\nn=randint(0,4)\np=randint(0,4)\ndisplay.set_pixel(n, p, 9)\n
Tester le programme pr\u00e9c\u00e9dent plusieurs fois de suite. Pour cela, red\u00e9marrer la micro:bit en appuyant sur le bouton RESET
situ\u00e9 \u00e0 l'arri\u00e8re de la carte.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#23-boucle-for","title":"2.3 Boucle for
","text":"Le programme suivant utilise une boucle for
pour faire d\u00e9filer un pixel sur une ligne. Ex\u00e9cutez-le.
from microbit import *\nwhile True:\n for i in range(5):\n display.set_pixel(i,0,9)\n sleep(200)\n display.clear()\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#24-les-entrees-boutons-a-b-et-ab-programmation-evenementielle-video-explicative","title":"2.4 Les entr\u00e9es boutons A, B et A+B - programmation \u00e9v\u00e9nementielle (vid\u00e9o explicative)","text":"Il y a deux boutons sur la face avant du micro:bit (\u00e9tiquet\u00e9s A et B). On peut d\u00e9tecter quand ces boutons sont press\u00e9s, ce qui permet de d\u00e9clencher des instructions sur l'appareil.
Exemples avec le boutton A: - button_a.is_pressed()
: renvoie True si le bouton sp\u00e9cifi\u00e9 est actuellement enfonc\u00e9 et False sinon. - button_a.was_pressed()
: renvoie True ou False pour indiquer si le bouton a \u00e9t\u00e9 appuy\u00e9 depuis le d\u00e9marrage de l'appareil ou la derni\u00e8re fois que cette m\u00e9thode a \u00e9t\u00e9 appel\u00e9e.
Exemple : Essayer le programme suivant qui fait d\u00e9filer le texte \"NSI\" ind\u00e9finiment. On introduit l'instruction conditionnelle if
qui va tester si le bouton A a \u00e9t\u00e9 press\u00e9 (pendant le d\u00e9filement du texte ou pendant la pause), auquel cas le programme s'arr\u00eate en ex\u00e9cutant la commande break
.
from microbit import *\nwhile True:\n display.scroll(\"NSI\")\n sleep(200)\n if button_a.was_pressed():\n break\n
Exercice 1
\u00c9nonc\u00e9Correction Cr\u00e9er le code permettant de basculer d'un visage triste \u00e0 un visage heureux suivant qu'on appuie sur A ou sur B.
from microbit import *\ndisplay.clear()\nwhile True:\n if button_a.was_pressed():\n display.show(Image.SAD)\n if button_b.was_pressed():\n display.show(Image.HAPPY)\n
Exercice 2
\u00c9nonc\u00e9Correction On veut cr\u00e9er le code permettant de d\u00e9placer un point vers la gauche ou vers la droite en appuyant sur A ou sur B.
Compl\u00e9ter le code propos\u00e9 :
from microbit import *\ndisplay.clear()\ni = 12\nwhile True:\n x = ... # \u00e0 compl\u00e9ter\n y = ... # \u00e0 compl\u00e9ter\n display.set_pixel(x,y,9)\n if button_a.was_pressed():\n display.set_pixel(x,y,0)\n i = i - 1\n if i < 0 : \n i = 0\n if button_b.was_pressed():\n display.set_pixel(x,y,0)\n i = i + 1\n if i > 24 :\n i = 24\n
Exercice 3
\u00c9nonc\u00e9Correction Cr\u00e9er le code permettant de faire d\u00e9filer toutes les images disponibles. Bouton B pour passer \u00e0 l'image suivante, bouton A pour revenir \u00e0 l'image pr\u00e9c\u00e9dente.
Compl\u00e9ter le code propos\u00e9 :
from microbit import *\n\nlst = [Image.HEART, Image.HEART_SMALL, Image.HAPPY, Image.SMILE,\n Image.SAD, Image.CONFUSED, Image.ANGRY, Image.ASLEEP, Image.SURPRISED, Image.SILLY,\n Image.FABULOUS, Image.MEH, Image.YES, Image.NO, Image.CLOCK12,\n Image.CLOCK11, Image.CLOCK10, Image.CLOCK9, Image.CLOCK8, Image.CLOCK7,\n Image.CLOCK6, Image.CLOCK5, Image.CLOCK4, Image.CLOCK3, Image.CLOCK2,\n Image.CLOCK1, Image.ARROW_N, Image.ARROW_NE, Image.ARROW_E, Image.ARROW_SE,\n Image.ARROW_S, Image.ARROW_SW, Image.ARROW_W, Image.ARROW_NW, Image.TRIANGLE,\n Image.TRIANGLE_LEFT, Image.CHESSBOARD, Image.DIAMOND, Image.DIAMOND_SMALL, Image.SQUARE,\n Image.SQUARE_SMALL, Image.RABBIT, Image.COW, Image.MUSIC_CROTCHET, Image.MUSIC_QUAVER,\n Image.MUSIC_QUAVERS, Image.PITCHFORK, Image.XMAS, Image.PACMAN, Image.TARGET, Image.TSHIRT,\n Image.ROLLERSKATE, Image.DUCK, Image.HOUSE, Image.TORTOISE, Image.BUTTERFLY, Image.STICKFIGURE,\n Image.GHOST, Image.SWORD, Image.GIRAFFE, Image.SKULL, Image.UMBRELLA, Image.SNAKE]\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#25-capteur-de-lumiere-video","title":"2.5 Capteur de lumi\u00e8re (vid\u00e9o)","text":"En inversant les LEDs d'un \u00e9cran pour devenir un point d'entr\u00e9e, l'\u00e9cran LED devient un capteur de lumi\u00e8re basique, permettant de d\u00e9tecter la luminosit\u00e9 ambiante.
La commande display.read_light_level()
retourne un entier compris entre 0 et 255 repr\u00e9sentant le niveau de lumi\u00e8re.
Exercice : Compl\u00e9ter le programme ci-dessous qui affiche une image de lune si on baisse la luminosit\u00e9 (en recouvrant la carte avec sa main par exemple) et un soleil sinon.
from microbit import *\n\nsoleil = Image(\"90909:\"\n \"09990:\"\n \"99999:\"\n \"09990:\"\n \"90909:\")\n\nlune = Image(\"00999:\"\n \"09990:\"\n \"09900:\"\n \"09990:\"\n \"00999:\")\n\nwhile True:\n if display.read_light_level()> ... : #trouver la bonne valeur (entre 0 et 255)\n display.show(soleil)\n else:\n display.show(...) #trouver la bonne variable\n sleep(10)\n
Prolongement: cr\u00e9er un programme qui affiche le niveau de luminosit\u00e9 et le tester avec la LED d'un t\u00e9l\u00e9phone portable ou une lampe-torche par exemple. Plus la luminosit\u00e9 sera \u00e9lev\u00e9e, plus il y aura de LEDs affich\u00e9es sur la matrice.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#26-capteur-de-temperature-video","title":"2.6 Capteur de temp\u00e9rature (vid\u00e9o)","text":"Le micro:bit n\u2019a pas un capteur de temp\u00e9rature d\u00e9di\u00e9. Au lieu de cela, la temp\u00e9rature fournie est en fait la temp\u00e9rature de la puce de silicium du processeur principal. Comme le processeur chauffe peu en fonctionnement (c'est un processeur ARM \u00e0 grande efficacit\u00e9), sa temp\u00e9rature est une bonne approximation de la temp\u00e9rature ambiante. L'instruction temperature()
renvoie la temp\u00e9rature de la carte micro:bit en degr\u00e9s Celsius.
Exercice : Ecrire un programme qui affiche la temp\u00e9rature (aide: on pourra utiliser l'instruction display.scroll()
; revoir le point 2.1.1).
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#27-accelerometre-video","title":"2.7 Acc\u00e9l\u00e9rom\u00e8tre (vid\u00e9o)","text":"Un acc\u00e9l\u00e9rom\u00e8tre mesure l'acc\u00e9l\u00e9ration de la carte micro:bit, ce composant d\u00e9tecte quand la micro:bit est en mouvement. Il peut aussi d\u00e9tecter d'autres actions (gestes), par exemple quand elle est secou\u00e9e, inclin\u00e9e ou qu'elle tombe.
La carte micro:bit est munie d\u2019un acc\u00e9l\u00e9rom\u00e8tre. Il mesure le mouvement selon trois axes :
- X - l\u2019inclinaison de gauche \u00e0 droite.
- Y - l\u2019inclinaison d\u2019avant en arri\u00e8re.
- Z - le mouvement haut et bas.
Dans l'exemple suivant \u00e0 essayer, l'instruction accelerometer.get_x()
permet de d\u00e9tecter un mouvement de gauche \u00e0 droite en renvoyant un nombre compris entre -1023 et 1023; 0 \u00e9tant la position \"d'\u00e9quilibre\"
#Exemple\nfrom microbit import *\n\nwhile True:\n abscisse = accelerometer.get_x()\n if abscisse > 500:\n display.show(Image.ARROW_E)\n elif abscisse < -500:\n display.show(Image.ARROW_W)\n else:\n display.show(\"-\")\n
Prolongement (secouer les d\u00e9s!):
Exercice 4
\u00c9nonc\u00e9Correction \u00c9crire un programme qui simule un d\u00e9 en affichant une face au hasard lorsque la micro:bit est secou\u00e9e. On pourra utiliser l'instruction accelerometer.is_gesture(shake)
qui teste si la carte est secou\u00e9e. Plus d'informations sur les gestes ici.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#28-boussole","title":"2.8 Boussole","text":"La boussole d\u00e9tecte le champ magn\u00e9tique de la Terre, nous permettant de savoir quelle direction la micro:bit indique. La boussole doit \u00eatre \u00e9talonn\u00e9e avant de pouvoir \u00eatre utilis\u00e9e. Pour cela, on utilise compass.calibrate()
qui ex\u00e9cute un petit jeu: au d\u00e9part, micro:bit fait d\u00e9filer \"Tilt to fill screen\". Ensuite, incliner micro:bit pour d\u00e9placer le point au centre de l\u2019\u00e9cran autour jusqu'\u00e0 ce que vous ayez rempli la totalit\u00e9 de l\u2019\u00e9cran.
La fonction compass.heading()
donne le cap de la boussole sous la forme d'un entier compris entre 0 et 360, repr\u00e9sentant l'angle en degr\u00e9s, dans le sens des aiguilles d'une montre, avec le nord \u00e9gal \u00e0 0.
Exercice : Compl\u00e9ter le programme suivant qui indique le Nord.
from microbit import *\n\ncompass.calibrate()\n\nwhile True:\n if compass.heading() < \"remplir ici\" or compass.heading() > \"remplir ici\":\n display.show(Image.ARROW_N)\n else:\n display.show(Image.DIAMOND_SMALL)\n
Prolongement: Am\u00e9liorer le programme pour que le micro:bit indique \"N\", \"S\", \"E\" et \"O\" en fonction de l'orientation de la boussole.
Autre prolongement: fabriquer une station m\u00e9t\u00e9o qui d\u00e9termine la direction du vent.
Autre prolongement: \u00e9tudier l'intensit\u00e9 du champ magn\u00e9tique autour du p\u00e9riph\u00e9rique (en utilisant la fonction compass.get_field_strength()
). Plus d'informations sur les fonctions \"boussole\" ici.
document bas\u00e9 sur le travail de Thomas Basso, acad\u00e9mie de Polyn\u00e9sie
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/","title":"3.2 Architecture Von Neumann","text":"John Von Neumann (1903-1957) est un math\u00e9maticien et physicien (et bien d'autres choses) am\u00e9ricano-hongrois. Il a le premier th\u00e9oris\u00e9 l'architecture des processeurs, tels qu'ils fonctionnent encore aujourd'hui.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#1-architecture-von-neumann","title":"1. Architecture von Neumann","text":"On distingue 4 zones essentielles :
- le CPU (Central Processing Unit) qui contient lui-m\u00eame :
- l'Unit\u00e9 Arithm\u00e9tique et Logique (UAL) dans laquelle sont effectu\u00e9es les op\u00e9rations de base (addition, multiplication...) Cette zone comporte notamment les registres (peu nombreux, de l'ordre de la dizaine) qui sont les espaces de travail ultra-rapides dans lesquels l'UAL va effectuer ses calculs. Une fois ceux-ci effectu\u00e9s, les valeurs des registres repartent dans la m\u00e9moire.
- l'Unit\u00e9 de contr\u00f4le, qui va s\u00e9quencer les op\u00e9rations. Lorsqu'on parle d'un processeur \u00e0 3 GHz, cela signifie (approximativement) que Unit\u00e9 de Contr\u00f4le va envoyer l'ordre d'une nouvelle op\u00e9ration \u00e0 l'UAL 3 milliards de fois par seconde.
- la m\u00e9moire, qui contient \u00e0 la fois les donn\u00e9es \u00e0 traiter et les instructions du programme. Cette id\u00e9e de stocker au m\u00eame endroit donn\u00e9es et programme est l'id\u00e9e centrale de l'architecture von Neumann.
- les bus de communication (des fils \u00e9lectriques permettant de transporter les donn\u00e9es entre les diff\u00e9rents composants).
- les Entr\u00e9es/Sorties, permettant de g\u00e9rer les informations avec l'ext\u00e9rieur.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#2-activite-1-simulation-dun-programme-en-assembleur","title":"2. Activit\u00e9 1 : simulation d'un programme en assembleur","text":""},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#21-le-programme-que-nous-etudierons","title":"2.1 Le programme que nous \u00e9tudierons","text":"a = 3\nb = 5\nc = a + b\n
Ce programme est ici \u00e9crit en langage Python. Le processeur ne comprend pas ce langage : les instructions doivent lui \u00eatre pass\u00e9es en langage-machine. C'est le r\u00f4le des interpr\u00e9teurs (pour le Python, par exemple) ou des compilateurs (pour le C, par exemple) que de faire le lien entre le langage pratiqu\u00e9 par les humains (Python, C...) et le langage-machine, qui n'est qu'une succession de chiffres binaires.
Par exemple, notre code ci-dessus s'\u00e9crit
01010000 00001111 00011000 00000000\n00000000 00000000 01010000 00111111\n00011100 00000000 00000000 00000000\n01100000 00000011 01000000 00111111\n00100000 00000000 00000000 00000000\n00000000 00000000 00000000 00000000\n00000011 00000000 00000000 00000000\n00000101 00000000 00000000 00000000\n
en langage-machine. Comment a lieu cette transformation ?
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#22-au-plus-proche-de-la-machine-mais-encore-humainement-comprehensible-le-langage-assembleur","title":"2.2 Au plus proche de la machine mais encore humainement compr\u00e9hensible : le langage assembleur","text":"Il existe un langage dit de \"bas-niveau\" (au sens qu'il est plus proche du langage machine qu'un langage de haut-niveau comme le Python) qui permet de passer des instructions directement au processeur : c'est le langage assembleur (ou ASM).
En assembleur, notre programme s'\u00e9crirait (par exemple) :
.pos 0\n mrmovl a, %eax\n mrmovl b, %ebx\n addl %eax, %ebx\n rmmovl %ebx, c\n halt\n\n.align 4\na: .long 3\nb: .long 5\nc: .long 0 \n
-
Le simulateur Y86 permet de simuler la mani\u00e8re dont le processeur va ex\u00e9cuter ce programme.
-
Vous pouvez retrouver le programme \u00e0 charger ici.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#231-code-en-langage-machine","title":"2.3.1 Code en langage-machine :","text":"Sur la partie droite du simulateur, la zone M\u00e9moire contient, apr\u00e8s assemblage, la traduction de notre code en langage-machine :
500f1800\n0000503f\n1c000000\n6003403f\n20000000\n00000000\n03000000\n05000000\n
Une fois transform\u00e9 en binaire, on retrouve le code donn\u00e9 au d\u00e9but du paragraphe pr\u00e9c\u00e9dent.
Ressources sur les instructions Y86
Exercice 1
Coder en assembleur la s\u00e9quence d'instruction suivante :
w = 10\nx = 3\ny = 5\nz = w - (x + y)\n
Vous aurez pour cela besoin de l'instruction subl rA rB
qui effectue l'op\u00e9ration rB-rA
et la stocke dans rB
. (rA
et rB
sont les noms des registres).
Correction .pos 0\nmrmovl x, %eax\nmrmovl y, %ebx\nmrmovl w, %ecx\naddl %eax, %ebx\nsubl %ebx, %ecx\nrmmovl %ecx, z\nhalt\n\n.align 4\nw: .long 10\nx: .long 3\ny: .long 5\nz: .long 0\n
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#24-resume-des-notions-essentielles","title":"2.4 R\u00e9sum\u00e9 des notions essentielles","text":" - Les registres sont \u00e0 percevoir comme des zones de travail temporaires, \u00e0 l'acc\u00e8s tr\u00e8s rapide. Les donn\u00e9es font l'aller-retour entre la m\u00e9moire et le registre : elles sont stock\u00e9es en m\u00e9moire, passent dans le registre pour y \u00eatre modifi\u00e9es, et reviennent en m\u00e9moire.
- les donn\u00e9es ET les instructions sont stock\u00e9es ensemble dans la m\u00e9moire : c'est le principe fondateur de l'architecture Von Neumann. Ici, l'octet
03
situ\u00e9 \u00e0 l'adresse 0x000d
signifie qu'il va falloir ajouter (on le sait gr\u00e2ce au 60
qui pr\u00e9c\u00e8de) le registre num\u00e9rot\u00e9 0
(donc %eax
) au registre num\u00e9rot\u00e9 3
(donc %ebx
). On retrouve un octet de m\u00eame valeur 03
\u00e0 l'adresse 0x0018
. Mais dans ce cas, cet octet n'est pas une instruction mais une simple donn\u00e9e : c'est la valeur 3 qu'on a donn\u00e9e \u00e0 la variable a
dans notre programme.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#25-conclusion","title":"2.5 Conclusion","text":"Le simulateur Y86 nous a permis d'observer comment un processeur r\u00e9alise des op\u00e9rations \u00e9l\u00e9mentaires. Nous avons d\u00e9couvert le langage assembleur, qui est un langage beaucoup moins agr\u00e9able qu'un langage de haut-niveau, mais qui reste n\u00e9anmoins compr\u00e9hensible par un \u00eatre humain. Certains informaticiens codent (encore de nos jours) directement en langage assembleur, pour \"coller\" au mieux au processeur et optimiser les ressources.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#3-activite-2-modification-dun-programme-par-desassemblage","title":"3. Activit\u00e9 2 : modification d'un programme par d\u00e9sassemblage","text":"On consid\u00e8re ci-dessous le programme crackme.c
, r\u00e9dig\u00e9 en langage en C. Vous pouvez t\u00e9l\u00e9charger ce programme ici.
#include \"stdio.h\"\n#include \"stdlib.h\"\n#include \"string.h\"\n\nint main()\n{\n\nchar saisie[50] = \"\";\nprintf(\"Acc\u00e8s restreint : saisissez votre mot de passe \\n\");\nwhile (strcmp(saisie,\"NSIMAURIAC\")!=0)\n{\nprintf(\"Mot de passe ? \\n\");\nscanf(\"%s\",&saisie);\n}\n\nprintf(\"Acc\u00e8s autoris\u00e9 \\n\");\n\nreturn 0;\n} \n
- Que fait ce programme ?
- Quel est le mot de passe ?
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#31-compilation-et-execution-du-programme","title":"3.1 Compilation et ex\u00e9cution du programme","text":" - Dans un terminal, tapez l'instruction
gcc crackme.c -o crackme
- Tapez
./crackme
et jouez avec le programme.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#32-observation-du-fichier-binaire","title":"3.2 Observation du fichier binaire","text":"\u00c0 l'aide du programme GHex , il est possible d'aller observer la valeur des octets directement dans le fichier binaire crackme
.
Ce fichier binaire est \u00e9crit en langage-machine. Il est donc incompr\u00e9hensible pour un autre humain... m\u00eame si GHex nous aide en affichant notamment (dans la partie droite) les cha\u00eenes de caract\u00e8res... dont notre mot de passe ;)
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#33-modification-du-fichier-binaire","title":"3.3 Modification du fichier binaire","text":"Dans notre code C l'instruction while (strcmp(saisie,\"NSIMAURIAC\")!=0)
est le c\u0153ur de la v\u00e9rification du mot de passe. En assembleur, elle va donner naissance \u00e0 une instruction JNE
(pour Jump if Not Equal, voir ici ). Cette instruction est cod\u00e9e en hexad\u00e9cimal par l'opcode 75 C5
. Nous allons rechercher ces octets et les remplacer par 90 90
, 90
\u00e9tant l'opcode pour NOP
(ne rien faire).
- Recherchez dans GHex
75 C5
. - Remplacez par
90 90
. - Sauvegardez le fichier sous le nom
crackme2
. Vous pouvez sinon le t\u00e9l\u00e9charger ici - Rendez ce fichier ex\u00e9cutable par
sudo chmod 777 crackme2
- Ex\u00e9cutez ce code et constatez les changements !
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#34-conclusion","title":"3.4 Conclusion","text":"Le d\u00e9sassemblage d'un programme est une op\u00e9ration tr\u00e8s complexe et les op\u00e9rations et cha\u00eenes de caract\u00e8res qui apparaissent sont souvent incompr\u00e9hensibles (parfois volontairement, dans le cas d'obfuscation de code). N\u00e9anmoins, il est parfois possible d'agir au niveau le plus bas (le langage-machine) pour modifier un code, comme nous venons de le faire.
Bibliographie - Num\u00e9rique et Sciences Informatiques, Terminale, T. BALABONSKI, S. CONCHON, J.-C. FILLIATRE, K. NGUYEN, \u00e9ditions ELLIPSES.
- Pr\u00e9pabac NSI, Terminale, G.CONNAN, V.PETROV, G.ROZSAVOLGYI, L.SIGNAC, \u00e9ditions HATIER.
- Cours du DIU-EIL, Architecture mat\u00e9rielle, Raymond Namyst, Universit\u00e9 de Bordeaux.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/","title":"3.3 Architecture d'un r\u00e9seau","text":"Ce cours a pour but de pr\u00e9senter la constitution classique d'un r\u00e9seau, et les \u00e9quipements associ\u00e9s. La partie relative aux protocoles utilis\u00e9s lors des \u00e9changes entre deux machines est d\u00e9taill\u00e9e dans le cours sur les protocoles de communication.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#1-premier-reseau-local","title":"1. Premier r\u00e9seau local","text":"Installation de Filius
Installation de la version 1.14.2 pour nos machines virtuelles :
- T\u00e9l\u00e9charger le fichier filius_1.14.2_all.deb
- Dans un terminal ouvert dans le dossier T\u00e9l\u00e9chargements, taper
sudo dpkg -i filius_2.4.0_all.deb
Testons le ping
de la machine 192.168.0.1
vers la machine 192.168.0.3
.
R\u00e9sultat du ping "},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#11-la-carte-reseau-et-son-adresse-mac","title":"1.1. La carte r\u00e9seau et son adresse MAC","text":"Chaque ordinateur sur le r\u00e9seau dispose d'une adresse MAC, qui une valeur unique attribu\u00e9e \u00e0 sa carte r\u00e9seau (Ethernet, Wifi, 4G, 5G, ...) lors de sa fabrication en usine.
Cette adresse est cod\u00e9e sur 48 bits, pr\u00e9sent\u00e9s sous la forme de 6 octets en hexad\u00e9cimal. Exemple : fc:aa:14:75:45:a5
Les trois premiers octets correspondent au code du fabricant. Un site comme https://www.macvendorlookup.com/ vous permet de retrouver le fabricant d'une adresse MAC quelconque.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#12-switch-hub-quelle-difference","title":"1.2. Switch, hub, quelle diff\u00e9rence ?","text":" - Au sein d'un hub Ethernet (de moins en moins vendus), il n'y a aucune analyse des donn\u00e9es qui transitent : il s'agit simplement d'un d\u00e9doublement des fils de cuivre (tout comme une multiprise \u00e9lectrique). L'int\u00e9gralit\u00e9 des messages est donc envoy\u00e9e \u00e0 l'int\u00e9gralit\u00e9 des ordinateurs du r\u00e9seau, m\u00eame s'ils ne sont pas concern\u00e9s.
- Au sein d'un switch Ethernet , une analyse est effectu\u00e9e sur la trame qui est \u00e0 distribuer (voir ici). Lors d'un branchement d'un nouvel ordinateur sur le switch, celui-ci r\u00e9cup\u00e8re son adresse MAC, ce qui lui permet de trier les messages et de ne les distribuer qu'au bon destinataire.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#2-un-deuxieme-sous-reseau","title":"2. Un deuxi\u00e8me sous-r\u00e9seau","text":"Rajoutons un deuxi\u00e8me sous-r\u00e9seau de la mani\u00e8re suivante (penser \u00e0 bien renommer les switchs).
Comment relier ces deux sous-r\u00e9seaux ?
Une r\u00e9ponse pas si b\u00eate : avec un cable entre les deux switchs !
Testons cette hypoth\u00e8se en essayant de pinger la machine 192.168.1.2
depuis la machine 192.168.0.1
.
R\u00e9sultat du ping Cela ne marche pas. L'ordinateur refuse d'envoyer le ping vers la machine 192.168.1.2
. (spoil : car elle n'est pas dans son sous-r\u00e9seau)
Temporairement, renommons la machine 192.168.1.2
en 192.168.0.33
. Testons \u00e0 nouveau le ping depuis la machine 192.168.0.1
.
R\u00e9sultat du ping Cela marche. Les paquets sont bien achemin\u00e9s.
Intuition : la notion de sous-r\u00e9seau n'est pas topologique (\u00abil suffit de relier les ordinateurs entre eux\u00bb) mais ob\u00e9it \u00e0 des r\u00e8gles num\u00e9riques.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#21-notion-de-masque-de-sous-reseau","title":"2.1. Notion de masque de sous-r\u00e9seau","text":"Dans Filius, lors de l'attribution de l'adresse IP \u00e0 une machine, une ligne nous permet de sp\u00e9cifier le masque de sous-r\u00e9seau (appel\u00e9 simplement \u00ab Masque \u00bb dans Filius). C'est ce masque qui va permettre de d\u00e9terminer si une machine appartient \u00e0 un sous-r\u00e9seau ou non, en fonction de son adresse IP.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#211-explication-basique","title":"2.1.1 Explication basique","text":" - Si le masque est
255.255.255.0
, toutes les machines partageant les m\u00eames trois premiers nombres de leur adresse IP appartiendront au m\u00eame sous-r\u00e9seau. Comme ceci est le r\u00e9glage par d\u00e9faut de Filius, cela explique pourquoi 192.168.0.33
et 192.168.0.1
sont sur le m\u00eame sous-r\u00e9seau, et pourquoi 192.168.1.2
et 192.168.0.1
ne sont pas sur le m\u00eame sous-r\u00e9seau.
Dans cette configuration, 256 machines peuvent donc appartenir au m\u00eame sous-r\u00e9seau (ce n'est pas tout \u00e0 fait le cas car des adresses finissant par 0 ou par 255 sont r\u00e9serv\u00e9es).
- Si le masque est
255.255.0.0
, toutes les machines partageant les m\u00eames deux premiers nombres de leur adresse IP appartiendront au m\u00eame sous-r\u00e9seau. Dans cette configuration, 65536 machines peuvent \u00eatre dans le m\u00eame sous-r\u00e9seau. (car 256^2=65536)
Exercice
- Renommons
192.168.0.33
en 192.168.1.2
et modifions son masque en 255.255.0.0
. - Modifions aussi le masque de
192.168.0.1
en 255.255.0.0
. - Testons le ping de
192.168.0.1
vers 192.168.1.2
.
R\u00e9sultat du ping Cela marche. Les deux machines appartiennent maintenant au m\u00eame sous-r\u00e9seau.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#212-explication-avancee","title":"2.1.2 Explication avanc\u00e9e","text":"Lorsqu'une machine A veut envoyer un message \u00e0 une machine B, elle doit d\u00e9terminer si cette machine :
- appartient au m\u00eame sous-r\u00e9seau : auquel cas le message est envoy\u00e9 directement via un ou plusieurs switchs.
- n'appartient pas au m\u00eame sous-r\u00e9seau : auquel cas le message doit d'abord transiter par un routeur (voir 3.)
Quelle op\u00e9ration permet de distinguer cette appartenance \u00e0 un m\u00eame sous-r\u00e9seau ?
Appelons IP_A
et IP_B
les adresses IP respectives des machines A et B. Appelons M
le masque de sous-r\u00e9seau. Nommons &
l'op\u00e9rateur de conjonction entre nombres binaires (voir ici):
Propri\u00e9t\u00e9
A et B appartiennent au m\u00eame sous-r\u00e9seau \u21d4 IP_A & M = IP_B & M
Exemple :
Cconsid\u00e9rons trois machines A, B, C d'IP respectives 192.168.129.10
, 192.168.135.200
et 192.168.145.1
, configur\u00e9es avec un masque de sous-r\u00e9seau \u00e9gal \u00e0 255.255.248.0
.
machine A machine B machine C IP 192.168.129.10 192.168.135.200 192.168.145.1 M 255.255.248.0 255.255.248.0 255.255.248.0 IP & M 192.168.128.0 192.168.128.0 192.168.144.0 Rappel des r\u00e8gles de calcul :
- pour tout octet
x
, x & 255 = x
et x & 0 = 0
. 129 & 248
s'\u00e9crit en binaire 10000001 & 11111000
qui vaut 10000000
, soit 128
en d\u00e9cimal.
Conclusion : les machines A et B sont sous le m\u00eame sous-r\u00e9seau, mais pas la machine C.
Exercice de bac Faire les questions Q1. et Q2. de l'exercice 5 du sujet La R\u00e9union J1 2022
Correction Q1.a. Une adresse IPv4 se code \u00e0 l'aide de 4 octets.
Correction Q1.b. Le PC3 a pour adresse 172.150.4.30 / 24
. Cela signfie que son masque, en notation CIDR, est 24. Ses 24 premiers bits sont donc \u00e0 1. Cela correspond au masque 255.255.255.0
en notation d\u00e9cimale.
Correction Q2. "},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#213-coherence-entre-les-deux-explications","title":"2.1.3 Coh\u00e9rence entre les deux explications","text":"Lorsqu'un masque de sous-r\u00e9seau est \u00e9gal \u00e0 255.255.255.0
, l'op\u00e9ration de conjonction &
avec chaque IP ne laissera intacts que les 3 premiers octets, le dernier sera \u00e9gal \u00e0 0. Donc si deux adresses s'\u00e9crivent A.B.C.X
et A.B.C.Y
, elles appartiendront forc\u00e9ment au m\u00eame sous-r\u00e9seau (typiquement, c'est le cas de 192.168.0.33
et 192.168.0.1
).
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#22-ecriture-des-masques-de-sous-reseau-notation-cidr","title":"2.2 \u00c9criture des masques de sous-r\u00e9seau : notation CIDR","text":"D'apr\u00e8s ce qui pr\u00e9c\u00e8de, 2 informations sont n\u00e9cessaires pour d\u00e9terminer le sous-r\u00e9seau auquel appartient une machine : son IP et le masque de sous-r\u00e9seau. Une convention de notation permet d'\u00e9crire simplement ces deux renseignements : la notation CIDR.
Exemple : Une machine d'IP 192.168.0.33
avec un masque de sous-r\u00e9seau 255.255.255.0
sera d\u00e9sign\u00e9e par 192.168.0.33 / 24
en notation CIDR.
Le suffixe / 24
signifie que le masque de sous-r\u00e9seau commence par 24 bits cons\u00e9cutifs de valeur 1 : le reste des bits (donc 8 bits) est \u00e0 mis \u00e0 0. Autrement dit, ce masque vaut 11111111.11111111.11111111.00000000
, soit 255.255.255.0
. De la m\u00eame mani\u00e8re, le suffixe / 16
donnera un masque de 11111111.11111111.00000000.00000000
, soit 255.255.0.0
. Ou encore, un suffixe / 21
donnera un masque de 11111111.11111111.11111000.00000000
, soit 255.255.248.0
.
(lien vers le cours sur le binaire)
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#23-adresses-ip-et-masques-ce-quil-faut-retenir","title":"2.3 Adresses IP et masques : ce qu'il faut retenir","text":" D\u00e9finition
- Les ordinateurs s'identifient sur les r\u00e9seaux \u00e0 l'aide d'une adresse IP (Internet Protocol).
- Suivant la norme IPv4, les adresses IP sont encod\u00e9es sur 4 octets : on parle d'IPv4.
- Chaque octet pouvant varier de la valeur (d\u00e9cimale) 0 \u00e0 255, cela signifie que les adresses IP th\u00e9oriquement possibles vont de
0.0.0.0
\u00e0 255.255.255.255
. - Il y a donc \\(256^4=4 294 967 296\\) adresses possibles. On a longtemps cru que ce nombre serait suffisant. Ce n'est plus le cas, on est donc en train de passer sur des adresses \u00e0 6 octets (en hexad\u00e9cimal) : voir la norme IPv6.
Exemple
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#3-un-vrai-reseau-contenant-deux-sous-reseaux-distincts-la-necessite-dun-routeur","title":"3. Un vrai r\u00e9seau contenant deux sous-r\u00e9seaux distincts : la n\u00e9cessit\u00e9 d'un routeur","text":"Notre solution initiale (relier les deux switchs par un cable pour unifier les deux sous-r\u00e9seaux) n'est pas viable \u00e0 l'\u00e9chelle d'un r\u00e9seau plan\u00e9taire.
Pour que les machines de deux r\u00e9seaux diff\u00e9rents puissent \u00eatre connect\u00e9es, on va utiliser un dispositif \u00e9quip\u00e9 de deux cartes r\u00e9seaux, situ\u00e9 \u00e0 cheval entre les deux sous-r\u00e9seaux. Ce \u00e9quipement de r\u00e9seau est appel\u00e9 routeur ou passerelle.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#31-principe-de-fonctionnement","title":"3.1 Principe de fonctionnement","text":"Imaginons que la machine 192.168.0.1 / 24
veuille communiquer avec la machine 172.16.52.3 / 24
. L'observation du masque de sous-r\u00e9seau de la machine 192.168.0.1 / 24
nous apprend qu'elle ne peut communiquer qu'avec les adresses de la forme 192.168.0.X / 24
, o\u00f9 X
est un nombre entre 0 et 255.
Les 3 \u00e9tapes du routage :
- Lorsque qu'une machine A veut envoyer un message \u00e0 une machine B, elle va tout d'abord v\u00e9rifier si cette machine appartient \u00e0 son r\u00e9seau local. si c'est le cas, le message est envoy\u00e9 par l'interm\u00e9diaire du switch qui relie les deux machines.
- Si la machine B n'est pas trouv\u00e9e sur le r\u00e9seau local de la machine A, le message va \u00eatre achemin\u00e9 vers le routeur, par l'interm\u00e9diaire de son adresse de passerelle (qui est bien une adresse appartenant au sous-r\u00e9seau de A).
- De l\u00e0, le routeur va regarder si la machine B appartient au deuxi\u00e8me sous-r\u00e9seau auquel il est connect\u00e9. Si c'est le cas, le message est distribu\u00e9, sinon, le routeur va donner le message \u00e0 un autre routeur auquel il est connect\u00e9 et va le charger de distribuer ce message : c'est le proc\u00e9d\u00e9 (complexe) de routage, qui sera vu en classe de Terminale.
Dans notre exemple, l'adresse 172.16.52.3
n'est pas dans le sous-r\u00e9seau de 192.168.0.1
. Le message va donc transiter par le routeur.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#32-illustration-avec-filius","title":"3.2 Illustration avec Filius","text":" -
Rajoutons un routeur entre le SwitchA et le SwitchB.
-
Configuration du routeur : L'interface reli\u00e9e au Switch A doit avoir une adresse du sous-r\u00e9seau A. On donne souvent une adresse finissant par 254
, qui est en quelque sorte la derni\u00e8re adresse du r\u00e9seau (en effet l'adresse en 255
est appel\u00e9e adresse de broadcast, utilis\u00e9e pour pinger en une seule fois l'int\u00e9gralit\u00e9 d'un sous-r\u00e9seau). On donne donc l'adresse 192.168.0.254
pour l'interface reli\u00e9e au Switch A, et 192.168.1.254
pour l'interface reli\u00e9e au Switch B. Dans l'onglet g\u00e9n\u00e9ral, s\u00e9lectionner \u00ab Routage automatique \u00bb. Ainsi configur\u00e9 notre routeur peut jouer le r\u00f4le de passerelle entre les deux sous-r\u00e9seaux.
Test du ping entre 192.168.0.1
et 192.168.1.2
Cela ne marche pas. La carte r\u00e9seau refuse d'envoyer les paquets car elle ne sait pas o\u00f9 les envoyer.
Pourquoi cet \u00e9chec ? Parce que nous devons dire \u00e0 chaque machine qu'une passerelle est maintenant disponible pour pouvoir sortir de son propre sous-r\u00e9seau. Il faut donc aller sur la machine 192.168.0.1
et lui donner l'adresse de sa passerelle, qui est 192.168.0.254
.
Attention, il faut faire de m\u00eame pour 192.168.1.2
(avec la bonne passerelle...) Testons \u00e0 nouveau le ping... Cette fois cela marche.
Plus int\u00e9ressant : effectuons un traceroute
entre 192.168.0.1
et 192.168.1.2
.
On y aper\u00e7oit que la machine 192.168.1.2
est atteignable en deux sauts depuis 192.168.0.1
, en passant par la passerelle 192.168.0.254
Cas d'un r\u00e9seau domestique
Chez vous, la box de votre op\u00e9rateur joue simultan\u00e9ment le r\u00f4le de switch et de routeur :
- switch car elle r\u00e9partit la connexion entre les diff\u00e9rents dispositifs (ordinateurs branch\u00e9s en ethernet, smartphone en wifi, tv connect\u00e9e...)
- routeur car elle fait le lien entre ce sous-r\u00e9seau domestique (les appareils de votre maison) et le r\u00e9seau internet.
L'image ci-dessous pr\u00e9sente le r\u00e9sultat de la commande ipconfig
sous Windows. On y retrouve l'adresse IP locale 192.168.9.103
, le masque de sous-r\u00e9seau 255.255.255.0
et l'adresse de la passerelle 192.168.9.1
.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#33-annexe-rajout-dun-serveur-dns","title":"3.3 Annexe : rajout d'un serveur DNS","text":""},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#331-rajout-dun-serveur-web","title":"3.3.1 Rajout d'un serveur web","text":" -
Connectons un ordinateur au SwitchB, sur l'adresse 192.168.1.30
et installons dessus un Serveur web et d\u00e9marrons-le.
-
Sur la machine 192.168.0.1
, rajoutons un Navigateur Web. En tapant dans la barre d'adresse l'adresse IP du Serveur web, la page d'accueil de Filius s'affiche.
Lors d'une utilisation classique d'un navigateur web, c'est une url m\u00e9morisable qui s'affiche, et non une adresse IP : on retient en effet plus facilement https://www.google.com/
que http://216.58.213.131
, qui renvoient pourtant \u00e0 la m\u00eame adresse. La machine qui assure ce r\u00f4le d'annuaire entre les serveurs web et leur adresse IP s'appelle un serveur DNS. Pour pouvoir indexer la totalit\u00e9 des sites internet, son r\u00f4le est structur\u00e9 de mani\u00e8re hi\u00e9rarchique. Vous trouverez des d\u00e9tails ici
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#331-rajout-dun-serveur-dns","title":"3.3.1 Rajout d'un serveur DNS","text":" - Rajoutons un serveur DNS minimal, qui n'aura dans son annuaire d'un seul site. Il faut pour cela raccorder une nouvelle machine (mais une machine d\u00e9j\u00e0 sur le r\u00e9seau aurait tr\u00e8s bien pu jouer ce r\u00f4le), et installer dessus un serveur DNS.
-
Sur ce serveur DNS, associons l'adresse http://www.vivelansi.fr
\u00e0 l'adresse IP 192.168.1.30
.
-
De retour sur notre machine 192.168.0.1
, sp\u00e9cifions maintenant l'adresse du serveur DNS :
-
Depuis le navigateur web de la machine 192.168.0.1
, le site http://www.vivelansi.fr
est maintenant accessible.
Bibliographie
- Num\u00e9rique et Sciences Informatiques, 1re, T. BALABONSKI, S. CONCHON, J.-C. FILLIATRE, K. NGUYEN, \u00e9ditions ELLIPSES.
- Cours d'OpenClassrooms :
- https://openclassrooms.com/fr/courses/857447-apprenez-le-fonctionnement-des-reseaux-tcp-ip/854659-le-routage
- https://openclassrooms.com/fr/courses/1561696-les-reseaux-de-zero/3607286-ladressage-cidr
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/","title":"3.4 Protocoles de communication dans un r\u00e9seau","text":""},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#1-modele-osi-modele-internet","title":"1. Mod\u00e8le OSI, mod\u00e8le Internet","text":"Les bits transmis d'un ordinateur \u00e0 un autre contiennent, en plus des donn\u00e9es utiles (le mot \u00abbonjour\u00bb dans un email), une multitude de donn\u00e9es (tout aussi utiles) qui vont aider \u00e0 l'acheminement de ces bits au bon endroit, puis au bon ordinateur, puis au bon logiciel. Les diff\u00e9rents protocoles qui r\u00e9gissent cette transmission sont regroup\u00e9s dans ce qui est appel\u00e9 un mod\u00e8le. Deux mod\u00e8les synth\u00e9tisent ces protocoles :
- le mod\u00e8le Internet (ou mod\u00e8le TCP/IP, 1974), organis\u00e9 en 4 couches : liaison, r\u00e9seau, transport, application.
- le mod\u00e8le OSI (Open Systems Interconnection, 1984), organis\u00e9 en 7 couches : physique, liaison, r\u00e9seau, transport, session, pr\u00e9sentation,application.
Ces deux mod\u00e8les co\u00efncident suivant le sch\u00e9ma ci-dessus. Ce sont des mod\u00e8les th\u00e9oriques et d'une certaine rigidit\u00e9. Leur utilisation dans la pratique est parfois plus floue, avec des protocoles \u00e0 cheval sur plusieurs couches. Dans la suite de ce cours, nous \u00e9voquerons les couches par leur num\u00e9ro dans le mod\u00e8le OSI.
Lors de son \u00e9mission, un message va subir successivement toutes les transformations effectu\u00e9es par chaque couche, depuis sa cr\u00e9ation (couche 7) jusqu'\u00e0 sa transmission physique (couche 1).
Lorsque ce m\u00eame message sera r\u00e9ceptionn\u00e9, les transformations seront effectu\u00e9es dans l'ordre inverse, jusqu'\u00e0 la pr\u00e9sentation du message au destinataire.
-
couches 7-6-5 \u2014 couches application-pr\u00e9sentation-session : Ces couches (r\u00e9unies dans le mod\u00e8le Internet en une couche unique \u00abapplication\u00bb ) regroupent les protocoles n\u00e9cessaires \u00e0 la bonne mise en forme d'un message (au sens large) avant sa transmission. Ces protocoles peuvent \u00eatre de nature tr\u00e8s diff\u00e9rente : protocole HTTP pour la transmisson de pages web, protocole FTP pour le transfert de fichiers, protocoles POP ou IMAP pour le courrier \u00e9lectronique...
-
couche 4 \u2014 couche transport : Le protocole majeur de cette couche est le protocole TCP :
- il s'assure par SYN-ACK que l'\u00e9metteur et le r\u00e9cepteur sont pr\u00eats \u00e0 \u00e9changer des messages.
- il d\u00e9coupe en segments num\u00e9rot\u00e9s le message \u00e0 transmettre (c\u00f4t\u00e9 \u00e9metteur) ou bien recompose le message total en remettant les segments dans l'ordre (c\u00f4t\u00e9 r\u00e9cepteur). Les \u00e9l\u00e9ments \u00e9chang\u00e9s avec la couche inf\u00e9rieure sont des segments.
-
couche 3 \u2014 couche r\u00e9seau : C'est la couche o\u00f9 chaque segment num\u00e9rot\u00e9 est encapsul\u00e9 dans un paquet qui, suivant le protocole IP, va contenir son adresse source et son adresse de destination. C'est \u00e0 ce niveau que se d\u00e9cide si le message doit rester dans le r\u00e9seau local ou \u00eatre envoy\u00e9 sur un autre r\u00e9seau via la passerelle du routeur. Les \u00e9l\u00e9ments \u00e9chang\u00e9s avec la couche inf\u00e9rieure sont des paquets.
-
couche 2 \u2014 couche liaison : C'est l'encapsulation finale du message. Suivant le protocole Ethernet, les informations sont transmises d'une carte r\u00e9seau \u00e0 une autre, gr\u00e2ce \u00e0 leur adresse MAC (Media Access Controler). Les \u00e9l\u00e9ments \u00e9chang\u00e9s avec la couche inf\u00e9rieure sont des trames.
-
couche 1 \u2014 couche physique : C'est la couche o\u00f9 le message est transmis physiquement d'un point \u00e0 un autre. Par signal lumineux (fibre optique), par ondes (wifi), par courant \u00e9lectrique (Ethernet)... Les \u00e9l\u00e9ments transmis sont les bits.
Lors de son parcours, une trame peut \u00eatre partiellement d\u00e9capsul\u00e9e et remonter \u00e0 la couche 3, avant de redescendre et de continuer son chemin. C'est le cas notamment lors du passage dans un routeur. Mais jamais, lors de son acheminement, le contenu r\u00e9el du message n'est ouvert : les paquets transmis sont achemin\u00e9s de mani\u00e8re identique, qu'ils contiennent les \u00e9l\u00e9ments constitutifs d'une vid\u00e9o YouTube ou d'un email \u00e0 votre cousin.
Ce principe fondateur, actuellement menac\u00e9 par certains acteurs politiques et industriels, est connu sous l'expression \u00abla neutralit\u00e9 du net\u00bb.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#2-observation-des-trames-avec-filius","title":"2. Observation des trames avec Filius","text":""},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#21-ping-a-travers-un-switch","title":"2.1. Ping \u00e0 travers un switch","text":"Vous pouvez t\u00e9l\u00e9charger le fichier ping_switch.fls.
- Relions une machine
192.168.0.10
d'adresse MAC BC:81:81:42:9C:31
\u00e0 une machine 192.168.0.11
d'adresse MAC 2A:AB:AC:27:D6:A7
\u00e0 travers un switch.
- Observons la table SAT de notre switch : elle est vide, car aucune machine n'a encore cherch\u00e9 \u00e0 communiquer.
- Lan\u00e7ons un ping depuis
192.168.0.10
vers 192.168.0.11
et observons les donn\u00e9es \u00e9chang\u00e9es :
- Observons de plus pr\u00e8s la premi\u00e8re ligne de donn\u00e9es \u00e9chang\u00e9es.
Cette premi\u00e8re ligne est une requ\u00eate ARP. ARP est un protocole qui s'interface entre la couche 3 / r\u00e9seau (appel\u00e9e dans la capture d'\u00e9cran Internet) et la couche 2 / liaison (appel\u00e9e dans la capture d'\u00e9cran R\u00e9seau). Comme indiqu\u00e9 dans le commentaire, elle consiste \u00e0 un appel \u00e0 tout le r\u00e9seau : \"Est-ce que quelqu'un ici poss\u00e8de l'IP 192.168.0.11
?
Message 1 : \u00ab Qui poss\u00e8de l'IP 192.168.0.11
? \u00bb
Il faut comprendre \u00e0 cette \u00e9tape que l'adresse IP est totalement inutile pour r\u00e9p\u00e9rer un ordinateur dans un sous-r\u00e9seau. Ce sont les adresses MAC qui permettent de se rep\u00e9rer dans un sous-r\u00e9seau. Les adresses IP, elles, permettront \u00e9ventuellement d'acheminer le message jusqu'au bon sous-r\u00e9seau (elles n'int\u00e9ressent donc que les routeurs).
Revenons \u00e0 notre ping vers 192.168.0.11
.
La commande arp -a
effectu\u00e9e dans un terminal de la machine 192.168.0.10
nous permet de voir qu'elle ne conna\u00eet encore personne dans son sous-r\u00e9seau. La table de correspondance IP \u2b80 MAC ne contient que l'adresse de broadcast 255.255.255.255
, qui permet d'envoyer un message \u00e0 tout le r\u00e9seau.
Constatant qu'elle ne sait pas quelle est l'adresse MAC de 192.168.0.11
, la machine 192.168.0.10
commence donc par envoyer un message \u00e0 tout le sous-r\u00e9seau, par l'adresse MAC de broadcast FF:FF:FF:FF:FF:FF
. Le switch va lui aussi lui aussi relayer ce message \u00e0 tous les \u00e9quipements qui lui sont connect\u00e9s (dans notre cas, un seul ordinateur)
Message 2 : \u00ab Moi ! \u00bb
La machine 192.168.0.11
s'est reconnu dans le message de broadcast de la machine 192.168.0.10
. Elle lui r\u00e9pond pour lui donner son adresse MAC.
\u00c0 partir de ce moment, la machine 192.168.0.10
sait comment communiquer avec 192.168.0.11
. Elle l'\u00e9crit dans sa table arp
, afin de ne plus avoir \u00e0 \u00e9mettre le message n\u00b01 :
Le switch, qui a vu passer sur ses ports 0 et 1 des messages venant des cartes MAC BC:81:81:42:9C:31
et 2A:AB:AC:27:D6:A7
, peut mettre \u00e0 jour sa table SAT :
Par la suite, il saura sur quel port rediriger les messages destin\u00e9s \u00e0 ces deux adresses MAC. Un switch est un \u00e9quipement de r\u00e9seau de la couche 2 du mod\u00e8le OSI, il ne sait pas lire les adresses IP : il ne travaille qu'avec les adresses MAC.
Message 3 : le ping est envoy\u00e9
Sch\u00e9matisons cette trame Ethernet (couche 2 du mod\u00e8le OSI) :
Message 4 : le pong est retourn\u00e9
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#22-ping-a-travers-un-routeur","title":"2.2. Ping \u00e0 travers un routeur","text":"Vous pouvez t\u00e9l\u00e9charger le fichier ping_routeur.fls.
L'objectif est d'observer les diff\u00e9rentes trames lors d'un ping entre :
- la machine
192.168.0.1 / 24
(adresse MAC F9:E1:D6:0B:29:03
) et - la machine
192.168.1.1 / 24
(adresse MAC D3:79:96:B8:5C:A4
)
Le routeur est configur\u00e9 ainsi :
- interface sur le r\u00e9seau A :
- IP :
192.168.0.254
- MAC :
77:C2:22:C9:5C:E7
- interface sur le r\u00e9seau B :
- IP :
192.168.1.254
- MAC :
66:E5:4E:7D:0B:B0
\u00c9tape 0 : le routeur signale sa pr\u00e9sence
Lors de l'observation des messages re\u00e7us ou \u00e9mis par la machine 192.168.0.1
, on peut \u00eatre intrigu\u00e9 par ce tout premier message re\u00e7u, \u00e9mis par le routeur :
On peut y distinguer les 4 couches du mod\u00e8le Internet. Le routeur, par ce message distribu\u00e9 \u00e0 tous les \u00e9l\u00e9ments du sous-r\u00e9seau A (il envoie un message \u00e9quivalent sur son sous-r\u00e9seau B), d\u00e9clare sa pr\u00e9sence, et le fait qu'il poss\u00e8de deux interfaces, une pour chaque r\u00e9seau. Il se positionne ainsi comme une passerelle : \u00abc'est par moi qu'il faudra passer si vous voulez sortir de votre sous-r\u00e9seau\u00bb. Dans cette trame envoy\u00e9e figure son adresse MAC, de sorte que tous les membres de son sous-r\u00e9seau pourront donc communiquer avec lui.
\u00c9tape 1 : de 192.168.0.1
vers le routeur
La machine 192.168.0.1 / 24
calcule que la machine 192.168.1.1 / 24
avec laquelle elle veut communiquer n'est pas dans son sous-r\u00e9seau. Elle va donc envoyer son message \u00e0 sa passerelle, qui est l'adresse du routeur dans son sous-r\u00e9seau.
Cette premi\u00e8re trame est :
\u00c9tape 2 : le routeur d\u00e9capsule la trame
Le routeur est un \u00e9quipement de r\u00e9seau de couche 3 (couche r\u00e9seau). Il doit observer le contenu du paquet IP (sans remonter jusqu'au contenu du message) pour savoir, suivant le proc\u00e9d\u00e9 de routage (voir cours de Terminale), o\u00f9 acheminer ce paquet.
Dans notre cas, l'adresse IP 192.168.1.1
de destination lui est accessible : elle fait partie de son sous-r\u00e9seau B.
Le routeur va modifier la valeur du TTL (Time To Live), en la d\u00e9cr\u00e9mentant de 1. Si, apr\u00e8s de multiples routages, cette valeur devenait \u00e9gale \u00e0 0, ce paquet serait d\u00e9truit. Ceci a pour but d'\u00e9viter l'encombrement des r\u00e9seaux avec des paquets ne trouvant pas leur destination.
NAT : translation d'adresse Dans notre cas, le routeur va laisser intacte l'adresse IP Source. Ce n'est pas toujours le cas. Dans le cas classique de la box qui relie votre domicile \u00e0 internet, le routeur contenu dans celle-ci va remplacer l'adresse locale de votre ordinateur ou smartphone (ex 192.168.0.26
) par son IP publique (celle apparaissant sur whatsmyip.com, par exemple). Elle effectue ce qu'on appelle une translation d'adresse (NAT). Pourquoi ? Parce que sinon la r\u00e9ponse du serveur distant que vous interrogez serait envoy\u00e9e sur une adresse locale (votre adresse 192.168.0.26
), qui est introuvable depuis un r\u00e9seau ext\u00e9rieur. Il faut donc remplacer toutes les adresses locales par l'IP publique de votre box. Pour \u00e9viter que la r\u00e9ponse du serveur web que vous avez interrog\u00e9 ne soit affich\u00e9e sur l'ordinateur de vos parents, le routeur affecte des ports diff\u00e9rents \u00e0 chaque machine de son sous-r\u00e9seau. Ce port est inclus dans le message transmis au serveur, et il l'est aussi dans sa r\u00e9ponse : le routeur peut donc rediriger le trafic vers la bonne machine du sous-r\u00e9seau.
Le routeur va r\u00e9-encapsuler le paquet IP modifi\u00e9, et cr\u00e9er une nouvelle trame Ethernet en modifiant :
- l'adresse MAC source : il va mettre l'adresse MAC de son interface dans le sous-r\u00e9seau B.
- l'adresse MAC de destination : il va mettre l'adresse MAC de
192.168.1.1
(qu'il aura peut-\u00eatre r\u00e9cup\u00e9r\u00e9e au pr\u00e9alable par le protocole ARP)
Cette deuxi\u00e8me trame est donc :
On peut observer dans Filius cette trame, en se positionnant sur l'interface 192.168.1.254
du routeur, ou sur 192.168.1.1
:
En suivant le m\u00eame principe, la machine 192.168.1.1
pourra envoyer son pong.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#23-exercice","title":"2.3. Exercice","text":"Exercice de bac
\u00c9nonc\u00e9Correction Parties 2 et 3 de l'exercice 2 du sujet Nouvelle-Cal\u00e9donie J1 2022.
Partie 2
Correction Q1. Le r\u00e9seau services a pour adresse IP 195.168.254.0
.
Correction Q2. Le r\u00e9seau services a pour adresse 195.168.254.0
. Comme le masque de sous-r\u00e9seau utilis\u00e9 est 255.255.255.0
, 254 adresses sont initialement disponibles (195.168.254.1
\u00e0 195.168.254.254
, puisque l'adresse 195.168.254.255
est r\u00e9serv\u00e9e pour le broadcast sur le r\u00e9seau). Comme deux adresses sont d\u00e9j\u00e0 prises par le routeur 1 et le routeur 2, il en reste 252.
Correction Q3. Le serveur web acc\u00e8de \u00e0 internet via le routeur 2, dont l'adresse sur le r\u00e9seau services est 192.168.254.2
. C'est donc cette adresse qui joue est l'adresse de passerelle pour le serveur web.
Partie 3
Correction Q1. La ligne 2 montre que l'adresse MAC du serveur DNS est 8A:FD:54:49:D0:CC
.
Correction Q2. La couche Transport montre que le protocole utilis\u00e9 est le protocole UDP.
Correction Q3. Le commentaire de la couche Application indique que l'adresse IP du serveur web est 192.168.254.201
.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#3-protocole-du-bit-alterne","title":"3. Protocole du bit altern\u00e9","text":"Ce protocole est un exemple simple de fiabilisation du transfert de donn\u00e9es.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#1-contexte","title":"1. Contexte","text":" - Alice veut envoyer \u00e0 Bob un message M, qu'elle a pr\u00e9d\u00e9coup\u00e9 en sous-messages M0, M1, M2,...
- Alice envoie ses sous-messages \u00e0 une cadence \u0394t fix\u00e9e (en pratique, les sous-messages partent quand leur acquittement a \u00e9t\u00e9 re\u00e7u ou qu'on a attendu celui-ci trop longtemps : on parle alors de timeout)
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#2-situation-ideale","title":"2. Situation id\u00e9ale","text":"Dans cette situation, les sous-messages arrivent tous \u00e0 destination dans le bon ordre. La transmission est correcte.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#3-situation-reelle","title":"3. Situation r\u00e9elle","text":"Mais parfois, les choses ne se passent pas toujours aussi bien. Car si on ma\u00eetrise parfaitement le timing de l'envoi des sous-messages d'Alice, on ne sait pas combien de temps vont mettre ces sous-messages pour arriver, ni m\u00eame (attention je vais passer dans un tunnel) s'ils ne vont pas \u00eatre d\u00e9truits en route.
Le sous-message M0 est arriv\u00e9 apr\u00e8s le M1, le message M2 n'est jamais arriv\u00e9...
Que faire ?
\u00c9cartons l'id\u00e9e de num\u00e9roter les sous-messages, afin que Bob puisse remettre dans l'ordre les messages arriv\u00e9s, ou m\u00eame redemander sp\u00e9cifiquement des sous-messages perdus. C'est ce que r\u00e9alise le protocole TCP (couche 4 \u2014 transport), c'est tr\u00e8s efficace, mais cher en ressources. Essayons de trouver une solution plus basique.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#3-solution-naive","title":"3. Solution na\u00efve...","text":"Pourquoi ne pas demander \u00e0 Bob d'envoyer un signal pour dire \u00e0 Alice qu'il vient bien de recevoir son sous-message ? Nous appelerons ce signal ACK (comme acknowledgement, traduisible par \u00abaccus\u00e9 de r\u00e9ception\u00bb). Ce signal ACK permettra \u00e0 Alice de renvoyer un message qu'elle consid\u00e9rera comme perdu :
N'ayant pas re\u00e7u le ACK cons\u00e9cutif \u00e0 son message M1, Alice suppose (avec raison) que ce message n'est pas parvenu jusqu'\u00e0 Bob, et donc renvoie le message M1.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#4-mais-peu-efficace","title":"4. Mais peu efficace...","text":"Le deuxi\u00e8me ACK de Bob a mis trop de temps pour arriver (ou s'est perdu en route) et donc Alice a suppos\u00e9 que son sous-message M1 n'\u00e9tait pas arriv\u00e9. Elle l'a donc renvoy\u00e9, et Bob se retrouve avec deux fois le sous-message M1. La transmission est incorrecte. En faisant transiter un message entre Bob et Alice, nous multiplions par 2 la probabilit\u00e9 que des probl\u00e8mes techniques de transmission interviennent. Et pour l'instant rien ne nous permet de les d\u00e9tecter.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#5-bob-prend-le-controle","title":"5. Bob prend le contr\u00f4le","text":"Bob va maintenant int\u00e9grer une m\u00e9thode de validation du sous-message re\u00e7u. Il pourra d\u00e9cider de le garder ou de l'\u00e9carter. Le but est d'\u00e9viter les doublons.
Pour r\u00e9aliser ceci, Alice va rajouter \u00e0 chacun de ses sous-messages un bit de contr\u00f4le, que nous appelerons FLAG (drapeau). Au d\u00e9part, ce FLAG vaut 0. Quand Bob re\u00e7oit un FLAG, il renvoie un ACK \u00e9gal au FLAG re\u00e7u.
Alice va attendre ce ACK contenant le m\u00eame bit que son dernier FLAG envoy\u00e9 :
- tant qu'elle ne l'aura pas re\u00e7u, elle continuera \u00e0 envoyer le m\u00eame sous-message, avec le m\u00eame FLAG.
- d\u00e8s qu'elle l'a re\u00e7u, elle peut envoyer un nouveau sous-message en inversant (\u00abalternant\u00bb) le bit de son dernier FLAG (d'o\u00f9 le nom de ce protocole).
Bob, de son c\u00f4t\u00e9, va contr\u00f4ler la validit\u00e9 de ce qu'il re\u00e7oit : il ne gardera que les sous-messages dont le FLAG est \u00e9gal \u00e0 l'inverse de son dernier ACK. C'est cette m\u00e9thode qui lui permettra d'\u00e9carter les doublons.
Observons ce protocole dans plusieurs cas :
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#51-cas-ou-le-sous-message-est-perdu","title":"5.1 Cas o\u00f9 le sous-message est perdu","text":""},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#52-cas-ou-le-ack-est-perdu","title":"5.2 Cas o\u00f9 le ACK est perdu","text":"Le protocole a bien d\u00e9tect\u00e9 le doublon du sous-message M1.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#53-cas-ou-un-sous-message-est-en-retard","title":"5.3 Cas o\u00f9 un sous-message est en retard","text":"Le protocole a bien d\u00e9tect\u00e9 le doublon du sous-message M1... mais que se passerait-il si notre premier sous-message M1 \u00e9tait encore plus en retard ?
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#6-conclusion","title":"6. Conclusion","text":"Le protocole du bit altern\u00e9 a longtemps \u00e9t\u00e9 utilis\u00e9 au sein de la couche 2 du mod\u00e8le OSI (distribution des trames Ethernet). Simple et l\u00e9ger, il peut toutefois \u00eatre facilement mis en d\u00e9faut, ce qui explique qu'il ait \u00e9t\u00e9 remplac\u00e9 par des protocoles plus performants.
Bibliographie - Num\u00e9rique et Sciences Informatiques, 1re, T. BALABONSKI, S. CONCHON, J.-C. FILLIATRE, K. NGUYEN, \u00e9ditions ELLIPSES. - Pr\u00e9pabac NSI 1\u00e8re, C.ADOBET, G.CONNAN, G. ROZSAVOLGYI, L.SIGNAC, \u00e9ditions Hatier.
"},{"location":"T3_Architecture_materielle/3.5_Decouverte_des_commandes_Linux/cours/","title":"3.5 D\u00e9couverte des commandes UNIX","text":"\u00e0 partir du jeu Terminus
Rendez-vous \u00e0 l'adresse http://luffah.xyz/bidules/Terminus/
Laissez-vous guider par le jeu, mais attention ! - vous devez noter sur un papier chaque nouvelle commande que vous apprenez. Vous pouvez par exemple construire un tableau de ce type :
- je vous conseille tr\u00e8s fortement d'\u00e9crire un plan du jeu au fur et \u00e0 mesure que vous avancez dans votre qu\u00eate. Par exemple :
"},{"location":"T3_Architecture_materielle/3.5_Decouverte_des_commandes_Linux/cours/#correction","title":"Correction","text":"Voici un corrig\u00e9 r\u00e9dig\u00e9 par Charles Poulmaire, de l'acad\u00e9mie de Versailles.
"},{"location":"T4_Algorithmique/sommaire/","title":"Th\u00e8me 4 : Algorithmique","text":" - Extremums et moyennes
- Complexit\u00e9
- Tri par insertion
- Tri par s\u00e9lection
- Dichotomie
- Algorithmes gloutons
- Algorithme KNN
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/cours/","title":"4.1 Extremums et moyennes","text":" Activit\u00e9 d'introduction
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/cours/#1-algorithme-de-recherche-de-maximum","title":"1. Algorithme de recherche de maximum","text":"Recherche de maximum
def recherche_max(tab):\n '''renvoie le maximum de la liste tab'''\n maxi = tab[0] # (1)\n for elt in tab:\n if elt > maxi:\n maxi = elt\n return maxi\n
- On initialise le maximum avec la premi\u00e8re valeur du tableau (surtout pas avec 0 ou \u00abmoins l'infini\u00bb !)
Utilisation :
>>> recherche_max([4, 3, 8, 1])\n 8\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/cours/#2-algorithme-de-calcul-de-moyenne","title":"2. Algorithme de calcul de moyenne","text":"Calcul de moyenne
def moyenne(tab):\n ''' renvoie la moyenne de tab'''\n somme = 0\n for elt in tab:\n somme += elt\n return somme / len(tab)\n
Utilisation :
>>> moyenne([4, 3, 8, 1])\n 4.0\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/cours/#3-algorithme-de-recherche-doccurrence","title":"3. Algorithme de recherche d'occurrence","text":"Recherche d'occurrence
def recherche_occurrence(elt, tab):\n ''' renvoie la liste (\u00e9ventuellement vide)\n des indices de elt dans tab'''\n liste_indices = []\n for i in range(len(tab)):\n if tab[i] == elt:\n liste_indices.append(i)\n return liste_indices\n
Utilisation :
>>> recherche_occurrence(3, [1, 6, 3, 8, 3, 2])\n[2, 4]\n>>> recherche_occurrence(7, [1, 6, 3, 8, 3, 2])\n[]\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/intro_cours/","title":"Vers les extremums et moyennes","text":""},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/intro_cours/#1-algorithme-de-recherche-de-maximum","title":"1. Algorithme de recherche de maximum","text":"On cherche \u00e0 coder une fonction recherche_max
qui prend en param\u00e8tre une liste tab
et qui renvoie le plus grand \u00e9l\u00e9ment de cette liste. L'usage de la fonction max
est interdit.
Utilisation :
>>> recherche_max([4, 3, 8, 1])\n 8\n
Code \u00e0 trous Recherche de maximum
def recherche_max(tab):\n '''renvoie le maximum de la liste tab'''\n
Code \u00e0 trous Recherche de maximum
def recherche_max(tab):\n '''renvoie le maximum de la liste tab'''\n ... = ... \n for ... in ...:\n if ... > ...:\n ... = ...\n return ...\n
Code \u00e0 trous Recherche de maximum
def recherche_max(tab):\n '''renvoie le maximum de la liste tab'''\n maxi = ... \n for elt in ...:\n if ... > ...:\n ... = ...\n return ...\n
Code \u00e0 trous Recherche de maximum
def recherche_max(tab):\n '''renvoie le maximum de la liste tab'''\n maxi = tab[0] \n for elt in tab:\n if ... > ...:\n maxi = ...\n return ...\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/intro_cours/#2-algorithme-de-calcul-de-moyenne","title":"2. Algorithme de calcul de moyenne","text":"On cherche \u00e0 coder une fonction moyenne
qui prend en param\u00e8tre une liste tab
et qui renvoie la moyenne des \u00e9l\u00e9ments de cette liste.
Utilisation :
>>> moyenne([4, 3, 8, 1])\n 4.0\n
Code \u00e0 trous Recherche de maximum
def moyenne(tab):\n ''' renvoie la moyenne de tab'''\n
Code \u00e0 trous Recherche de maximum
def moyenne(tab):\n ''' renvoie la moyenne de tab'''\n ... = ...\n for ... in ...:\n ... += ...\n return ... / ...\n
Code \u00e0 trous Recherche de maximum
def moyenne(tab):\n ''' renvoie la moyenne de tab'''\n somme = 0\n for elt in ...:\n ... += ...\n return ... / ...\n
Code \u00e0 trous Recherche de maximum
def moyenne(tab):\n ''' renvoie la moyenne de tab'''\n somme = 0\n for elt in tab:\n somme += ...\n return ... / ...\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/intro_cours/#3-algorithme-de-recherche-doccurrence","title":"3. Algorithme de recherche d'occurrence","text":"On cherche \u00e0 coder une fonction recherche_occurrence
qui prend en param\u00e8tre un \u00e9lement elt
et une liste tab
et qui renvoie la liste (\u00e9ventuellement vide) des indices de elt
dans tab
.
Utilisation :
>>> recherche_occurrence(3, [1, 6, 3, 8, 3, 2])\n[2, 4]\n>>> recherche_occurrence(7, [1, 6, 3, 8, 3, 2])\n[]\n
Code \u00e0 trous Recherche d'occurrence
def recherche_occurrence(elt, tab):\n ''' renvoie la liste (\u00e9ventuellement vide)\n des indices de elt dans tab'''\n
Code \u00e0 trous Recherche d'occurrence
def recherche_occurrence(elt, tab):\n ''' renvoie la liste (\u00e9ventuellement vide)\n des indices de elt dans tab'''\n ... = ...\n for ... in range(...):\n if ... == ...:\n ...\n return ...\n
Code \u00e0 trous Recherche d'occurrence
def recherche_occurrence(elt, tab):\n ''' renvoie la liste (\u00e9ventuellement vide)\n des indices de elt dans tab'''\n liste_indices = ...\n for i in range(...):\n if ... == ...:\n ....append(i)\n return ...\n
Code \u00e0 trous Recherche d'occurrence
def recherche_occurrence(elt, tab):\n ''' renvoie la liste (\u00e9ventuellement vide)\n des indices de elt dans tab'''\n liste_indices = []\n for i in range(len(tab)):\n if tab[i] == ...:\n ....append(i)\n return ...\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/intro_cours/#3-algorithme-de-recherche-de-maximum-avec-indice","title":"3. Algorithme de recherche de maximum avec indice","text":"On cherche \u00e0 coder une fonction recherche_max_et_indice
qui prend en param\u00e8tre une liste tab
et qui renvoie le plus grand \u00e9l\u00e9ment de cette liste ainsi que l'indice de ce maximum dans la liste (si il est pr\u00e9sent plusieurs fois, un seul indice sera renvoy\u00e9). L'usage de la fonction max
est interdit.
Utilisation :
>>> recherche_max_et_indice([4, 1, 3, 8, 3, 8, 1])\n 8, 5\n
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/","title":"4.2 Complexit\u00e9 d'un algorithme","text":"La complexit\u00e9 d'un algorithme est une notion qui nous \u00e9claire sur la mani\u00e8re dont cet algorithme va \u00eatre sensible \u00e0 la taille des donn\u00e9es pass\u00e9es en param\u00e8tre. Il y a plusieurs types de complexit\u00e9s \u00e9tudiables (nombre d'op\u00e9rations, temps n\u00e9cessaire, espace-m\u00e9moire n\u00e9cessaire...).
En NSI, nous nous contenterons d'estimer (lorsque cela est possible) le nombre d'op\u00e9rations effectu\u00e9es par l'algorithme, et nous mesurerons les temps d'ex\u00e9cution de ces algortihmes.
Nous observerons surtout comment \u00e9volue ce temps d'ex\u00e9cution en fonction de la taille des donn\u00e9es pass\u00e9es en param\u00e8tre (la taille d'une liste, par exemple). Cela nous permettra dans ce cours de classer nos algorithmes en deux cat\u00e9gories : les algorithmes de complexit\u00e9 lin\u00e9aire et ceux de complexit\u00e9 quadratique.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#1-complexite-lineaire","title":"1. Complexit\u00e9 lin\u00e9aire","text":""},{"location":"T4_Algorithmique/4.2_Complexite/cours/#11-exemple","title":"1.1 Exemple","text":"Exemple d'algorithme
Votre travail est de mettre des bulletins dans des enveloppes pour une campagne de communication. L'algorithme en jeu ici est \"je prends un bulletin, je le plie, je le mets dans l'enveloppe, je ferme l'enveloppe\".
On suppose que vous travaillez \u00e0 un rythme constant. Le premier jour, on vous donne \\(n\\) enveloppes \u00e0 remplir. Vous mettez un temps \\(T\\) pour les traiter. Le deuxi\u00e8me jour, suite \u00e0 l'absence d'un employ\u00e9, on vous donne le double d'enveloppes, soit \\(2n\\) enveloppes. Combien de temps allez vous mettre pour les traiter ?
R\u00e9ponse Cela prendra deux fois plus de temps, donc \\(2T\\).
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#12-vocabulaire","title":"1.2 Vocabulaire","text":"On dit que l'algorithme ci-dessus est de complexit\u00e9 lin\u00e9aire.
Complexit\u00e9 lin\u00e9aire
Les expressions suivantes sont \u00e9quivalentes :
- L'algorithme est de complexit\u00e9 lin\u00e9aire.
- L'algorithme est d'ordre n.
- L'algorithme est en \\(O(n)\\) (\u00abgrand O de n\u00bb)
Toutes ces formulations renvoient \u00e0 la m\u00eame id\u00e9e : le nombre d'op\u00e9rations n\u00e9cessaires (et donc le temps n\u00e9cessaire \u00e0 la terminaison de l'algorithme) \u00e9volue proportionnellement avec le nombre de donn\u00e9es \u00e0 traiter.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#13-formulation-mathematique","title":"1.3 Formulation math\u00e9matique","text":"Si un employ\u00e9 A met 3 secondes par enveloppe, on aura \\(T_A=3n\\). Si un employ\u00e9 B met 20 secondes par enveloppe, on aura \\(T_B=20n\\).
On retrouve la formulation math\u00e9matique d'une fonction lin\u00e9aire \\(f\\).
\\[f : x \\mapsto ax \\quad\\text{ , avec } a \\in \\mathbb{R}\\] Ici, la fonction \\(f_A\\) serait \\(f_A(x)=3x\\), la fonction \\(f_B\\) serait \\(f_B(x)=20x\\)
Dans les deux cas l'algorithme a la m\u00eame complexit\u00e9 (lin\u00e9aire donc). Ce qui compte est le fait que pour chacun des employ\u00e9s, avoir deux fois plus d'enveloppes prendrait deux fois plus de temps.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#14-verification-experimentale","title":"1.4 V\u00e9rification exp\u00e9rimentale","text":"On consid\u00e8re la fonction ci-dessous :
def fabrique(n):\n liste = []\n for _ in range(n):\n liste.append(\"ok\")\n return liste\n
Le code ci-dessous va mesurer le temps d'ex\u00e9cution de cette fonction avec deux param\u00e8tres diff\u00e9rents : la valeur 400 puis la valeur 800.
import time\nt0 = time.time()\nlstA = fabrique(400)\nprint(\"temps pour une liste de taille 400 :\", time.time() - t0)\nt0 = time.time()\nlstB = fabrique(800)\nprint(\"temps pour une liste de taille 800 :\", time.time() - t0)\n
R\u00e9sultats de l'ex\u00e9cution :
temps pour une liste de taille 400 : 2.384185791015625e-05\ntemps pour une liste de taille 800 : 4.2438507080078125e-05\n
Interpr\u00e9tation : Doubler la taille du param\u00e8tre d'entr\u00e9e a eu pour effet de doubler (quasiment) le temps d'ex\u00e9cution. Cela semble indiquer que la complexit\u00e9 de cette fonction est lin\u00e9aire. En observant l'algorithme, nous pouvons confirmer cette supposition : le nombre d'op\u00e9rations de la boucle for
est \u00e9gal au param\u00e8tre n
, et est donc directement proportionnel \u00e0 la valeur de ce param\u00e8tre.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#2-complexite-quadratique","title":"2. Complexit\u00e9 quadratique","text":""},{"location":"T4_Algorithmique/4.2_Complexite/cours/#21-exemple","title":"2.1 Exemple","text":"Exemple d'algorithme
Vous avez l'habitude de tondre la pelouse de votre terrain carr\u00e9, de c\u00f4t\u00e9 \\(n\\). Cela vous prend un certain temps \\(T\\). Votre voisin vous propose de venir chez lui tondre son terrain carr\u00e9 de c\u00f4t\u00e9 \\(2n\\). Combien de temps cela va-t-il vous prendre pour tondre le terrain de votre voisin ?
R\u00e9ponse Cela vous prendra 4 fois plus de temps.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#22-vocabulaire","title":"2.2 Vocabulaire","text":"On dit que l'algorithme ci-dessus est de complexit\u00e9 quadratique.
Complexit\u00e9 quadratique
Les expressions suivantes sont \u00e9quivalentes :
- L'algorithme est de complexit\u00e9 quadratique.
- L'algorithme est d'ordre n au carr\u00e9.
- L'algorithme est en \\(O(n^2)\\) (\u00abgrand O de n carr\u00e9\u00bb)
Toutes ces formulations renvoient \u00e0 la m\u00eame id\u00e9e : le nombre d'op\u00e9rations n\u00e9cessaires (et donc le temps n\u00e9cessaire \u00e0 la terminaison de l'algorithme) \u00e9volue proportionnellement avec le carr\u00e9 du nombre de donn\u00e9es \u00e0 traiter.
Les algorithmes quadratiques sont moins \u00abint\u00e9ressants\u00bb que les algorithmes lin\u00e9aires, car ils vont consommer beaucoup plus de ressources. Lors de l'\u00e9laboration d'un algorithme, on va toujours essayer de trouver l'algorithme ayant la complexit\u00e9 la plus faible possible.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#23-verification-experimentale","title":"2.3 V\u00e9rification exp\u00e9rimentale","text":"Effectuer des mesures de temps d'ex\u00e9cution pour la fonction ci-dessous :
def tables(n):\n for a in range(n):\n for b in range(n):\n c = a * b\n
Le code ci-dessous va mesurer le temps d'ex\u00e9cution de cette fonction avec deux param\u00e8tres diff\u00e9rents : la valeur 100 puis la valeur 200.
import time\nt0 = time.time()\ntables(100)\nprint(\"temps pour n = 100 :\", time.time() - t0)\nt0 = time.time()\ntables(200)\nprint(\"temps pour n = 200 : \", time.time() - t0)\n
R\u00e9sultats de l'ex\u00e9cution :
temps pour n = 100 : 0.0003533363342285156\ntemps pour n = 200 : 0.0014693737030029297\n
Interpr\u00e9tation : Doubler la taille du param\u00e8tre d'entr\u00e9e a eu pour effet de quadrupler le temps d'ex\u00e9cution. Cela semble indiquer que la complexit\u00e9 de cette fonction est quadratique, car \\(2^2=4\\).
En observant l'algorithme, nous pouvons confirmer cette supposition : le nombre d'op\u00e9rations des deux boucles for
est \u00e9gal \u00e0 n^2
.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#3-complexite-constante","title":"3. Complexit\u00e9 constante","text":"Il peut arriver (mais c'est rare) que la complexit\u00e9 d'un algorithme soit ind\u00e9pendante de la taille des donn\u00e9es \u00e0 traiter. Dans ce cas, c'est souvent une tr\u00e8s bonne nouvelle.
Observons l'acc\u00e8s au 1er \u00e9l\u00e9ment d'une liste :
Complexit\u00e9 constante
Les expressions suivantes sont \u00e9quivalentes :
- L'algorithme est de complexit\u00e9 constante.
- L'algorithme est d'ordre 1.
- L'algorithme est en \\(O(1)\\) (\u00abgrand O de 1\u00bb)
Toutes ces formulations renvoient \u00e0 la m\u00eame id\u00e9e : le nombre d'op\u00e9rations n\u00e9cessaires (et donc le temps n\u00e9cessaire \u00e0 la terminaison de l'algorithme) est constant quelle que soit la taille des donn\u00e9es d'entr\u00e9e de l'algorithme.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/","title":"4.3 Tri par insertion","text":""},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#0-introduction","title":"0. Introduction","text":" Activit\u00e9 d'introduction
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#1-tri-par-insertion-version-la-plus-intuitive","title":"1. Tri par insertion (version la plus intuitive)","text":""},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#11-principe-et-algorithme","title":"1.1 Principe et algorithme","text":"Consid\u00e9rons la liste [7, 5, 2, 8, 1, 4]
Voici le fonctionnement de l'algorithme :
Explications :
- On traite successivement toutes les valeurs \u00e0 trier, en commen\u00e7ant par celle en deuxi\u00e8me position.
- Traitement : tant que la valeur \u00e0 traiter est inf\u00e9rieure \u00e0 celle situ\u00e9e \u00e0 sa gauche, on \u00e9change ces deux valeurs.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#12-codage-de-lalgorithme","title":"1.2\u00a0Codage de l'algorithme","text":"Algorithme :
Pour toutes les valeurs, en commen\u00e7ant par la deuxi\u00e8me :
- Tant qu'on trouve \u00e0 gauche une valeur sup\u00e9rieure et qu'on n'est pas revenu \u00e0 la premi\u00e8re valeur, on \u00e9change ces deux valeurs.
Tri par insertion (version simple)
def tri_insertion(lst):\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n for i in range(1, len(lst)): #(1)\n k = i #(2)\n while k > 0 and lst[k-1] > lst[k] : #(3)\n lst[k], lst[k-1] = lst[k-1], lst[k] #(4) \n k = k - 1 #(5) \n
- On commence \u00e0 1 et non pas \u00e0 0.
- On \u00abduplique\u00bb la variable
i
en une variable k
. On se positionne sur l'\u00e9l\u00e9ment d'indice k
. On va faire \u00abreculer\u00bb cet \u00e9l\u00e9ment tant que c'est possible. On ne touche pas \u00e0 i
. - Tant qu'on n'est pas revenu au d\u00e9but de la liste et qu'il y a une valeur plus grande \u00e0 gauche.
- On \u00e9change de place avec l'\u00e9l\u00e9ment pr\u00e9c\u00e9dent.
- Notre \u00e9l\u00e9ment est maintenant \u00e0 l'indice
k - 1
. La boucle peut continuer.
Application :
>>> maliste = [7, 5, 2, 8, 1, 4]\n>>> tri_insertion(maliste)\n>>> maliste\n[1, 2, 4, 5, 7, 8]\n
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#2-tri-par-insertion-version-optimisee","title":"2. Tri par insertion (version optimis\u00e9e)","text":""},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#21-principe-et-algorithme","title":"2.1 Principe et algorithme","text":"Observez l'animation ci-dessous et comparer avec la version initiale.
- Au lieu d'effetuer un \u00e9change avec la valeur pr\u00e9c\u00e9dente \u00e0 chaque fois qu'elle est sup\u00e9rieure, on va d\u00e9caler vers la droite toutes les valeurs situ\u00e9es \u00e0 gauche et sup\u00e9rieures \u00e0 notre valeur de travail.
- On ins\u00e8re ensuite directement \u00e0 sa position \u00abla plus \u00e0 gauche possible\u00bb notre valeur de travail.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#22-codage-de-lalgorithme","title":"2.2 Codage de l'algorithme","text":"Tri par insertion (version optimis\u00e9e)
def tri_insertion_v2(lst) :\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n for i in range(1, len(lst)): # (1)\n cle = lst[i] # (2)\n k = i - 1 # (3)\n while k >= 0 and lst[k] > cle : # (4)\n lst[k + 1] = lst[k] # (5)\n k = k -1 # (6)\n lst[k + 1] = cle # (7)\n
- On d\u00e9marre \u00e0 la deuxi\u00e8me valeur.
- On stocke dans une variable
cle
notre valeur de travail - On d\u00e9marre l'\u00e9tude des valeurs \u00e0 gauche de notre valeur de travail
- Tant qu'on trouve une valeur sup\u00e9rieure \u00e0 notre valeur de travail, et qu'on n'est pas revenus au d\u00e9but de la liste.
- On d\u00e9cale cette valeur de un rang vers la droite.
- On se repositionne sur la valeur \u00e0 gauche de notre valeur actuelle.
- On s'est arr\u00eat\u00e9 quand la valeur n'\u00e9tait pas sup\u00e9rieure : on ins\u00e8re notre valeur de travail juste \u00e0 droite de notre position d'arr\u00eat.
Application :
>>> maliste = [7, 5, 2, 8, 1, 4]\n>>> tri_insertion_v2(maliste)\n>>> maliste\n[1, 2, 4, 5, 7, 8]\n
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#3-complexite-de-lalgorithme","title":"3. Complexit\u00e9 de l'algorithme","text":""},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#31-etude-experimentale","title":"3.1 \u00c9tude exp\u00e9rimentale","text":"Lire le cours sur la complexit\u00e9 et proposer des mesures exp\u00e9rimentales pour d\u00e9terminer la complexit\u00e9 du tri par insertion.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#32-demonstration","title":"3.2 D\u00e9monstration","text":"D\u00e9nombrons le nombre d'op\u00e9rations dans le pire des cas, pour une liste de taille \\(n\\).
- boucle
for
: elle s'ex\u00e9cute \\(n-1\\) fois. - boucle
while
: dans le pire des cas, elle ex\u00e9cute d'abord 1 op\u00e9ration, puis 2, puis 3... jusqu'\u00e0 \\(n-1\\). Or
\\[1+2+3+\\dots+n-1=\\dfrac{n \\times (n-1)}{2}\\] Le terme de plus haut degr\u00e9 de l'expression \\(\\dfrac{n \\times (n-1)}{2}\\) est de degr\u00e9 2 : le nombre d'op\u00e9rations effectu\u00e9es est donc proportionnel au carr\u00e9 de la taille des donn\u00e9es d'entr\u00e9e. Ceci d\u00e9montre que le tri par insertion est de complexit\u00e9 quadratique.
Dans le cas (rare, mais il faut l'envisager) o\u00f9 la liste est d\u00e9j\u00e0 tri\u00e9e, on ne rentre jamais dans la boucle while
: le nombre d'op\u00e9rations est dans ce cas \u00e9gal \u00e0 \\(n-1\\), ce qui caract\u00e9rise une complexit\u00e9 lin\u00e9aire.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#33-resume-de-la-complexite","title":"3.3 R\u00e9sum\u00e9 de la complexit\u00e9","text":" - dans le meilleur des cas (liste d\u00e9j\u00e0 tri\u00e9e) : complexit\u00e9 lin\u00e9aire
- dans le pire des cas (liste tri\u00e9e dans l'ordre d\u00e9croissant) : complexit\u00e9 quadratique
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#34-preuve-de-la-terminaison-de-lalgorithme","title":"3.4 Preuve de la terminaison de l'algorithme","text":"Est-on s\u00fbr que notre algorithme va s'arr\u00eater ? Le programme est constitu\u00e9 d'une boucle while
imbriqu\u00e9e dans une boucle for
. Seule la boucle while
peut provoquer une non-terminaison de l'algorithme. Observons donc ses conditions de sortie :
while k >= 0 and l[k] > cle :\n
La condition l[k] > cle
ne peut pas \u00eatre rendue fausse avec certitude. Par contre, la condition k >= 0
sera fausse d\u00e8s que la variable k
deviendra n\u00e9gative. Or la ligne k = k - 1
nous assure que la variable k
diminuera \u00e0 chaque tour de boucle. La condition k >= 0
deviendra alors forc\u00e9ment fausse au bout d'un certain temps.
Nous avonc donc prouv\u00e9 la terminaison de l'algorithme.
Vocabulaire
On dit que la valeur k
est un variant de boucle. C'est une notion th\u00e9orique (ici illustr\u00e9e de mani\u00e8re simple par la valeur k
) qui permet de prouver la bonne sortie d'une boucle et donc la terminaison d'un algorithme.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#35-preuve-de-la-correction-de-lalgorithme","title":"3.5 Preuve de la correction de l'algorithme","text":"Les preuves de correction sont des preuves th\u00e9oriques. La preuve ici s'appuie sur le concept math\u00e9matique de r\u00e9currence. Principe du raisonnement par r\u00e9currence : une propri\u00e9t\u00e9 \\(P(n)\\) est vraie si :
- \\(P(0)\\) (par exemple) est vraie
- Pour tout entier naturel \\(n\\), si \\(P(n)\\) est vraie alors \\(P(n+1)\\) est vraie.
Ici, la propri\u00e9t\u00e9 serait : \u00ab Quand \\(k\\) varie entre 0 et longueur(liste) -1
, la sous-liste de longueur \\(k\\) est tri\u00e9e dans l'ordre croissant.\u00bb
Vocabulaire
On appelle cette propri\u00e9t\u00e9 un invariant de boucle. Invariant siginifie qu'elle reste vraie pour chaque boucle.
- quand \\(k\\) vaut 0, on place le minimum \\(m_0\\) de la liste en position 0, la sous-liste [\\(m_0\\)] est donc tri\u00e9e.
- si la sous-liste de \\(k\\) \u00e9l\u00e9ments [\\(m_0, m_1, ..., m_{k-1}\\)] est tri\u00e9e, l'algorithme rajoute en derni\u00e8re position de la liste le minimum de la sous-liste restante, dont tous les \u00e9l\u00e9ments sont sup\u00e9rieurs au maximum de la sous-liste de \\(k\\) \u00e9l\u00e9ments. La sous-liste de \\(k+1\\) \u00e9l\u00e9ments [\\(m_0, m_1, ..., m_{k-1}, m_k\\)] est donc elle aussi tri\u00e9e.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#4-bonus-comparaison-des-algorithmes-de-tri","title":"4. Bonus : comparaison des algorithmes de tri","text":"Une jolie animation permettant de comparer les tris : (on peut y constater que le tri par s\u00e9lection met toujours autant de temps pour trier la liste, quelque soit son \u00e9tat initial)
Issue de ce site.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#bibliographie","title":"Bibliographie","text":" - Wikipedia, https://en.wikipedia.org/wiki/Sorting_algorithm
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/intro_cours/","title":"Vers le tri par insertion","text":"Principe de l'algorithme
Pour toutes les valeurs, en commen\u00e7ant par la deuxi\u00e8me :
- Tant qu'on trouve \u00e0 gauche une valeur sup\u00e9rieure et qu'on n'est pas revenu \u00e0 la premi\u00e8re valeur, on \u00e9change ces deux valeurs.
Pour tester son code :
>>> maliste = [7, 5, 2, 8, 1, 4]\n>>> tri_insertion(maliste)\n>>> maliste\n[1, 2, 4, 5, 7, 8]\n
Code \u00e0 trous def tri_insertion(lst):\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n
Code \u00e0 trous def tri_insertion(lst):\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n for i in range(..., ...): \n ... = ... \n while ... > ... and ... > ... : \n ..., ... = ..., ... \n ... = ... \n
Code \u00e0 trous def tri_insertion(lst):\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n for i in range(..., len(lst)): \n k = ... \n while k > ... and lst[...] > lst[...] : \n lst[...], lst[...] = lst[...], lst[...] \n k = ... \n
Code \u00e0 trous def tri_insertion(lst):\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n for i in range(1, len(lst)): \n k = ... \n while k > ... and lst[k-1] > lst[k] : \n lst[k], lst[k-1] = lst[...], lst[...] \n k = ... \n
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/","title":"4.4 Tri par s\u00e9lection","text":""},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#0-preambule","title":"0. Pr\u00e9ambule","text":"Pourquoi \u00e9tudier des algorithmes de tri ? Autant ne pas le cacher, ces algorithmes sont d\u00e9j\u00e0 impl\u00e9ment\u00e9s (quelque soit le langage) dans des fonctions tr\u00e8s performantes.
En Python, on utilise la fonction sort()
:
>>> tab = [4, 8, 1, 2, 6]\n>>> tab.sort()\n>>> tab\n[1, 2, 4, 6, 8]\n
Le meilleur de nos futurs algorithmes de tri sera moins efficace que celui de cette fonction sort()
... Malgr\u00e9 cela, il est essentiel de se confronter \u00e0 l'\u00e9laboration manuelle d'un algorithme de tri. Le tri par s\u00e9lection est le premier des deux algorithmes de tri que nous allons \u00e9tudier (nous \u00e9tudierons aussi le tri par insertion). Ces deux algorithmes ont pour particularit\u00e9 de :
- ne pas n\u00e9cessiter la cr\u00e9ation d'une nouvelle liste. Ils modifient la liste \u00e0 trier en place.
- ne pas faire intervenir de fonctions complexes (comme la recherche d'un minimum par exemple)
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#0-introduction","title":"0. Introduction","text":" Activit\u00e9 d'introduction
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#1-animation","title":"1. Animation","text":"Consid\u00e9rons la liste [5, 4, 2, 1]
Voici le fonctionnement de l'algorithme :
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#2-principe","title":"2. Principe","text":"Comme dans tous les autres algorithmes de tri que nous allons \u00e9tudier, nous allons travailler en place. Cela signifie que nous ne travaillons que sur la liste initiale, sans en cr\u00e9er de nouvelles. Le tri sera fait en permutant des \u00e9l\u00e9ments.
Tr\u00e8s tr\u00e8s grossi\u00e8rement, l'id\u00e9e de l'algorithme est la suivante :
- on cherche le minimum de toute la liste, et on le place au tout d\u00e9but de la liste.
- on cherche maintenant le minimum de toute la liste SAUF le 1er terme, et on le place en 2\u00e8me position.
- on continue ainsi jusqu'\u00e0 la fin.
Pour r\u00e9aliser ceci, le travail va se faire en manipulant les indices des \u00e9l\u00e9ments de la liste.
Description de l'algorithme
Le travail se fait essentiellement sur les indices.
- du premier \u00e9l\u00e9ment jusqu'\u00e0 l'avant-dernier :
- on consid\u00e8re que cet \u00e9l\u00e9ment est l'\u00e9l\u00e9ment minimum, on stocke donc son indice dans une variable indice du minimum.
- on parcourt les \u00e9l\u00e9ments suivants, et si on rep\u00e8re un \u00e9l\u00e9m\u00e9nt plus petit que notre mininum on met \u00e0 jour notre indice du minimum.
- une fois le parcours fini, on \u00e9change l'\u00e9l\u00e9ment de travail avec l'\u00e9l\u00e9ment minimum qui a \u00e9t\u00e9 trouv\u00e9.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#3-implementation-de-lalgorithme","title":"3. Impl\u00e9mentation de l'algorithme","text":"Tri par s\u00e9lection
def tri_selection(lst) :\n for i in range(len(lst)-1):\n indice_min = i\n for k in range(i+1, len(lst)) :\n if lst[k] < lst[indice_min]:\n indice_min = k\n lst[i], lst[indice_min] = lst[indice_min], lst[i]\n
V\u00e9rification :
>>> ma_liste = [7, 5, 2, 8, 1, 4]\n>>> tri_selection(ma_liste)\n>>> ma_liste\n[1, 2, 4, 5, 7, 8]\n
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#4-complexite-de-lalgorithme","title":"4. Complexit\u00e9 de l'algorithme","text":""},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#40-de-quoi-parle-t-on","title":"4.0. De quoi parle-t-on ?","text":" Cours sur la complexit\u00e9
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#41-calcul-du-nombre-doperations","title":"4.1. Calcul du nombre d'op\u00e9rations","text":"La ligne 3 indice_min = i
va s'ex\u00e9cuter \\(n\\) fois. Mais int\u00e9ressons-nous \u00e0 la ligne 5 (le test) : combien de fois va-t-elle s'ex\u00e9cuter ? \u00c0 chaque tour de la premi\u00e8re boucle (qui en comporte \\(n\\)), le nombre d'op\u00e9rations de la 2\u00e8me boucle va varier :
- La 1\u00e8re fois, de 1 \u00e0 \\(n-1\\), provoquera \\(n-1\\) op\u00e9rations.
- La 2\u00e8me fois, de 2 \u00e0 \\(n-1\\), provoquera \\(n-2\\) op\u00e9rations.
- ...
- La \\(n\\)-i\u00e8me fois, \\(n-1\\) \u00e0 \\(n-1\\), provoquera 1 op\u00e9ration.
Or \\(1+2+3+\\dots+n-1=\\dfrac{n \\times (n-1)}{2}= \\dfrac{1}{2}n^2 - \\dfrac{1}{2}n\\)
Dans cette expression, un terme joue un r\u00f4le fondamental : \\(n^2\\). C'est le terme pr\u00e9pond\u00e9rant (le terme de plus haut degr\u00e9), qui va \u00e0 lui seul caract\u00e9riser la mani\u00e8re dont le nombre d'op\u00e9rations \u00e9volue en fonction de \\(n\\).
Ici, \\(n\\) est \u00e9lev\u00e9 au carr\u00e9, ce qui signifie que le nombre d'op\u00e9rations va \u00e9voluer avec le carr\u00e9 du nombre de termes de la liste \u00e0 trier.
Complexit\u00e9 du tri par s\u00e9lection
Le tri par s\u00e9lection a une complexit\u00e9 quadratique.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#42-influence-de-la-taille-de-la-liste-sur-le-temps-dexecution","title":"4.2 Influence de la taille de la liste sur le temps d'ex\u00e9cution","text":"Consid\u00e9rons qu'une liste de taille \\(n\\) est tri\u00e9e par l'algorithme de tri par s\u00e9lection en un temps \\(T\\). Le temps d'ex\u00e9cution d\u00e9pendant du nombre d'op\u00e9rations \u00e0 traiter, il va \u00e9voluer avec le carr\u00e9 de la taille de la liste.
Voici donc un ordre de grandeur de ce que devraient \u00eatre les temps n\u00e9cessaires pour trier une liste de taille \\(2n\\) ou \\(10n\\).
Taille de la liste Temps \\(n\\) \\(T\\) \\(2n\\) \\(4T\\) \\(10n\\) \\(100T\\)"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#43-verification-experimentale","title":"4.3 V\u00e9rification exp\u00e9rimentale","text":"Exercice
\u00c9nonc\u00e9Correction Analyser le code suivant :
import time\n\ndef tri_selection(lst):\n for i in range(len(lst)-1):\n i_min = i\n for k in range(i+1, len(lst)):\n if lst[k] < lst[i_min]:\n i_min = k\n lst[i_min], lst[i] = lst[i], lst[i_min]\n\n\ndef mesures(n):\n total_temps = 0\n for _ in range(5):\n lst = list(range(n, 0, -1)) # (1)\n t0 = time.time()\n tri_selection(lst)\n delta_t = time.time() - t0\n total_temps += delta_t\n tps_moy = total_temps / 5\n print(f\"temps moyen pour trier une liste de taille {n} : {tps_moy}\")\n
- on se place ici dans le pire des cas : une liste initialement tri\u00e9e dans l'ordre d\u00e9croissant. Attention, pour le tri par s\u00e9lection, ces conditions initiales n'ont AUCUNE influence sur le nombre d'op\u00e9rations : le temps mis sera toujours le m\u00eame, quelque soit l'\u00e9tat initial de la liste.
Q1. Essayer de confirmer les r\u00e9sultats th\u00e9oriques du tableau pr\u00e9c\u00e9dent. On pourra travailler par exemple avec une liste initiale de taille 1000.
Q2. Recommencer avec une liste d\u00e9j\u00e0 tri\u00e9e. Que constate-t-on ?
Q1.
>>> mesures(10**3)\ntemps moyen pour trier une liste de taille 1000 : 0.03579235076904297\n>>> mesures(2*10**3)\ntemps moyen pour trier une liste de taille 2000 : 0.13821134567260743\n>>> mesures(10**4)\ntemps moyen pour trier une liste de taille 10000 : 3.3528685569763184\n
On retrouve (\u00e0 peu pr\u00e8s, mais plut\u00f4t bien) le facteur 4 quand la taille de la liste double, et le facteur 100 quand la taille de la liste est multipli\u00e9e par 10.
Q2. Changeons la ligne lst = list(range(n, 0, -1))
en lst = list(range(n))
:
>>> mesures(10**3)\ntemps moyen pour trier une liste de taille 1000 : 0.038380765914916994\n>>> mesures(2*10**3)\ntemps moyen pour trier une liste de taille 2000 : 0.13413033485412598\n>>> mesures(10**4)\ntemps moyen pour trier une liste de taille 10000 : 3.213682508468628\n
Les mesures sont identiques : l'\u00e9tat initial de la liste n'a pas d'influence.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#5-preuve-de-la-terminaison-de-lalgorithme","title":"5.\u00a0Preuve de la terminaison de l'algorithme","text":"Est-on s\u00fbr que notre algorithme va s'arr\u00eater ?
\u00c0 l'observation du programme, constitu\u00e9 de deux boucles for
imbriqu\u00e9es, il n'y a pas d'ambigu\u00eft\u00e9 : on ne peut pas rentrer dans une boucle infinie. Le programme s'arr\u00eate forc\u00e9ment au bout de d'un nombre fixe d'op\u00e9rations. D'apr\u00e8s nos calculs sur la complexit\u00e9, ce nombre de tours de boucles est \u00e9gal \u00e0 \\(\\dfrac{n \\times (n-1)}{2}\\).
Ceci prouve que l'algorithme se terminera.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#6-preuve-de-la-correction-de-lalgorithme","title":"6. Preuve de la correction de l'algorithme","text":"Est-on s\u00fbr que notre algorithme va bien trier notre liste ?
Les preuves de correction sont des preuves th\u00e9oriques. La preuve ici s'appuie sur le concept math\u00e9matique de r\u00e9currence. Principe du raisonnement par r\u00e9currence : une propri\u00e9t\u00e9 \\(P(n)\\) est vraie si :
- \\(P(0)\\) (par exemple) est vraie
- Pour tout entier naturel \\(n\\), si \\(P(n)\\) est vraie alors \\(P(n+1)\\) est vraie.
Ici, la propri\u00e9t\u00e9 serait : \u00ab Quand \\(k\\) varie entre 0 et longueur(liste) -1
, la sous-liste de longueur \\(k\\) est tri\u00e9e dans l'ordre croissant.\u00bb On appelle cette propri\u00e9t\u00e9 un invariant de boucle (sous-entendu : elle est vraie pour chaque boucle)
- quand \\(k\\) vaut 0, on place le minimum \\(m_0\\) de la liste en position 0, la sous-liste [\\(m_0\\)] est donc tri\u00e9e.
- si la sous-liste de \\(k\\) \u00e9l\u00e9ments [\\(m_0, m_1, ..., m_{k-1}\\)] est tri\u00e9e, l'algorithme rajoute en derni\u00e8re position de la liste le minimum de la sous-liste restante, dont tous les \u00e9l\u00e9ments sont sup\u00e9rieurs au maximum de la sous-liste de \\(k\\) \u00e9l\u00e9ments. La sous-liste de \\(k+1\\) \u00e9l\u00e9ments [\\(m_0, m_1, ..., m_{k-1}, m_k\\)] est donc elle aussi tri\u00e9e.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#7-bonus-comparaison-des-algorithmes-de-tri","title":"7. Bonus : comparaison des algorithmes de tri","text":"Une jolie animation permettant de comparer les tris : (on peut y constater que le tri par s\u00e9lection met toujours autant de temps pour trier la liste, quelque soit son \u00e9tat initial)
Issue de ce site.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/intro_cours/","title":"Vers le tri par s\u00e9lection","text":" pour tester votre code :
>>> ma_liste = [7, 5, 2, 8, 1, 4]\n>>> tri_selection(ma_liste)\n>>> ma_liste\n[1, 2, 4, 5, 7, 8]\n
Code \u00e0 trous def tri_selection(lst) :\n ...\n
Code \u00e0 trous def tri_selection(lst) :\n for ... in ... :\n ... = ...\n for ... in ... :\n if ... :\n ...\n ...\n
Code \u00e0 trous def tri_selection(lst) :\n for i in range(...):\n ... = i\n for k in range(..., ...) :\n if ... < ... :\n ... = ...\n ..., ... = ..., ...\n
Code \u00e0 trous def tri_selection(lst) :\n for i in range(len(lst)-1):\n indice_min = ...\n for k in range(..., len(lst)) :\n if lst[...] < lst[...]:\n indice_min = ...\n lst[...], lst[...] = lst[...], lst[...]\n
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/","title":"4.5 Dichotomie","text":"ou comment rechercher efficacement dans une liste tri\u00e9e ?
\u00abdichotomie\u00bb se dit en anglais binary search.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#1-introduction-recherche-dune-valeur-dans-une-liste","title":"1. Introduction : recherche d'une valeur dans une liste","text":""},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#11-preambule","title":"1.1 Pr\u00e9ambule","text":"De l'importance de bien ranger ses affaires
Les premiers algorithmes \u00abc\u00e9l\u00e8bres\u00bb que nous avons d\u00e9couverts \u00e9taient des algorithmes de tri.
Quel est l'int\u00e9r\u00eat de trier ses donn\u00e9es ?
-
l'int\u00e9r\u00eat imm\u00e9diat est d'en tirer un classement : quelle est la plus grande (ou plus petite) valeur, la deuxi\u00e8me, la troisi\u00e8me... On s'en sert donc \u00e9videmment pour d\u00e9terminer une valeur optimale, un gagnant dans une comp\u00e9tition, etc. Mais il y a une autre raison plus importante.
-
Trier ses donn\u00e9es permet de rechercher plus rapidement une valeur pr\u00e9cise parmi celles-ci.
Exemple : pouvez-vous deviner la couleur \u00e0 laquelle je pense ?
coul = [\"bleu\", \"jaune\", \"rouge\", \"vert\", \"violet\", \"marron\"]\n
Toutes les m\u00e9thodes (proposition des valeurs dans l'ordre, au hasard, dans l'ordre inverse...) sont \u00e9quivalentes : elles sont toutes aussi mauvaises, aucune strat\u00e9gie n'est possible car les donn\u00e9es ne sont pas tri\u00e9es. Si je suis \u00e0 la recherche de la valeur \"vert\", le fait de piocher \"rouge\" ne me donnera aucune indication sur le fait que je devrais chercher plus \u00e0 gauche \u00e0 plus \u00e0 droite que l'endroit o\u00f9 j'ai pioch\u00e9.
Il faudrait pour cela que la liste soit tri\u00e9e (et donc qu'elle soit \u00abtriable\u00bb, ce qui n'est pas toujours le cas !). C'est donc le cas dans lequel nous allons nous placer dans toute la suite de ce cours :
Dans toute la suite, nous rechercherons un \u00e9l\u00e9ment dans une liste d'entiers tri\u00e9e dans l'ordre croissant.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#12-contexte-de-recherche","title":"1.2 Contexte de recherche","text":"Consid\u00e9rons donc la liste lst
suivante :
lst = [2, 3, 6, 7, 11, 14, 18, 19, 24]\n
L'objectif est de d\u00e9finir un algorithme de recherche efficace d'une valeur arbitraire pr\u00e9sente dans cette liste.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#13-methode-naive-recherche-par-balayage","title":"1.3 M\u00e9thode na\u00efve : recherche par balayage","text":"C'est la m\u00e9thode la plus intuitive : on essaie toutes les valeurs (par exemple, dans l'ordre croissant) jusqu'\u00e0 trouver la bonne.
Exercice 1
\u00c9crire un code permettant d'afficher l'indice de la valeur 14
dans la liste lst = [2, 3, 6, 7, 11, 14, 18, 19, 24]
.
Correction lst = [2, 3, 6, 7, 11, 14, 18, 19, 24]\nfor k in range(len(lst)):\n if lst[k] == 14 :\n print(k)\n
Exercice 2
\u00c9crire une fonction recherche_naive
qui re\u00e7oit pour param\u00e8tres une liste lst
et un nombre val
et qui renvoie l'indice de val
dans la liste lst
. Si la valeur val
n'est pas trouv\u00e9e, on renverra None
.
Correction def recherche_naive(lst, val) :\n for k in range(len(lst)) :\n if lst[k] == val:\n return k\n return None\n
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#13-complexite-de-la-methode-naive","title":"1.3 Complexit\u00e9 de la m\u00e9thode na\u00efve","text":"Complexit\u00e9 de la m\u00e9thode na\u00efve
Dans le cas d'une recherche na\u00efve, le nombre (maximal) d'op\u00e9rations n\u00e9cessaires est proportionnel \u00e0 la taille de la liste \u00e0 \u00e9tudier. Si on appelle \\(n\\) la longueur de la liste, on dit que cet algorithme est d'ordre \\(n\\), ou lin\u00e9aire, ou en \\(O(n)\\).
Remarque : La m\u00e9thode na\u00efve n'utilise pas le fait que la liste est tri\u00e9e, on aurait pu aussi bien l'utiliser sur une liste non tri\u00e9e.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#2-recherche-dichotomique","title":"2. Recherche dichotomique","text":""},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#21-introduction-le-jeu-du-devine-un-nombre-entre-1-et-100","title":"2.1 Introduction : le jeu du \u00abdevine un nombre entre 1 et 100\u00bb","text":"R\u00e8gles du jeu
Si je choisis un nombre entre 1 et 100, quelle est la strat\u00e9gie optimale pour deviner ce nombre le plus vite possible ? (\u00e0 chaque \u00e9tape, une indication (trop grand, trop petit) permet d'affiner la proposition suivante)
R\u00e9ponse attendue : la meilleure strat\u00e9gie est de couper en deux \u00e0 chaque fois l'intervalle d'\u00e9tude. On d\u00e9marre de 50, puis 75 ou 25, etc.
Il convient toute fois de remettre en question cette m\u00e9thode qui para\u00eet naturellement optimale : si je propose 90 comme nombre de d\u00e9part, j'ai certes moins de chance que le nombre soit entre 90 et 100, mais s'il l'est, j'ai gagn\u00e9 un gros avantage car mon nouvel intervalle est tr\u00e8s r\u00e9duit.
Notion d'esp\u00e9rance probabiliste D\u00e9terminer si un risque vaut la peine d'\u00eatre pris passe par la compr\u00e9hension de la notion d'esp\u00e9rance probabiliste. Exemple : \"On lance un d\u00e9, s'il tombe sur le 6 vous recevez 8 euros, sinon vous me donnez 1 euro. Voulez-vous jouer ?\"
\\(E(X) = 8 \\times \\frac{1}{6} + (-1) \\times \\frac{5}{6} = \\frac{8}{6}-\\frac{5}{6}=\\frac12\\)
En moyenne, on gagnera 50 centimes par partie, il faut donc jouer.
Le graphique ci-dessous repr\u00e9sente le nombre de coups moyens (sur 10 000 parties simul\u00e9es)
Interpr\u00e9tations et remarques
- si le choix se porte toujours sur le nombre situ\u00e9 \u00e0 la moiti\u00e9 de l'intervalle (0.5), le nombre de coups moyen avant la victoire (sur 10 000 parties) est environ 6.
- si le choix se porte toujours sur le nombre situ\u00e9 \u00e0 90 % de l'intervalle (0.9), le nombre de coups moyen avant la victoire (sur 10 000 parties) est environ 11.
- l'asym\u00e9trie de la courbe (qui devrait \u00eatre sym\u00e9trique) est due aux arrondis par d\u00e9faut dans le cas de nombres non entiers.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#conclusion-generale-de-lactivite-dintroduction","title":"Conclusion g\u00e9n\u00e9rale de l'activit\u00e9 d'introduction","text":"La strat\u00e9gie optimale est de diviser en deux \u00e0 chaque \u00e9tape l'intervalle d'\u00e9tude. On appelle cela une m\u00e9thode par dichotomie, du grec ancien \u03b4\u03b9\u03c7\u03bf\u03c4\u03bf\u03bc\u03af\u03b1, dikhotomia (\u00ab division en deux parties \u00bb).
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#22-algorithme-de-recherche-dichotomique","title":"2.2 Algorithme de recherche dichotomique","text":"Dichotomie, d\u00e9roulement intuitif
- on se place au milieu de la liste.
- on regarde si la valeur sur laquelle on est plac\u00e9e est inf\u00e9rieure ou sup\u00e9rieure \u00e0 la valeur cherch\u00e9e.
- on ne consid\u00e8re maintenant que la bonne moiti\u00e9 de la liste qui nous int\u00e9resse.
- on continue jusqu'\u00e0 trouver la valeur cherch\u00e9e (ou pas)
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#23-programmation-de-la-methode-de-dichotomie","title":"2.3 Programmation de la m\u00e9thode de dichotomie","text":"Comprendre la m\u00e9thode de dichotomie est relativement simple, mais savoir la programmer est plus difficile.
Pour des raisons d'efficacit\u00e9, nous allons garder intacte notre liste de travail et simplement faire \u00e9voluer les indices qui d\u00e9terminent le d\u00e9but et la fin de notre liste.
Une autre m\u00e9thode pourrait \u00eatre d'extraire \u00e0 chaque \u00e9tape une nouvelle liste (dont on esp\u00e8re qu'elle contient la valeur cherch\u00e9e), mais la technique utilis\u00e9e (le slicing de liste) consomme beaucoup trop de ressources.
Nous allons donc travailler avec trois variables :
indice_debut
(en bleu sur le sch\u00e9ma) indice_fin
(en bleu sur le sch\u00e9ma) indice_central
, qui est \u00e9gale \u00e0 (indice_debut + indice_fin) // 2
(en rouge sur le sch\u00e9ma)
Nous allons faire se rapprocher les indices indice_debut
et indice_fin
tant que indice_debut <= indice_fin
Codes \u00e0 trous
Recherche dichotomique dans une liste tri\u00e9e
def recherche_dichotomique(lst, val) :\n indice_debut = 0\n indice_fin = len(lst) - 1\n while indice_debut <= indice_fin :\n indice_centre = (indice_debut + indice_fin) // 2 \n valeur_centrale = lst[indice_centre] \n if valeur_centrale == val : \n return indice_centre\n if valeur_centrale < val : \n indice_debut = indice_centre + 1\n else :\n indice_fin = indice_centre - 1\n return None\n
Utilisation
>>> mylist = [2, 3, 6, 7, 11, 14, 18, 19, 24]\n>>> recherche_dichotomique(mylist, 14)\n5\n>>> recherche_dichotomique(mylist, 2)\n0\n>>> recherche_dichotomique(mylist, 24)\n8\n>>> recherche_dichotomique(mylist, 1789)\n>>> \n
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#24-visualisations-avec-pythontutor","title":"2.4 Visualisations avec PythonTutor","text":"Cas o\u00f9 la valeur est trouv\u00e9e Cas o\u00f9 la valeur N'est PAS trouv\u00e9e"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#25-terminaison-de-lalgorithme","title":"2.5 Terminaison de l'algorithme","text":"Est-on s\u00fbr que l'algorithme va se terminer ? La boucle while
qui est utilis\u00e9e doit nous inciter \u00e0 la prudence (voir cours sur la boucle While). Il y a en effet le risque de rentrer dans une boucle infinie. Pourquoi n'est-ce pas le cas ?
Aide : observer la position des deux fl\u00e8ches bleues lors de l'ex\u00e9cution de l'algorithme
La condition de la boucle while
est indice_debut <= indice_fin
, qui pourrait aussi s'\u00e9crire indice_fin >= indice_debut
. Au d\u00e9marrage de la boucle, on a :
indice_debut = 0\n indice_fin = len(L) - 1\n
Ceci qui nous assure donc de bien rentrer dans la boucle.
Ensuite, \u00e0 chaque \u00e9tape :
- soit
indice_debut
augmente strictement (gr\u00e2ce \u00e0 indice_debut = indice_centre + 1
) - soit
indice_fin
diminue strictement (gr\u00e2ce \u00e0 indice_fin = indice_centre - 1
)
Il va donc forc\u00e9ment arriver un moment o\u00f9 indice_fin
sera inf\u00e9rieur \u00e0 indice_debut
: on sortira alors de la boucle et le programme va bien se terminer.
Variant de boucle On dit que la valeur indice_fin - indice_debut
repr\u00e9sente le variant de boucle de cet algorithme. Ce variant est un nombre entier, d'abord strictement positif, puis qui va d\u00e9cro\u00eetre jusqu'\u00e0 la valeur 0.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#26-complexite-de-lalgorithme","title":"2.6 Complexit\u00e9 de l'algorithme","text":"Combien d'\u00e9tapes (au maximum) sont-elles n\u00e9cessaires pour arriver \u00e0 la fin de l'algorithme ? Imaginons que la liste initiale poss\u00e8de 8 valeurs. Apr\u00e8s une \u00e9tape, il ne reste que 4 valeurs \u00e0 traiter. Puis 2 valeurs. Puis une seule valeur. Il y a donc 3 \u00e9tapes avant de trouver la valeur cherch\u00e9e.
Exercice 3
Q1. Remplissez le tableau ci-dessous :
taille de la liste 1 2 4 8 16 32 64 128 256 nombre d'\u00e9tapes _ _ _ 3 _ _ _ _ _ Q2. Pouvez-vous deviner le nombre d'\u00e9tapes n\u00e9cessaires pour une liste de 4096 termes ?
Q3. Pour une liste de \\(2^n\\) termes, quel est le nombre d'\u00e9tapes ?
Conclusion :
C'est le nombre de puissances de 2 que contient le nombre \\(N\\) de termes de la liste qui est d\u00e9terminant dans la complexit\u00e9 de l'algorithme.
Ce nombre s'appelle le logarithme de base 2 et se note \\(\\log_2(N)\\).
On dit que l'algorithme de dichotomie a une vitesse logarithmique. On rencontrera parfois la notation \\(O(\\log_2(n))\\).
Complexit\u00e9 de la dichotomie
La recherche dichotomique se fait avec une complexit\u00e9 logarithmique.
Cette complexit\u00e9 est bien meilleure qu'une complexit\u00e9 lin\u00e9aire. Le nombre d'op\u00e9rations \u00e0 effectuer est tr\u00e8s peu sensible \u00e0 la taille des donn\u00e9es d'entr\u00e9e, ce qui en fait un algorithme tr\u00e8s efficace.
Par exemple, si on faisait une recherche dichotomomique sur les 8 milliards d'\u00eatres humains de la plan\u00e8te (en admettant qu'on ait r\u00e9ussi \u00e0 les classer...), il suffirait de 33 \u00e9tapes pour trouver l'individu cherch\u00e9 !
(car \\(2^{33}= 8589934592\\))
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#3-experiences-et-comparaison-des-vitesses-dexecution","title":"3. Exp\u00e9riences et comparaison des vitesses d'ex\u00e9cution","text":"Exercice 4
Mesurer le temps d'ex\u00e9cution de deux fonctions recherche_naive
et recherche_dichotomique
. On se placera dans le pire des cas (recherche d'une valeur introuvable), avec des listes de taille 100 000 puis 1 000 000.
Correction import time\n\ndef recherche_dichotomique(lst, val) :\n indice_debut = 0\n indice_fin = len(lst) - 1\n while indice_debut <= indice_fin :\n indice_centre = (indice_debut + indice_fin) // 2 \n valeur_centrale = lst[indice_centre] \n if valeur_centrale == val : \n return indice_centre\n if valeur_centrale < val : \n indice_debut = indice_centre + 1\n else :\n indice_fin = indice_centre - 1\n return None\n\ndef recherche_naive(lst, val) :\n for k in range(len(lst)) :\n if lst[k] == val:\n return k\n return None\n\n\n\ndef mesures(n):\n lst = [k for k in range(n)]\n val = n\n total = 0\n for _ in range(10):\n t0 = time.time()\n recherche_naive(lst, val)\n total += time.time() - t0\n print(f'naive pour {n} valeurs : {total/10}')\n total = 0\n for _ in range(10):\n t0 = time.time()\n recherche_dichotomique(lst, val)\n total += time.time() - t0\n print(f'dicho pour {n} valeurs : {total/10}')\n
Tests avec une liste de taille 100 000, 1 000 000 puis 10 000 000:
>>> mesures(10**5)\nnaive pour 100000 valeurs : 0.004096603393554688\ndicho pour 100000 valeurs : 2.574920654296875e-06\n>>> mesures(10**6)\nnaive pour 1000000 valeurs : 0.03997344970703125\ndicho pour 1000000 valeurs : 3.0517578125e-06\n>>> mesures(10**7)\nnaive pour 10000000 valeurs : 0.4003706216812134\ndicho pour 10000000 valeurs : 3.886222839355469e-06\n
- Recherche na\u00efve : la recherche dans une liste 10 fois plus grand prend environ 10 fois plus de temps : la vitesse de l'algorithme est bien proportionnelle \u00e0 la taille \\(n\\) de la liste. \\(\\frac{10^6}{10^5} = 10\\)
- Recherche dichotomique : la recherche dans une liste 10 fois plus grand prend environ 1,2 fois plus de temps : la vitesse de l'algorithme est bien proportionnelle au logarithme de la taille \\(n\\) de la liste. \\(\\frac{\\log(1000000)}{\\log(100000)} \\approx 1,2\\)
"},{"location":"T4_Algorithmique/4.5_Dichotomie/intro_cours/","title":"Vers la recherche dichotomique","text":"\u00c9crire une fonction recherche_dichotomique
qui prend pour argument une liste lst
tri\u00e9e et qui recherche une valeur val
dans cette liste.
Si la valeur est trouv\u00e9e, l'indice de la valeur est renvoy\u00e9. Sinon, on renvoie None
.
Exemple d'utilisation
>>> mylist = [2, 3, 6, 7, 11, 14, 18, 19, 24]\n>>> recherche_dichotomique(mylist, 14)\n5\n>>> recherche_dichotomique(mylist, 2)\n0\n>>> recherche_dichotomique(mylist, 24)\n8\n>>> recherche_dichotomique(mylist, 1789)\n>>> \n
Code \u00e0 trous def recherche_dichotomique(lst, val) :\n
Code \u00e0 trous def recherche_dichotomique(lst, val) :\n indice_debut = ...\n indice_fin = ...\n while ... <= ... :\n ... = (... + ...) // ... \n ... = lst[...] \n if ... == ... : \n return ...\n if valeur_centrale < ... : \n ... = ... + ...\n else :\n ... = ... - ...\n return None \n
Code \u00e0 trous def recherche_dichotomique(lst, val) :\n indice_debut = ...\n indice_fin = ...\n while ... <= ... :\n indice_centre = (... + ...) // 2 \n ... = lst[...] \n if valeur_centrale == ... : \n return ...\n if valeur_centrale < ... : \n ... = ... + 1\n else :\n ... = ... - 1\n return None \n
Code \u00e0 trous def recherche_dichotomique(lst, val) :\n indice_debut = ...\n indice_fin = ...\n while indice_debut <= ... :\n indice_centre = (... + ...) // 2 \n valeur_centrale = lst[...] \n if valeur_centrale == ... : \n return indice_centre\n if valeur_centrale < ... : \n indice_debut = ... + 1\n else :\n indice_fin = ... - 1\n return None\n
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/","title":"4.6 Algorithmes gloutons","text":"en anglais : greedy algorithms
D\u00e9finition
Un algorithme est qualifi\u00e9 de glouton si le probl\u00e8me qu'il essaie de r\u00e9soudre est d\u00e9compos\u00e9 en une succession de probl\u00e8mes identiques pour lesquels l'algorithme va chercher une solution optimale.
La question (presque philosophique) est :
Lorsqu'on fait \u00e0 chaque \u00e9tape le meilleur choix possible, est-ce que la solution finale \u00e0 laquelle on arrive est la meilleure possible ?
Formul\u00e9 autrement :
Est-ce que faire le meilleur choix \u00e0 chaque \u00e9tape nous assure le meilleur choix global ?
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#1-exemples-dalgorithmes-gloutons","title":"1. Exemples d'algorithmes gloutons","text":""},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#11-un-plus-court-chemin","title":"1.1 Un plus court chemin ?","text":" - Vous partez du point O.
- Vous devez avoir atteint le plus rapidement possible tous les points A, B, C, D, E, F.
- L'ordre de parcours des points n'est pas important.
La philosophie de l'algorithme glouton implique qu'\u00e0 chaque \u00e9tape, vous allez vous diriger vers le point le plus proche.
Quel est alors le parcours final ?
R\u00e9ponse Voil\u00e0 ce que donnerait l'algorithme glouton :
Ce chemin est-il optimal ?
R\u00e9ponse Non ! Celui ci-dessous est meilleur :
Le fait d'avoir privil\u00e9gi\u00e9 \u00e0 chaque \u00e9tape le meilleur choix local nous a emp\u00each\u00e9 de voir le meilleur choix global.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#12-remplir-un-rectangle-avec-des-carres","title":"1.2 Remplir un rectangle avec des carr\u00e9s","text":"(d'apr\u00e8s S.Tummarello et E.Buonocore)
On consid\u00e8re un rectangle de dimension 11 sur 13 (figure 0). On veut remplir ce rectangle avec le minimum de carr\u00e9s.
Un algorithme glouton va chercher \u00e0 positionner d'abord le plus grand carr\u00e9 possible (figure 1) :
C'est une strat\u00e9gie efficace (8 carr\u00e9s n\u00e9cessaires), mais qui n'est pas optimale !
strat\u00e9gie optimale La figure 2 pr\u00e9sente un pavage avec seulement 6 carr\u00e9s.
Question : Est-ce qu'un algorithme glouton va toujours passer \u00e0 c\u00f4t\u00e9 de la solution optimale ?
Non ! Il arrive aussi qu'il donne la solution optimale. Changeons le rectangle initial en un rectangle de 10 sur 15 :
Dans cette situation, l'algorithme glouton nous am\u00e8ne \u00e0 la solution optimale.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#conclusion","title":"Conclusion","text":"Un algorithme glouton est une m\u00e9thode rapide et souvent efficace, mais qui ne garantit pas l'optimalit\u00e9 de la solution trouv\u00e9e.
La succession de meilleurs choix LOCAUX va nous amener \u00e0 une bonne solution GLOBALE, mais ne nous garantit pas d'arriver \u00e0 la solution optimale.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#2-le-probleme-du-rendu-de-monnaie","title":"2. Le probl\u00e8me du rendu de monnaie","text":"Nous allons travailler avec des pi\u00e8ces (ou billets) de 1, 2, 5, 10, 20, 50, 100, 200 euros.
L'objectif est de cr\u00e9er un programme renvoyant, pour une somme somme_a_rendre
entr\u00e9e en param\u00e8tre, la combinaison utilisant un minimum de pi\u00e8ces ou de billets pour fabriquer la somme somme_a_rendre
.
Par exemple, lorsque vous payez avec 20 \u20ac un objet co\u00fbtant 11 \u20ac, vous pr\u00e9f\u00e9rez qu'on vous rende vos 9 \u20ac de monnaie par \\(9 = 5 + 2 + 2\\) plut\u00f4t que par \\(9=2+2+2+1+1+1\\)
La r\u00e9solution de ce probl\u00e8me peut se faire de mani\u00e8re gloutonne : \u00e0 chaque \u00e9tape, vous allez essayer de rendre la plus grosse pi\u00e8ce (ou billet) possible.
Activit\u00e9 de d\u00e9couverte de l'algorithme
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#21-solution-du-probleme","title":"2.1 Solution du probl\u00e8me","text":"Rendu de monnaie
def rendu(somme_a_rendre):\n pieces = [200, 100, 50, 20, 10, 5, 2, 1]\n solution = []\n i = 0 # (1)\n while somme_a_rendre > 0:\n if pieces[i] <= somme_a_rendre : # (2) \n solution.append(pieces[i]) # (3) \n somme_a_rendre = somme_a_rendre - pieces[i] # (4)\n else :\n i += 1 # (5) \n return solution\n
- On part du 1er indice -> la plus grande pi\u00e8ce
- Est-ce que la pi\u00e8ce peut \u00eatre rendue ?
- On garde la pi\u00e8ce dans la liste
solution
- On met \u00e0 jour la somme \u00e0 rendre.
- La pi\u00e8ce \u00e9tait trop grosse, on avance dans la liste.
Utilisation : rendu(13)
doit renvoyer [10, 2, 1]
>>> rendu(13)\n [10, 2, 1]\n>>> rendu(58)\n [50, 5, 2, 1]\n
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#22-une-solution-optimale","title":"2.2 Une solution optimale ?","text":"Imaginons qu'il n'y ait plus de pi\u00e8ces de 10 et 5 euros. Faites fonctionner votre algorithme pour la somme de 63 euros.
>>> rendu(63)\n [50, 2, 2, 2, 2, 2, 2, 1]\n
Damned ! Mais ce n'est pas une solution optimale ! [20, 20, 20, 2, 1]
serait bien mieux.
Moralit\u00e9 : Lors d'un rendu de monnaie, l'algorithme glouton n'est optimal que sous certaines conditions, ce qui est un peu d\u00e9cevant. Un syst\u00e8me de monnaie qui rend l'algorithme glouton est dit canonique. Il est difficile de caract\u00e9riser math\u00e9matiquement si un syst\u00e8me de monnaie est canonique ou pas.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#3-le-probleme-du-sac-a-dos-knapsack-problem","title":"3. Le probl\u00e8me du sac \u00e0 dos (Knapsack Problem)","text":"Le probl\u00e8me est celui-ci : vous disposez d'un sac d'une contenance limit\u00e9e (sur le dessin ci-dessus, 15kg) dans lequel vous allez mettre des objets qui ont un certain poids et une certaine valeur. Vous souhaitez maximiser la valeur totale des objets que vous mettez dans votre sac. Evidemment, la somme de leur masse ne doit pas d\u00e9passer 15 kg.
Ce probl\u00e8me (de la cat\u00e9gorie des probl\u00e8me dits d'analyse combinatoire) malgr\u00e9 sa simplicit\u00e9 est un probl\u00e8me majeur d'optimisation.
O\u00f9 en est-on de la recherche acad\u00e9mique sur le probl\u00e8me du sac \u00e0 dos ?
Actuellement :
- On sait trouver LA meilleure solution, mais en explorant toutes les combinaisons une par une. Cette m\u00e9thode par force brute est inapplicable si beaucoup d'objets sont en jeu. (nous allons le faire)
- On sait facilement trouver une bonne solution, mais pas forc\u00e9ment la meilleure, par exemple en adoptant une strat\u00e9gie gloutonne. (nous allons le faire)
- On ne sait pas trouver facilement (en temps polynomial) la meilleure solution. Si vous y arrivez, 1 Million de $ sont pour vous. (nous n'allons pas le faire)
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#31-petite-aide-technique-avant-de-commencer","title":"3.1\u00a0Petite aide technique avant de commencer","text":"Supposons qu'on dispose d'une liste \u00a0mylist = [[\"A\",3], [\"B\",2], [\"C\",8]]
.
Comment classer les \u00e9l\u00e9ments de cette liste par leur deuxi\u00e8me \u00e9l\u00e9ment ???
Nous allons proc\u00e9der en 2 temps.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#311-une-fonction-qui-renvoie-le-deuxieme-element","title":"3.1.1 Une fonction qui renvoie le deuxi\u00e8me \u00e9l\u00e9ment","text":"Exercice 1
Cr\u00e9er une fonction deuxieme
qui prend en param\u00e8tre un tableau lst
de type List
et qui renvoie le deuxi\u00e8me \u00e9l\u00e9ment de lst
.
Exemple d'utilisation
>>> simpsons = ['Bart', 'Lisa', 'Maggie']\n>>> deuxieme(simpsons)\n'Lisa'\n
Correction def deuxieme(lst) :\n return lst[1]\n
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#312-tri-de-la-liste-grace-a-cette-fonction-deuxieme","title":"3.1.2 Tri de la liste gr\u00e2ce \u00e0 cette fonction deuxieme
","text":"Nous allons utiliser la fonction sorted
, qui prend en param\u00e8tre une liste \u00e0 trier et une fonction de tri.
Exemple :
>>> mylist = [[\"A\", 3], [\"B\", 2], [\"C\", 8]]\n>>> mynewlist = sorted(mylist, key=deuxieme, reverse=True)\n>>> mynewlist\n[['C', 8], ['A', 3], ['B', 2]]\n
Exercice 2
On consid\u00e8re une liste releve
de 100 \u00e9l\u00e8ves avec leur note.
(liste cr\u00e9\u00e9e gr\u00e2ce au module magique faker)
releve = [['Lucas', 13], ['Patrick', 4], ['Michelle', 15], ['Emmanuel', 8], ['Jacqueline', 3], ['Laurent', 11], ['Marcelle', 18], ['Maurice', 14], ['Michelle', 12], ['Michelle', 16], ['Alexandra', 12], ['Patricia', 18], ['Danielle', 15], ['Marc', 2], ['H\u00e9l\u00e8ne', 3], ['Benjamin', 16], ['Laetitia', 2], ['Hugues', 10], ['Samuel', 14], ['\u00c9milie', 6], ['Emmanuel-Maurice', 15], ['Laurent', 13], ['St\u00e9phane', 11], ['David', 16], ['Yves', 7], ['Xavier', 12], ['V\u00e9ronique-Pauline', 6], ['Vincent-Hugues', 15], ['C\u00e9line', 11], ['\u00c9ric-Alain', 19], ['Samuel', 13], ['Gr\u00e9goire', 16], ['\u00c9lodie', 13], ['Daniel', 2], ['Joseph', 18], ['Mathilde', 18], ['Claudine', 16], ['Jean', 12], ['Marcel', 8], ['Nicolas', 7], ['Luc', 11], ['Gabrielle', 8], ['Marianne', 8], ['Paul-St\u00e9phane', 3], ['Florence', 18], ['Joseph', 18], ['Alice', 2], ['Fr\u00e9d\u00e9rique', 17], ['Laurent', 4], ['B\u00e9atrice', 10], ['Agn\u00e8s-C\u00e9cile', 13], ['Jos\u00e9phine', 3], ['Gilbert', 8], ['Claire', 15], ['Tristan', 7], ['Nathan', 18], ['C\u00e9cile', 7], ['Laurent-Roland', 14], ['Christine', 14], ['Olivier', 4], ['Patrick', 18], ['Margot', 11], ['Jessica', 9], ['Guillaume', 19], ['Nicole', 8], ['Louise', 11], ['Kevin', 11], ['Hugues-Martin', 19], ['Emmanuel', 10], ['Nicolas', 5], ['Christiane', 7], ['Charles', 8], ['Paulette', 15], ['Colette', 7], ['Vanessa-\u00c9milie', 6], ['\u00c9lise', 5], ['Denis', 2], ['Alfred', 20], ['Simone', 3], ['Oc\u00e9ane-Jos\u00e9phine', 9], ['Henri', 10], ['Rosalie', 6], ['Doroth\u00e9e', 9], ['R\u00e9my', 8], ['Marcel', 18], ['Odette', 19], ['Monique', 15], ['Mathieu', 12], ['Anne', 9], ['St\u00e9phanie-Dominique', 9], ['Astrid', 10], ['Ren\u00e9', 17], ['Laurence', 11], ['Oc\u00e9ane', 16], ['Hugues', 7], ['G\u00e9rard', 11], ['Xavier', 4], ['Patricia', 19], ['Aur\u00e9lie', 17], ['Th\u00e9odore', 5]]\n
Quel est l'\u00e9l\u00e8ve qui a obtenu la meilleure note ?
Correction releve = [['Lucas', 13], ['Patrick', 4], ['Michelle', 15], ['Emmanuel', 8], ['Jacqueline', 3], ['Laurent', 11], ['Marcelle', 18], ['Maurice', 14], ['Michelle', 12], ['Michelle', 16], ['Alexandra', 12], ['Patricia', 18], ['Danielle', 15], ['Marc', 2], ['H\u00e9l\u00e8ne', 3], ['Benjamin', 16], ['Laetitia', 2], ['Hugues', 10], ['Samuel', 14], ['\u00c9milie', 6], ['Emmanuel-Maurice', 15], ['Laurent', 13], ['St\u00e9phane', 11], ['David', 16], ['Yves', 7], ['Xavier', 12], ['V\u00e9ronique-Pauline', 6], ['Vincent-Hugues', 15], ['C\u00e9line', 11], ['\u00c9ric-Alain', 19], ['Samuel', 13], ['Gr\u00e9goire', 16], ['\u00c9lodie', 13], ['Daniel', 2], ['Joseph', 18], ['Mathilde', 18], ['Claudine', 16], ['Jean', 12], ['Marcel', 8], ['Nicolas', 7], ['Luc', 11], ['Gabrielle', 8], ['Marianne', 8], ['Paul-St\u00e9phane', 3], ['Florence', 18], ['Joseph', 18], ['Alice', 2], ['Fr\u00e9d\u00e9rique', 17], ['Laurent', 4], ['B\u00e9atrice', 10], ['Agn\u00e8s-C\u00e9cile', 13], ['Jos\u00e9phine', 3], ['Gilbert', 8], ['Claire', 15], ['Tristan', 7], ['Nathan', 18], ['C\u00e9cile', 7], ['Laurent-Roland', 14], ['Christine', 14], ['Olivier', 4], ['Patrick', 18], ['Margot', 11], ['Jessica', 9], ['Guillaume', 19], ['Nicole', 8], ['Louise', 11], ['Kevin', 11], ['Hugues-Martin', 19], ['Emmanuel', 10], ['Nicolas', 5], ['Christiane', 7], ['Charles', 8], ['Paulette', 15], ['Colette', 7], ['Vanessa-\u00c9milie', 6], ['\u00c9lise', 5], ['Denis', 2], ['Alfred', 20], ['Simone', 3], ['Oc\u00e9ane-Jos\u00e9phine', 9], ['Henri', 10], ['Rosalie', 6], ['Doroth\u00e9e', 9], ['R\u00e9my', 8], ['Marcel', 18], ['Odette', 19], ['Monique', 15], ['Mathieu', 12], ['Anne', 9], ['St\u00e9phanie-Dominique', 9], ['Astrid', 10], ['Ren\u00e9', 17], ['Laurence', 11], ['Oc\u00e9ane', 16], ['Hugues', 7], ['G\u00e9rard', 11], ['Xavier', 4], ['Patricia', 19], ['Aur\u00e9lie', 17], ['Th\u00e9odore', 5]]\n\ndef deuxieme(lst) :\n return lst[1]\n\nclassement = sorted(releve, key=deuxieme, reverse=True)\n\nprint(classement[0])\n
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#32-retour-sur-le-probleme-du-sac-a-dos","title":"3.2 Retour sur le probl\u00e8me du sac \u00e0 dos","text":" Le probl\u00e8me
On consid\u00e8re un sac de 40 kg et les objets suivants :
objet A B C D E F masse (en kg) 13 12 8 10 14 18 valeur (en \u20ac) 700 500 200 300 600 800 Quels objets faut-il prendre ?
Vous ne pouvez prendre qu'un seul objet de chaque type
(interdiction de donner la combinaison A-A-D, par exemple)
Strat\u00e9gie gloutonne :
- on va classer les objets dans l'ordre d\u00e9croissant de leur taux de valeur (taux de valeur = valeur / masse). Ainsi le premier \u00e9l\u00e9ment de la liste sera celui ayant le meilleur rapport valeur/masse.
- on prend le premier \u00e9l\u00e9ment de la liste, puis le deuxi\u00e8me, etc., tant que le sac peut encore les contenir.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#321-classement-des-objets","title":"3.2.1 Classement des objets","text":"On consid\u00e8re la liste
objets = [[\"A\", 13, 700], [\"B\", 12, 500], [\"C\", 8, 200], [\"D\", 10, 300], [\"E\", 14, 600], [\"F\", 18, 800]]\n
Exercice 3
Cr\u00e9er une fonction ratio
qui prend en param\u00e8tre une liste objet
d\u00e9crivant un objet (exemple : [\"C\", 8, 200]
) et qui renvoie le nombre valeur/masse (donc le 3\u00e8me \u00e9l\u00e9ment divis\u00e9 par le 2\u00e8me).
Exemple d'utilisation :
>>> ratio(['C', 8, 200])\n25.0\n
Correction def ratio(objet):\n return objet[2] / objet[1]\n
Exercice 4
Cr\u00e9er une liste objets_tries
qui reprend les objets de la liste objets
, class\u00e9s suivant leur taux de valeur (ratio valeur/masse)
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#322-calcul-de-la-solution-par-methode-gloutonne","title":"3.2.2 Calcul de la solution, par m\u00e9thode gloutonne","text":"Contrairement \u00e0 l'algorithme du rendu de monnaie, o\u00f9 chaque pi\u00e8ce est disponible en quantit\u00e9 infinie, on ne poss\u00e8de ici qu'un seul objet de chaque type.
Cela signifie qu'il va suffir de parcourir la liste des objets (pr\u00e9alablement class\u00e9s suivant leur taux de valeur) et de d\u00e9cider \u00e0 chaque fois si cet objet peut \u00eatre pris ou pas.
Exercice 5
\u00c9nonc\u00e9Aide \u00c9crire l'algorithme de r\u00e9solution gloutonne du probl\u00e8me du sac \u00e0 dos pour la liste objets
.
objets = [['A', 13, 700], ['B', 12, 500], ['C', 8, 200], ['D', 10, 300], ['E', 14, 600], ['F', 18, 800]]\n
objets = [['A', 13, 700], ['B', 12, 500], ['C', 8, 200], ['D', 10, 300], ['E', 14, 600], ['F', 18, 800]]\n\ndef ratio(objet):\n ...\n\nobjets_tries = ...\n\npoids_max = ...\npoids_sac = ...\n\nbutin = []\n\nfor objet in ...:\n poids_objet = ...\n if ... + ... <= ... :\n butin.append(...)\n ... += ...\n
Correction objets = [['A', 13, 700], ['B', 12, 500], ['C', 8, 200], ['D', 10, 300], ['E', 14, 600], ['F', 18, 800]]\n\ndef ratio(objet):\n return objet[2] / objet[1]\n\nobjets_tries = sorted(objets, key=ratio, reverse=True)\n\npoids_max = 40\npoids_sac = 0\n\nbutin = []\n\nfor objet in objets_tries:\n poids_objet = objet[1]\n if poids_objet + poids_sac <= poids_max :\n butin.append(objet[0])\n poids_sac += poids_objet\n
>>> butin\n ['A', 'F', 'C']\n>>> poids_sac\n39\n
Il faut donc choisir la combinaison A, F, C. Elle est bien valide (poids 39) et rapporte 1700.
Question (toujours la m\u00eame) :
L'algorithme glouton nous a-t-il donn\u00e9 la solution optimale ? Nous allons pour cela avoir recours \u00e0 la force brute pour tester toutes les combinaisons possibles.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#33-force-brute","title":"3.3 Force brute","text":" - Il faut cr\u00e9er une liste de mots binaires qui vont correspondre \u00e0 chaque combinaison. Par exemple,
101001
signifiera qu'on prend les objets A, C et F. Cette liste est de taille \\(2^n\\), o\u00f9 \\(n\\) est le nombre d'objets. C'est cela qui pose probl\u00e8me : avec 80 objets, on obtient une liste \u00e0 traiter qui contient plus de \\(10^{24}\\) objets, soit de l'ordre de grandeur du nombre d'\u00e9toiles dans l'Univers observable, ou de gouttes d'eau dans la mer, ou du nombre de grains de sables au Sahara... (voir https://fr.wikipedia.org/wiki/Ordres_de_grandeur_de_nombres ) - Une fois cette liste \u00e9tablie, il suffit de parcourir chaque \u00e9l\u00e9ment et de calculer le poids total et la valeur totale correspondante. Si le poids total d\u00e9passe le poids autoris\u00e9, on met la valeur \u00e0 0 car cette combinaison ne nous int\u00e9resse pas.
- Il ne reste qu'\u00e0 chercher la valeur maximale et regarder la combinaison \u00e0 laquelle elle correspond.
objets = [[\"A\", 13, 700], [\"B\", 12, 500], [\"C\", 8, 200], [\"D\", 10, 300], [\"E\", 14, 600], [\"F\", 18, 800]]\npoids_max = 40\n
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#331-la-liste-de-tous-les-mots-possibles","title":"3.3.1 La liste de tous les mots possibles","text":"combinaisons = []\nfor i in range(2**len(objets)):\n k = bin(i)[2:]\n s = '0'*(len(objets)-len(k)) + k\n combinaisons.append(s)\n
La liste combinaisons
contient bien les 64 mots possibles (\\(2^6=64\\)) :
>>> combinaisons\n ['000000',\n '000001',\n '000010',\n '000011',\n '000100',\n '000101',\n '000110',\n '000111',\n '001000',\n '001001',\n '001010',\n '001011',\n '001100',\n '001101',\n '001110',\n '001111',\n '010000',\n '010001',\n '010010',\n '010011',\n '010100',\n '010101',\n '010110',\n '010111',\n '011000',\n '011001',\n '011010',\n '011011',\n '011100',\n '011101',\n '011110',\n '011111',\n '100000',\n '100001',\n '100010',\n '100011',\n '100100',\n '100101',\n '100110',\n '100111',\n '101000',\n '101001',\n '101010',\n '101011',\n '101100',\n '101101',\n '101110',\n '101111',\n '110000',\n '110001',\n '110010',\n '110011',\n '110100',\n '110101',\n '110110',\n '110111',\n '111000',\n '111001',\n '111010',\n '111011',\n '111100',\n '111101',\n '111110',\n '111111']\n
valeurs = [] \npoids = []\nfor comb in combinaisons :\n poids_comb = 0\n valeur = 0\n for i in range(len(objets)): \n if comb[i] == '1':\n poids_comb += objets[i][1]\n valeur += objets[i][2]\n if poids_comb > poids_max :\n valeur = 0\n valeurs.append(valeur)\n poids.append(poids_comb)\n\nvaleur_max = max(valeurs)\nmeilleure_comb = combinaisons[valeurs.index(valeur_max)]\npoids_comb = poids[valeurs.index(valeur_max)]\n\nmot_sol = \"\"\nfor k in range(len(meilleure_comb)) :\n if meilleure_comb[k] == '1' :\n mot_sol += objets[k][0]\n
>>> mot_sol\n 'ABE'\n
Damned ! La force brute a mis en \u00e9vidence une combinaison meilleure que celle donn\u00e9e par l'algorithme glouton.
En effet la combinaison A-B-E est bien valide (poids total 39) et rapporte 1800, donc 100 de mieux que la solution gloutonne.
Par contre, la force brute est inenvisageable pour si le nombre d'objets est grand, alors que la strat\u00e9gie gloutonne reste tr\u00e8s rapide.
Conclusion
La strat\u00e9gie gloutonne donne tr\u00e8s rapidement des solutions satisfaisantes mais pas forc\u00e9ment optimales. Pour beaucoup de probl\u00e8mes (dont le probl\u00e8me du sac \u00e0 dos), la recherche d'une solution optimale sans passer par la force brute semble impossible (mais cela n'est pas (encore ?) d\u00e9montr\u00e9). Dans ce cas-l\u00e0, la strat\u00e9gie gloutonne peut \u00eatre employ\u00e9e pour avoir vite et bien une solution convenable, m\u00eame si peut-\u00eatre non optimale. On dit que la strat\u00e9gie gloutonne est une heuristique de r\u00e9solution. On sait que ce n'est pas forc\u00e9ment optimal, mais faute de mieux, on s'en contente...
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/intro_rendu/","title":"Vers l'algorithme de rendu de monnaie","text":"On veut coder la fonction rendu
qui prend pour param\u00e8tre un entier positif somme_a_rendre
et qui renvoie la liste des pi\u00e8ces \u00e0 donner.
Les pieces disponibles (en quantit\u00e9 illimit\u00e9e) sont stock\u00e9es dans une variable pieces = [200, 100, 50, 20, 10, 5, 2, 1]
.
Utilisation : rendu(13)
doit renvoyer [10, 2, 1]
>>> rendu(13)\n [10, 2, 1]\n>>> rendu(58)\n [50, 5, 2, 1]\n
Code \u00e0 trous def rendu(somme_a_rendre):\n pieces = [200, 100, 50, 20, 10, 5, 2, 1]\n solution = []\n ...\n ...\n ...\n ...\n ...\n ...\n ... \n return solution \n
Code \u00e0 trous def rendu(somme_a_rendre):\n pieces = [200, 100, 50, 20, 10, 5, 2, 1]\n solution = []\n i = ... \n while ... > ...:\n if ... <= ... : \n ....append(...) \n ... = ... - ... \n else :\n ... += ... \n return solution \n
Code \u00e0 trous def rendu(somme_a_rendre):\n pieces = [200, 100, 50, 20, 10, 5, 2, 1]\n solution = []\n i = 0 \n while ... > ...:\n if pieces[i] <= ... : \n solution.append(...) \n somme_a_rendre = ... - ... \n else :\n ... += ... \n return solution \n
Code \u00e0 trous def rendu(somme_a_rendre):\n pieces = [200, 100, 50, 20, 10, 5, 2, 1]\n solution = []\n i = 0 \n while somme_a_rendre > ...:\n if pieces[i] <= somme_a_rendre : \n solution.append(...) \n somme_a_rendre = ... - ... \n else :\n i += 1 \n return solution\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/","title":"4.7 Algorithme des KNN","text":"Algorithme des K-Nearest-Neighbours (KNN), aka les k-plus-proches-voisins
La m\u00e9thode KNN est une m\u00e9thode simple et efficace de classification. La classification est un enjeu majeur de l'Intelligence Artificielle :
- la cam\u00e9ra d'une voiture autonome per\u00e7oit un panneau, mais quel est ce panneau ?
- un grain de beaut\u00e9 est pris en photo par un dermatologue, ce grain de beaut\u00e9 est-il \u00e0 surveiller ?
- ...
La m\u00e9thode du KNN va trouver quels sont, dans une base de donn\u00e9es d\u00e9j\u00e0 bien remplie et labell\u00e9e, les k-objets (les 6 objets si \\(k=6\\) par exemple) qui se rapprochent le plus de l'objet \u00e0 classifier. En prenant ensuite la caract\u00e9ristique la plus fr\u00e9quente parmi ces 6 objets, on devine alors dans quelle cat\u00e9gorie notre objet doit se classer.
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#1-objectif","title":"1. Objectif","text":"Nous allons reprendre le jeu de donn\u00e9es sur les joueurs du Top14 utilis\u00e9 dans le cours \u00abTrier des donn\u00e9es\u00bb
Nous souhaitons pouvoir r\u00e9pondre \u00e0 cette question :
Question
Si on croise une personne (qu'on appelera joueur X) nous disant qu'elle veut jouer en Top14, et qu'elle nous donne son poids et sa taille, peut-on lui pr\u00e9dire \u00e0 quel poste elle devrait jouer ?
Nous devons donc cr\u00e9er une fonction conseil_poste
qui prend en argument poids
et taille
, qui sont les caract\u00e9ristiques du joueur X. Cette fonction prendra aussi en param\u00e8tre un nombre k
qui sera le nombre de voisins utilis\u00e9s pour d\u00e9terminer le poste conseill\u00e9.
La fonction doit renvoyer une cha\u00eene de caract\u00e8re correspondant au poste auquel on lui conseille de jouer.
Il va falloir pour cela classer tous les joueurs du Top14 suivant leur proximit\u00e9 morphologique avec notre joueur X, et prendre parmi les k
premiers joueurs le poste majoritaire.
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#2-fonction-distance-morphologique","title":"2. Fonction distance
morphologique","text":"Dans toute id\u00e9e de classification il y a l'id\u00e9e de distance. Il faut comprendre la distance comme une mesure de la diff\u00e9rence.
Comment mesurer la diff\u00e9rence physique entre deux joueurs de rugby ?
Fonction distance
\u00c9crire une fonction distance
qui re\u00e7oit en param\u00e8tres :
poids
: le poids du joueur X taille
: la taille du joueur X player
: un joueur de la liste joueurs
et qui renvoie la distance morphologique du joueur X avec player
.
Exemple d'utilisation :
>>> distance(93, 190, joueurs[34])\n445\n
Correction def distance(poids, taille, player):\n p = int(player['Poids'])\n t = int(player['Taille'])\n return (poids-p)**2 + (taille-t)**2\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#3-classement-des-joueurs-suivant-leur-proximite-morphologique","title":"3. Classement des joueurs suivant leur proximit\u00e9 morphologique","text":"De la m\u00eame mani\u00e8re qu'on avait class\u00e9 les joueurs suivant leur IMC, on peut les classer suivant leur proximit\u00e9 morphologique avec le joueur X.
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#31-fonction-second","title":"3.1 Fonction second
","text":"Fonction second
\u00c9crire une fonction second
qui re\u00e7oit en param\u00e8tres :
couple
: un couple de valeurs
et qui renvoie le deuxi\u00e8me \u00e9l\u00e9ment du couple.
Exemple d'utilisation :
>>> cpl = (\"vendredi\", 13)\n>>> second(cpl)\n13\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#32-classement-des-k-plus-proches-joueurs","title":"3.2 Classement des k plus proches joueurs","text":"Fonction classement_k_joueurs
\u00c9crire une fonction classement_k_joueurs
qui re\u00e7oit en param\u00e8tres :
poids
: le poids du joueur X taille
: la taille du joueur X k
: le nombre de joueurs les plus proches que l'on veut garder
et qui renvoie une liste contenant les k
joueurs class\u00e9s suivant leur proximit\u00e9 morphologique avec le joueur X.
Exemple d'utilisation :
>>> classement_k_joueurs(85, 186, 3)\n[{'Equipe': 'Bordeaux', 'Nom': 'Geoffrey CROS', 'Poste': 'Arri\u00e8re', 'Date de naissance': '08/03/1997', 'Taille': '185', 'Poids': '85'}, {'Equipe': 'Toulouse', 'Nom': 'Romain NTAMACK', 'Poste': 'Ouverture', 'Date de naissance': '01/05/1999', 'Taille': '186', 'Poids': '84'}, {'Equipe': 'Bayonne', 'Nom': 'Manuel ORDAS', 'Poste': 'Ouverture', 'Date de naissance': '21/02/1998', 'Taille': '186', 'Poids': '83'}]\n
Correction def classement_k_joueurs(poids, taille, k):\n couples = []\n for player in joueurs:\n couples.append((player, distance(poids, taille, player)))\n couples_tries = sorted(couples, key=second)\n joueurs_classes = [couple[0] for couple in couples_tries]\n return joueurs_classes[:k]\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#4-recherche-du-poste-le-plus-represente","title":"4. Recherche du poste le plus repr\u00e9sent\u00e9","text":""},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#41-dictionnaire-doccurence-des-postes","title":"4.1 Dictionnaire d'occurence des postes","text":"Fonction occurence
\u00c9crire une fonction occurence
qui re\u00e7oit en param\u00e8tres :
joueurs
: une liste de joueurs
et qui renvoie le dictionnaire compos\u00e9 diff\u00e9rents postes de ces joueurs, et du nombre de fois o\u00f9 ils apparaissent dans la liste joueurs
.
Exemple d'utilisation :
>>> occurence(joueurs)\n{'Pilier': 110, 'Talonneur': 50, '2\u00e8me ligne': 74, '3\u00e8me ligne': 111, 'M\u00eal\u00e9e': 42, 'Ouverture': 38, 'Centre': 71, 'Ailier': 64, 'Arri\u00e8re': 35}\n
Correction def occurence(joueurs):\n occ = {}\n for player in joueurs:\n if player['Poste'] in occ:\n occ[player['Poste']] += 1\n else:\n occ[player['Poste']] = 1\n return occ\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#42-tri-dun-dictionnaire","title":"4.2 Tri d'un dictionnaire","text":"Fonction cle_max
\u00c9crire une fonction cle_max
qui re\u00e7oit en param\u00e8tre :
d
: un dictionnaire dont les cl\u00e9s sont des chaines de caract\u00e8re et les valeurs sont des nombres.
et qui renvoie la cl\u00e9 associ\u00e9e \u00e0 la valeur maximale.
Exemple d'utilisation :
>>> d = {\"lundi\":13, \"mardi\":9, \"mercredi\":18, \"jeudi\":4}\n>>> cle_max(d)\n'mercredi'\n
Correction def cle_max(d):\n maxi = 0\n for key in d:\n if d[key] > maxi:\n maxi = d[key]\n key_max = key\n return key_max\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#43-fonction-conseil_poste","title":"4.3 Fonction conseil_poste
","text":"Fonction conseil_poste
\u00c9crire une fonction conseil_poste
qui re\u00e7oit en param\u00e8tres :
poids
: le poids du joueur X taille
: la taille du joueur X k
: le nombre de joueurs les plus proches sur lequel on se base pour faire la pr\u00e9diction
et qui renvoie le poste le plus compatible avec la morphologie de X.
Exemple d'utilisation :
>>> conseil_poste(70, 170, 6)\n'M\u00eal\u00e9e'\n>>> conseil_poste(120, 210, 6)\n'2\u00e8me ligne'\n
Correction def conseil_poste(poids, taille, k):\n joueurs_classes = classement_k_joueurs(poids, taille, k)\n dico = occurence(joueurs_classes)\n poste_conseille = cle_max(dico)\n return poste_conseille\n
Faire varier les diff\u00e9rents param\u00e8tres pour observer leur r\u00f4le respectif.
"},{"location":"T5_Traitement_de_donnees/sommaire/","title":"Th\u00e8me 5 : Traitement de donn\u00e9es","text":" - Manipulation de fichiers csv
- Trier des donn\u00e9es
- Utilisation du module Pandas
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/","title":"5.1 Manipulation de fichiers csv","text":"Les fichiers CSV (pour Comma Separated Values) sont des fichiers-texte (ils ne contiennent aucune mise en forme) utilis\u00e9s pour stocker des donn\u00e9es, s\u00e9par\u00e9es par des virgules (ou des points-virgules, ou des espaces...). Il n'y a pas de norme officielle du CSV.
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#1-ouverture-dun-fichier-csv-par-des-logiciels-classiques","title":"1. Ouverture d'un fichier CSV par des logiciels classiques","text":" - T\u00e9l\u00e9charger le fichier exemple.csv
- Ouvrir avec le Bloc-Notes ce fichier.
- Rajouter une ligne avec une personne suppl\u00e9mentaire, sauvegarder le fichier.
- Ouvrir le fichier avec LibreOffice.
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#2-exploitation-dun-fichier-csv-en-python-avec-le-module-csv","title":"2. Exploitation d'un fichier CSV en Python avec le module CSV","text":"L'utilisation d'un tableur peut \u00eatre d\u00e9licate lorsque le fichier CSV comporte un tr\u00e8s grand nombre de lignes. Python permet de lire et d'extraire des informations d'un fichier CSV m\u00eame tr\u00e8s volumineux, gr\u00e2ce \u00e0 des modules d\u00e9di\u00e9s, comme le bien-nomm\u00e9 csv
(utilis\u00e9 ici) ou bien pandas
(qui sera vu plus tard).
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#21-premiere-methode","title":"2.1 Premi\u00e8re m\u00e9thode","text":"Le script suivant :
import csv \nf = open('exemple.csv', \"r\", encoding = 'utf-8') # le \"r\" signifie \"read\", le fichier est ouvert en lecture seule\ndonnees = csv.reader(f) # donnees est un objet (sp\u00e9cifique au module csv) qui contient des lignes\n\nfor ligne in donnees: \n print(ligne)\n\nf.close() # toujours fermer le fichier !\n
donne :
['Pr\u00e9nom', 'Nom', 'Email', 'SMS']\n['John', 'Smith', 'john@example.com', '33123456789']\n['Harry', 'Pierce', 'harry@example.com', '33111222222']\n['Howard', 'Paige', 'howard@example.com', '33777888898']\n
Probl\u00e8mes
- Les donn\u00e9es ne sont pas structur\u00e9es : la premi\u00e8re ligne est la ligne des \u00abdescripteurs\u00bb (ou des \u00abchamps\u00bb), alors que les lignes suivantes sont les valeurs de ces descripteurs.
- La variable
donnees
n'est pas exploitable en l'\u00e9tat. Ce n'est pas une structure connue.
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#22-ameliorations","title":"2.2 Am\u00e9liorations","text":"Au lieu d'utiliser la fonction csv.reader()
, utilisons csv.DictReader()
. Comme son nom l'indique, elle renverra une variable contenant des dictionnaires.
Le script suivant :
import csv\nf = open('exemple.csv', \"r\", encoding = 'utf-8')\ndonnees = csv.DictReader(f)\n\nfor ligne in donnees:\n print(dict(ligne))\n\nf.close()\n
donne
{'Pr\u00e9nom': 'John', 'Nom': 'Smith', 'Email': 'john@example.com', 'SMS': '33123456789'}\n{'Pr\u00e9nom': 'Harry', 'Nom': 'Pierce', 'Email': 'harry@example.com', 'SMS': '33111222222'}\n{'Pr\u00e9nom': 'Howard', 'Nom': 'Paige', 'Email': 'howard@example.com', 'SMS': '33777888898'}\n
C'est mieux ! Les donn\u00e9es sont maintenant des dictionnaires. Mais nous avons juste \u00e9num\u00e9r\u00e9 3 dictionnaires. Comment r\u00e9-acc\u00e9der au premier d'entre eux, celui de John Smith ? Essayons :
>>> donnees[0]\n\n ---------------------------------------------------------------------------\n\n TypeError Traceback (most recent call last)\n\n <ipython-input-3-9914ab00321e> in <module>\n ----> 1 donnees[0]\n\n\n TypeError: 'DictReader' object does not support indexing\n
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#23-une-liste-de-dictionnaires","title":"2.3 Une liste de dictionnaires","text":"Nous allons donc cr\u00e9er une liste de dictionnaires.
Le script suivant :
import csv\nf = open('exemple.csv', \"r\", encoding = 'utf-8')\ndonnees = csv.DictReader(f)\namis = []\nfor ligne in donnees:\n amis.append(dict(ligne))\n\nf.close()\n
permet de faire ceci :
>>> amis\n\n [{'Pr\u00e9nom': 'John',\n 'Nom': 'Smith',\n 'Email': 'john@example.com',\n 'SMS': '33123456789'},\n {'Pr\u00e9nom': 'Harry',\n 'Nom': 'Pierce',\n 'Email': 'harry@example.com',\n 'SMS': '33111222222'},\n {'Pr\u00e9nom': 'Howard',\n 'Nom': 'Paige',\n 'Email': 'howard@example.com',\n 'SMS': '33777888898'}]\n\n>>> print(amis[0]['Email'])\n john@example.com\n\n>>> print(amis[2]['Nom'])\n Paige\n
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#3-un-fichier-un-peu-plus-interessant-les-joueurs-de-rugby-du-top14","title":"3. Un fichier un peu plus int\u00e9ressant : les joueurs de rugby du TOP14","text":"Le fichier top14.csv
contient tous les joueurs du Top14 de rugby, saison 2019-2020, avec leur date de naissance, leur poste, et leurs mensurations.
Ce fichier a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9 par R\u00e9mi Deniaud, de l'acad\u00e9mie de Bordeaux.
Question 1
Stocker dans une variable joueurs
les renseignements de tous les joueurs pr\u00e9sents dans ce fichier csv.
Correction import csv\nf = open('data/top14.csv', 'r', encoding = 'utf-8')\ndonnees = csv.DictReader(f)\njoueurs = []\nfor ligne in donnees:\n joueurs.append(dict(ligne))\n\nf.close()\n
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#31-premiere-analyse","title":"3.1 Premi\u00e8re analyse","text":"Question 2
Combien de joueurs sont pr\u00e9sents dans ce fichier ?
Correction >>> len(joueurs)\n595\n
Question 3
Quel est le nom du joueur n\u00b0486 ?
Correction >>> joueurs[486]['Nom']\n'Wenceslas LAURET'\n
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#32-extraction-de-donnees-particulieres","title":"3.2 Extraction de donn\u00e9es particuli\u00e8res","text":"Question 4
En 2019, o\u00f9 jouait Baptiste SERIN ?
Correction La m\u00e9thode la plus naturelle est de parcourir toute la liste jusqu'\u00e0 trouver le bon joueur, puis d'afficher son \u00e9quipe.
>>> for joueur in joueurs :\n if joueur['Nom'] == 'Baptiste SERIN' :\n print(joueur['Equipe'])\n
Une m\u00e9thode plus efficace est d'utiliser une liste par compr\u00e9hension incluant un test.
>>> clubSerin = [joueur['Equipe'] for joueur in joueurs if joueur['Nom'] == 'Baptiste SERIN']\n>>> clubSerin\n
Question 5
Qui sont les joueurs de plus de 140 kg ?
Attention \u00e0 bien convertir en entier la chaine de caract\u00e8re renvoy\u00e9e par la cl\u00e9 Poids
, \u00e0 l'aide de la fonction int()
.
Correction >>> lourds = [(joueur['Nom'], joueur['Poids']) for joueur in joueurs if int(joueur['Poids']) > 140]\n>>> lourds\n
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#4-exploitation-graphique","title":"4. Exploitation graphique","text":"Nous allons utiliser le module Matplotlib pour illustrer les donn\u00e9es de notre fichier csv.
Pour tracer un nuage de points (par l'instruction plt.plot
), Matplotlib requiert :
- une liste
X
contenant toutes les abscisses des points \u00e0 tracer. - une liste
Y
contenant toutes les ordonn\u00e9es des points \u00e0 tracer.
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#41-exemple","title":"4.1 Exemple","text":"import matplotlib.pyplot as plt\nX = [0, 1, 3, 6]\nY = [12, 10, 7, 15]\nplt.plot(X, Y, 'ro') \nplt.show()\n
Dans l'instruction plt.plot(X, Y, 'ro')
: X
sont les abscisses, Y
sont les ordonn\u00e9es, 'ro'
signifie : - qu'on veut des points (c'est le
'o'
, plus de choix ici). - qu'on veut qu'ils soient rouges (c'est le
'r'
plus de choix ici).
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#42-application","title":"4.2 Application","text":"Question 6
Afficher sur un graphique tous les joueurs de rugby du Top14, en mettant le poids en abscisse et la taille en ordonn\u00e9e.
Correction X = [int(joueur['Poids']) for joueur in joueurs]\nY = [int(joueur['Taille']) for joueur in joueurs]\nplt.plot(X, Y, 'ro') \nplt.show()\n
Question 7
Faire appara\u00eetre ensuite les joueurs \u00e9voluant au poste de Centre en bleu, et les 2\u00e8me lignes en vert.
Correction #tous les joueurs\nX = [int(joueur['Poids']) for joueur in joueurs]\nY = [int(joueur['Taille']) for joueur in joueurs]\nplt.plot(X, Y, 'ro') \n\n#on recolorie les Centres en bleu\nX = [int(joueur['Poids']) for joueur in joueurs if joueur['Poste'] == 'Centre']\nY = [int(joueur['Taille']) for joueur in joueurs if joueur['Poste'] == 'Centre']\nplt.plot(X, Y, 'bo')\n\n#on recolorie les 2\u00e8me ligne en vert\nX = [int(joueur['Poids']) for joueur in joueurs if joueur['Poste'] == '2\u00e8me ligne']\nY = [int(joueur['Taille']) for joueur in joueurs if joueur['Poste'] == '2\u00e8me ligne']\nplt.plot(X, Y, 'go')\n\n\nplt.show()\n
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/","title":"5.2 Trier des donn\u00e9es","text":"Nous reprenons notre fichier de joueurs de rugby du Top14. : top14.csv
import csv\nf = open('top14.csv', \"r\", encoding = 'utf-8')\ndonnees = csv.DictReader(f)\njoueurs = []\nfor ligne in donnees:\n joueurs.append(dict(ligne))\n\nf.close()\n
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#1-creer-une-fonction-filtre","title":"1. Cr\u00e9er une fonction filtre","text":"Question 1
Cr\u00e9er une fonction joueursEquipe
qui renvoie une liste contenant les fiches de tous les joueurs de l'\u00e9quipe equipe
pass\u00e9e en param\u00e8tre.
Exemple d'utilisation :
>>> joueursEquipe('Bordeaux')\n[{'Equipe': 'Bordeaux', 'Nom': 'Jefferson POIROT', 'Poste': 'Pilier', 'Date de naissance': '01/11/1992', 'Taille': '181', 'Poids': '117'}, {'Equipe': 'Bordeaux', 'Nom': 'Lasha TABIDZE', 'Poste': 'Pilier', 'Date de naissance': '04/07/1997', 'Taille': '185', 'Poids': '117'}, {'Equipe': 'Bordeaux', 'Nom': 'Laurent DEL.....\n
Correction def joueursEquipe(equipe): \n return [player for player in joueurs if player['Equipe'] == equipe]\n
Question 2
D\u00e9finir de la m\u00eame mani\u00e8re une fonction joueursPoste
qui prend une cha\u00eene de caract\u00e8res poste
et qui renvoie la liste des fiches des joueurs jouant \u00e0 ce poste.
Exemple d'utilisation :
>>> joueursPoste(\"Talonneur\")\n[{'Equipe': 'Agen', 'Nom': 'Cl\u00e9ment MARTINEZ', 'Poste': 'Talonneur', 'Date de naissance': '14/03/1996', 'Taille': '181', 'Poids': '105'}, {'Equipe': 'Agen', 'Nom': 'Marc BARTHOMEUF', 'Poste': 'T...\n
Correction def joueursPoste(poste): \n return [player for player in joueurs if player['Poste'] == poste]\n
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#2-utilisation-dune-fonction-de-tri","title":"2. Utilisation d'une fonction de tri","text":""},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#21-le-probleme","title":"2.1 Le probl\u00e8me","text":"Comment classer les joueurs suivant leur taille ? La fonction sorted(liste)
est efficace sur les listes : elle renvoie une nouvelle liste tri\u00e9e dans l'ordre croissant.
>>> mylist = [4,2,8,6]\n>>> mynewlist = sorted(mylist)\n>>> print(mynewlist)\n [2, 4, 6, 8]\n
Mais comment trier un dictionnaire ?
>>> test = sorted(joueurs)\n
---------------------------------------------------------------------------\n\nTypeError Traceback (most recent call last)\n\n<ipython-input-14-de081d14a3da> in <module>\n----> 1 test = sorted(joueurs)\n\n\nTypeError: '<' not supported between instances of 'dict' and 'dict'\n
Il est normal que cette tentative \u00e9choue : un dictionnaire poss\u00e8de plusieurs cl\u00e9s diff\u00e9rentes. Ici, plusieurs cl\u00e9s peuvent \u00eatre des crit\u00e8res de tri : la taille, le poids.
Nous allons donc utiliser la m\u00eame strat\u00e9gie que celle utilis\u00e9e pour le probl\u00e8me du sac \u00e0 dos.
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#22-un-exemple-de-tri-de-dictionnaire","title":"2.2 Un exemple de tri de dictionnaire","text":"Simpsons = [{\"Prenom\" : \"Bart\", \"age estim\u00e9\": \"10\"},\n {\"Prenom\" : \"Lisa\", \"age estim\u00e9\": \"8\"},\n {\"Prenom\" : \"Maggie\", \"age estim\u00e9\": \"1\"},\n {\"Prenom\" : \"Homer\", \"age estim\u00e9\": \"38\"},\n {\"Prenom\" : \"Marge\", \"age estim\u00e9\": \"37\"}]\n\ndef age(personnage):\n return int(personnage[\"age estim\u00e9\"])\n
>>> age(Simpsons[0])\n 10\n
La cr\u00e9ation de cette fonction age
va nous permettre de sp\u00e9cifier une cl\u00e9 de tri, par le param\u00e8tre key
:
Tri d'un dictionnaire
>>> triSimpsons = sorted(Simpsons, key=age)\n
>>> triSimpsons\n [{'Prenom': 'Maggie', 'age estim\u00e9': '1'},\n {'Prenom': 'Lisa', 'age estim\u00e9': '8'},\n {'Prenom': 'Bart', 'age estim\u00e9': '10'},\n {'Prenom': 'Marge', 'age estim\u00e9': '37'},\n {'Prenom': 'Homer', 'age estim\u00e9': '38'}]\n
On peut aussi inverser l'ordre de tri :
>>> triSimpsons = sorted(Simpsons, key=age, reverse=True)\n>>> triSimpsons\n [{'Prenom': 'Homer', 'age estim\u00e9': '38'},\n {'Prenom': 'Marge', 'age estim\u00e9': '37'},\n {'Prenom': 'Bart', 'age estim\u00e9': '10'},\n {'Prenom': 'Lisa', 'age estim\u00e9': '8'},\n {'Prenom': 'Maggie', 'age estim\u00e9': '1'}]\n
Question 3
Trier les joueurs du Top14 par taille.
Correction def taillePlayer(player) :\n return int(player['Taille'])\n\njoueurs_taille_croissant = sorted(joueurs, key=taillePlayer)\n
Question 4
Trier les joueurs du Top14 par poids.
Correction def poidsPlayer(player) :\n return int(player['Poids'])\n\njoueurs_poids_croissant = sorted(joueurs, key=poidsPlayer)\n
Question 5
Trier les joueurs de Bordeaux suivant leur Indice de Masse Corporelle (IMC )
Correction def IMC(player):\n masse = int(player['Poids'])\n taille_m = int(player['Taille']) / 100\n return masse / taille_m**2\n\njoueursUBB = [player for player in joueurs if player['Equipe'] == 'Bordeaux']\njoueursUBB_tri = sorted(joueursUBB, key=IMC)\n
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#3-recherche-des-joueurs-de-profil-physique-similaire","title":"3. Recherche des joueurs de profil physique similaire","text":""},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#31-distance-entre-deux-joueurs","title":"3.1 Distance entre deux joueurs","text":"Question 6
Construire une fonction distance
qui renvoie la somme des carr\u00e9s des diff\u00e9rences de tailles et de poids entre deux joueurs joueur1
et joueur2
, pass\u00e9s en param\u00e8tres.
\\[d = (p_1-p_2)^2 + (t_1-t_2)^2\\] Cette fonction nous permettra d'estimer la diff\u00e9rence morphologique entre deux joueurs.
Exemple d'utilisation :
>>> distance(joueurs[23], joueurs[31])\n244\n
V\u00e9rification :
>>> joueurs[23]\n{'Equipe': 'Agen', 'Nom': 'Alban CONDUCH\u00c9', 'Poste': 'Centre', 'Date de naissance': '29/10/1996', 'Taille': '190', 'Poids': '102'}\n>>> joueurs[31]\n{'Equipe': 'Agen', 'Nom': 'JJ TAULAGI', 'Poste': 'Arri\u00e8re', 'Date de naissance': '18/06/1993', 'Taille': '180', 'Poids': '90'}\n
\\((102-90)^2+(190-180)^2=244\\)
Correction def distance(joueur1,joueur2):\n p1 = int(joueur1['Poids'])\n p2 = int(joueur2['Poids'])\n t1 = int(joueur1['Taille'])\n t2 = int(joueur2['Taille'])\n return (p1 - p2)**2 + (t1 - t2)**2\n
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#32-distance-des-joueurs-avec-baptiste-serin","title":"3.2 Distance des joueurs avec Baptiste Serin","text":"Retrouvons d'abord le num\u00e9ro de Baptiste Serin dans notre classement de joueurs :
>>> for k in range(len(joueurs)) :\n if joueurs[k]['Nom'] == 'Baptiste SERIN' :\n print(k)\n530\n
>>> joueurs[530]\n {'Equipe': 'Toulon',\n 'Nom': 'Baptiste SERIN',\n 'Poste': 'M\u00eal\u00e9e',\n 'Date de naissance': '20/06/1994',\n 'Taille': '180',\n 'Poids': '79'}\n
Baptiste SERIN est donc le joueur num\u00e9ro 530.
Question 7
Cr\u00e9er une fonction distanceSerin
qui prend en param\u00e8tre un joueur et qui renvoie sa diff\u00e9rence avec Baptiste Serin.
Exemple d'utilisation :
>>> distanceSerin(joueurs[18])\n745\n
Correction def distanceSerin(joueur):\n return distance(joueurs[530], joueur)\n
Question 8
Classer l'ensemble des joueurs du Top14 suivant leur diff\u00e9rence morphologique avec Baptiste Serin (du plus proche au plus \u00e9loign\u00e9). Afficher le nom des 10 premiers joueurs.
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/","title":"5.3 Utilisation du module Pandas","text":"Les manipulations de ce cours pourront \u00eatre effectu\u00e9es sur un Notebook de Capytale.
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#1-introduction-et-premiere-dataframe","title":"1. Introduction et premi\u00e8re dataframe","text":"Le module csv
utilis\u00e9 pr\u00e9c\u00e9demment se contente de lire les donn\u00e9es structur\u00e9es. Il ne fait aucun effort particulier pour analyser les donn\u00e9es. Nous nous en sommes aper\u00e7us lorsqu'il a fallu convertir par int()
toutes les valeurs num\u00e9riques, qui \u00e9taient interpr\u00e9t\u00e9es comme des cha\u00eenes de caract\u00e8res. La biblioth\u00e8que pandas est par contre sp\u00e9cialement con\u00e7ue pour l'analyse des donn\u00e9es (data analysis) : elle est donc naturellement bien plus performante.
Importation du module pandas
L'import se fait classiquement par :
import pandas as pd \n
Le type de variable dans lequel pandas
va stocker les donn\u00e9es s'appelle une dataframe, qui sera souvent abr\u00e9g\u00e9e par df
.
Nous allons retravailler avec le fichier top14.csv
.
Premi\u00e8re dataframe
Nos donn\u00e9es seront ensuite import\u00e9es dans la dataframe df
par l'instruction :
df = pd.read_csv('top14.csv', encoding = 'utf-8') \n
>>> type(df)\n<class 'pandas.core.frame.DataFrame'>\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#2-observation-des-donnees","title":"2. Observation des donn\u00e9es","text":"Que contient la variable df
?
>>> df\n Equipe Nom Poste Date de naissance Taille Poids\n0 Agen Anton PEIKRISHVILI Pilier 18/09/1987 183 122\n1 Agen Dave RYAN Pilier 21/04/1986 183 116\n2 Agen Giorgi TETRASHVILI Pilier 31/08/1993 177 112\n3 Agen Kamaliele TUFELE Pilier 11/10/1995 182 123\n4 Agen Malino VANA\u00cf Pilier 04/05/1993 183 119\n.. ... ... ... ... ... ...\n590 Toulouse Werner KOK Ailier 27/01/1993 177 78\n591 Toulouse Yoann HUGET Ailier 02/06/1987 190 97\n592 Toulouse Matthis LEBEL Arri\u00e8re 25/03/1999 185 91\n593 Toulouse Maxime M\u00c9DARD Arri\u00e8re 16/11/1986 180 85\n594 Toulouse Thomas RAMOS Arri\u00e8re 23/07/1995 178 86\n\n[595 rows x 6 columns]\n
Les donn\u00e9es sont pr\u00e9sent\u00e9es dans l'ordre originel du fichier.
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#21-structure-globale-des-donnees","title":"2.1 Structure globale des donn\u00e9es","text":"La structure des donn\u00e9es : info
>>> df.info()\n<class 'pandas.core.frame.DataFrame'>\nRangeIndex: 595 entries, 0 to 594\nData columns (total 6 columns):\n # Column Non-Null Count Dtype \n--- ------ -------------- ----- \n 0 Equipe 595 non-null object\n 1 Nom 595 non-null object\n 2 Poste 595 non-null object\n 3 Date de naissance 595 non-null object\n 4 Taille 595 non-null int64 \n 5 Poids 595 non-null int64 \ndtypes: int64(2), object(4)\nmemory usage: 28.0+ KB\n
On peut y constater une tr\u00e8s bonne nouvelle : les donn\u00e9es num\u00e9riques sont reconnues comme telles (type int64
).
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#22-acces-a-une-fiche-particuliere","title":"2.2 Acc\u00e8s \u00e0 une fiche particuli\u00e8re","text":"D'apr\u00e8s la commande pr\u00e9c\u00e9dente, il y a 595 entr\u00e9es dans notre fichier de donn\u00e9es. L'acc\u00e8s \u00e0 une fiche particuli\u00e8re se fera avec la commande loc
.
Acc\u00e8s \u00e0 une fiche : loc
>>> df.loc[312]\nEquipe Lyon\nNom Charlie NGATAI\nPoste Centre\nDate de naissance 17/08/1990\nTaille 188\nPoids 103\nName: 312, dtype: object\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#23-premieres-et-dernieres-lignes","title":"2.3 Premi\u00e8res et derni\u00e8res lignes","text":"Il est toutefois possible d'avoir uniquement les premi\u00e8res lignes du fichier avec la commande head()
et les derni\u00e8res du fichier avec la commande tail()
. Ces commandes peuvent recevoir en param\u00e8tre un nombre entier :
Les premi\u00e8res lignes du fichier : head
>>> df.head()\n Equipe Nom Poste Date de naissance Taille Poids\n0 Agen Anton PEIKRISHVILI Pilier 18/09/1987 183 122\n1 Agen Dave RYAN Pilier 21/04/1986 183 116\n2 Agen Giorgi TETRASHVILI Pilier 31/08/1993 177 112\n3 Agen Kamaliele TUFELE Pilier 11/10/1995 182 123\n4 Agen Malino VANA\u00cf Pilier 04/05/1993 183 119\n\n>>> df.head(2)\n Equipe Nom Poste Date de naissance Taille Poids\n0 Agen Anton PEIKRISHVILI Pilier 18/09/1987 183 122\n1 Agen Dave RYAN Pilier 21/04/1986 183 116\n
Les derni\u00e8res lignes du fichier : tail
>>> df.tail()\n Equipe Nom Poste Date de naissance Taille Poids\n590 Toulouse Werner KOK Ailier 27/01/1993 177 78\n591 Toulouse Yoann HUGET Ailier 02/06/1987 190 97\n592 Toulouse Matthis LEBEL Arri\u00e8re 25/03/1999 185 91\n593 Toulouse Maxime M\u00c9DARD Arri\u00e8re 16/11/1986 180 85\n594 Toulouse Thomas RAMOS Arri\u00e8re 23/07/1995 178 86\n\n>>> df.tail(3)\n Equipe Nom Poste Date de naissance Taille Poids\n592 Toulouse Matthis LEBEL Arri\u00e8re 25/03/1999 185 91\n593 Toulouse Maxime M\u00c9DARD Arri\u00e8re 16/11/1986 180 85\n594 Toulouse Thomas RAMOS Arri\u00e8re 23/07/1995 178 86\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#3-analyse-automatique-et-filtrage","title":"3. Analyse automatique et filtrage","text":""},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#31-extraction-dune-colonne","title":"3.1 Extraction d'une colonne","text":"L'id\u00e9e g\u00e9n\u00e9rale est que l'on va cr\u00e9er de nouveaux objets contenant uniquement les renseignements qui nous int\u00e9ressent.
Extraction d'une colonne : df[colonne]
Pour cr\u00e9er une liste contenant uniquement les donn\u00e9es num\u00e9riques de la colonne poids
, il suffit d'\u00e9crire :
poids = df['Poids']\n
La variable poids
est un objet de type Series
(assimilable \u00e0 une liste) qui va pouvoir \u00eatre exploit\u00e9e tr\u00e8s facilement.
On peut d'ailleurs acc\u00e9der \u00e0 un \u00e9l\u00e9ment particulier de cette variable :
>>> poids[15]\n114\n
On confirme donc une excellente nouvelle : les poids sont bien consid\u00e9r\u00e9s nativement comme des nombres. On peut donc se servir de mani\u00e8re tr\u00e8s intuitive de cette fonctionnalit\u00e9 pour faire des graphiques tr\u00e8s facilement, sans conversion comme dans le module csv
!
Pour trouver le poids minimal de cette s\u00e9rie, on utilisera naturellement la fonction min
:
>>> min(poids)\n70\n
Pour tracer notre nuage de points poids-taille, le code sera donc simplement :
import matplotlib.pyplot as plt\nX = df['Poids']\nY = df['Taille']\nplt.plot(X, Y, 'ro')\nplt.show()\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#32-tri-et-analyse-automatique-des-donnees","title":"3.2 Tri et Analyse automatique des donn\u00e9es","text":"L'interpr\u00e9tation num\u00e9rique permet \u00e0 pandas
d'analyser automatiquement les donn\u00e9es, avec notamment la fonction describe()
.
R\u00e9sum\u00e9 des donn\u00e9es num\u00e9riques : describe
>>> df['Taille'].describe()\ncount 595.000000\nmean 186.559664\nstd 7.572615\nmin 169.000000\n25% 181.000000\n50% 186.000000\n75% 192.000000\nmax 208.000000\nName: Taille, dtype: float64\n
On voit donc que les principaux indicateurs statistiques sont propos\u00e9s.
D'ailleurs, on peut tr\u00e8s facilement tracer des boites \u00e0 moustaches avec la fonction boxplot()
.
graph_taille = df.boxplot(\"Taille\")\ngraph_taille.plot()\nplt.show()\n
Pour les donn\u00e9es non-num\u00e9riques, la commande describe()
n'est que peu d'utilit\u00e9. Elle renseigne toutefois la valeur la plus fr\u00e9quente (en statistiques, le mode ou valeur modale) gr\u00e2ce \u00e0 describe().top
.
Valeur modale de donn\u00e9es non-num\u00e9riques : describe().top
>>> df['Poste'].describe().top\n'3\u00e8me ligne'\n
Pour avoir un d\u00e9tail plus pr\u00e9cis de la r\u00e9partition des donn\u00e9es, on peut utiliser value_counts
:
R\u00e9partition des valeurs : value_counts
>>> df['Poste'].value_counts()\n3\u00e8me ligne 111\nPilier 110\n2\u00e8me ligne 74\nCentre 71\nAilier 64\nTalonneur 50\nM\u00eal\u00e9e 42\nOuverture 38\nArri\u00e8re 35\nName: Poste, dtype: int64\n
Il est possible aussi de trier la dataframe en lui indiquant la colonne de tri :
Trier les donn\u00e9es : sort_values
>>> classement_par_taille = df.sort_values(by='Taille', ascending = True)\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#4-filtres-et-recherches","title":"4. Filtres et recherches","text":"Le principe du filtrage va \u00eatre de cr\u00e9er une nouvelle dataframe ne contenant que des lignes correspondant \u00e0 un certain crit\u00e8re.
Filtrage des lignes : df[bool\u00e9en]
Comment cr\u00e9er une dataframe ne contenant que les joueurs de l'UBB ? L'id\u00e9e syntaxique est d'\u00e9crire \u00e0 l'int\u00e9rieur de df[]
le test qui permettra le filtrage.
>>> UBB = df[df['Equipe'] == 'Bordeaux']\n
Le bool\u00e9en df['Equipe'] == 'Bordeaux'
doit se comprendre ainsi : on ne veut garder que les joueurs dont le champ Equipe
est \u00e9gal \u00e0 'Bordeaux'
. >>> UBB\n Equipe Nom Poste Date de naissance Taille Poids\n80 Bordeaux Jefferson POIROT Pilier 01/11/1992 181 117\n81 Bordeaux Lasha TABIDZE Pilier 04/07/1997 185 117\n82 Bordeaux Laurent DELBOULB\u00c8S Pilier 17/11/1986 181 106\n83 Bordeaux Lekso KAULASHVILI Pilier 27/08/1992 187 120\n84 Bordeaux Peni RAVAI Pilier 16/06/1990 185 119\n...\n
Exercice 1
Cr\u00e9er une dataframe grands
qui contient tous les joueurs mesurant plus de 2 m\u00e8tres (inclus).
Correction >>> grands = df[df['Taille'] >= 200]\n
Pour effectuer des op\u00e9rations sur les bool\u00e9ens, on utilisera le symbole &
pour le ET et |
pour le OU.
Exercice 2
Cr\u00e9er une dataframe grands_et_gros
qui contient tous les joueurs mesurant plus de 2 m\u00e8tres (inclus) et pesant plus de 120 kg (inclus).
Correction >>> grands_gros = df[(df['Taille'] >= 200) & (df['Poids'] >= 120)]\n
Autre solution, en utilisant la datadframe grands
de l'exercice 1 :
>>> grands_gros = grands[grands['Poids'] >= 120]\n
Exercice 3
Trouver en une seule ligne le joueur le plus l\u00e9ger du Top14.
Correction >>> df[df['Poids'] == min(df['Poids'])]\n Equipe Nom Poste Date de naissance Taille Poids\n491 Racing92 Teddy IRIBAREN M\u00eal\u00e9e 25/09/1990 170 70\n
ou bien
>>> df.sort_values(by='Poids', ascending=True).head(1)\n
Exercice 4
Tracer le nuage de points poids-taille comme pr\u00e9c\u00e9demment, mais en marquant d'un point bleu les 2\u00e8mes ligne et d'un point rouge les piliers.
Correction import pandas as pd\nimport matplotlib.pyplot as plt\n\ndf = pd.read_csv('top14.csv', encoding = 'utf-8') \n\nX = df['Poids']\nY = df['Taille']\nplt.plot(X, Y, 'ro')\n\n\nX = df[df['Poste'] == '2\u00e8me ligne']['Poids']\nY = df[df['Poste'] == '2\u00e8me ligne']['Taille']\nplt.plot(X, Y, 'bo')\n\n\nX = df[df['Poste'] == 'Pilier']['Poids']\nY = df[df['Poste'] == 'Pilier']['Taille']\nplt.plot(X, Y, 'go')\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#5-modification-de-la-structure-rajout-dune-colonne","title":"5. Modification de la structure : rajout d'une colonne","text":"Afin de pouvoir trier les joueurs suivant de nouveaux crit\u00e8res, nous allons rajouter un champ pour chaque joueur. Prenons un exemple stupide : fabriquons un nouveau champ 'Poids apr\u00e8s les vacances'
qui contiendra le poids des joueurs augment\u00e9 de 8 kg. Ceci se fera simplement par :
Rajout d'une colonne
>>> df['Poids apr\u00e8s les vacances'] = df['Poids'] + 8\n
On voit apparaitre dans la dataframe df
une nouvelle colonne
>>> df.head()\n Equipe Nom Poste ... Taille Poids Poids apr\u00e8s les vacances\n0 Agen Anton PEIKRISHVILI Pilier ... 183 122 130\n1 Agen Dave RYAN Pilier ... 183 116 124\n2 Agen Giorgi TETRASHVILI Pilier ... 177 112 120\n3 Agen Kamaliele TUFELE Pilier ... 182 123 131\n4 Agen Malino VANA\u00cf Pilier ... 183 119 127\n\n[5 rows x 7 columns]\n
Pour supprimer cette colonne sans int\u00e9r\u00eat, il suffit de faire :
del df['Poids apr\u00e8s les vacances'] \n
Exercice 5
Q1. Cr\u00e9er une colonne contenant l'IMC de chaque joueur.
Correction >>> df['IMC'] = df['Poids'] / (df['Taille']/100)**2\n
Q2. Cr\u00e9er une nouvelle dataframe contenant tous les joueurs du Top14 class\u00e9s par ordre d'IMC croissant.
Correction >>> df_imc = df.sort_values(by='IMC', ascending = True)\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#6-retour-sur-le-knn","title":"6.\u00a0Retour sur le KNN","text":"Comme dans ce cours, nous allons construire une fonction conseil_poste
recevant en param\u00e8tres :
df
: la dataframe contenant nos donn\u00e9es poids
: le poids du joueur X taille
: la taille du joueur X k
: le nombre de joueurs les plus proches sur lequel on se base pour faire la pr\u00e9diction
qui renvoie le poste le plus compatible avec la morphologie de X.
Il est maintenant possible de coder cette fonction beaucoup plus simplement (mais alors VRAIMENT beaucoup) qu'avec le module csv
.
Il va nous suffir de :
- cr\u00e9er une nouvelle colonne contenant la distance de chaque joueur avec le joueur X.
- classer la dataframe suivant cette nouvelle colonne.
- ne garder que les
k
premiers \u00e9l\u00e9ments. - renvoyer le poste le plus fr\u00e9quent parmi ces
k
premiers \u00e9lements.
Algorithme KNN
import pandas as pd\n\ndf = pd.read_csv('top14.csv', encoding = 'utf-8') \n\ndef conseil_poste(df, poids, taille, k):\n ...\n ...\n ...\n ...\n
Correction import pandas as pd\n\ndf = pd.read_csv('top14.csv', encoding = 'utf-8') \n\ndef conseil_poste(df, poids, taille, k):\n df['distance'] = (df['Poids']-poids)**2 + (df['Taille']-taille)**2\n df = df.sort_values(by = 'distance', ascending=True)\n df = df.head(k)\n return df['Poste'].describe().top \n
>>> conseil_poste(df, 70, 160, 10)\n'M\u00eal\u00e9e'\n>>> conseil_poste(df, 130, 160, 10)\n'Pilier'\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/exercices/","title":"Analyse des passagers du Titanic","text":"Nous allons travailler avec le fichier titanic.csv
.
"},{"location":"T6_IHM_Web/pagesperso/","title":"Pages personnelles","text":""},{"location":"T6_IHM_Web/pagesperso/#o-installation-du-serveur-xampp","title":"O. Installation du serveur Xampp","text":"Dans le dossier T\u00e9l\u00e9chargements :
sudo chmod +x xampp-linux....run
puis
sudo ./xampp-linux....run
"},{"location":"T6_IHM_Web/pagesperso/#1-demarrage","title":"1. D\u00e9marrage","text":""},{"location":"T6_IHM_Web/pagesperso/#11-serveur-demarre-ou-pas","title":"1.1 Serveur d\u00e9marr\u00e9 ou pas ?","text":"Dans la barre d'adresse de son navigateur, taper localhost
ou bien 127.0.0.1
.
Si aucune page n'appara\u00eet, c'est que le serveur n'est pas d\u00e9marr\u00e9.
"},{"location":"T6_IHM_Web/pagesperso/#12-demarrer-le-serveur","title":"1.2 D\u00e9marrer le serveur","text":"Dans un terminal, taper
sudo /opt/lampp/lampp start
"},{"location":"T6_IHM_Web/pagesperso/#13-connaitre-son-adresse-ip","title":"1.3 Conna\u00eetre son adresse IP","text":"Dans un terminal,
ip addr
regarder 4 lignes avant la fin, chercher une adresse IP commen\u00e7ant par 192.168.1.XXX
.
"},{"location":"T6_IHM_Web/pagesperso/#2-mettre-en-production-son-site","title":"2. Mettre en production son site","text":"Dans un terminal ouvert depuis le dossier contenant ses pages :
sudo cp mapage.html /opt/lampp/htdocs/
Si on veut tout copier :
sudo cp * /opt/lampp/htdocs/
"},{"location":"T6_IHM_Web/pagesperso/#3-liens-vers-la-page-de-chaque-eleve","title":"3. Liens vers la page de chaque \u00e9l\u00e8ve","text":" - page de M. Lassus
- page de Malone
- page de Tim\u00e9o
- page de Moustapha
- page de Jean
- page de Sarah
- page d'Antoine
- page de Nathana\u00ebl
- page de Lucas
- page de Nathan
- page de P\u00e9rine
- page de Rita
- page de Tesnime
- page de Max
- page de No\u00e9
- page de Gead
- page de Mikha\u00eflo
"},{"location":"T6_IHM_Web/sommaire/","title":"Th\u00e8me 6 : IHM sur le web","text":" - Interactions sur une page web
- Protocole HTTP : \u00e9tude du chargement d'une page web
- Requ\u00eates GET, POST et formulaires
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/","title":"6.1 Pages web et interactions","text":""},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#1-le-cas-le-plus-simple-la-meme-page-pour-tout-le-monde","title":"1. Le cas le plus simple : la m\u00eame page pour tout le monde","text":"Nous allons tout d'abord consid\u00e9rer le cas o\u00f9 le serveur renvoie une page unique, identique pour tous les utilisateurs. De plus, l'utilisateur ne pourra pas agir sur sa page : il n'y a aucune interactivit\u00e9.
Exemple de page statique c\u00f4t\u00e9 serveur et c\u00f4t\u00e9 utilisateur :
- cette merveille de page web.
- plus compl\u00e8te, mais tout aussi statique : cette page Wikipedia consacr\u00e9e \u00e0 John Conway.
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#11-html-pur","title":"1.1 html
pur","text":"Lorsque le client demande au serveur le contenu d'une page web, celui-ci lui renvoie, dans le cas le plus simple, une simple page html
. html
est un langage dit \u00ab \u00e0 balises \u00bb. Ce n'est pas \u00e0 proprement parler un langage de programmation, mais plut\u00f4t un langage de description de contenu. Il a \u00e9t\u00e9 invent\u00e9 en 1992 par Tim Berners-Lee. La version actuellement utilis\u00e9e est le html5
.
Exemple de page web minimale
<!DOCTYPE html>\n<html lang='fr'>\n <head>\n <meta charset=\"utf-8\">\n <title>Un titre tr\u00e8s original</title>\n </head>\n\n <body>\n <p>Ceci est le texte introductif de ma page.</p>\n <p>\n <h1> Ceci est un titre de niveau 1 </h1>\n Mais sans rien d'int\u00e9ressant.\n <h2> Ceci est un titre de niveau 2 </h2>\n <ul>\n <li> le d\u00e9but d'une liste indent\u00e9e </li>\n <li> la suite ... </li>\n </ul> \n Pour apprendre le fonctionnement des balises, voir <a href=\"https://developer.mozilla.org/fr/docs/Apprendre/HTML/Introduction_%C3%A0_HTML/Getting_started\"> ici</a> par exemple !\n </p>\n </body>\n</html>\n
Vous pouvez contempler ici le rendu de cette magnifique page.
Exercice 1
\u00c9nonc\u00e9 - Cr\u00e9ez un dossier contenant un fichier
mapage.html
. - Cr\u00e9ez une page contenant une image et un lien vers le site du lyc\u00e9e.
- Vous pouvez utiliser le logiciel Geany, install\u00e9 sur notre Debian.
- Vous pouvez aussi utiliser un \u00e9diteur en ligne avec rendu instantan\u00e9, du type https://www.w3schools.com/tryit/
lien t\u00e9l\u00e9chargement XAMPP
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#12-html-css","title":"1.2 html
+ css
","text":"L'acronyme css
signifie Cascading Style Sheets. L'id\u00e9e est de regrouper dans un seul fichier toutes les informations relatives \u00e0 la mise en forme des \u00e9l\u00e9ments de la page html. De mani\u00e8re tr\u00e8s simplifi\u00e9e, on peut dire que le fichier html
s'occupe du fond tandis que le fichier css
s'occupe de la forme.
Le fichier css
(souvent nomm\u00e9 style.css
et appel\u00e9 feuille de style) doit \u00eatre r\u00e9f\u00e9renc\u00e9 au d\u00e9but du fichier html
, au sein de la balise <head>
.
Exemple de couple html
/ css
minimal
-
fichier index.html
:
<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <title>page test</title>\n <link href=\"style.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body>\n <p>\n <h1> Ceci est un titre de niveau 1 </h1>\n Mais sans rien d'int\u00e9ressant.\n <h2> Ceci est un titre de niveau 2 </h2>\n </p>\n </body>\n</html>\n
-
fichier style.css
:
html {\n font-size: 15px;\n font-family: sans-serif;\n background-color: lightgray; \n }\n\nh1 {\n color: red;\n}\n
Vous pouvez contempler ici le nouveau rendu de cette encore plus magnifique page.
En savoir plus
- le cours d'OpenClassrooms : https://openclassrooms.com/fr/courses/1603881-apprenez-a-creer-votre-site-web-avec-html5-et-css3
Exercice 2
Reprenez votre page de l'exercice 1 et rajoutez une feuille de style.
Exercice 3
- Allez sur le site http://sudouest.fr, et affichez l'inspecteur d'\u00e9lement de votre navigateur (g\u00e9n\u00e9ralement accessible en appuyant sur
F12
) - Modifiez le plus possible les attributs de style de la page.
Exercice 4
- R\u00e9soudre ce challenge
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#2-quand-le-client-peut-agir-sur-sa-page-exemple-avec-javascript","title":"2. Quand le client peut agir sur sa page : exemple avec JavaScript","text":"Jusqu'\u00e0 pr\u00e9sent, la page web envoy\u00e9e par le serveur est :
- identique quel que soit le client.
- statique apr\u00e8s r\u00e9ception sur l'ordinateur du client.
Le JavaScript va venir r\u00e9gler le probl\u00e8me n\u00b02 : il est possible de fabriquer une page sur laquelle le client va pouvoir agir localement, sans avoir \u00e0 redemander une nouvelle page au serveur.
Invent\u00e9 en 1995 par Brendan Eich pour le navigateur Netscape, le langage JavaScript s'est impos\u00e9 comme la norme aupr\u00e8s de tous les navigateurs pour apporter de l'interactivit\u00e9 aux pages web.
Exemple de couple html
/ javascript
minimal
Notre fichier index.html
fait r\u00e9f\u00e9rence, au sein d'une balise <script>
, \u00e0 un fichier externe script.js
qui contiendra notre code JavaScript.
-
fichier index.html
:
<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <title>un peu d'action</title>\n <link href=\"style.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body>\n <script src=\"script.js\"></script>\n <p>\n <h2>Une page web extr\u00eamement dynamique</h2>\n </p>\n <div>\n\n <label>Changez la couleur d'arri\u00e8re-plan:</label>\n\n <button type=\"button\" onclick=\"choix('yellow');\">jaune</button>\n\n <button type=\"button\" onclick=\"choix('green');\">vert</button>\n\n <button type=\"button\" onclick=\"choix('purple');\">violet</button> \n\n <input onchange=\"choix(this.value)\" type=\"color\" />\n\n </div>\n <div>\n <p>\n En JavaScript, le nom de la couleur choisie est :\n </p>\n <p id=\"resultat\"></p>\n </div>\n </body>\n</html>\n
-
fichier script.js
:
function choix(color){\n document.body.style.background = color;\n document.getElementById(\"resultat\").innerHTML=color;\n}\n
Le r\u00e9sultat de cette page peut \u00eatre consult\u00e9 ici. (oui, j'ai confondu le jaune et le rose)
Commentaires
- Au sein du bouton d\u00e9clar\u00e9 par la balise
button
, l'attribut onclick
re\u00e7oit le nom d'une fonction d\u00e9clar\u00e9e \u00e0 l'int\u00e9rieur du fichier script.js
, ici la fonction choix()
. - Cette fonction nous permet de modifier \u00e0 la fois l'aspect esth\u00e9tique de la page (changement de la couleur de background) mais aussi le contenu de cette page, en faisant afficher le nom de la couleur.
La puissance du JavaScript permet de r\u00e9aliser aujourd'hui des interfaces utilisateurs tr\u00e8s complexes au sein d'un navigateur, \u00e9quivalentes \u00e0 celles produites par des logiciels externes (pensez \u00e0 la version web de Discord ou aux Google Docs, par ex.). Bien s\u00fbr, dans ces cas complexes, le serveur est aussi sollicit\u00e9 pour modifier la page, comme nous le verrons en partie 3.
En savoir plus
- le guide JavaScript de la fondation Mozilla : https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide
- le cours d'OpenClassrooms : https://openclassrooms.com/fr/courses/7696886-apprenez-a-programmer-avec-javascript
Exercice 5
- Reprenez votre page cr\u00e9\u00e9e aux exercices pr\u00e9c\u00e9dents et rajoutez du JavaScript pour la rendre dynamique. Vous \u00eates libres !
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#3-quand-la-page-est-fabriquee-a-la-demande-pour-le-client-exemple-avec-php","title":"3. Quand la page est fabriqu\u00e9e \u00e0 la demande pour le client : exemple avec PHP","text":"Rappelons que toutes les pages que nous avons cr\u00e9\u00e9es jusqu'\u00e0 pr\u00e9sent sont uniform\u00e9ment envoy\u00e9es par le serveur au client. Aucune \u00abpr\u00e9paration\u00bb de la page en amont n'a lieu sur le serveur, aucun dialogue n'a lieu avec le serveur une fois que la page a \u00e9t\u00e9 livr\u00e9e. \u00c9videmment, si le web \u00e9tait comme ceci, il ne serait qu'une gigantesque biblioth\u00e8que en consultation seule (ce fut le cas pendant longtemps, et ce qui n'\u00e9tait d\u00e9j\u00e0 pas si mal).
Les langages serveurs, parmi lesquels PHP (pr\u00e9sent sur environ 80% des serveurs), Python (via le framework Django), Java, Ruby, C#, permettent de rajouter de l'interactivit\u00e9 c\u00f4t\u00e9 serveur.
Il convient de rappeler la diff\u00e9rence fondamentale entre une page statique (c\u00f4t\u00e9 serveur) et une page dynamique (c\u00f4t\u00e9 serveur) :
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#31-page-statique-cote-serveur","title":"3.1 Page statique (c\u00f4t\u00e9 serveur) :","text":"Lors d'une requ\u00eate d'un client vers un serveur, si le client demande la page index.html
, une copie exacte du fichier index.html
est transmise au client sur sa machine.
Exemple : la page http://glassus1.free.fr/interesting.html que vous avez d\u00e9j\u00e0 consult\u00e9e se trouve telle quelle sur le serveur mis \u00e0 disposition par Free pour l'h\u00e9bergement des pages personnelles :
Depuis votre navigateur, l'affichage du code-source (par Ctrl-U) vous donnera le fichier html tel qu'il \u00e9tait stock\u00e9 sur le serveur.
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#32-page-dynamique-cote-serveur","title":"3.2 Page dynamique (c\u00f4t\u00e9 serveur) :","text":"Lors d'une requ\u00eate d'un client vers un serveur, si le client demande la page test.php
, un code html est g\u00e9n\u00e9r\u00e9 \u00e0 partir du fichier test.php
puis est transmise au client sur sa machine. Le fichier transmis ne contient plus de balises php
, il ne comporte que des balises html
classiques.
Exemple : la consultation de la page http://glassus1.free.fr/test.php va renvoyer la page suivante :
dont le code-source est :
Notez bien que ce code-source ne contient que du html
.
Allons regarder cette page du c\u00f4t\u00e9 du serveur :
Le contenu de cette page est :
<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <title>Quel jour sommes-nous</title>\n </head>\n <body>\n <p>\n <?php\n $date = date(\"d-m-Y\");\n Print(\"Nous sommes le $date\");\n ?>\n </p>\n</body>\n</html>\n
On y rep\u00e8re la balise <?php>
:
<?php\n $date = date(\"d-m-Y\");\n Print(\"Nous sommes le $date\");\n ?>\n
Ce code php
a donc g\u00e9n\u00e9r\u00e9, lors de l'appel au serveur, le code html
: Nous sommes le 13-04-2020\n
Vous pouvez tester du code PHP et la page g\u00e9n\u00e9r\u00e9e par exemple sur ce site.
Voil\u00e0 comment un serveur peut adapter la page qu'il renvoie, suivant l'utilisateur qui la demande. Nous verrons prochainement comment par des requ\u00eates le client peut envoyer des param\u00e8tres au serveur, et comment celui-ci modifie sa r\u00e9ponse en cons\u00e9quence.
En savoir plus : https://www.php.net/manual/fr/tutorial.firstpage.php
"},{"location":"T6_IHM_Web/6.2_Protocole_HTTP/cours/","title":"6.2 Protocole HTTP : \u00e9tude du chargement d'une page web","text":""},{"location":"T6_IHM_Web/6.2_Protocole_HTTP/cours/#le-protocole-http-des-requetes-et-des-reponses","title":"Le protocole HTTP : des requ\u00eates et des r\u00e9ponses","text":"HTTP (HyperText Transfer Protocol) est le protocole qui r\u00e9git la communication entre :
- le client (la machine de l'utilisateur qui souhaite obtenir une page web). On dit que le client effectue une requ\u00eate.
- le serveur (la machine sur laquelle sont stock\u00e9s les fichiers n\u00e9cessaires \u00e0 l'affichage de cette page web). Le serveur va renvoyer une r\u00e9ponse.
"},{"location":"T6_IHM_Web/6.2_Protocole_HTTP/cours/#deroule-dune-requete","title":"D\u00e9roul\u00e9 d'une requ\u00eate","text":"Prenons pour exemple la requ\u00eate d'un navigateur vers la page http://glassus1.free.fr/interesting.html
- le navigateur analyse l'url : la demande concerne la page
interesting.html
, stock\u00e9e sur le serveur glassus1.free.fr
. - une demande est pr\u00e9alablement effectu\u00e9e aupr\u00e8s pour obtenir l'adresse IP du serveur
glassus1.free.fr
(qui est en fait un sous-domaine du serveur des pages personnelles de l'op\u00e9rateur Free). Ici, l'adresse IP sera 212.27.63.111
(on la retrouvera dans la capture de la fen\u00eatre d'Outils de dev\u00e9loppement). - la requ\u00eate est effectu\u00e9e sur le port 80 de l'adresse
212.27.63.111
. - la r\u00e9ponse est envoy\u00e9e au navigateur, qui en extrait la charge utile et proc\u00e8de \u00e0 l'affichage de la page.
"},{"location":"T6_IHM_Web/6.2_Protocole_HTTP/cours/#analyse-a-laide-dun-navigateur","title":"Analyse \u00e0 l'aide d'un navigateur","text":"Observons \u00e0 partir de l'Inspecteur d'\u00e9l\u00e9ment d'un navigateur (ici Firefox) les informations qui transitent lors de la requ\u00eate et de la r\u00e9ponse.
- Point 1 : La requ\u00eate de type GET vers l'url
http://glassus1.free.fr/interesting.html
a g\u00e9n\u00e9r\u00e9 un code de r\u00e9ponse 200 OK, ce qui signifie que la requ\u00eate a \u00e9t\u00e9 trait\u00e9e et que la r\u00e9ponse contenant la page a \u00e9t\u00e9 envoy\u00e9e. Vous pouvez trouver \u00e0 l'adresse https://developer.mozilla.org/fr/docs/Web/HTTP/Status la totalit\u00e9 des codes de r\u00e9ponse possibles. Citons par exemple : - 304 Not Modified : la page n'a pas eu besoin d'\u00eatre renvoy\u00e9e, elle indique au navigateur d'aller la rechercher dans son cache. On peut obtenir ce code de r\u00e9ponse en actualisant la page actuelle
http://glassus1.free.fr/interesting.fr
(qui est une page ultra-basique, et n'\u00e9volue pas). Pour r\u00e9-obtenir un code 200, il faut faire un hard-refresh en appuyant sur Maj pendant l'actualisation. - 403 Forbidden : le client n'a pas le droit d'acc\u00e8s \u00e0 la page.
- 404 Not Found : la page demand\u00e9e est introuvable
- 500 Internal Server Error : le serveur a rencontr\u00e9 une erreur qu'il ne sait pas traiter.
- Point 2 : en observant la taille totale des donn\u00e9es transf\u00e9r\u00e9es (388 octets), on peut comprendre que la r\u00e9ponse faite par le serveur est constitu\u00e9e :
- d'un En-t\u00eate (264 octets) qui contient :
HTTP/1.1 200 OK\nDate: Wed, 22 Apr 2020 08:02:01 GMT\nServer: Apache/ProXad [Jan 23 2019 19:58:42]\nLast-Modified: Sun, 12 Apr 2020 16:39:55 GMT\nETag: \"15d7c75-7c-5e93445b\"\nConnection: close\nAccept-Ranges: bytes\nContent-Length: 124\nContent-Type: text/html\n
- du corps de la R\u00e9ponse (dont on sait d'apr\u00e8s l'en-t\u00eate qu'il p\u00e8se 124 octets). Ce corps de la r\u00e9ponse est la charge utile de la r\u00e9ponse. Elle contient ici le code html de la page :
<!DOCTYPE html>\n<html>\n<head>\n<title>Waouh</title>\n</head>\n<body>\nCeci est vraiment une jolie page web.\n</body>\n</html>\n
Remarque : on peut observer que le navigateur a aussi effectu\u00e9 (de sa propre initiative) une requ\u00eate vers un fichier favicon.ico
qui est l'icone de la page web dans les onglets du navigateur ou la barre de favoris. Ce fichier \u00e9tait bien pr\u00e9sent sur le serveur (ce n'est pas toujours le cas), il a donc \u00e9t\u00e9 envoy\u00e9 dans la r\u00e9ponse du serveur.
De mani\u00e8re g\u00e9n\u00e9rale, une requ\u00eate vers un site web moins \u00e9l\u00e9mentaire va occasionner une multitude de r\u00e9ponses.
Par exemple, l'appel au site www.lyceemauriac.fr
g\u00e9n\u00e8re 129 requ\u00eates/r\u00e9ponses diff\u00e9rentes, compos\u00e9es de fichiers html, css, js, de fichiers de fontes woff2, d'images jpg, png...
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/","title":"6.3 Requ\u00eates GET, POST et formulaires","text":""},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#1-cote-client-comment-envoyer-des-parametres-a-un-serveur","title":"1. C\u00f4t\u00e9 client : comment envoyer des param\u00e8tres \u00e0 un serveur ?","text":""},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#11-la-methode-get","title":"1.1. La m\u00e9thode GET","text":"Consid\u00e9rons le formulaire suivant, inclus dans une page html ouverte dans le navigateur du client :
Le mot de passe est :\n<form action=\"cible2.php\" method=\"get\">\n<p>\n <input type=\"password\" name=\"pass\" /> \n <input type=\"submit\" value=\"Valider\" />\n</p>\n</form>\n
Aper\u00e7u :
Explications :
- le fichier
cible2.php
est le fichier sur le serveur qui recevra les param\u00e8tres contenus dans le formulaire. - le param\u00e8tre sera nomm\u00e9
pass
et sera de type password
, ce qui signifie qu'on n'affichera pas les caract\u00e8res tap\u00e9s par l'utilisateur. On aurait pu aussi avoir un type : text
: le texte s'affiche en clair (pour les login par ex) radio
: pour une s\u00e9lection (d'un seul \u00e9l\u00e9ment) checkbox
: pour une s\u00e9lection (\u00e9ventuellement multiple)
- un bouton comportant le label \u00abValider\u00bb d\u00e9clenchera l'envoi (gr\u00e2ce au type particulier
submit
) des param\u00e8tres (ici un seul, la variable pass
) au serveur.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#test","title":"Test :","text":" - Rendez-vous sur la page http://glassus1.free.fr/ex_get.html et testez un mot de passe.
- Observez attentivement l'url de la page sur laquelle vous \u00eates arriv\u00e9s. Que remarquez-vous ?
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#la-methode-get-et-la-confidentialite","title":"La m\u00e9thode GET et la confidentialit\u00e9 :","text":"Les param\u00e8tres pass\u00e9s au serveur par la m\u00e9thode GET sont transmis dans l'url de la requ\u00eate. Ils sont donc lisibles en clair par n'importe qui.
\u00c9videmment, c'est une m\u00e9thode catastrophique pour la transmission des mots de passe. Par contre, c'est une m\u00e9thode efficace pour acc\u00e9der directement \u00e0 une page particuli\u00e8re : ainsi l'url https://www.google.fr/search?q=bordeaux nous am\u00e8nera directement au r\u00e9sultat de la recherche Google sur le mot-cl\u00e9 \u00abbordeaux\u00bb.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#12-la-methode-post","title":"1.2. La m\u00e9thode POST","text":"Dans notre code de formulaire du 1.1, modifions l'attribut method
, auparavant \u00e9gal \u00e0 \"get\"
. Passons-le \u00e9gal \u00e0 \"post\"
:
Le mot de passe est :\n<form action=\"cible2.php\" method=\"post\">\n<p>\n <input type=\"password\" name=\"pass\" /> \n <input type=\"submit\" value=\"Valider\" />\n</p>\n</form>\n
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#test_1","title":"Test :","text":" - Rendez-vous sur la page http://glassus1.free.fr/ex_post.html et testez un mot de passe.
- Observez attentivement l'url de la page sur laquelle vous \u00eates arriv\u00e9s. Que remarquez-vous ?
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#la-methode-post-et-la-confidentialite","title":"La m\u00e9thode POST et la confidentialit\u00e9 :","text":"Les param\u00e8tres pass\u00e9s au serveur par la m\u00e9thode POST ne sont pas visibles dans l'url de la requ\u00eate. Ils sont contenus dans le corps de la requ\u00eate, mais non affich\u00e9s sur le navigateur.
Donc, la transmission du mot de passe est bien s\u00e9curis\u00e9e par la m\u00e9thode POST ?
Pas du tout ! Si le protocole de transmission est du http
et non pas du https
, n'importe qui interceptant le trafic peut lire le contenu de la requ\u00eate et y trouver le mot de passe en clair.
Exemple avec Wireshark :
Le contenu de la variable \"pass\"
est donc visible dans le contenu de la requ\u00eate.
Le passage en https
chiffre le contenu de la requ\u00eate et emp\u00eache donc la simple lecture du mot de passe.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#resume-quand-utiliser-get-ou-post","title":"R\u00e9sum\u00e9 : quand utiliser GET ou POST ?","text":" - GET : la m\u00e9thode GET doit \u00eatre utilis\u00e9e quand les param\u00e8tres \u00e0 envoyer :
- n'ont pas de caract\u00e8re confidentiel.
- n'ont pas vocation \u00e0 cr\u00e9er des modifications sur le serveur (ceci est plus une bonne pratique qu'une interdiction technique)
- ne sont pas trop longs. En effet, vu qu'ils seront contenus dans l'url, il peut exister des limites de longueur sp\u00e9cifiques au navigateur. Une taille inf\u00e9rieure \u00e0 2000 caract\u00e8re est conseill\u00e9e. Si vous vous demandez \u00e0 quoi peuvent servir des url si longues, songez \u00e0 ce type d'url, (ici PythonTutor) o\u00f9 le code du programme \u00e0 analyser est contenu dans l'url : http://pythontutor.com/visualize.html#code=L%20%3D%20%5B2,%203,%206,%207,%2011,%2014,%2018,%2019,%2024%5D%0A%0Adef%20trouve_dicho%28L,%20n%29%20%3A%0A%20%20%20%20indice_debut%20%3D%200%0A%20%20%20%20indice_fin%20%3D%20len%28L%29%20-%201%0A%20%20%20%20while%20indice_debut%20%3C%3D%20indice_fin%20%3A%0A%20%20%20%20%20%20%20%20indice_centre%20%3D%20%28indice_debut%20%2B%20indice_fin%29%20//%202%0A%20%20%20%20%20%20%20%20valeur_centrale%20%3D%20L%5Bindice_centre%5D%0A%20%20%20%20%20%20%20%20if%20valeur_centrale%20%3D%3D%20n%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20indice_centre%0A%20%20%20%20%20%20%20%20if%20valeur_centrale%20%3C%20n%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20indice_debut%20%3D%20indice_centre%20%2B%201%0A%20%20%20%20%20%20%20%20else%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20indice_fin%20%3D%20indice_centre%20-%201%0A%20%20%20%20return%20None%0A%0Aprint%28trouve_dicho%28L,14%29%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false
-
POST : la m\u00e9thode POST doit \u00eatre utilis\u00e9e quand les param\u00e8tres \u00e0 envoyer :
- ont un caract\u00e8re confidentiel (attention, \u00e0 coupler imp\u00e9rativement avec un protocole de chiffrement).
- peuvent avoir une longueur tr\u00e8s importante (le param\u00e8tre \u00e9tant dans le corps de la requ\u00eate et non plus dans l'url, sa longueur peut \u00eatre arbitraire).
- ont vocation \u00e0 provoquer des changements sur le serveur. Ainsi, un ordre d'achat sur un site de commerce sera n\u00e9cessairement pass\u00e9 par une m\u00e9thode POST. Les navigateurs pr\u00e9viennent alors le risque de \u00abdouble commande\u00bb lors d'une actualisation malencontreuse de la page par l'utilisateur par la fen\u00eatre :
Cette fen\u00eatre est caract\u00e9ristique de l'utilisation d'une m\u00e9thode POST.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#2-cote-serveur-comment-recuperer-les-parametres-envoyes","title":"2. C\u00f4t\u00e9 serveur : comment r\u00e9cup\u00e9rer les param\u00e8tres envoy\u00e9s ?","text":"Du c\u00f4t\u00e9 du serveur, le langage utilis\u00e9 (PHP, Java...) doit r\u00e9cup\u00e9rer les param\u00e8tres envoy\u00e9s pour modifier les \u00e9lements d'une nouvelle page, mettre \u00e0 jour une base de donn\u00e9es, etc. Comment sont r\u00e9cup\u00e9r\u00e9es ces valeurs ?
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#exemple-en-php","title":"Exemple en PHP","text":"L'acronyme PHP signifie **P**HP : **H**ypertext **P**rocessor (c'est un acronyme r\u00e9cursif).
Notre exemple va contenir deux fichiers :
- une page
page1.html
, qui contiendra un formulaire et qui renverra, par la m\u00e9thode GET, un param\u00e8tre \u00e0 la page page2.php
. - une page
page2.php
, qui g\u00e9n\u00e8rera un code html
personnalis\u00e9 en fonction du param\u00e8tre re\u00e7u.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#page1html","title":"page1.html
","text":"<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <title>exemple</title>\n </head>\n <body>\n Votre OS actuel est un : \n<form action=page2.php method=\"get\">\n<p>\n <input type=\"radio\" name=\"OS\" value=\"Windows\"> Windows </input>\n <input type=\"radio\" name=\"OS\" value=\"MacOS\"> MacOS </input>\n <input type=\"radio\" name=\"OS\" value=\"GNU/Linux\"> GNU/Linux </input>\n</p>\n<p> \n <input type=\"submit\" value=\"Valider\" />\n</p>\n</form>\n </body>\n</html>\n
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#page2php","title":"page2.php
","text":" <!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <title>Le meilleur OS</title>\n </head>\n <body>\n <p>\n <?php\n if (isset($_GET['OS']))\n {\n Print(\"Vous avez raison, \");\n echo $_GET['OS'];\n Print(\" est le meilleur des OS.\");\n }\n ?>\n </p>\n\n</body>\n</html>\n
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#detail-du-fonctionnement","title":"D\u00e9tail du fonctionnement :","text":" - \u00c0 l'arriv\u00e9e sur la page
page1.html
, un formulaire de type boutons radio lui propose : - Lorsque l'utilisateur clique sur \u00abValider\u00bb, la variable nomm\u00e9e
OS
va recevoir la valeur choisie et va \u00eatre transmise par une requ\u00eate GET \u00e0 l'url donn\u00e9e par la variable action
d\u00e9finie en d\u00e9but de formulaire. Ici, le navigateur va donc demander \u00e0 acc\u00e9der \u00e0 la page page2.php?OS=MacOS
(par exemple) - Le serveur PHP qui h\u00e9berge la page
page2.php
va recevoir la demande d'acc\u00e8s \u00e0 la page ainsi que la valeur de la variable OS
. Dans le code PHP, on reconnait : - le bool\u00e9en
isset($_GET['OS'])
qui v\u00e9rifie si le param\u00e8tre OS
a bien re\u00e7u une valeur. - l'expression
$_GET['OS']
qui r\u00e9cup\u00e8re cette valeur. Si la valeur avait \u00e9t\u00e9 transmise par m\u00e9thode POST (pour un mot de passe, par exemple), la variable aurait \u00e9t\u00e9 r\u00e9cup\u00e9r\u00e9e par $_POST['OS']
. Elle n'aurait par contre pas \u00e9t\u00e9 affich\u00e9e dans l'url de la page.
- La page
page2.php?OS=MacOS
s'affiche sur le navigateur de l'utilisateur :
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#remarque","title":"Remarque","text":"L'exemple ci-dessus est un mauvais exemple : rien ne justifie l'emploi d'un serveur distant. L'affichage de ce message aurait tr\u00e8s bien pu se faire en local sur le navigateur du client, en Javascript par exemple.
L'envoi de param\u00e8tre \u00e0 un serveur distant est n\u00e9cessaire pour aller interroger une base de donn\u00e9es, par exemple (lorsque vous remplissez un formulaire sur le site de la SNCF, les bases de donn\u00e9es des horaires de trains, des places disponibles et de leurs tarifs ne sont pas h\u00e9berg\u00e9es sur votre ordinateur en local...).
La v\u00e9rification d'un mot de passe doit aussi se faire sur un serveur distant.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#exercice-attaque-par-force-brute-et-requete-get","title":"Exercice : attaque par force brute et requ\u00eate GET","text":""},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#pre-requis-1-le-module-requests-en-python","title":"Pr\u00e9-requis 1 : le module requests
en python","text":"Le module requests
permet d'aller chercher le contenu d'une page web, suivant la syntaxe ci-dessous. Testez le code ci-dessous :
import requests\np = requests.get(\"http://glassus1.free.fr/interesting.html\", verify = False)\nprint(p.text)\n
La sortie en console est :
<!DOCTYPE html>\n<html>\n\n<head>\n\n<title>Waouh</title>\n</head>\n\n<body>\nCeci est vraiment une jolie page web.\n</body>\n\n</html>\n
Notre programme Python se comporte donc \u00abcomme un navigateur\u00bb : il se rend sur une page, effectue une requ\u00eate et r\u00e9cup\u00e8re la page renvoy\u00e9e.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#pre-requis-2-lextraction-dun-fichier-texte-sous-forme-de-liste","title":"Pr\u00e9-requis 2 : l'extraction d'un fichier texte sous forme de liste","text":"Le code ci-dessous permet de collecter dans une liste mots
l'ensemble des mots compris dans le fichier monfichiertexte.txt
(si celui-ci comprend un mot par ligne)
mots = open(\"monfichiertexte.txt\").read().splitlines()\n
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#exercice","title":"Exercice :","text":"Votre objectif est de trouver le mot de passe demand\u00e9 sur la page http://glassus1.free.fr/exoBF.html
Vous allez vous appuyer sur un leak (fuite) tr\u00e8s c\u00e9l\u00e8bre de mots de passe , qui est le leak du site Rockyou. Dans la base de donn\u00e9es de ce site, 32 millions de mots de passe \u00e9taient stock\u00e9s en clair \u00af\\_(\u30c4)_/\u00af
.
Lorsque le site a \u00e9t\u00e9 pirat\u00e9 (par une injection SQL, voir le cours de Terminale), ces 32 millions de mots de passe se sont retrouv\u00e9s dans la nature. Ils sont aujourd'hui t\u00e9l\u00e9chargeables librement, et constituent un dictionnaire de 14 341 564 mots de passe diff\u00e9rents (car parmi les 32 millions d'utilisateurs, beaucoup utilisaient des mots de passe identiques). Ce fichier est t\u00e9l\u00e9chargeable ici, mais attention il p\u00e8se 134 Mo.
Nous allons utiliser un fichier beaucoup plus l\u00e9ger ne contenant que les 1000 premiers mots de passe : vous le trouverez \u00e0 l'adresse http://glassus1.free.fr/extraitrockyou.txt .
L'un de ces mots de passe est le mot de passe demand\u00e9 \u00e0 la page http://glassus1.free.fr/exoBF.html .
Lequel ?
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/","title":"Initiation \u00e0 Pygame","text":""},{"location":"T6_Mini-projets/05_Initiation_Pygame/#1-preparation-de-la-scene","title":"1. Pr\u00e9paration de la sc\u00e8ne","text":"import pygame\nfrom pygame.locals import *\n\npygame.init() # (4)\n\nfenetre = pygame.display.set_mode((640, 480)) # (1)\nfenetre.fill((10, 186, 181)) # (2)\n\nrunning = True\nwhile running: \n fenetre.fill((10, 186, 181)) # (2)\n pygame.display.flip() #(3) \n\npygame.quit()\n
- On cr\u00e9e une fen\u00eatre de taille
(640, 480)
. - On remplit la fen\u00eatre avec la couleur
(10, 186, 181)
. - Permet de rafra\u00eechir la totalit\u00e9 de la fen\u00eatre. Pour l'instant inutile car rien ne bouge...
- Initialisation du module
pygame
.
Ce code devrait vous donner ceci :
Remarques
- La ligne
from pygame.locals import *
permettra d'utiliser des variables locales d\u00e9j\u00e0 d\u00e9finies par pygame
, comme MOUSEBUTTONDOWN
, par exemple. - Durant tout le code, notre sc\u00e8ne de travail sera l'objet
fenetre
, dans lequel nous viendrons coller de nouveaux \u00e9l\u00e9ments. - Pour l'instant, notre code nous enferme dans une boucle infinie : la fen\u00eatre ne se ferme pas, il faut arr\u00eater Python depuis Thonny. Nous y remedierons bient\u00f4t.
Les \u00e9l\u00e9ments structurants d'un code pygame
pygame.init()
effectue une initialisation globale de tous les modules pygame
import\u00e9s. \u00c0 mettre au d\u00e9but du code. while running:
comme tr\u00e8s souvent dans les jeux, la structure essentielle est une boucle infinie dont on ne sortira que par la bascule d'un bool\u00e9en. Ici on restera bloqu\u00e9 dans la boucle jusqu'au moment o\u00f9 la variable running
passera \u00e0 False
. pygame.display.flip()
effectue un rafra\u00eechissement total de tous les \u00e9l\u00e9ments graphiques de la fen\u00eatre. \u00c0 mettre \u00e0 l'int\u00e9rieur de la boucle infinie, g\u00e9n\u00e9ralement \u00e0 la fin de celle-ci.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#2-apparition-dun-personnage","title":"2. Apparition d'un personnage","text":""},{"location":"T6_Mini-projets/05_Initiation_Pygame/#21-telechargement-de-limage","title":"2.1. T\u00e9l\u00e9chargement de l'image","text":"Nous allons travailler avec le sprite ci-dessous, nomm\u00e9 perso.png
. Il est issu de https://openclassrooms.com/fr/courses/1399541-interface-graphique-pygame-pour-python/1399813-premieres-fenetres
T\u00e9l\u00e9chargez-le pour le mettre dans le m\u00eame dossier que votre code pygame
.
Vous pouvez trouver sur internet un grand nombre de sprites libres de droits, au format png
(donc g\u00e9rant la transparence), dans de multiples positions (ce qui permet de simuler des mouvements fluides). Ici nous travaillerons avec un sprite unique.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#22-importation-de-limage-dans-la-fenetre","title":"2.2. Importation de l'image dans la fen\u00eatre","text":"perso = pygame.image.load('perso.png').convert_alpha()\n
La fonction convert_alpha()
est appel\u00e9e pour que soit correctement trait\u00e9 le canal de transparence (canal alpha) de notre image."},{"location":"T6_Mini-projets/05_Initiation_Pygame/#23-affichage-de-limage","title":"2.3. Affichage de l'image","text":"\u00c0 ce stade, perso
est un objet pygame
de type Surface
.
Afin de facilement pouvoir le d\u00e9placer, nous allons stocker la position de cet objet dans une variable position_perso
, gr\u00e2ce \u00e0 l'instruction perso.get_rect()
.
Notre image est devenue \u00abun rectangle\u00bb que nous allons positionner o\u00f9 nous voulons.
Par exemple, pour positionner le coin sup\u00e9rieur gauche du personnage aux coordonn\u00e9es (100, 200)
, nous \u00e9crirons :
position_perso = perso.get_rect()\nposition_perso.topleft = (100, 200)\n
Il y a d'autres instructions que topleft
: vous pouvez les retrouver ici.
Pour afficher cette image, nous allons venir le superposer aux \u00e9l\u00e9ments graphiques d\u00e9j\u00e0 dessin\u00e9s (en l'occurence : rien) avec l'instruction blit()
:
fenetre.blit(perso, position_perso)\n
\u25b8 r\u00e9capitulatif du code
import pygame\nfrom pygame.locals import *\n\npygame.init()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\nrunning = True\nwhile running: \n fenetre.fill((10, 186, 181))\n position_perso.topleft = (100, 200)\n fenetre.blit(perso, position_perso)\n pygame.display.flip()\n\npygame.quit()\n
Aper\u00e7u
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#3-gestion-des-evenements","title":"3. Gestion des \u00e9v\u00e8nements","text":"Lorsqu'un programme pygame
est lanc\u00e9, la variable interne pygame.event.get()
re\u00e7oit en continu les \u00e9v\u00e8nements des p\u00e9riph\u00e9riques g\u00e9r\u00e9s par le syst\u00e8me d'exploitation. Nous allons nous int\u00e9resser aux \u00e9v\u00e8nements de type KEYDOWN
(touche de clavier appuy\u00e9e) ou de type MOUSEBUTTONDOWN
(boutons de souris appuy\u00e9).
Pour commencer, la gestion des \u00e9v\u00e8nements nous permettra de pouvoir enfin fermer proprement la fen\u00eatre Pygame, gr\u00e2ce au code suivant :
for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n
Exercice 1
Int\u00e9grer le code ci-dessus au code pr\u00e9c\u00e9dent afin de pouvoir fermer proprement la fen\u00eatre.
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\nrunning = True\nwhile running: \n fenetre.fill((10, 186, 181))\n position_perso.topleft = (100, 200)\n fenetre.blit(perso, position_perso)\n pygame.display.flip()\n\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n\npygame.quit()\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#31-evenements-clavier","title":"3.1. \u00c9v\u00e8nements clavier","text":""},{"location":"T6_Mini-projets/05_Initiation_Pygame/#311-exemple-de-code","title":"3.1.1. Exemple de code","text":"La structure de code pour d\u00e9tecter l'appui sur une touche de clavier est, dans le cas de la d\u00e9tection de la touche \u00abFl\u00e8che droite\u00bb :
for event in pygame.event.get(): \n if event.type == KEYDOWN:\n if event.key == K_RIGHT:\n print('fl\u00e8che droite appuy\u00e9e')\n
La touche (en anglais key) \u00abFl\u00e8che Droite\u00bb est appel\u00e9e K_RIGHT
par pygame
. il ne doit y avoir qu'une seule boucle de capture d'\u00e9v\u00e8nements, donc la routine de fermeture de la fen\u00eatre doit \u00eatre dans la m\u00eame boucle :
for event in pygame.event.get():\n if event.type == KEYDOWN:\n if event.key == K_RIGHT:\n print('fl\u00e8che droite appuy\u00e9e')\n\n if event.type == pygame.QUIT:\n running = False\n
Le nom de toutes les touches peut \u00eatre retrouv\u00e9 \u00e0 l'adresse https://www.pygame.org/docs/ref/key.html.
Remarque : c'est gr\u00e2ce \u00e0 la ligne initiale
from pygame.locals import *\n
que la variable K_RIGHT
(et toutes les autres) est reconnue."},{"location":"T6_Mini-projets/05_Initiation_Pygame/#312-probleme-de-la-remanence","title":"3.1.2. Probl\u00e8me de la r\u00e9manence","text":"Quand une touche de clavier est appuy\u00e9e, elle le reste un certain temps. Parfois volontairement (sur un intervalle long) quand l'utilisateur d\u00e9cide de la laisser appuy\u00e9e, mais aussi involontairement (sur un intervalle tr\u00e8s court), lors d'un appui \u00abclassique\u00bb. Il existe donc toujours un intervalle de temps pendant lequel la touche reste appuy\u00e9e. Que doit faire notre programme pendant ce temps ? Deux options sont possibles :
- option 1 : consid\u00e9rer que la touche appuy\u00e9e correspond \u00e0 un seul et unique \u00e9v\u00e8nement, quelle que soit la dur\u00e9e de l'appui sur la touche.
- option 2 : consid\u00e9rer qu'au bout d'un certain d\u00e9lai, la touche encore appuy\u00e9e doit d\u00e9clencher un nouvel \u00e9v\u00e8nement.
Par d\u00e9faut,pygame
est r\u00e9gl\u00e9 sur l'option 1. N\u00e9anmoins, il est classique pour les jeux vid\u00e9os de vouloir que \u00ablaisser la touche appuy\u00e9e\u00bb continue \u00e0 faire avancer le personnage. Nous allons donc faire en sorte que toutes les 50 millisecondes, un nouvel appui soit d\u00e9tect\u00e9 si la touche est rest\u00e9e enfonc\u00e9e. Cela se fera par l'expression :
pygame.key.set_repeat(50)\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#32-evenements-souris","title":"3.2 \u00c9v\u00e8nements souris","text":""},{"location":"T6_Mini-projets/05_Initiation_Pygame/#321-exemple-de-code","title":"3.2.1. Exemple de code","text":"La structure de code pour d\u00e9tecter l'appui sur un bouton de la souris est :
for event in pygame.event.get(): \n if event.type == MOUSEBUTTONDOWN and event.button == 1 :\n print('clic gauche d\u00e9tect\u00e9')\n if event.type == MOUSEBUTTONDOWN and event.button == 3 :\n print('clic droit d\u00e9tect\u00e9')\n
Le clic-gauche est associ\u00e9 \u00e0 la valeur 1, le clic-droit \u00e0 la valeur 3 (le clic-molette \u00e9ventuel \u00e0 la valeur 2).
Exercice 2
Reprendre le code initial et y int\u00e9grer la capture d'\u00e9v\u00e8nements souris afin que s'affiche en console le bouton de souris appuy\u00e9.
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\npygame.key.set_repeat(50)\n\nrunning = True\nwhile running: \n fenetre.fill((10, 186, 181))\n position_perso.topleft = (100, 200)\n fenetre.blit(perso, position_perso)\n pygame.display.flip()\n\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n\n if event.type == MOUSEBUTTONDOWN and event.button == 1 :\n print('clic gauche d\u00e9tect\u00e9')\n if event.type == MOUSEBUTTONDOWN and event.button == 3 :\n print('clic droit d\u00e9tect\u00e9')\n\npygame.quit()\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#322-recuperation-des-coordonnees-de-la-souris","title":"3.2.2. R\u00e9cup\u00e9ration des coordonn\u00e9es de la souris","text":"Le tuple (abscisse, ordonn\u00e9e)
des coordonn\u00e9es de la souris sera r\u00e9cup\u00e9r\u00e9 avec l'instruction pygame.mouse.get_pos()
.
Cette fonction n'a pas besoin d'\u00eatre dans notre boucle d'\u00e9coute des \u00e9v\u00e8nements : elle peut se situer n'importe o\u00f9 dans le code.
Exercice 3
Faire afficher en console les coordonn\u00e9es de la souris.
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\npygame.key.set_repeat(50)\n\nrunning = True\nwhile running: \n fenetre.fill((10, 186, 181))\n position_perso.topleft = (100, 200)\n fenetre.blit(perso, position_perso)\n\n x, y = pygame.mouse.get_pos()\n print(x, y)\n\n pygame.display.flip()\n\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n\n if event.type == MOUSEBUTTONDOWN and event.button == 1 :\n print('clic gauche d\u00e9tect\u00e9')\n if event.type == MOUSEBUTTONDOWN and event.button == 3 :\n print('clic droit d\u00e9tect\u00e9')\n\npygame.quit()\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#33-activation-dun-framerate","title":"3.3 Activation d'un framerate","text":"Pour l'instant, notre boucle infinie tourne \u00ab\u00e0 fond\u00bb et le rafra\u00eechissement de l'affichage se fait aussi rapidement que le peut le processeur. Afin de garder le contr\u00f4le sur cet fr\u00e9quence de rafra\u00eechissement (le nombre de frames par seconde, le fameux FPS) nous allons utiliser une horloge.
clock = pygame.time.Clock()
cr\u00e9e une horloge dans le corps du programme.
Ensuite, dans la boucle, nous rajouterons
clock.tick(30)
pour r\u00e9gler (par exemple) le FPS \u00e0 30.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#4-deplacement-du-personnage","title":"4. D\u00e9placement du personnage","text":"Le d\u00e9placement d'un personnage se fera toujours par modification de ses coordonn\u00e9es (et visuellement, par effacement de la derni\u00e8re position). Ce d\u00e9placement pourra \u00eatre :
- absolu : on donne de nouvelles coordonn\u00e9es au personnage.
- relatif : on indique de combien le personnage doit se d\u00e9caler par rapport \u00e0 sa position initiale.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#41-deplacement-absolu","title":"4.1. D\u00e9placement absolu","text":"Rappel : pour afficher le personnage \u00e0 la position (300,200)
, on \u00e9crit simplement:
position_perso.topleft = (300,200)\n
Au prochain fenetre.blit(perso, position_perso)
, le personnage sera positionn\u00e9 \u00e0 cette nouvelle position.
Exercice 4
R\u00e9aliser un d\u00e9placement al\u00e9atoire, comme l'animation ci-dessous.
Vous pourrez utiliser les instructions :
pygame.time.delay(1000)
afin de ne bouger le personnage que toutes les 1000 millisecondes. randint(a,b)
du package random
, qui renvoie un entier pseudo-al\u00e9atoire entre a
et b
.
Correction import pygame\nfrom pygame.locals import *\nfrom random import randint\n\npygame.init()\nclock = pygame.time.Clock()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\nrunning = True\nwhile running :\n clock.tick(30)\n fenetre.fill((10, 186, 181))\n position_perso = (randint(0, 540), randint(0, 380))\n\n fenetre.blit(perso, position_perso)\n pygame.display.flip()\n\n pygame.time.delay(1000)\n\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n\npygame.quit()\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#42-deplacement-relatif","title":"4.2. D\u00e9placement relatif","text":"Pour d\u00e9placer le personnage de 15 pixels vers la droite et de 10 pixels vers le haut par rapport \u00e0 sa position pr\u00e9c\u00e9dente, on \u00e9crira :
position_perso = position_perso.move(15,-10)\n
o\u00f9 position_perso
est l'objet de type rect
contenant les coordonn\u00e9es. Exercice 5
R\u00e9aliser un contr\u00f4le au clavier du personnage, comme dans l'animation ci-dessous.
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\npygame.key.set_repeat(50)\nclock = pygame.time.Clock()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\npas = 15 \n\nrunning = True\nwhile running:\n clock.tick(30)\n fenetre.fill((10, 186, 181))\n fenetre.blit(perso, position_perso)\n\n for event in pygame.event.get() : \n if event.type == KEYDOWN:\n\n if event.key == K_DOWN : \n position_perso = position_perso.move(0, pas)\n\n if event.key == K_UP :\n position_perso = position_perso.move(0, -pas)\n\n if event.key == K_RIGHT : \n position_perso = position_perso.move(pas, 0)\n\n if event.key == K_LEFT : \n position_perso = position_perso.move(-pas, 0) \n\n # routine pour pouvoir fermer \u00abproprement\u00bb la fen\u00eatre Pygame\n if event.type == pygame.QUIT:\n running = False\n\n\n pygame.display.flip() \n\npygame.quit()\n
Exercice 6
Rajouter des instructions afin que le personnage ne puisse pas sortir de la fen\u00eatre de jeu.
On utilisera les variables suivantes :
position_perso.top
: ordonn\u00e9e du haut du personnage position_perso.bottom
: ordonn\u00e9e du bas du personnage position_perso.left
: abscisse de la gauche du personnage position_perso.right
: abscisse de la droite du personnage
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\npygame.key.set_repeat(50)\nclock = pygame.time.Clock()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\npas = 15 \n\nrunning = True\nwhile running:\n clock.tick(30)\n fenetre.fill((10, 186, 181))\n fenetre.blit(perso, position_perso)\n\n if position_perso.top < 0:\n position_perso.top = 0\n\n if position_perso.bottom > 480:\n position_perso.bottom = 480\n\n if position_perso.left < 0:\n position_perso.left = 0\n\n if position_perso.right > 640:\n position_perso.right = 640\n\n\n for event in pygame.event.get() : \n if event.type == KEYDOWN:\n\n if event.key == K_DOWN : \n position_perso = position_perso.move(0, pas)\n\n if event.key == K_UP :\n position_perso = position_perso.move(0, -pas)\n\n if event.key == K_RIGHT : \n position_perso = position_perso.move(pas, 0)\n\n if event.key == K_LEFT : \n position_perso = position_perso.move(-pas, 0) \n\n if event.type == pygame.QUIT:\n running = False\n\n\n pygame.display.flip() \n\npygame.quit()\n
Exercice 7
Reprendre l'exercice pr\u00e9c\u00e9dent mais faire en sorte que le personnage r\u00e9apparaisse \u00e0 l'oppos\u00e9 de l\u00e0 o\u00f9 il est sorti.
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\npygame.key.set_repeat(50)\nclock = pygame.time.Clock()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\npas = 15 \n\nrunning = True\nwhile running:\n clock.tick(30)\n fenetre.fill((10, 186, 181))\n fenetre.blit(perso, position_perso)\n\n if position_perso.top < 0:\n position_perso.bottom = 480\n\n if position_perso.bottom > 480:\n position_perso.top = 0\n\n if position_perso.left < 0:\n position_perso.right = 640\n\n if position_perso.right > 640:\n position_perso.left = 0\n\n\n for event in pygame.event.get() : \n if event.type == KEYDOWN:\n\n if event.key == K_DOWN : \n position_perso = position_perso.move(0, pas)\n\n if event.key == K_UP :\n position_perso = position_perso.move(0, -pas)\n\n if event.key == K_RIGHT : \n position_perso = position_perso.move(pas, 0)\n\n if event.key == K_LEFT : \n position_perso = position_perso.move(-pas, 0) \n\n if event.type == pygame.QUIT:\n running = False\n\n\n pygame.display.flip() \n\npygame.quit()\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#5-controle-avec-la-microbit","title":"5. Contr\u00f4le avec la micro:bit","text":"Pour pouvoir contr\u00f4ler notre personnage avec (par exemple) les boutons de la carte micro:bit, il va falloir :
- mettre dans la carte un programme minimal qui va se contenter d'envoyer des donn\u00e9es.
- mettre dans notre programme Pygame une instruction capable de recevoir les donn\u00e9es envoy\u00e9es par la carte.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#51-programme-a-televerser-dans-la-microbit","title":"5.1 Programme \u00e0 t\u00e9l\u00e9verser dans la micro:bit","text":"Lien vers le simulateur
from microbit import *\n\nwhile True:\n incX = accelerometer.get_x()\n incY = accelerometer.get_y()\n\n message = \"{},{}\".format(incX,incY)\n print(message)\n\n sleep(50)\n
Ce programme va envoyer, 20 fois par seconde, la valeur de l'inclinaison en X et la valeur de l'inclinaison en Y.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#52-recuperation-des-donnees-dans-pygame","title":"5.2 R\u00e9cup\u00e9ration des donn\u00e9es dans Pygame","text":"Il faut conna\u00eetre le port utilis\u00e9 par le syst\u00e8me d'exploitation pour communiquer avec la micro:bit. Sous Linux, ce port est de la forme ttyACM0
, sous Windows il sera de la forme COM2
.
connaitre le port sous Windows
Ouvrir un terminal via cmd
et taper la commande mode
.
Une fois le programme d'envoi t\u00e9l\u00e9vers\u00e9 dans la micro:bit et le port connu, testez le programme suivant :
import serial\n\nport = \"COM2\" # \u00e0 adapter en allant voir le port utilis\u00e9 par la microbit\ns = serial.Serial(port)\ns.baudrate = 115200\n\nwhile True:\n s.flushInput()\n data = s.readline()\n data = data.decode('utf-8')\n data = data.split(',')\n incX = int(data[0])\n incY = int(data[1])\n print(incX, incY)\n
En inclinant la carte, vous devriez voir bouger les valeurs dans la console de Thonny. Observer quelles sont les valeurs minimales et maximales.
Exercice 8
\u00c0 l'aide de l'exemple pr\u00e9c\u00e9dent, modifiez le code de l'exercice 5 afin de pouvoir bouger le personnage \u00e0 l'aide de la micro:bit.
Correction import pygame \nfrom pygame.locals import *\n\nimport serial\n\nport = 'COM2' # \u00e0 adapter\ns = serial.Serial(port)\ns.baudrate = 115200 \n\n\n\npygame.init()\npygame.key.set_repeat(50)\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\n\nposition_perso = perso.get_rect()\nposition_perso.center = (320, 240)\npas = 10 \npygame.time.delay(500)\nclock = pygame.time.Clock()\n\nseuil = 200\n\nrunning = True\nwhile running:\n\n clock.tick(30)\n\n s.flushInput()\n data = s.readline()\n data = data.decode('utf-8')\n data = data.split(',')\n accX = int(data[0])\n accY = int(data[1]) \n\n if accY < -seuil : \n position_perso = position_perso.move(0, -pas)\n\n if accY > seuil :\n position_perso = position_perso.move(0, pas)\n\n if accX > seuil : \n position_perso = position_perso.move(pas, 0)\n\n if accX < -seuil : \n position_perso = position_perso.move(-pas, 0)\n\n if position_perso.top < 0:\n position_perso.top = 0\n\n if position_perso.bottom > 480:\n position_perso.bottom = 480\n\n if position_perso.left < 0:\n position_perso.left = 0\n\n if position_perso.right > 640:\n position_perso.right = 640\n\n\n for event in pygame.event.get() : \n if event.type == pygame.QUIT:\n running = False\n\n fenetre.fill((10, 186, 181))\n fenetre.blit(perso, position_perso)\n pygame.display.flip()\n\npygame.quit()\n
Bibliographie
- Documentation officielle de Pygame, https://www.pygame.org/docs/
- Cours d'OpenClassrooms, https://openclassrooms.com/fr/courses/1399541-interface-graphique-pygame-pour-python/1399813-premieres-fenetres.
"},{"location":"T6_Mini-projets/Attaque_BF/","title":"Attaque d'un mot de passe par force brute","text":" attention
L'activit\u00e9 ci-dessous n'est pas r\u00e9alisable sous Capytale, qui n'autorise pas l'utilisation du module requests
. Vous devez donc la r\u00e9aliser sur (par exemple) Thonny. Si vous n'avez pas (encore) Thonny sur votre ordinateur personnel, t\u00e9l\u00e9chargez-le ici
Par contre, les r\u00e9ponses aux questions pos\u00e9es doivent \u00eatre donn\u00e9es sur l'activit\u00e9 Capytale https://capytale2.ac-paris.fr/web/c/7371-1140429
Votre objectif est de trouver le mot de passe demand\u00e9 sur la page http://glassus1.free.fr/exoBF.html
Vous allez vous appuyer sur un leak (fuite) tr\u00e8s c\u00e9l\u00e8bre de mots de passe , qui est le leak du site Rockyou. Dans la base de donn\u00e9es de ce site, 32 millions de mots de passe \u00e9taient stock\u00e9s en clair.
Lorsque le site a \u00e9t\u00e9 pirat\u00e9 (par une injection SQL, voir le cours de Terminale), ces 32 millions de mots de passe se sont retrouv\u00e9s dans la nature. Ils sont aujourd'hui t\u00e9l\u00e9chargeables librement, et constituent un dictionnaire de 14 341 564 mots de passe diff\u00e9rents (car parmi les 32 millions d'utilisateurs, beaucoup utilisaient des mots de passe identiques).
Nous allons utiliser un fichier beaucoup plus l\u00e9ger ne contenant que les 1000 premiers mots de passe. Ce fichier est nomm\u00e9 extraitrockyou.txt
.
"},{"location":"T6_Mini-projets/Attaque_BF/#1-lire-les-mots-dun-fichier","title":"1. Lire les mots d'un fichier","text":""},{"location":"T6_Mini-projets/Attaque_BF/#11-telechargement-du-fichier-extraitrockyoutxt","title":"1.1 T\u00e9l\u00e9chargement du fichier extraitrockyou.txt
","text":"T\u00e9l\u00e9chargez le fichier extraitrockyou.txt. Attention, ce fichier doit \u00eatre imp\u00e9rativement situ\u00e9 dans le m\u00eame r\u00e9pertoire que le fichier du code Python que vous allez \u00e9crire.
"},{"location":"T6_Mini-projets/Attaque_BF/#12-recuperer-les-elements-du-fichier","title":"1.2 R\u00e9cup\u00e9rer les \u00e9l\u00e9ments du fichier","text":"Ouvrir un nouveau code dans Thonny et enregistrez-le \u00e0 c\u00f4t\u00e9 du fichier extraitrockyou.txt
.
La ligne suivante va stocker dans une liste liste_mdp
les 1000 mots de passe pr\u00e9sents dans le fichier extraitrockyou.txt
.
liste_mdp = open(\"extraitrockyou.txt\").read().splitlines()\n
Si vous avez l'erreur :
FileNotFoundError: [Errno 2] No such file or directory: 'extraitrockyou.txt'\n
c'est que votre code et le fichier extraitrockyou.txt
ne sont pas dans le m\u00eame r\u00e9pertoire.
Question 1
\u00c9crire un code qui affiche les 1000 mots de passe contenus dans liste_mdp
.
(rappel : vous devez aller \u00e9crire vos r\u00e9ponses sur l'activit\u00e9 Capytale https://capytale2.ac-paris.fr/web/c/7371-1140429)
"},{"location":"T6_Mini-projets/Attaque_BF/#2-utilisation-du-module-requests","title":"2. Utilisation du module requests
","text":"Le module requests
de Python permet de r\u00e9cup\u00e9rer le contenu d'une page web dont on aura donn\u00e9 l'adresse en param\u00e8tre.
Souvenez-vous par exemple de cette superbe page : http://glassus1.free.fr/interesting.html
Exc\u00e9cutez le code ci-dessous :
import requests\np = requests.get(\"http://glassus1.free.fr/interesting.html\")\nprint(p.text)\n
Question 2
\u00c9crire ce qui s'affiche en console lors de l'ex\u00e9cution du code :
import requests\np = requests.get(\"http://glassus1.free.fr/interesting.html\")\nprint(p.text)\n
Si vous avez l'erreur :
ModuleNotFoundError: No module named 'requests'\n
c'est que le module requests
n'est pas install\u00e9. Dans Thonny, aller dans Outils / G\u00e9rer les paquets et installer requests
.
"},{"location":"T6_Mini-projets/Attaque_BF/#3-proposer-un-mot-de-passe","title":"3. Proposer un mot de passe","text":"Un des 1000 mots de passe du fichier extraitrockyou.txt
est le bon. Mais comment savoir lequel ?
"},{"location":"T6_Mini-projets/Attaque_BF/#31-observation-a-la-main","title":"3.1 Observation \u00ab\u00e0 la main\u00bb","text":"Question 3
Rendez-vous sur la page http://glassus1.free.fr/exoBF.html et proposer le mot de passe mauriac
. Quelle url s'affiche alors dans la barre d'adresse ?
"},{"location":"T6_Mini-projets/Attaque_BF/#32-automatisation-dun-proposition","title":"3.2 Automatisation d'un proposition","text":"Question 4
\u00c9crire un code qui va proposer le mot de passe vacances
et afficher le texte de la page obtenue.
"},{"location":"T6_Mini-projets/Attaque_BF/#4-resolution-du-probleme","title":"4. R\u00e9solution du probl\u00e8me","text":""},{"location":"T6_Mini-projets/Attaque_BF/#41-petite-aide-sur-les-chaines-de-caracteres","title":"4.1 Petite aide sur les chaines de caract\u00e8res","text":"Pour rappel la concat\u00e9nation des chaines de caract\u00e8res permet de faire ceci :
base = \"je vous souhaite de bonnes\"\nsuite = \"vacances\"\nphrase = base + suite\n
Question 5
\u00c9crire un code qui va afficher les 1000 urls diff\u00e9rentes qui serviront \u00e0 tester tous les mots de passe du fichier extraitrockyou.txt
.
"},{"location":"T6_Mini-projets/Attaque_BF/#42-quel-est-le-bon-mot-de-passe","title":"4.2 Quel est le bon mot de passe ?","text":"Question 6
\u00c9crire un code qui d\u00e9termine le mot de passe de la page http://glassus1.free.fr/exoBF.html.
"},{"location":"T6_Mini-projets/D%C3%A9codeuses/","title":"D\u00e9codeuses du num\u00e9rique","text":" -
La BD en ligne est disponible ici.
-
Le pdf est disponible en t\u00e9l\u00e9chargement ici.
-
Les portraits sont accessibles ici.
Affectation des pr\u00e9sentations
- Alissa : Anne-C\u00e9cile Orgerie
- Ahmed : Magalie Ochs
- Antoine : Claire Mathieu
- Louka : Emmanuelle Kristensen
- Tristan : Caroline Fontaine
- Candice : Elsa Cazelles
- Elouo : Lucile Sassatelli
- Louan : Sarah Cohen-Boulakia
- Hugo : Nina Amini
- Emma : Fran\u00e7oise Conil
- Emmy : Marie-Christine Rousset
- Vincent : Pauline Maurice
- Mathias : Anne-C\u00e9cile Orgerie
"},{"location":"T6_Mini-projets/Exercice_Perseverance/","title":"Le message secret de Perseverance","text":"Lors de sa descente vers la plan\u00e8te Mars le 18/02/2021, le rover Perseverance de la Nasa a frein\u00e9 sa chute gr\u00e2ce \u00e0 un parachute qui a intrigu\u00e9 quelques internautes du forum Reddit.
Vid\u00e9o du d\u00e9ploiement du parachute :
Les zones blanches et rouge se d\u00e9composent comme ceci :
"},{"location":"T6_Mini-projets/Exercice_Perseverance/#indications","title":"Indications","text":" - Le tout premier secteur contenant un message est le secteur sur lequel est \u00e9crite la lettre D, qui est effectivement la signification de ce secteur. C'est en l'observant bien que vous comprendrez le codage qui a \u00e9t\u00e9 utilis\u00e9.
- Les autres secteurs sont marqu\u00e9s de points d'interrogation : c'est \u00e0 vous de d\u00e9couvrir ce qu'ils cachent.
- La phrase myst\u00e8re s'obtiendra en tournant en spirale depuis la lettre D, dans le sens horaire.
- La derni\u00e8re couronne (la plus \u00e0 l'ext\u00e9rieur) est un peu particuli\u00e8re, mais n'en disons pas plus...
"},{"location":"T6_Mini-projets/Exercice_Perseverance/#a-vous","title":"\u00c0 vous !","text":"Un grand bravo aux brillants redditors u/rdtwt1
et u/tend0g
.
"},{"location":"T6_Mini-projets/Exercice_Perseverance/#update-faites-votre-propre-parachute","title":"Update : faites votre propre parachute !","text":"https://sjwarner.github.io/perseverance-parachute-generator/?
"},{"location":"T6_Mini-projets/Exercice_Perseverance/#sources-attention-spoiler","title":"Sources (attention spoiler):","text":" - https://www.lemonde.fr/pixels/article/2021/02/23/des-internautes-dechiffrent-un-message-cache-dans-le-parachute-du-rover-de-la-nasa-sur-mars_6070952_4408996.html
- https://www.reddit.com/r/nasa/comments/lpy2fa/does_the_parachute_for_perseverance_have_some/goedts0/
- https://twitter.com/steltzner/status/1364076615932645379
"},{"location":"T6_Mini-projets/Github/","title":"Mise en place de GitHub","text":"Afin de travailler efficacement entre votre ordinateur personnel et votre VM du lyc\u00e9e, nous utiliser la solution GitHub.
"},{"location":"T6_Mini-projets/Github/#etape-0-creer-un-compte-github","title":"\u00c9tape 0 : cr\u00e9er un compte GitHub","text":"Cela se passe ici
"},{"location":"T6_Mini-projets/Github/#etape-1-creer-un-premier-depot-repository","title":"\u00c9tape 1 : cr\u00e9er un premier d\u00e9p\u00f4t (repository)","text":"Une fois termin\u00e9e la cr\u00e9ation de compte, GitHub vous proposera de cr\u00e9er votre premier d\u00e9p\u00f4t (on dira aussi repository, ou repo). Vous pourrez avoir autant de d\u00e9p\u00f4ts que vous voulez : \u00e0 chaque nouveau projet doit correspondre un nouveau d\u00e9p\u00f4t.
Cr\u00e9ez donc un d\u00e9p\u00f4t Projet Pygame
(ou comme vous voulez).
"},{"location":"T6_Mini-projets/Github/#etape-2-installer-github-desktop","title":"\u00c9tape 2 : installer GitHub Desktop","text":"GitHub Desktop est un logiciel qui devra \u00eatre install\u00e9 sur nos VMs (c'est fait) mais aussi sur votre ordinateur personnel de travail. Vous trouverez les liens de t\u00e9l\u00e9chargement ici.
Le r\u00f4le de GitHub Desktop va \u00eatre de synchroniser vos fichiers locaux avec le serveur distant de github.com (\u00able cloud\u00bb). Contrairement \u00e0 une solution automatique (type Dropbox ou Google Drive), la synchronisation n'est pas automatique mais manuelle. C'est \u00e0 vous d'aller uploader vos fichiers (push) ou bien de les t\u00e9l\u00e9charger (fetch).
"},{"location":"T6_Mini-projets/Github/#etape-3-configurer-github-desktop","title":"\u00c9tape 3 : configurer GitHub Desktop","text":"Il va falloir pr\u00e9ciser \u00e0 GitHub que nous avons d\u00e9j\u00e0 un compte, et un d\u00e9p\u00f4t que nous avons cr\u00e9\u00e9 plus haut. Vous pouvez vous laisser guider ou suivre ce tutoriel
"},{"location":"T6_Mini-projets/Tkinter/","title":"Introduction \u00e0 Tkinter","text":"Tkinter
est un module de Python permettant la cr\u00e9ation d'interfaces graphiques.
"},{"location":"T6_Mini-projets/Tkinter/#0-site-de-presentation-de-tkinter","title":"0. Site de pr\u00e9sentation de Tkinter","text":"Vous pouvez suivre pas \u00e0 pas l'excellent travail de Fabrice Sinc\u00e8re, disponible \u00e0 cette page :
http://f.sincere.free.fr/isn/python/cours_python_tkinter.php
Vous pouvez aussi poser des questions \u00e0 https://www.perplexity.ai/ ou une autre IA.
"},{"location":"T6_Mini-projets/Tkinter/#1-objectif-final","title":"1. Objectif final","text":""},{"location":"T6_Mini-projets/Tkinter/#2-etape-1","title":"2. \u00c9tape 1","text":"Instructions :
Tracer
doit tracer un cercle bleu (avec une bordure noire) de taille fixe (30 px). - Les boutons
Tracer
et Effacer
sont dans une frame particuli\u00e8re. - La zone de dessin mesure 480x320.
Aide :
- Exemple 6 de http://f.sincere.free.fr/isn/python/cours_python_tkinter.php
Correction from tkinter import *\nimport random\n\n\ndef cercle():\n x = random.randint(0, largeur)\n y = random.randint(0, hauteur)\n r = 30\n zone_dessin.create_oval(x-r, y-r, x+r, y+r, outline='black', fill='blue')\n\n\ndef effacer():\n zone_dessin.delete(ALL)\n\nma_fenetre = Tk()\nma_fenetre.title('Traceur de cercles')\n\n\nlargeur = 480\nhauteur = 320\nzone_dessin = Canvas(ma_fenetre, width=largeur, height=hauteur, bg='white')\nzone_dessin.pack(padx=5, pady=5)\n\nframe1 = Frame(ma_fenetre, borderwidth=2, relief=GROOVE)\nframe1.pack(side=LEFT, padx=10, pady=10)\n\nframe2 = Frame(ma_fenetre, relief=GROOVE)\nframe2.pack(side=LEFT, padx=10, pady=10)\n\nbouton_Tracer = Button(frame1, text='Tracer', command=cercle)\nbouton_Tracer.pack(side=LEFT, padx=10, pady=10)\n\nbouton_Effacer = Button(frame1, text='Effacer', command=effacer)\nbouton_Effacer.pack(side=LEFT, padx=5, pady=5)\n\nbouton_Quitter = Button(frame2, text='Quitter', command=ma_fenetre.destroy)\nbouton_Quitter.pack(side=LEFT, padx=5, pady=5)\n\nma_fenetre.mainloop()\n
"},{"location":"T6_Mini-projets/Tkinter/#3-etape-2","title":"3. \u00c9tape 2","text":"Instructions :
Couleur
doit ouvrir une boite de dialogue pour changer la couleur de remplissage.
"},{"location":"T6_Mini-projets/Tkinter/#1-variable-couleur","title":"1. Variable couleur
","text":"Pour commencer, il faut cr\u00e9er une variable dynamique couleur
qui sera plus tard modifi\u00e9e par la boite de dialogue :
couleur = StringVar() # on cr\u00e9e la variable\ncouleur.set('blue') # on l'initialise \u00e0 'blue' \n
Pour acc\u00e9der au contenu de la variable couleur
, on utilise l'instruction couleur.get()
.
Modifier la fonction cercle
pour que la couleur de remplissage soit couleur
.
"},{"location":"T6_Mini-projets/Tkinter/#2-bouton-couleur","title":"2. Bouton Couleur
","text":" Cr\u00e9er et placer un bouton Couleur
qui d\u00e9clenchera une fonction change_color
que nous \u00e9crirons plus tard.
"},{"location":"T6_Mini-projets/Tkinter/#3-fonction-change_color-et-boite-de-dialogue","title":"3. Fonction change_color
et boite de dialogue","text":"Pour int\u00e9grer la boite de dialogue de choix de couleur, il faut commencer par appeler deux fonctions / modules suppl\u00e9mentaires :
from tkinter import ttk\nfrom tkinter.colorchooser import askcolor\n
La fonction change_color
s'\u00e9crira comme ceci :
def change_color():\n colors = askcolor(title=\"Tkinter Color Chooser\")\n couleur.set(...)\n
Pour savoir ce qu'il faut \u00e9crire \u00e0 la place des pointill\u00e9s, faites des tests (avec un print
, par exemple) pour savoir \u00e0 quoi ressemble la variable colors
qui est renvoy\u00e9e par la fonction askcolor
.
Souvenez-vous ensuite que Tkinter
travaille avec les couleurs en \u00e9criture hexad\u00e9cimale et non pas RGB...
Correction from tkinter import *\nfrom tkinter import ttk\nfrom tkinter.colorchooser import askcolor\nimport random\n\n\ndef cercle():\n x = random.randint(0, largeur)\n y = random.randint(0, hauteur)\n r = 30\n zone_dessin.create_oval(x-r, y-r, x+r, y+r, outline='black', fill=couleur.get())\n\n\ndef effacer():\n zone_dessin.delete(ALL)\n\n\ndef change_color():\n colors = askcolor(title='Tkinter Color Chooser')\n couleur.set(colors[1])\n\n\nma_fenetre = Tk()\nma_fenetre.title('Traceur de cercles')\n\ncouleur = StringVar()\ncouleur.set('blue')\n\n\nlargeur = 480\nhauteur = 320\nzone_dessin = Canvas(ma_fenetre, width=largeur, height=hauteur, bg='white')\nzone_dessin.pack(padx=5, pady=5)\n\nframe1 = Frame(ma_fenetre, borderwidth=2, relief=GROOVE)\nframe1.pack(side=LEFT, padx=10, pady=10)\n\nframe2 = Frame(ma_fenetre, relief=GROOVE)\nframe2.pack(side=LEFT, padx=10, pady=10)\n\nbouton_Tracer = Button(frame1, text='Tracer', command=cercle)\nbouton_Tracer.pack(side=LEFT, padx=10, pady=10)\n\n\nbouton_Effacer = Button(frame1, text='Effacer', command=effacer)\nbouton_Effacer.pack(side=LEFT, padx=5, pady=5)\n\nbouton_Couleur = ttk.Button(frame1, text='Couleur', command=change_color)\nbouton_Couleur.pack(side=LEFT, padx=5, pady=5)\n\n\nbouton_Quitter = Button(frame2, text='Quitter', command=ma_fenetre.destroy)\nbouton_Quitter.pack(side=LEFT, padx=5, pady=5)\n\nma_fenetre.mainloop()\n
"},{"location":"T6_Mini-projets/Tkinter/#4-etape-3","title":"4. \u00c9tape 3","text":"Instructions :
- Un curseur doit permettre de modifier le rayon du cercle.
Il faut proc\u00e9der de la m\u00eame mani\u00e8re que pour la couleur.
Pensez \u00e0 utiliser IntVar
plut\u00f4t que StringVar
, car le rayon est un nombre entier.
Des indications pour l'int\u00e9gration du curseur sont \u00e0 retrouver dans l'exemple 5 du site http://f.sincere.free.fr/isn/python/cours_python_tkinter.php
"},{"location":"T6_Mini-projets/Tkinter/#5-bonus","title":"5. Bonus","text":"Remplacer le placement al\u00e9atoire par un placement au clic de souris.
"},{"location":"T7_Divers/1_Conseils_generaux/cours/","title":"Conseils de travail","text":""},{"location":"T7_Divers/1_Conseils_generaux/cours/#conditions-materielles","title":"Conditions mat\u00e9rielles","text":"Il est conseill\u00e9 de travailler avec 3 espaces:
- l'\u00e9cran de l'ordinateur partitionn\u00e9 avec les 2 premiers espaces: ce site et un IDE (Thonny par exemple);
C'est en codant qu'on apprend \u00e0 coder
Tous les exemples de code dans le cours doivent \u00eatre retap\u00e9s (r\u00e9sistez \u00e0 l'envie du copier-coller) dans Thonny, soit en fen\u00eatre de script, soit en console.
Cela permet de :
- m\u00e9moriser la syntaxe ;
- v\u00e9rifier si le code propos\u00e9 ne contient pas d'erreur ;
et le plus important :
- faire ses propres tests et modifications pour v\u00e9rifier sa bonne compr\u00e9hension.
- et un troisi\u00e8me espace essentiel : un petit cahier \u00e0 spirale et un stylo !
"},{"location":"T7_Divers/1_Conseils_generaux/cours/#script-ou-console","title":"Script ou console ???","text":"Thonny, comme la grande majorit\u00e9 des IDE Python, est compos\u00e9 de deux zones distinctes :
- la zone de script
- la console
La zone de script est asynchrone. Il ne se passera rien tant que vous n'aurez pas ex\u00e9cut\u00e9 le script (par F5 par exemple). C'est donc l'endroit o\u00f9 on va r\u00e9diger son programme.
La console est synchrone : elle r\u00e9pond d\u00e8s que vous appuyez sur la touche Entr\u00e9e. Elle sert donc aux petits tests rapides, ou bien tests post-ex\u00e9cution d'un code.
Utilisation classique du couple script / console
- On \u00e9crit son code dans la zone de script
- On l'ex\u00e9cute.
- On interroge la console pour conna\u00eetre l'\u00e9tat des variables, pour utiliser les fonctions construites dans le script.
Pour les extraits de code pr\u00e9sents sur ce site :
- tout le code qui est pr\u00e9c\u00e9d\u00e9 d'une num\u00e9rotation de ligne est \u00e0 \u00e9crire en zone de script.
Exemple :
def accueil(n):\n for k in range(n):\n print(\"bonjour\") \n
- tout le code qui est pr\u00e9c\u00e9d\u00e9
>>>
est \u00e0 taper en console.
Exemple :
>>> accueil(5)\n
"},{"location":"T7_Divers/1_Conseils_generaux/cours/#dossiers-fichiers-et-versionning","title":"Dossiers, fichiers et versionning","text":"Cette ann\u00e9e en NSI nous allons manipuler un certain nombre de fichiers. Il est important de les nommer et les classer de fa\u00e7on rigoureuse pour les retrouver rapidement et les partager.
Conseils
- Utilisez des dossiers pour classer vos fichiers. Il n'y en a jamais assez.
- Prenez l'habitude de faire plusieurs sauvegardes de vos documents (sur le r\u00e9seau du lyc\u00e9e, sur l'ENT, sur cl\u00e9 USB).
- \u00c9vitez dans les noms de fichiers et de dossiers les espaces (utilisez plut\u00f4t _ ) ainsi que les caract\u00e8res accentu\u00e9s et les caract\u00e8res sp\u00e9ciaux.
- Un nom de fichier doit \u00eatre parlant (un peu comme une variable en fait). On \u00e9vitera de nommer ses codes Python
python1.py
, python2.py
, python3.py
, etc. Mais plut\u00f4t 1NSI_T4_tri_selection.py
par exemple pour un exercice de programmation sur le tri par selection au th\u00e8me 4. - Lorsqu'on travaille sur un projet ou un programme cons\u00e9quent, il peut \u00eatre utile de conserver des archives du travail \u00e0 plusieurs \u00e9tapes de l'\u00e9laboration, plut\u00f4t que de ne conserver que la derni\u00e8re version. \u00c0 cet effet on pourra num\u00e9roter :
1NSI_projet_morpion_v1.py
, puis 1NSI_projet_morpion_v2.py
, 1NSI_projet_morpion_v3.py
, etc.
"},{"location":"T7_Divers/1_Conseils_generaux/cours/#usage-du-clavier","title":"Usage du clavier","text":"Utiliser le clavier est souvent bien plus pratique et surtout plus rapide qu'utiliser la souris. Encore faut-il apprendre \u00e0 l'apprivoiser...
La s\u00e9lection au clavier
Outre les touches DEBUT
et FIN
qui permettent d'atteindre rapidement le d\u00e9but ou la fin d'une ligne, les fl\u00e8ches directionelles servent \u00e9videmment \u00e0 se d\u00e9placer dans du texte. Mais combin\u00e9es:
- \u00e0 la touche
CTRL
: elles permettent de se d\u00e9placer de mot en mot; - \u00e0 la touche
MAJ
: elles permettent de s\u00e9lectionner un caract\u00e8re; - aux touches
MAJ
et CTRL
: elles permettent de s\u00e9lectionner un mot.
De m\u00eame, en se pla\u00e7ant en d\u00e9but d'une ligne et en combinant la touche MAJ
et FIN
, on s\u00e9lectionne la ligne enti\u00e8re.
Les raccourcis clavier
Il existe de tr\u00e8s nombreux raccourcis clavier qui permettent d'ex\u00e9cuter des t\u00e2ches courantes sans passer par les menus du logiciel. Certains sont (quasi-)universels, c'est-\u00e0-dire que ce sont les m\u00eames sur tous les logiciels, d'autres sont sp\u00e9cifiques \u00e0 chaque logiciel. Il est important d'en conna\u00eetre quelques-uns pour \u00eatre plus efficace.
Les universelsIDENavigateur Web - La triplette magique
CTRL+X
, CTRL+C
, CTRL+V
pour couper, copier, coller; CTRL+O
pour ouvrir un fichier CTRL+N
pour cr\u00e9er un nouveau document; CTRL+S
pour sauvegarder le document en cours; CTRL+MAJ+S
pour sauvegarder en pr\u00e9cisant le nom du fichier; CTRL+Z
pour annuler la derni\u00e8re action, CTRL+Y
ou CTRL+MAJ+Z
pour la r\u00e9tablir; CTRL+W
pour fermer un onglet; CTRL+Q
ou ALT+F4
pour fermer le logiciel; CTRL+A
pour s\u00e9lectionner tout (All).
\u00c0 chercher de suite lorsqu'on utilise un nouvel IDE, les raccourcis pour les actions suivantes (entre parenth\u00e8ses ceux de Thonny):
- ex\u00e9cuter le code (
F5
) - commenter/d\u00e9commenter une ligne (
CTRL+M
)
CTRL+T
pour ouvrir un nouvel onglet; CTRL+H
pour ouvrir l'historique; - combiner
CTRL
+ clic pour forcer l'ouverture d'un lien dans un nouvel onglet; - combiner
MAJ
+ clic pour forcer l'ouverture d'un lien dans une nouvelle fen\u00eatre;
sources - site de C\u00e9dric Gouygou
"},{"location":"T7_Divers/2_VM/cours/","title":"Utilisation des VMs au lyc\u00e9e","text":""},{"location":"T7_Divers/2_VM/cours/#principe","title":"Principe","text":"Afin de pouvoir travailler sous le syst\u00e8me d'exploitation libre Linux sur les machines du lyc\u00e9e (sous Windows), nous utilisons la solution de virtualisation Proxmox. De mani\u00e8re simplifi\u00e9e :
- un serveur (assez puissant) se trouve dans la salle serveur du lyc\u00e9e.
- sur cet ordinateur, un grand nombre de syst\u00e8mes d'exploitation peuvent \u00eatre d\u00e9marr\u00e9s ind\u00e9pendamment.
- l'un d'entre eux porte votre nom : c'est votre machine virtuelle (votre VM).
- vous vous connectez \u00e0 votre VM depuis un navigateur de n'importe quel ordinateur du lyc\u00e9e.
- cet ordinateur (appel\u00e9 h\u00f4te) ne va faire que recevoir le flux vid\u00e9o venu du serveur (et lui envoyer les interactions utilisateurs : souris, clavier)
- en mettant ce flux vid\u00e9o en plein \u00e9cran, on a l'illusion d'\u00eatre sous un nouveau syst\u00e8me d'exploitation. Nous allons donc travailler sous Linux, tout en restant en r\u00e9alit\u00e9 sous Windows.
"},{"location":"T7_Divers/2_VM/cours/#methode","title":"M\u00e9thode","text":" - Sur le bureau Windows, ouvrir le dossier
Programmation
. - Cliquer sur
Proxmox NSI
. - Un navigateur s'ouvre, mais une alerte de s\u00e9curit\u00e9 appara\u00eet. Cliquer sur
Param\u00e8tres avanc\u00e9s
puis sur Continuer vers le site 172.17.191.244
- Sur la fen\u00eatre de connexion
Proxmox VE Login
, renseigner ses identifiants et s\u00e9lectionner Realm Proxmox VE authentication server
. - Un messade d'avertissement appara\u00eet. Cliquer
ok
pour l'ignorer. - S\u00e9lectionner sa machine virtuelle (VM) dans la colonne de gauche.
- Cliquer sur
Start
pour d\u00e9marrer la VM. - Cliquer sur le bouton
Console
et choisir Spice
. - Cliquer sur le fichier
telechargement.vv
apparu en bas \u00e0 gauche. - Attendre (un peu).
- Si rien ne se passe au bout d'une dizaine de secondes, fermer la fen\u00eatre et cliquer de nouveau sur Spice pour ret\u00e9l\u00e9charger un nouveau fichier.
-
Remplir ses identifiants dans la fen\u00eatre de connexion :
- login : eleve
- mdp : donn\u00e9 \u00e0 l'oral
-
Basculer l'affichage en plein \u00e9cran
- Au premier lancement d'un navigateur, remplir ses identifiants Scribe, permettant d'acc\u00e9der \u00e0 internet.
"},{"location":"T7_Divers/3_Thonny/cours/","title":"Thonny","text":"Comme pour tous les langages de programmation, il n'existe pas un logiciel permettant de coder en Python, mais un tr\u00e8s (tr\u00e8s) grand nombre de logiciels diff\u00e9rents, qu'on regroupe sous le nom d'IDE (interfaces de d\u00e9veloppement)
Pour la NSI, nous conseillons Thonny :
"},{"location":"T7_Divers/3_Thonny/cours/#installer-thonny","title":"Installer Thonny","text":" -
Rendez vous sur la page https://thonny.org/
-
T\u00e9l\u00e9chargez et installez la version qui correspond \u00e0 votre syst\u00e8me d'exploitation (Windows, Mac, Linux).
"},{"location":"T7_Divers/3_Thonny/cours/#alternatives","title":"Alternatives","text":"Pyzo, PyCharm, Spyder, VisualStudioCode... impossible de toutes les citer !
"},{"location":"T7_Divers/3_Thonny/cours/#solutions-en-ligne","title":"Solutions en ligne","text":"En ligne, sans aucune installation, vous pouvez utiliser https://console.basthon.fr/
ou bien m\u00eame la console ci-dessous !
>>> ou l'IDE qui suit :
\u25b6\ufe0f \u2935\ufe0f \u2934\ufe0f "},{"location":"T7_Divers/4_Processing/cours/","title":"Processing","text":" Processing est un outil de cr\u00e9ation multim\u00e9dia utilisant le code informatique. Simple de prise en main, il a \u00e9t\u00e9 cr\u00e9\u00e9 par des artistes pour des artistes. On peut utiliser le langage Python pour entrer les instructions.
Nous l'utiliserons pour ajouter du graphisme \u00e0 nos cr\u00e9ations...
Documentation - Le site officiel (anglais)
- Un manuel d'utilisation (fran\u00e7ais)
"},{"location":"T7_Divers/4_Processing/cours/#les-bases-de-processing","title":"Les bases de Processing","text":""},{"location":"T7_Divers/4_Processing/cours/#repere","title":"Rep\u00e8re","text":"\u00c0 l'ex\u00e9cution de tout script Processing, une fen\u00eatre s'affiche avec une zone de dessin. Sa taille se d\u00e9finit \u00e0 l'aide de la fonction size
. Par exemple, pour cr\u00e9er une zone de dessin de 300 pixels sur 200 pixels, on utilisera:
size(300, 200)\n
Chaque pixel de cette zone est rep\u00e9r\u00e9e par des coordonn\u00e9es dans le rep\u00e8re suivant, dont l'origine se situe en haut \u00e0 gauche et l'axe des ordonn\u00e9es est orient\u00e9 vers le bas.
"},{"location":"T7_Divers/4_Processing/cours/#traces","title":"Trac\u00e9s","text":"Trac\u00e9s de base
point
: permet de dessiner un point (pixel). En param\u00e8tre, les coordonn\u00e9es du point. line
: permet de tracer une ligne entre deux points. En param\u00e8tres, les coordonn\u00e9es des deux points. rect
: permet de tracer un rectangle. En param\u00e8tres, les coordonn\u00e9es du sommet haut-gauche, puis la largeur et la hauteur du rectangle. ellipse
: permet de tracer une ellipse. En param\u00e8tres, les coordonn\u00e9es du centre, puis la largeur et la hauteur (mettre la m\u00eame valeur pour un cercle).
Exemples Copier-coller le code suivant et faire varier les param\u00e8tres pour bien les comprendre.
size(200, 200)\npoint(10, 60)\nline(10, 10, 100, 150)\nrect(80, 10, 20, 50)\nellipse(150, 100, 80, 40)\n
"},{"location":"T7_Divers/4_Processing/cours/#couleurs","title":"Couleurs","text":"Pinceau
background
: permet de d\u00e9finir la couleur du fond de la zone de dessin. En param\u00e8tres, les trois composantes RGB de la couleur. stroke
: permet de d\u00e9finir la couleur du pinceau (noir par d\u00e9faut) pour le contour de la forme. En param\u00e8tres, les trois composantes RGB de la couleur. noStroke
: permet de dessiner une forme sans coutour (pas de param\u00e8tre). strokeWeight
: permet de d\u00e9finir la largeur du pinceau. En param\u00e8tre, le nombre de pixel. fill
: permet de d\u00e9finir la couleur de remplissage de la forme. En param\u00e8tres, les trois composantes RGB de la couleur.
Exemples Copier-coller le code suivant et faire varier les param\u00e8tres pour bien les comprendre.
size(200, 200)\nbackground(255, 255, 255)\nstroke(255, 0, 0)\npoint(10, 60)\nline(10, 10, 100, 150)\nstroke(0, 127, 255)\nstrokeWeight(5)\nrect(80, 10, 20, 50)\nnoStroke()\nfill(204, 153, 204)\nellipse(150, 100, 80, 40)\n
"},{"location":"T7_Divers/4_Processing/cours/#exercices","title":"Exercices","text":"Exercice 9
\u00c9crire un programme qui affiche le drapeau fran\u00e7ais, comme ci-contre, dans une zone de 300 x 200 pixels.
Exercice 10
\u00c9crire un programme qui trace un quadrillage (espacement de 20 pixels).
Contrainte: en seulement 3 lignes (sans compter \u00e9ventuellement size
.
Exercice 11
Afficher une croix verte de longueur 50 centr\u00e9e au point (60 ; 40), et un cercle rouge de diam\u00e8tre 30 centr\u00e9 en (150 ; 100). On prendra 10 pixels comme \u00e9paisseur.
Exercice 12
Cr\u00e9ez un programme permettant d\u2019afficher 100 disques \u00e0 l\u2019\u00e9cran. La taille de chaque disque devra \u00eatre al\u00e9atoire (mais comprise entre 20 et 50). La couleur de chaque disque devra aussi \u00eatre al\u00e9atoire.
Avec Processing, il est tr\u00e8s simple d\u2019avoir un nombre al\u00e9atoire : random(a,b)
permet d\u2019obtenir un nombre al\u00e9atoire entre a
et b
.
source - site de C\u00e9dric Gouygou
"},{"location":"T7_Divers/4_Processing_p5/cours/","title":"Processing au lyc\u00e9e \u21d4 p5 sur Capytale","text":""},{"location":"T7_Divers/4_Processing_p5/cours/#1-explication-du-probleme","title":"1. Explication du probl\u00e8me","text":"Pour r\u00e9aliser facilement de jolis graphiques, nous utilisons sur les ordinateurs du lyc\u00e9e le logiciel Processing. Celui-ci permet d'\u00e9crire du code Python et d'avoir un rendu imm\u00e9diat dans une fen\u00eatre s\u00e9par\u00e9e.
Pour le travail \u00e0 la maison, nous utilisons le service Capytale.
Probl\u00e8me, il n'est pas possible d'\u00e9crire du code Processing dans Capytale.
"},{"location":"T7_Divers/4_Processing_p5/cours/#2-une-solution-la-librairie-p5","title":"2. Une solution : la librairie p5","text":"Si Processing n'existe pas dans Capytale, une solution tr\u00e8s similaire est disponible : la librairie p5.
Remarque
La librairie p5
incluse dans Capytale est l\u00e9g\u00e8rement diff\u00e9rente de la libraire p5
utilisable dans Thonny (ou tout autre IDE). En effet, pour pouvoir fonctionner sur Capytale, elle a \u00e9t\u00e9 en partie r\u00e9-\u00e9crite par un des d\u00e9veloppeurs de Capytale, Romain Casati.
"},{"location":"T7_Divers/4_Processing_p5/cours/#3-structure-commune-des-codes-processing-et-p5","title":"3. Structure commune des codes Processing et p5","text":"Les codes Processing que nous avons \u00e9crits jusqu'\u00e0 pr\u00e9sent sont des codes statiques. Mais l'architecture naturelle d'un code Processing ou p5 est en r\u00e9alit\u00e9 articul\u00e9e autour de deux fonctions : la fonction setup()
et la fonction draw()
.
"},{"location":"T7_Divers/4_Processing_p5/cours/#31-la-fonction-setup","title":"3.1 La fonction setup()
","text":"Comme son nom l'indique, elle va proc\u00e9der \u00e0 tous les r\u00e9glages initiaux avant de commencer le dessin : taille de la fen\u00eatre, (\u00e9ventuellement couleur d'arri\u00e8re-plan), autres r\u00e9glages.
Elle n'est ex\u00e9cut\u00e9e qu'une seule fois.
"},{"location":"T7_Divers/4_Processing_p5/cours/#32-la-fonction-draw","title":"3.2 La fonction draw()
","text":"C'est dans cette fonction que toutes les instructions de dessin seront donn\u00e9es.
Tr\u00e8s important : cette fonction est une boucle infinie. Elle est donc r\u00e9p\u00e9t\u00e9e (\u00e0 une certaine cadence qui est r\u00e9glable) jusqu'\u00e0 ce que (par exemple) l'utilisateur ferme la fen\u00eatre.
Des instructions \u00e9crites dans la fonction setup()
peuvent influer sur cette boucle infinie draw()
: notamment l'instruction noLoop()
qui permet de n'ex\u00e9cuter la fonction draw()
qu'une seule fois.
"},{"location":"T7_Divers/4_Processing_p5/cours/#4-passer-dun-code-processing-a-un-code-p5","title":"4. Passer d'un code Processing \u00e0 un code p5","text":""},{"location":"T7_Divers/4_Processing_p5/cours/#41-seulement-en-p5-linstruction-run","title":"4.1 Seulement en p5 : l'instruction run()
","text":"Un code p5 devra forc\u00e9ment se terminer par l'instruction run()
"},{"location":"T7_Divers/4_Processing_p5/cours/#42-une-difference-de-syntaxe-createcanvas-vs-size","title":"4.2 Une diff\u00e9rence de syntaxe : createCanvas()
vs size()
","text":"Pour cr\u00e9er une zone de dessin de 300 pixels sur 300 pixels :
- Processing :
size(300,300)
- p5 :
createCanvas(300,300)
"},{"location":"T7_Divers/4_Processing_p5/cours/#43-cas-particulier-des-dessins-statiques","title":"4.3 Cas particulier des dessins statiques","text":"Nos premiers codes en Processing actuellement sont statiques : ils n'ont pas d'animation. Processing accepte alors que le code ne comporte ni fonction setup()
ni fonction draw()
.
Par contre, pour faire un code statique en p5, il faudra quand m\u00eame que les fonctions setup()
etdraw()
soient pr\u00e9sentes. On indiquera l'instruction noLoop()
dans le setup()
pour que le draw()
ne soit execut\u00e9 qu'une fois.
Exemple de passage d'un code statique en Processing \u00e0 un code statique en p5 :
- en bleu : les instructions \u00e0 rajouter
- en rouge : les instructions \u00e0 modifier (il n'y en a qu'une)
- sur fond jaune : le code \u00e0 conserver
Vous pouvez aussi comparer des codes statiques Processing avec leur \u00e9quivalent en p5 dans la feuille d'exercices sur Processing.
"},{"location":"T7_Divers/5_Capytale/cours/","title":"Utilisation du service Capytale","text":"Capytale est accessible via Lyc\u00e9econnect\u00e9, il faut donc avoir ses identifiants Educonnect.
"},{"location":"T7_Divers/5_Capytale/cours/#activite-test","title":"Activit\u00e9-test :","text":" - Connectez-vous \u00e0 Lyc\u00e9eConnect\u00e9 gr\u00e2ce \u00e0 vos identifiants Educonnect.
- Cliquez sur https://capytale2.ac-paris.fr/web/c/797d-639207
- Dans la liste des ENT, choisir Lyc\u00e9eConnect\u00e9.
- Capytale apparait avec le code de l'activit\u00e9 pr\u00e9-rempli, cliquez sur
Go !
.
"},{"location":"T7_Divers/5_Exposes/cours/","title":"Figures de l'informatique","text":""},{"location":"T7_Divers/5_Exposes/cours/#ada-lovelace","title":"Ada Lovelace","text":""},{"location":"T7_Divers/5_Exposes/cours/#alan-turing","title":"Alan Turing","text":""},{"location":"T7_Divers/5_Exposes/cours/#donald-knuth","title":"Donald Knuth","text":""},{"location":"T7_Divers/5_Exposes/cours/#bill-gates","title":"Bill Gates","text":""},{"location":"T7_Divers/5_Exposes/cours/#heidi-lamar","title":"Heidi Lamar","text":""},{"location":"T7_Divers/5_Exposes/cours/#steve-jobs","title":"Steve Jobs","text":""},{"location":"T7_Divers/5_Exposes/cours/#aaron-swartz","title":"Aaron Swartz","text":""},{"location":"T7_Divers/5_Exposes/cours/#grace-hopper","title":"Grace Hopper","text":""},{"location":"T7_Divers/5_Exposes/cours/#linus-torvalds","title":"Linus Torvalds","text":""},{"location":"T7_Divers/5_Exposes/cours/#margaret-hamilton","title":"Margaret Hamilton","text":""},{"location":"T7_Divers/5_Exposes/cours/#serguei-brin","title":"Sergue\u00ef Brin","text":""},{"location":"T7_Divers/5_Exposes/cours/#larry-page","title":"Larry Page","text":""},{"location":"T7_Divers/5_Exposes/cours/#richard-stallman","title":"Richard Stallman","text":""},{"location":"T7_Divers/5_Exposes/cours/#guido-van-rossum","title":"Guido Van Rossum","text":""},{"location":"T7_Divers/5_Exposes/cours/#dennis-ritchie","title":"Dennis Ritchie","text":""},{"location":"T7_Divers/5_Exposes/cours/#john-conway","title":"John Conway","text":""},{"location":"T8_DS/DS01/","title":"DS01","text":"Exercice 1
\u00c9nonc\u00e9Correction - \u00c9crire ci-dessous les instructions afin que les valeurs respectives de
p
et de q
soient \u00e9chang\u00e9es :
>>> p = 3\n>>> q = 7\n>>>\n>>>\n>>>\n
2. Proposer une autre m\u00e9thode plus rapide \u00e0 \u00e9crire : >>> p = 3\n>>> q = 7\n>>>\n
>>> p = 3\n>>> q = 7\n>>> temp = p\n>>> p = q\n>>> q = temp\n
2.
>>> p = 3\n>>> q = 7\n>>> p, q = q, p\n
Exercice 2
\u00c9nonc\u00e9Correction - \u00c9crire ci-dessous les instructions afin que la variable
score
soit augment\u00e9e de 20: >>> score = 0\n>>> \n
- Proposer une deuxi\u00e8me instruction \u00e9quivalente :
>>> score = 0\n>>> \n
1.
>>> score = 0\n>>> score = score + 20\n
2. >>> score = 0\n>>> score += 20\n
Exercice 3
\u00c9nonc\u00e9Correction Je souhaite coder un jeu. Je vais stocker dans une variable la largeur de l'\u00e9cran (qui vaudra 640 pixels par d\u00e9faut) et dans une autre variable la hauteur de l'\u00e9cran (qui vaudra 400 pixels par d\u00e9faut).
\u00c9crire ce que peuvent \u00eatre les deux premi\u00e8res lignes de mon code :
1 \n2 \n
largeur_ecran = 640\nhauteur_ecran = 400\n
Exercice 4
\u00c9nonc\u00e9Correction On consid\u00e8re le programme suivant :
for lettre in \"LUNDI\":\n print(lettre)\n
\u00c9crire ci-dessous ce qui s'affiche en console lors de l'ex\u00e9cution de ce programme. \n
L\nU\nN\nD\nI\n
Exercice 5
\u00c9nonc\u00e9Correction On consid\u00e8re le programme suivant :
liste_langages = ['Python', 'C++', 'SmallTalk']\nfor langage in liste_langages:\n print(langage, \"est un langage orient\u00e9-objet\")\n
\u00c9crire ci-dessous ce qui s'affiche en console lors de l'ex\u00e9cution de ce programme.
\n
Python est un langage orient\u00e9-objet\nC++ est un langage orient\u00e9-objet\nSmallTalk est un langage orient\u00e9-objet\n
Exercice 6
\u00c9nonc\u00e9Correction Proposer un code pour \u00e9crire (intelligemment) les lignes suivantes :
Voici le verdict du Choixpeau Magique :\nHarry sera \u00e0 Griffondor\nHermione sera \u00e0 Griffondor\nRon sera \u00e0 Griffondor\n
\n
print('Voici le verdict du Choixpeau Magique :')\npersonnages = ['Harry', 'Hermione', 'Ron']\nfor nom in personnages:\n print(nom, 'sera \u00e0 Griffondor')\n
"},{"location":"T8_DS/DS03/","title":"DS03","text":"correction sur Capytale.
"},{"location":"T8_Liens_utiles/liens/","title":"Liens utiles","text":""},{"location":"T8_Liens_utiles/liens/#a-propos-de-la-specialite-nsi","title":"\u00c0 propos de la sp\u00e9cialit\u00e9 NSI","text":" - Le site Eduscol
"},{"location":"T8_Liens_utiles/liens/#pour-resoudre-des-enigmes","title":"Pour r\u00e9soudre des \u00e9nigmes","text":"Quelques sites de challenges/\u00e9nigmes/d\u00e9fis de programmation:
- PyD\u00e9fis
- Hackinscience
- Advent of Code
- MicroContest
"},{"location":"T8_Liens_utiles/liens/#a-propos-de-la-culture-des-sciences-de-linformatique","title":"\u00c0 propos de la culture des sciences de l'informatique","text":" -
Interstices
-
Inria
"},{"location":"T8_Liens_utiles/liens/#pour-se-former-en-autonomie","title":"Pour se former en autonomie","text":"Au cas o\u00f9 vous vous ennuieriez...
- France-IOI
- CheckIO
- CodinGame
source - site de C\u00e9dric Gouygou
"}]}
\ No newline at end of file
+{"config":{"lang":["fr"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Accueil","text":""},{"location":"#themes-en-cours-detude","title":"Th\u00e8mes en cours d'\u00e9tude :","text":" - Fonctions
- Exercices sur les Fonctions
Anciens th\u00e8mes trait\u00e9s
- Boucle
while
- Exercices sur
while
- Instruction conditionnelle
if
- Exercices sur les
if
- Boucle
for ... in ...
- Exercices
for ... in ...
- Variables
"},{"location":"T1_Demarrer_en_Python/sommaire/","title":"Th\u00e8me 1 : Bases de Python","text":" - Variables
- Boucle For
- Boucle While
- Instruction conditionnelle If
- Fonctions
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/","title":"1.1 Variables","text":""},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#a-pourquoi-des-variables","title":"A. Pourquoi des variables ?","text":""},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#a1-introduction","title":"A.1 Introduction","text":"De la m\u00eame mani\u00e8re que dans votre chambre chaque objet a (normalement) une place attitr\u00e9e, un ordinateur (dont le r\u00f4le peut se r\u00e9sumer \u00e0 \u00abmanipuler tr\u00e8s vite des donn\u00e9es\u00bb) va assigner \u00e0 chaque objet une place particuli\u00e8re dans son espace-m\u00e9moire. Et il lui assignera un nom (choisi par l'utilisateur) afin de pouvoir acc\u00e9der \u00e0 cette valeur.
Nous ne rentrerons pas dans le d\u00e9tail du processus d'allocation-m\u00e9moire, nous retiendrons juste ceci : pour manipuler un objet, il faut qu'il d\u00e9j\u00e0 qu'il ait un nom. C'est par cela que nous allons commencer :
Premi\u00e8re variable
Consid\u00e9rons la phrase \u00abnous allons stocker le prix du spectacle dans une variable a
, qui vaudra au d\u00e9part 32.\u00bb
Il y a plusieurs commentaires \u00e0 faire sur une telle annonce :
- Dans le probl\u00e8me que l'on cherche \u00e0 mod\u00e9liser, le prix du spectacle est une donn\u00e9e importante, qui va peut-\u00eatre \u00e9voluer (ou pas !).
- Pour la manipuler plus simplement, on va la d\u00e9signer par un nom, le nom de la variable (ici, le nom
a
est particuli\u00e8rement mal choisi, voir D. Bonnes pratiques de nommage) - Comme en math\u00e9matiques, le nom de cette variable va d\u00e9signer une valeur qui peut changer (varier) au cours du temps (encore une fois : ou pas).
- Cette valeur est fix\u00e9e au d\u00e9part \u00e0 32. On dira en informatique qu'elle est initialis\u00e9e \u00e0 32.
- Si cette valeur ne change pas, on dira qu'elle est constante. Cela peut para\u00eetre inutile de donner un nom \u00e0 quelque chose qui ne change pas, mais cela est tr\u00e8s utile de d\u00e9finir les constantes au d\u00e9but d'un programme.
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#a2-on-code","title":"A.2 On code !","text":"La phrase pr\u00e9c\u00e9dente donnera donc lieu \u00e0 la ligne Python suivante :
>>> a = 32\n
Attention
Le symbole =
ici utilis\u00e9 n'a rien \u00e0 voir avec le symbole = utilis\u00e9 en math\u00e9matique. On dit qu'on a affect\u00e9 \u00e0 a
la valeur 32, et il faut se repr\u00e9senter mentalement cette action par l'\u00e9criture a \u2190 32
.
Comparaison de la syntaxe dans diff\u00e9rents langages
PythonCPHPJavaJavascriptRustGo a = 32\n
int a = 32;\n
$a = 32;\n
int a = 32;\n
var a = 32;\n
let a = 32;\n
a := 32\n
Une fois la valeur 32 stock\u00e9e dans la variable a
, on peut alors utiliser cette variable :
>>> a\n32\n>>> a + 5\n37\n>>> b\nTraceback (most recent call last):\n File \"<pyshell>\", line 1, in <module>\nNameError: name 'b' is not defined\n
Remarquez bien l'erreur lorsqu'on a fait appel \u00e0 une variable b
qui n'avait jamais \u00e9t\u00e9 d\u00e9finie, comme le dit explicitement le message NameError: name 'b' is not defined
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b-le-fonctionnement-interne","title":"B. Le fonctionnement interne","text":""},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b1-explication-simplifiee","title":"B.1 Explication simplifi\u00e9e","text":"En premi\u00e8re intention, il est possible d'expliquer le fonctionnement interne de l'affectation des variables par la m\u00e9taphore des tiroirs :
\u00c9crire l'instruction :
>>> a = 2\n
va provoquer chez l'ordinateur le comportement suivant :
- Est-ce que je poss\u00e8de d\u00e9j\u00e0 un tiroir appel\u00e9
a
? - si oui, je me positionne devant.
- si non, je cr\u00e9e un tiroir appel\u00e9
a
. - J'ouvre le tiroir et j'y d\u00e9pose la valeur num\u00e9rique 2. Si le tiroir contenait d\u00e9j\u00e0 une valeur, celle-ci dispara\u00eet (on dit qu'elle est \u00e9cras\u00e9e).
Cette explication est suffisante pour aborder la notion de variable : c'est un mot (ou une lettre) qui va d\u00e9signer une valeur.
Partie difficile (optionnelle) La m\u00e9taphore du tiroir est malheureusement un peu trop simplificatrice.
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b2-une-realite-bien-plus-complexe","title":"B.2 Une r\u00e9alit\u00e9 bien plus complexe...","text":""},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b21-la-commande-id-ladresse-du-tiroir","title":"B.2.1 La commande id()
: l'adresse du tiroir ?","text":"Python poss\u00e8de une fonction qui renvoie l'adresse m\u00e9moire de la variable donn\u00e9e en argument.
>>> b = 7\n>>> id(b)\n9788800\n
Faites le test avec votre propre IDE Python (vous n'obtiendrez pas forc\u00e9ment la m\u00eame valeur d'adresse m\u00e9moire)
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b22-cela-se-complique","title":"B.2.2 Cela se complique.","text":"Sans refermer notre IDE, \u00e9crasons la valeur de b
avec une nouvelle valeur :
>>> b = 12\n
et redemandons l'adresse de b
: >>> id(b)\n9788960\n
Tr\u00e8s mauvaise nouvelle : l'adresse de la variable b
a chang\u00e9. Ceci invalide notre m\u00e9taphore du \u00abtiroir\u00bb, une place unique qui serait r\u00e9serv\u00e9e pour y stocker les valeurs successives d'une variable.
La modification de la valeur de b
ne s'est pas faite \u00aben place\u00bb, la variable b
s'est d\u00e9plac\u00e9e : que s'est-il donc pass\u00e9 ?
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b23-tentative-dexplication","title":"B.2.3 Tentative d'explication","text":"L'affectation
>>> b = 9\n
ne provoque pas la r\u00e9servation d\u00e9finitive d'un espace-m\u00e9moire pour la variable b
, mais la cr\u00e9ation d'un lien vers un espace-m\u00e9moire qui contient la valeur 9. Ce lien consiste en l'adresse-m\u00e9moire de cette valeur 9. Cette adresse-m\u00e9moire vaut (sur ma configuration personnelle) 9788864
.
>>> id(b)\n9788864\n
Comme le pr\u00e9sente le ruban ci-dessus, Python pr\u00e9-positionne les entiers (de -5 \u00e0 256) sur des petites adresses-m\u00e9moires, car il consid\u00e8re que ces entiers servent souvent, et doivent donc \u00eatre rapidement accessibles.
Si on cr\u00e9\u00e9 une nouvelle variable tokyo
aussi \u00e9gale \u00e0 9, elle va aussi pointer vers la m\u00eame adresse-m\u00e9moire :
>>> tokyo = 9\n>>> id(tokyo)\n9788864\n
Les variables tokyo
et b
renvoient vers la m\u00eame adresse-m\u00e9moire. Affectons maintenant \u00e0 tokyo
la valeur 2020 et observons son adresse-m\u00e9moire :
>>> tokyo = 2020\n>>> id(tokyo)\n139762979309936\n
L'adresse-m\u00e9moire est (bien) plus grande : elle a \u00e9t\u00e9 choisie sur le moment par Python pour y stocker 2020 (car 2020 > 256).
De mani\u00e8re plus surprenante, si on cr\u00e9\u00e9 une nouvelle variable jo
qui vaut aussi 2020, Python va ouvrir une autre adresse-m\u00e9moire pour y stocker 2020, alors qu'il l'a d\u00e9j\u00e0 stock\u00e9e ailleurs :
>>> jo = 2020\n>>> id(jo)\n139762979310064\n
En r\u00e9sum\u00e9, une variable n'est pas le nom d'un tiroir mais plut\u00f4t le nom d'une fl\u00e8che qui pointe vers un espace-m\u00e9moire de l'ordinateur. - La fl\u00e8che peut pointer vers un nouvel espace-m\u00e9moire sans que le nom de la variable change. - Deux variables peuvent pointer vers le m\u00eame espace-m\u00e9moire.
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b3-une-histoire-en-2-temps-evaluation-affectation","title":"B.3 Une histoire en 2 temps : \u00e9valuation, affectation","text":"Observons l'instruction
>>> a = 2 + 3\n
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b31-etape-1-levaluation","title":"B.3.1 \u00c9tape 1 : l'\u00e9valuation","text":"Python va prendre la partie \u00e0 droite du signe \u00e9gal et va l'\u00e9valuer, ce qui signifie qu'il va essayer de lui donner une valeur. Dans nos exemples, cette valeur sera num\u00e9rique, mais elle peut \u00eatre d'un autre type (voir plus loin)
Ici, Python effectue le calcul 2 + 3 et l'\u00e9value \u00e0 la valeur 5.
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b32-etape-2-laffectation","title":"B.3.2 \u00c9tape 2 : l'affectation","text":"Une fois \u00e9valu\u00e9e l'expression \u00e0 droite du signe =, il ne reste plus qu'\u00e0 l'affecter \u00e0 la variable (d\u00e9j\u00e0 existante ou pas) situ\u00e9e \u00e0 gauche du signe =.
Comme expliqu\u00e9 pr\u00e9c\u00e9demment, un \u00ablien\u00bb est fait entre le nom de la variable et l'adresse-m\u00e9moire qui contient la valeur \u00e9valu\u00e9e. a
sera donc li\u00e9 \u00e0 la valeur 5. Plus simplement, on dira que \u00aba
vaut 5\u00bb
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b32-lincrementation-dune-variable","title":"B.3.2 L'incr\u00e9mentation d'une variable.","text":"\u00abIncr\u00e9menter\u00bb une variable signifie l'augmenter.
Imaginons une variable appel\u00e9e compteur
. Au d\u00e9marrage de notre programme, elle est initialis\u00e9e \u00e0 la valeur 0.
>>> compteur = 0\n
Consid\u00e9rons qu'\u00e0 un moment du programme, cette variable doit \u00eatre modifi\u00e9e, par exemple en lui ajoutant 1.
En Python, cela s'\u00e9crira :
>>> compteur = compteur + 1\n
Observ\u00e9e avec des yeux de math\u00e9maticien, la pr\u00e9c\u00e9dente instruction est une horreur.
Vue avec des yeux d'informaticien, voil\u00e0 comment est interpr\u00e9t\u00e9e la commande
>>> compteur = compteur + 1\n
- On \u00e9value la partie droite de l'\u00e9galit\u00e9, donc l'expression
compteur + 1
. - On va donc chercher le contenu de la variable
compteur
. Si celle-ci n'existe pas, un message d'erreur est renvoy\u00e9. - On additionne 1 au contenu de la variable
compteur
. - On \u00e9crase le contenu actuel de la variable
compteur
avec la valeur obtenue au 3.
\u00c0 la fin de ces op\u00e9rations, la variable compteur
a bien augment\u00e9 de 1.
Cette proc\u00e9dure d'incr\u00e9mentation est tr\u00e8s tr\u00e8s classique, il faut la ma\u00eetriser parfaitement !
Syntaxe classique et syntaxe Pythonesque
L'incr\u00e9mentation d'une variable compteur
s'\u00e9crira donc en Python :
>>> compteur = compteur + 1\n
Mais il existe aussi une syntaxe particuli\u00e8re, un peu plus courte : >>> compteur += 1\n
Cette syntaxe peut se ranger dans la cat\u00e9gorie des sucres syntaxiques : c'est bien de la conna\u00eetre, c'est amusant de s'en servir, mais son utilisation n'est en rien obligatoire et peut avoir un effet n\u00e9faste, celui d'oublier r\u00e9ellement ce qu'il se passe derri\u00e8re. Exercice 1
\u00c9crire le code \u00abclassique\u00bb et le code \u00abPythonesque\u00bb pour l'instruction suivante :
On initialise une variable score
\u00e0 100 et on l'augmente de 15.
Correction >>> score = 100\n>>> score = score + 15\n
ou encore >>> score = 100\n>>> score += 15\n
Exercice 2
\u00c9crire le code \u00abclassique\u00bb et le code \u00abPythonesque\u00bb pour l'instruction suivante :
On initialise une variable cellule
\u00e0 1 et on la multiplie par 2.
Correction >>> cellule = 1\n>>> cellule = cellule * 2\n
ou bien >>> cellule = 1\n>>> cellule *= 2\n
Exercice 3
\u00c9crire le code \u00abclassique\u00bb et le code \u00abPythonesque\u00bb pour l'instruction suivante.
On initialise une variable capital
\u00e0 1000 et on lui enl\u00e8ve 5%.
Correction >>> capital = 1000\n>>> capital = capital - capital * 5/100\n
ou bien >>> capital = 1000\n>>> capital *= 0.95\n
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#b33-lechange-de-variables","title":"B.3.3 L'\u00e9change de variables","text":"Apr\u00e8s l'incr\u00e9mentation, une autre technique de base reviendra fr\u00e9quemment dans nos codes : l'\u00e9change de variables.
Imaginons les variables suivantes :
>>> a = 3\n>>> b = 5\n
Le but est d'\u00e9changer les valeurs de a
et de b
. \u25b8 M\u00e9thode na\u00efve
>>> a = b\n>>> b = a\n
Que valent a
et b
maintenant ?
Malheureusement :
>>> a\n5\n>>> b\n5\n>\n
La variable a
a \u00e9t\u00e9 \u00e9cras\u00e9e d\u00e8s qu'on lui a donn\u00e9 la valeur de la variable b
.
Comment la pr\u00e9server ?
La situation est similaire au probl\u00e8me suivant : comment \u00e9changer le contenu de ces deux verres ?
La m\u00e9thode est \u00e9vidente : il nous faut un troisi\u00e8me verre.
Nous allons faire de m\u00eame pour nos variables. Nous allons utiliser une variable temporaire (on parle aussi de variable tampon) pour conserver la m\u00e9moire de la valeur de a
(par exemple) avant que celle-ci ne se fasse \u00e9craser :
>>> a = 3\n>>> b = 5\n>>> temp = a\n>>> a = b\n>>> b = temp\n
Vous pouvez v\u00e9rifier maintenant que les valeurs de a
et de b
ont bien \u00e9t\u00e9 \u00e9chang\u00e9es.
Syntaxe classique et syntaxe Pythonesque
L'\u00e9change de deux variables a
et de b
s'\u00e9crit donc :
>>> temp = a\n>>> a = b\n>>> b = temp\n
Mais il existe aussi une syntaxe particuli\u00e8re \u00e0 Python, bien plus courte : >>> a, b = b, a\n
C'est de nouveau un sucre syntaxique. Cette syntaxe nous dispense de cr\u00e9er nous-m\u00eame une troisi\u00e8me variable. Mais pas de miracle : en interne, Python cr\u00e9e lui-m\u00eame cette variable temporaire. La simultan\u00e9it\u00e9 n'existe pas en informatique. Exercice 4
Une petite erreur s'est gliss\u00e9e \u00e0 Poudlard :
>>> maison_Harry = \"Serpentard\"\n>>> maison_Malfoy = \"Gryffondor\"\n
Corriger cette erreur, de deux mani\u00e8res diff\u00e9rentes. Correction >>> t = maison_Harry\n>>> maison_Harry = maison_Malfoy\n>>> maison_Malfoy = t\n
ou plus rapidement : >>> maison_Harry, maison_Malfoy = maison_Malfoy, maison_Harry\n
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#c-differents-types-de-variables","title":"C. Diff\u00e9rents types de variables","text":"Pour l'instant, les variables que nous avons manipul\u00e9es contiennent toutes des nombres entiers.
Sauf les maisons de Poudlard, qui sont des mots cha\u00eenes de caract\u00e8res.
Pour diff\u00e9rencier la nature de ce que peut contenir une variable, on parle alors de type de variable.
En voici quelques uns, que nous d\u00e9couvrirons au fil de l'ann\u00e9e :
Types de base
Voici les types Python les plus fr\u00e9quemment utilis\u00e9s cette ann\u00e9e:
Type Python Traduction Exemple int
entier 42
float
flottant (d\u00e9cimal) 3.1416
str
cha\u00eene de caract\u00e8res (string) \"NSI\"
bool
bool\u00e9en (True ou False) True
tuple
p-uplet (255, 127, 0)
list
liste [0, 1, 2, 3, 4, 5]
dict
dictionnaire {'Homer':43, 'Marge':41, 'Bart':12, 'Lisa':10, 'Maggie':4}
function
fonction print
Comment conna\u00eetre le type d'une variable ? Il suffit dans la console d'utiliser la fonction type
.
>>> a = 1\n>>> type(a)\n<class 'int'>\n
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#c1-python-et-le-typage-dynamique","title":"C.1 Python et le typage dynamique","text":"Jusqu'\u00e0 pr\u00e9sent, nous ne nous sommes pas occup\u00e9s de pr\u00e9ciser \u00e0 Python le type de notre variable.
a = 3\n
Mais dans certains langages, c'est obligatoire. En C par exemple, il faut \u00e9crire :
int a = 3;\n
Cela signifie (pour le langage C) que notre variable a
n'aura pas le droit de contenir autre chose qu'un nombre entier. Si on \u00e9crit ensuite
a = \"test\";\n
Le compilateur C renverra une erreur : on ne peut pas stocker une cha\u00eene de caract\u00e8res dans une variable qu'on a cr\u00e9\u00e9e comme \u00e9tant de type entier.
Et en Python ?
>>> a = 3\n>>> type(a)\n<class 'int'>\n>>> a = \"test\"\n>>> type(a)\n<class 'str'>\n
Python a chang\u00e9 tout seul le type de notre variable, sans intervention. On parle de typage dynamique.
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#d-bonnes-pratiques-de-nommage","title":"D. Bonnes pratiques de nommage","text":""},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#d1-ce-qui-est-autorise-et-ce-qui-ne-lest-pas","title":"D.1 Ce qui est autoris\u00e9 et ce qui ne l'est pas","text":"Pour nommer correctement une variable, il existe des r\u00e8gles \u00e0 respecter.
Les r\u00e8gles
-
le nom de la variable peut contenir les caract\u00e8res suivants :
- des lettres non accentu\u00e9es. Attention, minuscule et majuscule sont des caract\u00e8res diff\u00e9rents. Les accents sont en fait tol\u00e9r\u00e9s mais sont \u00e0 \u00e9viter.
- des chiffres (mais pas comme premier caract\u00e8re)
- le tiret du bas _ (underscore, tiret du 8)
-
le nom de la variable ne doit pas commencer par un chiffre
- le nom de la variable ne doit pas contenir d'espace
- le nom de la variable ne doit pas \u00eatre un mot-cl\u00e9 du langage.
Liste des mots-cl\u00e9s r\u00e9serv\u00e9s par Python andas assert break class continue def del elif else except False finally for from global if import in is lambda None not or pass raise return True try while with yield
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#d2-du-sens-du-sens-du-sens","title":"D.2 Du sens, du sens, du sens","text":"Hormis pour les indices (de boucles, de tableaux...) un nom de variable (dans un programme destin\u00e9 \u00e0 \u00eatre lu, par vous ou quelqu'un d'autre) doit imp\u00e9rativement avoir du sens :
# PAS BIEN\nif d == 1:\n cep += vm\n\n# BIEN\nif date == 1:\n compte_epargne += versement_mensuel\n
R\u00e8gle d'or
On ne donne jamais un nom de variable au hasard, on le choisit pour qu'il soit explicite.
Oui mais pour donner du sens, il faut souvent plusieurs mots... La longueur du nom de la variable (\u00abc'est trop long \u00e0 taper\u00bb) n'est plus un probl\u00e8me depuis que la grande majorit\u00e9 des IDE propose la compl\u00e9tion automatique. Mais comment former ces longs mots ?
"},{"location":"T1_Demarrer_en_Python/1.1_Variables/cours/#d3-syntaxe-des-noms-a-rallonge","title":"D.3 Syntaxe des noms \u00e0 rallonge","text":"Comment accoler des mots
- S'il est compos\u00e9, le nom peut \u00eatre de la forme:
snake_case
: les mots sont s\u00e9par\u00e9s par des underscores. Conseill\u00e9 en Python. camelCase
: les mots sont s\u00e9par\u00e9s par des majuscules mais la 1\u00e8re lettre est minuscule. Conseill\u00e9 en Javascript. PascalCase
: les mots sont s\u00e9par\u00e9s par des majuscules et la 1\u00e8re lettre est majuscule. Conseill\u00e9 en C. kebab-case
: les mots sont s\u00e9par\u00e9s par des tirets courts. Conseill\u00e9 en HTML - CSS.
Sans surprise, en Python, nous utiliserons donc le snake_case
.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/","title":"1.2 Boucle for ... in ...
","text":""},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#1-les-enumerables","title":"1. Les \u00e9num\u00e9rables","text":"En math\u00e9matiques, on dit qu'un ensemble est d\u00e9nombrable lorsqu'on peut associer \u00e0 chaque \u00e9l\u00e9ment de l'ensemble un nombre (traditionnellement 1, 2, 3 ...)
- les fraises Tagada d'un paquet sont d\u00e9nombrables.
- les voitures qui roulent sur l'autoroute sont d\u00e9nombrables.
- l'eau qui coule d'un robinet n'est pas d\u00e9nombrable.
En informatique, il existe un concept similaire qui va d\u00e9signer les objets que l'on peut \u00e9num\u00e9rer, c'est-\u00e0-dire les d\u00e9composer en une succession ordonn\u00e9e d'\u00e9l\u00e9ments. On les appelle les \u00e9num\u00e9rables ou les it\u00e9rables (Python utilise le mot anglais iterable
).
- la variable
\"NSI\"
(qui est de type String
) est \u00e9num\u00e9rable : on peut la d\u00e9composer en N
, S
, I
. - la variable
[4, 3, 17]
(qui est de type List
) est \u00e9num\u00e9rable : on peut la d\u00e9composer en 4
, 3
, 17
. - la variable
5
(qui est de type Int
) n'est PAS \u00e9num\u00e9rable : on ne peut pas la d\u00e9composer.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#2-iterer-sur-les-iterables-la-boucle-for-in","title":"2. It\u00e9rer sur les it\u00e9rables : la boucle for ... in ...
","text":""},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#21-iterer-sur-une-chaine-de-caracteres","title":"2.1 It\u00e9rer sur une cha\u00eene de caract\u00e8res","text":"La principale caract\u00e9ristique d'un ordinateur est d'exceller dans les op\u00e9rations r\u00e9p\u00e9titives.
(je vous laisse retrouver la citation de G\u00e9rard Berry, professeur au Coll\u00e8ge de France, commen\u00e7ant par \u00abl'ordinateur est...\u00bb)
Il existe donc une instruction permettant de faire une (ou plusieurs) action(s) \u00e0 chaque it\u00e9ration sur un \u00e9l\u00e9ment \u00e9num\u00e9rable.
Exemple fondateur n\u00b01
Le programme suivant :
for k in 'NSI':\n print(k)\n
va donner ceci : N\nS\nI\n
Analyse gr\u00e2ce \u00e0 PythonTutor
\u00c9tudions, gr\u00e2ce \u00e0 PythonTutor, le d\u00e9tail de cette ex\u00e9cution.
Cliquez sur Next et observez bien l'\u00e9volution de la variable k
.
La variable k
prend donc successivement toutes les lettre de la cha\u00eene de caract\u00e8re \"NSI\"
.
Pour chaque valeur de k
, la ou les instruction(s) situ\u00e9es de mani\u00e8re indent\u00e9e sous la ligne du for
seront ex\u00e9cut\u00e9es.
Ici, il y a simplement un print(k)
, donc chaque lettre de \"NSI\"
s'affiche l'une apr\u00e8s l'autre.
Exercice 1
Que donne le script suivant ?
for m in 'NASA':\n print(\"bonjour\")\n
Correction bonjour\nbonjour\nbonjour\nbonjour\n
Dans cet exercice, la variable de boucle m
est muette : elle n'appara\u00eet dans les instructions indent\u00e9es sous le for
.
La variable m
prend successivement les valeurs 'N
, 'A'
, 'S'
et 'A'
, mais on ne la voit pas.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#23-lindentation","title":"2.3 L'indentation","text":"L'indentation est primordiale en Python : c'est elle qui indique les blocs de code. Dans d'autres langages, ils peuvent \u00eatre d\u00e9limit\u00e9s par des accolades {
et }
.
Dans une boucle, tout ce qui sera indent\u00e9 sous le for
sera r\u00e9p\u00e9t\u00e9 un certain nombre de fois. Puis le code continuera : on dit qu'on sera sorti de la boucle.
Observez la diff\u00e9rence entre l'ex\u00e9cution des codes suivants :
for m in 'NASA':\n print(\"bonjour\")\n print(\"au revoir\")\n
et
for m in 'NASA':\n print(\"bonjour\")\nprint(\"au revoir\")\n
et persuadez-vous de l'importance d'\u00eatre vigilant sur l'indentation !
Comment \u00e9viter les erreurs classiques
Quand vous \u00e9crivez une boucle for ... in ...
, veillez bien \u00e0 :
- finir la ligne du
for
par les deux points :
- indenter sous le
for
les instructions qui doivent \u00eatre r\u00e9p\u00e9t\u00e9es. Si l'indentation ne s'est pas faite automatiquement apr\u00e8s appui sur la touche Entr\u00e9e
, c'est que vous avez oubli\u00e9 les :
.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#23-iterer-sur-une-liste","title":"2.3 It\u00e9rer sur une liste","text":"Exemple fondateur n\u00b02
Le programme suivant :
for jour in [\"lundi\", \"mardi\", \"mercredi\", \"jeudi\", \"vendredi\"]:\n print(\"je vais au lyc\u00e9e le\", jour)\n
va donner ceci : je vais au lyc\u00e9e le lundi\nje vais au lyc\u00e9e le mardi\nje vais au lyc\u00e9e le mercredi\nje vais au lyc\u00e9e le jeudi\nje vais au lyc\u00e9e le vendredi\n
Analyse gr\u00e2ce \u00e0 PythonTutor
Attention: tr\u00e8s souvent, l'objet \u00e9num\u00e9rable que la boucle va parcourir aura \u00e9t\u00e9 au pr\u00e9alable stock\u00e9 dans une variable :
Exemple fondateur n\u00b03
Le programme pr\u00e9c\u00e9dent est \u00e9quivalent \u00e0 :
semaine = [\"lundi\", \"mardi\", \"mercredi\", \"jeudi\", \"vendredi\"]\nfor jour in semaine:\n print(\"je vais au lyc\u00e9e le\", jour)\n
Notez l'importance d'avoir choisi des noms de variables explicites : ils aident grandement \u00e0 la lisibilit\u00e9 du code.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#3-comment-repeter-n-fois-la-meme-action","title":"3. Comment r\u00e9p\u00e9ter n
fois la m\u00eame action ?","text":"Scratch dispose du (tr\u00e8s pratique) bloc suivant :
Comment effectuer la m\u00eame chose en Python ?
Comment r\u00e9p\u00e9ter 10 fois la phrase \"We're up all night to get lucky\"
?
Nous pourrions nous en sortir par
for k in \"blablablab\": #(1) \n print(\"We're up all night to get lucky\")\n
- n'importe quel mot de 10 caract\u00e8res ferait l'affaire...
mais il doit clairement y avoir mieux...
Il y a mieux !
L'ensemble range
Le programme suivant :
for i in range(5):\n print(\"We're up all night to get lucky\")\n
va donner ceci : We're up all night to get lucky\nWe're up all night to get lucky\nWe're up all night to get lucky\nWe're up all night to get lucky\nWe're up all night to get lucky\n
L\u00e0 encore, le i
est une variable muette.
Le _
comme variable muette
Lorsque la variable de boucle est muette et ne sert qu'\u00e0 effectuer \\(n\\) fois la m\u00eame action, on utilise souvent le caract\u00e8re _
(appel\u00e9 underscore)comme variable de boucle.
Il faut le comprendre comme un avertissement au lecteur du code : \u00abcette boucle ne sert qu'\u00e0 faire \\(n\\) fois la m\u00eame chose\u00bb
for _ in range(5):\n print(\"Tout \u00e7a est tr\u00e8s r\u00e9p\u00e9titif\")\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#4-tout-sur-le-range","title":"4. Tout sur le range
.","text":""},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#41-retour-sur-lexemple-precedent","title":"4.1 Retour sur l'exemple pr\u00e9c\u00e9dent.","text":"Si nous rendions la variable i
moins muette ?
for i in range(5):\n print(i, \"We're up all night to get lucky\")\n
va donner ceci : 0 We're up all night to get lucky\n1 We're up all night to get lucky\n2 We're up all night to get lucky\n3 We're up all night to get lucky\n4 We're up all night to get lucky\n
i
prend donc successivement toutes les valeurs enti\u00e8res entre 0 et 4. Il y en a bien 5."},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#42-utilisation-minimale-de-lobjet-range","title":"4.2 Utilisation minimale de l'objet range()
","text":"Syntaxe minimale de range()
Le programme suivant :
for k in range(4):\n print(k)\n
va donner ceci : 0\n1\n2\n3\n
Interpr\u00e9tation : faire parcourir \u00e0 une variable k
l'ensemble range(n)
va faire prendre \u00e0 k
les valeurs 0, 1, 2, ..., n-1. "},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#43-utilisation-avancee-de-lobjet-range","title":"4.3 Utilisation avanc\u00e9e de l'objet range()
","text":"Syntaxe compl\u00e8te de range()
Le programme suivant :
for k in range(5, 15, 2):\n print(k)\n
va donner ceci : 5\n7\n9\n11\n13\n
Interpr\u00e9tation : faire parcourir \u00e0 k
l'ensemble range(start, stop, step)
fait : - d\u00e9marrer
k
\u00e0 la valeur start
, - progresser
k
de step
en step
tant que k
est strictement inf\u00e9rieur \u00e0 stop
.
Remarques :
- si le
step
est omis, il vaut 1 par d\u00e9faut. - l'objet
range(5)
n'est pas \u00abtechniquement\u00bb \u00e9gal \u00e0 la liste [0, 1, 2, 3, 4]
, car ce n'est pas un objet de type List
:
>>> type(range(5))\n<class 'range'>\n
Si n\u00e9cessaire, on peut le convertir en liste : >>> list(range(5))\n[0, 1, 2, 3, 4]\n
Il faut donc garder en t\u00eate que l'objet renvoy\u00e9 par range()
est un it\u00e9rable assimilable \u00e0 une liste de nombres.
Exercice 2
Faire afficher les s\u00e9ries de nombres suivantes.
On utilisera la syntaxe print(k, end = ' ')
) pour afficher les nombres horizontalement.
A. 0 1 2 3 4 5
Correction for k in range(6):\n print(k, end = ' ')\n
B. 10 11 12 13 14 15
Correction for k in range(10,16):\n print(k, end = ' ')\n
C. 3 6 9 12
Correction for k in range(3,13,3):\n print(k, end = ' ')\n
D. 10 9 8 7 6 5 4 3 2 1 0
Correction for k in range(10,-1,-1):\n print(k, end = ' ')\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#5-une-situation-classique-la-double-boucle","title":"5. Une situation classique : la double boucle","text":"Il est tr\u00e8s souvent utile d'imbriquer une boucle dans une autre, notamment lors du parcours de tous les pixels d'une image. Prenons pour l'instant un exemple num\u00e9rique.
Exemple fondateur
Le programme suivant :
for a in range(1,5):\n for b in range(1,4):\n p = a * b\n print(a, '*', b, '=', p)\n
va donner ceci : 1 * 1 = 1\n1 * 2 = 2\n1 * 3 = 3\n2 * 1 = 2\n2 * 2 = 4\n2 * 3 = 6\n3 * 1 = 3\n3 * 2 = 6\n3 * 3 = 9\n4 * 1 = 4\n4 * 2 = 8\n4 * 3 = 12\n
Analyse gr\u00e2ce \u00e0 PythonTutor
Exercice 3
\u00c9crire un programme qui affiche :
Papa dit : \u00ab et une cuill\u00e8re pour Riri ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re pour Fifi ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re pour Loulou ! \u00bb\nMaman dit : \u00ab et une cuill\u00e8re pour Riri ! \u00bb\nMaman dit : \u00ab et une cuill\u00e8re pour Fifi ! \u00bb\nMaman dit : \u00ab et une cuill\u00e8re pour Loulou ! \u00bb\nMamie dit : \u00ab et une cuill\u00e8re pour Riri ! \u00bb\nMamie dit : \u00ab et une cuill\u00e8re pour Fifi ! \u00bb\nMamie dit : \u00ab et une cuill\u00e8re pour Loulou ! \u00bb\n
Correction adultes = ['Papa', 'Maman', 'Mamie']\nenfants = ['Riri', 'Fifi', 'Loulou']\n\nfor parent in adultes:\n for enfant in enfants:\n print(parent, 'dit : \u00ab et une cuill\u00e8re pour', enfant, '! \u00bb') \n
Exercice 4
Rajouter \u00e0 la phrase pr\u00e9c\u00e9dente le contenu de la cuill\u00e8re (pur\u00e9e puis compote).
Exemple :
Papa dit : \u00ab et une cuill\u00e8re de pur\u00e9e pour Riri ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re de compote pour Riri ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re de pur\u00e9e pour Fifi ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re de compote pour Fifi ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re de pur\u00e9e pour Loulou ! \u00bb\nPapa dit : \u00ab et une cuill\u00e8re de compote pour Loulou ! \u00bb\nMaman dit : \u00ab et une cuill\u00e8re de pur\u00e9e pour Riri ! \u00bb\nMaman dit : \u00ab et une cuill\u00e8re de compote pour Riri ! \u00bb\n...\n
Correction for parent in ['Papa', 'Maman', 'Mamie']:\n for enfant in ['Riri', 'Fifi', 'Loulou']:\n for nourriture in ['pur\u00e9e', 'compote']:\n print(parent, 'dit : \u00ab et une cuill\u00e8re de', nourriture, 'pour', enfant, '! \u00bb')\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/cours/#6-pour-conclure","title":"6. Pour conclure","text":"\u00c0 retenir
- La boucle
for ... in ...
s'utilise lorsque : - on veut parcourir un \u00e0 un les \u00e9l\u00e9ments d'un objet it\u00e9rable (une cha\u00eene de caract\u00e8re, une liste, un tuple, un dictionnaire...)
- on veut r\u00e9p\u00e9ter une action un nombre de fois connu \u00e0 l'avance. On parle de boucle born\u00e9e.
-
Les instructions r\u00e9p\u00e9t\u00e9es peuvent - mais ce n'est pas obligatoire - faire appel \u00e0 la variable de boucle, mais il ne faut pas que ces instructions la modifient.
-
Ne pas oublier les :
et l'indentation !
range(n)
g\u00e9n\u00e8re une s\u00e9quence de n
nombres entiers: on s'en servira d\u00e8s qu'on aura besoin de r\u00e9p\u00e9ter n
fois des instructions.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exercices/","title":"Exercices sur la boucle for ... in
","text":"Exercice 1
On donne une liste d'acteurs :
liste_acteurs = ['Tahar', 'Omar', 'Guillaume', 'Swann', 'Alex', 'Roschdy']\n
Utilisez cette liste pour produire la sortie suivante:
Tahar a eu le C\u00e9sar du meilleur acteur\nOmar a eu le C\u00e9sar du meilleur acteur\nGuillaume a eu le C\u00e9sar du meilleur acteur\nSwann a eu le C\u00e9sar du meilleur acteur\nAlex a eu le C\u00e9sar du meilleur acteur\nRoschdy a eu le C\u00e9sar du meilleur acteur\n
Correction liste_acteurs = ['Tahar', 'Omar', 'Guillaume', 'Swann', 'Alex', 'Roschdy']\n\nfor acteur in liste_acteurs:\n print(acteur, 'a eu le C\u00e9sar du meilleur acteur')\n
Concat\u00e9nation de caract\u00e8res
Il est possible de coller (le vrai mot est concat\u00e9ner) deux cha\u00eenes de caract\u00e8res par l'op\u00e9rateur +
:
>>> \"a\" + \"b\"\n'ab'\n
Exercice 2
Dans l'extrait de code suivant:
chaine
est une variable initialis\u00e9e avec un str
vide : \"\"
; - on veut qu'en sortie de programme cette variable contienne la valeur
'bravo'
.
L'id\u00e9e est d'ajouter une par une les lettres \u00e0 la variable chaine
.
\u00c0 l'ex\u00e9cution, le programme doit afficher uniquement bravo
.
Compl\u00e9ter le code.
chaine = \"\"\nfor ... in ['b', 'r', 'a', 'v', 'o']:\n ...\nprint(chaine)\n
Cette variable chaine
est appel\u00e9e un accumulateur.
Correction chaine = ''\nfor lettre in ['b', 'r', 'a', 'v', 'o']:\n chaine = chaine + lettre #(1)\n\nprint(chaine)\n
- Ou bien
chaine += lettre
Exercice 3
En Python, la fonction ord
renvoie le code Unicode d'un caract\u00e8re et la fonction chr
le contraire: elle renvoie le caract\u00e8re correspondant \u00e0 un code Unicode.
Par exemple:
>>> ord('a')\n97\n>>> chr(97)\n'a'\n
Voici une liste contenant les codes Unicode des lettres d'un mot secret... \u00c0 vous d'\u00e9crire un programme o\u00f9 en sortie, la variable mot_secret
contiendra la cha\u00eene de caract\u00e8res de ce mot.
mystere = [111, 107, 44, 32, 98, 105, 101, 110, 32, 106, 111, 117, 233]\nmot_secret = \"\"\n\n# \u00e0 vous !\n
Correction mystere = [111, 107, 44, 32, 98, 105, 101, 110, 32, 106, 111, 117, 233]\nmot_secret = \"\"\n\nfor nombre in mystere:\n lettre = chr(nombre)\n mot_secret = mot_secret + lettre\n\nprint(mot_secret)\n
Exercice 4
On souhaite calculer la somme des 1000 premiers nombres entiers naturels, c'est-\u00e0-dire:
\\(1+2+3+4+5+ \\dots +999+1000\\)
\u00c9crire un programme avec une variable somme
accumulateur (comme \u00e0 l'exercice 3) qui contiendra la valeur souhait\u00e9e en fin de programme.
Correction somme = 0\nfor k in range(1001):\n somme += k\nprint(somme)\n
Exercice 5
Calculer \\(1\\times 2 \\times 3 \\times \\dots 99 \\times 100\\).
Correction produit = 1\nfor k in range(1,101):\n produit = produit * k\nprint(produit) \n
Exercice 6
Proposer un code qui \u00e9crit la table de multiplication de 7, de 8 et de 9.
La sortie doit ressembler \u00e0 :
7*1 = 7\n\n7*2 = 14\n\n... \n...\n\n9*9 = 81 \n
Correction for a in range(7, 10):\n for b in range(1, 10):\n print(a, '*', b, '=', a*b)\n
Exercice 7
Sur un jeu d'\u00e9checs, les cases sont rep\u00e9r\u00e9es par une lettre (de A jusqu'\u00e0 H) et par un chiffre (de 1 jusqu'\u00e0 8).
Les cases sont donc A1, A2, A3, ..., H7, H8.
Proposer un code qui \u00e9crit toutes les cases possibles.
Correction for lettre in 'ABCDEFGH':\n for chiffre in '12345678':\n case = lettre + chiffre\n print(case)\n
Autre solution utilisant la conversion d'un entier en chaine de caract\u00e8res, gr\u00e2ce \u00e0 la fonction str
:
for lettre in 'ABCDEFGH':\n for chiffre in range(1, 9):\n case = lettre + str(chiffre)\n print(case)\n
Exercice 8
Travail sur ipythonblocks
:
Exercice \u00e0 faire sur Capytale : https://capytale2.ac-paris.fr/web/c/8869-1863952
Correction Ex. 1 grid = BlockGrid(10, 10, fill=(125,234,231))\n\nfor k in range(10):\n grid[k,2].set_colors(0,0,0)\ngrid.show()\n
Correction Ex. 2 grid = BlockGrid(10, 10, fill=(125, 234, 231))\n\nfor col in range(0, 10, 2):\n for lig in range(10):\n grid[lig, col].set_colors(0, 0, 0)\n\ngrid.show()\n
Correction Ex. 3 grid = BlockGrid(10, 10, fill=(125,234,231))\n\nfor col in range(0, 10, 2):\n for lig in range(0, 10, 2):\n grid[lig, col].set_colors(0, 0, 0)\n\nfor col in range(1, 10, 2):\n for lig in range(1, 10, 2):\n grid[lig, col].set_colors(0, 0, 0) \n\ngrid.show()\n
ou bien (plus difficile):
grid = BlockGrid(10, 10, fill=(125,234,231))\n\nfor x in range(10):\n for y in range(10):\n if (x + y) % 2 == 1: #on teste si la somme abscisse + ordonn\u00e9e est impaire\n grid[x, y].set_colors(0, 0, 0) \n\ngrid.show()\n
Correction Ex. 4 grid = BlockGrid(10, 10, fill=(125,234,231))\n\nfor y in range(10):\n for x in range(y, 10):\n grid[x, y].set_colors(0, 0, 0) \ngrid.show()\n
Exercice 9
Dans ma trousse je dispose de 5 feutres de couleur :
- jaune (J)
- vert (V)
- noir (N)
- bleu (B)
- orange (O)
Pour un exercice, je dois colorier 3 pastilles en choissant sans aucune contrainte des couleurs parmi les 5 disponibles. Je peux tout colorier en jaune (JJJ
) ou bien colorier la 1\u00e8re en orange, la 2\u00e8me en bleu, la 3\u00e8me en vert (OBV
)
Faire afficher la totalit\u00e9 des combinaisons possibles.
Correction couleurs = 'JVNBO'\nfor c1 in couleurs:\n for c2 in couleurs:\n for c3 in couleurs:\n print(c1 + c2 + c3)\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/","title":"Exercices sous Processing","text":""},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#1-presentation-de-processing","title":"1. Pr\u00e9sentation de Processing","text":" Processing est un outil de cr\u00e9ation multim\u00e9dia utilisant le code informatique. Simple de prise en main, il a \u00e9t\u00e9 cr\u00e9\u00e9 par des artistes pour des artistes. On peut utiliser le langage Python pour entrer les instructions.
Nous l'utiliserons pour ajouter du graphisme \u00e0 nos cr\u00e9ations. Dans tous les exercices de cette page, les dessins r\u00e9alis\u00e9s seront statiques. Nous verrons plus tard comment Processing permet tr\u00e8s facilement de faire des animations.
Documentation - Le site officiel (anglais)
- Un manuel d'utilisation (fran\u00e7ais)
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#2-les-bases-de-processing","title":"2. Les bases de Processing","text":""},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#21-repere","title":"2.1 Rep\u00e8re","text":"\u00c0 l'ex\u00e9cution de tout script Processing, une fen\u00eatre s'affiche avec une zone de dessin. Sa taille se d\u00e9finit \u00e0 l'aide de la fonction size
. Par exemple, pour cr\u00e9er une zone de dessin de 300 pixels sur 200 pixels, on utilisera:
size(300, 200)\n
Chaque pixel de cette zone est rep\u00e9r\u00e9e par des coordonn\u00e9es dans le rep\u00e8re suivant, dont l'origine se situe en haut \u00e0 gauche et l'axe des ordonn\u00e9es est orient\u00e9 vers le bas.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#22-traces","title":"2.2 Trac\u00e9s","text":"Trac\u00e9s de base
point
: permet de dessiner un point (pixel). En param\u00e8tre, les coordonn\u00e9es du point. line
: permet de tracer une ligne entre deux points. En param\u00e8tres, les coordonn\u00e9es des deux points. rect
: permet de tracer un rectangle. En param\u00e8tres, les coordonn\u00e9es du sommet haut-gauche, puis la largeur et la hauteur du rectangle. ellipse
: permet de tracer une ellipse. En param\u00e8tres, les coordonn\u00e9es du centre, puis la largeur et la hauteur (mettre la m\u00eame valeur pour un cercle).
Exemples Copier-coller le code suivant et faire varier les param\u00e8tres pour bien les comprendre.
size(200, 200)\npoint(10, 60)\nline(10, 10, 100, 150)\nrect(80, 10, 20, 50)\nellipse(150, 100, 80, 40)\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#23-couleurs","title":"2.3 Couleurs","text":"Pinceau
background
: permet de d\u00e9finir la couleur du fond de la zone de dessin. En param\u00e8tres, les trois composantes RGB de la couleur. stroke
: permet de d\u00e9finir la couleur du pinceau (noir par d\u00e9faut) pour le contour de la forme. En param\u00e8tres, les trois composantes RGB de la couleur. noStroke
: permet de dessiner une forme sans coutour (pas de param\u00e8tre). strokeWeight
: permet de d\u00e9finir la largeur du pinceau. En param\u00e8tre, le nombre de pixel. fill
: permet de d\u00e9finir la couleur de remplissage de la forme. En param\u00e8tres, les trois composantes RGB de la couleur.
Exemples Copier-coller le code suivant et faire varier les param\u00e8tres pour bien les comprendre.
size(200, 200)\nbackground(255, 255, 255)\nstroke(255, 0, 0)\npoint(10, 60)\nline(10, 10, 100, 150)\nstroke(0, 127, 255)\nstrokeWeight(5)\nrect(80, 10, 20, 50)\nnoStroke()\nfill(204, 153, 204)\nellipse(150, 100, 80, 40)\n
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#3-exercices-sur-la-simple-boucle","title":"3. Exercices sur la simple boucle","text":"Tous les exercices sont \u00e0 faire dans une fen\u00eatre de 300 pixels sur 300 pixels.
Exercice 1
\u00c9nonc\u00e9Correction en ProcessingCorrection en p5 L'objectif est d'obtenir dix lignes al\u00e9atoires, de couleur al\u00e9atoire et d'\u00e9paisseur 10.
Aide
- la fonction
random(a,b)
permet d'obtenir un entier pseudo al\u00e9atoire entre a
et b
.
size(300,300)\nbackground(0)\nfor k in range(10):\n Ax = random(0,300)\n Ay = random(0,300)\n Bx = random(0,300)\n By = random(0,300)\n strokeWeight(10)\n stroke(random(0,255), random(0,255), random(0,255))\n line(Ax,Ay,Bx,By)\n
from p5 import *\n\ndef setup():\n createCanvas(300, 300)\n noLoop()\n\ndef draw():\n background(0)\n for k in range(10):\n Ax = random(0,300)\n Ay = random(0,300)\n Bx = random(0,300)\n By = random(0,300)\n strokeWeight(10)\n stroke(random(0,255), random(0,255), random(0,255))\n line(Ax,Ay,Bx,By)\n\nrun()\n
Exercice 2 difficile
\u00c9nonc\u00e9Correction en ProcessingCorrection en p5 Reprendre l'exercice pr\u00e9c\u00e9dent en faisant en sorte que chaque ligne commence l\u00e0 o\u00f9 une autre s'arr\u00eate (hormis la premi\u00e8re)
size(300,300)\nbackground(0)\nAx = random(0,300)\nAy = random(0,300)\nfor k in range(10):\n Bx = random(0,300)\n By = random(0,300)\n strokeWeight(10)\n stroke(random(0,255), random(0,255), random(0,255))\n line(Ax,Ay,Bx,By)\n Ax = Bx\n Ay = By\n
from p5 import *\n\ndef setup():\n createCanvas(300, 300)\n noLoop()\n\ndef draw():\n background(0)\n Ax = random(0,300)\n Ay = random(0,300)\n for k in range(10):\n Bx = random(0,300)\n By = random(0,300)\n strokeWeight(10)\n stroke(random(0,255), random(0,255), random(0,255))\n line(Ax,Ay,Bx,By)\n Ax = Bx\n Ay = By\n\nrun()\n
Exercice 3
\u00c9nonc\u00e9Correction en ProcessingCorrection en p5 Tracer 50 disques de position, diam\u00e8tre, couleur et transparence al\u00e9atoires.
Aide
- la transparence s'obtient en rajoutant un 4\u00e8me param\u00e8tre (entre 0 et 255) \u00e0 la suite de RGB. On appelle ce param\u00e8tre le canal Alpha. Ex : (255,0,0,200) est un rouge tr\u00e8s transparent.
size(300,300)\nbackground(0)\nfor k in range(50):\n Ax = random(0,300)\n Ay = random(0,300)\n diametre = random(0,50)\n noStroke()\n r = random(0,255)\n g = random(0,255)\n b = random(0,255)\n a = random(0,255)\n fill(r, g, b, a)\n ellipse(Ax,Ay,diametre, diametre)\n
from p5 import *\n\ndef setup():\n createCanvas(300, 300)\n noLoop()\n\ndef draw():\n background(0)\n for k in range(50):\n Ax = random(0,300)\n Ay = random(0,300)\n diametre = random(0,50)\n noStroke()\n r = random(0,255)\n g = random(0,255)\n b = random(0,255)\n a = random(0,255)\n fill(r, g, b, a)\n ellipse(Ax,Ay,diametre, diametre)\n\nrun()\n
Exercice 4 \u00e0 faire sur Capytale : activit\u00e9 55f1-63735
Lire obligatoirement au pr\u00e9alable la page \u00abComment passer d'un code Processing \u00e0 un code p5\u00bb
\u00c9nonc\u00e9 Proposer un code r\u00e9alisant la figure suivante. Votre code devra obligatoirement comporter une boucle for
.
"},{"location":"T1_Demarrer_en_Python/1.2_Boucle_for/exos_processing/#4-exercices-sur-la-double-boucle","title":"4. Exercices sur la double boucle","text":"La structure de double boucle va permettre (par exemple) de parcourir l'int\u00e9gralit\u00e9 des pixels d'une image.
Exercices \u00e0 faire sur Capytale : activit\u00e9 38d9-68425
Exercice 5
Construire une image o\u00f9 tous les points ont une couleur al\u00e9atoire.
Exercice 6
Construire une image constitu\u00e9e de carr\u00e9s de 20 pixels de cot\u00e9, de couleur al\u00e9atoire. L'image est toujours un carr\u00e9 de c\u00f4t\u00e9 300 pixels.
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/","title":"1.3 Boucle While","text":""},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#1-premiers-exemples","title":"1. Premiers exemples","text":"\u00c0 la diff\u00e9rence essentielle des boucles for
, dont on peut savoir \u00e0 l'avance combien de fois elles vont \u00eatre ex\u00e9cut\u00e9es, les boucles while
sont des boucles dont on ne sort que lorsqu'une condition n'est plus satisfaite.
Avec donc le risque de rester infiniment bloqu\u00e9 \u00e0 l'int\u00e9rieur !
Exemple fondateur n\u00b01
Le programme suivant :
a = 0\nwhile a < 3:\n print(\"ok\")\n a = a + 1\nprint(\"fini\")\n
va donner ceci : ok\nok\nok\nfini\n
Analyse gr\u00e2ce \u00e0 PythonTutor
Question
le code ci-dessous va-t-il donner un r\u00e9sultat diff\u00e9rent ?
a = 0\nwhile a < 3:\n a = a + 1\n print(\"ok\")\nprint(\"fini\")\n
R\u00e9sultat du programme \u23ec ok\nok\nok\nfini\n
Conclusion : l'\u00e9valuation de la condition ne se fait pas \u00e0 chaque ligne mais bien au d\u00e9but de chaque tour de boucle. Si la variable qui d\u00e9clenchera la sortie de boucle atteint sa valeur de sortie au milieu des instructions, les lignes restantes sont quand m\u00eame ex\u00e9cut\u00e9es.
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#2-syntaxe-generale","title":"2. Syntaxe g\u00e9n\u00e9rale","text":"\u00c9criture d'une boucle while
while condition:\n instruction1\n instruction2\n ...\n instructionN\n
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#21-la-condition","title":"2.1 La condition","text":"La condition
est un bool\u00e9en, c'est-\u00e0-dire une expression que Python \u00e9valuera \u00e0 True
ou \u00e0 False
.
Prenons une variable a
\u00e9gale \u00e0 10.
>>> a = 10\n>>> a\n10\n
Voici diff\u00e9rents tests sur cette variable a
. Chacun de ces tests va donner un bool\u00e9en, qui sera \u00e9gal \u00e0 True
ou \u00e0 False
.
La syntaxe de ces tests est \u00e0 conna\u00eetre par c\u0153ur.
>>> a > 8\nTrue\n>>> a > 12\nFalse\n>>> a == 10\nTrue\n>>> a != 7\nTrue\n>>> a != 10\nFalse\n>>> a >= 10\nTrue\n
Un cours sur les bool\u00e9ens aura lieu ici.
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#22-les-instructions","title":"2.2 Les instructions","text":"Les instructions instruction1
jusqu'\u00e0 instructionN
sont ex\u00e9cut\u00e9es dans cet ordre \u00e0 chaque tour de boucle.
Attention : ces instructions doivent obligatoirement avoir un impact sur la condition
\u00e9valu\u00e9e apr\u00e8s le while
(dans le cours sur la dichotomie, nous \u00e9voquerons la notion de variant de boucle).
Voir le pi\u00e8ge n\u00b01 ...
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#3-les-pieges","title":"3. Les pi\u00e8ges ...","text":""},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#31-piege-n1-ne-jamais-sortir-de-la-boucle","title":"3.1 pi\u00e8ge n\u00b01 : ne JAMAIS SORTIR de la boucle","text":"Exemple fondateur n\u00b02
Le programme suivant :
a = 0\nwhile a < 3:\n print(\"ok\")\n a = a + 1\n a = a * 0\nprint(\"ce texte ne s'\u00e9crira jamais\")\n
va \u00e9crire une suite infinie de ok
et ne jamais s'arr\u00eater"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#32-piege-n2-ne-jamais-entrer-dans-la-boucle","title":"3.2 pi\u00e8ge n\u00b02 : ne JAMAIS ENTRER dans la boucle","text":"Exemple fondateur n\u00b03
Le programme suivant :
a = 0\nwhile a > 10:\n print(\"ce texte non plus ne s'\u00e9crira jamais\")\n a = a + 1\n\nprint(\"fini\") \n
va \u00e9crire fini
et s'arr\u00eater.
Exercice 1
Trouver le plus petit nombre entier \\(n\\) tel que \\(2^n\\) soit sup\u00e9rieur \u00e0 1 milliard.
Correction n = 1\nwhile 2**n < 10**9:\n n = n + 1\nprint('trouv\u00e9 : ',n)\n
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#4-quelques-remarques","title":"4. Quelques remarques","text":""},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#41-lien-entre-while-et-for","title":"4.1 Lien entre while
et for
","text":"La boucle born\u00e9e for
que nous avons \u00e9tudi\u00e9e est tr\u00e8s pratique.
Mais nous pourrions nous en passer : toutes les boucles for
peuvent en fait \u00eatre r\u00e9-\u00e9crites en utilisant while
. (alors que la r\u00e9ciproque est fausse)
Exercice 2
On consid\u00e8re le code ci-dessous :
for k in range(5):\n print(\"scooby-doo\")\n
R\u00e9-\u00e9crire ce code en utilisant une boucle while
. Correction k = 0\nwhile k < 5:\n print('scooby-doo')\n k = k + 1\n
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/cours/#42-les-boucles-infinies-volontaires","title":"4.2 Les boucles infinies volontaires","text":"La boucle infinie a \u00e9t\u00e9 pr\u00e9sent\u00e9e comme un danger qu'il faut \u00e9viter.
Pourtant, dans quelques situations, il est d'usage d'enfermer volontairement l'utilisateur dans une boucle infinie.
Observez et ex\u00e9cutez le code suivant :
while True:\n reponse = input(\"tapez sur la lettre S du clavier pour me sortir de cet enfer : \")\n if reponse == 's':\n break\n\nprint(\"merci, j'\u00e9tais bloqu\u00e9 dans une boucle infinie\")\n
- le d\u00e9but du code :
while True
est typique des boucles infinies volontaires. On aurait tout aussi bien pu \u00e9crire while 3 > 2
(on rencontre m\u00eame parfois des while 1
) - vous avez d\u00e9couvert l'expression
break
qui comme son nom l'indique permet de casser la boucle (cela marche pour while
comme pour for
) et donc d'en sortir. Son emploi est controvers\u00e9 parmi les puristes de la programmation. Nous dirons juste que c'est une instruction bien pratique.
Exercice 3
Reprendre l'exemple pr\u00e9c\u00e9dent en faisant deviner un mot de passe (pr\u00e9alablement stock\u00e9 dans une variable).
Correction mdp = 'supermotdepasse'\n\nwhile True:\n rep = input('mot de passe ?')\n if rep == mdp:\n break\nprint('acc\u00e8s autoris\u00e9')\n
mieux :
import hashlib\nhsh = '696cebb8f23e45f3c3d8e6582bc1a8182abc0119ed3dd89b7de069a9ea8957ab'\n\nwhile True:\n rep = input(\"mot de passe \")\n if hashlib.sha256(rep.encode(\"utf-8\")).hexdigest() == hsh:\n break\nprint(\"acc\u00e8s autoris\u00e9\")\n
"},{"location":"T1_Demarrer_en_Python/1.3_Boucle_while/exercices/","title":"Exercices sur la boucle while
","text":"Exercice 1
Pour chaque code, \u00e9crire ce qui va s'afficher en console.
Code A
c = 0\nwhile c <= 3:\n print(\"ok\")\n c += 1\n
Correction ok\nok\nok\nok\n
Code B
k = 0\nwhile k > 3:\n print(\"ok\")\n k += 1\nprint(\"fini\")\n
Correction fini\n
Code C
n = 0\nwhile n < 4:\n print(\"ok\")\n n += 2\n
Correction ok\nok\n
Exercice 2
Que va afficher le code ci-dessous ?
c = 0\nmot = 'a'\nwhile mot != 'aaaa':\n mot += 'a'\n c += 1\nprint(c)\n
Correction Il va afficher 4.
Exercice 3
Un capital de 10 000 \u20ac est plac\u00e9 au taux annuel de 4 %.
\u00c9crire le code permettant d'afficher au bout de combien d'ann\u00e9es le capital va d\u00e9passer 14 000 \u20ac.
On rappelle qu'une augmentation de 4 % correspond \u00e0 une multiplication par 1,04.
Correction capital = 10000\nannee = 0\nwhile capital < 14000:\n annee += 1\n capital = capital * 1.04 #(1)\nprint(annee)\n
- ou
capital *= 1.04
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/","title":"1.4 Instruction conditionnelle if","text":"L'instruction conditionnelle if
permet de soumettre l'ex\u00e9cution d'instructions \u00e0 une condition donn\u00e9e. Cette condition sera une expression bool\u00e9enne, comme pour la boucle while
.
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/#1-exemples-fondateurs","title":"1. Exemples fondateurs","text":"Dans les exemples ci-dessous, changez la valeur affect\u00e9e \u00e0 la variable age
afin d'observer les modifications de comportement du programme.
Exemple fondateur n\u00b01
L'exemple minimal ci-dessous ne contient que le mot-cl\u00e9 if
.
age = 20\nif age >= 18:\n print(\"Tu as le droit de vote\")\n
Exemple fondateur n\u00b02
La structure qu'on rencontrera le plus souvent est la structure if ... else ...
age = 20\nif age >= 18:\n print(\"Tu as le droit de vote\")\nelse:\n print(\"D\u00e9sol\u00e9, il faudra attendre\", 18 - age, \"ans avant de pouvoir voter\")\n
Syntaxe g\u00e9n\u00e9rale
if expression bool\u00e9enne:\n *instructions \u00e0 effectuer si l'expression est vraie*\nelse:\n *instructions \u00e0 effectuer si l'expression est fausse*\n
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/#2-levaluation-de-la-condition","title":"2. L'\u00e9valuation de la condition","text":"Comme pour la boucle while
, on dit que l'expression qui suit le if
est \u00e9valu\u00e9e par Python lors de l'ex\u00e9cution du programme.
Cette \u00e9valuation renvoie un bool\u00e9en, True
ou False
.
Les symboles de comparaison (ou d'appartenance) permettant d'\u00e9crire une condition sont :
Op\u00e9rateurs de comparaison
Op\u00e9rateur Signification ==
est \u00e9gal \u00e0 !=
est diff\u00e9rent de <
inf\u00e9rieur \u00e0 >
sup\u00e9rieur \u00e0 <=
inf\u00e9rieur ou \u00e9gal \u00e0 >=
sup\u00e9rieur ou \u00e9gal \u00e0 in
appartient \u00e0 not in
n'appartient pas \u00e0 Exemples
>>> a = 2\n\n>>> a == 3\nFalse\n\n>>> a == 2\nTrue\n\n>>> a != 1\nTrue\n\n>>> a > 2\nFalse\n\n>>> a >= 2\nTrue\n\n>>> a <= 2\nTrue\n\n>>> a <= 5\nTrue\n\n>>> 'e' in 'abracadabra'\nFalse\n\n>>> 'b' in 'abracadabra'\nTrue\n\n>>> 'A' not in 'abracadabra'\nTrue\n\n>>> not True\nFalse\n
Comme nous le verrons dans le cours sur les bool\u00e9ens, ces conditions peuvent \u00eatre combin\u00e9es avec (par exemple) les mots-cl\u00e9s and
ou or
:
>>> b = 20\n>>> b > 15 and b < 30\nTrue\n>>> b > 2000 or b < 30\nTrue\n
Exercice 1
Compter le nombre de voyelles de la phrase 'cet exercice est prodigieusement ennuyeux'
phrase = 'cet exercice est prodigieusement ennuyeux'\nvoyelles = 'aeiouy'\n
Correction phrase = 'cet exercice est prodigieusement ennuyeux'\nvoyelles = 'aeiouy'\n\ncompteur = 0\n\nfor lettre in phrase:\n if lettre in voyelles:\n compteur += 1\n\nprint(compteur)\n
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/#3-un-test-tres-frequent-le-test-de-divisibilite","title":"3. Un test tr\u00e8s fr\u00e9quent : le test de divisibilit\u00e9","text":"Exemple fondateur n\u00b03
Pour tester si un nombre n
est divisible par un nombre d
, on teste si le reste de la division euclidienne de n
par d
est \u00e9gal \u00e0 0 :
n = 17\nif n % 2 == 0:\n print(n, \"est un nombre pair\")\nelse:\n print(n, \"est un nombre impair\")\n
Exercice 2
Afficher la liste de tous les nombres entre 1 et 100 qui sont divisibles \u00e0 la fois par 2 et par 7.
Correction for n in range(1,101):\n if n % 2 == 0 and n % 7 == 0:\n print(n)\n
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/#4-les-cas-multiples-utilisation-de-elif","title":"4. Les cas multiples : utilisation de elif
","text":"Dans les situations o\u00f9 l'on veut effectuer des instructions diff\u00e9rentes selon les diff\u00e9rentes valeurs prises par une variable, on peut imbriquer les instructions if
... else
.
Observer par exemple le code ci-dessous :
moyenne = 13\n\nif moyenne < 8:\n print(\"rat\u00e9\")\nelse:\n if moyenne < 10:\n print(\"rep\u00eachage\")\n else:\n if moyenne < 12:\n print(\"admis\")\n else:\n if moyenne < 14:\n print(\"mention AB\")\n else:\n if moyenne < 16:\n print(\"mention B\")\n else:\n print(\"mention TB\")\n
Mais cela est vite long et peu lisible, et les diff\u00e9rents niveaux d'indentation peuvent devenir pi\u00e9geux.
Il existe alors une instruction qui contracte else
et if
: elif
(sinon si).
Ce code devient alors
moyenne = 7\n\nif moyenne < 8:\n print(\"rat\u00e9\")\nelif moyenne < 10:\n print(\"rep\u00eachage\")\nelif moyenne < 12:\n print(\"admis\")\nelif moyenne < 14:\n print(\"mention AB\")\nelif moyenne < 16:\n print(\"mention B\")\nelse:\n print(\"mention TB\")\n
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/cours/#4-recreation-a-vous-dobeir","title":"4. R\u00e9cr\u00e9ation : \u00e0 vous d'ob\u00e9ir !","text":"Le site https://compute-it.toxicode.fr/ vous demande d'ex\u00e9cuter mentalement les instructions affich\u00e9es, \u00e0 l'aide des touches directionnelles de votre clavier. Attention, ce site est tr\u00e8s addictif !
"},{"location":"T1_Demarrer_en_Python/1.4_Instruction_conditionnelle_if/exercices/","title":"Exercices","text":"Exercice 1
\u00c9crire un programme qui demande deux nombres et qui affiche le plus grand des deux.
Aide : pour stocker dans une variable n
un nombre tap\u00e9 au clavier par l'utilisateur, on utilise le code suivant :
n = int(input('Entrez un nombre'))\n
Exemples d'utilisation du programme :
Premier nombre ? 12\nDeuxi\u00e8me nombre ? 45\nle nombre le plus grand est 45\n
Premier nombre ? 17\nDeuxi\u00e8me nombre ? 17\nles deux nombres sont \u00e9gaux\n
Correction n1 = int(input('Premier nombre ?'))\nn2 = int(input('Deuxi\u00e8me nombre ?'))\n\nif n1 > n2:\n print('le nombre le plus grand est', n1)\nelif n2 > n1:\n print('le nombre le plus grand est', n2)\nelse:\n print('les deux nombres sont \u00e9gaux')\n
Exercice 2
Le jeu du FizzBuzz : il s'agit de compter \u00e0 partir de 1 en rempla\u00e7ant certains nombres par Fizz, Buzz ou Fizzbuzz :
- si le nombre est divisible par 3, on ne le dit pas et on le remplace par Fizz.
- si le nombre est divisible par 5, on ne le dit pas et on le remplace par Buzz.
- si le nombre est divisible par 3 et par 5, on ne le dit pas et on le remplace par FizzBuzz.
\u00c9crire un code qui joue au FizzBuzz jusqu'\u00e0 20.
Exemple d'utilisation du programme :
1\n2\nfizz\n4\nbuzz\nfizz\n7\n8\n...\n
Correction for k in range(1, 21):\n if k % 3 == 0 and k % 5 == 0:\n print('fizzbuzz')\n elif k % 3 == 0:\n print('fizz')\n elif k % 5 == 0:\n print('buzz')\n else:\n print(k)\n
Exercice 3
Une ann\u00e9e est d\u00e9clar\u00e9e bissextile (et compte donc 366 jours au lieu de 365) si elle est :
- soit divisible par 400.
- soit divisible par 4 mais pas divisible par 100.
\u00c9crire un code qui d\u00e9termine si une ann\u00e9e est bissextile ou non.
Explication : la Terre faisant le tour du Soleil en un peu plus que 365 jours, on s'est dit qu'on allait rajouter un jour tous les 4 ans, mais c'\u00e9tait trop, alors on a enlev\u00e9 un jour tous les 100 ans, mais c'\u00e9tait plus assez, alors on a rajout\u00e9 un jour tous les 400 ans, ce qui donne une approximation convenable.
Correction annee = int(input(\"ann\u00e9e ? \"))\n\nif annee % 400 == 0:\n print(annee, 'est bissextile')\nelif annee % 4 == 0 and annee % 100 != 0:\n print(annee, 'est bissextile')\nelse:\n print(annee, \"n'est pas bissextile\")\n
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/","title":"1.5 Fonctions","text":"La notion de fonction est essentielle en programmation. Elle permet de construire des codes modulaires, plus faciles \u00e0 lire et \u00e0 modifier. En Python, une fonction se cr\u00e9e avec le mot-cl\u00e9 def
.
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#1-fonctions-sans-parametre-sans-valeur-renvoyee","title":"1. Fonctions sans param\u00e8tre, sans valeur renvoy\u00e9e","text":"Exemple fondateur n\u00b01
def accueil():\n print(\"bonjour\")\n print(\"comment allez-vous ?\")\n
Lorsque l'interpr\u00e9teur Python parcourt cette fonction, rien ne s'affiche : la fonction est maintenant pr\u00eate \u00e0 \u00eatre appel\u00e9e, mais n'est pas ex\u00e9cut\u00e9e tant que l'utilisateur ne le demande pas explicitement.
Ce sera le cas pour toutes les fonctions : elles doivent \u00eatre appel\u00e9es pour s'ex\u00e9cuter.
>>> accueil()\nbonjour\ncomment allez-vous ?\n
Dans ce cas d'utilisation, la fonction accueil
n'est qu'un raccourci, une factorisation d'un ensemble d'instructions.
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#2-fonction-avec-parametres-sans-valeur-renvoyee","title":"2. Fonction avec param\u00e8tre(s), sans valeur renvoy\u00e9e","text":""},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#21-parametre-simple","title":"2.1 Param\u00e8tre simple","text":"Exemple fondateur n\u00b02
def chat_penible(n):\n for k in range(n):\n print(\"meoww\")\n
>>> chat_penible(3)\nmeoww\nmeoww\nmeoww\n
Vocabulaire
- La valeur
n
est appel\u00e9e param\u00e8tre de la fonction chat_penible
. - On dit qu'on passe le param\u00e8tre
n
\u00e0 la fonction chat_penible
. - Dans l'exemple ci-dessus, on dit qu'on a appel\u00e9 la fonction
chat_penible
avec l'argument 3.
Remarques :
- l\u00e0 encore, notre fonction ne renvoie rien : on peut encore la consid\u00e9rer comme un ensemble d'instructions factoris\u00e9 dans un m\u00eame bloc. \u00c0 la diff\u00e9rence de la fonction sans param\u00e8tre, ces instructions ne sont pas toujours les m\u00eames, gr\u00e2ce \u00e0 l'utilisation du param\u00e8tre demand\u00e9 \u00e0 l'utilisateur.
- la fonction bien connue
print()
est une fonction \u00e0 param\u00e8tre, qui affiche dans la console le contenu du param\u00e8tre.
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#22-parametres-multiples","title":"2.2 Param\u00e8tres multiples","text":"Une fonction peut avoir de multiples param\u00e8tres :
Exemple fondateur n\u00b02
def repete(mot, k):\n for i in range(k):\n print(mot)\n
>>> repete(\"NSI\", 3)\nNSI\nNSI\nNSI\n
L'ordre des param\u00e8tres pass\u00e9s est alors important ! Le code ci-dessous est incorrect.
>>> repete(3, \"test\")\n---------------------------------------------------------------------------\n\nTypeError Traceback (most recent call last)\n\n<ipython-input-9-a84914f8a6c6> in <module>()\n----> 1 repete(3, \"test\")\n\n\n<ipython-input-8-7dc8032e3f17> in repete(mot, k)\n 1 def repete(mot, k) :\n----> 2 for i in range(k):\n 3 print(mot)\n 4 \n 5 repete(\"NSI\", 5)\n\n\nTypeError: 'str' object cannot be interpreted as an integer\n
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#3-fonction-avec-parametres-et-avec-valeur-renvoyee","title":"3. Fonction avec param\u00e8tre(s) et avec valeur renvoy\u00e9e","text":"On retrouve ici la notion classique de fonction rencontr\u00e9e en math\u00e9matiques : un proc\u00e9d\u00e9 qui prend un nombre et en renvoie un autre. En informatique, l'objet renvoy\u00e9 ne sera pas forc\u00e9ment un nombre (cela pourra \u00eatre aussi une liste, un tableau, une image...). Le renvoi d'une valeur se fait gr\u00e2ce au mot-cl\u00e9 return
.
Exemple fondateur n\u00b03
La fonction math\u00e9matique \\(f : x \\longmapsto 2x+3\\) se codera par :
def f(x):\n return 2*x + 3\n
>>> f(10)\n23\n
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#4-autour-du-return","title":"4. Autour du return
","text":""},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#41-la-force-du-return","title":"4.1 La force du return
","text":"Diff\u00e9rence fondamentale entre return
et print
Le mot-cl\u00e9 return
de l'exemple pr\u00e9c\u00e9dent fait que l'expression f(10)
est \u00e9gale \u00e0 23. On peut d'ailleurs \u00e9crire en console :
>>> f(10) + 5\n28\n
Imaginons (avant de l'oublier tr\u00e8s vite) le code affreux ci-dessous : def g(x):\n print(2*x + 3)\n
On pourrait avoir l'illusion que la fonction g
fait correctement son travail : >>> g(10)\n23\n
Mais g
se contente d'afficher sa valeur calcul\u00e9e, et non pas de la renvoyer. En effet : >>> g(10) + 5\n23\nTraceback (most recent call last):\nFile \"<pyshell>\", line 1, in <module>\nTypeError: unsupported operand type(s) for +: 'NoneType' and 'int'\n
En r\u00e9sum\u00e9 : "},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#42-le-return-est-un-siege-ejectable","title":"4.2 Le return
est un si\u00e8ge \u00e9jectable","text":"Le mot-cl\u00e9 return
provoque une \u00e9jection du code : tout ce qui est situ\u00e9 apr\u00e8s le \u00a0return
ne sera pas ex\u00e9cut\u00e9. Observez la diff\u00e9rence entre les fonctions g
et h
.
def g(x):\n print(\"ce texte sera bien affich\u00e9\")\n return 2*x+3\n
>>> g(4)\nce texte sera bien affich\u00e9\n11\n
def h(x):\n return 2*x+3\n print(\"ceci ne sera jamais affich\u00e9\")\n
>>> h(4)\n11\n
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#43-les-fonctions-sans-return-sont-elles-des-fonctions","title":"4.3 Les fonctions sans return
sont-elles des fonctions ?","text":" -
Pour les puristes, une fonction sans valeur renvoy\u00e9e sera plut\u00f4t appel\u00e9e proc\u00e9dure. Le mot fonction est alors r\u00e9serv\u00e9 aux fonctions qui ont effectivement un return
.
-
On peut doter artificiellement \u00e0 toutes les fonctions d'un return
, en renvoyant la valeur None
:
def chat_penible(n):\n for k in range(n):\n print(\"meoww\")\n return None\n
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#5-variables-locales-variables-globales","title":"5. Variables locales, variables globales","text":""},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#51-notion-despace-de-noms","title":"5.1 Notion d'espace de noms","text":"D\u00e9finitions
- Les variables d\u00e9finies dans le corps d'une fonction sont appel\u00e9es variables locales.
- Les variables d\u00e9finies dans le corps du programme (sous-entendu : pas \u00e0 l'int\u00e9rieur d'une fonction) sont appel\u00e9es variables globales.
On dit que les fonctions cr\u00e9ent leur \u00abespace de noms\u00bb (espace est \u00e0 prendre au sens d'univers), un espace qui leur est propre.
Quelles sont les r\u00e8gles r\u00e9gissant ces espaces de noms ? Les fronti\u00e8res entre ces espaces sont elles poreuses ?
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#52-regles-dacces-en-lecture-et-en-modification-dune-variable-suivant-son-espace-dorigine","title":"5.2 R\u00e8gles d'acc\u00e8s en lecture et en modification d'une variable suivant son espace d'origine","text":"R\u00e8gles d'acc\u00e8s aux variables locales et globales
- r\u00e8gle 1 : une variable locale (d\u00e9finie au c\u0153ur d'une fonction) est inaccessible hors de cette fonction.
- r\u00e8gle 2 : une variable globale (d\u00e9finie \u00e0 l'ext\u00e9rieur d'une fonction) est accessible en lecture \u00e0 l'int\u00e9rieur d'une fonction.
- r\u00e8gle 3 : une variable globale (d\u00e9finie \u00e0 l'ext\u00e9rieur d'une fonction) ne peut pas \u00eatre modifi\u00e9e \u00e0 l'int\u00e9rieur d'une fonction.
Exercice
On consid\u00e8re les 3 codes ci-dessous. Pour chacun, dire sans l'ex\u00e9cuter s'il est valide ou non. S'il ne l'est pas, identifier la r\u00e8gle (parmi celles \u00e9nonc\u00e9es ci-dessus) qui est bafou\u00e9e.
code A
points = 0\ndef verdict(reponse):\n if reponse > 10:\n points += 3\n\nverdict(12)\n
Correction Ce code n'est pas valide, car il contrevient \u00e0 la r\u00e8gle 3.
ligne 4
: la modification de la variable globale points
est interdite.
code B
def bouge(x, decalage):\n x += decalage\n\nbouge(100, 5)\nprint(x)\n
Correction Ce code n'est pas valide, car il contrevient \u00e0 la r\u00e8gle 1.
ligne 5
: l'acc\u00e8s \u00e0 la variable locale x
est interdit.
code C
def test_bac(moyenne):\n if moyenne >= 10:\n print(\"admis !\")\n\ndef coup_de_pouce(note):\n return note + bonus\n\nbonus = 0.6\nma_moyenne = 9.5\nma_moyenne = coup_de_pouce(ma_moyenne)\ntest_bac(ma_moyenne)\n
Correction Ce code est valide.
ligne 6
: l'acc\u00e8s \u00e0 la variable globale bonus
est autoris\u00e9, selon la r\u00e8gle 2.
\u00c0 propos de la r\u00e8gle n\u00b03
(toute la v\u00e9rit\u00e9, rien que la v\u00e9rit\u00e9)
Pour certains types de variables (listes, dictionnaires...), la modification d'une variable globale \u00e0 l'int\u00e9rieur du corps d'une fonction est en fait possible (contrairement \u00e0 ce qu'\u00e9nonce la r\u00e8gle 3). Mais cela reste tr\u00e8s fortement d\u00e9conseill\u00e9.
Pour les autres types de variables, on peut m\u00eame forcer pour avoir cette possibilit\u00e9 en utilisant le mot global
\u00e0 l'int\u00e9rieur de la fonction.
Mais il faut essayer d'\u00e9viter ceci. Une fonction ne doit (mais ceci est plus un conseil appuy\u00e9 qu'une obligation l\u00e9gale...) modifier que les variables qu'elle cr\u00e9e (ses variables locales) ou bien les variables qu'on lui a donn\u00e9es en param\u00e8tres.
Une fonction qui ne respecte pas cette r\u00e8gle pr\u00e9sente des effets de bord : on peut peut-\u00eatre arriver \u00e0 les g\u00e9rer sur un \u00abpetit\u00bb code, mais cela devient illusoire sur un code utilisant de multiples fonctions.
.
En r\u00e9sum\u00e9
Ne pas faire cela :
# PAS BIEN\nscore = 0\ndef ramasse_objet(objet):\n global score\n if objet == \"champignon\":\n score += 20\n if objet == \"banane\":\n score -= 300\n
>>> ramasse_objet(\"champignon\")\n>>> score\n20\n
Faire plut\u00f4t ceci :
# BIEN\nscore = 0\ndef ramasse_objet(objet, score): # ma fonction veut modifier score ? \n if objet == \"champignon\": # -> ok, je mets score dans ses param\u00e8tres\n score += 20\n if objet == \"banane\":\n score -= 300\n return score # je renvoie le nouveau score\n
>>> score = ramasse_objet(\"champignon\", score)\n>>> score\n20\n
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#6-documenter-une-fonction","title":"6. Documenter une fonction","text":""},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#61-help","title":"6.1 Help !","text":"Si une fonction peut \u00eatre assimil\u00e9e \u00e0 un outil, il est normal de se demander si cet outil poss\u00e8de un mode d'emploi.
Observons les fonctions pr\u00e9-d\u00e9finies par Python, et notamment une des premi\u00e8res que nous avons rencontr\u00e9es : la fonction print()
. Son mode d'emploi est accessible gr\u00e2ce \u00e0 la commande help(print)
.
>>> help(print)\nHelp on built-in function print in module builtins:\n\nprint(...)\n print(value, ..., sep=' ', end='\\n', file=sys.stdout, flush=False)\n\n Prints the values to a stream, or to sys.stdout by default.\n Optional keyword arguments:\n file: a file-like object (stream); defaults to the current sys.stdout.\n sep: string inserted between values, default a space.\n end: string appended after the last value, default a newline.\n flush: whether to forcibly flush the stream\n
Pensez \u00e0 utiliser cette fonction help()
(en d'autres termes, RTFM)
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#62-creer-le-mode-demploi-de-ses-propres-fonctions-les-docstrings","title":"6.2 Cr\u00e9er le mode d'emploi de ses propres fonctions : les docstrings","text":"Il est possible, voire souhaitable (d\u00e8s qu'on cr\u00e9\u00e9 un code comportant plusieurs fonctions, et/ou qui sera amen\u00e9 \u00e0 \u00eatre lu par d'autres personnes), de cr\u00e9er un mode d'emploi pour ses fonctions. On appelle cela \u00e9crire la docstring de la fonction, et c'est tr\u00e8s simple : il suffit de l'encadrer par des triples double-quotes \"\"\"
.
Exemple
def chat_penible(n):\n \"\"\"\n Affiche n fois la chaine de caract\u00e8res \"meoww\"\n \"\"\"\n for k in range(n):\n print(\"meoww\")\n
On peut donc maintenant demander de l'aide pour cette fonction :
>>> help(chat_penible)\nHelp on function chat_penible in module __main__:\n\nchat_penible(n)\n Affiche n fois la chaine de caract\u00e8res \"meoww\"\n
Plus de renseignements sur les docstrings ici
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/cours/#7-jeux-de-tests-pour-une-fonction","title":"7. Jeux de tests pour une fonction","text":"Les exercices de cette feuille sont (presque) tous livr\u00e9s avec un jeu de tests. Il s'agit d'une fonction, souvent appel\u00e9e test_nom_de_la fonction()
, qui va regrouper les diff\u00e9rents tests qu'on pourrait faire en console pour v\u00e9rifier que la fonction a le comportement d\u00e9sir\u00e9.
Ces tests reposent sur le mot-cl\u00e9 assert
, qui va lever une erreur lorsqu'il est suivi d'une expression \u00e9valu\u00e9e \u00e0 False
:
>>> assert 3 > 2\n>>> assert 3 > 5\nTraceback (most recent call last):\n File \"<pyshell>\", line 1, in <module>\nAssertionError\n>>> assert True\n>>> assert False\nTraceback (most recent call last):\n File \"<pyshell>\", line 1, in <module>\nAssertionError\n
Exemple d'un jeu de tests
def maxi(n1, n2):\n if n1 < n2 :\n return n2\n else :\n return n1\n\ndef test_maxi():\n assert maxi(3,4) == 4\n assert maxi(5,2) == 5\n assert maxi(7,7) == 7\n print(\"tests ok\")\n
Il faut v\u00e9rifier que les tests couvrent toutes les situations possibles, mais ce n'est pas toujours facile !
Exercice
On consid\u00e8re (\u00e0 nouveau !) le jeu du FizzBuzz.
Rappel des r\u00e8gles
- si le nombre est divisible par 3, on ne le dit pas et on le remplace par Fizz.
- si le nombre est divisible par 5, on ne le dit pas et on le remplace par Buzz.
- si le nombre est divisible par 3 et par 5, on ne le dit pas et on le remplace par FizzBuzz.
On souhaite \u00e9crire la fonction fizzbuzz
qui renverra soit le nombre n
(pass\u00e9 en param\u00e8tre), soit le mot par lequel il faut le remplacer.
Q1. \u00c9crire la fonction test_fizzbuzz
qui testera la fonction fizzbuzz
.
Correction def test_fizzbuzz():\n assert fizzbuzz(4) == 4\n assert fizzbuzz(6) == 'fizz'\n assert fizzbuzz(10) == 'buzz'\n assert fizzbuzz(15) == 'fizzbuzz'\n print('tests ok !') \n
Q2. \u00c9crire la fonction fizzbuzz
. (Vous pouvez vous inspirer fortement du code de l'exercice 2 du chapitre pr\u00e9c\u00e9dent )
Correction ```python linenums='1'
def fizzbuzz(n): if n % 3 == 0 and n % 5 == 0: return 'fizzbuzz' elif n % 3 == 0: return 'fizz' elif n % 5 == 0: return 'buzz' else: return n
"},{"location":"T1_Demarrer_en_Python/1.5_Fonctions/exercices/","title":"Exercices","text":"Exercice 1
\u00c9nonc\u00e9Tester sa fonction \u00c9crire une fonction maxi
qui prend comme param\u00e8tres deux nombres n1
et n2
et qui renvoie le plus grand \u00e9l\u00e9ment entre n1
et n2
.
Exemple d'utilisation
>>> maxi(3,1)\n3\n
Vous pouvez utiliser la fonction de tests ci-dessous :
def test_maxi():\n assert maxi(3,4) == 4\n assert maxi(5,2) == 5\n assert maxi(7,7) == 7\n print(\"tests ok\")\n
Correction def maxi(n1, n2):\n if n1 < n2 :\n return n2\n else :\n return n1\n
Exercice 2
\u00c9crire une fonction moyenne
qui prend en param\u00e8tres trois nombres a
, b
et c
et qui renvoie la moyenne de ces trois nombres.
Exemple d'utilisation
>>> moyenne(6, 15, 9)\n10\n
Correction def moyenne(a, b, c):\n return (a + b + c) / 3 \n
Exercice 3
\u00c9crire une fonction somme
qui prend en param\u00e8tre un entier positif n
et qui renvoie la somme de tous les entiers de 1 \u00e0 n
.
\\(S = 1+2+3+4+5+ \\dots +(n-1) + n\\)
Exemple d'utilisation
>>> somme(10)\n55\n
Correction def somme(n):\n s = 0\n for k in range(1, n+1):\n s += k\n return s\n
Exercice 4
\u00c9nonc\u00e9Tester sa fonction \u00c9crire une fonction nb_voyelles
qui prend en param\u00e8tre la chaine de caract\u00e8res mot
renvoie le nombre de voyelles de mot
.
Exemple d'utilisation
>>> nb_voyelles(\"bonjour\")\n3\n
Vous pouvez utiliser la fonction de tests ci-dessous :
def test_nb_voyelles():\n assert nb_voyelles(\"bonjour\") == 3\n assert nb_voyelles(\"fdjgdhk\") == 0\n assert nb_voyelles(\"au\") == 2\n print(\"tests ok\")\n
Exercice 5
\u00c9nonc\u00e9Tester sa fonction D\u00e9finissez une fonction decale
qui d\u00e9cale de 3 rangs dans l'alphabet la lettre majuscule lettre
pass\u00e9e en param\u00e8tre (apr\u00e8s Z, on recommencera \u00e0 A..)
Aide
>>> ord('A')\n65\n>>> chr(65)\n'A'\n
Exemple d'utilisation
>>> decale('F')\n'I'\n
Vous pouvez utiliser la fonction de tests ci-dessous :
def test_decale():\n assert decale('A') == 'D'\n assert decale('Z') == 'C'\n print('tests ok !')\n
Exercice 6
\u00c9nonc\u00e9Tester sa fonction Rajoutez un param\u00e8tre n
\u00e0 la fonction pr\u00e9c\u00e9dente pour pouvoir d\u00e9caler la lettre de n
rangs.
Exemple d'utilisation
>>> decale('B', 5)\n'G'\n
Vous pouvez utiliser la fonction de tests ci-dessous :
def test_decale():\n assert decale('A', 3) == 'D'\n assert decale('A', 5) == 'F'\n assert decale('Z', 1) == 'A'\n print('tests ok !')\n
Exercice 7
Utilisez la fonction pr\u00e9c\u00e9dente pour cr\u00e9er la fonction decale_phrase
qui prend en param\u00e8tres une phrase p
et un nombre n
et qui d\u00e9cale toutes les lettres de p
de n
rangs. On laissera les espaces intacts.
Exemple d'utilisation
>>> decale_phrase(\"PAS MAL DU TOUT\", 4)\n'TEW QEP HY XSYX'\n
Exercice 8
D\u00e9codez la phrase RT BTHHPVT CT RDCIXTCI GXTC S XCITGTHHPCI
.
Exercice 9
La conjecture de Syracuse (ou de Collatz) postule ceci :
Prenons un nombre \\(n\\) : si \\(n\\) est pair, on le divise par 2, sinon on le multiplie par 3 puis on ajoute 1. On recommence cette op\u00e9ration tant que possible. Au bout d'un certain temps, on finira toujours par tomber sur le nombre 1.
Q1. \u00c9crire une fonction suivant
qui prend en param\u00e8tre un nombre n
renvoie le successeur den
, suivant les r\u00e8gles \u00e9nonc\u00e9es ci-dessus.
Q2. \u00c9crire une fonction syracuse
qui affiche tous les termes de la suite de Syracuse depuis un nombre n
pass\u00e9 en param\u00e8tre jusqu'\u00e0 (on l'esp\u00e8re !) 1.
Exercice 10
Q1. \u00c9crire une fonction temps_de_vol
qui prend un nombre n
en param\u00e8tre et qui renvoie le nombre d'\u00e9tapes pour arriver \u00e0 1, en partant de n
.
Q2. \u00c9crire une fonction temps_max(nmax)
qui affiche le plus grand temps de vol pour un nombre entre 1 et nmax
.
Q3. Modifier cette fonction pour afficher aussi le nombre de d\u00e9part donnant ce plus grand temps de vol.
"},{"location":"T2_Representation_des_donnees/sommaire/","title":"Th\u00e8me 2 : Repr\u00e9sentation des donn\u00e9es","text":" - Listes
- Tuples
- Dictionnaires
- Bases
- Bool\u00e9ens
- Codage des caract\u00e8res
- Codage des entiers
- Codage des non-entiers
- Cha\u00eenes de caract\u00e8res
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/","title":"2.1 Listes","text":"Les listes font partie de ce qu'on appelle les donn\u00e9es composites (nous verrons plus tard les tuples et les dictionnaires). Elles permettent de regrouper de mani\u00e8re structur\u00e9e un ensemble de valeurs (et non plus une valeur unique). On les appelle listes en Python, ou bien tableaux de mani\u00e8re plus g\u00e9n\u00e9rale.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#1-declaration-dune-liste","title":"1. D\u00e9claration d'une liste","text":"Exemple fondateur n\u00b01
Une variable de type liste sera d\u00e9limit\u00e9e par des crochets, et ses \u00e9l\u00e9ments s\u00e9par\u00e9s par des virgules :
>>> maliste = [\"riri\", \"fifi\", \"loulou\"]\n
On peut observer le type de la variable ainsi cr\u00e9\u00e9e :
>>> type(maliste)\n<class 'list'>\n
Remarques :
-
M\u00eame si cela n'a ici un grand int\u00e9r\u00eat, les \u00e9l\u00e9ments d'une liste peuvent donc \u00eatre de types diff\u00e9rents : ici, tous les \u00e9l\u00e9ments de ma liste sont des cha\u00eenes de caract\u00e8res (str
), mais la liste [\"riri\", 5, \"fifi\", \"loulou\"]
est aussi une liste valide.
-
Une liste vide se d\u00e9clarera avec []
.
>>> copies_corrigees = []\n
Nous verrons plus tard qu'il est fr\u00e9quent dans les exercices de partir d'une liste vide et d'ajouter progressivement des \u00e9l\u00e9ments.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#2-acces-aux-elements-dune-liste","title":"2. Acc\u00e8s aux \u00e9l\u00e9ments d'une liste","text":"Exemple fondateur n\u00b02
On acc\u00e8de \u00e0 un \u00e9l\u00e9ment d'une liste en mettant entre crochets l'indice de l'\u00e9l\u00e9ment (qui commence \u00e0 z\u00e9ro).
>>> famille = [\"Bart\", \"Lisa\", \"Maggie\"] # (1)\n>>> famille[0]\n'Bart'\n>>> famille[1]\n'Lisa'\n>>> famille[2]\n'Maggie'\n>>> famille[3]\nTraceback (most recent call last):\n File \"<pyshell>\", line 1, in <module>\nIndexError: list index out of range\n
- Nous prendrons souvent l'exemple de la famille Simpsons.
Remarques :
-
Un indice qui d\u00e9passe la valeur \u00a0longueur de la liste -1
provoquera donc une erreur list index out of range
. C'est une erreur tr\u00e8s fr\u00e9quente lorsqu'on manipule des listes.
-
Il est par contre possible d'utiliser des indices n\u00e9gatifs. On utilise par exemple tr\u00e8s souvent l'indice -1 pour acc\u00e9der au dernier \u00e9l\u00e9ment de la liste, sans avoir \u00e0 conna\u00eetre la longueur de celle-ci :
>>> famille[-1]\n'Maggie'\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#3-longueur-dune-liste","title":"3. Longueur d'une liste","text":"Exemple fondateur n\u00b03
La longueur d'une liste sera donn\u00e9e par la fonction len()
, qui renvoie donc un nombre entier positif ou nul.
>>> len(famille)\n3\n
Remarques :
- La liste vide a pour longueur 0 :
>>> len([])\n0\n
- Le dernier \u00e9l\u00e9ment d'une liste
maliste
(non vide) sera donc toujours l'\u00e9l\u00e9ment d'indice len(maliste)-1
. >>> famille[len(famille) - 1]\n'Maggie'\n
- Comme indiqu\u00e9 pr\u00e9c\u00e9demment, ce dernier \u00e9l\u00e9ment est aussi accessible par l'indice -1.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#4-parcours-des-elements-dune-liste","title":"4. Parcours des \u00e9l\u00e9ments d'une liste","text":"Il existe deux m\u00e9thodes pour parcourir s\u00e9quentiellement tous les \u00e9l\u00e9ments d'une liste. Ces deux m\u00e9thodes sont \u00e0 ma\u00eetriser imp\u00e9rativement.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#41-parcours-par-elements","title":"4.1 Parcours \u00abpar \u00e9l\u00e9ments\u00bb","text":"C'est la m\u00e9thode la plus naturelle, celle d\u00e9j\u00e0 vue lors de la pr\u00e9sentation de la boucle for
. Nous allons simplement it\u00e9rer sur les \u00e9l\u00e9ments de la liste.
Exemple fondateur n\u00b04
Le code :
famille = [\"Bart\", \"Lisa\", \"Maggie\"]\n\nfor membre in famille:\n print(membre)\n
renverra : Bart\nLisa\nMaggie\n
Remarque :
- Penser \u00e0 donner un nom signifiant \u00e0 la variable qui parcourt la liste. Il aurait par exemple \u00e9t\u00e9 tr\u00e8s maladroit d'\u00e9crire
for k in famille:\n print(k)\n
En effet le nom de variable k
est habituellement utilis\u00e9 pour les nombres (les indices, les compteurs...).
Exercice 1
\u00c9nonc\u00e9Correction Apr\u00e8s un r\u00e9f\u00e9rendum, la liste urne
contient uniquement des 'oui'
ou des 'non'
. D\u00e9terminer le vainqueur de ce r\u00e9f\u00e9rendum.
urne = ['oui', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'non', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'non', 'oui', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'oui']\n
urne = ['oui', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'non', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'non', 'non', 'non', 'oui', 'oui', 'non', 'oui', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'non', 'non', 'oui', 'oui', 'oui', 'non', 'oui', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'non', 'oui', 'non', 'non', 'non', 'non', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'non', 'non', 'oui', 'oui', 'oui', 'oui', 'oui', 'oui', 'non', 'oui']\n\nnb_oui = 0\nnb_non = 0\nfor vote in urne:\n if vote == 'oui':\n nb_oui += 1\n else:\n nb_non += 1\nprint('pourcentage de oui', 100*nb_oui/len(urne), '%')\nprint('pourcentage de non', 100*nb_non/len(urne), '%')\nprint('-'*10)\nif nb_oui > nb_non:\n print('le oui est vainqueur')\nelif nb_oui < nb_non:\n print('le non est vainqueur')\nelse:\n print('le oui et le non sont \u00e0 \u00e9galit\u00e9')\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#42-parcours-par-indice","title":"4.2 Parcours \u00abpar indice\u00bb","text":"Chaque \u00e9l\u00e9ment \u00e9tant accessible par son indice (de 0
\u00e0 len(liste) - 1
), il suffit de faire parcourir \u00e0 une variable i
l'ensemble des entiers de 0
\u00e0 len(liste) - 1
, par l'instruction range(len(liste))
:
Exemple fondateur n\u00b05
Le code :
famille = [\"Bart\", \"Lisa\", \"Maggie\"]\n\nfor i in range(len(famille)):\n print(famille[i])\n
renverra : Bart\nLisa\nMaggie\n
Bonne habitude \u00e0 prendre : nommer sa variable d'indice i
, j
, k
ou indice
mais pas autre chose !
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#43-avantages-et-inconvenients-de-chaque-methode","title":"4.3 Avantages et inconv\u00e9nients de chaque m\u00e9thode","text":""},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#431-parcours-par-element","title":"4.3.1 Parcours par \u00e9l\u00e9ment","text":" for membre in famille:\n print(membre)\n
Les avantages
- la simplicit\u00e9 : un code plus facile \u00e0 \u00e9crire, avec un nom de variable explicite.
- la s\u00e9curit\u00e9 : pas de risque d'
index out of range
!
Les inconv\u00e9nients
- m\u00e9thode rudimentaire : lorsqu'on est \u00abpositionn\u00e9\u00bb sur un \u00e9l\u00e9ment, il n'est pas possible d'acc\u00e9der au pr\u00e9c\u00e9dent ou au suivant. (et c'est parfois utile).
- on ne peut pas modifier l'\u00e9l\u00e9ment sur lequel on est positionn\u00e9 :
>>> lst = [1, 2, 3]\n>>> for nb in lst:\n nb = nb * 2 # (1)\n\n>>> lst \n[1, 2, 3] # (2)\n
- On veut multiplier par 2 chaque \u00e9l\u00e9ment de la liste
- La liste
lst
n'a pas chang\u00e9...
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#432-parcours-par-indice","title":"4.3.2 Parcours par indice","text":" for i in range(len(famille)):\n print(famille[i])\n
Les avantages
- le contr\u00f4le : en parcourant par indice, on peut s'arr\u00eater o\u00f9 on veut, on peut acc\u00e9der au suivant/pr\u00e9c\u00e9dent...
- pour les tableaux \u00e0 deux dimensions, on retrouve la d\u00e9signation classique d'un \u00e9l\u00e9ment par num\u00e9ro de ligne / num\u00e9ro de colonne.
Les inconv\u00e9nients
- la complexit\u00e9 : il faut conna\u00eetre le nombre d'\u00e9l\u00e9ments de la liste (ou le r\u00e9cup\u00e9rer par la fonction
len()
) - le risque d'erreur : encore et toujours le
index out of range
...
Exercice 1
\u00c9nonc\u00e9Correction On donne la liste :
lst = [3, 1, 4, 1, 5, 9]\n
En utilisant un parcours par indice : - Afficher un \u00e0 un les \u00e9l\u00e9ments de cette liste.
- Afficher un \u00e0 un les \u00e9l\u00e9ments de cette liste dans l'ordre inverse (en commen\u00e7ant par 9)
for i in range(len(lst)):\n print(lst[i])\n
2.
lst = [3, 1, 4, 1, 5, 9]\n\nfor i in range(len(lst)-1, -1, -1):\n print(lst[i])\n
Exercice 2
\u00c9nonc\u00e9Correction 1.Correction 2. Trouvez le nombre qui est exactement \u00e0 la m\u00eame place dans la liste list1
et dans la liste list2
, sachant que les deux listes ont la m\u00eame taille.
- En utilisant une boucle
for
(une seule !). - En utilisant une boucle
while
. Quel est l'avantage de la boucle while
?
list1 = [8468, 4560, 3941, 3328, 7, 9910, 9208, 8400, 6502, 1076, 5921, 6720, 948, 9561, 7391, 7745, 9007, 9707, 4370, 9636, 5265, 2638, 8919, 7814, 5142, 1060, 6971, 4065, 4629, 4490, 2480, 9180, 5623, 6600, 1764, 9846, 7605, 8271, 4681, 2818, 832, 5280, 3170, 8965, 4332, 3198, 9454, 2025, 2373, 4067]\nlist2 = [9093, 2559, 9664, 8075, 4525, 5847, 67, 8932, 5049, 5241, 5886, 1393, 9413, 8872, 2560, 4636, 9004, 7586, 1461, 350, 2627, 2187, 7778, 8933, 351, 7097, 356, 4110, 1393, 4864, 1088, 3904, 5623, 8040, 7273, 1114, 4394, 4108, 7123, 8001, 5715, 7215, 7460, 5829, 9513, 1256, 4052, 1585, 1608, 3941]\n
list1 = [8468, 4560, 3941, 3328, 7, 9910, 9208, 8400, 6502, 1076, 5921, 6720, 948, 9561, 7391, 7745, 9007, 9707, 4370, 9636, 5265, 2638, 8919, 7814, 5142, 1060, 6971, 4065, 4629, 4490, 2480, 9180, 5623, 6600, 1764, 9846, 7605, 8271, 4681, 2818, 832, 5280, 3170, 8965, 4332, 3198, 9454, 2025, 2373, 4067]\nlist2 = [9093, 2559, 9664, 8075, 4525, 5847, 67, 8932, 5049, 5241, 5886, 1393, 9413, 8872, 2560, 4636, 9004, 7586, 1461, 350, 2627, 2187, 7778, 8933, 351, 7097, 356, 4110, 1393, 4864, 1088, 3904, 5623, 8040, 7273, 1114, 4394, 4108, 7123, 8001, 5715, 7215, 7460, 5829, 9513, 1256, 4052, 1585, 1608, 3941]\n\nfor i in range(len(list1)):\n if list1[i] == list2[i]:\n print(list1[i])\n
list1 = [8468, 4560, 3941, 3328, 7, 9910, 9208, 8400, 6502, 1076, 5921, 6720, 948, 9561, 7391, 7745, 9007, 9707, 4370, 9636, 5265, 2638, 8919, 7814, 5142, 1060, 6971, 4065, 4629, 4490, 2480, 9180, 5623, 6600, 1764, 9846, 7605, 8271, 4681, 2818, 832, 5280, 3170, 8965, 4332, 3198, 9454, 2025, 2373, 4067]\nlist2 = [9093, 2559, 9664, 8075, 4525, 5847, 67, 8932, 5049, 5241, 5886, 1393, 9413, 8872, 2560, 4636, 9004, 7586, 1461, 350, 2627, 2187, 7778, 8933, 351, 7097, 356, 4110, 1393, 4864, 1088, 3904, 5623, 8040, 7273, 1114, 4394, 4108, 7123, 8001, 5715, 7215, 7460, 5829, 9513, 1256, 4052, 1585, 1608, 3941]\n\ni = 0\nwhile list1[i] != list2[i]:\n i += 1\nprint(list1[i])\n
Avantage : on s'arr\u00eate d\u00e8s qu'on a trouv\u00e9 ! Inconv\u00e9nient : on part du principe que ce nombre existe vraiment. Si on ne le trouve pas, on aura une erreur...
Exercice 3
\u00c9nonc\u00e9Correction Dans la liste
lst = [2428970, 1518306, 4971405, 1690994, 7918102, 4030834, 8830131, 7514856, 7903128, 6307569, 6624056, 5260490, 6447835, 4598783, 9108626, 5045240, 4128269, 4460134, 2497873, 5076659, 8104003, 7604887, 7451976, 4136924, 5691945, 8726293, 7855592, 3562473, 8849129, 6488474, 5303587, 2606124, 5484044, 4559758, 7592232, 2211406, 9974334, 7988936, 7582946, 7668748, 1799997, 3837917, 3196209, 7064342, 2543765, 1182013, 7253381, 1153735, 1037391, 4375946, 4445821, 5965587, 6001887, 4162629, 5235783, 8716582, 4901175, 5445422, 1120005, 8332321, 7075046, 2194175, 5557300, 2887907, 5103214, 2520744, 5104399, 2065665, 3035703, 7890213, 1758301, 3407982, 1355453, 4896338, 7979392, 9671602, 9690721, 7423779, 7423780, 3080825, 6785783, 3836837, 7310931, 1857470, 3492507, 2823231, 1492310, 1911148, 9620515, 5564910, 7009452, 7464745, 9608747, 7267383, 6939140, 6556578, 3592267, 8135497, 4881660, 5346884, 6859150]\n
se cachent deux nombres cons\u00e9cutifs (comme les nombres 4 et 5 dans la liste [6, 2, 4, 5, 3]
). Pouvez-vous les trouver ? lst = [2428970, 1518306, 4971405, 1690994, 7918102, 4030834, 8830131, 7514856, 7903128, 6307569, 6624056, 5260490, 6447835, 4598783, 9108626, 5045240, 4128269, 4460134, 2497873, 5076659, 8104003, 7604887, 7451976, 4136924, 5691945, 8726293, 7855592, 3562473, 8849129, 6488474, 5303587, 2606124, 5484044, 4559758, 7592232, 2211406, 9974334, 7988936, 7582946, 7668748, 1799997, 3837917, 3196209, 7064342, 2543765, 1182013, 7253381, 1153735, 1037391, 4375946, 4445821, 5965587, 6001887, 4162629, 5235783, 8716582, 4901175, 5445422, 1120005, 8332321, 7075046, 2194175, 5557300, 2887907, 5103214, 2520744, 5104399, 2065665, 3035703, 7890213, 1758301, 3407982, 1355453, 4896338, 7979392, 9671602, 9690721, 7423779, 7423780, 3080825, 6785783, 3836837, 7310931, 1857470, 3492507, 2823231, 1492310, 1911148, 9620515, 5564910, 7009452, 7464745, 9608747, 7267383, 6939140, 6556578, 3592267, 8135497, 4881660, 5346884, 6859150]\n\nfor i in range(len(lst)-1): # Il faut s'arr\u00eater \u00e0 l'avant-dernier \u00e9l\u00e9ment de la liste\n if lst[i] + 1 == lst[i+1]:\n print(lst[i], lst[i+1])\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#5-modification-dune-liste","title":"5. Modification d'une liste","text":"En Python, les objets de type List
sont modifiables (on emploie le mot mutables). Et c'est souvent une bonne chose, car des listes peuvent \u00e9voluer apr\u00e8s leur cr\u00e9ation. Lorsqu'on souhaitera figer le contenu d'une liste (pour des raisons de s\u00e9curit\u00e9 du code essentiellement), on utilisera alors le type Tuple
, qui sera vu ult\u00e9rieurement.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#51-modification-dun-element-existant","title":"5.1 Modification d'un \u00e9l\u00e9ment existant","text":"Il suffit d'\u00e9craser la valeur actuelle avec une nouvelle valeur
Exemple fondateur n\u00b06
>>> famille = [\"Bart\", \"Lisa\", \"Maggie\"]\n>>> famille[0] = \"Bartholomew\" # oui, c'est son vrai nom\n>>> famille\n['Bartholomew', 'Lisa', 'Maggie'] \n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#52-ajout-dun-element-a-la-fin-dune-liste-la-methode-append","title":"5.2 Ajout d'un \u00e9lement \u00e0 la fin d'une liste : la m\u00e9thode append()","text":"Exemple fondateur n\u00b07
>>> famille = [\"Bart\", \"Lisa\", \"Maggie\"]\n>>> famille.append(\"Milhouse\")\n>>> famille\n['Bart', 'Lisa', 'Maggie', 'Milhouse'] \n
Remarques :
- La m\u00e9thode
append()
rajoute donc un \u00e9l\u00e9ment \u00e0 la fin de la liste. - Dans beaucoup d'exercices, on part d'une liste vide
[]
que l'on remplit peu \u00e0 peu avec des append()
. - (HP) Il est possible d'ins\u00e9rer un \u00e9l\u00e9ment \u00e0 la position
i
avec la m\u00e9thode insert
: >>> famille = [\"Bart\", \"Lisa\", \"Maggie\"]\n>>> famille.insert(1, \"Nelson\") # on ins\u00e8re \u00e0 la position 1\n>>> famille\n['Bart', 'Nelson', 'Lisa', 'Maggie']\n
Exercice 4
\u00c9nonc\u00e9Correction Construire une liste contenant tous les nombres inf\u00e9rieurs \u00e0 100 qui sont divisibles par 7.
lst = []\nfor n in range(1, 101):\n if n % 7 == 0:\n lst.append(n)\n
Exercice 5
\u00c9nonc\u00e9Correction On consid\u00e8re la liste temp = [4, -5, 8, 10, -1, -2, 7, 13]
. Construire la liste temp_pos
qui ne contient que les \u00e9l\u00e9ments positifs de temp
.
temp = [4, -5, 8, 10, -1, -2, 7, 13]\n\ntemp_pos = []\nfor t in temp:\n if t > 0:\n temp_pos.append(t)\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#53-suppression-dun-element-dune-liste","title":"5.3 Suppression d'un \u00e9l\u00e9ment d'une liste ...","text":""},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#531-par-la-methode-remove","title":"5.3.1 ... par la m\u00e9thode remove()","text":"Exemple fondateur n\u00b07
>>> famille = ['Bart', 'Nelson', 'Lisa', 'Maggie']\n>>> famille.remove(\"Nelson\")\n>>> famille\n['Bart', 'Lisa', 'Maggie']\n
Remarques :
- Attention,
remove
n'enl\u00e8ve que la premi\u00e8re occurrence de l'\u00e9l\u00e9ment d\u00e9sign\u00e9. S'il y en a d'autres apr\u00e8s, elles resteront dans la liste : >>> lst = [3, 1, 4, 5, 1, 9, 4]\n>>> lst.remove(4)\n>>> lst\n[3, 1, 5, 1, 9, 4]\n
- Si l'\u00e9l\u00e9ment \u00e0 supprimer n'est pas trouv\u00e9, un message d'erreur est renvoy\u00e9 :
>>> lst = [3, 1, 4, 5, 1, 9]\n>>> lst.remove(2)\nTraceback (most recent call last):\n File \"<pyshell>\", line 1, in <module>\nValueError: list.remove(x): x not in list\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#532-par-linstruction-del","title":"5.3.2 ... par l'instruction del
","text":"L'instruction del
(qui n'est pas une fonction) permet de supprimer un \u00e9l\u00e9ment en donnant son indice.
>>> maliste = [8, 4, 2, 5, 7]\n>>> del maliste[3]\n>>> maliste\n[8, 4, 2, 7]\n
Exercice 6
\u00c9nonc\u00e9 Exercice de la BNS.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#6-construction-dune-liste-delements-identiques","title":"6. Construction d'une liste d'\u00e9l\u00e9ments identiques","text":"Il est souvent pratique d'initialiser une liste de taille donn\u00e9e, souvent en la remplissant de 0.
Imaginons par exemple que nous souhaitions une liste de taille 26 remplie de 0. Il est possible de faire comme ceci :
lst = []\nfor _ in range(26):\n lst.append(0)\n
mais on pr\u00e9f\u00e8rera ce code :
Exemple fondateur n\u00b08
>>> lst = [0]*26\n
qui produira la liste [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Exercice 7
\u00c9nonc\u00e9Correction Que fait le code ci-dessous ?
texte = \"cet texte est prodigieusement ennuyeux\"\n\ndef rang(lettre):\n return ord(lettre) - 97\n\ncompt = [0]*26\nfor lettre in texte :\n if lettre != \" \" :\n compt[rang(lettre)] += 1\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#7-construction-dune-liste-en-comprehension","title":"7. Construction d'une liste en compr\u00e9hension","text":"C'est une grande caract\u00e9ristique du langage Python (m\u00eame si ce n'est pas une exclusivit\u00e9) : la m\u00e9thode de liste en compr\u00e9hension propose une mani\u00e8re \u00e9l\u00e9gante, rapide et naturelle pour cr\u00e9er des listes.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#71-en-comprehension-pourquoi","title":"7.1 \u00aben compr\u00e9hension\u00bb, pourquoi ?","text":"Cette expression vient des math\u00e9matiques. On dit qu'on d\u00e9finit un sous-ensemble par compr\u00e9hension lorsqu'on part d'un ensemble plus grand dont on ne garde que les \u00e9l\u00e9ments v\u00e9rifiant une certaine propri\u00e9t\u00e9.
On pourrait par exemple d\u00e9finir les \u00e9l\u00e8ves de Premi\u00e8re NSI de cette mani\u00e8re :
\u00ab\u00e9l\u00e8ves du lyc\u00e9e inscrits en classe de Premi\u00e8re ayant choisi la sp\u00e9cialit\u00e9 NSI\u00bb
On part d'un ensemble large (les \u00e9l\u00e8ves du lyc\u00e9e) qu'on va ensuite r\u00e9duire par des caract\u00e9risations sp\u00e9cifiques : \u00eatre un \u00e9l\u00e8ve de Premi\u00e8re, puis avoir choisi la sp\u00e9cialit\u00e9 NSI.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#72-premier-exemple","title":"7.2 Premier exemple","text":"Exemple fondateur n\u00b09
Imaginons que nous poss\u00e9dons une liste data
de temp\u00e9ratures, dont nous ne voulons garder que celles strictement sup\u00e9rieures \u00e0 20.
>>> data = [17, 22, 15, 28, 16, 13, 21, 23]\n>>> good = [t for t in data if t > 20]\n>>> good\n[22, 28, 21, 23]\n
Explications :
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#721-le-filtre-eventuel","title":"7.2.1 le filtre \u00e9ventuel","text":"C'est lui qui donne tout son sens \u00e0 cette m\u00e9thode : il permet de ne garder que certaines valeurs. Il est pourtant \u00e9ventuel : que se passe-t-il s'il n'y a pas de filtre ?
>>> data = [17, 22, 15, 28, 16, 13, 21, 23]\n>>> good = [t for t in data]\n>>> good\n[17, 22, 15, 28, 16, 13, 21, 23]\n
On se retrouve \u00e9videmment avec une nouvelle liste qui contient exactement les \u00e9l\u00e9ments de la liste de d\u00e9part, ce qui n'est pas tr\u00e8s int\u00e9ressant. Pourtant les listes en compr\u00e9hension sans filtre sont tr\u00e8s fr\u00e9quentes, nous le verrons plus loin. Exercice 8
\u00c9nonc\u00e9Correction On consid\u00e8re la variable phrase = 'Bonjour les vacances sont finies'
et la variable voyelles = 'aeiouy'
.
Construire en compr\u00e9hension la liste liste_voyelles
qui contient toutes les voyelles pr\u00e9sentes dans la variable phrase
.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#722-lensemble-de-depart","title":"7.2.2 l'ensemble de d\u00e9part","text":"C'est \u00e0 partir de lui que va se construire notre liste. Pour l'instant, cet ensemble de d\u00e9part a toujours \u00e9t\u00e9 de type list
.
Cet ensemble peut \u00eatre aussi donn\u00e9 \u00e0 partir de l'instruction range()
. Souvenons-nous de l'exercice 4 : \u00abConstruire une liste contenant tous les nombres inf\u00e9rieurs \u00e0 100 qui sont divisibles par 7.\u00bb.
Une solution possible \u00e9tait :
lst = []\nfor n in range(1, 101):\n if n % 7 == 0:\n lst.append(n)\n
Ce code peut maintenant s'\u00e9crire tr\u00e8s simplement en une seule instruction :
Exemple fondateur n\u00b010
>>> lst = [n for n in range(1,101) if n % 7 == 0]\n>>> lst\n[7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98]\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#723-la-valeur-a-garder","title":"7.2.3 la valeur \u00e0 garder","text":"Pour l'instant, nous avons proc\u00e9d\u00e9 \u00e0 des filtres sur des ensembles existants, sans modifier la valeur filtr\u00e9e (la valeur \u00e0 garder). Les listes en compr\u00e9hension deviennent encore plus int\u00e9ressantes lorsqu'on comprend qu'il est possible de modifier la valeur filtr\u00e9e :
Exemple fondateur n\u00b011
>>> lst_carres = [t**2 for t in range(1,10)]\n>>> lst_carres\n[1, 4, 9, 16, 25, 36, 49, 64, 81]\n
Exercice 9
\u00c9nonc\u00e9Correction - On consid\u00e8re la fonction math\u00e9matique \\(f : x \\mapsto 2x+3\\). Coder la fonction
f
. - Cr\u00e9er (en compr\u00e9hension) une liste contenant l'image des entiers de 1 \u00e0 10 par la fonction \\(f\\).
def f(x):\n return 2*x + 3\n\nlst = [f(x) for x in range(1, 11)]\n
Exercice 10
\u00c9nonc\u00e9Correction On consid\u00e8re la liste lst = [51, 52, 66, 91, 92, 82, 65, 53, 86, 42, 79, 95]
. Seuls les nombres entre 60 et 90 ont une signification : ce sont des codes ASCII (r\u00e9cup\u00e9rables par la fonction chr
). Cr\u00e9er (en compr\u00e9hension) une liste sol
qui contient les lettres correspondants aux nombres ayant une signification.
>>> lst = [51, 52, 66, 91, 92, 82, 65, 53, 86, 42, 79, 95]\n>>> decode = [chr(k) for k in lst if k > 60 and k < 90]\n>>> decode\n['B', 'R', 'A', 'V', 'O']\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#8-un-phenomene-inquietant-la-copie-de-liste","title":"8. Un ph\u00e9nom\u00e8ne inqui\u00e9tant : la copie de liste","text":"une copie un peu trop parfaite
Observez le code ci-dessous, r\u00e9alis\u00e9 sans trucage.
>>> listA = [1, 2, 3]\n>>> listB = listA\n>>> listA.append(7)\n>>> listB\n[1, 2, 3, 7]\n>>> listB.append(8)\n>>> listA\n[1, 2, 3, 7, 8]\n
Tout se passe comme si les listes listA
etlistB
\u00e9taient devenus des clones \u00absynchronis\u00e9s\u00bb depuis l'affectation listB = listA
.
Analyse gr\u00e2ce \u00e0 PythonTutor
L'illustration de PythonTutor nous donne la cl\u00e9 de l'\u00e9nigme :
listA
etlistB
sont en fait un seul et m\u00eame objet.
Comment en avoir le c\u0153ur net ? En observant leur adresse-m\u00e9moire, disponible gr\u00e2ce \u00e0 la fonction id
:
>>> id(listA)\n140485841327616\n>>> id(listB)\n140485841327616\n
Ceci met en \u00e9vidence que la m\u00e9taphore du tiroir dont on se sert pour expliquer ce qu'est une variable est malheureusement inexacte. Une variable est une r\u00e9f\u00e9rence vers une adresse-m\u00e9moire. Si deux variables font r\u00e9f\u00e9rence \u00e0 la m\u00eame adresse-m\u00e9moire, alors elles sont totalement identiques: toute modification de l'une entra\u00eene une modification de l'autre.
Pour en savoir plus sur les variables, vous pouvez revenir sur la partie optionnelle du cours sur les variables.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#mais-alors-comment-copier-le-contenu-dune-liste-vers-une-autre-sans-creer-un-clone","title":"Mais alors, comment copier le contenu d'une liste vers une autre sans cr\u00e9er un clone ?","text":"Exemple fondateur n\u00b012
>>> listA = [3, 4, 5]\n>>> listB = list(listA)\n
D'autres possibilit\u00e9s existent, comme listA.copy()
, ou encore listA[::]
... Exercice 11
\u00c9nonc\u00e9Correction Effectuer les tests n\u00e9cessaires pour prouver que l'exemple pr\u00e9c\u00e9dent a bien produit deux objets diff\u00e9rents.
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#9-tableaux-a-plusieurs-dimensions-listes-de-listes","title":"9. Tableaux \u00e0 plusieurs dimensions : listes de listes","text":"Nous avons vu qu'une liste pouvait contenir des \u00e9l\u00e9ments de tous types : des entiers, des chaines des caract\u00e8res... et pourquoi pas une liste qui contient des listes ?
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#91-syntaxe","title":"9.1 Syntaxe","text":"Exemple fondateur n\u00b012
La liste tab
ci-dessous est compos\u00e9e de 3 listes qui elles-m\u00eames contiennent trois nombres :
tab = [[3, 5, 2],\n [7, 1, 4], \n [8, 6, 9]]\n
tab[0][0] = 3
tab[0][1] = 5
tab[2][1] = 6
tab[1] = [7, 1, 4]
La liste a
est compos\u00e9e de 3 \u00e9l\u00e9ments qui sont eux-m\u00eame des listes de 3 \u00e9l\u00e9ments.
Exercice 12
\u00c9nonc\u00e9Correction On consid\u00e8re le jeu du Morpion (ou Tic-Tac-Toe) dont la surface de jeu vierge est represent\u00e9e par le tableau : tab = [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]
Les premiers coups jou\u00e9s sont ceux-ci :
tab[1][1] = 'X'
tab[2][1] = 'O'
tab[2][2] = 'X'
tab[0][0] = 'O'
Quel coup doit maintenant jouer le joueur 'X'
pour s'assurer la victoire ?
tab[0][2] = 'X'\n# ou\ntab[1][2] = 'X'\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/cours/#92-parcours-dune-liste-de-listes","title":"9.2 Parcours d'une liste de listes","text":"Exemple fondateur n\u00b013
-
Parcours par \u00e9l\u00e9ments :
for ligne in tab:\n for elt in ligne:\n print(elt)\n
-
Parcours par indice :
for i in range(3):\n for j in range(3):\n print(tab[i][j])\n
Exercice 13
\u00c9nonc\u00e9Correction On consid\u00e8re la liste m
('m' comme matrice) suivante :
m = [[1, 9, 4], [4, 1, 8], [7, 10, 1]]
Quelle est la somme de tous les nombres de la matrice m
?
m = [[1, 9, 4], [4, 1, 8], [7, 10, 1]]\n\nsomme = 0\nfor ligne in m:\n for elt in ligne:\n somme += elt\n\nprint(somme)\n
ou bien
m = [[1, 9, 4], [4, 1, 8], [7, 10, 1]]\n\nsomme = 0\nfor i in range(3):\n for j in range(3):\n somme += m[i][j]\n\nprint(somme)\n
"},{"location":"T2_Representation_des_donnees/2.1_Listes/exercices/","title":"Exercices","text":"Exercice 1
\u00c9nonc\u00e9Correction R\u00e9solvez le Pyd\u00e9fi propos\u00e9 \u00e0 cette adresse
Vous pouvez vous cr\u00e9er un compte pour valider vos r\u00e9sultats, ce site (g\u00e9r\u00e9 par l'Acad\u00e9mie de Poitiers) est remarquable.
Exercice 2
\u00c9nonc\u00e9 On donne la liste jours
suivante :
jours = [\"lundi\", \"mardi\", \"mercredi\", \"jeudi\", \"vendredi\", \"samedi\", \"dimanche\"]\n
On rappelle que la fonction len
permet d'obtenir le nombre de caract\u00e8res d'une chaine de caract\u00e8res :
>>> len(\"test\")\n4\n
Q1. Cr\u00e9er en compr\u00e9hension une liste lst1
contenant uniquement les jours comportant 5 lettres.
Correction lst1 = [day for day in jours if len(day) == 5]\n
Q2. Cr\u00e9er en compr\u00e9hension une liste lst2
contenant uniquement les jours comportant la lettre a
dans leur nom.
Correction lst2 = [day for day in jours if 'a' in day]\n
Q3a. Cr\u00e9er une fonction compte_e
qui prend en param\u00e8tre une chaine de caract\u00e8res et qui renvoie le nombre de e
que contient cette chaine de caract\u00e8res.
Correction def compte_e(mot):\n compteur = 0\n for lettre in mot:\n if lettre == 'e':\n compteur += 1\n return compteur\n
Q3b. Cr\u00e9er en compr\u00e9hension une liste lst4
contenant uniquement les jours comportant deux fois la lettre e
dans leur nom.
Correction lst4 = [day for day in jours if compte_e(day) == 2]\n
Exercice 3
\u00c9nonc\u00e9Correction On donne le tableau m
suivant :
m = [[17, 71, 75, 89, 45, 10, 54, 26, 59, 47, 57, 64, 44], \\\n [67, 25, 47, 49, 28, 40, 10, 17, 77, 35, 87, 15, 68], \\\n [66, 89, 28, 43, 16, 14, 12, 21, 68, 22, 14, 18, 59], \\\n [60, 35, 30, 23, 22, 37, 49, 89, 82, 80, 85, 28, 17], \\\n [61, 42, 39, 46, 29, 38, 85, 72, 44, 60, 47, 35, 52], \\\n [44, 28, 24, 40, 71, 71, 46, 25, 78, 54, 66, 84, 52], \\\n [29, 71, 7, 38, 71, 60, 71, 60, 16, 82, 35, 39, 23], \\\n [18, 61, 38, 7, 8, 32, 67, 43, 23, 28, 29, 16, 30], \\\n [45, 30, 74, 9, 84, 78, 11, 80, 42, 64, 9, 39, 26], \\\n [78, 57, 54, 66, 57, 63, 10, 42, 61, 19, 26, 25, 53], \\\n [38, 87, 10, 64, 75, 26, 14, 68, 19, 33, 75, 50, 18], \\\n [52, 81, 24, 67, 37, 78, 17, 19, 61, 82, 57, 24, 54]]\n
Afficher successivement chaque ligne du tableau en respectant les r\u00e8gles suivantes : - si le nombre est divisible par 7, afficher
*
, sinon afficher une espace
- sur une m\u00eame ligne, on affichera tous les symboles c\u00f4te \u00e0 c\u00f4te, en rajoutant le param\u00e8tre
end = ''
\u00e0 la fonction print
. (exemple : print('*', end = '')
) - on ira \u00e0 la ligne \u00e0 la fin de chaque ligne, par l'instruction
print()
m = [[17, 71, 75, 89, 45, 10, 54, 26, 59, 47, 57, 64, 44], \\\n [67, 25, 47, 49, 28, 40, 10, 17, 77, 35, 87, 15, 68], \\\n [66, 89, 28, 43, 16, 14, 12, 21, 68, 22, 14, 18, 59], \\\n [60, 35, 30, 23, 22, 37, 49, 89, 82, 80, 85, 28, 17], \\\n [61, 42, 39, 46, 29, 38, 85, 72, 44, 60, 47, 35, 52], \\\n [44, 28, 24, 40, 71, 71, 46, 25, 78, 54, 66, 84, 52], \\\n [29, 71, 7, 38, 71, 60, 71, 60, 16, 82, 35, 39, 23], \\\n [18, 61, 38, 7, 8, 32, 67, 43, 23, 28, 29, 16, 30], \\\n [45, 30, 74, 9, 84, 78, 11, 80, 42, 64, 9, 39, 26], \\\n [78, 57, 54, 66, 57, 63, 10, 42, 61, 19, 26, 25, 53], \\\n [38, 87, 10, 64, 75, 26, 14, 68, 19, 33, 75, 50, 18], \\\n [52, 81, 24, 67, 37, 78, 17, 19, 61, 82, 57, 24, 54]]\n\nfor ligne in m:\n for elt in ligne:\n if elt % 7 == 0:\n print('*', end = '')\n else:\n print(' ', end = '')\n print('')\n
Exercice 4
\u00c9nonc\u00e9Correction Pyd\u00e9fi Insaisissable matrice (version originale \u00e0 cette adresse)
On consid\u00e8re la matrice suivante :
-------------------------------\n| 17 | 3 | 4 | 14 | 5 | 17 |\n-------------------------------\n| 8 | 16 | 3 | 17 | 14 | 12 |\n-------------------------------\n| 13 | 5 | 15 | 4 | 16 | 3 |\n-------------------------------\n| 14 | 7 | 3 | 16 | 3 | 2 |\n-------------------------------\n| 6 | 1 | 16 | 10 | 5 | 13 |\n-------------------------------\n| 11 | 1 | 9 | 11 | 18 | 8 |\n-------------------------------\n
M = [[17, 3, 4, 14, 5, 17], [8, 16, 3, 17, 14, 12], [13, 5, 15, 4, 16, 3], [14, 7, 3, 16, 3, 2], [6, 1, 16, 10, 5, 13], [11, 1, 9, 11, 18, 8]]\n
Cette matrice va \u00e9voluer au cours du temps, et le contenu k
d'une case est transform\u00e9, \u00e0 chaque \u00e9tape en (9*k + 3) % 19
.
Rappelons que a % b
donne le reste de la division enti\u00e8re de a
par b
.
\u00c0 chaque \u00e9tape de calcul, tous les nombres de la matrice sont simultan\u00e9ment modifi\u00e9s. L'entr\u00e9e du probl\u00e8me est le nombre d'\u00e9tapes \u00e0 appliquer (ici : 39). Vous devez r\u00e9pondre en donnant la somme des valeurs contenues dans la matrice apr\u00e8s application de toutes les \u00e9tapes.
M = [[17, 3, 4, 14, 5, 17], [8, 16, 3, 17, 14, 12], [13, 5, 15, 4, 16, 3], [14, 7, 3, 16, 3, 2], [6, 1, 16, 10, 5, 13], [11, 1, 9, 11, 18, 8]]\n\ndef f(k):\n return (9*k + 3) % 19\n\ndef tour():\n for i in range(6):\n for j in range(6):\n M[i][j] = f(M[i][j])\n\nfor _ in range(39):\n tour()\n\nsomme = 0\nfor i in range(6):\n for j in range(6):\n somme += M[i][j]\n\nprint(somme)\n
Exercice 5
\u00c9nonc\u00e9Correction D'apr\u00e8s Advent Of Code 2021, day02
Un sous-marin peut se d\u00e9placer horizontalement (toujours vers la droite) gr\u00e2ce \u00e0 l'instruction forward
suivie d'un nombre.
Il peut aussi monter ou descendre, gr\u00e2ce aux instructions up
ou down
, elles aussi suivies d'un nombre.
Un grand nombre d'instructions successives sont donn\u00e9es. Le but de l'exercice est de trouver le produit final de l'abscisse du sous-marin et de sa profondeur.
Exemple :
forward 5\ndown 5\nforward 8\nup 3\ndown 8\nforward 2\n
Apr\u00e8s ces d\u00e9placements, le sous-marin se trouve \u00e0 l'abscisse 15 et \u00e0 la profondeur 10. La r\u00e9ponse \u00e0 l'\u00e9nigme serait donc 150.
-
\u00e9nonc\u00e9 orginal
-
T\u00e9l\u00e9chargez le fichier input.txt. Votre fichier .py
de travail doit se situer dans le m\u00eame r\u00e9pertoire que le fichier input.txt
.
Parsing des donn\u00e9es
Parser des donn\u00e9es consiste \u00e0 les r\u00e9cup\u00e9rer et les rendre exploitables. C'est quelque chose de souvent p\u00e9nible (dans les \u00e9nigmes de code ET dans la vraie vie). Pourtant de la qualit\u00e9 du parsing (et surtout de la structure de stockage choisie) va d\u00e9pendre la difficult\u00e9 (ou non) de l'exploitation des donn\u00e9es.
Proposition de parsing :
data_raw = open('input.txt').read().splitlines()\nlst_raw = [d.split(' ') for d in data_raw]\nlst = [[l[0], int(l[1])] for l in lst_raw]\n
Ex\u00e9cutez ce code et observez ce que contient la liste lst
.
R\u00e9solution de l'\u00e9nigme
\u00c0 la fin de toutes ses man\u0153uvres, quel est le produit de l'abscisse du sous-marin et de sa profondeur ?
data_raw = open('input.txt').read().splitlines()\nlst_raw = [d.split(' ') for d in data_raw]\nlst = [[l[0], int(l[1])] for l in lst_raw]\n\nx = 0\ny = 0\n\nfor couple in lst:\n direction = couple[0]\n valeur = couple[1]\n if direction == 'forward':\n x += valeur\n if direction == 'down':\n y += valeur\n if direction == 'up':\n y -= valeur\n\nprint(x*y)\n
La r\u00e9ponse est donc 1746616.
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/","title":"2.2 Tuples","text":""},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#1definition-des-tuples","title":"1.D\u00e9finition des tuples","text":"Les tuples (appel\u00e9s p-uplets dans le programme officiel de NSI) sont une collection d'objets ordonn\u00e9e mais NON MODIFIABLE. Pour rappel :
- chaine de caract\u00e8res : ordonn\u00e9e et non modifiable
- liste : ordonn\u00e9e et modifiable
- tuple : ordonn\u00e9e et non modifiable
Quel peut \u00eatre l'int\u00e9r\u00eat d'un tuple par rapport \u00e0 une liste ?
- Justement son caract\u00e8re prot\u00e9g\u00e9 : jamais une portion de code ne pourra venir modifier les informations contenues dans le tuple.
- L'utilisation des tuples est \u00e9conome en ressources-syst\u00e8me par rapport \u00e0 une liste (en particulier, parce que sa taille est fixe).
>>> monPremierTuple = (3, 5, 6)\n
Un tuple se diff\u00e9rencie d'une liste par l'utilisation des parenth\u00e8ses au lieu des crochets.
>>> type(monPremierTuple)\ntuple\n
\u00c0 noter qu'un tuple peut \u00eatre d\u00e9clar\u00e9 sans parenth\u00e8ses. C'est toutefois \u00e0 \u00e9viter.
>>> taille = 600, 800\n>>> type(taille)\ntuple\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#2-acces-aux-elements-dun-tuple","title":"2. Acc\u00e8s aux \u00e9l\u00e9ments d'un tuple","text":"Comme pour une liste ou une cha\u00eene de caract\u00e8re, l'acc\u00e8s se fait par un indice entre crochets.
>>> a = (12, 25, 6)\n>>> a[0]\n12\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#3-tentative-de-modification-dun-tuple","title":"3. Tentative de modification d'un tuple","text":">>> a[0] = 4\n ---------------------------------------------------------------------------\n TypeError Traceback (most recent call last)\n\n <ipython-input-7-5fe525706b2b> in <module>()\n ----> 1 a[0] = 4\n\n\n TypeError: 'tuple' object does not support item assignment\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#4-parcours-dun-tuple","title":"4. Parcours d'un tuple","text":"On retrouve bien \u00e9videmment les deux m\u00e9thodes utilisables pour les listes :
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#41-parcours-par-indice","title":"4.1 Parcours par indice","text":">>> for k in range(len(a)):\n print(a[k])\n12\n25\n6\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#41-parcours-par-element","title":"4.1 Parcours par \u00e9l\u00e9ment","text":">>> for k in a :\n print(k)\n12\n25\n6\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#5-construction-dune-fonction-renvoyant-un-tuple","title":"5. Construction d'une fonction renvoyant un tuple","text":"def division(a, b):\n # fonction renvoyant le tuple (quotient, reste) de la division euclidienne de a par b.\n q = a // b\n r = a % b\n return (q, r)\n
>>> division(49,12)\n(4,1)\n
"},{"location":"T2_Representation_des_donnees/2.2_Tuples/cours/#6-exercice","title":"6. Exercice","text":"Exercice
\u00c9nonc\u00e9Correction On consid\u00e8re deux points A et B d'un rep\u00e8re quelconque. Leurs coordonn\u00e9es sont des tuples \u00e0 deux \u00e9l\u00e9ments. \u00c9crire une fonction qui prend en argument les coordonn\u00e9es de deux points et qui renvoie le milieu de ces deux points.
La fonction doit fonctionner de cette mani\u00e8re :
>>> C = (45, 12)\n>>> D = (49, 32)\n>>> milieu(C,D)\n(47, 22)\n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/","title":"2.3 Dictionnaires","text":""},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#1-les-dictionnaires-premiers-exemples","title":"1. Les dictionnaires : premiers exemples","text":"Une liste est un ensemble d'\u00e9l\u00e9ments accessibles par leur indice. Cet indice est en quelque sorte la \u00abplace\u00bb de l'\u00e9l\u00e9ment dans la liste. On peut dire que cet indice est la cl\u00e9 qui permet d'acc\u00e9der \u00e0 l'\u00e9l\u00e9ment.
Dans un dictionnaire, chaque \u00e9l\u00e9ment est accessible par une cl\u00e9 qui n'est plus forc\u00e9ment un nombre : une chaine de caract\u00e8re, un nombre, ou autre chose, peut \u00eatre une cl\u00e9.
Imaginons que je fasse l'inventaire de mon dressing :
habits quantit\u00e9 pantalons 3 pulls 4 tee-shirts 8 Exemple fondateur n\u00b01
- La cr\u00e9ation du dictionnaire repr\u00e9sentant mon dressing se fera par :
>>> dressing = {\"pantalons\":3, \"pulls\":4, \"tee-shirts\":8}\n
- L'acc\u00e8s \u00e0 une valeur se fera par :
>>> dressing[\"pulls\"]\n 4\n
-
On dit que \"pulls\"
est la cl\u00e9 et que 4 est la valeur associ\u00e9e \u00e0 la cl\u00e9.
-
Un dictionnaire est un ensemble cl\u00e9s / valeurs.
Attention : une cl\u00e9 peut aussi \u00eatre un nombre :
>>> myst = {9:4, 1:2, 6:3, 7:4} \n>>> myst[1]\n2\n>>> myst[7]\n4 \n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#2-definitions-et-proprietes-dun-dictionnaire","title":"2. D\u00e9finitions et propri\u00e9t\u00e9s d'un dictionnaire","text":""},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#21-definitions","title":"2.1 D\u00e9finitions","text":"D\u00e9finition
Un dictionnaire est une donn\u00e9e composite qui n'est pas ordonn\u00e9e (\u00e0 la diff\u00e9rence des listes !) Il fonctionne par un syst\u00e8me de cl\u00e9:valeur
. Les cl\u00e9s, comme les valeurs, peuvent \u00eatre de types diff\u00e9rents. Un dictionnaire est d\u00e9limit\u00e9 par des accolades.
Rappel :
- crochets
[ ]
-> listes - parenth\u00e8ses
( )
-> tuples - accolades
{ }
-> dictionnaires
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#22-methodes-keys-et-values","title":"2.2 M\u00e9thodes .keys()
et .values()
","text":"Exemples fondateurs n\u00b02
- Pour lister les cl\u00e9s d'un dictionnaire :
>>> dressing.keys()\ndict_keys(['pantalons', 'pulls', 'tee-shirts'])\n
- Pour lister les valeurs d'un dictionnaire :
>>> dressing.values()\ndict_values([3, 4, 8])\n
Ces m\u00e9thodes sont importantes (elles figurent explicitement au programme de NSI) mais sont en pratique peu utilis\u00e9es. On leur pr\u00e9f\u00e8rera tr\u00e8s largement la m\u00e9thode de parcours suivante :
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#23-parcours-dun-dictionnaire","title":"2.3 Parcours d'un dictionnaire","text":"Exemple fondateur n\u00b03
>>> for habit in dressing:\n print(dressing[habit])\n3\n4\n8\n
Observation gr\u00e2ce \u00e0 PythonTutor
Exercice 1
Faire afficher la sortie suivante :
pantalons -> 3\npulls -> 4\ntee-shirts -> 8\n
Correction dressing = {'pantalons':3, 'pulls':4, 'tee-shirts':8}\n\nfor habit in dressing:\n print(habit, '->', dressing[habit]) \n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#24-creation-dun-dictionnaire-vide","title":"2.4 Cr\u00e9ation d'un dictionnaire vide","text":"Exemple fondateur n\u00b04
Deux m\u00e9thodes existent pour cr\u00e9er un dictionnaire : dict()
et {}
>>> mondico = dict()\n>>> mondico\n{}\n>>> mondico['john'] = 12\n>>> mondico\n{'john': 12}\n
>>> contacts = {}\n>>> contacts['bob'] = '06 12 17 21 32'\n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#25-ajout-modification-dun-element-dans-un-dictionnaire","title":"2.5 Ajout / Modification d'un \u00e9l\u00e9ment dans un dictionnaire","text":"Exemple fondateur n\u00b05
Pas besoin d'une m\u00e9thode append()
, il suffit de rajouter une paire cl\u00e9 : valeur
>>> dressing[\"chaussettes\"] = 12\n
On peut aussi modifier un dictionnaire existant.
dressing[\"chaussettes\"] = 11\n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#26-suppression-dune-valeur","title":"2.6 Suppression d'une valeur","text":"Exemple fondateur n\u00b06
On utilise l'instruction del
(d\u00e9j\u00e0 rencontr\u00e9e pour les listes)
del dressing[\"chaussettes\"]\n
Exercice 2
Reprenons notre dictionnaire dressing
:
dressing = {\"pantalons\":3, \"pulls\":4, \"tee-shirts\":8}\n
Cr\u00e9er une fonction achat(habit)
qui augmente de 1 le nombre d'habits (pantalon, pull ou tee-shirt) de mon dressing. Exemple d'utilisation :
>>> dressing[\"pulls\"]\n4\n>>> achat(\"pulls\")\n>>> dressing[\"pulls\"]\n5\n
Correction dressing = {'pantalons':3, 'pulls':4, 'tee-shirts':8}\n\ndef achat(habit):\n dressing[habit] += 1\n
Remarque : Petit probl\u00e8me si on essaie d'acheter un v\u00eatement pour la 1\u00e8re fois
>>> achat(\"chemises\")\n ---------------------------------------------------------------------------\n\n KeyError Traceback (most recent call last)\n\n <ipython-input-28-fd9d1ac5f62d> in <module>\n ----> 1 achat(\"chemises\")\n\n\n <ipython-input-27-feb173444189> in achat(habit)\n 1 def achat(habit):\n ----> 2 dressing[habit] = dressing[habit] + 1\n\n\n KeyError: 'chemises'\n
Nous allons r\u00e9soudre ce probl\u00e8me gr\u00e2ce \u00e0 :
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#27-test-dappartenance-a-un-dictionnaire","title":"2.7 Test d'appartenance \u00e0 un dictionnaire","text":"Exemple fondateur n\u00b07
Le mot in
permet de tester l'appartenance d'une cl\u00e9 \u00e0 un dictionnaire. Un bool\u00e9en est renvoy\u00e9.
>>> \"cravates\" in dressing\n False\n
"},{"location":"T2_Representation_des_donnees/2.3_Dictionnaires/cours/#3-exercices","title":"3. Exercices","text":"Exercice 3
Am\u00e9liorer la fonction achat(habit)
en y incluant un test pour prendre en compte les nouveaux habits.
Exemple d'utilisation :
>>> dressing\n{'pantalons': 3, 'pulls': 4, 'tee-shirts': 8}\n>>> achat('pulls')\n>>> achat('chapeau')\n>>> dressing\n{'pantalons': 3, 'pulls': 5, 'tee-shirts': 8, 'chapeau': 1}\n
Correction def achat(habit):\n if habit in dressing:\n dressing[habit] += 1\n else:\n dressing[habit] = 1\n
Exercice 4
On consid\u00e8re la liste suivante :
lst = ['Samuel', 'Pauline', 'Lina', 'Lina', 'Louis', 'Wa\u00ebll', 'Cl\u00e9ment', 'Khaled', 'Alexandre', 'Elie', 'Khaled', 'Khaled', 'Armand', 'Lina', 'Louis', 'Lina', 'Lina', 'Elie', 'Jules', 'Louis', 'Cl\u00e9ment', 'Khaled', 'Jules-Evan', 'Lina', 'Jules', 'Hadzo', 'Zoran', 'Cl\u00e9ment', 'Armand', 'Louis', 'Elie', 'Lina', 'Alexandre', 'Khaled', 'Iris', 'Gianni', 'Gianni', 'Pauline', 'Gianni', 'Elie', 'Iris', 'Armand', 'Louis', 'Cl\u00e9ment', 'Pauline', 'Zoran', 'Khaled', 'Zoran', 'Elie', 'Wa\u00ebll', 'Pauline', 'Lina', 'Alexandre', 'Khaled', 'Mehmet', 'Khaled', 'Hadzo', 'Zoran', 'Gianni', 'Jules', 'Paul', 'Pauline', 'Cl\u00e9ment', 'Alexandre', 'Iris', 'Khaled', 'Gianni', 'Elie', 'Jules', 'Khaled', 'Louis', 'Jules-Evan', 'Jules-Evan', 'Louis', 'Gianni', 'Elie', 'Cl\u00e9ment', 'Khaled', 'Louis', 'Louis', 'Emrys', 'Jules', 'Pauline', 'Armand', 'Elie', 'Jules', 'Elie', 'Khaled', 'Cl\u00e9ment', 'Louis', 'Khaled', 'Emrys', 'Samuel', 'Hadzo', 'Elie', 'Cl\u00e9ment', 'Alexandre', 'Hadzo', 'Lina', 'Iris', 'Alexandre', 'Mehmet', 'Elie', 'Jules', 'Khaled', 'Pauline', 'Samuel', 'Armand', 'Mehmet', 'Cl\u00e9ment', 'Jules', 'Armand', 'Mehmet', 'Lina', 'Armand', 'Cl\u00e9ment', 'Hadzo', 'Cl\u00e9ment', 'Emrys', 'Samuel', 'Zoran', 'Zoran', 'Zoran', 'Mehmet', 'Jules', 'Khaled', 'Khaled', 'Elie', 'Armand', 'Jules', 'Alexandre', 'Alexandre', 'Louis', 'Armand', 'Zoran', 'Iris', 'Cl\u00e9ment', 'Mehmet', 'Armand', 'Armand', 'Khaled', 'Lina', 'Lina', 'Jules', 'Louis', 'Paul', 'Pauline', 'Pauline', 'Pauline', 'Khaled', 'Lina', 'Wa\u00ebll', 'Zoran', 'Hadzo', 'Emrys', 'Gianni', 'Jules', 'Samuel', 'Gianni', 'Pauline', 'Wa\u00ebll', 'Cl\u00e9ment', 'Khaled', 'Jules', 'Jules', 'Louis', 'Zoran', 'Alexandre', 'Iris', 'Paul', 'Emrys', 'Armand', 'Wa\u00ebll', 'Zoran', 'Jules', 'Lina', 'Elie', 'Paul', 'Elie', 'Armand', 'Jules-Evan', 'Zoran', 'Alexandre', 'Zoran', 'Elie', 'Elie', 'Elie', 'Lina', 'Armand', 'Louis', 'Zoran', 'Lina', 'Armand', 'Alexandre', 'Samuel', 'Iris', 'Zoran', 'Paul', 'Pauline', 'Jules', 'Armand', 'Jules', 'Iris', 'Iris', 'Jules', 'Alexandre', 'Jules-Evan', 'Jules', 'Iris', 'Iris', 'Armand', 'Lina', 'Pauline', 'Zoran', 'Zoran', 'Pauline', 'Mehmet']\n
Cr\u00e9er un dictionnaire qui associera \u00e0 chaque pr\u00e9nom son nombre d'occurrences dans la liste.
Correction occurrence = {}\n\nfor prenom in lst:\n if prenom in occurrence:\n occurrence[prenom] += 1\n else:\n occurrence[prenom] = 1\n
Exercice 5
On consid\u00e8re la liste suivante : lst = ['5717', '1133', '5545', '4031', '6398', '2734', '3070', '1346', '7849', '7288', '7587', '6217', '8240', '5733', '6466', '7972', '7341', '6616', '5061', '2441', '2571', '4496', '4831', '5395', '8584', '3033', '6266', '2452', '6909', '3021', '5404', '3799', '5053', '8096', '2488', '8519', '6896', '7300', '5914', '7464', '5068', '1386', '9898', '8313', '1072', '1441', '7333', '5691', '6987', '5255']
Quel est le chiffre qui revient le plus fr\u00e9quemment dans cette liste ?
Correction lst = ['5717', '1133', '5545', '4031', '6398', '2734', '3070', '1346', '7849', '7288', '7587', '6217', '8240', '5733', '6466', '7972', '7341', '6616', '5061', '2441', '2571', '4496', '4831', '5395', '8584', '3033', '6266', '2452', '6909', '3021', '5404', '3799', '5053', '8096', '2488', '8519', '6896', '7300', '5914', '7464', '5068', '1386', '9898', '8313', '1072', '1441', '7333', '5691', '6987', '5255']\n\nocc = {}\nmaxi = 0\nfor nombre in lst:\n for chiffre in nombre:\n if chiffre in occ:\n occ[chiffre] += 1\n else:\n occ[chiffre] = 1\n if occ[chiffre] > maxi:\n maxi = occ[chiffre]\n chiffre_max = chiffre\n\nprint(chiffre_max, 'est le chiffre le plus fr\u00e9quent')\nprint('il apparait', maxi, 'fois')\n
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/","title":"2.4 Repr\u00e9sentation d'un entier positif dans diff\u00e9rentes bases","text":"Hormis la base 10, deux bases sont utilis\u00e9es en informatique :
- la base 2 (le syst\u00e8me binaire)
- la base 16 (le syst\u00e8me hexad\u00e9cimal)
Dans toute la suite, la base dans laquelle le nombre est \u00e9crit sera pr\u00e9cis\u00e9e en indice. Exemple : \\(13_{10}=1101_2=\\rm{D}_{16}\\)
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#1-le-systeme-binaire","title":"1. Le syst\u00e8me binaire","text":"En base 2, on ne dispose que des chiffres 0
et 1
. Le syst\u00e8me binaire est un syst\u00e8me de num\u00e9ration de position (comme le syst\u00e8me d\u00e9cimal, hexad\u00e9cimal... mais pas comme le syst\u00e8me romain). \u00c0 chaque rang correspond une puissance de 2.
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#11-du-binaire-vers-le-decimal","title":"1.1 Du binaire vers le d\u00e9cimal :","text":"... 128 64 32 16 8 4 2 1 ... \\(2^7\\) \\(2^6\\) \\(2^5\\) \\(2^4\\) \\(2^3\\) \\(2^2\\) \\(2^1\\) \\(2^0\\) ... 1 1 0 1 0 0 1 0 \\(11010010_2=1 \\times 2^7+ 1 \\times 2^6+0 \\times 2^5+1 \\times 2^4+0 \\times 2^3+0 \\times 2^2+1 \\times 2^1+0 \\times 2^0=128+64+32+2=210_{10}\\)
Le nombre binaire 11010010 correspond donc au nombre d\u00e9cimal 210.
Code Python
En Python, on peut utiliser la fonction int(\"nombre\", base)
.
>>> int(\"11010010\", 2)\n210\n
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#12-du-decimal-vers-le-binaire","title":"1.2 Du d\u00e9cimal vers le binaire :","text":"Principe : dans chaque nombre d\u00e9cimal, il existe une plus grande puissance de 2 qui est inf\u00e9rieure au nombre.
Par exemple, dans 243, il y a 128. Donc \\(243=128 + (115)\\) \\(243=128+64+(51)\\) \\(243=128+64+32+(19)\\) \\(243=128+64+32+16+(3)\\) \\(243=128+64+32+16+2+1\\) \\(243=1 \\times 2^7+ 1 \\times 2^6+1 \\times 2^5+1 \\times 2^4+0 \\times 2^3+0 \\times 2^2+1 \\times 2^1+1 \\times 2^0\\)
Donc \\(243_{10}=11110011_2\\)
M\u00e9thode des divisions successives
Code Python
En Python, on peut utiliser la fonction bin(nombre)
. Elle renvoie une cha\u00eene de caract\u00e8re o\u00f9 le nombre binaire est pr\u00e9c\u00e9d\u00e9 de '0b'
.
>>> bin(243)\n'0b11110011'\n
Exercice 1
\u00c9nonc\u00e9Correction Quelle est la valeur maximale d'un octet (un octet = 8 chiffres binaires) ?
\\(11111111_2=255\\). On retrouve ce nombre comme \u00e9tant la valeur maximale d'une composante de couleur dans le codage RGB, ce qui signifie que chaque composante est cod\u00e9e sur un octet.
Exercice 2
\u00c9nonc\u00e9Correction Cr\u00e9er une fonction binaire(n)
qui renvoie l'\u00e9criture binaire de n
, en utilisant les divisions successives.
def restes_successifs(n):\n ''' renvoie la liste des restes successifs lors des divisions de n par 2'''\n restes = []\n while n != 0 :\n restes.append(n % 2)\n n = n // 2\n return restes\n\ndef binaire(n) :\n ''' recompose le mot binaire en mettant dans l'ordre les restes successifs'''\n liste = restes_successifs(n)\n liste.reverse() #permet d'inverser l'ordre des \u00e9l\u00e9ment d'une liste\n mot = \"\"\n for k in liste :\n mot += str(k)\n return mot\n
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#2-le-systeme-hexadecimal","title":"2. Le syst\u00e8me hexad\u00e9cimal","text":"L'inconv\u00e9nient essentiel du syst\u00e8me binaire est la longueur de l'\u00e9criture des nombres qu'il g\u00e9n\u00e8re. Pour cette raison, le syst\u00e8me hexad\u00e9cimal, ou syst\u00e8me de base 16 est tr\u00e8s souvent employ\u00e9.
-
Pour \u00e9crire en base 2, il faut 2 chiffres diff\u00e9rents : le 0 et le 1.
-
Pour \u00e9crire en base 10, il faut 10 chiffres diff\u00e9rents: 0,1,2,3,4,5,6,7,8,9.
-
Pour \u00e9crire en base 16, il faut donc 16 chiffres diff\u00e9rents : 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F.
On a donc la correspondance :
- A repr\u00e9sente 10
- B repr\u00e9sente 11
- C repr\u00e9sente 12
- D repr\u00e9sente 13
- E repr\u00e9sente 14
- F repr\u00e9sente 15
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#21-de-lhexadecimal-vers-le-decimal","title":"2.1 De l'hexad\u00e9cimal vers le d\u00e9cimal :","text":"256 16 1 \\(16^2\\) \\(16^1\\) \\(16^0\\) 1 D 2 \\(\\rm{1D2}_{16}=1 \\times 16^2+ 13 \\times 16^1+2 \\times 16^0=256+208+2=466_{10}\\)
Le nombre hexad\u00e9cimal 1D2
correspond donc au nombre d\u00e9cimal 466.
En pratique, l'hexad\u00e9cimal est surtout utilis\u00e9 pour sa capacit\u00e9 \u00e0 repr\u00e9senter la valeur de n'importe quel octet sur 2 chiffres (\"chiffres\" \u00e9tant \u00e0 prendre au sens large = chiffres ou lettres !).
Exercice 3
\u00c9nonc\u00e9Correction - Donner la valeur des octets
FF
, 3A
, B2
. - Expliquer pourquoi la couleur RGB (138,255,51) a pour code html
#8AFF33
. - Quelle est la couleur
html
du blanc ?
- FF = 255 ; 3A = 58 ; B2 = 178
- 138 a pour code hexa 8A, 255 a pour code hexa 255, 51 a pour code hexa 33.
- #FFFFFF
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#22-en-python","title":"2.2 En python :","text":""},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#221-pour-passer-du-decimal-a-lhexadecimal","title":"2.2.1 Pour passer du d\u00e9cimal \u00e0 l'hexad\u00e9cimal :","text":"On peut utiliser la fonction hex(nombre)
. Elle renvoie une cha\u00eene de caract\u00e8re o\u00f9 le nombre hexad\u00e9cimal est pr\u00e9c\u00e9d\u00e9 de '0x'
.
>>> hex(125)\n'0x7d'\n
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#222-pour-passer-de-lhexadecimal-au-decimal","title":"2.2.2 Pour passer de l'hexad\u00e9cimal au d\u00e9cimal :","text":"On peut utiliser la fonction int(\"nombre\",base)
.
>>> int(\"FF\", 16)\n 255\n
"},{"location":"T2_Representation_des_donnees/2.4_Bases/cours/#3-du-binaire-inattendu","title":"3. Du binaire inattendu","text":"Le message secret de Perseverance
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/","title":"Les op\u00e9rateurs bool\u00e9ens","text":""},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#1-reperes-historiques","title":"1. Rep\u00e8res historiques","text":"En 1847, le britannique George BOOLE inventa un formalisme permettant d'\u00e9crire des raisonnements logiques : l'alg\u00e8bre de Boole. La notion m\u00eame d'informatique n'existait pas \u00e0 l'\u00e9poque, m\u00eame si les calculs \u00e9taient d\u00e9j\u00e0 automatis\u00e9s (penser \u00e0 la Pascaline de 1642).
Bien plus tard, en 1938, les travaux de l'am\u00e9ricain Claude SHANNON prouva que des circuits \u00e9lectriques peuvent r\u00e9soudre tous les probl\u00e8mes que l'alg\u00e8bre de Boole peut elle-m\u00eame r\u00e9soudre. Pendant la deuxi\u00e8me guerre mondiale, les travaux d'Alan TURING puis de John VON NEUMANN poseront d\u00e9finitivement les bases de l'informatique moderne.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#2-algebre-de-boole","title":"2. Alg\u00e8bre de Boole","text":"L'alg\u00e8bre de Boole d\u00e9finit des op\u00e9rations dans un ensemble qui ne contient que deux \u00e9l\u00e9ments not\u00e9s 0 et 1, ou bien FAUX et VRAI ,ou encore False et True (en Python)
Les op\u00e9rations fondamentales sont :
- la conjonction (\"ET\")
- la disjonction (\"OU\")
- la n\u00e9gation (\"NON\").
Dans toute la suite, x
et y
d\u00e9signeront des Bool\u00e9ens (\u00e9l\u00e9ments d'une alg\u00e8bre de Boole) quelconques, F
d\u00e9signera FAUX et V
d\u00e9signera VRAI.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#21-conjonction-and","title":"2.1 Conjonction (AND)","text":" - symbole usuel : & (appel\u00e9 esperluette en fran\u00e7ais et ampersand en anglais)
- fran\u00e7ais : ET
- anglais (et Python) :
and
- notation logique : \\(\\wedge\\)
- notation math\u00e9matique :
.
C'est l'op\u00e9ration d\u00e9finie par:
x & F = F
x & V = x
Puisque l'alg\u00e8bre de Boole ne contient que deux \u00e9l\u00e9ments, on peut \u00e9tudier tous les cas possibles et les regrouper dans un tableau appel\u00e9 table de v\u00e9rit\u00e9:
Table de v\u00e9rit\u00e9 de AND
x
y
x & y
F F F F V F V F F V V V On repr\u00e9sente souvent les op\u00e9rateurs bool\u00e9ens \u00e0 l'aide de portes logiques:
Notation usuelle en \u00e9lectronique : \\(Q=A \\wedge B\\)
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#exemples-en-python","title":"Exemples en Python","text":">>> n = 20\n>>> (n % 10 == 0) and (n % 7 == 0)\nFalse\n>>> (n % 4 == 0) and (n % 5 == 0)\nTrue\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#levaluation-paresseuse","title":"L'\u00e9valuation paresseuse","text":"Pouvez-vous pr\u00e9voir le r\u00e9sultat du code ci-dessous ?
>>> (n % 4 == 0) and (n % 0 == 0)\n ---------------------------------------------------------------------------\n\n ZeroDivisionError Traceback (most recent call last)\n\n <ipython-input-3-d8a98dcba9be> in <module>\n ----> 1 (n % 4 == 0) and (n % 0 == 0)\n\n\n ZeroDivisionError: integer division or modulo by zero\n
\u00c9videmment, la division par 0 provoque une erreur. Mais observez maintenant ce code :
>>> (n % 7 == 0) and (n % 0 == 0)\nFalse\n
On appelle \u00e9valuation paresseuse le fait que l'interpr\u00e9teur Python s'arr\u00eate d\u00e8s que sa d\u00e9cision est prise : comme le premier bool\u00e9en vaut False et que la conjonction and
est appel\u00e9e, il n'est pas n\u00e9cessaire d'\u00e9valuer le deuxi\u00e8me bool\u00e9en.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#22-disjonction-or","title":"2.2 Disjonction (OR)","text":" - symbole usuel : | appel\u00e9 pipe en anglais
- fran\u00e7ais : OU
- anglais (et Python) :
or
- notation logique : \\(\\vee\\)
- notation math\u00e9matique : \\(+\\)
C'est l'op\u00e9ration d\u00e9finie par:
C'est l'op\u00e9ration d\u00e9finie par:
x | V = V
x | F = x
On en d\u00e9duit la table suivante:
Table de v\u00e9rit\u00e9 de OR
x
y
x or y
F F F F V V V F V V V V Notation usuelle en \u00e9lectronique : \\(Q=A \\vee B\\)
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#exemples-en-python_1","title":"Exemples en Python","text":">>> n = 20\n>>> (n % 10 == 0) or (n % 7 == 0)\nTrue\n>>> (n % 4 == 0) or (n % 5 == 0)\nTrue\n>>> (n % 7 == 0) or (n % 3 == 0)\nFalse\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#levaluation-paresseuse-retour","title":"L'\u00e9valuation paresseuse (retour)","text":"Pouvez-vous pr\u00e9voir le r\u00e9sultat du code ci-dessous ?
>>> (n % 5 == 0) or (n % 0 == 0)\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#23-negation-not","title":"2.3 N\u00e9gation (NOT)","text":" - symbole usuel : ~
- fran\u00e7ais : NON
- anglais (et Python) :
not
- notation logique : \\(\\neg\\)
- notation math\u00e9matique : \\(\\overline{x}\\)
C'est l'op\u00e9ration d\u00e9finie par:
~V = F
~F = V
On en d\u00e9duit la table suivante:
Table de v\u00e9rit\u00e9 de NOT
x
~x
F V V F Notation usuelle en \u00e9lectronique : \\(Q=\\neg A\\)
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#exemples-en-python_2","title":"Exemples en Python","text":">>> n = 20\n>>> not(n % 10 == 0)\nFalse\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#24-exercice","title":"2.4 Exercice","text":"Exercice 1
Comprendre ce m\u00e8me :
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#25-exercice","title":"2.5 Exercice","text":"Exercice 2
Ouvrir le simulateur de circuits et cr\u00e9er pour chaque op\u00e9ration AND, OR, NOT un circuit \u00e9lectrique illustrant ses propri\u00e9t\u00e9s.
Exemple (inint\u00e9ressant) de circuit :
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#3-fonctions-composees","title":"3. Fonctions compos\u00e9es","text":""},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#31-disjonction-exclusive-xor","title":"3.1 Disjonction exclusive XOR","text":"(en fran\u00e7ais OU EXCLUSIF)
x ^ y = (x & ~y) | (~x & y)
Table de v\u00e9rit\u00e9 de XOR
x
y
x ^ y
F F F F V V V F V V V F Le XOR joue un r\u00f4le fondamental en cryptographie car il poss\u00e8de une propri\u00e9t\u00e9 tr\u00e8s int\u00e9ressante : \\((x\\wedge y)\\wedge y=x\\)
Si \\(x\\) est un message et \\(y\\) une cl\u00e9 de chiffrage, alors \\(x\\wedge y\\) est le message chiffr\u00e9. Mais en refaisant un XOR du message chiffr\u00e9 avec la cl\u00e9 \\(y\\), on retrouve donc le message \\(x\\) initial.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#32-fonction-non-et-nand","title":"3.2 Fonction Non Et (NAND)","text":"x \u2191 y = ~(x & y)
Table de v\u00e9rit\u00e9 de NAND
x
y
x \u2191 y
F F V F V V V F V V V F "},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#33-fonction-non-ou-nor","title":"3.3 Fonction Non Ou (NOR)","text":"x \u2193 y = ~(x & y)
Table de v\u00e9rit\u00e9 de NOR
x
y
x \u2193 y
F F V F V F V F F V V F Il est temps de se reposer un peu et d'admirer cette vid\u00e9o :
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#remarque","title":"Remarque :","text":"Les fonctions NAND ET NOR sont dites universelles : chacune d'entre elles peut g\u00e9n\u00e9rer l'int\u00e9gralit\u00e9 des autres portes logiques. Il est donc possible de coder toutes les op\u00e9rations uniquement avec des NAND (ou uniquement avec des NOR).
Exercice 3
Nous allons r\u00e9utiliser le simulateur de circuits mais en n'utilisant QUE DES PORTES NAND.
Q1. R\u00e9aliser la porte AND (avec que des NAND...)
Correction Q2. R\u00e9aliser la porte OR (avec que des NAND...)
Correction Vous pouvez trouver d'autres renseigements sur Wikipedia.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#34-exercice-4","title":"3.4 Exercice 4","text":"Exercice 4
\u00c9nonc\u00e9Correction Effectuer les op\u00e9rations suivantes.
1011011\n& 1010101\n----------\n\n\n 1011011\n| 1010101\n----------\n\n\n 1011011\n^ 1010101\n----------\n
1011011\n&1010101\n----------\n 1010001\n\n 1011011\n|1010101\n----------\n 1011111\n\n 1011011\n^1010101\n----------\n 0001110\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#35-calculs-en-python","title":"3.5 Calculs en Python","text":"les op\u00e9rateurs &
, |
et ^
sont utilisables directement en Python
# calcul A\n>>> 12 & 7\n4\n
# calcul B\n>>> 12 | 7\n15\n
# calcul C\n>>> 12 ^ 5\n9\n
Pour comprendre ces r\u00e9sultats, il faut travailler en binaire. Voici les m\u00eames calculs :
# calcul A\n>>> bin(0b1100 & 0b111)\n '0b100'\n
# calcul B\n>>> bin(0b1100 | 0b111)\n '0b1111'\n
# calcul C\n>>> bin(0b1100 ^ 0b111)\n '0b1011'\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#exercice-5-cryptographie","title":"Exercice 5 : Cryptographie","text":"Exercice 5
On souhaite chiffrer (chiffrer est le mot utilis\u00e9 en cryptographie pour crypter) le mot \"BONJOUR\"
avec la cl\u00e9 \"MAURIAC\"
. Le chiffrement retenu est un chiffrement par XOR, ce qui signifie qu'on va effectuer un XOR entre les deux nombres associ\u00e9s aux lettres.
Exemple :
- la lettre
'B'
va \u00eatre chiffr\u00e9e gr\u00e2ce au 'M'
. - Le code ASCII de
'B'
est 66. (on le sait car ord('B')
renvoie 66 ) - Le code ASCII de
'M'
est 77. (on le sait car ord('M')
renvoie 77 ) - 66 ^ 77 vaut 15.
- Le \u00abcaract\u00e8re\u00bb associ\u00e9 \u00e0 15 est
'\\x0f'
(on le sait car chr(15)
renvoie '\\x0f'
)
Le premier caract\u00e8re du mot chiffr\u00e9 sera donc '\\x0f'
Q1. \u00c9crire une fonction chiffre
qui prendra en param\u00e8tre un mot mot_clair
et un mot de passe cle
de m\u00eame taille que mot_clair
et qui renvoie la cha\u00eene de caract\u00e8res obtenue en XORant mot_clair
avec cle
.
Correction def chiffre(mot_clair, cle):\n mot_chiffre = ''\n for i in range(len(mot_clair)):\n code = ord(mot_clair[i]) ^ ord(cle[i])\n mot_chiffre += chr(code)\n return mot_chiffre\n
Q2. Chiffrer le mot \"BONJOUR\"
avec la cl\u00e9 \"MAURIAC\"
.
Correction >>> chiffre('BONJOUR', 'MAURIAC')\n'\u000f\u000e\u001b\u0018\u0006\u0014\u0011'\n
Q3. Reprendre la cha\u00eene de caract\u00e8res pr\u00e9c\u00e9demment obtenue et la rechiffrer \u00e0 nouveau avec la cl\u00e9 \"MAURIAC\"
. Que constate-t-on ? Etait-ce pr\u00e9visible ?
Correction >>> chiffre('\u000f\u000e\u001b\u0018\u0006\u0014\u0011', 'MAURIAC')\n'BONJOUR'\n
C'\u00e9tait pr\u00e9visible car c'est une propri\u00e9t\u00e9 remarquable du XOR : (a^b)^b = a
Q4. R\u00e9soudre le Pyd\u00e9fi La cl\u00e9 endommag\u00e9e
Correction msg = [255, 87, 255, 93, 254, 112, 98, 239, 146, 205, 59, 198, 173, 65, 50, 174, 200, 218, 189, 130, 96, 4, 57, 173, 143, 8, 175, 19, 2, 109, 216, 2, 65, 14, 36, 206, 32, 157, 181, 22, 248, 119, 153, 204, 8, 137, 7, 203, 0, 89, 251, 16, 79, 214, 52, 15, 249, 42, 115, 67, 241, 175, 160, 65, 217, 40, 36, 68, 205, 234, 14, 21, 73, 172, 70, 81, 37, 83, 1, 113, 180, 8, 194, 90, 46, 239, 194, 122, 244, 15, 24, 14, 86, 72, 43, 246, 241, 24, 182, 91, 220, 48, 92, 147, 16, 82, 139, 169, 104, 236, 88, 106, 192, 76, 23, 72, 233, 130, 92, 67, 235, 199, 149, 108, 180, 217, 156, 175, 175, 234, 177, 145, 242, 17, 245, 94, 113, 16, 88, 170, 71, 226, 13, 122, 189, 56, 44, 48, 185, 159, 73, 160, 84, 147, 231, 21, 86, 81, 238, 196, 137, 133, 222, 174, 208, 9, 105, 83, 80, 60, 49, 191, 19, 220, 231, 196, 172, 10, 72, 237, 211, 163, 23, 119, 247, 37, 177, 3, 246, 136, 82, 222, 93, 245, 202, 24, 164, 177, 167, 174, 203, 247, 101, 201, 32, 99, 83, 189, 241, 46, 208, 125, 167, 111, 217, 84, 120, 5, 158, 50, 180, 129, 202, 116, 149, 226, 195, 6, 56, 221, 54, 1, 233, 119, 186, 113, 87, 194, 240, 244, 29, 195, 251, 186, 54, 175, 66, 8, 193, 189, 143, 151, 101, 153, 25, 100, 151, 75, 71, 176, 55, 183, 66, 28, 119, 90, 142, 60, 100, 170, 46, 231, 149, 131, 139, 249, 247, 209, 60, 206, 40, 121, 175, 78, 246, 189, 88, 33, 46, 147, 11, 30, 65, 208, 131, 163, 37, 44, 77, 220, 148, 101, 101, 167, 34, 68, 179, 117, 200, 234, 91, 170, 134, 203, 240, 164, 71, 220, 122, 77, 249, 76, 39, 145, 217, 151, 36, 96, 249, 61, 105, 52, 59, 231, 86, 166, 88, 42, 134, 182, 74, 166, 106, 36, 194, 160, 92, 69, 84, 74, 15, 217, 189, 28, 89, 41, 212, 60, 49, 30, 225, 95, 196, 36, 199, 0, 126, 127, 251, 23, 76, 182, 66, 213, 119, 28, 187, 173, 239, 27, 97, 196, 17, 95, 124, 4, 95, 222, 191, 238, 152, 142, 208, 122, 139, 135, 12, 212, 96, 4, 126, 210, 7, 71, 225, 202, 106, 79, 206, 156, 216, 22, 163, 159, 49, 248, 120, 100, 2, 88, 41, 145, 234, 38, 196, 189, 77, 247, 71, 172, 109, 215, 134, 37, 145, 236, 6, 198, 217, 89, 94, 98, 158, 165, 99, 17, 99, 246, 90, 161, 76, 159, 194, 75, 208, 234, 18, 51, 205, 227, 167, 199, 1, 128, 68, 112, 25, 10, 66, 202, 255, 243, 163, 16, 3, 72, 43, 143, 76, 241, 108, 239, 216, 30, 236, 224, 7, 1, 222, 6, 244, 70, 151, 110, 175, 49, 153, 253, 241, 160, 117, 232, 42, 68, 77, 253, 64, 142, 11, 88, 234, 251, 20, 1, 239, 39, 157, 181, 106, 47, 180, 26, 227, 121, 164, 183, 124, 180, 238, 42, 89, 75, 19, 244, 245, 116, 82, 124, 85, 12, 7, 22, 1, 25, 118, 126, 36, 209, 22, 226, 252, 6, 72, 26, 101, 127, 23, 124, 151, 185, 184, 203, 231, 56, 26, 128, 110, 216, 94, 202, 174, 211, 210, 125, 145, 220, 185, 43, 204, 215, 210, 224, 54, 111, 217, 202, 47, 31, 224, 46, 177, 165, 31, 68, 127, 206, 99, 11, 213, 192, 46, 222, 34, 115, 16, 73, 131, 221, 218, 180, 4, 249, 207, 74, 155, 84, 87, 242, 58, 133, 248, 61, 205, 9, 158, 226, 21, 216, 80, 154, 153, 79, 98, 105, 190, 56, 134, 187, 37, 10, 224, 82, 97, 126, 246, 24, 190, 173, 21, 62, 236, 10, 180, 242, 144, 244, 145, 117, 67, 62, 246, 57, 96, 192, 92, 126, 27, 67, 168, 223, 222, 247, 236, 224, 240, 243, 100, 150, 193, 79, 223, 143, 208, 133, 125, 80, 107, 106, 245, 118, 248, 79, 199, 116, 190, 54, 236, 81, 106, 244, 212, 241, 16, 179, 245, 238, 185, 89, 199, 175, 54, 218, 86, 84, 184, 177, 174, 92, 171, 176, 43, 149, 46, 202, 151, 181, 98, 86, 18, 58, 46, 163, 117, 33, 149, 87, 248, 235, 0, 181, 136, 16, 188, 110, 20, 108, 213, 104, 165, 45, 86, 19, 208, 48, 153, 186, 163, 221, 165, 39, 70, 200, 98, 235, 68, 167, 252, 42, 102, 52, 228, 210, 187, 151, 178, 242, 221, 44, 143, 79, 230, 159, 164, 253, 25, 90, 24, 182, 142, 122, 140, 115, 45, 182, 104, 132, 22, 109, 55, 205, 185, 27, 27, 77, 224, 184, 199, 121, 21, 250, 254, 78, 158, 215, 245, 187, 143, 211, 110, 228, 18, 36, 68, 168, 100, 126, 85, 238, 208, 98, 241, 34, 235, 254, 184, 39, 182, 239, 34, 242, 232, 6, 187, 18, 113, 176, 228, 2, 103, 135, 52, 28, 183, 9, 19, 142, 156, 242, 21, 253, 48, 21, 67, 138, 207, 131, 72, 191, 198, 107, 233, 202, 227, 108, 186, 124, 165, 23, 247]\n\ncle = [111, 22, 12, 177, 12, 199, 78, 21, 175, 181, 64, 73, 174, 101, 212, 225, 63, 106, 248, 91, 175, 48, 247, 245, 51, 250, 160, 111, 23, 4, 70, 167, 177, 49, 17, 53, 17, 73, 85, 89]\n\ndef decrypt(dec):\n l = ''\n for i in range(len(cle)):\n c = msg[i + dec] ^ cle[i]\n l = l + chr(c)\n return l\n\nfor i in range(0, len(msg)-len(cle)):\n print(decrypt(i))\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/cours/#complement-mathematique-proprietes-des-operateurs-logiques","title":"Compl\u00e9ment math\u00e9matique: propri\u00e9t\u00e9s des op\u00e9rateurs logiques","text":"Les propri\u00e9t\u00e9s suivantes sont facilement d\u00e9montrables \u00e0 l'aide de tables de v\u00e9rit\u00e9s: (source : G.Connan)
Toutes ces lois sont ais\u00e9ment compr\u00e9hensibles si on les transpose en math\u00e9matiques :
- & \u00e9quivaut \u00e0 \\(\\times\\)
- \\(|\\) \u00e9quivaut \u00e0 \\(+\\)
- \\(\\neg\\) \u00e9quivaut \u00e0 \\(-\\)
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/","title":"\u00c9nigme","text":"Vous pouvez faire cette \u00e9nigme sur Thonny (pensez \u00e0 bien travailler dans le dossier qui contient vos deux images) ou bien sur Capytale https://capytale2.ac-paris.fr/web/c/5912-1397991
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#1-a-la-recherche-du-personnage-mystere","title":"1. \u00c0 la recherche du personnage myst\u00e8re","text":"Vous avez trouv\u00e9 une image bien \u00e9trange :
Un visage semble se deviner derri\u00e8re un champ de fleurs... mais quel est ce visage ?
L'image du champ de fleurs ne vous est pas inconnue, d'ailleurs en cherchant bien vous l'avez retrouv\u00e9e dans vos dossiers :
On dirait que le personnage-myst\u00e8re a voulu se fondre dans le champ de fleurs...
XORez-vous d\u00e9couvrir qui est ce personnage-myst\u00e8re ?
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#2-aide-pour-la-manipulation-dimages-et-lextraction-de-pixels","title":"2. Aide pour la manipulation d'images et l'extraction de pixels","text":""},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#21-code-de-demarrage","title":"2.1 Code de d\u00e9marrage","text":"from PIL import Image\n\nimg_myst = Image.open(\"mystere.bmp\")\nimg_mask = Image.open(\"mask.jpg\")\n\nlargeur = img_myst.width\nhauteur = img_myst.height\n\nimg_new = Image.new('RGB', img_myst.size)\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#22-manipulation-de-pixels","title":"2.2 Manipulation de pixels","text":"Les expressions ci-dessous sont \u00e0 tester pour en comprendre le fonctionnement.
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#221-recuperer-le-code-rgb-un-pixel","title":"2.2.1 R\u00e9cup\u00e9rer le code RGB
un pixel","text":">>> img_myst.getpixel((125, 80))\n(54, 217, 174)\n
Le pixel de coordonn\u00e9es (125, 80) a pour composantes RGB (54, 217, 174)."},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#222-modifier-la-couleur-dun-pixel","title":"2.2.2 Modifier la couleur d'un pixel","text":">>> img_new.putpixel((30,70), (255,0,0))\n>>> \n
Le pixel de coordonn\u00e9es (30, 70) est maintenant un pixel rouge."},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#223-afficher-une-image","title":"2.2.3 Afficher une image","text":">>> img_mask.show()\n
"},{"location":"T2_Representation_des_donnees/2.5_Booleens/enigme/#224-sauvegarder-une-image","title":"2.2.4 Sauvegarder une image","text":">>> img_new.save(\"solution.png\")\n
Correction from PIL import Image\n\nimg_myst = Image.open('mystere.bmp')\nimg_mask = Image.open('mask.jpg')\n\nlargeur = img_myst.width\nhauteur = img_myst.height\n\nimg_new = Image.new('RGB', img_myst.size)\n\nfor x in range(largeur):\n for y in range(hauteur):\n pix_myst = img_myst.getpixel((x, y))\n pix_mask = img_mask.getpixel((x, y))\n new_pix = (pix_myst[0] ^ pix_mask[0], pix_myst[1] ^ pix_mask[1], pix_myst[2] ^ pix_mask[2])\n img_new.putpixel((x,y), new_pix)\n\nimg_new.show() \n
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/","title":"2.6 Codage des caract\u00e8res","text":"Tout pour comprendre et \u00c3\u00a9viter les erreurs d'encodage
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#1-au-commencement-etait-lascii","title":"1. Au commencement \u00e9tait l'ASCII","text":"pour American Standard Code for Information Interchange, cr\u00e9\u00e9 en 1960 aux \u00c9tats-Unis.
En ASCII, 127 \u00abpoints de code\u00bb (nombres associ\u00e9s aux caract\u00e8res) sont disponibles. Les caract\u00e8res sont donc cod\u00e9s sur 7 bits.
Exercice
\u00c9nonc\u00e9Aide D\u00e9coder l'expression suivante, \u00e9crite en ASCII :
1101100 1100101 1110011 100000 1001110 1010011 1001001 100000 1100011 100111 1100101 1110011 1110100 100000 1101100 1100101 1110011 100000 1101101 1100101 1101001 1101100 1101100 1100101 1110101 1110010 1110011
- la fonction
split(\" \")
permet de d\u00e9composer une chaine de caract\u00e8res en une liste, en se servant de l'espace \" \"
comme caract\u00e8re s\u00e9parateur. int(\"1101100\",2)
permet de r\u00e9cup\u00e9rer facilement la valeur en base 10 du nombre binaire 1101100
.
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#2-et-le-reste-du-monde","title":"2. Et le reste du monde ?","text":"Lorsque d'autres personnes que des americains ou des anglais ont voulu s'\u00e9changer des donn\u00e9es faisant intervenir du texte, certains caract\u00e8res (\u00e9, \u00e8, \u00e0, \u00f1, \u00d8, \u00d6, \u03b2, \u6f22...) \u00e9taient manquants. Les 127 caract\u00e8res de l'ASCII \u00e9taient largement insuffisants. Il a donc \u00e9t\u00e9 d\u00e9cid\u00e9 de passer \u00e0... 256 caract\u00e8res ! Il suffisait pour cela de coder les caract\u00e8res non plus sur 7 bits mais sur 8 bits.
Ainsi naqu\u00eet, apr\u00e8s de nombreuses modifications successives (la derni\u00e8re en date rajoutant par exemple le symbole \u20ac), la c\u00e9l\u00e8bre table ISO 8859-15, dite aussi Latin-9 :
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#utilisation","title":"Utilisation :","text":"Les codes sont donn\u00e9s en hexad\u00e9cimal :
- le caract\u00e8re \u20ac correspond au code hexad\u00e9cimal A4, donc au nombre d\u00e9cimal 164.
- le caract\u00e8re A correspond au code hexad\u00e9cimal 41, donc au nombre d\u00e9cimal 65.
65... comme en ASCII ! Oui, la (seule) bonne id\u00e9e aura \u00e9t\u00e9 d'inclure les caract\u00e8res ASCII avec leur m\u00eame code, ce qui rendait cette nouvelle norme r\u00e9tro-compatible.
Exemple :
Le fichier test.txt
contient un texte enregistr\u00e9 avec l'encodage Latin-9. Ce fichier est ensuite ouvert avec un \u00e9diteur hexad\u00e9cimal, qui permet d'observer la valeur des octets qui composent le fichier. (Comme le fichier est un .txt, le fichier ne contient que les donn\u00e9es et rien d'autre.)
Parfait, mais comment font les Grecs pour \u00e9crire leur alphabet ? Pas de probl\u00e8me, il leur suffit d'utiliser... une autre table, appel\u00e9e ISO-8859-7 :
On retrouve les caract\u00e8res universels h\u00e9rit\u00e9s de l'ASCII, puis des caract\u00e8res sp\u00e9cifiques \u00e0 la langue grecque... oui mais les Tha\u00eflandais alors ?
Pas de probl\u00e8me, ils ont la ISO-8859-11 :
\u00c9videmment, quand tous ces gens veulent discuter entre eux, les probl\u00e8mes d'encodage surviennent imm\u00e9diatement : certains caract\u00e8res sont remplac\u00e9s par d'autres.
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#3-que-fait-un-logiciel-a-louverture-dun-fichier-texte","title":"3. Que fait un logiciel \u00e0 l'ouverture d'un fichier texte ?","text":"Il essaie de deviner l'encodage utilis\u00e9... Parfois cela marche, parfois non.
Normalement, pour un navigateur, une page web correctement cod\u00e9e doit contenir dans une balise meta
le charset
utilis\u00e9.
Mais parfois, il n'y a pas d'autre choix pour le logiciel d'essayer de deviner l'encodage qui semble \u00eatre utilis\u00e9.
Exercice
\u00c9nonc\u00e9Correction Le mot repr\u00e9sent\u00e9 par les octets ci-dessous est-il encod\u00e9 en ASCII ou en Latin-9 ?
C'est du Latin-9, et c'est le mot \"v\u00e9lo\"
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#4-enfin-une-normalisation-larrivee-de-lutf","title":"4. Enfin une normalisation : l'arriv\u00e9e de l'UTF","text":"En 1996, le Consortium Unicode d\u00e9cide de normaliser tout cela et de cr\u00e9er un syst\u00e8me unique qui contiendra l'int\u00e9gralit\u00e9 des caract\u00e8res dont les \u00eatres humains ont besoin pour communiquer entre eux.
Ils cr\u00e9ent l'Universal character set Transformation Format : l'UTF. Ou plut\u00f4t ils en cr\u00e9ent... plusieurs :
- l'UTF-8 : les caract\u00e8res sont cod\u00e9s sur 1, 2, 3 ou 4 octets.
- l'UTF-16 : les caract\u00e8res sont cod\u00e9s sur 2 ou 4 octets.
- l'UTF-32 : les caract\u00e8res sont cod\u00e9s sur 4 octets.
Pourquoi est-ce encore si compliqu\u00e9 ? En UTF-32, 32 bits sont disponibles, soit \\(2^{32}=4294967296\\) caract\u00e8res diff\u00e9rents encodables.
C'est largement suffisant, mais c'est surtout tr\u00e8s tr\u00e8s lourd ! D'autres encodages plus l\u00e9gers, mais plus complexes, sont donc propos\u00e9s :
Arr\u00eatons-nous sur l'UTF-8 :
Le principe fondateur de l'UTF-8 est qu'il est adaptatif : les carac\u00e8res les plus fr\u00e9quents sont cod\u00e9s sur un octet, qui est la taille minimale (et qui donne le 8 de \"UTF-8\"). Les autres caract\u00e8res peuvent \u00eatre cod\u00e9s sur 2, 3 ou 4 octets au maximum.
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#5-la-reponse-a-une-question-existentielle","title":"5. La r\u00e9ponse \u00e0 une question existentielle","text":"Pourquoi le caract\u00e8re \u00e9
en UTF-8 devient-il \u00c3\u00a9
en ISO 8859-15 ?
Q1. Gr\u00e2ce \u00e0 la fonction ord
puis \u00e0 la fonction bin
, \u00e9crire en binaire le nombre associ\u00e9 au caract\u00e8re \u00e9
en UTF-8.
Correction >>> ord('\u00e9')\n233\n>>> bin(233)\n'0b11101001'\n
Donc en UTF-8, \u00e9
est associ\u00e9 au nombre 11101001
. Q2. D'apr\u00e8s l'explication de fonctionnement de l'encodage adaptatif de l'UTF-8 (voir ci-dessus), les 8 bits n\u00e9cessaires \u00e0 l'encodage de \u00e9
en UTF-8 vont \u00eatre \u00abencapsul\u00e9s\u00bb dans 2 octets de la forme 110XXXXX 10XXXXXX
, o\u00f9 les 11 X
repr\u00e9sentent les 11 bits d'information disponibles. \u00c9crire ces 2 octets en compl\u00e9tant si n\u00e9cessaire avec des 0
\u00e0 gauche.
Correction Sur 11 bits, le nombre 11101001
va s'\u00e9crire 00011101001
. En s\u00e9parant ces 11 bits en deux groupes de 5 bits et 6 bits (00011
et 101001
), et en les encapsulant, on obtient les deux octets 11000011 10101001
.
Q3. Convertir les deux octets obtenus en notation d\u00e9cimale (gr\u00e2ce \u00e0 int
) puis en hexad\u00e9cimal (gr\u00e2ce \u00e0 hex
).
Correction >>> int('11000011', 2)\n195\n>>> hex(195)\n'0xc3'\n>>> int('10101001', 2)\n169\n>>> hex(169)\n'0xa9'\n
Q4. Si un logiciel consid\u00e8re \u00e0 tort que les deux octets servant \u00e0 encoder le \u00e9
en UTF-8 servent \u00e0 encoder deux caract\u00e8res en ISO 8859-15, quels seront ces deux caract\u00e8res ?
Correction Le premier octet, c3
en hexad\u00e9cimal, sera per\u00e7u en ISO 8859-15 comme le caract\u00e8re \u00c3
. Le deuxi\u00e8me octet, a9
en hexad\u00e9cimal, sera per\u00e7u en ISO 8859-15 comme la lettre \u00a9
.
Finalement, ce qui aurait d\u00fb \u00eatre un \u00e9
en UTF-8 se retrouvera \u00eatre un \u00c3\u00a9
en ISO 8859-15.
"},{"location":"T2_Representation_des_donnees/2.6_Codage_caracteres/cours/#utilisation-grandissante-de-lencodage-utf-8","title":"Utilisation grandissante de l'encodage UTF-8","text":"La majorit\u00e9 des sites internet utilisent maintenant l'UTF-8, tout comme les syst\u00e8mes d'exploitation r\u00e9cents.
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/","title":"2.7 Codage des entiers","text":" Attention
La mani\u00e8re dont les nombres (entiers, non-entiers, positifs, n\u00e9gatifs...) sont trait\u00e9s par un langage de programmation est sp\u00e9cifique \u00e0 ce langage.
Dans toute la suite de ce cours, pour simplifier, nous consid\u00e9rerons que les nombres sont cod\u00e9s sur 1 octet seulement. Ce qui ne correspond pas \u00e0 la r\u00e9alit\u00e9, mais permet de comprendre les notions essentielles.
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#1-les-nombres-entiers-en-binaire-non-signe","title":"1. Les nombres entiers en binaire non sign\u00e9","text":"L'expression \"non sign\u00e9\" signifie que la contrainte du signe n'existe pas : tous les nombres sont consid\u00e9r\u00e9s comme \u00e9tant positifs.
Nous avons d\u00e9j\u00e0 vu comment ces nombres se codaient en binaire.
Sur un octet, le nombre minimal qu'on puisse coder est 00000000
. C'est l'entier naturel 0. Le nombre maximal qu'on puisse coder est 11111111
. C'est l'entier naturel 255.
Exercice 1
- Quel est le plus grand entier non sign\u00e9 codable sur 16 bits ?
- ... sur 32 bits ?
- ... \\(n\\) bits ?
Correction - \\(N=1+2+2^2+2^3+\\dots+2^{15}= 65535\\)
- \\(N=1+2+2^2+2^3+\\dots+2^{31}= 4294967295\\)
- Pour tout \\(n \\in \\mathbb{N}\\), \\(1+2+2^2+2^3+\\dots+2^{n-1}=2^{n}-1\\) (formule de la somme des termes d'une suite g\u00e9om\u00e9trique de raison 2).
Python et les entiers
Depuis la version 3 du langage Python, il n'y a plus de taille maximale pour les entiers en Python.
Ceci implique que la taille n\u00e9cessaire au codage de l'entier est allou\u00e9e dynamiquement par Python (avec pour seule limite celle de la m\u00e9moire disponible).
Exercice 2
- Effectuer la somme des deux nombres binaires
00001101
et 00001011
. - V\u00e9rifier que le r\u00e9sultat est coh\u00e9rent en base 10.
Correction - Cette addition correspond \u00e0 \\(13+11=24\\)
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#2-les-nombres-entiers-en-binaire-signe","title":"2. Les nombres entiers en binaire sign\u00e9","text":"ou Comment repr\u00e9senter des nombres n\u00e9gatifs ???
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#21-la-partiellement-fausse-bonne-idee","title":"2.1 La (partiellement) fausse bonne id\u00e9e","text":"Comment diff\u00e9rencier les nombres positifs des nombres n\u00e9gatifs ? L'id\u00e9e naturelle est de r\u00e9server 1 bit pour le signe, et de coder le reste du nombre \u00abnaturellement\u00bb.
Par exemple, on peut d\u00e9cr\u00e9ter que le premier bit (appel\u00e9 bit de poids fort) sera le bit de signe :
- 0 pour un nombre positif
- 1 pour un nombre n\u00e9gatif
Dans ce cas, 00000011
serait le nombre \\(+3\\) et 10000011
serait le nombre \\(-3\\).
Probl\u00e8mes :
- le z\u00e9ro serait repr\u00e9sent\u00e9 \u00e0 la fois par
00000000
et 10000000
, ce qui n'est pas tr\u00e8s \u00e9conome. - plus grave :
Exercice 3
Avec cette convention, effectuer l'addition \\((+3)+(-3)\\) en binaire.
Correction L'addition \\((+3)+(-3)\\) serait \u00e9gale \u00e0 \\(-6\\) !
Moralit\u00e9 :
Ce syst\u00e8me d'\u00e9criture ne marche pas bien.
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#22-a-la-recherche-de-loppose-dun-nombre","title":"2.2 \u00c0 la recherche de l'oppos\u00e9 d'un nombre","text":"Id\u00e9e :
Plut\u00f4t que de chercher \u00e0 \u00e9crire directement le nombre \\(-3\\), nous allons chercher \u00e0 d\u00e9terminer ce qu'il faut ajouter \u00e0 \\((+3)\\) pour obtenir 0.
Que faut-il ajouter au nombre \\((+3)\\) pour obtenir 0 ?
L'id\u00e9e naturelle est de commencer par la droite, en essayant de \u00abfabriquer du z\u00e9ro\u00bb en choisissant le bon bit \u00e0 ajouter :
On arrive bien \u00e0 fabriquer des 0 sur tout notre octet, mais que devient la retenue (en anglais carry) de 1 qui d\u00e9borde de notre octet ?
R\u00e9ponse : rien ! Elle sera perdue et c'est une tr\u00e8s bonne nouvelle. Ce nombre sera donc consid\u00e9r\u00e9 comme un 0 : nous avons trouv\u00e9 comment coder \\(-3\\).
Le nombre \\(-3\\) s'\u00e9crit donc 11111101
.
Comment, \u00e0 partir du nombre 00000011
, aurait-on pu le trouver directement (sans raisonner de proche en proche) ?
On peut remarquer qu'en inversant chaque bit du nombre de d\u00e9part 00000011
, on obtient 11111100
, qui appel\u00e9 le compl\u00e9ment \u00e0 2 du nombre 00000011
.
Il ne reste donc plus qu'\u00e0 ajouter 1
\u00e0 ce nombre 11111100
pour obtenir le nombre cherch\u00e9, 11111101
ce nombre 11111101
repr\u00e9sente 253 en codage non sign\u00e9. Il est donc n\u00e9cessaire, lorsqu'on repr\u00e9sente un nombre, de savoir si les nombres manipul\u00e9s seront des entiers naturels (non sign\u00e9s) ou bien relatifs (sign\u00e9s).
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#23-tableau-des-entiers-en-binaire-signe","title":"2.3 Tableau des entiers en binaire sign\u00e9","text":"Tableau binaire base 10 10000000 -128 10000001 -127 10000010 -126 10000011 -125 10000100 -124 10001001 -123 ... ... 11111100 -4 11111101 -3 11111110 -2 11111111 -1 00000000 0 00000001 1 00000010 2 00000011 3 00000100 4 ... ... 01111100 124 01111101 125 01111110 126 01111111 127"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#24-conclusion-ecriture-loppose-dun-nombre-positif","title":"2.4 Conclusion : \u00e9criture l'oppos\u00e9 d'un nombre positif","text":"Consid\u00e9rons que ce nombre positif s'\u00e9crit sur 7 bits, donc qu'il est de la forme 0XXXXXXX
.
\u00c9criture de l'oppos\u00e9 d'un nombre positif
- On prend le compl\u00e9ment \u00e0 2 de chacun des 8 bits du nombre de d\u00e9part
- On ajoute 1 au nombre obtenu.
Exercice 4
Donner l'\u00e9criture binaire sur un octet du nombre \\(-13\\).
Correction Commen\u00e7ons par \u00e9crire le nombre 13 en binaire. Il s'\u00e9crit \u00a000001101
.
- en prenant le compl\u00e9ment \u00e0 2 de chaque bit, on obtient
11110010
. - en ajoutant 1 \u00e0 ce dernier nombre, on obtient
11110011
.
Le nombre \\(-13\\) s'\u00e9crit donc 11110011
.
Remarque Les nombres n\u00e9gatifs commenceront donc toujours par le bit 1, et les nombres positifs par le bit 0. Cela revient \u00e0 suivre partiellement notre fausse bonne id\u00e9e du 2.1. Et cela donne surtout une m\u00e9thode tr\u00e8s pratique pour savoir qui est positif et qui est n\u00e9gatif !
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#3-travail-inverse-passage-du-binaire-signe-au-nombre-relatif","title":"3. Travail inverse : passage du binaire sign\u00e9 au nombre relatif","text":"Consid\u00e9rons le nombre 11101101
, cod\u00e9 en binaire sign\u00e9. \u00c0 quel nombre relatif correspond-il ?
- On observe son bit de poids fort : ici 1, donc ce nombre est n\u00e9gatif. Si ce bit est \u00e9gal \u00e0 0, le nombre cod\u00e9 est positif, il suffit d'op\u00e9rer une conversion binaire classique.
- Comme ce nombre est n\u00e9gatif, il va falloir inverser le protocole pr\u00e9c\u00e9dent. On commence donc par enlever 1 au nombre propos\u00e9. On trouve
11101100
. - On prend ensuite le compl\u00e9ment \u00e0 2 de chaque bit. On trouve
00010011
. - On convertit en base 10 le nombre obtenu, qui \u00e9tait donc 19.
- Le nombre initial \u00e9tait donc \\(-19\\).
Exercice
Q1. En binaire sign\u00e9, \u00e0 quel nombre correspond 11110001
?
Correction 11110001
- 1
= 11110000
. En prenant le compl\u00e9ment \u00e0 2, on trouve 00001111
, qui vaut 15. Le nombre 11110001
repr\u00e9sente donc \\(-15\\).
Q2. En binaire sign\u00e9, quel est le plus grand nombre que l'on puisse \u00e9crire sur un octet ?
Correction Le plus grand nombre est 01111111
, soit \\(+127\\).
Q3. Quel est le plus petit nombre ?
Correction Le plus petit nombre est 10000000
. 10000000
- 1
= 01111111
. Le compl\u00e9ment est 10000000
, qui est \u00e9gal \u00e0 128. Donc le nombre minimal est \\(-128\\).
Q4. Au total, combien de nombres diff\u00e9rents peuvent \u00eatre \u00e9crits en binaire sign\u00e9 ?
Correction Il y a 128 nombres n\u00e9gatifs (de \\(-128\\) \u00e0 \\(-1\\)), le nombre 0, puis 127 nombres positifs (de 1 \u00e0 127). Il y a donc 256 nombres au total, comme en binaire non sign\u00e9.
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#4-le-codage-des-entiers-une-source-intarissable-derreurs","title":"4. Le codage des entiers, une source intarissable d'erreurs...","text":""},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#41-le-vol-501-dariane-5","title":"4.1 Le vol 501 d'Ariane 5","text":"Le 04 juin 1996, le vol inaugural d'Ariane 5 a malheureusement fini dans une gerbe d'\u00e9tincelles.
En cause : un code pr\u00e9vu pour Ariane 4 avait \u00e9t\u00e9 gard\u00e9 pour le nouveau mod\u00e8le Ariane 5. Dans ce \u00abvieux\u00bb code, une donn\u00e9e issue d'un capteur (le capteur de vitesse horizontale) \u00e9tait cod\u00e9 sur 8 bits. La valeur maximale acceptable de cette donn\u00e9e \u00e9tait donc 255.
Or, Ariane 5 \u00e9tant beaucoup plus puissante, le capteur de vitesse horizontale a renvoy\u00e9, au bout de 30 secondes, la valeur 300 : cette valeur a provoqu\u00e9 un d\u00e9passement des 8 bits pr\u00e9vus et a donn\u00e9 un r\u00e9sultat absurde. L'ordinateur de bord a cru que la fus\u00e9e \u00e9tait en train de se coucher et a violemment orient\u00e9 les tuy\u00e8res de propulsion pour redresser Ariane 5, alors que celle-ci s'\u00e9levait pourtant bien verticalement... Ariane 5 a alors brusquement pivot\u00e9 avant d'exploser.
Cette catastrophe (150 millions d'euros et des ann\u00e9es de travail perdus) a fait prendre conscience \u00e0 la communaut\u00e9 scientifique de l'importance de faire des tests logiciels toujours plus pouss\u00e9s : ce n'est pas parce qu'un code marche dans un environnement donn\u00e9 qu'il marchera de la m\u00eame mani\u00e8re dans d'autres conditions...
"},{"location":"T2_Representation_des_donnees/2.7_Codage_entiers/cours/#42-le-bug-de-lannee-2038","title":"4.2 Le bug de l'ann\u00e9e 2038","text":"Expliquons ce (superbe) gif issu de la page Wikipedia Bug de l'an 2038.
Lorsqu'on demande \u00e0 Python l'heure qu'il est, par la fonction time()
du module time
, voici ce qu'il r\u00e9pond :
>>> import time\n>>> time.time()\n1653855138.398177\n
Il nous renvoie le nombre de secondes \u00e9coul\u00e9es depuis le 1er janvier 1970 \u00e0 00h00. On appelle cela l'heure POSIX ou l'heure UNIX l'heure UNIX. Au 29 mai 2022, il s'en donc \u00e9coul\u00e9 environ 1,6 milliards.
Dans beaucoup de syst\u00e8mes informatiques, ce nombre de secondes est cod\u00e9 par un entier sign\u00e9 sur 32 bits. Le nombre maximum de secondes qui peut \u00eatre repr\u00e9sent\u00e9 est donc 01111111 11111111 11111111 11111111
>>> int('01111111111111111111111111111111', 2)\n2147483647\n
Ce nombre repr\u00e9sente un peu plus de 2 milliards de secondes... En les comptant depuis le 01/01/1970 00h00m00s, on arrive au 19/01/2038 \u00e0 03h14m07s.
\u00c0 la seconde d'apr\u00e8s, la repres\u00e9ntation binaire du temps sera 10000000 00000000 00000000 00000000
, qui sera interpr\u00e9t\u00e9 comme le nombre n\u00e9gatif \u22122147483648, et qui ram\u00e8nera donc les horloges au 13 d\u00e9cembre 1901...
Vous pourrez lire sur la page Wikipedia cit\u00e9e plus haut plus d'informations sur ce probl\u00e8me.
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/","title":"2.8 Codage des non-entiers","text":"Le principe est l'extension du syst\u00e8me d\u00e9j\u00e0 rencontr\u00e9 pour les nombres entiers. La partie d\u00e9cimale (\u00e0 droite de la virgule) correspondra aux puissances n\u00e9gatives de 2.
... 8 4 2 1 0.5 0.25 0.125 ... ... \\(2^3\\) \\(2^2\\) \\(2^1\\) \\(2^0\\) \\(2^{-1}\\) \\(2^{-2}\\) \\(2^{-3}\\) ... ... 0 1 1 0, 1 0 1 ... Exemple : \\(110,101_2=1 \\times 2^2 + 1 \\times2^1 +0 \\times 2^0 + 1 \\times 2^{-1} +0 \\times 2^{-2}+1 \\times 2^{-2} =4+2+0,5+0,125=6,625\\)
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#1-tentatives-de-conversion","title":"1. Tentatives de conversion","text":""},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#11-theoreme-de-decomposition-en-puissances-de-2","title":"1.1 Th\u00e9or\u00e8me de d\u00e9composition en puissances de 2","text":"Tout commence bien, avec un r\u00e9sultat math\u00e9matique rassurant : tous les nombres r\u00e9els peuvent s'\u00e9crire comme une somme de puissances de 2 (puissances positives et n\u00e9gatives).
Th\u00e9or\u00e8me
Pour tout r\u00e9el \\(x \\in \\mathbb{R}^+\\), il existe \\(p \\in \\mathbb{N}\\) et \\((a_p,a_{p-1},...,a_0,a_{-1},a_{-2},...)\\) tels que \\(x = \\sum_{i=0}^pa_i2^i+\\sum_{i=1}^{+\\infty}a_{-i}2^{-i}\\)
\u00c9crire un nombre en binaire revient \u00e0 calculer les coefficients \\(a_k\\) (ils sont \u00e9gaux \u00e0 0 ou 1). Il y en a un nombre fini pour la partie enti\u00e8re, mais un nombre potentiellement infini pour la partie d\u00e9cimale.
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#12-methode-de-conversion","title":"1.2 M\u00e9thode de conversion","text":"Consid\u00e9rons le nombre \\(3,6875\\). Il se d\u00e9compose en une partie enti\u00e8re (3) et une partie d\u00e9cimale (\\(0,6875\\)).
- partie enti\u00e8re : \\(3=11_2\\)
- partie d\u00e9cimale : la conversion de \\(0,6875\\) se fait en plusieurs \u00e9tapes. \\(0,6875 \\times 2 = \\textbf{1},375\\) \\(0,375 \\times 2 = \\textbf{0},75\\) \\(0,75 \\times 2 = \\textbf{1},5\\) \\(0,5 \\times 2 = \\textbf{1}\\)
On prend ensuite le chiffre des unit\u00e9s de tous les nombres obtenus : 1011
Donc \\(3,6875=11,1011_2\\)
Exercice 1
Donner l'\u00e9criture binaire de 20,875.
Correction - partie enti\u00e8re : \\(20 = 10100_2\\)
- partie d\u00e9cimale :
- \\(0,875 \\times 2 = \\textbf{1},75\\)
- \\(0,75 \\times 2 = \\textbf{1},5\\)
- \\(0,5 \\times 2 = \\textbf{1}\\)
Donc \\(20,875=10100,111_2\\)
Exercice 2
Donner l'\u00e9criture binaire de 0,2.
Correction - partie enti\u00e8re : \\(0 = 0_2\\)
- partie d\u00e9cimale :
- \\(0,2 \\times 2 = \\textbf{0},4\\)
- \\(0,4 \\times 2 = \\textbf{0},8\\)
- \\(0,8 \\times 2 = \\textbf{1},6\\)
- \\(0,6 \\times 2 = \\textbf{1},2\\)
- \\(0,2 \\times 2 = \\textbf{0},4\\)
- et cela continue...
Le nombre 0,2 n'admet pas d'\u00e9criture binaire finie.
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#conclusion","title":"Conclusion","text":"Certains nombres n'admettent pas une \u00e9criture binaire finie. Or la m\u00e9moire d'un ordinateur, quelqu'il soit, est toujours finie. Certains nombres ne peuvent donc pas \u00eatre repr\u00e9sent\u00e9s correctement en machine : c'est une impossibilit\u00e9 th\u00e9orique. Cela am\u00e8ne \u00e0 des comportements \u00e9tranges :
>>> 0.1 + 0.2\n0.30000000000000004\n
Remarque : parmi les nombres d\u00e9cimaux \u00e0 un chiffre apr\u00e8s la virgule (0,1 0,2 0,3 ...) seul 0,5 admet une \u00e9criture binaire finie ! Tous les autres ont une repr\u00e9sentation en machine qui n'en donne qu'une valeur approch\u00e9e. Vous pouvez avoir un aper\u00e7u de la repr\u00e9sentation des nombres flottants sur ce site.
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#2-consequences-la-difficile-manipulation-des-flottants","title":"2. Cons\u00e9quences : la difficile manipulation des flottants","text":"En python, les nombres non entiers sont du type float.
>>> type(0.1)\n<class 'float'>\n
Ces flottants (traduction fran\u00e7aise) sont \u00e0 manipuler avec une extr\u00eame pr\u00e9caution. Il faut garder en t\u00eate que les calculs sont potentiellement faux, du moins impr\u00e9cis, lorsque des flottants interviennent.
>>> 0.5 - 0.2 - 0.2 - 0.1\n-2.7755575615628914e-17\n
En 1991, durant la Guerre du Golfe, un missile anti-missile am\u00e9ricain a rat\u00e9 sa cible de 500 m\u00e8tres car son ordinateur interne \u00e9mettait un signal toutes les 0.1 secondes. Au bout de 100 heures de fonctionnement, l'approximation du nombre flottant 0.1 a conduit \u00e0 un d\u00e9calage de 0,34 secondes, ce qui lui a fait rater sa cible. (source)
Hormis ce cas tragique, est-ce si grave de devoir travailler avec des valeurs approch\u00e9es ? Non, pas vraiment : par exemple, la valeur de Pi utilis\u00e9e par la NASA pour faire ses calculs (g\u00e9n\u00e9ralement tr\u00e8s, tr\u00e8s, tr\u00e8s pr\u00e9cis) est 3.141592653589793
, donc \u00abjuste\u00bb 15 chiffres apr\u00e8s la virgule. (source)
Un bug int\u00e9ressant : on a enfin compris pourquoi dans Minecraft les barques tombant d'une certaine hauteur cassaient, et pas d'autres. La raison ? Les nombres flottants bien s\u00fbr ! (vid\u00e9o)
"},{"location":"T2_Representation_des_donnees/2.8_Codage_non-entiers/cours/#3-comment-faire-des-tests-degalite-sur-les-flottants","title":"3. Comment faire des tests d'egalit\u00e9 sur les flottants ?","text":"Premi\u00e8re r\u00e9ponse : ON N'EN FAIT PAS.
Si a
et b
sont deux flottants, le test classique
if a == b :\n print(\"a et b sont \u00e9gaux\")\n
a de grandes chances d'\u00e9chouer :
Le script
a = 0.1\nb = 0.3 - 0.2\nif a == b :\n print(\"a et b sont \u00e9gaux\")\nelse :\n print(\"a et b sont diff\u00e9rents\")\n
renverra
a et b sont diff\u00e9rents\n
Si vraiment un test d'\u00e9galit\u00e9 est n\u00e9cessaire, on ne va pas tester l'\u00e9galit\u00e9 entre a
et b
mais leur proximit\u00e9, gr\u00e2ce \u00e0 la valeur absolue de leur diff\u00e9rence.
La fonction abs(a-b)
renvoie un nombre positif \u00e9gal \u00e0 la distance entre a
et b
. Il faut alors d\u00e9cider d'un \u00e9cart minimal e
en dessous duquel on consid\u00e8rera que a
et b
sont \u00e9gaux.
Le script
a = 0.1\nb = 0.3 - 0.2\ne = 10**(-12)\nif abs(a - b) < e :\n print(\"a et b sont \u00e9gaux\")\nelse :\n print(\"a et b sont diff\u00e9rents\")\n
renverra
a et b sont \u00e9gaux\n
car notre code les aura consid\u00e9r\u00e9s comme \u00absuffisamment proches\u00bb. Exercice 3
On consid\u00e8re la fonction \\(f(x)=x^3-6x+2\\). L'\u00e9quation \\(f(x)=1\\) admet une solution unique dans l'intervalle \\([0;1]\\). Trouver une valeur approch\u00e9e de cette solution \u00e0 \\(10^{-5}\\) pr\u00e8s. On prendra e
\\(=0,001\\).
Correction def f(x):\n return x**3 - 6*x + 2\n\ne = 10**(-3)\na = 0\nwhile abs(f(a) - 1 ) > e :\n a += 10**(-5)\nprint(a)\n
"},{"location":"T2_Representation_des_donnees/2.9_Chaines_caracteres/cours/","title":"2.9 Cha\u00eenes de caract\u00e8res","text":"La manipulation des cha\u00eenes de caract\u00e8res n'est pas au programme, mais quelques astuces sont tr\u00e8s utiles \u00e0 conna\u00eetre.
"},{"location":"T3_Architecture_materielle/sommaire/","title":"Th\u00e8me 3 : Architecture mat\u00e9rielle","text":" - Microbit
- Architecture Von Neumann
- Architecture r\u00e9seau
- Protocoles de communication dans un r\u00e9seau
- D\u00e9couverte des commandes Linux
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/","title":"Micro:bit","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#0-presentation-de-la-carte-bbc-microbit","title":"0. Pr\u00e9sentation de la carte BBC micro:bit","text":"BBC micro:bit est une carte \u00e0 microcontr\u00f4leur con\u00e7ue en 2015 au Royaume-Uni pour d\u00e9velopper l'apprentissage de l'algorithmique et de la programmation.
La carte micro:bit dispose des sp\u00e9cificit\u00e9s techniques suivantes :
- 25 LEDs programmables individuellement
- 2 boutons programmables
- Broches de connexion
- Capteurs de lumi\u00e8re et de temp\u00e9rature
- Capteurs de mouvements (acc\u00e9l\u00e9rom\u00e8tre et boussole)
- Communication sans fil, via Radio et Bluetooth
- Interface USB
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#1-hello-world-virtuellement-ou-irl","title":"1. \"Hello world !\", virtuellement ou IRL...","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#11-a-distance-pas-de-microbit-le-simulateur-est-la","title":"1.1 \u00c0 distance ? Pas de micro:bit ? le simulateur est l\u00e0 !","text":"Rendez-vous sur la page https://python.microbit.org/v/3
Effacez le code existant et collez-le code ci-dessous :
from microbit import *\n\nwhile True:\n display.scroll('Hello, World!')\n display.show(Image.HEART)\n sleep(2000)\n
Cliquez sur le bouton Play de la micro:bit virtuelle. C'est parti !
Pour \u00e9viter des erreurs, fermez la fen\u00eatre de droite (le simulateur) \u00e0 chaque fois que vous modifiez votre code de la partie gauche.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#12-avec-une-microbit-reelle","title":"1.2 Avec une micro:bit r\u00e9elle","text":"La manipulation suivante ne marche que sur le navigateur Google Chrome.
- Branchez la carte sur un port USB. Un lecteur MICROBIT apparait dans les p\u00e9riph\u00e9riques USB.
- Rendez-vous sur l'adresse https://python.microbit.org/v/3
- Modifiez le code pr\u00e9sent puis cliquez sur le bouton Play de la micro:bit virtuelle.
- Cliquer sur le bouton violet \u00abSend to micro:bit\u00bb.
Cette proc\u00e9dure est \u00e0 r\u00e9p\u00e9ter \u00e0 chaque nouveau code.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#2-decouverte-des-fonctionnalites","title":"2. D\u00e9couverte des fonctionnalit\u00e9s","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#21-commandes-de-base-de-lafficheur-matrice-de-5x5-leds","title":"2.1 Commandes de base de l'afficheur, matrice de 5x5 LEDs","text":"voir vid\u00e9o explicative (en anglais)
LED signifie Light Emitting Diode, Diode \u00e9lectroluminescente. La carte micro:bit en dispose de 25, toutes programmables individuellement, ce qui permet d'afficher du texte, des nombres et des images.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#211-afficher-un-texte-defilant-displayscrollstring-delay400","title":"2.1.1 Afficher un texte \"d\u00e9filant\" display.scroll(string, delay=400)
","text":"from microbit import *\ndisplay.scroll(\"NSI\")\n
La premi\u00e8re ligne de ce programme importe la biblioth\u00e8que de fonctions micro:bit. La deuxi\u00e8me ligne fait d\u00e9filer un message \u00e0 l\u2019\u00e9cran. Cela n'arrive qu'une seule fois.
La vitesse de d\u00e9filement peut \u00eatre ralentie ou acc\u00e9l\u00e9r\u00e9e \u00e0 l'aide du param\u00e8tre delay
. L'unit\u00e9 est la milliseconde.
from microbit import *\ndisplay.scroll(\"mauriac\", delay=20)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#212-afficher-une-image-displayshowimage","title":"2.1.2 Afficher une \"image\" display.show(image)
","text":"Ex\u00e9cuter le programme suivant:
from microbit import *\ndisplay.show(Image.SAD)\n
Liste des images disponibles Image.HEART\nImage.HEART_SMALL\nImage.HAPPY\nImage.SMILE\nImage.SAD\nImage.CONFUSED\nImage.ANGRY\nImage.ASLEEP\nImage.SURPRISED\nImage.SILLY\nImage.FABULOUS\nImage.MEH\nImage.YES\nImage.NO\nImage.CLOCK12\nImage.CLOCK11\nImage.CLOCK10\nImage.CLOCK9\nImage.CLOCK8\nImage.CLOCK7\nImage.CLOCK6\nImage.CLOCK5\nImage.CLOCK4\nImage.CLOCK3\nImage.CLOCK2\nImage.CLOCK1\nImage.ARROW_N\nImage.ARROW_NE\nImage.ARROW_E\nImage.ARROW_SE\nImage.ARROW_S\nImage.ARROW_SW\nImage.ARROW_W\nImage.ARROW_NW\nImage.TRIANGLE\nImage.TRIANGLE_LEFT\nImage.CHESSBOARD\nImage.DIAMOND\nImage.DIAMOND_SMALL\nImage.SQUARE\nImage.SQUARE_SMALL\nImage.RABBIT\nImage.COW\nImage.MUSIC_CROTCHET\nImage.MUSIC_QUAVER\nImage.MUSIC_QUAVERS\nImage.PITCHFORK\nImage.XMAS\nImage.PACMAN\nImage.TARGET\nImage.TSHIRT\nImage.ROLLERSKATE\nImage.DUCK\nImage.HOUSE\nImage.TORTOISE\nImage.BUTTERFLY\nImage.STICKFIGURE\nImage.GHOST\nImage.SWORD\nImage.GIRAFFE\nImage.SKULL\nImage.UMBRELLA\nImage.SNAKE\n
Exercice 1
Cr\u00e9er un code qui permet d'afficher la totalit\u00e9 des images, pendant une demi-seconde chacune (gr\u00e2ce \u00e0 l'instruction sleep(500)
). On utilisera la liste
lst = [Image.HEART, Image.HEART_SMALL, Image.HAPPY, Image.SMILE,\n Image.SAD, Image.CONFUSED, Image.ANGRY, Image.ASLEEP, Image.SURPRISED, Image.SILLY,\n Image.FABULOUS, Image.MEH, Image.YES, Image.NO, Image.CLOCK12,\n Image.CLOCK11, Image.CLOCK10, Image.CLOCK9, Image.CLOCK8, Image.CLOCK7,\n Image.CLOCK6, Image.CLOCK5, Image.CLOCK4, Image.CLOCK3, Image.CLOCK2,\n Image.CLOCK1, Image.ARROW_N, Image.ARROW_NE, Image.ARROW_E, Image.ARROW_SE,\n Image.ARROW_S, Image.ARROW_SW, Image.ARROW_W, Image.ARROW_NW, Image.TRIANGLE,\n Image.TRIANGLE_LEFT, Image.CHESSBOARD, Image.DIAMOND, Image.DIAMOND_SMALL, Image.SQUARE,\n Image.SQUARE_SMALL, Image.RABBIT, Image.COW, Image.MUSIC_CROTCHET, Image.MUSIC_QUAVER,\n Image.MUSIC_QUAVERS, Image.PITCHFORK, Image.XMAS, Image.PACMAN, Image.TARGET, Image.TSHIRT,\n Image.ROLLERSKATE, Image.DUCK, Image.HOUSE, Image.TORTOISE, Image.BUTTERFLY, Image.STICKFIGURE,\n Image.GHOST, Image.SWORD, Image.GIRAFFE, Image.SKULL, Image.UMBRELLA, Image.SNAKE]\n
Correction from microbit import *\n\nlst = [Image.HEART, Image.HEART_SMALL, Image.HAPPY, Image.SMILE,\n Image.SAD, Image.CONFUSED, Image.ANGRY, Image.ASLEEP, Image.SURPRISED, Image.SILLY,\n Image.FABULOUS, Image.MEH, Image.YES, Image.NO, Image.CLOCK12,\n Image.CLOCK11, Image.CLOCK10, Image.CLOCK9, Image.CLOCK8, Image.CLOCK7,\n Image.CLOCK6, Image.CLOCK5, Image.CLOCK4, Image.CLOCK3, Image.CLOCK2,\n Image.CLOCK1, Image.ARROW_N, Image.ARROW_NE, Image.ARROW_E, Image.ARROW_SE,\n Image.ARROW_S, Image.ARROW_SW, Image.ARROW_W, Image.ARROW_NW, Image.TRIANGLE,\n Image.TRIANGLE_LEFT, Image.CHESSBOARD, Image.DIAMOND, Image.DIAMOND_SMALL, Image.SQUARE,\n Image.SQUARE_SMALL, Image.RABBIT, Image.COW, Image.MUSIC_CROTCHET, Image.MUSIC_QUAVER,\n Image.MUSIC_QUAVERS, Image.PITCHFORK, Image.XMAS, Image.PACMAN, Image.TARGET, Image.TSHIRT,\n Image.ROLLERSKATE, Image.DUCK, Image.HOUSE, Image.TORTOISE, Image.BUTTERFLY, Image.STICKFIGURE,\n Image.GHOST, Image.SWORD, Image.GIRAFFE, Image.SKULL, Image.UMBRELLA, Image.SNAKE]\n\nfor img in lst:\n display.show(img)\n sleep(500)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#creer-sa-propre-image","title":"Cr\u00e9er sa propre image","text":"Chaque pixel LED sur l\u2019affichage physique peut prendre une parmi dix valeurs. Si un pixel prend la valeur 0 c\u2019est qu\u2019il est \u00e9teint. Litt\u00e9ralement, il a une luminosit\u00e9 de z\u00e9ro. En revanche, s\u2019il prend la valeur 9 il est \u00e0 la luminosit\u00e9 maximale. Les valeurs de 1 \u00e0 8 repr\u00e9sentent des niveaux de luminosit\u00e9 entre \u00e9teint (0) et \u00ab au maximum \u00bb (9).
from microbit import *\n\nbateau = Image(\"05050:\"\n \"05050:\"\n \"05050:\"\n \"99999:\"\n \"09990\")\n\ndisplay.show(bateau)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#213-les-pixels-displayset_pixelx-y-val","title":"2.1.3 Les pixels (display.set_pixel(x, y, val)
)","text":"Vous pouvez r\u00e9gler la luminosit\u00e9 des pixels de l'affichage individuellement de 0 (d\u00e9sactiv\u00e9) \u00e0 9 (luminosit\u00e9 maximale). Pour des informations sur les coordonn\u00e9es de l'affichage, voir le guide pour matrice \u00e0 LED.
Ex\u00e9cuter le programme suivant:
from microbit import *\ndisplay.set_pixel(1, 4, 9)\n
Exercice 2
Faire clignoter le pixel central.
Correction from microbit import *\n\nwhile True:\n display.set_pixel(2, 2, 9)\n sleep(200)\n display.set_pixel(2, 2, 0)\n sleep(200)\n
Exercice 3
Faire afficher en boucle un pixel al\u00e9atoire pendant 200 ms.
Pour obtenir un entier pseudo-al\u00e9atoire, on utilisera la fonction randint
du module random
. Par exemple, l'instruction randint(2, 8)
va renvoyer un nombre (pseudo-)al\u00e9atoire entre 2 et 8 inclus.
On pourra aussi utiliser l'instruction display.clear()
pour \u00e9teindre tout l'affichage.
Correction from microbit import *\nfrom random import randint\n\nwhile True:\n x = randint(0,4)\n y = randint(0,4)\n display.set_pixel(x, y, 9)\n sleep(200)\n display.clear()\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours/#24-les-entrees-boutons-a-b-et-ab-programmation-evenementielle-video-explicative","title":"2.4 Les entr\u00e9es boutons A, B et A+B - programmation \u00e9v\u00e9nementielle (vid\u00e9o explicative)","text":"Il y a deux boutons sur la face avant du micro:bit (\u00e9tiquet\u00e9s A et B). On peut d\u00e9tecter quand ces boutons sont press\u00e9s, ce qui permet de d\u00e9clencher des instructions sur l'appareil.
Exemples avec le boutton A:
button_a.is_pressed()
: renvoie True si le bouton sp\u00e9cifi\u00e9 est actuellement enfonc\u00e9 et False sinon. button_a.was_pressed()
: renvoie True ou False pour indiquer si le bouton a \u00e9t\u00e9 appuy\u00e9 depuis le d\u00e9marrage de l'appareil ou la derni\u00e8re fois que cette m\u00e9thode a \u00e9t\u00e9 appel\u00e9e.
Exemple : Essayer le programme suivant qui fait d\u00e9filer le texte \"NSI\" ind\u00e9finiment. D\u00e8s qu'un bouton est press\u00e9, on sort de la boucle break
et le programme s'ach\u00e8ve.
from microbit import *\nwhile True:\n display.scroll(\"NSI\")\n sleep(200)\n if button_a.was_pressed():\n break\ndisplay.clear()\ndisplay.show(Image.SAD)\n
Exercice 4
Cr\u00e9er le code permettant de basculer d'un visage triste \u00e0 un visage heureux suivant qu'on appuie sur A ou sur B.
Correction from microbit import *\nwhile True:\n if button_a.was_pressed():\n display.show(Image.SAD)\n if button_b.was_pressed():\n display.show(Image.HAPPY)\n
Exercice 5
Cr\u00e9er le code permettant de d\u00e9placer un point vers la gauche ou vers la droite en appuyant sur A ou sur B.
Exercice 6
M\u00eame \u00e9nonc\u00e9 que l'exercice pr\u00e9c\u00e9dent, mais en faisant parcourir tout l'\u00e9cran au pixel :
- si on sort \u00e0 droite, on se d\u00e9cale d'une ligne vers le bas et on revient tout \u00e0 gauche.
- si on sort \u00e0 gauche, on se d\u00e9cale d'une ligne vers le haut et on revient tout \u00e0 droite.
- arriv\u00e9 tout en bas \u00e0 droite, on r\u00e9appara\u00eet en haut \u00e0 gauche (et r\u00e9ciproquement).
Exercice 7
On veut cr\u00e9er le jeu suivant :
- au d\u00e9marrage, un pixel al\u00e9atoire est plac\u00e9 sur l'\u00e9cran.
- il faut ensuite se d\u00e9placer un point vers la gauche ou vers la droite en appuyant sur A ou sur B.
- lorsque qu'on a rejoint le point al\u00e9atoire, un emoji HAPPY apparait.
Exercice 8
Rajout d'un temps limit\u00e9
La fonction tick_ms
du module utime
renvoie le nombre de millisecondes \u00e9coul\u00e9es depuis le d\u00e9marrage de la carte. Pour mesurer le temps \u00e9coul\u00e9 dans un programme, on fixe le temps du d\u00e9but du programme dans une variable t0
. Il suffit d'observer ensuite la valeur de tick_ms() - t0
pour savoir combien de temps (en millisecondes) s'est \u00e9coul\u00e9 depuis le d\u00e9but du programme.
Exemple (\u00e0 ex\u00e9cuter pour comprendre !) :
from microbit import *\nfrom utime import *\n\ndisplay.show(Image.HAPPY)\nt0 = ticks_ms()\n\nwhile True:\n if ticks_ms() - t0 > 5000:\n display.show(Image.SAD)\n break\n
Reprendre l'exercice pr\u00e9c\u00e9dent en rajoutant une difficult\u00e9 suppl\u00e9mentaire avec un temps limit\u00e9.
Exercice 9
Cr\u00e9er un jeu de Pierre-Feuille-Ciseaux qui se d\u00e9clenchera lorsqu'on secoue la Microbit. (Vous pouvez cr\u00e9er vos propres images de pierre, de feuille et de ciseaux)
La d\u00e9tection du \"secouage\" de la carte se fera avec l'instruction suivante :
if accelerometer.was_gesture('shake'):\n ...\n
Correction from microbit import *\nfrom random import randint\n\npierre = Image('09990:'\n '09009:'\n '09990:'\n '09000:'\n '09000')\n\nfeuille = Image('09999:'\n '09000:'\n '09990:'\n '09000:'\n '09000')\n\nciseaux = Image('00999:'\n '09000:'\n '09000:'\n '09000:'\n '00999')\n\n\nwhile True:\n if accelerometer.was_gesture('shake'):\n v = randint(1,3)\n if v == 1:\n display.show(pierre)\n if v == 2:\n display.show(feuille)\n if v == 3:\n display.show(ciseaux)\n
Exercice 10
En utilisant les fonctions accelerometer.get_x()
et accelerometer.get_y()
de l'acc\u00e9l\u00e9rom\u00e8tre, cr\u00e9er un code qui allumera la LED du centre lorsque la carte est \u00e0 l'horizontale, puis qui fera bouger cette LED en fonction de l'inclinaison de la carte.
from microbit import *\n\ndef move(x, y):\n incx = accelerometer.get_x()\n if incx > 500:\n x += 1\n x = min(..., ...)\n if incx < -500:\n x -= 1\n x = max(..., ...)\n incy = accelerometer.get_y()\n if incy > 500:\n y += 1\n y = min(..., ...)\n if incy < -500:\n y -= 1\n y = max(..., ...)\n return x, y\n\nx = 2\ny = 2\nwhile True:\n display.clear()\n ..., ... = move(..., ...)\n display.set_pixel(..., ..., 9)\n sleep(200) \n
Exercice 11
Communication radio
Voici un code proposant une communication radio entre deux cartes. Inspirez-vous de ce code pour (par exemple) faire un \u00abvrai\u00bb Pierre-Feuille-Ciseaux entre deux cartes.
from microbit import *\nimport radio\n\nradio.on()\nradio.config(channel=12)\nradio.config(power=7)\n\nwhile True:\n message = radio.receive()\n if message:\n if message == 'yes':\n display.show(Image.YES)\n sleep(500)\n display.clear()\n elif message == 'no':\n display.show(Image.NO)\n sleep(500)\n display.clear()\n if button_a.was_pressed():\n radio.send('yes')\n display.show(Image.YES)\n sleep(500)\n display.clear()\n if button_b.was_pressed():\n radio.send('no')\n display.show(Image.NO)\n sleep(500)\n display.clear()\n
Plus de renseignements ici
Exercice 12
En utilisant l'exercice 10 et la communication radio, faire \u00abpasser\u00bb une led d'une carte \u00e0 l'autre en inclinant la carte.
video "},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/","title":"3.1 Microbit","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#0-presentation-de-la-carte-bbc-microbit","title":"0. Pr\u00e9sentation de la carte BBC micro:bit","text":"BBC micro:bit est une carte \u00e0 microcontr\u00f4leur con\u00e7ue en 2015 au Royaume-Uni pour d\u00e9velopper l'apprentissage de l'algorithmique et de la programmation.
La carte micro:bit dispose des sp\u00e9cificit\u00e9s techniques suivantes :
- 25 LEDs programmables individuellement
- 2 boutons programmables
- Broches de connexion
- Capteurs de lumi\u00e8re et de temp\u00e9rature
- Capteurs de mouvements (acc\u00e9l\u00e9rom\u00e8tre et boussole)
- Communication sans fil, via Radio et Bluetooth
- Interface USB
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#1-hello-world-virtuellement-ou-irl","title":"1. \"Hello world !\", virtuellement ou IRL...","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#11-a-distance-pas-de-microbit-le-simulateur-est-la","title":"1.1 \u00c0 distance ? Pas de micro:bit ? le simulateur est l\u00e0 !","text":"Rendez-vous sur la page https://create.withcode.uk/
Effacez le code existant et collez-le code ci-dessous :
from microbit import *\n\nwhile True:\n display.scroll('Hello, World!')\n display.show(Image.HEART)\n sleep(2000)\n
Cliquez sur le triangle vert en bas \u00e0 droite. C'est parti !
Pour \u00e9viter des erreurs, fermez la fen\u00eatre de droite (le simulateur) \u00e0 chaque fois que vous modifiez votre code de la partie gauche.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#12-avec-une-microbit-reelle","title":"1.2 Avec une micro:bit r\u00e9elle","text":" - Branchez la carte sur un port USB. Un lecteur MICROBIT apparait dans les p\u00e9riph\u00e9riques USB.
- Rendez-vous sur l'adresse https://create.withcode.uk/
- Modifiez le code pr\u00e9sent puis cliquez sur la fl\u00e8che verte.
- Vous pouvez t\u00e9l\u00e9charger le fichier .hex en cliquant sur Download HEX.
- Transf\u00e9rez (par copier-coller, ou \"envoyer vers\") ce fichier .hex dans votre lecteur micro:bit.
Cette proc\u00e9dure est \u00e0 r\u00e9peter \u00e0 chaque nouveau code.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#2-decouverte-des-fonctionnalites","title":"2. D\u00e9couverte des fonctionnalit\u00e9s","text":""},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#21-commandes-de-base-de-lafficheur-matrice-de-5x5-leds","title":"2.1 Commandes de base de l'afficheur, matrice de 5x5 LEDs","text":"voir vid\u00e9o explicative (en anglais)
LED signifie Light Emitting Diode, Diode \u00e9lectroluminescente. La carte micro:bit en dispose de 25, toutes programmables individuellement, ce qui permet d'afficher du texte, des nombres et des images.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#211-afficher-un-texte-defilant-displayscrollstring-delay400","title":"2.1.1 Afficher un texte \"d\u00e9filant\" display.scroll(string, delay=400)
","text":"from microbit import *\ndisplay.scroll(\"NSI\")\n
La premi\u00e8re ligne de ce programme importe la biblioth\u00e8que de fonctions micro:bit. La deuxi\u00e8me ligne fait d\u00e9filer un message \u00e0 l\u2019\u00e9cran. Cela n'arrive qu'une seule fois.
La vitesse de d\u00e9filement peut \u00eatre ralentie ou acc\u00e9l\u00e9r\u00e9e \u00e0 l'aide du param\u00e8tre delay
. L'unit\u00e9 est la milliseconde.
from microbit import *\ndisplay.scroll(\"mauriac\", delay=20)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#212-afficher-une-image-displayshowimage","title":"2.1.2 Afficher une \"image\" display.show(image)
","text":"Ex\u00e9cuter le programme suivant:
from microbit import *\ndisplay.show(Image.SAD)\n
Liste des images disponibles Image.HEART\nImage.HEART_SMALL\nImage.HAPPY\nImage.SMILE\nImage.SAD\nImage.CONFUSED\nImage.ANGRY\nImage.ASLEEP\nImage.SURPRISED\nImage.SILLY\nImage.FABULOUS\nImage.MEH\nImage.YES\nImage.NO\nImage.CLOCK12\nImage.CLOCK11\nImage.CLOCK10\nImage.CLOCK9\nImage.CLOCK8\nImage.CLOCK7\nImage.CLOCK6\nImage.CLOCK5\nImage.CLOCK4\nImage.CLOCK3\nImage.CLOCK2\nImage.CLOCK1\nImage.ARROW_N\nImage.ARROW_NE\nImage.ARROW_E\nImage.ARROW_SE\nImage.ARROW_S\nImage.ARROW_SW\nImage.ARROW_W\nImage.ARROW_NW\nImage.TRIANGLE\nImage.TRIANGLE_LEFT\nImage.CHESSBOARD\nImage.DIAMOND\nImage.DIAMOND_SMALL\nImage.SQUARE\nImage.SQUARE_SMALL\nImage.RABBIT\nImage.COW\nImage.MUSIC_CROTCHET\nImage.MUSIC_QUAVER\nImage.MUSIC_QUAVERS\nImage.PITCHFORK\nImage.XMAS\nImage.PACMAN\nImage.TARGET\nImage.TSHIRT\nImage.ROLLERSKATE\nImage.DUCK\nImage.HOUSE\nImage.TORTOISE\nImage.BUTTERFLY\nImage.STICKFIGURE\nImage.GHOST\nImage.SWORD\nImage.GIRAFFE\nImage.SKULL\nImage.UMBRELLA\nImage.SNAKE\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#creer-sa-propre-image","title":"Cr\u00e9er sa propre image","text":"Chaque pixel LED sur l\u2019affichage physique peut prendre une parmi dix valeurs. Si un pixel prend la valeur 0 c\u2019est qu\u2019il est \u00e9teint. Litt\u00e9ralement, il a une luminosit\u00e9 de z\u00e9ro. En revanche, s\u2019il prend la valeur 9 il est \u00e0 la luminosit\u00e9 maximale. Les valeurs de 1 \u00e0 8 repr\u00e9sentent des niveaux de luminosit\u00e9 entre \u00e9teint (0) et \u00ab au maximum \u00bb (9).
from microbit import *\n\nbateau = Image(\"05050:\"\n \"05050:\"\n \"05050:\"\n \"99999:\"\n \"09990\")\n\ndisplay.show(bateau)\n
Comment dessiner une image? Chaque ligne de l\u2019affichage physique est repr\u00e9sent\u00e9e par une ligne de nombres se terminant par :
et entour\u00e9e de guillemets doubles \"
. Chaque nombre indique une luminosit\u00e9. Il y a cinq lignes de cinq nombres donc il est possible de sp\u00e9cifier la luminosit\u00e9 individuelle de chacune des cinq LED sur chacune des cinq lignes sur l\u2019affichage physique. C\u2019est ainsi que l'on cr\u00e9e une image.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#213-les-pixels-displayset_pixelx-y-val","title":"2.1.3 Les pixels (display.set_pixel(x, y, val)
)","text":"Vous pouvez r\u00e9gler la luminosit\u00e9 des pixels de l'affichage individuellement de 0 (d\u00e9sactiv\u00e9) \u00e0 9 (luminosit\u00e9 maximale). Pour des informations sur les coordonn\u00e9es de l'affichage, voir le guide pour matrice \u00e0 LED.
Ex\u00e9cuter le programme suivant:
from microbit import *\ndisplay.set_pixel(1, 4, 9)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#22-boucle-while","title":"2.2 Boucle while
","text":"Le programme suivant utilise une boucle while
pour faire clignoter le pixel central de mani\u00e8re r\u00e9p\u00e9t\u00e9e sur l\u2019\u00e9cran. La boucle while
se r\u00e9p\u00e8te tant que la condition sp\u00e9cifi\u00e9e est vraie (True
). Dans ce cas, nous avons dit que la condition est vraie. Cela cr\u00e9e une boucle infinie.
L'instruction de veille sleep()
provoque la pause du micro:bit pendant un nombre d\u00e9fini de millisecondes choisi entre parenth\u00e8ses.
L'instruction display.clear()
\u00e9teint l'affichage.
Ex\u00e9cuter le programme ci-dessous:
from microbit import *\nwhile True:\n display.set_pixel(2, 2, 9)\n sleep(500)\n display.clear()\n sleep(500)\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#avec-un-peu-daleatoire-voir-documentation-sur-le-hasard","title":"Avec un peu d'al\u00e9atoire (voir documentation sur le hasard)","text":"Dans le programme suivant que vous ex\u00e9cuterez, on importe randint
du module random
de MicroPython et on l'utilise pour afficher un pixel au hasard sur la matrice.
from microbit import *\nfrom random import randint\nn=randint(0,4)\np=randint(0,4)\ndisplay.set_pixel(n, p, 9)\n
Tester le programme pr\u00e9c\u00e9dent plusieurs fois de suite. Pour cela, red\u00e9marrer la micro:bit en appuyant sur le bouton RESET
situ\u00e9 \u00e0 l'arri\u00e8re de la carte.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#23-boucle-for","title":"2.3 Boucle for
","text":"Le programme suivant utilise une boucle for
pour faire d\u00e9filer un pixel sur une ligne. Ex\u00e9cutez-le.
from microbit import *\nwhile True:\n for i in range(5):\n display.set_pixel(i,0,9)\n sleep(200)\n display.clear()\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#24-les-entrees-boutons-a-b-et-ab-programmation-evenementielle-video-explicative","title":"2.4 Les entr\u00e9es boutons A, B et A+B - programmation \u00e9v\u00e9nementielle (vid\u00e9o explicative)","text":"Il y a deux boutons sur la face avant du micro:bit (\u00e9tiquet\u00e9s A et B). On peut d\u00e9tecter quand ces boutons sont press\u00e9s, ce qui permet de d\u00e9clencher des instructions sur l'appareil.
Exemples avec le boutton A: - button_a.is_pressed()
: renvoie True si le bouton sp\u00e9cifi\u00e9 est actuellement enfonc\u00e9 et False sinon. - button_a.was_pressed()
: renvoie True ou False pour indiquer si le bouton a \u00e9t\u00e9 appuy\u00e9 depuis le d\u00e9marrage de l'appareil ou la derni\u00e8re fois que cette m\u00e9thode a \u00e9t\u00e9 appel\u00e9e.
Exemple : Essayer le programme suivant qui fait d\u00e9filer le texte \"NSI\" ind\u00e9finiment. On introduit l'instruction conditionnelle if
qui va tester si le bouton A a \u00e9t\u00e9 press\u00e9 (pendant le d\u00e9filement du texte ou pendant la pause), auquel cas le programme s'arr\u00eate en ex\u00e9cutant la commande break
.
from microbit import *\nwhile True:\n display.scroll(\"NSI\")\n sleep(200)\n if button_a.was_pressed():\n break\n
Exercice 1
\u00c9nonc\u00e9Correction Cr\u00e9er le code permettant de basculer d'un visage triste \u00e0 un visage heureux suivant qu'on appuie sur A ou sur B.
from microbit import *\ndisplay.clear()\nwhile True:\n if button_a.was_pressed():\n display.show(Image.SAD)\n if button_b.was_pressed():\n display.show(Image.HAPPY)\n
Exercice 2
\u00c9nonc\u00e9Correction On veut cr\u00e9er le code permettant de d\u00e9placer un point vers la gauche ou vers la droite en appuyant sur A ou sur B.
Compl\u00e9ter le code propos\u00e9 :
from microbit import *\ndisplay.clear()\ni = 12\nwhile True:\n x = ... # \u00e0 compl\u00e9ter\n y = ... # \u00e0 compl\u00e9ter\n display.set_pixel(x,y,9)\n if button_a.was_pressed():\n display.set_pixel(x,y,0)\n i = i - 1\n if i < 0 : \n i = 0\n if button_b.was_pressed():\n display.set_pixel(x,y,0)\n i = i + 1\n if i > 24 :\n i = 24\n
Exercice 3
\u00c9nonc\u00e9Correction Cr\u00e9er le code permettant de faire d\u00e9filer toutes les images disponibles. Bouton B pour passer \u00e0 l'image suivante, bouton A pour revenir \u00e0 l'image pr\u00e9c\u00e9dente.
Compl\u00e9ter le code propos\u00e9 :
from microbit import *\n\nlst = [Image.HEART, Image.HEART_SMALL, Image.HAPPY, Image.SMILE,\n Image.SAD, Image.CONFUSED, Image.ANGRY, Image.ASLEEP, Image.SURPRISED, Image.SILLY,\n Image.FABULOUS, Image.MEH, Image.YES, Image.NO, Image.CLOCK12,\n Image.CLOCK11, Image.CLOCK10, Image.CLOCK9, Image.CLOCK8, Image.CLOCK7,\n Image.CLOCK6, Image.CLOCK5, Image.CLOCK4, Image.CLOCK3, Image.CLOCK2,\n Image.CLOCK1, Image.ARROW_N, Image.ARROW_NE, Image.ARROW_E, Image.ARROW_SE,\n Image.ARROW_S, Image.ARROW_SW, Image.ARROW_W, Image.ARROW_NW, Image.TRIANGLE,\n Image.TRIANGLE_LEFT, Image.CHESSBOARD, Image.DIAMOND, Image.DIAMOND_SMALL, Image.SQUARE,\n Image.SQUARE_SMALL, Image.RABBIT, Image.COW, Image.MUSIC_CROTCHET, Image.MUSIC_QUAVER,\n Image.MUSIC_QUAVERS, Image.PITCHFORK, Image.XMAS, Image.PACMAN, Image.TARGET, Image.TSHIRT,\n Image.ROLLERSKATE, Image.DUCK, Image.HOUSE, Image.TORTOISE, Image.BUTTERFLY, Image.STICKFIGURE,\n Image.GHOST, Image.SWORD, Image.GIRAFFE, Image.SKULL, Image.UMBRELLA, Image.SNAKE]\n
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#25-capteur-de-lumiere-video","title":"2.5 Capteur de lumi\u00e8re (vid\u00e9o)","text":"En inversant les LEDs d'un \u00e9cran pour devenir un point d'entr\u00e9e, l'\u00e9cran LED devient un capteur de lumi\u00e8re basique, permettant de d\u00e9tecter la luminosit\u00e9 ambiante.
La commande display.read_light_level()
retourne un entier compris entre 0 et 255 repr\u00e9sentant le niveau de lumi\u00e8re.
Exercice : Compl\u00e9ter le programme ci-dessous qui affiche une image de lune si on baisse la luminosit\u00e9 (en recouvrant la carte avec sa main par exemple) et un soleil sinon.
from microbit import *\n\nsoleil = Image(\"90909:\"\n \"09990:\"\n \"99999:\"\n \"09990:\"\n \"90909:\")\n\nlune = Image(\"00999:\"\n \"09990:\"\n \"09900:\"\n \"09990:\"\n \"00999:\")\n\nwhile True:\n if display.read_light_level()> ... : #trouver la bonne valeur (entre 0 et 255)\n display.show(soleil)\n else:\n display.show(...) #trouver la bonne variable\n sleep(10)\n
Prolongement: cr\u00e9er un programme qui affiche le niveau de luminosit\u00e9 et le tester avec la LED d'un t\u00e9l\u00e9phone portable ou une lampe-torche par exemple. Plus la luminosit\u00e9 sera \u00e9lev\u00e9e, plus il y aura de LEDs affich\u00e9es sur la matrice.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#26-capteur-de-temperature-video","title":"2.6 Capteur de temp\u00e9rature (vid\u00e9o)","text":"Le micro:bit n\u2019a pas un capteur de temp\u00e9rature d\u00e9di\u00e9. Au lieu de cela, la temp\u00e9rature fournie est en fait la temp\u00e9rature de la puce de silicium du processeur principal. Comme le processeur chauffe peu en fonctionnement (c'est un processeur ARM \u00e0 grande efficacit\u00e9), sa temp\u00e9rature est une bonne approximation de la temp\u00e9rature ambiante. L'instruction temperature()
renvoie la temp\u00e9rature de la carte micro:bit en degr\u00e9s Celsius.
Exercice : Ecrire un programme qui affiche la temp\u00e9rature (aide: on pourra utiliser l'instruction display.scroll()
; revoir le point 2.1.1).
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#27-accelerometre-video","title":"2.7 Acc\u00e9l\u00e9rom\u00e8tre (vid\u00e9o)","text":"Un acc\u00e9l\u00e9rom\u00e8tre mesure l'acc\u00e9l\u00e9ration de la carte micro:bit, ce composant d\u00e9tecte quand la micro:bit est en mouvement. Il peut aussi d\u00e9tecter d'autres actions (gestes), par exemple quand elle est secou\u00e9e, inclin\u00e9e ou qu'elle tombe.
La carte micro:bit est munie d\u2019un acc\u00e9l\u00e9rom\u00e8tre. Il mesure le mouvement selon trois axes :
- X - l\u2019inclinaison de gauche \u00e0 droite.
- Y - l\u2019inclinaison d\u2019avant en arri\u00e8re.
- Z - le mouvement haut et bas.
Dans l'exemple suivant \u00e0 essayer, l'instruction accelerometer.get_x()
permet de d\u00e9tecter un mouvement de gauche \u00e0 droite en renvoyant un nombre compris entre -1023 et 1023; 0 \u00e9tant la position \"d'\u00e9quilibre\"
#Exemple\nfrom microbit import *\n\nwhile True:\n abscisse = accelerometer.get_x()\n if abscisse > 500:\n display.show(Image.ARROW_E)\n elif abscisse < -500:\n display.show(Image.ARROW_W)\n else:\n display.show(\"-\")\n
Prolongement (secouer les d\u00e9s!):
Exercice 4
\u00c9nonc\u00e9Correction \u00c9crire un programme qui simule un d\u00e9 en affichant une face au hasard lorsque la micro:bit est secou\u00e9e. On pourra utiliser l'instruction accelerometer.is_gesture(shake)
qui teste si la carte est secou\u00e9e. Plus d'informations sur les gestes ici.
"},{"location":"T3_Architecture_materielle/3.1_Microbit/cours_old/#28-boussole","title":"2.8 Boussole","text":"La boussole d\u00e9tecte le champ magn\u00e9tique de la Terre, nous permettant de savoir quelle direction la micro:bit indique. La boussole doit \u00eatre \u00e9talonn\u00e9e avant de pouvoir \u00eatre utilis\u00e9e. Pour cela, on utilise compass.calibrate()
qui ex\u00e9cute un petit jeu: au d\u00e9part, micro:bit fait d\u00e9filer \"Tilt to fill screen\". Ensuite, incliner micro:bit pour d\u00e9placer le point au centre de l\u2019\u00e9cran autour jusqu'\u00e0 ce que vous ayez rempli la totalit\u00e9 de l\u2019\u00e9cran.
La fonction compass.heading()
donne le cap de la boussole sous la forme d'un entier compris entre 0 et 360, repr\u00e9sentant l'angle en degr\u00e9s, dans le sens des aiguilles d'une montre, avec le nord \u00e9gal \u00e0 0.
Exercice : Compl\u00e9ter le programme suivant qui indique le Nord.
from microbit import *\n\ncompass.calibrate()\n\nwhile True:\n if compass.heading() < \"remplir ici\" or compass.heading() > \"remplir ici\":\n display.show(Image.ARROW_N)\n else:\n display.show(Image.DIAMOND_SMALL)\n
Prolongement: Am\u00e9liorer le programme pour que le micro:bit indique \"N\", \"S\", \"E\" et \"O\" en fonction de l'orientation de la boussole.
Autre prolongement: fabriquer une station m\u00e9t\u00e9o qui d\u00e9termine la direction du vent.
Autre prolongement: \u00e9tudier l'intensit\u00e9 du champ magn\u00e9tique autour du p\u00e9riph\u00e9rique (en utilisant la fonction compass.get_field_strength()
). Plus d'informations sur les fonctions \"boussole\" ici.
document bas\u00e9 sur le travail de Thomas Basso, acad\u00e9mie de Polyn\u00e9sie
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/","title":"3.2 Architecture Von Neumann","text":"John Von Neumann (1903-1957) est un math\u00e9maticien et physicien (et bien d'autres choses) am\u00e9ricano-hongrois. Il a le premier th\u00e9oris\u00e9 l'architecture des processeurs, tels qu'ils fonctionnent encore aujourd'hui.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#1-architecture-von-neumann","title":"1. Architecture von Neumann","text":"On distingue 4 zones essentielles :
- le CPU (Central Processing Unit) qui contient lui-m\u00eame :
- l'Unit\u00e9 Arithm\u00e9tique et Logique (UAL) dans laquelle sont effectu\u00e9es les op\u00e9rations de base (addition, multiplication...) Cette zone comporte notamment les registres (peu nombreux, de l'ordre de la dizaine) qui sont les espaces de travail ultra-rapides dans lesquels l'UAL va effectuer ses calculs. Une fois ceux-ci effectu\u00e9s, les valeurs des registres repartent dans la m\u00e9moire.
- l'Unit\u00e9 de contr\u00f4le, qui va s\u00e9quencer les op\u00e9rations. Lorsqu'on parle d'un processeur \u00e0 3 GHz, cela signifie (approximativement) que Unit\u00e9 de Contr\u00f4le va envoyer l'ordre d'une nouvelle op\u00e9ration \u00e0 l'UAL 3 milliards de fois par seconde.
- la m\u00e9moire, qui contient \u00e0 la fois les donn\u00e9es \u00e0 traiter et les instructions du programme. Cette id\u00e9e de stocker au m\u00eame endroit donn\u00e9es et programme est l'id\u00e9e centrale de l'architecture von Neumann.
- les bus de communication (des fils \u00e9lectriques permettant de transporter les donn\u00e9es entre les diff\u00e9rents composants).
- les Entr\u00e9es/Sorties, permettant de g\u00e9rer les informations avec l'ext\u00e9rieur.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#2-activite-1-simulation-dun-programme-en-assembleur","title":"2. Activit\u00e9 1 : simulation d'un programme en assembleur","text":""},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#21-le-programme-que-nous-etudierons","title":"2.1 Le programme que nous \u00e9tudierons","text":"a = 3\nb = 5\nc = a + b\n
Ce programme est ici \u00e9crit en langage Python. Le processeur ne comprend pas ce langage : les instructions doivent lui \u00eatre pass\u00e9es en langage-machine. C'est le r\u00f4le des interpr\u00e9teurs (pour le Python, par exemple) ou des compilateurs (pour le C, par exemple) que de faire le lien entre le langage pratiqu\u00e9 par les humains (Python, C...) et le langage-machine, qui n'est qu'une succession de chiffres binaires.
Par exemple, notre code ci-dessus s'\u00e9crit
01010000 00001111 00011000 00000000\n00000000 00000000 01010000 00111111\n00011100 00000000 00000000 00000000\n01100000 00000011 01000000 00111111\n00100000 00000000 00000000 00000000\n00000000 00000000 00000000 00000000\n00000011 00000000 00000000 00000000\n00000101 00000000 00000000 00000000\n
en langage-machine. Comment a lieu cette transformation ?
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#22-au-plus-proche-de-la-machine-mais-encore-humainement-comprehensible-le-langage-assembleur","title":"2.2 Au plus proche de la machine mais encore humainement compr\u00e9hensible : le langage assembleur","text":"Il existe un langage dit de \"bas-niveau\" (au sens qu'il est plus proche du langage machine qu'un langage de haut-niveau comme le Python) qui permet de passer des instructions directement au processeur : c'est le langage assembleur (ou ASM).
En assembleur, notre programme s'\u00e9crirait (par exemple) :
.pos 0\n mrmovl a, %eax\n mrmovl b, %ebx\n addl %eax, %ebx\n rmmovl %ebx, c\n halt\n\n.align 4\na: .long 3\nb: .long 5\nc: .long 0 \n
-
Le simulateur Y86 permet de simuler la mani\u00e8re dont le processeur va ex\u00e9cuter ce programme.
-
Vous pouvez retrouver le programme \u00e0 charger ici.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#231-code-en-langage-machine","title":"2.3.1 Code en langage-machine :","text":"Sur la partie droite du simulateur, la zone M\u00e9moire contient, apr\u00e8s assemblage, la traduction de notre code en langage-machine :
500f1800\n0000503f\n1c000000\n6003403f\n20000000\n00000000\n03000000\n05000000\n
Une fois transform\u00e9 en binaire, on retrouve le code donn\u00e9 au d\u00e9but du paragraphe pr\u00e9c\u00e9dent.
Ressources sur les instructions Y86
Exercice 1
Coder en assembleur la s\u00e9quence d'instruction suivante :
w = 10\nx = 3\ny = 5\nz = w - (x + y)\n
Vous aurez pour cela besoin de l'instruction subl rA rB
qui effectue l'op\u00e9ration rB-rA
et la stocke dans rB
. (rA
et rB
sont les noms des registres).
Correction .pos 0\nmrmovl x, %eax\nmrmovl y, %ebx\nmrmovl w, %ecx\naddl %eax, %ebx\nsubl %ebx, %ecx\nrmmovl %ecx, z\nhalt\n\n.align 4\nw: .long 10\nx: .long 3\ny: .long 5\nz: .long 0\n
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#24-resume-des-notions-essentielles","title":"2.4 R\u00e9sum\u00e9 des notions essentielles","text":" - Les registres sont \u00e0 percevoir comme des zones de travail temporaires, \u00e0 l'acc\u00e8s tr\u00e8s rapide. Les donn\u00e9es font l'aller-retour entre la m\u00e9moire et le registre : elles sont stock\u00e9es en m\u00e9moire, passent dans le registre pour y \u00eatre modifi\u00e9es, et reviennent en m\u00e9moire.
- les donn\u00e9es ET les instructions sont stock\u00e9es ensemble dans la m\u00e9moire : c'est le principe fondateur de l'architecture Von Neumann. Ici, l'octet
03
situ\u00e9 \u00e0 l'adresse 0x000d
signifie qu'il va falloir ajouter (on le sait gr\u00e2ce au 60
qui pr\u00e9c\u00e8de) le registre num\u00e9rot\u00e9 0
(donc %eax
) au registre num\u00e9rot\u00e9 3
(donc %ebx
). On retrouve un octet de m\u00eame valeur 03
\u00e0 l'adresse 0x0018
. Mais dans ce cas, cet octet n'est pas une instruction mais une simple donn\u00e9e : c'est la valeur 3 qu'on a donn\u00e9e \u00e0 la variable a
dans notre programme.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#25-conclusion","title":"2.5 Conclusion","text":"Le simulateur Y86 nous a permis d'observer comment un processeur r\u00e9alise des op\u00e9rations \u00e9l\u00e9mentaires. Nous avons d\u00e9couvert le langage assembleur, qui est un langage beaucoup moins agr\u00e9able qu'un langage de haut-niveau, mais qui reste n\u00e9anmoins compr\u00e9hensible par un \u00eatre humain. Certains informaticiens codent (encore de nos jours) directement en langage assembleur, pour \"coller\" au mieux au processeur et optimiser les ressources.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#3-activite-2-modification-dun-programme-par-desassemblage","title":"3. Activit\u00e9 2 : modification d'un programme par d\u00e9sassemblage","text":"On consid\u00e8re ci-dessous le programme crackme.c
, r\u00e9dig\u00e9 en langage en C. Vous pouvez t\u00e9l\u00e9charger ce programme ici.
#include \"stdio.h\"\n#include \"stdlib.h\"\n#include \"string.h\"\n\nint main()\n{\n\nchar saisie[50] = \"\";\nprintf(\"Acc\u00e8s restreint : saisissez votre mot de passe \\n\");\nwhile (strcmp(saisie,\"NSIMAURIAC\")!=0)\n{\nprintf(\"Mot de passe ? \\n\");\nscanf(\"%s\",&saisie);\n}\n\nprintf(\"Acc\u00e8s autoris\u00e9 \\n\");\n\nreturn 0;\n} \n
- Que fait ce programme ?
- Quel est le mot de passe ?
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#31-compilation-et-execution-du-programme","title":"3.1 Compilation et ex\u00e9cution du programme","text":" - Dans un terminal, tapez l'instruction
gcc crackme.c -o crackme
- Tapez
./crackme
et jouez avec le programme.
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#32-observation-du-fichier-binaire","title":"3.2 Observation du fichier binaire","text":"\u00c0 l'aide du programme GHex , il est possible d'aller observer la valeur des octets directement dans le fichier binaire crackme
.
Ce fichier binaire est \u00e9crit en langage-machine. Il est donc incompr\u00e9hensible pour un autre humain... m\u00eame si GHex nous aide en affichant notamment (dans la partie droite) les cha\u00eenes de caract\u00e8res... dont notre mot de passe ;)
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#33-modification-du-fichier-binaire","title":"3.3 Modification du fichier binaire","text":"Dans notre code C l'instruction while (strcmp(saisie,\"NSIMAURIAC\")!=0)
est le c\u0153ur de la v\u00e9rification du mot de passe. En assembleur, elle va donner naissance \u00e0 une instruction JNE
(pour Jump if Not Equal, voir ici ). Cette instruction est cod\u00e9e en hexad\u00e9cimal par l'opcode 75 C5
. Nous allons rechercher ces octets et les remplacer par 90 90
, 90
\u00e9tant l'opcode pour NOP
(ne rien faire).
- Recherchez dans GHex
75 C5
. - Remplacez par
90 90
. - Sauvegardez le fichier sous le nom
crackme2
. Vous pouvez sinon le t\u00e9l\u00e9charger ici - Rendez ce fichier ex\u00e9cutable par
sudo chmod 777 crackme2
- Ex\u00e9cutez ce code et constatez les changements !
"},{"location":"T3_Architecture_materielle/3.2_Architecture_Von_Neumann/cours/#34-conclusion","title":"3.4 Conclusion","text":"Le d\u00e9sassemblage d'un programme est une op\u00e9ration tr\u00e8s complexe et les op\u00e9rations et cha\u00eenes de caract\u00e8res qui apparaissent sont souvent incompr\u00e9hensibles (parfois volontairement, dans le cas d'obfuscation de code). N\u00e9anmoins, il est parfois possible d'agir au niveau le plus bas (le langage-machine) pour modifier un code, comme nous venons de le faire.
Bibliographie - Num\u00e9rique et Sciences Informatiques, Terminale, T. BALABONSKI, S. CONCHON, J.-C. FILLIATRE, K. NGUYEN, \u00e9ditions ELLIPSES.
- Pr\u00e9pabac NSI, Terminale, G.CONNAN, V.PETROV, G.ROZSAVOLGYI, L.SIGNAC, \u00e9ditions HATIER.
- Cours du DIU-EIL, Architecture mat\u00e9rielle, Raymond Namyst, Universit\u00e9 de Bordeaux.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/","title":"3.3 Architecture d'un r\u00e9seau","text":"Ce cours a pour but de pr\u00e9senter la constitution classique d'un r\u00e9seau, et les \u00e9quipements associ\u00e9s. La partie relative aux protocoles utilis\u00e9s lors des \u00e9changes entre deux machines est d\u00e9taill\u00e9e dans le cours sur les protocoles de communication.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#1-premier-reseau-local","title":"1. Premier r\u00e9seau local","text":"Installation de Filius
Installation de la version 1.14.2 pour nos machines virtuelles :
- T\u00e9l\u00e9charger le fichier filius_1.14.2_all.deb
- Dans un terminal ouvert dans le dossier T\u00e9l\u00e9chargements, taper
sudo dpkg -i filius_2.4.0_all.deb
Testons le ping
de la machine 192.168.0.1
vers la machine 192.168.0.3
.
R\u00e9sultat du ping "},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#11-la-carte-reseau-et-son-adresse-mac","title":"1.1. La carte r\u00e9seau et son adresse MAC","text":"Chaque ordinateur sur le r\u00e9seau dispose d'une adresse MAC, qui une valeur unique attribu\u00e9e \u00e0 sa carte r\u00e9seau (Ethernet, Wifi, 4G, 5G, ...) lors de sa fabrication en usine.
Cette adresse est cod\u00e9e sur 48 bits, pr\u00e9sent\u00e9s sous la forme de 6 octets en hexad\u00e9cimal. Exemple : fc:aa:14:75:45:a5
Les trois premiers octets correspondent au code du fabricant. Un site comme https://www.macvendorlookup.com/ vous permet de retrouver le fabricant d'une adresse MAC quelconque.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#12-switch-hub-quelle-difference","title":"1.2. Switch, hub, quelle diff\u00e9rence ?","text":" - Au sein d'un hub Ethernet (de moins en moins vendus), il n'y a aucune analyse des donn\u00e9es qui transitent : il s'agit simplement d'un d\u00e9doublement des fils de cuivre (tout comme une multiprise \u00e9lectrique). L'int\u00e9gralit\u00e9 des messages est donc envoy\u00e9e \u00e0 l'int\u00e9gralit\u00e9 des ordinateurs du r\u00e9seau, m\u00eame s'ils ne sont pas concern\u00e9s.
- Au sein d'un switch Ethernet , une analyse est effectu\u00e9e sur la trame qui est \u00e0 distribuer (voir ici). Lors d'un branchement d'un nouvel ordinateur sur le switch, celui-ci r\u00e9cup\u00e8re son adresse MAC, ce qui lui permet de trier les messages et de ne les distribuer qu'au bon destinataire.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#2-un-deuxieme-sous-reseau","title":"2. Un deuxi\u00e8me sous-r\u00e9seau","text":"Rajoutons un deuxi\u00e8me sous-r\u00e9seau de la mani\u00e8re suivante (penser \u00e0 bien renommer les switchs).
Comment relier ces deux sous-r\u00e9seaux ?
Une r\u00e9ponse pas si b\u00eate : avec un cable entre les deux switchs !
Testons cette hypoth\u00e8se en essayant de pinger la machine 192.168.1.2
depuis la machine 192.168.0.1
.
R\u00e9sultat du ping Cela ne marche pas. L'ordinateur refuse d'envoyer le ping vers la machine 192.168.1.2
. (spoil : car elle n'est pas dans son sous-r\u00e9seau)
Temporairement, renommons la machine 192.168.1.2
en 192.168.0.33
. Testons \u00e0 nouveau le ping depuis la machine 192.168.0.1
.
R\u00e9sultat du ping Cela marche. Les paquets sont bien achemin\u00e9s.
Intuition : la notion de sous-r\u00e9seau n'est pas topologique (\u00abil suffit de relier les ordinateurs entre eux\u00bb) mais ob\u00e9it \u00e0 des r\u00e8gles num\u00e9riques.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#21-notion-de-masque-de-sous-reseau","title":"2.1. Notion de masque de sous-r\u00e9seau","text":"Dans Filius, lors de l'attribution de l'adresse IP \u00e0 une machine, une ligne nous permet de sp\u00e9cifier le masque de sous-r\u00e9seau (appel\u00e9 simplement \u00ab Masque \u00bb dans Filius). C'est ce masque qui va permettre de d\u00e9terminer si une machine appartient \u00e0 un sous-r\u00e9seau ou non, en fonction de son adresse IP.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#211-explication-basique","title":"2.1.1 Explication basique","text":" - Si le masque est
255.255.255.0
, toutes les machines partageant les m\u00eames trois premiers nombres de leur adresse IP appartiendront au m\u00eame sous-r\u00e9seau. Comme ceci est le r\u00e9glage par d\u00e9faut de Filius, cela explique pourquoi 192.168.0.33
et 192.168.0.1
sont sur le m\u00eame sous-r\u00e9seau, et pourquoi 192.168.1.2
et 192.168.0.1
ne sont pas sur le m\u00eame sous-r\u00e9seau.
Dans cette configuration, 256 machines peuvent donc appartenir au m\u00eame sous-r\u00e9seau (ce n'est pas tout \u00e0 fait le cas car des adresses finissant par 0 ou par 255 sont r\u00e9serv\u00e9es).
- Si le masque est
255.255.0.0
, toutes les machines partageant les m\u00eames deux premiers nombres de leur adresse IP appartiendront au m\u00eame sous-r\u00e9seau. Dans cette configuration, 65536 machines peuvent \u00eatre dans le m\u00eame sous-r\u00e9seau. (car 256^2=65536)
Exercice
- Renommons
192.168.0.33
en 192.168.1.2
et modifions son masque en 255.255.0.0
. - Modifions aussi le masque de
192.168.0.1
en 255.255.0.0
. - Testons le ping de
192.168.0.1
vers 192.168.1.2
.
R\u00e9sultat du ping Cela marche. Les deux machines appartiennent maintenant au m\u00eame sous-r\u00e9seau.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#212-explication-avancee","title":"2.1.2 Explication avanc\u00e9e","text":"Lorsqu'une machine A veut envoyer un message \u00e0 une machine B, elle doit d\u00e9terminer si cette machine :
- appartient au m\u00eame sous-r\u00e9seau : auquel cas le message est envoy\u00e9 directement via un ou plusieurs switchs.
- n'appartient pas au m\u00eame sous-r\u00e9seau : auquel cas le message doit d'abord transiter par un routeur (voir 3.)
Quelle op\u00e9ration permet de distinguer cette appartenance \u00e0 un m\u00eame sous-r\u00e9seau ?
Appelons IP_A
et IP_B
les adresses IP respectives des machines A et B. Appelons M
le masque de sous-r\u00e9seau. Nommons &
l'op\u00e9rateur de conjonction entre nombres binaires (voir ici):
Propri\u00e9t\u00e9
A et B appartiennent au m\u00eame sous-r\u00e9seau \u21d4 IP_A & M = IP_B & M
Exemple :
Cconsid\u00e9rons trois machines A, B, C d'IP respectives 192.168.129.10
, 192.168.135.200
et 192.168.145.1
, configur\u00e9es avec un masque de sous-r\u00e9seau \u00e9gal \u00e0 255.255.248.0
.
machine A machine B machine C IP 192.168.129.10 192.168.135.200 192.168.145.1 M 255.255.248.0 255.255.248.0 255.255.248.0 IP & M 192.168.128.0 192.168.128.0 192.168.144.0 Rappel des r\u00e8gles de calcul :
- pour tout octet
x
, x & 255 = x
et x & 0 = 0
. 129 & 248
s'\u00e9crit en binaire 10000001 & 11111000
qui vaut 10000000
, soit 128
en d\u00e9cimal.
Conclusion : les machines A et B sont sous le m\u00eame sous-r\u00e9seau, mais pas la machine C.
Exercice de bac Faire les questions Q1. et Q2. de l'exercice 5 du sujet La R\u00e9union J1 2022
Correction Q1.a. Une adresse IPv4 se code \u00e0 l'aide de 4 octets.
Correction Q1.b. Le PC3 a pour adresse 172.150.4.30 / 24
. Cela signfie que son masque, en notation CIDR, est 24. Ses 24 premiers bits sont donc \u00e0 1. Cela correspond au masque 255.255.255.0
en notation d\u00e9cimale.
Correction Q2. "},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#213-coherence-entre-les-deux-explications","title":"2.1.3 Coh\u00e9rence entre les deux explications","text":"Lorsqu'un masque de sous-r\u00e9seau est \u00e9gal \u00e0 255.255.255.0
, l'op\u00e9ration de conjonction &
avec chaque IP ne laissera intacts que les 3 premiers octets, le dernier sera \u00e9gal \u00e0 0. Donc si deux adresses s'\u00e9crivent A.B.C.X
et A.B.C.Y
, elles appartiendront forc\u00e9ment au m\u00eame sous-r\u00e9seau (typiquement, c'est le cas de 192.168.0.33
et 192.168.0.1
).
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#22-ecriture-des-masques-de-sous-reseau-notation-cidr","title":"2.2 \u00c9criture des masques de sous-r\u00e9seau : notation CIDR","text":"D'apr\u00e8s ce qui pr\u00e9c\u00e8de, 2 informations sont n\u00e9cessaires pour d\u00e9terminer le sous-r\u00e9seau auquel appartient une machine : son IP et le masque de sous-r\u00e9seau. Une convention de notation permet d'\u00e9crire simplement ces deux renseignements : la notation CIDR.
Exemple : Une machine d'IP 192.168.0.33
avec un masque de sous-r\u00e9seau 255.255.255.0
sera d\u00e9sign\u00e9e par 192.168.0.33 / 24
en notation CIDR.
Le suffixe / 24
signifie que le masque de sous-r\u00e9seau commence par 24 bits cons\u00e9cutifs de valeur 1 : le reste des bits (donc 8 bits) est \u00e0 mis \u00e0 0. Autrement dit, ce masque vaut 11111111.11111111.11111111.00000000
, soit 255.255.255.0
. De la m\u00eame mani\u00e8re, le suffixe / 16
donnera un masque de 11111111.11111111.00000000.00000000
, soit 255.255.0.0
. Ou encore, un suffixe / 21
donnera un masque de 11111111.11111111.11111000.00000000
, soit 255.255.248.0
.
(lien vers le cours sur le binaire)
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#23-adresses-ip-et-masques-ce-quil-faut-retenir","title":"2.3 Adresses IP et masques : ce qu'il faut retenir","text":" D\u00e9finition
- Les ordinateurs s'identifient sur les r\u00e9seaux \u00e0 l'aide d'une adresse IP (Internet Protocol).
- Suivant la norme IPv4, les adresses IP sont encod\u00e9es sur 4 octets : on parle d'IPv4.
- Chaque octet pouvant varier de la valeur (d\u00e9cimale) 0 \u00e0 255, cela signifie que les adresses IP th\u00e9oriquement possibles vont de
0.0.0.0
\u00e0 255.255.255.255
. - Il y a donc \\(256^4=4 294 967 296\\) adresses possibles. On a longtemps cru que ce nombre serait suffisant. Ce n'est plus le cas, on est donc en train de passer sur des adresses \u00e0 6 octets (en hexad\u00e9cimal) : voir la norme IPv6.
Exemple
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#3-un-vrai-reseau-contenant-deux-sous-reseaux-distincts-la-necessite-dun-routeur","title":"3. Un vrai r\u00e9seau contenant deux sous-r\u00e9seaux distincts : la n\u00e9cessit\u00e9 d'un routeur","text":"Notre solution initiale (relier les deux switchs par un cable pour unifier les deux sous-r\u00e9seaux) n'est pas viable \u00e0 l'\u00e9chelle d'un r\u00e9seau plan\u00e9taire.
Pour que les machines de deux r\u00e9seaux diff\u00e9rents puissent \u00eatre connect\u00e9es, on va utiliser un dispositif \u00e9quip\u00e9 de deux cartes r\u00e9seaux, situ\u00e9 \u00e0 cheval entre les deux sous-r\u00e9seaux. Ce \u00e9quipement de r\u00e9seau est appel\u00e9 routeur ou passerelle.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#31-principe-de-fonctionnement","title":"3.1 Principe de fonctionnement","text":"Imaginons que la machine 192.168.0.1 / 24
veuille communiquer avec la machine 172.16.52.3 / 24
. L'observation du masque de sous-r\u00e9seau de la machine 192.168.0.1 / 24
nous apprend qu'elle ne peut communiquer qu'avec les adresses de la forme 192.168.0.X / 24
, o\u00f9 X
est un nombre entre 0 et 255.
Les 3 \u00e9tapes du routage :
- Lorsque qu'une machine A veut envoyer un message \u00e0 une machine B, elle va tout d'abord v\u00e9rifier si cette machine appartient \u00e0 son r\u00e9seau local. si c'est le cas, le message est envoy\u00e9 par l'interm\u00e9diaire du switch qui relie les deux machines.
- Si la machine B n'est pas trouv\u00e9e sur le r\u00e9seau local de la machine A, le message va \u00eatre achemin\u00e9 vers le routeur, par l'interm\u00e9diaire de son adresse de passerelle (qui est bien une adresse appartenant au sous-r\u00e9seau de A).
- De l\u00e0, le routeur va regarder si la machine B appartient au deuxi\u00e8me sous-r\u00e9seau auquel il est connect\u00e9. Si c'est le cas, le message est distribu\u00e9, sinon, le routeur va donner le message \u00e0 un autre routeur auquel il est connect\u00e9 et va le charger de distribuer ce message : c'est le proc\u00e9d\u00e9 (complexe) de routage, qui sera vu en classe de Terminale.
Dans notre exemple, l'adresse 172.16.52.3
n'est pas dans le sous-r\u00e9seau de 192.168.0.1
. Le message va donc transiter par le routeur.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#32-illustration-avec-filius","title":"3.2 Illustration avec Filius","text":" -
Rajoutons un routeur entre le SwitchA et le SwitchB.
-
Configuration du routeur : L'interface reli\u00e9e au Switch A doit avoir une adresse du sous-r\u00e9seau A. On donne souvent une adresse finissant par 254
, qui est en quelque sorte la derni\u00e8re adresse du r\u00e9seau (en effet l'adresse en 255
est appel\u00e9e adresse de broadcast, utilis\u00e9e pour pinger en une seule fois l'int\u00e9gralit\u00e9 d'un sous-r\u00e9seau). On donne donc l'adresse 192.168.0.254
pour l'interface reli\u00e9e au Switch A, et 192.168.1.254
pour l'interface reli\u00e9e au Switch B. Dans l'onglet g\u00e9n\u00e9ral, s\u00e9lectionner \u00ab Routage automatique \u00bb. Ainsi configur\u00e9 notre routeur peut jouer le r\u00f4le de passerelle entre les deux sous-r\u00e9seaux.
Test du ping entre 192.168.0.1
et 192.168.1.2
Cela ne marche pas. La carte r\u00e9seau refuse d'envoyer les paquets car elle ne sait pas o\u00f9 les envoyer.
Pourquoi cet \u00e9chec ? Parce que nous devons dire \u00e0 chaque machine qu'une passerelle est maintenant disponible pour pouvoir sortir de son propre sous-r\u00e9seau. Il faut donc aller sur la machine 192.168.0.1
et lui donner l'adresse de sa passerelle, qui est 192.168.0.254
.
Attention, il faut faire de m\u00eame pour 192.168.1.2
(avec la bonne passerelle...) Testons \u00e0 nouveau le ping... Cette fois cela marche.
Plus int\u00e9ressant : effectuons un traceroute
entre 192.168.0.1
et 192.168.1.2
.
On y aper\u00e7oit que la machine 192.168.1.2
est atteignable en deux sauts depuis 192.168.0.1
, en passant par la passerelle 192.168.0.254
Cas d'un r\u00e9seau domestique
Chez vous, la box de votre op\u00e9rateur joue simultan\u00e9ment le r\u00f4le de switch et de routeur :
- switch car elle r\u00e9partit la connexion entre les diff\u00e9rents dispositifs (ordinateurs branch\u00e9s en ethernet, smartphone en wifi, tv connect\u00e9e...)
- routeur car elle fait le lien entre ce sous-r\u00e9seau domestique (les appareils de votre maison) et le r\u00e9seau internet.
L'image ci-dessous pr\u00e9sente le r\u00e9sultat de la commande ipconfig
sous Windows. On y retrouve l'adresse IP locale 192.168.9.103
, le masque de sous-r\u00e9seau 255.255.255.0
et l'adresse de la passerelle 192.168.9.1
.
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#33-annexe-rajout-dun-serveur-dns","title":"3.3 Annexe : rajout d'un serveur DNS","text":""},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#331-rajout-dun-serveur-web","title":"3.3.1 Rajout d'un serveur web","text":" -
Connectons un ordinateur au SwitchB, sur l'adresse 192.168.1.30
et installons dessus un Serveur web et d\u00e9marrons-le.
-
Sur la machine 192.168.0.1
, rajoutons un Navigateur Web. En tapant dans la barre d'adresse l'adresse IP du Serveur web, la page d'accueil de Filius s'affiche.
Lors d'une utilisation classique d'un navigateur web, c'est une url m\u00e9morisable qui s'affiche, et non une adresse IP : on retient en effet plus facilement https://www.google.com/
que http://216.58.213.131
, qui renvoient pourtant \u00e0 la m\u00eame adresse. La machine qui assure ce r\u00f4le d'annuaire entre les serveurs web et leur adresse IP s'appelle un serveur DNS. Pour pouvoir indexer la totalit\u00e9 des sites internet, son r\u00f4le est structur\u00e9 de mani\u00e8re hi\u00e9rarchique. Vous trouverez des d\u00e9tails ici
"},{"location":"T3_Architecture_materielle/3.3_Architecture_reseau/cours/#331-rajout-dun-serveur-dns","title":"3.3.1 Rajout d'un serveur DNS","text":" - Rajoutons un serveur DNS minimal, qui n'aura dans son annuaire d'un seul site. Il faut pour cela raccorder une nouvelle machine (mais une machine d\u00e9j\u00e0 sur le r\u00e9seau aurait tr\u00e8s bien pu jouer ce r\u00f4le), et installer dessus un serveur DNS.
-
Sur ce serveur DNS, associons l'adresse http://www.vivelansi.fr
\u00e0 l'adresse IP 192.168.1.30
.
-
De retour sur notre machine 192.168.0.1
, sp\u00e9cifions maintenant l'adresse du serveur DNS :
-
Depuis le navigateur web de la machine 192.168.0.1
, le site http://www.vivelansi.fr
est maintenant accessible.
Bibliographie
- Num\u00e9rique et Sciences Informatiques, 1re, T. BALABONSKI, S. CONCHON, J.-C. FILLIATRE, K. NGUYEN, \u00e9ditions ELLIPSES.
- Cours d'OpenClassrooms :
- https://openclassrooms.com/fr/courses/857447-apprenez-le-fonctionnement-des-reseaux-tcp-ip/854659-le-routage
- https://openclassrooms.com/fr/courses/1561696-les-reseaux-de-zero/3607286-ladressage-cidr
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/","title":"3.4 Protocoles de communication dans un r\u00e9seau","text":""},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#1-modele-osi-modele-internet","title":"1. Mod\u00e8le OSI, mod\u00e8le Internet","text":"Les bits transmis d'un ordinateur \u00e0 un autre contiennent, en plus des donn\u00e9es utiles (le mot \u00abbonjour\u00bb dans un email), une multitude de donn\u00e9es (tout aussi utiles) qui vont aider \u00e0 l'acheminement de ces bits au bon endroit, puis au bon ordinateur, puis au bon logiciel. Les diff\u00e9rents protocoles qui r\u00e9gissent cette transmission sont regroup\u00e9s dans ce qui est appel\u00e9 un mod\u00e8le. Deux mod\u00e8les synth\u00e9tisent ces protocoles :
- le mod\u00e8le Internet (ou mod\u00e8le TCP/IP, 1974), organis\u00e9 en 4 couches : liaison, r\u00e9seau, transport, application.
- le mod\u00e8le OSI (Open Systems Interconnection, 1984), organis\u00e9 en 7 couches : physique, liaison, r\u00e9seau, transport, session, pr\u00e9sentation,application.
Ces deux mod\u00e8les co\u00efncident suivant le sch\u00e9ma ci-dessus. Ce sont des mod\u00e8les th\u00e9oriques et d'une certaine rigidit\u00e9. Leur utilisation dans la pratique est parfois plus floue, avec des protocoles \u00e0 cheval sur plusieurs couches. Dans la suite de ce cours, nous \u00e9voquerons les couches par leur num\u00e9ro dans le mod\u00e8le OSI.
Lors de son \u00e9mission, un message va subir successivement toutes les transformations effectu\u00e9es par chaque couche, depuis sa cr\u00e9ation (couche 7) jusqu'\u00e0 sa transmission physique (couche 1).
Lorsque ce m\u00eame message sera r\u00e9ceptionn\u00e9, les transformations seront effectu\u00e9es dans l'ordre inverse, jusqu'\u00e0 la pr\u00e9sentation du message au destinataire.
-
couches 7-6-5 \u2014 couches application-pr\u00e9sentation-session : Ces couches (r\u00e9unies dans le mod\u00e8le Internet en une couche unique \u00abapplication\u00bb ) regroupent les protocoles n\u00e9cessaires \u00e0 la bonne mise en forme d'un message (au sens large) avant sa transmission. Ces protocoles peuvent \u00eatre de nature tr\u00e8s diff\u00e9rente : protocole HTTP pour la transmisson de pages web, protocole FTP pour le transfert de fichiers, protocoles POP ou IMAP pour le courrier \u00e9lectronique...
-
couche 4 \u2014 couche transport : Le protocole majeur de cette couche est le protocole TCP :
- il s'assure par SYN-ACK que l'\u00e9metteur et le r\u00e9cepteur sont pr\u00eats \u00e0 \u00e9changer des messages.
- il d\u00e9coupe en segments num\u00e9rot\u00e9s le message \u00e0 transmettre (c\u00f4t\u00e9 \u00e9metteur) ou bien recompose le message total en remettant les segments dans l'ordre (c\u00f4t\u00e9 r\u00e9cepteur). Les \u00e9l\u00e9ments \u00e9chang\u00e9s avec la couche inf\u00e9rieure sont des segments.
-
couche 3 \u2014 couche r\u00e9seau : C'est la couche o\u00f9 chaque segment num\u00e9rot\u00e9 est encapsul\u00e9 dans un paquet qui, suivant le protocole IP, va contenir son adresse source et son adresse de destination. C'est \u00e0 ce niveau que se d\u00e9cide si le message doit rester dans le r\u00e9seau local ou \u00eatre envoy\u00e9 sur un autre r\u00e9seau via la passerelle du routeur. Les \u00e9l\u00e9ments \u00e9chang\u00e9s avec la couche inf\u00e9rieure sont des paquets.
-
couche 2 \u2014 couche liaison : C'est l'encapsulation finale du message. Suivant le protocole Ethernet, les informations sont transmises d'une carte r\u00e9seau \u00e0 une autre, gr\u00e2ce \u00e0 leur adresse MAC (Media Access Controler). Les \u00e9l\u00e9ments \u00e9chang\u00e9s avec la couche inf\u00e9rieure sont des trames.
-
couche 1 \u2014 couche physique : C'est la couche o\u00f9 le message est transmis physiquement d'un point \u00e0 un autre. Par signal lumineux (fibre optique), par ondes (wifi), par courant \u00e9lectrique (Ethernet)... Les \u00e9l\u00e9ments transmis sont les bits.
Lors de son parcours, une trame peut \u00eatre partiellement d\u00e9capsul\u00e9e et remonter \u00e0 la couche 3, avant de redescendre et de continuer son chemin. C'est le cas notamment lors du passage dans un routeur. Mais jamais, lors de son acheminement, le contenu r\u00e9el du message n'est ouvert : les paquets transmis sont achemin\u00e9s de mani\u00e8re identique, qu'ils contiennent les \u00e9l\u00e9ments constitutifs d'une vid\u00e9o YouTube ou d'un email \u00e0 votre cousin.
Ce principe fondateur, actuellement menac\u00e9 par certains acteurs politiques et industriels, est connu sous l'expression \u00abla neutralit\u00e9 du net\u00bb.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#2-observation-des-trames-avec-filius","title":"2. Observation des trames avec Filius","text":""},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#21-ping-a-travers-un-switch","title":"2.1. Ping \u00e0 travers un switch","text":"Vous pouvez t\u00e9l\u00e9charger le fichier ping_switch.fls.
- Relions une machine
192.168.0.10
d'adresse MAC BC:81:81:42:9C:31
\u00e0 une machine 192.168.0.11
d'adresse MAC 2A:AB:AC:27:D6:A7
\u00e0 travers un switch.
- Observons la table SAT de notre switch : elle est vide, car aucune machine n'a encore cherch\u00e9 \u00e0 communiquer.
- Lan\u00e7ons un ping depuis
192.168.0.10
vers 192.168.0.11
et observons les donn\u00e9es \u00e9chang\u00e9es :
- Observons de plus pr\u00e8s la premi\u00e8re ligne de donn\u00e9es \u00e9chang\u00e9es.
Cette premi\u00e8re ligne est une requ\u00eate ARP. ARP est un protocole qui s'interface entre la couche 3 / r\u00e9seau (appel\u00e9e dans la capture d'\u00e9cran Internet) et la couche 2 / liaison (appel\u00e9e dans la capture d'\u00e9cran R\u00e9seau). Comme indiqu\u00e9 dans le commentaire, elle consiste \u00e0 un appel \u00e0 tout le r\u00e9seau : \"Est-ce que quelqu'un ici poss\u00e8de l'IP 192.168.0.11
?
Message 1 : \u00ab Qui poss\u00e8de l'IP 192.168.0.11
? \u00bb
Il faut comprendre \u00e0 cette \u00e9tape que l'adresse IP est totalement inutile pour r\u00e9p\u00e9rer un ordinateur dans un sous-r\u00e9seau. Ce sont les adresses MAC qui permettent de se rep\u00e9rer dans un sous-r\u00e9seau. Les adresses IP, elles, permettront \u00e9ventuellement d'acheminer le message jusqu'au bon sous-r\u00e9seau (elles n'int\u00e9ressent donc que les routeurs).
Revenons \u00e0 notre ping vers 192.168.0.11
.
La commande arp -a
effectu\u00e9e dans un terminal de la machine 192.168.0.10
nous permet de voir qu'elle ne conna\u00eet encore personne dans son sous-r\u00e9seau. La table de correspondance IP \u2b80 MAC ne contient que l'adresse de broadcast 255.255.255.255
, qui permet d'envoyer un message \u00e0 tout le r\u00e9seau.
Constatant qu'elle ne sait pas quelle est l'adresse MAC de 192.168.0.11
, la machine 192.168.0.10
commence donc par envoyer un message \u00e0 tout le sous-r\u00e9seau, par l'adresse MAC de broadcast FF:FF:FF:FF:FF:FF
. Le switch va lui aussi lui aussi relayer ce message \u00e0 tous les \u00e9quipements qui lui sont connect\u00e9s (dans notre cas, un seul ordinateur)
Message 2 : \u00ab Moi ! \u00bb
La machine 192.168.0.11
s'est reconnu dans le message de broadcast de la machine 192.168.0.10
. Elle lui r\u00e9pond pour lui donner son adresse MAC.
\u00c0 partir de ce moment, la machine 192.168.0.10
sait comment communiquer avec 192.168.0.11
. Elle l'\u00e9crit dans sa table arp
, afin de ne plus avoir \u00e0 \u00e9mettre le message n\u00b01 :
Le switch, qui a vu passer sur ses ports 0 et 1 des messages venant des cartes MAC BC:81:81:42:9C:31
et 2A:AB:AC:27:D6:A7
, peut mettre \u00e0 jour sa table SAT :
Par la suite, il saura sur quel port rediriger les messages destin\u00e9s \u00e0 ces deux adresses MAC. Un switch est un \u00e9quipement de r\u00e9seau de la couche 2 du mod\u00e8le OSI, il ne sait pas lire les adresses IP : il ne travaille qu'avec les adresses MAC.
Message 3 : le ping est envoy\u00e9
Sch\u00e9matisons cette trame Ethernet (couche 2 du mod\u00e8le OSI) :
Message 4 : le pong est retourn\u00e9
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#22-ping-a-travers-un-routeur","title":"2.2. Ping \u00e0 travers un routeur","text":"Vous pouvez t\u00e9l\u00e9charger le fichier ping_routeur.fls.
L'objectif est d'observer les diff\u00e9rentes trames lors d'un ping entre :
- la machine
192.168.0.1 / 24
(adresse MAC F9:E1:D6:0B:29:03
) et - la machine
192.168.1.1 / 24
(adresse MAC D3:79:96:B8:5C:A4
)
Le routeur est configur\u00e9 ainsi :
- interface sur le r\u00e9seau A :
- IP :
192.168.0.254
- MAC :
77:C2:22:C9:5C:E7
- interface sur le r\u00e9seau B :
- IP :
192.168.1.254
- MAC :
66:E5:4E:7D:0B:B0
\u00c9tape 0 : le routeur signale sa pr\u00e9sence
Lors de l'observation des messages re\u00e7us ou \u00e9mis par la machine 192.168.0.1
, on peut \u00eatre intrigu\u00e9 par ce tout premier message re\u00e7u, \u00e9mis par le routeur :
On peut y distinguer les 4 couches du mod\u00e8le Internet. Le routeur, par ce message distribu\u00e9 \u00e0 tous les \u00e9l\u00e9ments du sous-r\u00e9seau A (il envoie un message \u00e9quivalent sur son sous-r\u00e9seau B), d\u00e9clare sa pr\u00e9sence, et le fait qu'il poss\u00e8de deux interfaces, une pour chaque r\u00e9seau. Il se positionne ainsi comme une passerelle : \u00abc'est par moi qu'il faudra passer si vous voulez sortir de votre sous-r\u00e9seau\u00bb. Dans cette trame envoy\u00e9e figure son adresse MAC, de sorte que tous les membres de son sous-r\u00e9seau pourront donc communiquer avec lui.
\u00c9tape 1 : de 192.168.0.1
vers le routeur
La machine 192.168.0.1 / 24
calcule que la machine 192.168.1.1 / 24
avec laquelle elle veut communiquer n'est pas dans son sous-r\u00e9seau. Elle va donc envoyer son message \u00e0 sa passerelle, qui est l'adresse du routeur dans son sous-r\u00e9seau.
Cette premi\u00e8re trame est :
\u00c9tape 2 : le routeur d\u00e9capsule la trame
Le routeur est un \u00e9quipement de r\u00e9seau de couche 3 (couche r\u00e9seau). Il doit observer le contenu du paquet IP (sans remonter jusqu'au contenu du message) pour savoir, suivant le proc\u00e9d\u00e9 de routage (voir cours de Terminale), o\u00f9 acheminer ce paquet.
Dans notre cas, l'adresse IP 192.168.1.1
de destination lui est accessible : elle fait partie de son sous-r\u00e9seau B.
Le routeur va modifier la valeur du TTL (Time To Live), en la d\u00e9cr\u00e9mentant de 1. Si, apr\u00e8s de multiples routages, cette valeur devenait \u00e9gale \u00e0 0, ce paquet serait d\u00e9truit. Ceci a pour but d'\u00e9viter l'encombrement des r\u00e9seaux avec des paquets ne trouvant pas leur destination.
NAT : translation d'adresse Dans notre cas, le routeur va laisser intacte l'adresse IP Source. Ce n'est pas toujours le cas. Dans le cas classique de la box qui relie votre domicile \u00e0 internet, le routeur contenu dans celle-ci va remplacer l'adresse locale de votre ordinateur ou smartphone (ex 192.168.0.26
) par son IP publique (celle apparaissant sur whatsmyip.com, par exemple). Elle effectue ce qu'on appelle une translation d'adresse (NAT). Pourquoi ? Parce que sinon la r\u00e9ponse du serveur distant que vous interrogez serait envoy\u00e9e sur une adresse locale (votre adresse 192.168.0.26
), qui est introuvable depuis un r\u00e9seau ext\u00e9rieur. Il faut donc remplacer toutes les adresses locales par l'IP publique de votre box. Pour \u00e9viter que la r\u00e9ponse du serveur web que vous avez interrog\u00e9 ne soit affich\u00e9e sur l'ordinateur de vos parents, le routeur affecte des ports diff\u00e9rents \u00e0 chaque machine de son sous-r\u00e9seau. Ce port est inclus dans le message transmis au serveur, et il l'est aussi dans sa r\u00e9ponse : le routeur peut donc rediriger le trafic vers la bonne machine du sous-r\u00e9seau.
Le routeur va r\u00e9-encapsuler le paquet IP modifi\u00e9, et cr\u00e9er une nouvelle trame Ethernet en modifiant :
- l'adresse MAC source : il va mettre l'adresse MAC de son interface dans le sous-r\u00e9seau B.
- l'adresse MAC de destination : il va mettre l'adresse MAC de
192.168.1.1
(qu'il aura peut-\u00eatre r\u00e9cup\u00e9r\u00e9e au pr\u00e9alable par le protocole ARP)
Cette deuxi\u00e8me trame est donc :
On peut observer dans Filius cette trame, en se positionnant sur l'interface 192.168.1.254
du routeur, ou sur 192.168.1.1
:
En suivant le m\u00eame principe, la machine 192.168.1.1
pourra envoyer son pong.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#23-exercice","title":"2.3. Exercice","text":"Exercice de bac
\u00c9nonc\u00e9Correction Parties 2 et 3 de l'exercice 2 du sujet Nouvelle-Cal\u00e9donie J1 2022.
Partie 2
Correction Q1. Le r\u00e9seau services a pour adresse IP 195.168.254.0
.
Correction Q2. Le r\u00e9seau services a pour adresse 195.168.254.0
. Comme le masque de sous-r\u00e9seau utilis\u00e9 est 255.255.255.0
, 254 adresses sont initialement disponibles (195.168.254.1
\u00e0 195.168.254.254
, puisque l'adresse 195.168.254.255
est r\u00e9serv\u00e9e pour le broadcast sur le r\u00e9seau). Comme deux adresses sont d\u00e9j\u00e0 prises par le routeur 1 et le routeur 2, il en reste 252.
Correction Q3. Le serveur web acc\u00e8de \u00e0 internet via le routeur 2, dont l'adresse sur le r\u00e9seau services est 192.168.254.2
. C'est donc cette adresse qui joue est l'adresse de passerelle pour le serveur web.
Partie 3
Correction Q1. La ligne 2 montre que l'adresse MAC du serveur DNS est 8A:FD:54:49:D0:CC
.
Correction Q2. La couche Transport montre que le protocole utilis\u00e9 est le protocole UDP.
Correction Q3. Le commentaire de la couche Application indique que l'adresse IP du serveur web est 192.168.254.201
.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#3-protocole-du-bit-alterne","title":"3. Protocole du bit altern\u00e9","text":"Ce protocole est un exemple simple de fiabilisation du transfert de donn\u00e9es.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#1-contexte","title":"1. Contexte","text":" - Alice veut envoyer \u00e0 Bob un message M, qu'elle a pr\u00e9d\u00e9coup\u00e9 en sous-messages M0, M1, M2,...
- Alice envoie ses sous-messages \u00e0 une cadence \u0394t fix\u00e9e (en pratique, les sous-messages partent quand leur acquittement a \u00e9t\u00e9 re\u00e7u ou qu'on a attendu celui-ci trop longtemps : on parle alors de timeout)
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#2-situation-ideale","title":"2. Situation id\u00e9ale","text":"Dans cette situation, les sous-messages arrivent tous \u00e0 destination dans le bon ordre. La transmission est correcte.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#3-situation-reelle","title":"3. Situation r\u00e9elle","text":"Mais parfois, les choses ne se passent pas toujours aussi bien. Car si on ma\u00eetrise parfaitement le timing de l'envoi des sous-messages d'Alice, on ne sait pas combien de temps vont mettre ces sous-messages pour arriver, ni m\u00eame (attention je vais passer dans un tunnel) s'ils ne vont pas \u00eatre d\u00e9truits en route.
Le sous-message M0 est arriv\u00e9 apr\u00e8s le M1, le message M2 n'est jamais arriv\u00e9...
Que faire ?
\u00c9cartons l'id\u00e9e de num\u00e9roter les sous-messages, afin que Bob puisse remettre dans l'ordre les messages arriv\u00e9s, ou m\u00eame redemander sp\u00e9cifiquement des sous-messages perdus. C'est ce que r\u00e9alise le protocole TCP (couche 4 \u2014 transport), c'est tr\u00e8s efficace, mais cher en ressources. Essayons de trouver une solution plus basique.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#3-solution-naive","title":"3. Solution na\u00efve...","text":"Pourquoi ne pas demander \u00e0 Bob d'envoyer un signal pour dire \u00e0 Alice qu'il vient bien de recevoir son sous-message ? Nous appelerons ce signal ACK (comme acknowledgement, traduisible par \u00abaccus\u00e9 de r\u00e9ception\u00bb). Ce signal ACK permettra \u00e0 Alice de renvoyer un message qu'elle consid\u00e9rera comme perdu :
N'ayant pas re\u00e7u le ACK cons\u00e9cutif \u00e0 son message M1, Alice suppose (avec raison) que ce message n'est pas parvenu jusqu'\u00e0 Bob, et donc renvoie le message M1.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#4-mais-peu-efficace","title":"4. Mais peu efficace...","text":"Le deuxi\u00e8me ACK de Bob a mis trop de temps pour arriver (ou s'est perdu en route) et donc Alice a suppos\u00e9 que son sous-message M1 n'\u00e9tait pas arriv\u00e9. Elle l'a donc renvoy\u00e9, et Bob se retrouve avec deux fois le sous-message M1. La transmission est incorrecte. En faisant transiter un message entre Bob et Alice, nous multiplions par 2 la probabilit\u00e9 que des probl\u00e8mes techniques de transmission interviennent. Et pour l'instant rien ne nous permet de les d\u00e9tecter.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#5-bob-prend-le-controle","title":"5. Bob prend le contr\u00f4le","text":"Bob va maintenant int\u00e9grer une m\u00e9thode de validation du sous-message re\u00e7u. Il pourra d\u00e9cider de le garder ou de l'\u00e9carter. Le but est d'\u00e9viter les doublons.
Pour r\u00e9aliser ceci, Alice va rajouter \u00e0 chacun de ses sous-messages un bit de contr\u00f4le, que nous appelerons FLAG (drapeau). Au d\u00e9part, ce FLAG vaut 0. Quand Bob re\u00e7oit un FLAG, il renvoie un ACK \u00e9gal au FLAG re\u00e7u.
Alice va attendre ce ACK contenant le m\u00eame bit que son dernier FLAG envoy\u00e9 :
- tant qu'elle ne l'aura pas re\u00e7u, elle continuera \u00e0 envoyer le m\u00eame sous-message, avec le m\u00eame FLAG.
- d\u00e8s qu'elle l'a re\u00e7u, elle peut envoyer un nouveau sous-message en inversant (\u00abalternant\u00bb) le bit de son dernier FLAG (d'o\u00f9 le nom de ce protocole).
Bob, de son c\u00f4t\u00e9, va contr\u00f4ler la validit\u00e9 de ce qu'il re\u00e7oit : il ne gardera que les sous-messages dont le FLAG est \u00e9gal \u00e0 l'inverse de son dernier ACK. C'est cette m\u00e9thode qui lui permettra d'\u00e9carter les doublons.
Observons ce protocole dans plusieurs cas :
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#51-cas-ou-le-sous-message-est-perdu","title":"5.1 Cas o\u00f9 le sous-message est perdu","text":""},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#52-cas-ou-le-ack-est-perdu","title":"5.2 Cas o\u00f9 le ACK est perdu","text":"Le protocole a bien d\u00e9tect\u00e9 le doublon du sous-message M1.
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#53-cas-ou-un-sous-message-est-en-retard","title":"5.3 Cas o\u00f9 un sous-message est en retard","text":"Le protocole a bien d\u00e9tect\u00e9 le doublon du sous-message M1... mais que se passerait-il si notre premier sous-message M1 \u00e9tait encore plus en retard ?
"},{"location":"T3_Architecture_materielle/3.4_Protocoles_de_communication/cours/#6-conclusion","title":"6. Conclusion","text":"Le protocole du bit altern\u00e9 a longtemps \u00e9t\u00e9 utilis\u00e9 au sein de la couche 2 du mod\u00e8le OSI (distribution des trames Ethernet). Simple et l\u00e9ger, il peut toutefois \u00eatre facilement mis en d\u00e9faut, ce qui explique qu'il ait \u00e9t\u00e9 remplac\u00e9 par des protocoles plus performants.
Bibliographie - Num\u00e9rique et Sciences Informatiques, 1re, T. BALABONSKI, S. CONCHON, J.-C. FILLIATRE, K. NGUYEN, \u00e9ditions ELLIPSES. - Pr\u00e9pabac NSI 1\u00e8re, C.ADOBET, G.CONNAN, G. ROZSAVOLGYI, L.SIGNAC, \u00e9ditions Hatier.
"},{"location":"T3_Architecture_materielle/3.5_Decouverte_des_commandes_Linux/cours/","title":"3.5 D\u00e9couverte des commandes UNIX","text":"\u00e0 partir du jeu Terminus
Rendez-vous \u00e0 l'adresse http://luffah.xyz/bidules/Terminus/
Laissez-vous guider par le jeu, mais attention ! - vous devez noter sur un papier chaque nouvelle commande que vous apprenez. Vous pouvez par exemple construire un tableau de ce type :
- je vous conseille tr\u00e8s fortement d'\u00e9crire un plan du jeu au fur et \u00e0 mesure que vous avancez dans votre qu\u00eate. Par exemple :
"},{"location":"T3_Architecture_materielle/3.5_Decouverte_des_commandes_Linux/cours/#correction","title":"Correction","text":"Voici un corrig\u00e9 r\u00e9dig\u00e9 par Charles Poulmaire, de l'acad\u00e9mie de Versailles.
"},{"location":"T4_Algorithmique/sommaire/","title":"Th\u00e8me 4 : Algorithmique","text":" - Extremums et moyennes
- Complexit\u00e9
- Tri par insertion
- Tri par s\u00e9lection
- Dichotomie
- Algorithmes gloutons
- Algorithme KNN
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/cours/","title":"4.1 Extremums et moyennes","text":" Activit\u00e9 d'introduction
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/cours/#1-algorithme-de-recherche-de-maximum","title":"1. Algorithme de recherche de maximum","text":"Recherche de maximum
def recherche_max(tab):\n '''renvoie le maximum de la liste tab'''\n maxi = tab[0] # (1)\n for elt in tab:\n if elt > maxi:\n maxi = elt\n return maxi\n
- On initialise le maximum avec la premi\u00e8re valeur du tableau (surtout pas avec 0 ou \u00abmoins l'infini\u00bb !)
Utilisation :
>>> recherche_max([4, 3, 8, 1])\n 8\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/cours/#2-algorithme-de-calcul-de-moyenne","title":"2. Algorithme de calcul de moyenne","text":"Calcul de moyenne
def moyenne(tab):\n ''' renvoie la moyenne de tab'''\n somme = 0\n for elt in tab:\n somme += elt\n return somme / len(tab)\n
Utilisation :
>>> moyenne([4, 3, 8, 1])\n 4.0\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/cours/#3-algorithme-de-recherche-doccurrence","title":"3. Algorithme de recherche d'occurrence","text":"Recherche d'occurrence
def recherche_occurrence(elt, tab):\n ''' renvoie la liste (\u00e9ventuellement vide)\n des indices de elt dans tab'''\n liste_indices = []\n for i in range(len(tab)):\n if tab[i] == elt:\n liste_indices.append(i)\n return liste_indices\n
Utilisation :
>>> recherche_occurrence(3, [1, 6, 3, 8, 3, 2])\n[2, 4]\n>>> recherche_occurrence(7, [1, 6, 3, 8, 3, 2])\n[]\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/intro_cours/","title":"Vers les extremums et moyennes","text":""},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/intro_cours/#1-algorithme-de-recherche-de-maximum","title":"1. Algorithme de recherche de maximum","text":"On cherche \u00e0 coder une fonction recherche_max
qui prend en param\u00e8tre une liste tab
et qui renvoie le plus grand \u00e9l\u00e9ment de cette liste. L'usage de la fonction max
est interdit.
Utilisation :
>>> recherche_max([4, 3, 8, 1])\n 8\n
Code \u00e0 trous Recherche de maximum
def recherche_max(tab):\n '''renvoie le maximum de la liste tab'''\n
Code \u00e0 trous Recherche de maximum
def recherche_max(tab):\n '''renvoie le maximum de la liste tab'''\n ... = ... \n for ... in ...:\n if ... > ...:\n ... = ...\n return ...\n
Code \u00e0 trous Recherche de maximum
def recherche_max(tab):\n '''renvoie le maximum de la liste tab'''\n maxi = ... \n for elt in ...:\n if ... > ...:\n ... = ...\n return ...\n
Code \u00e0 trous Recherche de maximum
def recherche_max(tab):\n '''renvoie le maximum de la liste tab'''\n maxi = tab[0] \n for elt in tab:\n if ... > ...:\n maxi = ...\n return ...\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/intro_cours/#2-algorithme-de-calcul-de-moyenne","title":"2. Algorithme de calcul de moyenne","text":"On cherche \u00e0 coder une fonction moyenne
qui prend en param\u00e8tre une liste tab
et qui renvoie la moyenne des \u00e9l\u00e9ments de cette liste.
Utilisation :
>>> moyenne([4, 3, 8, 1])\n 4.0\n
Code \u00e0 trous Recherche de maximum
def moyenne(tab):\n ''' renvoie la moyenne de tab'''\n
Code \u00e0 trous Recherche de maximum
def moyenne(tab):\n ''' renvoie la moyenne de tab'''\n ... = ...\n for ... in ...:\n ... += ...\n return ... / ...\n
Code \u00e0 trous Recherche de maximum
def moyenne(tab):\n ''' renvoie la moyenne de tab'''\n somme = 0\n for elt in ...:\n ... += ...\n return ... / ...\n
Code \u00e0 trous Recherche de maximum
def moyenne(tab):\n ''' renvoie la moyenne de tab'''\n somme = 0\n for elt in tab:\n somme += ...\n return ... / ...\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/intro_cours/#3-algorithme-de-recherche-doccurrence","title":"3. Algorithme de recherche d'occurrence","text":"On cherche \u00e0 coder une fonction recherche_occurrence
qui prend en param\u00e8tre un \u00e9lement elt
et une liste tab
et qui renvoie la liste (\u00e9ventuellement vide) des indices de elt
dans tab
.
Utilisation :
>>> recherche_occurrence(3, [1, 6, 3, 8, 3, 2])\n[2, 4]\n>>> recherche_occurrence(7, [1, 6, 3, 8, 3, 2])\n[]\n
Code \u00e0 trous Recherche d'occurrence
def recherche_occurrence(elt, tab):\n ''' renvoie la liste (\u00e9ventuellement vide)\n des indices de elt dans tab'''\n
Code \u00e0 trous Recherche d'occurrence
def recherche_occurrence(elt, tab):\n ''' renvoie la liste (\u00e9ventuellement vide)\n des indices de elt dans tab'''\n ... = ...\n for ... in range(...):\n if ... == ...:\n ...\n return ...\n
Code \u00e0 trous Recherche d'occurrence
def recherche_occurrence(elt, tab):\n ''' renvoie la liste (\u00e9ventuellement vide)\n des indices de elt dans tab'''\n liste_indices = ...\n for i in range(...):\n if ... == ...:\n ....append(i)\n return ...\n
Code \u00e0 trous Recherche d'occurrence
def recherche_occurrence(elt, tab):\n ''' renvoie la liste (\u00e9ventuellement vide)\n des indices de elt dans tab'''\n liste_indices = []\n for i in range(len(tab)):\n if tab[i] == ...:\n ....append(i)\n return ...\n
"},{"location":"T4_Algorithmique/4.1_Extremums_et_moyennes/intro_cours/#3-algorithme-de-recherche-de-maximum-avec-indice","title":"3. Algorithme de recherche de maximum avec indice","text":"On cherche \u00e0 coder une fonction recherche_max_et_indice
qui prend en param\u00e8tre une liste tab
et qui renvoie le plus grand \u00e9l\u00e9ment de cette liste ainsi que l'indice de ce maximum dans la liste (si il est pr\u00e9sent plusieurs fois, un seul indice sera renvoy\u00e9). L'usage de la fonction max
est interdit.
Utilisation :
>>> recherche_max_et_indice([4, 1, 3, 8, 3, 8, 1])\n 8, 5\n
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/","title":"4.2 Complexit\u00e9 d'un algorithme","text":"La complexit\u00e9 d'un algorithme est une notion qui nous \u00e9claire sur la mani\u00e8re dont cet algorithme va \u00eatre sensible \u00e0 la taille des donn\u00e9es pass\u00e9es en param\u00e8tre. Il y a plusieurs types de complexit\u00e9s \u00e9tudiables (nombre d'op\u00e9rations, temps n\u00e9cessaire, espace-m\u00e9moire n\u00e9cessaire...).
En NSI, nous nous contenterons d'estimer (lorsque cela est possible) le nombre d'op\u00e9rations effectu\u00e9es par l'algorithme, et nous mesurerons les temps d'ex\u00e9cution de ces algortihmes.
Nous observerons surtout comment \u00e9volue ce temps d'ex\u00e9cution en fonction de la taille des donn\u00e9es pass\u00e9es en param\u00e8tre (la taille d'une liste, par exemple). Cela nous permettra dans ce cours de classer nos algorithmes en deux cat\u00e9gories : les algorithmes de complexit\u00e9 lin\u00e9aire et ceux de complexit\u00e9 quadratique.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#1-complexite-lineaire","title":"1. Complexit\u00e9 lin\u00e9aire","text":""},{"location":"T4_Algorithmique/4.2_Complexite/cours/#11-exemple","title":"1.1 Exemple","text":"Exemple d'algorithme
Votre travail est de mettre des bulletins dans des enveloppes pour une campagne de communication. L'algorithme en jeu ici est \"je prends un bulletin, je le plie, je le mets dans l'enveloppe, je ferme l'enveloppe\".
On suppose que vous travaillez \u00e0 un rythme constant. Le premier jour, on vous donne \\(n\\) enveloppes \u00e0 remplir. Vous mettez un temps \\(T\\) pour les traiter. Le deuxi\u00e8me jour, suite \u00e0 l'absence d'un employ\u00e9, on vous donne le double d'enveloppes, soit \\(2n\\) enveloppes. Combien de temps allez vous mettre pour les traiter ?
R\u00e9ponse Cela prendra deux fois plus de temps, donc \\(2T\\).
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#12-vocabulaire","title":"1.2 Vocabulaire","text":"On dit que l'algorithme ci-dessus est de complexit\u00e9 lin\u00e9aire.
Complexit\u00e9 lin\u00e9aire
Les expressions suivantes sont \u00e9quivalentes :
- L'algorithme est de complexit\u00e9 lin\u00e9aire.
- L'algorithme est d'ordre n.
- L'algorithme est en \\(O(n)\\) (\u00abgrand O de n\u00bb)
Toutes ces formulations renvoient \u00e0 la m\u00eame id\u00e9e : le nombre d'op\u00e9rations n\u00e9cessaires (et donc le temps n\u00e9cessaire \u00e0 la terminaison de l'algorithme) \u00e9volue proportionnellement avec le nombre de donn\u00e9es \u00e0 traiter.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#13-formulation-mathematique","title":"1.3 Formulation math\u00e9matique","text":"Si un employ\u00e9 A met 3 secondes par enveloppe, on aura \\(T_A=3n\\). Si un employ\u00e9 B met 20 secondes par enveloppe, on aura \\(T_B=20n\\).
On retrouve la formulation math\u00e9matique d'une fonction lin\u00e9aire \\(f\\).
\\[f : x \\mapsto ax \\quad\\text{ , avec } a \\in \\mathbb{R}\\] Ici, la fonction \\(f_A\\) serait \\(f_A(x)=3x\\), la fonction \\(f_B\\) serait \\(f_B(x)=20x\\)
Dans les deux cas l'algorithme a la m\u00eame complexit\u00e9 (lin\u00e9aire donc). Ce qui compte est le fait que pour chacun des employ\u00e9s, avoir deux fois plus d'enveloppes prendrait deux fois plus de temps.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#14-verification-experimentale","title":"1.4 V\u00e9rification exp\u00e9rimentale","text":"On consid\u00e8re la fonction ci-dessous :
def fabrique(n):\n liste = []\n for _ in range(n):\n liste.append(\"ok\")\n return liste\n
Le code ci-dessous va mesurer le temps d'ex\u00e9cution de cette fonction avec deux param\u00e8tres diff\u00e9rents : la valeur 400 puis la valeur 800.
import time\nt0 = time.time()\nlstA = fabrique(400)\nprint(\"temps pour une liste de taille 400 :\", time.time() - t0)\nt0 = time.time()\nlstB = fabrique(800)\nprint(\"temps pour une liste de taille 800 :\", time.time() - t0)\n
R\u00e9sultats de l'ex\u00e9cution :
temps pour une liste de taille 400 : 2.384185791015625e-05\ntemps pour une liste de taille 800 : 4.2438507080078125e-05\n
Interpr\u00e9tation : Doubler la taille du param\u00e8tre d'entr\u00e9e a eu pour effet de doubler (quasiment) le temps d'ex\u00e9cution. Cela semble indiquer que la complexit\u00e9 de cette fonction est lin\u00e9aire. En observant l'algorithme, nous pouvons confirmer cette supposition : le nombre d'op\u00e9rations de la boucle for
est \u00e9gal au param\u00e8tre n
, et est donc directement proportionnel \u00e0 la valeur de ce param\u00e8tre.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#2-complexite-quadratique","title":"2. Complexit\u00e9 quadratique","text":""},{"location":"T4_Algorithmique/4.2_Complexite/cours/#21-exemple","title":"2.1 Exemple","text":"Exemple d'algorithme
Vous avez l'habitude de tondre la pelouse de votre terrain carr\u00e9, de c\u00f4t\u00e9 \\(n\\). Cela vous prend un certain temps \\(T\\). Votre voisin vous propose de venir chez lui tondre son terrain carr\u00e9 de c\u00f4t\u00e9 \\(2n\\). Combien de temps cela va-t-il vous prendre pour tondre le terrain de votre voisin ?
R\u00e9ponse Cela vous prendra 4 fois plus de temps.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#22-vocabulaire","title":"2.2 Vocabulaire","text":"On dit que l'algorithme ci-dessus est de complexit\u00e9 quadratique.
Complexit\u00e9 quadratique
Les expressions suivantes sont \u00e9quivalentes :
- L'algorithme est de complexit\u00e9 quadratique.
- L'algorithme est d'ordre n au carr\u00e9.
- L'algorithme est en \\(O(n^2)\\) (\u00abgrand O de n carr\u00e9\u00bb)
Toutes ces formulations renvoient \u00e0 la m\u00eame id\u00e9e : le nombre d'op\u00e9rations n\u00e9cessaires (et donc le temps n\u00e9cessaire \u00e0 la terminaison de l'algorithme) \u00e9volue proportionnellement avec le carr\u00e9 du nombre de donn\u00e9es \u00e0 traiter.
Les algorithmes quadratiques sont moins \u00abint\u00e9ressants\u00bb que les algorithmes lin\u00e9aires, car ils vont consommer beaucoup plus de ressources. Lors de l'\u00e9laboration d'un algorithme, on va toujours essayer de trouver l'algorithme ayant la complexit\u00e9 la plus faible possible.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#23-verification-experimentale","title":"2.3 V\u00e9rification exp\u00e9rimentale","text":"Effectuer des mesures de temps d'ex\u00e9cution pour la fonction ci-dessous :
def tables(n):\n for a in range(n):\n for b in range(n):\n c = a * b\n
Le code ci-dessous va mesurer le temps d'ex\u00e9cution de cette fonction avec deux param\u00e8tres diff\u00e9rents : la valeur 100 puis la valeur 200.
import time\nt0 = time.time()\ntables(100)\nprint(\"temps pour n = 100 :\", time.time() - t0)\nt0 = time.time()\ntables(200)\nprint(\"temps pour n = 200 : \", time.time() - t0)\n
R\u00e9sultats de l'ex\u00e9cution :
temps pour n = 100 : 0.0003533363342285156\ntemps pour n = 200 : 0.0014693737030029297\n
Interpr\u00e9tation : Doubler la taille du param\u00e8tre d'entr\u00e9e a eu pour effet de quadrupler le temps d'ex\u00e9cution. Cela semble indiquer que la complexit\u00e9 de cette fonction est quadratique, car \\(2^2=4\\).
En observant l'algorithme, nous pouvons confirmer cette supposition : le nombre d'op\u00e9rations des deux boucles for
est \u00e9gal \u00e0 n^2
.
"},{"location":"T4_Algorithmique/4.2_Complexite/cours/#3-complexite-constante","title":"3. Complexit\u00e9 constante","text":"Il peut arriver (mais c'est rare) que la complexit\u00e9 d'un algorithme soit ind\u00e9pendante de la taille des donn\u00e9es \u00e0 traiter. Dans ce cas, c'est souvent une tr\u00e8s bonne nouvelle.
Observons l'acc\u00e8s au 1er \u00e9l\u00e9ment d'une liste :
Complexit\u00e9 constante
Les expressions suivantes sont \u00e9quivalentes :
- L'algorithme est de complexit\u00e9 constante.
- L'algorithme est d'ordre 1.
- L'algorithme est en \\(O(1)\\) (\u00abgrand O de 1\u00bb)
Toutes ces formulations renvoient \u00e0 la m\u00eame id\u00e9e : le nombre d'op\u00e9rations n\u00e9cessaires (et donc le temps n\u00e9cessaire \u00e0 la terminaison de l'algorithme) est constant quelle que soit la taille des donn\u00e9es d'entr\u00e9e de l'algorithme.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/","title":"4.3 Tri par insertion","text":""},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#0-introduction","title":"0. Introduction","text":" Activit\u00e9 d'introduction
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#1-tri-par-insertion-version-la-plus-intuitive","title":"1. Tri par insertion (version la plus intuitive)","text":""},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#11-principe-et-algorithme","title":"1.1 Principe et algorithme","text":"Consid\u00e9rons la liste [7, 5, 2, 8, 1, 4]
Voici le fonctionnement de l'algorithme :
Explications :
- On traite successivement toutes les valeurs \u00e0 trier, en commen\u00e7ant par celle en deuxi\u00e8me position.
- Traitement : tant que la valeur \u00e0 traiter est inf\u00e9rieure \u00e0 celle situ\u00e9e \u00e0 sa gauche, on \u00e9change ces deux valeurs.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#12-codage-de-lalgorithme","title":"1.2\u00a0Codage de l'algorithme","text":"Algorithme :
Pour toutes les valeurs, en commen\u00e7ant par la deuxi\u00e8me :
- Tant qu'on trouve \u00e0 gauche une valeur sup\u00e9rieure et qu'on n'est pas revenu \u00e0 la premi\u00e8re valeur, on \u00e9change ces deux valeurs.
Tri par insertion (version simple)
def tri_insertion(lst):\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n for i in range(1, len(lst)): #(1)\n k = i #(2)\n while k > 0 and lst[k-1] > lst[k] : #(3)\n lst[k], lst[k-1] = lst[k-1], lst[k] #(4) \n k = k - 1 #(5) \n
- On commence \u00e0 1 et non pas \u00e0 0.
- On \u00abduplique\u00bb la variable
i
en une variable k
. On se positionne sur l'\u00e9l\u00e9ment d'indice k
. On va faire \u00abreculer\u00bb cet \u00e9l\u00e9ment tant que c'est possible. On ne touche pas \u00e0 i
. - Tant qu'on n'est pas revenu au d\u00e9but de la liste et qu'il y a une valeur plus grande \u00e0 gauche.
- On \u00e9change de place avec l'\u00e9l\u00e9ment pr\u00e9c\u00e9dent.
- Notre \u00e9l\u00e9ment est maintenant \u00e0 l'indice
k - 1
. La boucle peut continuer.
Application :
>>> maliste = [7, 5, 2, 8, 1, 4]\n>>> tri_insertion(maliste)\n>>> maliste\n[1, 2, 4, 5, 7, 8]\n
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#2-tri-par-insertion-version-optimisee","title":"2. Tri par insertion (version optimis\u00e9e)","text":""},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#21-principe-et-algorithme","title":"2.1 Principe et algorithme","text":"Observez l'animation ci-dessous et comparer avec la version initiale.
- Au lieu d'effetuer un \u00e9change avec la valeur pr\u00e9c\u00e9dente \u00e0 chaque fois qu'elle est sup\u00e9rieure, on va d\u00e9caler vers la droite toutes les valeurs situ\u00e9es \u00e0 gauche et sup\u00e9rieures \u00e0 notre valeur de travail.
- On ins\u00e8re ensuite directement \u00e0 sa position \u00abla plus \u00e0 gauche possible\u00bb notre valeur de travail.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#22-codage-de-lalgorithme","title":"2.2 Codage de l'algorithme","text":"Tri par insertion (version optimis\u00e9e)
def tri_insertion_v2(lst) :\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n for i in range(1, len(lst)): # (1)\n cle = lst[i] # (2)\n k = i - 1 # (3)\n while k >= 0 and lst[k] > cle : # (4)\n lst[k + 1] = lst[k] # (5)\n k = k -1 # (6)\n lst[k + 1] = cle # (7)\n
- On d\u00e9marre \u00e0 la deuxi\u00e8me valeur.
- On stocke dans une variable
cle
notre valeur de travail - On d\u00e9marre l'\u00e9tude des valeurs \u00e0 gauche de notre valeur de travail
- Tant qu'on trouve une valeur sup\u00e9rieure \u00e0 notre valeur de travail, et qu'on n'est pas revenus au d\u00e9but de la liste.
- On d\u00e9cale cette valeur de un rang vers la droite.
- On se repositionne sur la valeur \u00e0 gauche de notre valeur actuelle.
- On s'est arr\u00eat\u00e9 quand la valeur n'\u00e9tait pas sup\u00e9rieure : on ins\u00e8re notre valeur de travail juste \u00e0 droite de notre position d'arr\u00eat.
Application :
>>> maliste = [7, 5, 2, 8, 1, 4]\n>>> tri_insertion_v2(maliste)\n>>> maliste\n[1, 2, 4, 5, 7, 8]\n
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#3-complexite-de-lalgorithme","title":"3. Complexit\u00e9 de l'algorithme","text":""},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#31-etude-experimentale","title":"3.1 \u00c9tude exp\u00e9rimentale","text":"Lire le cours sur la complexit\u00e9 et proposer des mesures exp\u00e9rimentales pour d\u00e9terminer la complexit\u00e9 du tri par insertion.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#32-demonstration","title":"3.2 D\u00e9monstration","text":"D\u00e9nombrons le nombre d'op\u00e9rations dans le pire des cas, pour une liste de taille \\(n\\).
- boucle
for
: elle s'ex\u00e9cute \\(n-1\\) fois. - boucle
while
: dans le pire des cas, elle ex\u00e9cute d'abord 1 op\u00e9ration, puis 2, puis 3... jusqu'\u00e0 \\(n-1\\). Or
\\[1+2+3+\\dots+n-1=\\dfrac{n \\times (n-1)}{2}\\] Le terme de plus haut degr\u00e9 de l'expression \\(\\dfrac{n \\times (n-1)}{2}\\) est de degr\u00e9 2 : le nombre d'op\u00e9rations effectu\u00e9es est donc proportionnel au carr\u00e9 de la taille des donn\u00e9es d'entr\u00e9e. Ceci d\u00e9montre que le tri par insertion est de complexit\u00e9 quadratique.
Dans le cas (rare, mais il faut l'envisager) o\u00f9 la liste est d\u00e9j\u00e0 tri\u00e9e, on ne rentre jamais dans la boucle while
: le nombre d'op\u00e9rations est dans ce cas \u00e9gal \u00e0 \\(n-1\\), ce qui caract\u00e9rise une complexit\u00e9 lin\u00e9aire.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#33-resume-de-la-complexite","title":"3.3 R\u00e9sum\u00e9 de la complexit\u00e9","text":" - dans le meilleur des cas (liste d\u00e9j\u00e0 tri\u00e9e) : complexit\u00e9 lin\u00e9aire
- dans le pire des cas (liste tri\u00e9e dans l'ordre d\u00e9croissant) : complexit\u00e9 quadratique
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#34-preuve-de-la-terminaison-de-lalgorithme","title":"3.4 Preuve de la terminaison de l'algorithme","text":"Est-on s\u00fbr que notre algorithme va s'arr\u00eater ? Le programme est constitu\u00e9 d'une boucle while
imbriqu\u00e9e dans une boucle for
. Seule la boucle while
peut provoquer une non-terminaison de l'algorithme. Observons donc ses conditions de sortie :
while k >= 0 and l[k] > cle :\n
La condition l[k] > cle
ne peut pas \u00eatre rendue fausse avec certitude. Par contre, la condition k >= 0
sera fausse d\u00e8s que la variable k
deviendra n\u00e9gative. Or la ligne k = k - 1
nous assure que la variable k
diminuera \u00e0 chaque tour de boucle. La condition k >= 0
deviendra alors forc\u00e9ment fausse au bout d'un certain temps.
Nous avonc donc prouv\u00e9 la terminaison de l'algorithme.
Vocabulaire
On dit que la valeur k
est un variant de boucle. C'est une notion th\u00e9orique (ici illustr\u00e9e de mani\u00e8re simple par la valeur k
) qui permet de prouver la bonne sortie d'une boucle et donc la terminaison d'un algorithme.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#35-preuve-de-la-correction-de-lalgorithme","title":"3.5 Preuve de la correction de l'algorithme","text":"Les preuves de correction sont des preuves th\u00e9oriques. La preuve ici s'appuie sur le concept math\u00e9matique de r\u00e9currence. Principe du raisonnement par r\u00e9currence : une propri\u00e9t\u00e9 \\(P(n)\\) est vraie si :
- \\(P(0)\\) (par exemple) est vraie
- Pour tout entier naturel \\(n\\), si \\(P(n)\\) est vraie alors \\(P(n+1)\\) est vraie.
Ici, la propri\u00e9t\u00e9 serait : \u00ab Quand \\(k\\) varie entre 0 et longueur(liste) -1
, la sous-liste de longueur \\(k\\) est tri\u00e9e dans l'ordre croissant.\u00bb
Vocabulaire
On appelle cette propri\u00e9t\u00e9 un invariant de boucle. Invariant siginifie qu'elle reste vraie pour chaque boucle.
- quand \\(k\\) vaut 0, on place le minimum \\(m_0\\) de la liste en position 0, la sous-liste [\\(m_0\\)] est donc tri\u00e9e.
- si la sous-liste de \\(k\\) \u00e9l\u00e9ments [\\(m_0, m_1, ..., m_{k-1}\\)] est tri\u00e9e, l'algorithme rajoute en derni\u00e8re position de la liste le minimum de la sous-liste restante, dont tous les \u00e9l\u00e9ments sont sup\u00e9rieurs au maximum de la sous-liste de \\(k\\) \u00e9l\u00e9ments. La sous-liste de \\(k+1\\) \u00e9l\u00e9ments [\\(m_0, m_1, ..., m_{k-1}, m_k\\)] est donc elle aussi tri\u00e9e.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#4-bonus-comparaison-des-algorithmes-de-tri","title":"4. Bonus : comparaison des algorithmes de tri","text":"Une jolie animation permettant de comparer les tris : (on peut y constater que le tri par s\u00e9lection met toujours autant de temps pour trier la liste, quelque soit son \u00e9tat initial)
Issue de ce site.
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/cours/#bibliographie","title":"Bibliographie","text":" - Wikipedia, https://en.wikipedia.org/wiki/Sorting_algorithm
"},{"location":"T4_Algorithmique/4.3_Tri_par_insertion/intro_cours/","title":"Vers le tri par insertion","text":"Principe de l'algorithme
Pour toutes les valeurs, en commen\u00e7ant par la deuxi\u00e8me :
- Tant qu'on trouve \u00e0 gauche une valeur sup\u00e9rieure et qu'on n'est pas revenu \u00e0 la premi\u00e8re valeur, on \u00e9change ces deux valeurs.
Pour tester son code :
>>> maliste = [7, 5, 2, 8, 1, 4]\n>>> tri_insertion(maliste)\n>>> maliste\n[1, 2, 4, 5, 7, 8]\n
Code \u00e0 trous def tri_insertion(lst):\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n
Code \u00e0 trous def tri_insertion(lst):\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n for i in range(..., ...): \n ... = ... \n while ... > ... and ... > ... : \n ..., ... = ..., ... \n ... = ... \n
Code \u00e0 trous def tri_insertion(lst):\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n for i in range(..., len(lst)): \n k = ... \n while k > ... and lst[...] > lst[...] : \n lst[...], lst[...] = lst[...], lst[...] \n k = ... \n
Code \u00e0 trous def tri_insertion(lst):\n '''trie en place la liste lst donn\u00e9e en param\u00e8tre'''\n for i in range(1, len(lst)): \n k = ... \n while k > ... and lst[k-1] > lst[k] : \n lst[k], lst[k-1] = lst[...], lst[...] \n k = ... \n
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/","title":"4.4 Tri par s\u00e9lection","text":""},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#0-preambule","title":"0. Pr\u00e9ambule","text":"Pourquoi \u00e9tudier des algorithmes de tri ? Autant ne pas le cacher, ces algorithmes sont d\u00e9j\u00e0 impl\u00e9ment\u00e9s (quelque soit le langage) dans des fonctions tr\u00e8s performantes.
En Python, on utilise la fonction sort()
:
>>> tab = [4, 8, 1, 2, 6]\n>>> tab.sort()\n>>> tab\n[1, 2, 4, 6, 8]\n
Le meilleur de nos futurs algorithmes de tri sera moins efficace que celui de cette fonction sort()
... Malgr\u00e9 cela, il est essentiel de se confronter \u00e0 l'\u00e9laboration manuelle d'un algorithme de tri. Le tri par s\u00e9lection est le premier des deux algorithmes de tri que nous allons \u00e9tudier (nous \u00e9tudierons aussi le tri par insertion). Ces deux algorithmes ont pour particularit\u00e9 de :
- ne pas n\u00e9cessiter la cr\u00e9ation d'une nouvelle liste. Ils modifient la liste \u00e0 trier en place.
- ne pas faire intervenir de fonctions complexes (comme la recherche d'un minimum par exemple)
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#0-introduction","title":"0. Introduction","text":" Activit\u00e9 d'introduction
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#1-animation","title":"1. Animation","text":"Consid\u00e9rons la liste [5, 4, 2, 1]
Voici le fonctionnement de l'algorithme :
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#2-principe","title":"2. Principe","text":"Comme dans tous les autres algorithmes de tri que nous allons \u00e9tudier, nous allons travailler en place. Cela signifie que nous ne travaillons que sur la liste initiale, sans en cr\u00e9er de nouvelles. Le tri sera fait en permutant des \u00e9l\u00e9ments.
Tr\u00e8s tr\u00e8s grossi\u00e8rement, l'id\u00e9e de l'algorithme est la suivante :
- on cherche le minimum de toute la liste, et on le place au tout d\u00e9but de la liste.
- on cherche maintenant le minimum de toute la liste SAUF le 1er terme, et on le place en 2\u00e8me position.
- on continue ainsi jusqu'\u00e0 la fin.
Pour r\u00e9aliser ceci, le travail va se faire en manipulant les indices des \u00e9l\u00e9ments de la liste.
Description de l'algorithme
Le travail se fait essentiellement sur les indices.
- du premier \u00e9l\u00e9ment jusqu'\u00e0 l'avant-dernier :
- on consid\u00e8re que cet \u00e9l\u00e9ment est l'\u00e9l\u00e9ment minimum, on stocke donc son indice dans une variable indice du minimum.
- on parcourt les \u00e9l\u00e9ments suivants, et si on rep\u00e8re un \u00e9l\u00e9m\u00e9nt plus petit que notre mininum on met \u00e0 jour notre indice du minimum.
- une fois le parcours fini, on \u00e9change l'\u00e9l\u00e9ment de travail avec l'\u00e9l\u00e9ment minimum qui a \u00e9t\u00e9 trouv\u00e9.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#3-implementation-de-lalgorithme","title":"3. Impl\u00e9mentation de l'algorithme","text":"Tri par s\u00e9lection
def tri_selection(lst) :\n for i in range(len(lst)-1):\n indice_min = i\n for k in range(i+1, len(lst)) :\n if lst[k] < lst[indice_min]:\n indice_min = k\n lst[i], lst[indice_min] = lst[indice_min], lst[i]\n
V\u00e9rification :
>>> ma_liste = [7, 5, 2, 8, 1, 4]\n>>> tri_selection(ma_liste)\n>>> ma_liste\n[1, 2, 4, 5, 7, 8]\n
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#4-complexite-de-lalgorithme","title":"4. Complexit\u00e9 de l'algorithme","text":""},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#40-de-quoi-parle-t-on","title":"4.0. De quoi parle-t-on ?","text":" Cours sur la complexit\u00e9
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#41-calcul-du-nombre-doperations","title":"4.1. Calcul du nombre d'op\u00e9rations","text":"La ligne 3 indice_min = i
va s'ex\u00e9cuter \\(n\\) fois. Mais int\u00e9ressons-nous \u00e0 la ligne 5 (le test) : combien de fois va-t-elle s'ex\u00e9cuter ? \u00c0 chaque tour de la premi\u00e8re boucle (qui en comporte \\(n\\)), le nombre d'op\u00e9rations de la 2\u00e8me boucle va varier :
- La 1\u00e8re fois, de 1 \u00e0 \\(n-1\\), provoquera \\(n-1\\) op\u00e9rations.
- La 2\u00e8me fois, de 2 \u00e0 \\(n-1\\), provoquera \\(n-2\\) op\u00e9rations.
- ...
- La \\(n\\)-i\u00e8me fois, \\(n-1\\) \u00e0 \\(n-1\\), provoquera 1 op\u00e9ration.
Or \\(1+2+3+\\dots+n-1=\\dfrac{n \\times (n-1)}{2}= \\dfrac{1}{2}n^2 - \\dfrac{1}{2}n\\)
Dans cette expression, un terme joue un r\u00f4le fondamental : \\(n^2\\). C'est le terme pr\u00e9pond\u00e9rant (le terme de plus haut degr\u00e9), qui va \u00e0 lui seul caract\u00e9riser la mani\u00e8re dont le nombre d'op\u00e9rations \u00e9volue en fonction de \\(n\\).
Ici, \\(n\\) est \u00e9lev\u00e9 au carr\u00e9, ce qui signifie que le nombre d'op\u00e9rations va \u00e9voluer avec le carr\u00e9 du nombre de termes de la liste \u00e0 trier.
Complexit\u00e9 du tri par s\u00e9lection
Le tri par s\u00e9lection a une complexit\u00e9 quadratique.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#42-influence-de-la-taille-de-la-liste-sur-le-temps-dexecution","title":"4.2 Influence de la taille de la liste sur le temps d'ex\u00e9cution","text":"Consid\u00e9rons qu'une liste de taille \\(n\\) est tri\u00e9e par l'algorithme de tri par s\u00e9lection en un temps \\(T\\). Le temps d'ex\u00e9cution d\u00e9pendant du nombre d'op\u00e9rations \u00e0 traiter, il va \u00e9voluer avec le carr\u00e9 de la taille de la liste.
Voici donc un ordre de grandeur de ce que devraient \u00eatre les temps n\u00e9cessaires pour trier une liste de taille \\(2n\\) ou \\(10n\\).
Taille de la liste Temps \\(n\\) \\(T\\) \\(2n\\) \\(4T\\) \\(10n\\) \\(100T\\)"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#43-verification-experimentale","title":"4.3 V\u00e9rification exp\u00e9rimentale","text":"Exercice
\u00c9nonc\u00e9Correction Analyser le code suivant :
import time\n\ndef tri_selection(lst):\n for i in range(len(lst)-1):\n i_min = i\n for k in range(i+1, len(lst)):\n if lst[k] < lst[i_min]:\n i_min = k\n lst[i_min], lst[i] = lst[i], lst[i_min]\n\n\ndef mesures(n):\n total_temps = 0\n for _ in range(5):\n lst = list(range(n, 0, -1)) # (1)\n t0 = time.time()\n tri_selection(lst)\n delta_t = time.time() - t0\n total_temps += delta_t\n tps_moy = total_temps / 5\n print(f\"temps moyen pour trier une liste de taille {n} : {tps_moy}\")\n
- on se place ici dans le pire des cas : une liste initialement tri\u00e9e dans l'ordre d\u00e9croissant. Attention, pour le tri par s\u00e9lection, ces conditions initiales n'ont AUCUNE influence sur le nombre d'op\u00e9rations : le temps mis sera toujours le m\u00eame, quelque soit l'\u00e9tat initial de la liste.
Q1. Essayer de confirmer les r\u00e9sultats th\u00e9oriques du tableau pr\u00e9c\u00e9dent. On pourra travailler par exemple avec une liste initiale de taille 1000.
Q2. Recommencer avec une liste d\u00e9j\u00e0 tri\u00e9e. Que constate-t-on ?
Q1.
>>> mesures(10**3)\ntemps moyen pour trier une liste de taille 1000 : 0.03579235076904297\n>>> mesures(2*10**3)\ntemps moyen pour trier une liste de taille 2000 : 0.13821134567260743\n>>> mesures(10**4)\ntemps moyen pour trier une liste de taille 10000 : 3.3528685569763184\n
On retrouve (\u00e0 peu pr\u00e8s, mais plut\u00f4t bien) le facteur 4 quand la taille de la liste double, et le facteur 100 quand la taille de la liste est multipli\u00e9e par 10.
Q2. Changeons la ligne lst = list(range(n, 0, -1))
en lst = list(range(n))
:
>>> mesures(10**3)\ntemps moyen pour trier une liste de taille 1000 : 0.038380765914916994\n>>> mesures(2*10**3)\ntemps moyen pour trier une liste de taille 2000 : 0.13413033485412598\n>>> mesures(10**4)\ntemps moyen pour trier une liste de taille 10000 : 3.213682508468628\n
Les mesures sont identiques : l'\u00e9tat initial de la liste n'a pas d'influence.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#5-preuve-de-la-terminaison-de-lalgorithme","title":"5.\u00a0Preuve de la terminaison de l'algorithme","text":"Est-on s\u00fbr que notre algorithme va s'arr\u00eater ?
\u00c0 l'observation du programme, constitu\u00e9 de deux boucles for
imbriqu\u00e9es, il n'y a pas d'ambigu\u00eft\u00e9 : on ne peut pas rentrer dans une boucle infinie. Le programme s'arr\u00eate forc\u00e9ment au bout de d'un nombre fixe d'op\u00e9rations. D'apr\u00e8s nos calculs sur la complexit\u00e9, ce nombre de tours de boucles est \u00e9gal \u00e0 \\(\\dfrac{n \\times (n-1)}{2}\\).
Ceci prouve que l'algorithme se terminera.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#6-preuve-de-la-correction-de-lalgorithme","title":"6. Preuve de la correction de l'algorithme","text":"Est-on s\u00fbr que notre algorithme va bien trier notre liste ?
Les preuves de correction sont des preuves th\u00e9oriques. La preuve ici s'appuie sur le concept math\u00e9matique de r\u00e9currence. Principe du raisonnement par r\u00e9currence : une propri\u00e9t\u00e9 \\(P(n)\\) est vraie si :
- \\(P(0)\\) (par exemple) est vraie
- Pour tout entier naturel \\(n\\), si \\(P(n)\\) est vraie alors \\(P(n+1)\\) est vraie.
Ici, la propri\u00e9t\u00e9 serait : \u00ab Quand \\(k\\) varie entre 0 et longueur(liste) -1
, la sous-liste de longueur \\(k\\) est tri\u00e9e dans l'ordre croissant.\u00bb On appelle cette propri\u00e9t\u00e9 un invariant de boucle (sous-entendu : elle est vraie pour chaque boucle)
- quand \\(k\\) vaut 0, on place le minimum \\(m_0\\) de la liste en position 0, la sous-liste [\\(m_0\\)] est donc tri\u00e9e.
- si la sous-liste de \\(k\\) \u00e9l\u00e9ments [\\(m_0, m_1, ..., m_{k-1}\\)] est tri\u00e9e, l'algorithme rajoute en derni\u00e8re position de la liste le minimum de la sous-liste restante, dont tous les \u00e9l\u00e9ments sont sup\u00e9rieurs au maximum de la sous-liste de \\(k\\) \u00e9l\u00e9ments. La sous-liste de \\(k+1\\) \u00e9l\u00e9ments [\\(m_0, m_1, ..., m_{k-1}, m_k\\)] est donc elle aussi tri\u00e9e.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/cours/#7-bonus-comparaison-des-algorithmes-de-tri","title":"7. Bonus : comparaison des algorithmes de tri","text":"Une jolie animation permettant de comparer les tris : (on peut y constater que le tri par s\u00e9lection met toujours autant de temps pour trier la liste, quelque soit son \u00e9tat initial)
Issue de ce site.
"},{"location":"T4_Algorithmique/4.4_Tri_par_selection/intro_cours/","title":"Vers le tri par s\u00e9lection","text":" pour tester votre code :
>>> ma_liste = [7, 5, 2, 8, 1, 4]\n>>> tri_selection(ma_liste)\n>>> ma_liste\n[1, 2, 4, 5, 7, 8]\n
Code \u00e0 trous def tri_selection(lst) :\n ...\n
Code \u00e0 trous def tri_selection(lst) :\n for ... in ... :\n ... = ...\n for ... in ... :\n if ... :\n ...\n ...\n
Code \u00e0 trous def tri_selection(lst) :\n for i in range(...):\n ... = i\n for k in range(..., ...) :\n if ... < ... :\n ... = ...\n ..., ... = ..., ...\n
Code \u00e0 trous def tri_selection(lst) :\n for i in range(len(lst)-1):\n indice_min = ...\n for k in range(..., len(lst)) :\n if lst[...] < lst[...]:\n indice_min = ...\n lst[...], lst[...] = lst[...], lst[...]\n
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/","title":"4.5 Dichotomie","text":"ou comment rechercher efficacement dans une liste tri\u00e9e ?
\u00abdichotomie\u00bb se dit en anglais binary search.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#1-introduction-recherche-dune-valeur-dans-une-liste","title":"1. Introduction : recherche d'une valeur dans une liste","text":""},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#11-preambule","title":"1.1 Pr\u00e9ambule","text":"De l'importance de bien ranger ses affaires
Les premiers algorithmes \u00abc\u00e9l\u00e8bres\u00bb que nous avons d\u00e9couverts \u00e9taient des algorithmes de tri.
Quel est l'int\u00e9r\u00eat de trier ses donn\u00e9es ?
-
l'int\u00e9r\u00eat imm\u00e9diat est d'en tirer un classement : quelle est la plus grande (ou plus petite) valeur, la deuxi\u00e8me, la troisi\u00e8me... On s'en sert donc \u00e9videmment pour d\u00e9terminer une valeur optimale, un gagnant dans une comp\u00e9tition, etc. Mais il y a une autre raison plus importante.
-
Trier ses donn\u00e9es permet de rechercher plus rapidement une valeur pr\u00e9cise parmi celles-ci.
Exemple : pouvez-vous deviner la couleur \u00e0 laquelle je pense ?
coul = [\"bleu\", \"jaune\", \"rouge\", \"vert\", \"violet\", \"marron\"]\n
Toutes les m\u00e9thodes (proposition des valeurs dans l'ordre, au hasard, dans l'ordre inverse...) sont \u00e9quivalentes : elles sont toutes aussi mauvaises, aucune strat\u00e9gie n'est possible car les donn\u00e9es ne sont pas tri\u00e9es. Si je suis \u00e0 la recherche de la valeur \"vert\", le fait de piocher \"rouge\" ne me donnera aucune indication sur le fait que je devrais chercher plus \u00e0 gauche \u00e0 plus \u00e0 droite que l'endroit o\u00f9 j'ai pioch\u00e9.
Il faudrait pour cela que la liste soit tri\u00e9e (et donc qu'elle soit \u00abtriable\u00bb, ce qui n'est pas toujours le cas !). C'est donc le cas dans lequel nous allons nous placer dans toute la suite de ce cours :
Dans toute la suite, nous rechercherons un \u00e9l\u00e9ment dans une liste d'entiers tri\u00e9e dans l'ordre croissant.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#12-contexte-de-recherche","title":"1.2 Contexte de recherche","text":"Consid\u00e9rons donc la liste lst
suivante :
lst = [2, 3, 6, 7, 11, 14, 18, 19, 24]\n
L'objectif est de d\u00e9finir un algorithme de recherche efficace d'une valeur arbitraire pr\u00e9sente dans cette liste.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#13-methode-naive-recherche-par-balayage","title":"1.3 M\u00e9thode na\u00efve : recherche par balayage","text":"C'est la m\u00e9thode la plus intuitive : on essaie toutes les valeurs (par exemple, dans l'ordre croissant) jusqu'\u00e0 trouver la bonne.
Exercice 1
\u00c9crire un code permettant d'afficher l'indice de la valeur 14
dans la liste lst = [2, 3, 6, 7, 11, 14, 18, 19, 24]
.
Correction lst = [2, 3, 6, 7, 11, 14, 18, 19, 24]\nfor k in range(len(lst)):\n if lst[k] == 14 :\n print(k)\n
Exercice 2
\u00c9crire une fonction recherche_naive
qui re\u00e7oit pour param\u00e8tres une liste lst
et un nombre val
et qui renvoie l'indice de val
dans la liste lst
. Si la valeur val
n'est pas trouv\u00e9e, on renverra None
.
Correction def recherche_naive(lst, val) :\n for k in range(len(lst)) :\n if lst[k] == val:\n return k\n return None\n
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#13-complexite-de-la-methode-naive","title":"1.3 Complexit\u00e9 de la m\u00e9thode na\u00efve","text":"Complexit\u00e9 de la m\u00e9thode na\u00efve
Dans le cas d'une recherche na\u00efve, le nombre (maximal) d'op\u00e9rations n\u00e9cessaires est proportionnel \u00e0 la taille de la liste \u00e0 \u00e9tudier. Si on appelle \\(n\\) la longueur de la liste, on dit que cet algorithme est d'ordre \\(n\\), ou lin\u00e9aire, ou en \\(O(n)\\).
Remarque : La m\u00e9thode na\u00efve n'utilise pas le fait que la liste est tri\u00e9e, on aurait pu aussi bien l'utiliser sur une liste non tri\u00e9e.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#2-recherche-dichotomique","title":"2. Recherche dichotomique","text":""},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#21-introduction-le-jeu-du-devine-un-nombre-entre-1-et-100","title":"2.1 Introduction : le jeu du \u00abdevine un nombre entre 1 et 100\u00bb","text":"R\u00e8gles du jeu
Si je choisis un nombre entre 1 et 100, quelle est la strat\u00e9gie optimale pour deviner ce nombre le plus vite possible ? (\u00e0 chaque \u00e9tape, une indication (trop grand, trop petit) permet d'affiner la proposition suivante)
R\u00e9ponse attendue : la meilleure strat\u00e9gie est de couper en deux \u00e0 chaque fois l'intervalle d'\u00e9tude. On d\u00e9marre de 50, puis 75 ou 25, etc.
Il convient toute fois de remettre en question cette m\u00e9thode qui para\u00eet naturellement optimale : si je propose 90 comme nombre de d\u00e9part, j'ai certes moins de chance que le nombre soit entre 90 et 100, mais s'il l'est, j'ai gagn\u00e9 un gros avantage car mon nouvel intervalle est tr\u00e8s r\u00e9duit.
Notion d'esp\u00e9rance probabiliste D\u00e9terminer si un risque vaut la peine d'\u00eatre pris passe par la compr\u00e9hension de la notion d'esp\u00e9rance probabiliste. Exemple : \"On lance un d\u00e9, s'il tombe sur le 6 vous recevez 8 euros, sinon vous me donnez 1 euro. Voulez-vous jouer ?\"
\\(E(X) = 8 \\times \\frac{1}{6} + (-1) \\times \\frac{5}{6} = \\frac{8}{6}-\\frac{5}{6}=\\frac12\\)
En moyenne, on gagnera 50 centimes par partie, il faut donc jouer.
Le graphique ci-dessous repr\u00e9sente le nombre de coups moyens (sur 10 000 parties simul\u00e9es)
Interpr\u00e9tations et remarques
- si le choix se porte toujours sur le nombre situ\u00e9 \u00e0 la moiti\u00e9 de l'intervalle (0.5), le nombre de coups moyen avant la victoire (sur 10 000 parties) est environ 6.
- si le choix se porte toujours sur le nombre situ\u00e9 \u00e0 90 % de l'intervalle (0.9), le nombre de coups moyen avant la victoire (sur 10 000 parties) est environ 11.
- l'asym\u00e9trie de la courbe (qui devrait \u00eatre sym\u00e9trique) est due aux arrondis par d\u00e9faut dans le cas de nombres non entiers.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#conclusion-generale-de-lactivite-dintroduction","title":"Conclusion g\u00e9n\u00e9rale de l'activit\u00e9 d'introduction","text":"La strat\u00e9gie optimale est de diviser en deux \u00e0 chaque \u00e9tape l'intervalle d'\u00e9tude. On appelle cela une m\u00e9thode par dichotomie, du grec ancien \u03b4\u03b9\u03c7\u03bf\u03c4\u03bf\u03bc\u03af\u03b1, dikhotomia (\u00ab division en deux parties \u00bb).
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#22-algorithme-de-recherche-dichotomique","title":"2.2 Algorithme de recherche dichotomique","text":"Dichotomie, d\u00e9roulement intuitif
- on se place au milieu de la liste.
- on regarde si la valeur sur laquelle on est plac\u00e9e est inf\u00e9rieure ou sup\u00e9rieure \u00e0 la valeur cherch\u00e9e.
- on ne consid\u00e8re maintenant que la bonne moiti\u00e9 de la liste qui nous int\u00e9resse.
- on continue jusqu'\u00e0 trouver la valeur cherch\u00e9e (ou pas)
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#23-programmation-de-la-methode-de-dichotomie","title":"2.3 Programmation de la m\u00e9thode de dichotomie","text":"Comprendre la m\u00e9thode de dichotomie est relativement simple, mais savoir la programmer est plus difficile.
Pour des raisons d'efficacit\u00e9, nous allons garder intacte notre liste de travail et simplement faire \u00e9voluer les indices qui d\u00e9terminent le d\u00e9but et la fin de notre liste.
Une autre m\u00e9thode pourrait \u00eatre d'extraire \u00e0 chaque \u00e9tape une nouvelle liste (dont on esp\u00e8re qu'elle contient la valeur cherch\u00e9e), mais la technique utilis\u00e9e (le slicing de liste) consomme beaucoup trop de ressources.
Nous allons donc travailler avec trois variables :
indice_debut
(en bleu sur le sch\u00e9ma) indice_fin
(en bleu sur le sch\u00e9ma) indice_central
, qui est \u00e9gale \u00e0 (indice_debut + indice_fin) // 2
(en rouge sur le sch\u00e9ma)
Nous allons faire se rapprocher les indices indice_debut
et indice_fin
tant que indice_debut <= indice_fin
Codes \u00e0 trous
Recherche dichotomique dans une liste tri\u00e9e
def recherche_dichotomique(lst, val) :\n indice_debut = 0\n indice_fin = len(lst) - 1\n while indice_debut <= indice_fin :\n indice_centre = (indice_debut + indice_fin) // 2 \n valeur_centrale = lst[indice_centre] \n if valeur_centrale == val : \n return indice_centre\n if valeur_centrale < val : \n indice_debut = indice_centre + 1\n else :\n indice_fin = indice_centre - 1\n return None\n
Utilisation
>>> mylist = [2, 3, 6, 7, 11, 14, 18, 19, 24]\n>>> recherche_dichotomique(mylist, 14)\n5\n>>> recherche_dichotomique(mylist, 2)\n0\n>>> recherche_dichotomique(mylist, 24)\n8\n>>> recherche_dichotomique(mylist, 1789)\n>>> \n
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#24-visualisations-avec-pythontutor","title":"2.4 Visualisations avec PythonTutor","text":"Cas o\u00f9 la valeur est trouv\u00e9e Cas o\u00f9 la valeur N'est PAS trouv\u00e9e"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#25-terminaison-de-lalgorithme","title":"2.5 Terminaison de l'algorithme","text":"Est-on s\u00fbr que l'algorithme va se terminer ? La boucle while
qui est utilis\u00e9e doit nous inciter \u00e0 la prudence (voir cours sur la boucle While). Il y a en effet le risque de rentrer dans une boucle infinie. Pourquoi n'est-ce pas le cas ?
Aide : observer la position des deux fl\u00e8ches bleues lors de l'ex\u00e9cution de l'algorithme
La condition de la boucle while
est indice_debut <= indice_fin
, qui pourrait aussi s'\u00e9crire indice_fin >= indice_debut
. Au d\u00e9marrage de la boucle, on a :
indice_debut = 0\n indice_fin = len(L) - 1\n
Ceci qui nous assure donc de bien rentrer dans la boucle.
Ensuite, \u00e0 chaque \u00e9tape :
- soit
indice_debut
augmente strictement (gr\u00e2ce \u00e0 indice_debut = indice_centre + 1
) - soit
indice_fin
diminue strictement (gr\u00e2ce \u00e0 indice_fin = indice_centre - 1
)
Il va donc forc\u00e9ment arriver un moment o\u00f9 indice_fin
sera inf\u00e9rieur \u00e0 indice_debut
: on sortira alors de la boucle et le programme va bien se terminer.
Variant de boucle On dit que la valeur indice_fin - indice_debut
repr\u00e9sente le variant de boucle de cet algorithme. Ce variant est un nombre entier, d'abord strictement positif, puis qui va d\u00e9cro\u00eetre jusqu'\u00e0 la valeur 0.
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#26-complexite-de-lalgorithme","title":"2.6 Complexit\u00e9 de l'algorithme","text":"Combien d'\u00e9tapes (au maximum) sont-elles n\u00e9cessaires pour arriver \u00e0 la fin de l'algorithme ? Imaginons que la liste initiale poss\u00e8de 8 valeurs. Apr\u00e8s une \u00e9tape, il ne reste que 4 valeurs \u00e0 traiter. Puis 2 valeurs. Puis une seule valeur. Il y a donc 3 \u00e9tapes avant de trouver la valeur cherch\u00e9e.
Exercice 3
Q1. Remplissez le tableau ci-dessous :
taille de la liste 1 2 4 8 16 32 64 128 256 nombre d'\u00e9tapes _ _ _ 3 _ _ _ _ _ Q2. Pouvez-vous deviner le nombre d'\u00e9tapes n\u00e9cessaires pour une liste de 4096 termes ?
Q3. Pour une liste de \\(2^n\\) termes, quel est le nombre d'\u00e9tapes ?
Conclusion :
C'est le nombre de puissances de 2 que contient le nombre \\(N\\) de termes de la liste qui est d\u00e9terminant dans la complexit\u00e9 de l'algorithme.
Ce nombre s'appelle le logarithme de base 2 et se note \\(\\log_2(N)\\).
On dit que l'algorithme de dichotomie a une vitesse logarithmique. On rencontrera parfois la notation \\(O(\\log_2(n))\\).
Complexit\u00e9 de la dichotomie
La recherche dichotomique se fait avec une complexit\u00e9 logarithmique.
Cette complexit\u00e9 est bien meilleure qu'une complexit\u00e9 lin\u00e9aire. Le nombre d'op\u00e9rations \u00e0 effectuer est tr\u00e8s peu sensible \u00e0 la taille des donn\u00e9es d'entr\u00e9e, ce qui en fait un algorithme tr\u00e8s efficace.
Par exemple, si on faisait une recherche dichotomomique sur les 8 milliards d'\u00eatres humains de la plan\u00e8te (en admettant qu'on ait r\u00e9ussi \u00e0 les classer...), il suffirait de 33 \u00e9tapes pour trouver l'individu cherch\u00e9 !
(car \\(2^{33}= 8589934592\\))
"},{"location":"T4_Algorithmique/4.5_Dichotomie/cours/#3-experiences-et-comparaison-des-vitesses-dexecution","title":"3. Exp\u00e9riences et comparaison des vitesses d'ex\u00e9cution","text":"Exercice 4
Mesurer le temps d'ex\u00e9cution de deux fonctions recherche_naive
et recherche_dichotomique
. On se placera dans le pire des cas (recherche d'une valeur introuvable), avec des listes de taille 100 000 puis 1 000 000.
Correction import time\n\ndef recherche_dichotomique(lst, val) :\n indice_debut = 0\n indice_fin = len(lst) - 1\n while indice_debut <= indice_fin :\n indice_centre = (indice_debut + indice_fin) // 2 \n valeur_centrale = lst[indice_centre] \n if valeur_centrale == val : \n return indice_centre\n if valeur_centrale < val : \n indice_debut = indice_centre + 1\n else :\n indice_fin = indice_centre - 1\n return None\n\ndef recherche_naive(lst, val) :\n for k in range(len(lst)) :\n if lst[k] == val:\n return k\n return None\n\n\n\ndef mesures(n):\n lst = [k for k in range(n)]\n val = n\n total = 0\n for _ in range(10):\n t0 = time.time()\n recherche_naive(lst, val)\n total += time.time() - t0\n print(f'naive pour {n} valeurs : {total/10}')\n total = 0\n for _ in range(10):\n t0 = time.time()\n recherche_dichotomique(lst, val)\n total += time.time() - t0\n print(f'dicho pour {n} valeurs : {total/10}')\n
Tests avec une liste de taille 100 000, 1 000 000 puis 10 000 000:
>>> mesures(10**5)\nnaive pour 100000 valeurs : 0.004096603393554688\ndicho pour 100000 valeurs : 2.574920654296875e-06\n>>> mesures(10**6)\nnaive pour 1000000 valeurs : 0.03997344970703125\ndicho pour 1000000 valeurs : 3.0517578125e-06\n>>> mesures(10**7)\nnaive pour 10000000 valeurs : 0.4003706216812134\ndicho pour 10000000 valeurs : 3.886222839355469e-06\n
- Recherche na\u00efve : la recherche dans une liste 10 fois plus grand prend environ 10 fois plus de temps : la vitesse de l'algorithme est bien proportionnelle \u00e0 la taille \\(n\\) de la liste. \\(\\frac{10^6}{10^5} = 10\\)
- Recherche dichotomique : la recherche dans une liste 10 fois plus grand prend environ 1,2 fois plus de temps : la vitesse de l'algorithme est bien proportionnelle au logarithme de la taille \\(n\\) de la liste. \\(\\frac{\\log(1000000)}{\\log(100000)} \\approx 1,2\\)
"},{"location":"T4_Algorithmique/4.5_Dichotomie/intro_cours/","title":"Vers la recherche dichotomique","text":"\u00c9crire une fonction recherche_dichotomique
qui prend pour argument une liste lst
tri\u00e9e et qui recherche une valeur val
dans cette liste.
Si la valeur est trouv\u00e9e, l'indice de la valeur est renvoy\u00e9. Sinon, on renvoie None
.
Exemple d'utilisation
>>> mylist = [2, 3, 6, 7, 11, 14, 18, 19, 24]\n>>> recherche_dichotomique(mylist, 14)\n5\n>>> recherche_dichotomique(mylist, 2)\n0\n>>> recherche_dichotomique(mylist, 24)\n8\n>>> recherche_dichotomique(mylist, 1789)\n>>> \n
Code \u00e0 trous def recherche_dichotomique(lst, val) :\n
Code \u00e0 trous def recherche_dichotomique(lst, val) :\n indice_debut = ...\n indice_fin = ...\n while ... <= ... :\n ... = (... + ...) // ... \n ... = lst[...] \n if ... == ... : \n return ...\n if valeur_centrale < ... : \n ... = ... + ...\n else :\n ... = ... - ...\n return None \n
Code \u00e0 trous def recherche_dichotomique(lst, val) :\n indice_debut = ...\n indice_fin = ...\n while ... <= ... :\n indice_centre = (... + ...) // 2 \n ... = lst[...] \n if valeur_centrale == ... : \n return ...\n if valeur_centrale < ... : \n ... = ... + 1\n else :\n ... = ... - 1\n return None \n
Code \u00e0 trous def recherche_dichotomique(lst, val) :\n indice_debut = ...\n indice_fin = ...\n while indice_debut <= ... :\n indice_centre = (... + ...) // 2 \n valeur_centrale = lst[...] \n if valeur_centrale == ... : \n return indice_centre\n if valeur_centrale < ... : \n indice_debut = ... + 1\n else :\n indice_fin = ... - 1\n return None\n
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/","title":"4.6 Algorithmes gloutons","text":"en anglais : greedy algorithms
D\u00e9finition
Un algorithme est qualifi\u00e9 de glouton si le probl\u00e8me qu'il essaie de r\u00e9soudre est d\u00e9compos\u00e9 en une succession de probl\u00e8mes identiques pour lesquels l'algorithme va chercher une solution optimale.
La question (presque philosophique) est :
Lorsqu'on fait \u00e0 chaque \u00e9tape le meilleur choix possible, est-ce que la solution finale \u00e0 laquelle on arrive est la meilleure possible ?
Formul\u00e9 autrement :
Est-ce que faire le meilleur choix \u00e0 chaque \u00e9tape nous assure le meilleur choix global ?
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#1-exemples-dalgorithmes-gloutons","title":"1. Exemples d'algorithmes gloutons","text":""},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#11-un-plus-court-chemin","title":"1.1 Un plus court chemin ?","text":" - Vous partez du point O.
- Vous devez avoir atteint le plus rapidement possible tous les points A, B, C, D, E, F.
- L'ordre de parcours des points n'est pas important.
La philosophie de l'algorithme glouton implique qu'\u00e0 chaque \u00e9tape, vous allez vous diriger vers le point le plus proche.
Quel est alors le parcours final ?
R\u00e9ponse Voil\u00e0 ce que donnerait l'algorithme glouton :
Ce chemin est-il optimal ?
R\u00e9ponse Non ! Celui ci-dessous est meilleur :
Le fait d'avoir privil\u00e9gi\u00e9 \u00e0 chaque \u00e9tape le meilleur choix local nous a emp\u00each\u00e9 de voir le meilleur choix global.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#12-remplir-un-rectangle-avec-des-carres","title":"1.2 Remplir un rectangle avec des carr\u00e9s","text":"(d'apr\u00e8s S.Tummarello et E.Buonocore)
On consid\u00e8re un rectangle de dimension 11 sur 13 (figure 0). On veut remplir ce rectangle avec le minimum de carr\u00e9s.
Un algorithme glouton va chercher \u00e0 positionner d'abord le plus grand carr\u00e9 possible (figure 1) :
C'est une strat\u00e9gie efficace (8 carr\u00e9s n\u00e9cessaires), mais qui n'est pas optimale !
strat\u00e9gie optimale La figure 2 pr\u00e9sente un pavage avec seulement 6 carr\u00e9s.
Question : Est-ce qu'un algorithme glouton va toujours passer \u00e0 c\u00f4t\u00e9 de la solution optimale ?
Non ! Il arrive aussi qu'il donne la solution optimale. Changeons le rectangle initial en un rectangle de 10 sur 15 :
Dans cette situation, l'algorithme glouton nous am\u00e8ne \u00e0 la solution optimale.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#conclusion","title":"Conclusion","text":"Un algorithme glouton est une m\u00e9thode rapide et souvent efficace, mais qui ne garantit pas l'optimalit\u00e9 de la solution trouv\u00e9e.
La succession de meilleurs choix LOCAUX va nous amener \u00e0 une bonne solution GLOBALE, mais ne nous garantit pas d'arriver \u00e0 la solution optimale.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#2-le-probleme-du-rendu-de-monnaie","title":"2. Le probl\u00e8me du rendu de monnaie","text":"Nous allons travailler avec des pi\u00e8ces (ou billets) de 1, 2, 5, 10, 20, 50, 100, 200 euros.
L'objectif est de cr\u00e9er un programme renvoyant, pour une somme somme_a_rendre
entr\u00e9e en param\u00e8tre, la combinaison utilisant un minimum de pi\u00e8ces ou de billets pour fabriquer la somme somme_a_rendre
.
Par exemple, lorsque vous payez avec 20 \u20ac un objet co\u00fbtant 11 \u20ac, vous pr\u00e9f\u00e9rez qu'on vous rende vos 9 \u20ac de monnaie par \\(9 = 5 + 2 + 2\\) plut\u00f4t que par \\(9=2+2+2+1+1+1\\)
La r\u00e9solution de ce probl\u00e8me peut se faire de mani\u00e8re gloutonne : \u00e0 chaque \u00e9tape, vous allez essayer de rendre la plus grosse pi\u00e8ce (ou billet) possible.
Activit\u00e9 de d\u00e9couverte de l'algorithme
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#21-solution-du-probleme","title":"2.1 Solution du probl\u00e8me","text":"Rendu de monnaie
def rendu(somme_a_rendre):\n pieces = [200, 100, 50, 20, 10, 5, 2, 1]\n solution = []\n i = 0 # (1)\n while somme_a_rendre > 0:\n if pieces[i] <= somme_a_rendre : # (2) \n solution.append(pieces[i]) # (3) \n somme_a_rendre = somme_a_rendre - pieces[i] # (4)\n else :\n i += 1 # (5) \n return solution\n
- On part du 1er indice -> la plus grande pi\u00e8ce
- Est-ce que la pi\u00e8ce peut \u00eatre rendue ?
- On garde la pi\u00e8ce dans la liste
solution
- On met \u00e0 jour la somme \u00e0 rendre.
- La pi\u00e8ce \u00e9tait trop grosse, on avance dans la liste.
Utilisation : rendu(13)
doit renvoyer [10, 2, 1]
>>> rendu(13)\n [10, 2, 1]\n>>> rendu(58)\n [50, 5, 2, 1]\n
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#22-une-solution-optimale","title":"2.2 Une solution optimale ?","text":"Imaginons qu'il n'y ait plus de pi\u00e8ces de 10 et 5 euros. Faites fonctionner votre algorithme pour la somme de 63 euros.
>>> rendu(63)\n [50, 2, 2, 2, 2, 2, 2, 1]\n
Damned ! Mais ce n'est pas une solution optimale ! [20, 20, 20, 2, 1]
serait bien mieux.
Moralit\u00e9 : Lors d'un rendu de monnaie, l'algorithme glouton n'est optimal que sous certaines conditions, ce qui est un peu d\u00e9cevant. Un syst\u00e8me de monnaie qui rend l'algorithme glouton est dit canonique. Il est difficile de caract\u00e9riser math\u00e9matiquement si un syst\u00e8me de monnaie est canonique ou pas.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#3-le-probleme-du-sac-a-dos-knapsack-problem","title":"3. Le probl\u00e8me du sac \u00e0 dos (Knapsack Problem)","text":"Le probl\u00e8me est celui-ci : vous disposez d'un sac d'une contenance limit\u00e9e (sur le dessin ci-dessus, 15kg) dans lequel vous allez mettre des objets qui ont un certain poids et une certaine valeur. Vous souhaitez maximiser la valeur totale des objets que vous mettez dans votre sac. Evidemment, la somme de leur masse ne doit pas d\u00e9passer 15 kg.
Ce probl\u00e8me (de la cat\u00e9gorie des probl\u00e8me dits d'analyse combinatoire) malgr\u00e9 sa simplicit\u00e9 est un probl\u00e8me majeur d'optimisation.
O\u00f9 en est-on de la recherche acad\u00e9mique sur le probl\u00e8me du sac \u00e0 dos ?
Actuellement :
- On sait trouver LA meilleure solution, mais en explorant toutes les combinaisons une par une. Cette m\u00e9thode par force brute est inapplicable si beaucoup d'objets sont en jeu. (nous allons le faire)
- On sait facilement trouver une bonne solution, mais pas forc\u00e9ment la meilleure, par exemple en adoptant une strat\u00e9gie gloutonne. (nous allons le faire)
- On ne sait pas trouver facilement (en temps polynomial) la meilleure solution. Si vous y arrivez, 1 Million de $ sont pour vous. (nous n'allons pas le faire)
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#31-petite-aide-technique-avant-de-commencer","title":"3.1\u00a0Petite aide technique avant de commencer","text":"Supposons qu'on dispose d'une liste \u00a0mylist = [[\"A\",3], [\"B\",2], [\"C\",8]]
.
Comment classer les \u00e9l\u00e9ments de cette liste par leur deuxi\u00e8me \u00e9l\u00e9ment ???
Nous allons proc\u00e9der en 2 temps.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#311-une-fonction-qui-renvoie-le-deuxieme-element","title":"3.1.1 Une fonction qui renvoie le deuxi\u00e8me \u00e9l\u00e9ment","text":"Exercice 1
Cr\u00e9er une fonction deuxieme
qui prend en param\u00e8tre un tableau lst
de type List
et qui renvoie le deuxi\u00e8me \u00e9l\u00e9ment de lst
.
Exemple d'utilisation
>>> simpsons = ['Bart', 'Lisa', 'Maggie']\n>>> deuxieme(simpsons)\n'Lisa'\n
Correction def deuxieme(lst) :\n return lst[1]\n
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#312-tri-de-la-liste-grace-a-cette-fonction-deuxieme","title":"3.1.2 Tri de la liste gr\u00e2ce \u00e0 cette fonction deuxieme
","text":"Nous allons utiliser la fonction sorted
, qui prend en param\u00e8tre une liste \u00e0 trier et une fonction de tri.
Exemple :
>>> mylist = [[\"A\", 3], [\"B\", 2], [\"C\", 8]]\n>>> mynewlist = sorted(mylist, key=deuxieme, reverse=True)\n>>> mynewlist\n[['C', 8], ['A', 3], ['B', 2]]\n
Exercice 2
On consid\u00e8re une liste releve
de 100 \u00e9l\u00e8ves avec leur note.
(liste cr\u00e9\u00e9e gr\u00e2ce au module magique faker)
releve = [['Lucas', 13], ['Patrick', 4], ['Michelle', 15], ['Emmanuel', 8], ['Jacqueline', 3], ['Laurent', 11], ['Marcelle', 18], ['Maurice', 14], ['Michelle', 12], ['Michelle', 16], ['Alexandra', 12], ['Patricia', 18], ['Danielle', 15], ['Marc', 2], ['H\u00e9l\u00e8ne', 3], ['Benjamin', 16], ['Laetitia', 2], ['Hugues', 10], ['Samuel', 14], ['\u00c9milie', 6], ['Emmanuel-Maurice', 15], ['Laurent', 13], ['St\u00e9phane', 11], ['David', 16], ['Yves', 7], ['Xavier', 12], ['V\u00e9ronique-Pauline', 6], ['Vincent-Hugues', 15], ['C\u00e9line', 11], ['\u00c9ric-Alain', 19], ['Samuel', 13], ['Gr\u00e9goire', 16], ['\u00c9lodie', 13], ['Daniel', 2], ['Joseph', 18], ['Mathilde', 18], ['Claudine', 16], ['Jean', 12], ['Marcel', 8], ['Nicolas', 7], ['Luc', 11], ['Gabrielle', 8], ['Marianne', 8], ['Paul-St\u00e9phane', 3], ['Florence', 18], ['Joseph', 18], ['Alice', 2], ['Fr\u00e9d\u00e9rique', 17], ['Laurent', 4], ['B\u00e9atrice', 10], ['Agn\u00e8s-C\u00e9cile', 13], ['Jos\u00e9phine', 3], ['Gilbert', 8], ['Claire', 15], ['Tristan', 7], ['Nathan', 18], ['C\u00e9cile', 7], ['Laurent-Roland', 14], ['Christine', 14], ['Olivier', 4], ['Patrick', 18], ['Margot', 11], ['Jessica', 9], ['Guillaume', 19], ['Nicole', 8], ['Louise', 11], ['Kevin', 11], ['Hugues-Martin', 19], ['Emmanuel', 10], ['Nicolas', 5], ['Christiane', 7], ['Charles', 8], ['Paulette', 15], ['Colette', 7], ['Vanessa-\u00c9milie', 6], ['\u00c9lise', 5], ['Denis', 2], ['Alfred', 20], ['Simone', 3], ['Oc\u00e9ane-Jos\u00e9phine', 9], ['Henri', 10], ['Rosalie', 6], ['Doroth\u00e9e', 9], ['R\u00e9my', 8], ['Marcel', 18], ['Odette', 19], ['Monique', 15], ['Mathieu', 12], ['Anne', 9], ['St\u00e9phanie-Dominique', 9], ['Astrid', 10], ['Ren\u00e9', 17], ['Laurence', 11], ['Oc\u00e9ane', 16], ['Hugues', 7], ['G\u00e9rard', 11], ['Xavier', 4], ['Patricia', 19], ['Aur\u00e9lie', 17], ['Th\u00e9odore', 5]]\n
Quel est l'\u00e9l\u00e8ve qui a obtenu la meilleure note ?
Correction releve = [['Lucas', 13], ['Patrick', 4], ['Michelle', 15], ['Emmanuel', 8], ['Jacqueline', 3], ['Laurent', 11], ['Marcelle', 18], ['Maurice', 14], ['Michelle', 12], ['Michelle', 16], ['Alexandra', 12], ['Patricia', 18], ['Danielle', 15], ['Marc', 2], ['H\u00e9l\u00e8ne', 3], ['Benjamin', 16], ['Laetitia', 2], ['Hugues', 10], ['Samuel', 14], ['\u00c9milie', 6], ['Emmanuel-Maurice', 15], ['Laurent', 13], ['St\u00e9phane', 11], ['David', 16], ['Yves', 7], ['Xavier', 12], ['V\u00e9ronique-Pauline', 6], ['Vincent-Hugues', 15], ['C\u00e9line', 11], ['\u00c9ric-Alain', 19], ['Samuel', 13], ['Gr\u00e9goire', 16], ['\u00c9lodie', 13], ['Daniel', 2], ['Joseph', 18], ['Mathilde', 18], ['Claudine', 16], ['Jean', 12], ['Marcel', 8], ['Nicolas', 7], ['Luc', 11], ['Gabrielle', 8], ['Marianne', 8], ['Paul-St\u00e9phane', 3], ['Florence', 18], ['Joseph', 18], ['Alice', 2], ['Fr\u00e9d\u00e9rique', 17], ['Laurent', 4], ['B\u00e9atrice', 10], ['Agn\u00e8s-C\u00e9cile', 13], ['Jos\u00e9phine', 3], ['Gilbert', 8], ['Claire', 15], ['Tristan', 7], ['Nathan', 18], ['C\u00e9cile', 7], ['Laurent-Roland', 14], ['Christine', 14], ['Olivier', 4], ['Patrick', 18], ['Margot', 11], ['Jessica', 9], ['Guillaume', 19], ['Nicole', 8], ['Louise', 11], ['Kevin', 11], ['Hugues-Martin', 19], ['Emmanuel', 10], ['Nicolas', 5], ['Christiane', 7], ['Charles', 8], ['Paulette', 15], ['Colette', 7], ['Vanessa-\u00c9milie', 6], ['\u00c9lise', 5], ['Denis', 2], ['Alfred', 20], ['Simone', 3], ['Oc\u00e9ane-Jos\u00e9phine', 9], ['Henri', 10], ['Rosalie', 6], ['Doroth\u00e9e', 9], ['R\u00e9my', 8], ['Marcel', 18], ['Odette', 19], ['Monique', 15], ['Mathieu', 12], ['Anne', 9], ['St\u00e9phanie-Dominique', 9], ['Astrid', 10], ['Ren\u00e9', 17], ['Laurence', 11], ['Oc\u00e9ane', 16], ['Hugues', 7], ['G\u00e9rard', 11], ['Xavier', 4], ['Patricia', 19], ['Aur\u00e9lie', 17], ['Th\u00e9odore', 5]]\n\ndef deuxieme(lst) :\n return lst[1]\n\nclassement = sorted(releve, key=deuxieme, reverse=True)\n\nprint(classement[0])\n
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#32-retour-sur-le-probleme-du-sac-a-dos","title":"3.2 Retour sur le probl\u00e8me du sac \u00e0 dos","text":" Le probl\u00e8me
On consid\u00e8re un sac de 40 kg et les objets suivants :
objet A B C D E F masse (en kg) 13 12 8 10 14 18 valeur (en \u20ac) 700 500 200 300 600 800 Quels objets faut-il prendre ?
Vous ne pouvez prendre qu'un seul objet de chaque type
(interdiction de donner la combinaison A-A-D, par exemple)
Strat\u00e9gie gloutonne :
- on va classer les objets dans l'ordre d\u00e9croissant de leur taux de valeur (taux de valeur = valeur / masse). Ainsi le premier \u00e9l\u00e9ment de la liste sera celui ayant le meilleur rapport valeur/masse.
- on prend le premier \u00e9l\u00e9ment de la liste, puis le deuxi\u00e8me, etc., tant que le sac peut encore les contenir.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#321-classement-des-objets","title":"3.2.1 Classement des objets","text":"On consid\u00e8re la liste
objets = [[\"A\", 13, 700], [\"B\", 12, 500], [\"C\", 8, 200], [\"D\", 10, 300], [\"E\", 14, 600], [\"F\", 18, 800]]\n
Exercice 3
Cr\u00e9er une fonction ratio
qui prend en param\u00e8tre une liste objet
d\u00e9crivant un objet (exemple : [\"C\", 8, 200]
) et qui renvoie le nombre valeur/masse (donc le 3\u00e8me \u00e9l\u00e9ment divis\u00e9 par le 2\u00e8me).
Exemple d'utilisation :
>>> ratio(['C', 8, 200])\n25.0\n
Correction def ratio(objet):\n return objet[2] / objet[1]\n
Exercice 4
Cr\u00e9er une liste objets_tries
qui reprend les objets de la liste objets
, class\u00e9s suivant leur taux de valeur (ratio valeur/masse)
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#322-calcul-de-la-solution-par-methode-gloutonne","title":"3.2.2 Calcul de la solution, par m\u00e9thode gloutonne","text":"Contrairement \u00e0 l'algorithme du rendu de monnaie, o\u00f9 chaque pi\u00e8ce est disponible en quantit\u00e9 infinie, on ne poss\u00e8de ici qu'un seul objet de chaque type.
Cela signifie qu'il va suffir de parcourir la liste des objets (pr\u00e9alablement class\u00e9s suivant leur taux de valeur) et de d\u00e9cider \u00e0 chaque fois si cet objet peut \u00eatre pris ou pas.
Exercice 5
\u00c9nonc\u00e9Aide \u00c9crire l'algorithme de r\u00e9solution gloutonne du probl\u00e8me du sac \u00e0 dos pour la liste objets
.
objets = [['A', 13, 700], ['B', 12, 500], ['C', 8, 200], ['D', 10, 300], ['E', 14, 600], ['F', 18, 800]]\n
objets = [['A', 13, 700], ['B', 12, 500], ['C', 8, 200], ['D', 10, 300], ['E', 14, 600], ['F', 18, 800]]\n\ndef ratio(objet):\n ...\n\nobjets_tries = ...\n\npoids_max = ...\npoids_sac = ...\n\nbutin = []\n\nfor objet in ...:\n poids_objet = ...\n if ... + ... <= ... :\n butin.append(...)\n ... += ...\n
Correction objets = [['A', 13, 700], ['B', 12, 500], ['C', 8, 200], ['D', 10, 300], ['E', 14, 600], ['F', 18, 800]]\n\ndef ratio(objet):\n return objet[2] / objet[1]\n\nobjets_tries = sorted(objets, key=ratio, reverse=True)\n\npoids_max = 40\npoids_sac = 0\n\nbutin = []\n\nfor objet in objets_tries:\n poids_objet = objet[1]\n if poids_objet + poids_sac <= poids_max :\n butin.append(objet[0])\n poids_sac += poids_objet\n
>>> butin\n ['A', 'F', 'C']\n>>> poids_sac\n39\n
Il faut donc choisir la combinaison A, F, C. Elle est bien valide (poids 39) et rapporte 1700.
Question (toujours la m\u00eame) :
L'algorithme glouton nous a-t-il donn\u00e9 la solution optimale ? Nous allons pour cela avoir recours \u00e0 la force brute pour tester toutes les combinaisons possibles.
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#33-force-brute","title":"3.3 Force brute","text":" - Il faut cr\u00e9er une liste de mots binaires qui vont correspondre \u00e0 chaque combinaison. Par exemple,
101001
signifiera qu'on prend les objets A, C et F. Cette liste est de taille \\(2^n\\), o\u00f9 \\(n\\) est le nombre d'objets. C'est cela qui pose probl\u00e8me : avec 80 objets, on obtient une liste \u00e0 traiter qui contient plus de \\(10^{24}\\) objets, soit de l'ordre de grandeur du nombre d'\u00e9toiles dans l'Univers observable, ou de gouttes d'eau dans la mer, ou du nombre de grains de sables au Sahara... (voir https://fr.wikipedia.org/wiki/Ordres_de_grandeur_de_nombres ) - Une fois cette liste \u00e9tablie, il suffit de parcourir chaque \u00e9l\u00e9ment et de calculer le poids total et la valeur totale correspondante. Si le poids total d\u00e9passe le poids autoris\u00e9, on met la valeur \u00e0 0 car cette combinaison ne nous int\u00e9resse pas.
- Il ne reste qu'\u00e0 chercher la valeur maximale et regarder la combinaison \u00e0 laquelle elle correspond.
objets = [[\"A\", 13, 700], [\"B\", 12, 500], [\"C\", 8, 200], [\"D\", 10, 300], [\"E\", 14, 600], [\"F\", 18, 800]]\npoids_max = 40\n
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/cours/#331-la-liste-de-tous-les-mots-possibles","title":"3.3.1 La liste de tous les mots possibles","text":"combinaisons = []\nfor i in range(2**len(objets)):\n k = bin(i)[2:]\n s = '0'*(len(objets)-len(k)) + k\n combinaisons.append(s)\n
La liste combinaisons
contient bien les 64 mots possibles (\\(2^6=64\\)) :
>>> combinaisons\n ['000000',\n '000001',\n '000010',\n '000011',\n '000100',\n '000101',\n '000110',\n '000111',\n '001000',\n '001001',\n '001010',\n '001011',\n '001100',\n '001101',\n '001110',\n '001111',\n '010000',\n '010001',\n '010010',\n '010011',\n '010100',\n '010101',\n '010110',\n '010111',\n '011000',\n '011001',\n '011010',\n '011011',\n '011100',\n '011101',\n '011110',\n '011111',\n '100000',\n '100001',\n '100010',\n '100011',\n '100100',\n '100101',\n '100110',\n '100111',\n '101000',\n '101001',\n '101010',\n '101011',\n '101100',\n '101101',\n '101110',\n '101111',\n '110000',\n '110001',\n '110010',\n '110011',\n '110100',\n '110101',\n '110110',\n '110111',\n '111000',\n '111001',\n '111010',\n '111011',\n '111100',\n '111101',\n '111110',\n '111111']\n
valeurs = [] \npoids = []\nfor comb in combinaisons :\n poids_comb = 0\n valeur = 0\n for i in range(len(objets)): \n if comb[i] == '1':\n poids_comb += objets[i][1]\n valeur += objets[i][2]\n if poids_comb > poids_max :\n valeur = 0\n valeurs.append(valeur)\n poids.append(poids_comb)\n\nvaleur_max = max(valeurs)\nmeilleure_comb = combinaisons[valeurs.index(valeur_max)]\npoids_comb = poids[valeurs.index(valeur_max)]\n\nmot_sol = \"\"\nfor k in range(len(meilleure_comb)) :\n if meilleure_comb[k] == '1' :\n mot_sol += objets[k][0]\n
>>> mot_sol\n 'ABE'\n
Damned ! La force brute a mis en \u00e9vidence une combinaison meilleure que celle donn\u00e9e par l'algorithme glouton.
En effet la combinaison A-B-E est bien valide (poids total 39) et rapporte 1800, donc 100 de mieux que la solution gloutonne.
Par contre, la force brute est inenvisageable pour si le nombre d'objets est grand, alors que la strat\u00e9gie gloutonne reste tr\u00e8s rapide.
Conclusion
La strat\u00e9gie gloutonne donne tr\u00e8s rapidement des solutions satisfaisantes mais pas forc\u00e9ment optimales. Pour beaucoup de probl\u00e8mes (dont le probl\u00e8me du sac \u00e0 dos), la recherche d'une solution optimale sans passer par la force brute semble impossible (mais cela n'est pas (encore ?) d\u00e9montr\u00e9). Dans ce cas-l\u00e0, la strat\u00e9gie gloutonne peut \u00eatre employ\u00e9e pour avoir vite et bien une solution convenable, m\u00eame si peut-\u00eatre non optimale. On dit que la strat\u00e9gie gloutonne est une heuristique de r\u00e9solution. On sait que ce n'est pas forc\u00e9ment optimal, mais faute de mieux, on s'en contente...
"},{"location":"T4_Algorithmique/4.6_Algorithmes_gloutons/intro_rendu/","title":"Vers l'algorithme de rendu de monnaie","text":"On veut coder la fonction rendu
qui prend pour param\u00e8tre un entier positif somme_a_rendre
et qui renvoie la liste des pi\u00e8ces \u00e0 donner.
Les pieces disponibles (en quantit\u00e9 illimit\u00e9e) sont stock\u00e9es dans une variable pieces = [200, 100, 50, 20, 10, 5, 2, 1]
.
Utilisation : rendu(13)
doit renvoyer [10, 2, 1]
>>> rendu(13)\n [10, 2, 1]\n>>> rendu(58)\n [50, 5, 2, 1]\n
Code \u00e0 trous def rendu(somme_a_rendre):\n pieces = [200, 100, 50, 20, 10, 5, 2, 1]\n solution = []\n ...\n ...\n ...\n ...\n ...\n ...\n ... \n return solution \n
Code \u00e0 trous def rendu(somme_a_rendre):\n pieces = [200, 100, 50, 20, 10, 5, 2, 1]\n solution = []\n i = ... \n while ... > ...:\n if ... <= ... : \n ....append(...) \n ... = ... - ... \n else :\n ... += ... \n return solution \n
Code \u00e0 trous def rendu(somme_a_rendre):\n pieces = [200, 100, 50, 20, 10, 5, 2, 1]\n solution = []\n i = 0 \n while ... > ...:\n if pieces[i] <= ... : \n solution.append(...) \n somme_a_rendre = ... - ... \n else :\n ... += ... \n return solution \n
Code \u00e0 trous def rendu(somme_a_rendre):\n pieces = [200, 100, 50, 20, 10, 5, 2, 1]\n solution = []\n i = 0 \n while somme_a_rendre > ...:\n if pieces[i] <= somme_a_rendre : \n solution.append(...) \n somme_a_rendre = ... - ... \n else :\n i += 1 \n return solution\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/","title":"4.7 Algorithme des KNN","text":"Algorithme des K-Nearest-Neighbours (KNN), aka les k-plus-proches-voisins
La m\u00e9thode KNN est une m\u00e9thode simple et efficace de classification. La classification est un enjeu majeur de l'Intelligence Artificielle :
- la cam\u00e9ra d'une voiture autonome per\u00e7oit un panneau, mais quel est ce panneau ?
- un grain de beaut\u00e9 est pris en photo par un dermatologue, ce grain de beaut\u00e9 est-il \u00e0 surveiller ?
- ...
La m\u00e9thode du KNN va trouver quels sont, dans une base de donn\u00e9es d\u00e9j\u00e0 bien remplie et labell\u00e9e, les k-objets (les 6 objets si \\(k=6\\) par exemple) qui se rapprochent le plus de l'objet \u00e0 classifier. En prenant ensuite la caract\u00e9ristique la plus fr\u00e9quente parmi ces 6 objets, on devine alors dans quelle cat\u00e9gorie notre objet doit se classer.
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#1-objectif","title":"1. Objectif","text":"Nous allons reprendre le jeu de donn\u00e9es sur les joueurs du Top14 utilis\u00e9 dans le cours \u00abTrier des donn\u00e9es\u00bb
Nous souhaitons pouvoir r\u00e9pondre \u00e0 cette question :
Question
Si on croise une personne (qu'on appelera joueur X) nous disant qu'elle veut jouer en Top14, et qu'elle nous donne son poids et sa taille, peut-on lui pr\u00e9dire \u00e0 quel poste elle devrait jouer ?
Nous devons donc cr\u00e9er une fonction conseil_poste
qui prend en argument poids
et taille
, qui sont les caract\u00e9ristiques du joueur X. Cette fonction prendra aussi en param\u00e8tre un nombre k
qui sera le nombre de voisins utilis\u00e9s pour d\u00e9terminer le poste conseill\u00e9.
La fonction doit renvoyer une cha\u00eene de caract\u00e8re correspondant au poste auquel on lui conseille de jouer.
Il va falloir pour cela classer tous les joueurs du Top14 suivant leur proximit\u00e9 morphologique avec notre joueur X, et prendre parmi les k
premiers joueurs le poste majoritaire.
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#2-fonction-distance-morphologique","title":"2. Fonction distance
morphologique","text":"Dans toute id\u00e9e de classification il y a l'id\u00e9e de distance. Il faut comprendre la distance comme une mesure de la diff\u00e9rence.
Comment mesurer la diff\u00e9rence physique entre deux joueurs de rugby ?
Fonction distance
\u00c9crire une fonction distance
qui re\u00e7oit en param\u00e8tres :
poids
: le poids du joueur X taille
: la taille du joueur X player
: un joueur de la liste joueurs
et qui renvoie la distance morphologique du joueur X avec player
.
Exemple d'utilisation :
>>> distance(93, 190, joueurs[34])\n445\n
Correction def distance(poids, taille, player):\n p = int(player['Poids'])\n t = int(player['Taille'])\n return (poids-p)**2 + (taille-t)**2\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#3-classement-des-joueurs-suivant-leur-proximite-morphologique","title":"3. Classement des joueurs suivant leur proximit\u00e9 morphologique","text":"De la m\u00eame mani\u00e8re qu'on avait class\u00e9 les joueurs suivant leur IMC, on peut les classer suivant leur proximit\u00e9 morphologique avec le joueur X.
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#31-fonction-second","title":"3.1 Fonction second
","text":"Fonction second
\u00c9crire une fonction second
qui re\u00e7oit en param\u00e8tres :
couple
: un couple de valeurs
et qui renvoie le deuxi\u00e8me \u00e9l\u00e9ment du couple.
Exemple d'utilisation :
>>> cpl = (\"vendredi\", 13)\n>>> second(cpl)\n13\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#32-classement-des-k-plus-proches-joueurs","title":"3.2 Classement des k plus proches joueurs","text":"Fonction classement_k_joueurs
\u00c9crire une fonction classement_k_joueurs
qui re\u00e7oit en param\u00e8tres :
poids
: le poids du joueur X taille
: la taille du joueur X k
: le nombre de joueurs les plus proches que l'on veut garder
et qui renvoie une liste contenant les k
joueurs class\u00e9s suivant leur proximit\u00e9 morphologique avec le joueur X.
Exemple d'utilisation :
>>> classement_k_joueurs(85, 186, 3)\n[{'Equipe': 'Bordeaux', 'Nom': 'Geoffrey CROS', 'Poste': 'Arri\u00e8re', 'Date de naissance': '08/03/1997', 'Taille': '185', 'Poids': '85'}, {'Equipe': 'Toulouse', 'Nom': 'Romain NTAMACK', 'Poste': 'Ouverture', 'Date de naissance': '01/05/1999', 'Taille': '186', 'Poids': '84'}, {'Equipe': 'Bayonne', 'Nom': 'Manuel ORDAS', 'Poste': 'Ouverture', 'Date de naissance': '21/02/1998', 'Taille': '186', 'Poids': '83'}]\n
Correction def classement_k_joueurs(poids, taille, k):\n couples = []\n for player in joueurs:\n couples.append((player, distance(poids, taille, player)))\n couples_tries = sorted(couples, key=second)\n joueurs_classes = [couple[0] for couple in couples_tries]\n return joueurs_classes[:k]\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#4-recherche-du-poste-le-plus-represente","title":"4. Recherche du poste le plus repr\u00e9sent\u00e9","text":""},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#41-dictionnaire-doccurence-des-postes","title":"4.1 Dictionnaire d'occurence des postes","text":"Fonction occurence
\u00c9crire une fonction occurence
qui re\u00e7oit en param\u00e8tres :
joueurs
: une liste de joueurs
et qui renvoie le dictionnaire compos\u00e9 diff\u00e9rents postes de ces joueurs, et du nombre de fois o\u00f9 ils apparaissent dans la liste joueurs
.
Exemple d'utilisation :
>>> occurence(joueurs)\n{'Pilier': 110, 'Talonneur': 50, '2\u00e8me ligne': 74, '3\u00e8me ligne': 111, 'M\u00eal\u00e9e': 42, 'Ouverture': 38, 'Centre': 71, 'Ailier': 64, 'Arri\u00e8re': 35}\n
Correction def occurence(joueurs):\n occ = {}\n for player in joueurs:\n if player['Poste'] in occ:\n occ[player['Poste']] += 1\n else:\n occ[player['Poste']] = 1\n return occ\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#42-tri-dun-dictionnaire","title":"4.2 Tri d'un dictionnaire","text":"Fonction cle_max
\u00c9crire une fonction cle_max
qui re\u00e7oit en param\u00e8tre :
d
: un dictionnaire dont les cl\u00e9s sont des chaines de caract\u00e8re et les valeurs sont des nombres.
et qui renvoie la cl\u00e9 associ\u00e9e \u00e0 la valeur maximale.
Exemple d'utilisation :
>>> d = {\"lundi\":13, \"mardi\":9, \"mercredi\":18, \"jeudi\":4}\n>>> cle_max(d)\n'mercredi'\n
Correction def cle_max(d):\n maxi = 0\n for key in d:\n if d[key] > maxi:\n maxi = d[key]\n key_max = key\n return key_max\n
"},{"location":"T4_Algorithmique/4.7_Algorithme_KNN/cours/#43-fonction-conseil_poste","title":"4.3 Fonction conseil_poste
","text":"Fonction conseil_poste
\u00c9crire une fonction conseil_poste
qui re\u00e7oit en param\u00e8tres :
poids
: le poids du joueur X taille
: la taille du joueur X k
: le nombre de joueurs les plus proches sur lequel on se base pour faire la pr\u00e9diction
et qui renvoie le poste le plus compatible avec la morphologie de X.
Exemple d'utilisation :
>>> conseil_poste(70, 170, 6)\n'M\u00eal\u00e9e'\n>>> conseil_poste(120, 210, 6)\n'2\u00e8me ligne'\n
Correction def conseil_poste(poids, taille, k):\n joueurs_classes = classement_k_joueurs(poids, taille, k)\n dico = occurence(joueurs_classes)\n poste_conseille = cle_max(dico)\n return poste_conseille\n
Faire varier les diff\u00e9rents param\u00e8tres pour observer leur r\u00f4le respectif.
"},{"location":"T5_Traitement_de_donnees/sommaire/","title":"Th\u00e8me 5 : Traitement de donn\u00e9es","text":" - Manipulation de fichiers csv
- Trier des donn\u00e9es
- Utilisation du module Pandas
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/","title":"5.1 Manipulation de fichiers csv","text":"Les fichiers CSV (pour Comma Separated Values) sont des fichiers-texte (ils ne contiennent aucune mise en forme) utilis\u00e9s pour stocker des donn\u00e9es, s\u00e9par\u00e9es par des virgules (ou des points-virgules, ou des espaces...). Il n'y a pas de norme officielle du CSV.
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#1-ouverture-dun-fichier-csv-par-des-logiciels-classiques","title":"1. Ouverture d'un fichier CSV par des logiciels classiques","text":" - T\u00e9l\u00e9charger le fichier exemple.csv
- Ouvrir avec le Bloc-Notes ce fichier.
- Rajouter une ligne avec une personne suppl\u00e9mentaire, sauvegarder le fichier.
- Ouvrir le fichier avec LibreOffice.
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#2-exploitation-dun-fichier-csv-en-python-avec-le-module-csv","title":"2. Exploitation d'un fichier CSV en Python avec le module CSV","text":"L'utilisation d'un tableur peut \u00eatre d\u00e9licate lorsque le fichier CSV comporte un tr\u00e8s grand nombre de lignes. Python permet de lire et d'extraire des informations d'un fichier CSV m\u00eame tr\u00e8s volumineux, gr\u00e2ce \u00e0 des modules d\u00e9di\u00e9s, comme le bien-nomm\u00e9 csv
(utilis\u00e9 ici) ou bien pandas
(qui sera vu plus tard).
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#21-premiere-methode","title":"2.1 Premi\u00e8re m\u00e9thode","text":"Le script suivant :
import csv \nf = open('exemple.csv', \"r\", encoding = 'utf-8') # le \"r\" signifie \"read\", le fichier est ouvert en lecture seule\ndonnees = csv.reader(f) # donnees est un objet (sp\u00e9cifique au module csv) qui contient des lignes\n\nfor ligne in donnees: \n print(ligne)\n\nf.close() # toujours fermer le fichier !\n
donne :
['Pr\u00e9nom', 'Nom', 'Email', 'SMS']\n['John', 'Smith', 'john@example.com', '33123456789']\n['Harry', 'Pierce', 'harry@example.com', '33111222222']\n['Howard', 'Paige', 'howard@example.com', '33777888898']\n
Probl\u00e8mes
- Les donn\u00e9es ne sont pas structur\u00e9es : la premi\u00e8re ligne est la ligne des \u00abdescripteurs\u00bb (ou des \u00abchamps\u00bb), alors que les lignes suivantes sont les valeurs de ces descripteurs.
- La variable
donnees
n'est pas exploitable en l'\u00e9tat. Ce n'est pas une structure connue.
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#22-ameliorations","title":"2.2 Am\u00e9liorations","text":"Au lieu d'utiliser la fonction csv.reader()
, utilisons csv.DictReader()
. Comme son nom l'indique, elle renverra une variable contenant des dictionnaires.
Le script suivant :
import csv\nf = open('exemple.csv', \"r\", encoding = 'utf-8')\ndonnees = csv.DictReader(f)\n\nfor ligne in donnees:\n print(dict(ligne))\n\nf.close()\n
donne
{'Pr\u00e9nom': 'John', 'Nom': 'Smith', 'Email': 'john@example.com', 'SMS': '33123456789'}\n{'Pr\u00e9nom': 'Harry', 'Nom': 'Pierce', 'Email': 'harry@example.com', 'SMS': '33111222222'}\n{'Pr\u00e9nom': 'Howard', 'Nom': 'Paige', 'Email': 'howard@example.com', 'SMS': '33777888898'}\n
C'est mieux ! Les donn\u00e9es sont maintenant des dictionnaires. Mais nous avons juste \u00e9num\u00e9r\u00e9 3 dictionnaires. Comment r\u00e9-acc\u00e9der au premier d'entre eux, celui de John Smith ? Essayons :
>>> donnees[0]\n\n ---------------------------------------------------------------------------\n\n TypeError Traceback (most recent call last)\n\n <ipython-input-3-9914ab00321e> in <module>\n ----> 1 donnees[0]\n\n\n TypeError: 'DictReader' object does not support indexing\n
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#23-une-liste-de-dictionnaires","title":"2.3 Une liste de dictionnaires","text":"Nous allons donc cr\u00e9er une liste de dictionnaires.
Le script suivant :
import csv\nf = open('exemple.csv', \"r\", encoding = 'utf-8')\ndonnees = csv.DictReader(f)\namis = []\nfor ligne in donnees:\n amis.append(dict(ligne))\n\nf.close()\n
permet de faire ceci :
>>> amis\n\n [{'Pr\u00e9nom': 'John',\n 'Nom': 'Smith',\n 'Email': 'john@example.com',\n 'SMS': '33123456789'},\n {'Pr\u00e9nom': 'Harry',\n 'Nom': 'Pierce',\n 'Email': 'harry@example.com',\n 'SMS': '33111222222'},\n {'Pr\u00e9nom': 'Howard',\n 'Nom': 'Paige',\n 'Email': 'howard@example.com',\n 'SMS': '33777888898'}]\n\n>>> print(amis[0]['Email'])\n john@example.com\n\n>>> print(amis[2]['Nom'])\n Paige\n
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#3-un-fichier-un-peu-plus-interessant-les-joueurs-de-rugby-du-top14","title":"3. Un fichier un peu plus int\u00e9ressant : les joueurs de rugby du TOP14","text":"Le fichier top14.csv
contient tous les joueurs du Top14 de rugby, saison 2019-2020, avec leur date de naissance, leur poste, et leurs mensurations.
Ce fichier a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9 par R\u00e9mi Deniaud, de l'acad\u00e9mie de Bordeaux.
Question 1
Stocker dans une variable joueurs
les renseignements de tous les joueurs pr\u00e9sents dans ce fichier csv.
Correction import csv\nf = open('data/top14.csv', 'r', encoding = 'utf-8')\ndonnees = csv.DictReader(f)\njoueurs = []\nfor ligne in donnees:\n joueurs.append(dict(ligne))\n\nf.close()\n
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#31-premiere-analyse","title":"3.1 Premi\u00e8re analyse","text":"Question 2
Combien de joueurs sont pr\u00e9sents dans ce fichier ?
Correction >>> len(joueurs)\n595\n
Question 3
Quel est le nom du joueur n\u00b0486 ?
Correction >>> joueurs[486]['Nom']\n'Wenceslas LAURET'\n
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#32-extraction-de-donnees-particulieres","title":"3.2 Extraction de donn\u00e9es particuli\u00e8res","text":"Question 4
En 2019, o\u00f9 jouait Baptiste SERIN ?
Correction La m\u00e9thode la plus naturelle est de parcourir toute la liste jusqu'\u00e0 trouver le bon joueur, puis d'afficher son \u00e9quipe.
>>> for joueur in joueurs :\n if joueur['Nom'] == 'Baptiste SERIN' :\n print(joueur['Equipe'])\n
Une m\u00e9thode plus efficace est d'utiliser une liste par compr\u00e9hension incluant un test.
>>> clubSerin = [joueur['Equipe'] for joueur in joueurs if joueur['Nom'] == 'Baptiste SERIN']\n>>> clubSerin\n
Question 5
Qui sont les joueurs de plus de 140 kg ?
Attention \u00e0 bien convertir en entier la chaine de caract\u00e8re renvoy\u00e9e par la cl\u00e9 Poids
, \u00e0 l'aide de la fonction int()
.
Correction >>> lourds = [(joueur['Nom'], joueur['Poids']) for joueur in joueurs if int(joueur['Poids']) > 140]\n>>> lourds\n
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#4-exploitation-graphique","title":"4. Exploitation graphique","text":"Nous allons utiliser le module Matplotlib pour illustrer les donn\u00e9es de notre fichier csv.
Pour tracer un nuage de points (par l'instruction plt.plot
), Matplotlib requiert :
- une liste
X
contenant toutes les abscisses des points \u00e0 tracer. - une liste
Y
contenant toutes les ordonn\u00e9es des points \u00e0 tracer.
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#41-exemple","title":"4.1 Exemple","text":"import matplotlib.pyplot as plt\nX = [0, 1, 3, 6]\nY = [12, 10, 7, 15]\nplt.plot(X, Y, 'ro') \nplt.show()\n
Dans l'instruction plt.plot(X, Y, 'ro')
: X
sont les abscisses, Y
sont les ordonn\u00e9es, 'ro'
signifie : - qu'on veut des points (c'est le
'o'
, plus de choix ici). - qu'on veut qu'ils soient rouges (c'est le
'r'
plus de choix ici).
"},{"location":"T5_Traitement_de_donnees/5.1_Manipulation_csv/cours/#42-application","title":"4.2 Application","text":"Question 6
Afficher sur un graphique tous les joueurs de rugby du Top14, en mettant le poids en abscisse et la taille en ordonn\u00e9e.
Correction X = [int(joueur['Poids']) for joueur in joueurs]\nY = [int(joueur['Taille']) for joueur in joueurs]\nplt.plot(X, Y, 'ro') \nplt.show()\n
Question 7
Faire appara\u00eetre ensuite les joueurs \u00e9voluant au poste de Centre en bleu, et les 2\u00e8me lignes en vert.
Correction #tous les joueurs\nX = [int(joueur['Poids']) for joueur in joueurs]\nY = [int(joueur['Taille']) for joueur in joueurs]\nplt.plot(X, Y, 'ro') \n\n#on recolorie les Centres en bleu\nX = [int(joueur['Poids']) for joueur in joueurs if joueur['Poste'] == 'Centre']\nY = [int(joueur['Taille']) for joueur in joueurs if joueur['Poste'] == 'Centre']\nplt.plot(X, Y, 'bo')\n\n#on recolorie les 2\u00e8me ligne en vert\nX = [int(joueur['Poids']) for joueur in joueurs if joueur['Poste'] == '2\u00e8me ligne']\nY = [int(joueur['Taille']) for joueur in joueurs if joueur['Poste'] == '2\u00e8me ligne']\nplt.plot(X, Y, 'go')\n\n\nplt.show()\n
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/","title":"5.2 Trier des donn\u00e9es","text":"Nous reprenons notre fichier de joueurs de rugby du Top14. : top14.csv
import csv\nf = open('top14.csv', \"r\", encoding = 'utf-8')\ndonnees = csv.DictReader(f)\njoueurs = []\nfor ligne in donnees:\n joueurs.append(dict(ligne))\n\nf.close()\n
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#1-creer-une-fonction-filtre","title":"1. Cr\u00e9er une fonction filtre","text":"Question 1
Cr\u00e9er une fonction joueursEquipe
qui renvoie une liste contenant les fiches de tous les joueurs de l'\u00e9quipe equipe
pass\u00e9e en param\u00e8tre.
Exemple d'utilisation :
>>> joueursEquipe('Bordeaux')\n[{'Equipe': 'Bordeaux', 'Nom': 'Jefferson POIROT', 'Poste': 'Pilier', 'Date de naissance': '01/11/1992', 'Taille': '181', 'Poids': '117'}, {'Equipe': 'Bordeaux', 'Nom': 'Lasha TABIDZE', 'Poste': 'Pilier', 'Date de naissance': '04/07/1997', 'Taille': '185', 'Poids': '117'}, {'Equipe': 'Bordeaux', 'Nom': 'Laurent DEL.....\n
Correction def joueursEquipe(equipe): \n return [player for player in joueurs if player['Equipe'] == equipe]\n
Question 2
D\u00e9finir de la m\u00eame mani\u00e8re une fonction joueursPoste
qui prend une cha\u00eene de caract\u00e8res poste
et qui renvoie la liste des fiches des joueurs jouant \u00e0 ce poste.
Exemple d'utilisation :
>>> joueursPoste(\"Talonneur\")\n[{'Equipe': 'Agen', 'Nom': 'Cl\u00e9ment MARTINEZ', 'Poste': 'Talonneur', 'Date de naissance': '14/03/1996', 'Taille': '181', 'Poids': '105'}, {'Equipe': 'Agen', 'Nom': 'Marc BARTHOMEUF', 'Poste': 'T...\n
Correction def joueursPoste(poste): \n return [player for player in joueurs if player['Poste'] == poste]\n
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#2-utilisation-dune-fonction-de-tri","title":"2. Utilisation d'une fonction de tri","text":""},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#21-le-probleme","title":"2.1 Le probl\u00e8me","text":"Comment classer les joueurs suivant leur taille ? La fonction sorted(liste)
est efficace sur les listes : elle renvoie une nouvelle liste tri\u00e9e dans l'ordre croissant.
>>> mylist = [4,2,8,6]\n>>> mynewlist = sorted(mylist)\n>>> print(mynewlist)\n [2, 4, 6, 8]\n
Mais comment trier un dictionnaire ?
>>> test = sorted(joueurs)\n
---------------------------------------------------------------------------\n\nTypeError Traceback (most recent call last)\n\n<ipython-input-14-de081d14a3da> in <module>\n----> 1 test = sorted(joueurs)\n\n\nTypeError: '<' not supported between instances of 'dict' and 'dict'\n
Il est normal que cette tentative \u00e9choue : un dictionnaire poss\u00e8de plusieurs cl\u00e9s diff\u00e9rentes. Ici, plusieurs cl\u00e9s peuvent \u00eatre des crit\u00e8res de tri : la taille, le poids.
Nous allons donc utiliser la m\u00eame strat\u00e9gie que celle utilis\u00e9e pour le probl\u00e8me du sac \u00e0 dos.
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#22-un-exemple-de-tri-de-dictionnaire","title":"2.2 Un exemple de tri de dictionnaire","text":"Simpsons = [{\"Prenom\" : \"Bart\", \"age estim\u00e9\": \"10\"},\n {\"Prenom\" : \"Lisa\", \"age estim\u00e9\": \"8\"},\n {\"Prenom\" : \"Maggie\", \"age estim\u00e9\": \"1\"},\n {\"Prenom\" : \"Homer\", \"age estim\u00e9\": \"38\"},\n {\"Prenom\" : \"Marge\", \"age estim\u00e9\": \"37\"}]\n\ndef age(personnage):\n return int(personnage[\"age estim\u00e9\"])\n
>>> age(Simpsons[0])\n 10\n
La cr\u00e9ation de cette fonction age
va nous permettre de sp\u00e9cifier une cl\u00e9 de tri, par le param\u00e8tre key
:
Tri d'un dictionnaire
>>> triSimpsons = sorted(Simpsons, key=age)\n
>>> triSimpsons\n [{'Prenom': 'Maggie', 'age estim\u00e9': '1'},\n {'Prenom': 'Lisa', 'age estim\u00e9': '8'},\n {'Prenom': 'Bart', 'age estim\u00e9': '10'},\n {'Prenom': 'Marge', 'age estim\u00e9': '37'},\n {'Prenom': 'Homer', 'age estim\u00e9': '38'}]\n
On peut aussi inverser l'ordre de tri :
>>> triSimpsons = sorted(Simpsons, key=age, reverse=True)\n>>> triSimpsons\n [{'Prenom': 'Homer', 'age estim\u00e9': '38'},\n {'Prenom': 'Marge', 'age estim\u00e9': '37'},\n {'Prenom': 'Bart', 'age estim\u00e9': '10'},\n {'Prenom': 'Lisa', 'age estim\u00e9': '8'},\n {'Prenom': 'Maggie', 'age estim\u00e9': '1'}]\n
Question 3
Trier les joueurs du Top14 par taille.
Correction def taillePlayer(player) :\n return int(player['Taille'])\n\njoueurs_taille_croissant = sorted(joueurs, key=taillePlayer)\n
Question 4
Trier les joueurs du Top14 par poids.
Correction def poidsPlayer(player) :\n return int(player['Poids'])\n\njoueurs_poids_croissant = sorted(joueurs, key=poidsPlayer)\n
Question 5
Trier les joueurs de Bordeaux suivant leur Indice de Masse Corporelle (IMC )
Correction def IMC(player):\n masse = int(player['Poids'])\n taille_m = int(player['Taille']) / 100\n return masse / taille_m**2\n\njoueursUBB = [player for player in joueurs if player['Equipe'] == 'Bordeaux']\njoueursUBB_tri = sorted(joueursUBB, key=IMC)\n
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#3-recherche-des-joueurs-de-profil-physique-similaire","title":"3. Recherche des joueurs de profil physique similaire","text":""},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#31-distance-entre-deux-joueurs","title":"3.1 Distance entre deux joueurs","text":"Question 6
Construire une fonction distance
qui renvoie la somme des carr\u00e9s des diff\u00e9rences de tailles et de poids entre deux joueurs joueur1
et joueur2
, pass\u00e9s en param\u00e8tres.
\\[d = (p_1-p_2)^2 + (t_1-t_2)^2\\] Cette fonction nous permettra d'estimer la diff\u00e9rence morphologique entre deux joueurs.
Exemple d'utilisation :
>>> distance(joueurs[23], joueurs[31])\n244\n
V\u00e9rification :
>>> joueurs[23]\n{'Equipe': 'Agen', 'Nom': 'Alban CONDUCH\u00c9', 'Poste': 'Centre', 'Date de naissance': '29/10/1996', 'Taille': '190', 'Poids': '102'}\n>>> joueurs[31]\n{'Equipe': 'Agen', 'Nom': 'JJ TAULAGI', 'Poste': 'Arri\u00e8re', 'Date de naissance': '18/06/1993', 'Taille': '180', 'Poids': '90'}\n
\\((102-90)^2+(190-180)^2=244\\)
Correction def distance(joueur1,joueur2):\n p1 = int(joueur1['Poids'])\n p2 = int(joueur2['Poids'])\n t1 = int(joueur1['Taille'])\n t2 = int(joueur2['Taille'])\n return (p1 - p2)**2 + (t1 - t2)**2\n
"},{"location":"T5_Traitement_de_donnees/5.2_Trier_des_donnees/cours/#32-distance-des-joueurs-avec-baptiste-serin","title":"3.2 Distance des joueurs avec Baptiste Serin","text":"Retrouvons d'abord le num\u00e9ro de Baptiste Serin dans notre classement de joueurs :
>>> for k in range(len(joueurs)) :\n if joueurs[k]['Nom'] == 'Baptiste SERIN' :\n print(k)\n530\n
>>> joueurs[530]\n {'Equipe': 'Toulon',\n 'Nom': 'Baptiste SERIN',\n 'Poste': 'M\u00eal\u00e9e',\n 'Date de naissance': '20/06/1994',\n 'Taille': '180',\n 'Poids': '79'}\n
Baptiste SERIN est donc le joueur num\u00e9ro 530.
Question 7
Cr\u00e9er une fonction distanceSerin
qui prend en param\u00e8tre un joueur et qui renvoie sa diff\u00e9rence avec Baptiste Serin.
Exemple d'utilisation :
>>> distanceSerin(joueurs[18])\n745\n
Correction def distanceSerin(joueur):\n return distance(joueurs[530], joueur)\n
Question 8
Classer l'ensemble des joueurs du Top14 suivant leur diff\u00e9rence morphologique avec Baptiste Serin (du plus proche au plus \u00e9loign\u00e9). Afficher le nom des 10 premiers joueurs.
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/","title":"5.3 Utilisation du module Pandas","text":"Les manipulations de ce cours pourront \u00eatre effectu\u00e9es sur un Notebook de Capytale.
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#1-introduction-et-premiere-dataframe","title":"1. Introduction et premi\u00e8re dataframe","text":"Le module csv
utilis\u00e9 pr\u00e9c\u00e9demment se contente de lire les donn\u00e9es structur\u00e9es. Il ne fait aucun effort particulier pour analyser les donn\u00e9es. Nous nous en sommes aper\u00e7us lorsqu'il a fallu convertir par int()
toutes les valeurs num\u00e9riques, qui \u00e9taient interpr\u00e9t\u00e9es comme des cha\u00eenes de caract\u00e8res. La biblioth\u00e8que pandas est par contre sp\u00e9cialement con\u00e7ue pour l'analyse des donn\u00e9es (data analysis) : elle est donc naturellement bien plus performante.
Importation du module pandas
L'import se fait classiquement par :
import pandas as pd \n
Le type de variable dans lequel pandas
va stocker les donn\u00e9es s'appelle une dataframe, qui sera souvent abr\u00e9g\u00e9e par df
.
Nous allons retravailler avec le fichier top14.csv
.
Premi\u00e8re dataframe
Nos donn\u00e9es seront ensuite import\u00e9es dans la dataframe df
par l'instruction :
df = pd.read_csv('top14.csv', encoding = 'utf-8') \n
>>> type(df)\n<class 'pandas.core.frame.DataFrame'>\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#2-observation-des-donnees","title":"2. Observation des donn\u00e9es","text":"Que contient la variable df
?
>>> df\n Equipe Nom Poste Date de naissance Taille Poids\n0 Agen Anton PEIKRISHVILI Pilier 18/09/1987 183 122\n1 Agen Dave RYAN Pilier 21/04/1986 183 116\n2 Agen Giorgi TETRASHVILI Pilier 31/08/1993 177 112\n3 Agen Kamaliele TUFELE Pilier 11/10/1995 182 123\n4 Agen Malino VANA\u00cf Pilier 04/05/1993 183 119\n.. ... ... ... ... ... ...\n590 Toulouse Werner KOK Ailier 27/01/1993 177 78\n591 Toulouse Yoann HUGET Ailier 02/06/1987 190 97\n592 Toulouse Matthis LEBEL Arri\u00e8re 25/03/1999 185 91\n593 Toulouse Maxime M\u00c9DARD Arri\u00e8re 16/11/1986 180 85\n594 Toulouse Thomas RAMOS Arri\u00e8re 23/07/1995 178 86\n\n[595 rows x 6 columns]\n
Les donn\u00e9es sont pr\u00e9sent\u00e9es dans l'ordre originel du fichier.
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#21-structure-globale-des-donnees","title":"2.1 Structure globale des donn\u00e9es","text":"La structure des donn\u00e9es : info
>>> df.info()\n<class 'pandas.core.frame.DataFrame'>\nRangeIndex: 595 entries, 0 to 594\nData columns (total 6 columns):\n # Column Non-Null Count Dtype \n--- ------ -------------- ----- \n 0 Equipe 595 non-null object\n 1 Nom 595 non-null object\n 2 Poste 595 non-null object\n 3 Date de naissance 595 non-null object\n 4 Taille 595 non-null int64 \n 5 Poids 595 non-null int64 \ndtypes: int64(2), object(4)\nmemory usage: 28.0+ KB\n
On peut y constater une tr\u00e8s bonne nouvelle : les donn\u00e9es num\u00e9riques sont reconnues comme telles (type int64
).
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#22-acces-a-une-fiche-particuliere","title":"2.2 Acc\u00e8s \u00e0 une fiche particuli\u00e8re","text":"D'apr\u00e8s la commande pr\u00e9c\u00e9dente, il y a 595 entr\u00e9es dans notre fichier de donn\u00e9es. L'acc\u00e8s \u00e0 une fiche particuli\u00e8re se fera avec la commande loc
.
Acc\u00e8s \u00e0 une fiche : loc
>>> df.loc[312]\nEquipe Lyon\nNom Charlie NGATAI\nPoste Centre\nDate de naissance 17/08/1990\nTaille 188\nPoids 103\nName: 312, dtype: object\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#23-premieres-et-dernieres-lignes","title":"2.3 Premi\u00e8res et derni\u00e8res lignes","text":"Il est toutefois possible d'avoir uniquement les premi\u00e8res lignes du fichier avec la commande head()
et les derni\u00e8res du fichier avec la commande tail()
. Ces commandes peuvent recevoir en param\u00e8tre un nombre entier :
Les premi\u00e8res lignes du fichier : head
>>> df.head()\n Equipe Nom Poste Date de naissance Taille Poids\n0 Agen Anton PEIKRISHVILI Pilier 18/09/1987 183 122\n1 Agen Dave RYAN Pilier 21/04/1986 183 116\n2 Agen Giorgi TETRASHVILI Pilier 31/08/1993 177 112\n3 Agen Kamaliele TUFELE Pilier 11/10/1995 182 123\n4 Agen Malino VANA\u00cf Pilier 04/05/1993 183 119\n\n>>> df.head(2)\n Equipe Nom Poste Date de naissance Taille Poids\n0 Agen Anton PEIKRISHVILI Pilier 18/09/1987 183 122\n1 Agen Dave RYAN Pilier 21/04/1986 183 116\n
Les derni\u00e8res lignes du fichier : tail
>>> df.tail()\n Equipe Nom Poste Date de naissance Taille Poids\n590 Toulouse Werner KOK Ailier 27/01/1993 177 78\n591 Toulouse Yoann HUGET Ailier 02/06/1987 190 97\n592 Toulouse Matthis LEBEL Arri\u00e8re 25/03/1999 185 91\n593 Toulouse Maxime M\u00c9DARD Arri\u00e8re 16/11/1986 180 85\n594 Toulouse Thomas RAMOS Arri\u00e8re 23/07/1995 178 86\n\n>>> df.tail(3)\n Equipe Nom Poste Date de naissance Taille Poids\n592 Toulouse Matthis LEBEL Arri\u00e8re 25/03/1999 185 91\n593 Toulouse Maxime M\u00c9DARD Arri\u00e8re 16/11/1986 180 85\n594 Toulouse Thomas RAMOS Arri\u00e8re 23/07/1995 178 86\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#3-analyse-automatique-et-filtrage","title":"3. Analyse automatique et filtrage","text":""},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#31-extraction-dune-colonne","title":"3.1 Extraction d'une colonne","text":"L'id\u00e9e g\u00e9n\u00e9rale est que l'on va cr\u00e9er de nouveaux objets contenant uniquement les renseignements qui nous int\u00e9ressent.
Extraction d'une colonne : df[colonne]
Pour cr\u00e9er une liste contenant uniquement les donn\u00e9es num\u00e9riques de la colonne poids
, il suffit d'\u00e9crire :
poids = df['Poids']\n
La variable poids
est un objet de type Series
(assimilable \u00e0 une liste) qui va pouvoir \u00eatre exploit\u00e9e tr\u00e8s facilement.
On peut d'ailleurs acc\u00e9der \u00e0 un \u00e9l\u00e9ment particulier de cette variable :
>>> poids[15]\n114\n
On confirme donc une excellente nouvelle : les poids sont bien consid\u00e9r\u00e9s nativement comme des nombres. On peut donc se servir de mani\u00e8re tr\u00e8s intuitive de cette fonctionnalit\u00e9 pour faire des graphiques tr\u00e8s facilement, sans conversion comme dans le module csv
!
Pour trouver le poids minimal de cette s\u00e9rie, on utilisera naturellement la fonction min
:
>>> min(poids)\n70\n
Pour tracer notre nuage de points poids-taille, le code sera donc simplement :
import matplotlib.pyplot as plt\nX = df['Poids']\nY = df['Taille']\nplt.plot(X, Y, 'ro')\nplt.show()\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#32-tri-et-analyse-automatique-des-donnees","title":"3.2 Tri et Analyse automatique des donn\u00e9es","text":"L'interpr\u00e9tation num\u00e9rique permet \u00e0 pandas
d'analyser automatiquement les donn\u00e9es, avec notamment la fonction describe()
.
R\u00e9sum\u00e9 des donn\u00e9es num\u00e9riques : describe
>>> df['Taille'].describe()\ncount 595.000000\nmean 186.559664\nstd 7.572615\nmin 169.000000\n25% 181.000000\n50% 186.000000\n75% 192.000000\nmax 208.000000\nName: Taille, dtype: float64\n
On voit donc que les principaux indicateurs statistiques sont propos\u00e9s.
D'ailleurs, on peut tr\u00e8s facilement tracer des boites \u00e0 moustaches avec la fonction boxplot()
.
graph_taille = df.boxplot(\"Taille\")\ngraph_taille.plot()\nplt.show()\n
Pour les donn\u00e9es non-num\u00e9riques, la commande describe()
n'est que peu d'utilit\u00e9. Elle renseigne toutefois la valeur la plus fr\u00e9quente (en statistiques, le mode ou valeur modale) gr\u00e2ce \u00e0 describe().top
.
Valeur modale de donn\u00e9es non-num\u00e9riques : describe().top
>>> df['Poste'].describe().top\n'3\u00e8me ligne'\n
Pour avoir un d\u00e9tail plus pr\u00e9cis de la r\u00e9partition des donn\u00e9es, on peut utiliser value_counts
:
R\u00e9partition des valeurs : value_counts
>>> df['Poste'].value_counts()\n3\u00e8me ligne 111\nPilier 110\n2\u00e8me ligne 74\nCentre 71\nAilier 64\nTalonneur 50\nM\u00eal\u00e9e 42\nOuverture 38\nArri\u00e8re 35\nName: Poste, dtype: int64\n
Il est possible aussi de trier la dataframe en lui indiquant la colonne de tri :
Trier les donn\u00e9es : sort_values
>>> classement_par_taille = df.sort_values(by='Taille', ascending = True)\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#4-filtres-et-recherches","title":"4. Filtres et recherches","text":"Le principe du filtrage va \u00eatre de cr\u00e9er une nouvelle dataframe ne contenant que des lignes correspondant \u00e0 un certain crit\u00e8re.
Filtrage des lignes : df[bool\u00e9en]
Comment cr\u00e9er une dataframe ne contenant que les joueurs de l'UBB ? L'id\u00e9e syntaxique est d'\u00e9crire \u00e0 l'int\u00e9rieur de df[]
le test qui permettra le filtrage.
>>> UBB = df[df['Equipe'] == 'Bordeaux']\n
Le bool\u00e9en df['Equipe'] == 'Bordeaux'
doit se comprendre ainsi : on ne veut garder que les joueurs dont le champ Equipe
est \u00e9gal \u00e0 'Bordeaux'
. >>> UBB\n Equipe Nom Poste Date de naissance Taille Poids\n80 Bordeaux Jefferson POIROT Pilier 01/11/1992 181 117\n81 Bordeaux Lasha TABIDZE Pilier 04/07/1997 185 117\n82 Bordeaux Laurent DELBOULB\u00c8S Pilier 17/11/1986 181 106\n83 Bordeaux Lekso KAULASHVILI Pilier 27/08/1992 187 120\n84 Bordeaux Peni RAVAI Pilier 16/06/1990 185 119\n...\n
Exercice 1
Cr\u00e9er une dataframe grands
qui contient tous les joueurs mesurant plus de 2 m\u00e8tres (inclus).
Correction >>> grands = df[df['Taille'] >= 200]\n
Pour effectuer des op\u00e9rations sur les bool\u00e9ens, on utilisera le symbole &
pour le ET et |
pour le OU.
Exercice 2
Cr\u00e9er une dataframe grands_et_gros
qui contient tous les joueurs mesurant plus de 2 m\u00e8tres (inclus) et pesant plus de 120 kg (inclus).
Correction >>> grands_gros = df[(df['Taille'] >= 200) & (df['Poids'] >= 120)]\n
Autre solution, en utilisant la datadframe grands
de l'exercice 1 :
>>> grands_gros = grands[grands['Poids'] >= 120]\n
Exercice 3
Trouver en une seule ligne le joueur le plus l\u00e9ger du Top14.
Correction >>> df[df['Poids'] == min(df['Poids'])]\n Equipe Nom Poste Date de naissance Taille Poids\n491 Racing92 Teddy IRIBAREN M\u00eal\u00e9e 25/09/1990 170 70\n
ou bien
>>> df.sort_values(by='Poids', ascending=True).head(1)\n
Exercice 4
Tracer le nuage de points poids-taille comme pr\u00e9c\u00e9demment, mais en marquant d'un point bleu les 2\u00e8mes ligne et d'un point rouge les piliers.
Correction import pandas as pd\nimport matplotlib.pyplot as plt\n\ndf = pd.read_csv('top14.csv', encoding = 'utf-8') \n\nX = df['Poids']\nY = df['Taille']\nplt.plot(X, Y, 'ro')\n\n\nX = df[df['Poste'] == '2\u00e8me ligne']['Poids']\nY = df[df['Poste'] == '2\u00e8me ligne']['Taille']\nplt.plot(X, Y, 'bo')\n\n\nX = df[df['Poste'] == 'Pilier']['Poids']\nY = df[df['Poste'] == 'Pilier']['Taille']\nplt.plot(X, Y, 'go')\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#5-modification-de-la-structure-rajout-dune-colonne","title":"5. Modification de la structure : rajout d'une colonne","text":"Afin de pouvoir trier les joueurs suivant de nouveaux crit\u00e8res, nous allons rajouter un champ pour chaque joueur. Prenons un exemple stupide : fabriquons un nouveau champ 'Poids apr\u00e8s les vacances'
qui contiendra le poids des joueurs augment\u00e9 de 8 kg. Ceci se fera simplement par :
Rajout d'une colonne
>>> df['Poids apr\u00e8s les vacances'] = df['Poids'] + 8\n
On voit apparaitre dans la dataframe df
une nouvelle colonne
>>> df.head()\n Equipe Nom Poste ... Taille Poids Poids apr\u00e8s les vacances\n0 Agen Anton PEIKRISHVILI Pilier ... 183 122 130\n1 Agen Dave RYAN Pilier ... 183 116 124\n2 Agen Giorgi TETRASHVILI Pilier ... 177 112 120\n3 Agen Kamaliele TUFELE Pilier ... 182 123 131\n4 Agen Malino VANA\u00cf Pilier ... 183 119 127\n\n[5 rows x 7 columns]\n
Pour supprimer cette colonne sans int\u00e9r\u00eat, il suffit de faire :
del df['Poids apr\u00e8s les vacances'] \n
Exercice 5
Q1. Cr\u00e9er une colonne contenant l'IMC de chaque joueur.
Correction >>> df['IMC'] = df['Poids'] / (df['Taille']/100)**2\n
Q2. Cr\u00e9er une nouvelle dataframe contenant tous les joueurs du Top14 class\u00e9s par ordre d'IMC croissant.
Correction >>> df_imc = df.sort_values(by='IMC', ascending = True)\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/cours/#6-retour-sur-le-knn","title":"6.\u00a0Retour sur le KNN","text":"Comme dans ce cours, nous allons construire une fonction conseil_poste
recevant en param\u00e8tres :
df
: la dataframe contenant nos donn\u00e9es poids
: le poids du joueur X taille
: la taille du joueur X k
: le nombre de joueurs les plus proches sur lequel on se base pour faire la pr\u00e9diction
qui renvoie le poste le plus compatible avec la morphologie de X.
Il est maintenant possible de coder cette fonction beaucoup plus simplement (mais alors VRAIMENT beaucoup) qu'avec le module csv
.
Il va nous suffir de :
- cr\u00e9er une nouvelle colonne contenant la distance de chaque joueur avec le joueur X.
- classer la dataframe suivant cette nouvelle colonne.
- ne garder que les
k
premiers \u00e9l\u00e9ments. - renvoyer le poste le plus fr\u00e9quent parmi ces
k
premiers \u00e9lements.
Algorithme KNN
import pandas as pd\n\ndf = pd.read_csv('top14.csv', encoding = 'utf-8') \n\ndef conseil_poste(df, poids, taille, k):\n ...\n ...\n ...\n ...\n
Correction import pandas as pd\n\ndf = pd.read_csv('top14.csv', encoding = 'utf-8') \n\ndef conseil_poste(df, poids, taille, k):\n df['distance'] = (df['Poids']-poids)**2 + (df['Taille']-taille)**2\n df = df.sort_values(by = 'distance', ascending=True)\n df = df.head(k)\n return df['Poste'].describe().top \n
>>> conseil_poste(df, 70, 160, 10)\n'M\u00eal\u00e9e'\n>>> conseil_poste(df, 130, 160, 10)\n'Pilier'\n
"},{"location":"T5_Traitement_de_donnees/5.3_Pandas/exercices/","title":"Analyse des passagers du Titanic","text":"Nous allons travailler avec le fichier titanic.csv
.
"},{"location":"T6_IHM_Web/pagesperso/","title":"Pages personnelles","text":""},{"location":"T6_IHM_Web/pagesperso/#o-installation-du-serveur-xampp","title":"O. Installation du serveur Xampp","text":"Dans le dossier T\u00e9l\u00e9chargements :
sudo chmod +x xampp-linux....run
puis
sudo ./xampp-linux....run
"},{"location":"T6_IHM_Web/pagesperso/#1-demarrage","title":"1. D\u00e9marrage","text":""},{"location":"T6_IHM_Web/pagesperso/#11-serveur-demarre-ou-pas","title":"1.1 Serveur d\u00e9marr\u00e9 ou pas ?","text":"Dans la barre d'adresse de son navigateur, taper localhost
ou bien 127.0.0.1
.
Si aucune page n'appara\u00eet, c'est que le serveur n'est pas d\u00e9marr\u00e9.
"},{"location":"T6_IHM_Web/pagesperso/#12-demarrer-le-serveur","title":"1.2 D\u00e9marrer le serveur","text":"Dans un terminal, taper
sudo /opt/lampp/lampp start
"},{"location":"T6_IHM_Web/pagesperso/#13-connaitre-son-adresse-ip","title":"1.3 Conna\u00eetre son adresse IP","text":"Dans un terminal,
ip addr
regarder 4 lignes avant la fin, chercher une adresse IP commen\u00e7ant par 192.168.1.XXX
.
"},{"location":"T6_IHM_Web/pagesperso/#2-mettre-en-production-son-site","title":"2. Mettre en production son site","text":"Dans un terminal ouvert depuis le dossier contenant ses pages :
sudo cp mapage.html /opt/lampp/htdocs/
Si on veut tout copier :
sudo cp * /opt/lampp/htdocs/
"},{"location":"T6_IHM_Web/pagesperso/#3-liens-vers-la-page-de-chaque-eleve","title":"3. Liens vers la page de chaque \u00e9l\u00e8ve","text":" - page de M. Lassus
- page de Malone
- page de Tim\u00e9o
- page de Moustapha
- page de Jean
- page de Sarah
- page d'Antoine
- page de Nathana\u00ebl
- page de Lucas
- page de Nathan
- page de P\u00e9rine
- page de Rita
- page de Tesnime
- page de Max
- page de No\u00e9
- page de Gead
- page de Mikha\u00eflo
"},{"location":"T6_IHM_Web/sommaire/","title":"Th\u00e8me 6 : IHM sur le web","text":" - Interactions sur une page web
- Protocole HTTP : \u00e9tude du chargement d'une page web
- Requ\u00eates GET, POST et formulaires
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/","title":"6.1 Pages web et interactions","text":""},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#1-le-cas-le-plus-simple-la-meme-page-pour-tout-le-monde","title":"1. Le cas le plus simple : la m\u00eame page pour tout le monde","text":"Nous allons tout d'abord consid\u00e9rer le cas o\u00f9 le serveur renvoie une page unique, identique pour tous les utilisateurs. De plus, l'utilisateur ne pourra pas agir sur sa page : il n'y a aucune interactivit\u00e9.
Exemple de page statique c\u00f4t\u00e9 serveur et c\u00f4t\u00e9 utilisateur :
- cette merveille de page web.
- plus compl\u00e8te, mais tout aussi statique : cette page Wikipedia consacr\u00e9e \u00e0 John Conway.
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#11-html-pur","title":"1.1 html
pur","text":"Lorsque le client demande au serveur le contenu d'une page web, celui-ci lui renvoie, dans le cas le plus simple, une simple page html
. html
est un langage dit \u00ab \u00e0 balises \u00bb. Ce n'est pas \u00e0 proprement parler un langage de programmation, mais plut\u00f4t un langage de description de contenu. Il a \u00e9t\u00e9 invent\u00e9 en 1992 par Tim Berners-Lee. La version actuellement utilis\u00e9e est le html5
.
Exemple de page web minimale
<!DOCTYPE html>\n<html lang='fr'>\n <head>\n <meta charset=\"utf-8\">\n <title>Un titre tr\u00e8s original</title>\n </head>\n\n <body>\n <p>Ceci est le texte introductif de ma page.</p>\n <p>\n <h1> Ceci est un titre de niveau 1 </h1>\n Mais sans rien d'int\u00e9ressant.\n <h2> Ceci est un titre de niveau 2 </h2>\n <ul>\n <li> le d\u00e9but d'une liste indent\u00e9e </li>\n <li> la suite ... </li>\n </ul> \n Pour apprendre le fonctionnement des balises, voir <a href=\"https://developer.mozilla.org/fr/docs/Apprendre/HTML/Introduction_%C3%A0_HTML/Getting_started\"> ici</a> par exemple !\n </p>\n </body>\n</html>\n
Vous pouvez contempler ici le rendu de cette magnifique page.
Exercice 1
\u00c9nonc\u00e9 - Cr\u00e9ez un dossier contenant un fichier
mapage.html
. - Cr\u00e9ez une page contenant une image et un lien vers le site du lyc\u00e9e.
- Vous pouvez utiliser le logiciel Geany, install\u00e9 sur notre Debian.
- Vous pouvez aussi utiliser un \u00e9diteur en ligne avec rendu instantan\u00e9, du type https://www.w3schools.com/tryit/
lien t\u00e9l\u00e9chargement XAMPP
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#12-html-css","title":"1.2 html
+ css
","text":"L'acronyme css
signifie Cascading Style Sheets. L'id\u00e9e est de regrouper dans un seul fichier toutes les informations relatives \u00e0 la mise en forme des \u00e9l\u00e9ments de la page html. De mani\u00e8re tr\u00e8s simplifi\u00e9e, on peut dire que le fichier html
s'occupe du fond tandis que le fichier css
s'occupe de la forme.
Le fichier css
(souvent nomm\u00e9 style.css
et appel\u00e9 feuille de style) doit \u00eatre r\u00e9f\u00e9renc\u00e9 au d\u00e9but du fichier html
, au sein de la balise <head>
.
Exemple de couple html
/ css
minimal
-
fichier index.html
:
<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <title>page test</title>\n <link href=\"style.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body>\n <p>\n <h1> Ceci est un titre de niveau 1 </h1>\n Mais sans rien d'int\u00e9ressant.\n <h2> Ceci est un titre de niveau 2 </h2>\n </p>\n </body>\n</html>\n
-
fichier style.css
:
html {\n font-size: 15px;\n font-family: sans-serif;\n background-color: lightgray; \n }\n\nh1 {\n color: red;\n}\n
Vous pouvez contempler ici le nouveau rendu de cette encore plus magnifique page.
En savoir plus
- le cours d'OpenClassrooms : https://openclassrooms.com/fr/courses/1603881-apprenez-a-creer-votre-site-web-avec-html5-et-css3
Exercice 2
Reprenez votre page de l'exercice 1 et rajoutez une feuille de style.
Exercice 3
- Allez sur le site http://sudouest.fr, et affichez l'inspecteur d'\u00e9lement de votre navigateur (g\u00e9n\u00e9ralement accessible en appuyant sur
F12
) - Modifiez le plus possible les attributs de style de la page.
Exercice 4
- R\u00e9soudre ce challenge
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#2-quand-le-client-peut-agir-sur-sa-page-exemple-avec-javascript","title":"2. Quand le client peut agir sur sa page : exemple avec JavaScript","text":"Jusqu'\u00e0 pr\u00e9sent, la page web envoy\u00e9e par le serveur est :
- identique quel que soit le client.
- statique apr\u00e8s r\u00e9ception sur l'ordinateur du client.
Le JavaScript va venir r\u00e9gler le probl\u00e8me n\u00b02 : il est possible de fabriquer une page sur laquelle le client va pouvoir agir localement, sans avoir \u00e0 redemander une nouvelle page au serveur.
Invent\u00e9 en 1995 par Brendan Eich pour le navigateur Netscape, le langage JavaScript s'est impos\u00e9 comme la norme aupr\u00e8s de tous les navigateurs pour apporter de l'interactivit\u00e9 aux pages web.
Exemple de couple html
/ javascript
minimal
Notre fichier index.html
fait r\u00e9f\u00e9rence, au sein d'une balise <script>
, \u00e0 un fichier externe script.js
qui contiendra notre code JavaScript.
-
fichier index.html
:
<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <title>un peu d'action</title>\n <link href=\"style.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body>\n <script src=\"script.js\"></script>\n <p>\n <h2>Une page web extr\u00eamement dynamique</h2>\n </p>\n <div>\n\n <label>Changez la couleur d'arri\u00e8re-plan:</label>\n\n <button type=\"button\" onclick=\"choix('yellow');\">jaune</button>\n\n <button type=\"button\" onclick=\"choix('green');\">vert</button>\n\n <button type=\"button\" onclick=\"choix('purple');\">violet</button> \n\n <input onchange=\"choix(this.value)\" type=\"color\" />\n\n </div>\n <div>\n <p>\n En JavaScript, le nom de la couleur choisie est :\n </p>\n <p id=\"resultat\"></p>\n </div>\n </body>\n</html>\n
-
fichier script.js
:
function choix(color){\n document.body.style.background = color;\n document.getElementById(\"resultat\").innerHTML=color;\n}\n
Le r\u00e9sultat de cette page peut \u00eatre consult\u00e9 ici. (oui, j'ai confondu le jaune et le rose)
Commentaires
- Au sein du bouton d\u00e9clar\u00e9 par la balise
button
, l'attribut onclick
re\u00e7oit le nom d'une fonction d\u00e9clar\u00e9e \u00e0 l'int\u00e9rieur du fichier script.js
, ici la fonction choix()
. - Cette fonction nous permet de modifier \u00e0 la fois l'aspect esth\u00e9tique de la page (changement de la couleur de background) mais aussi le contenu de cette page, en faisant afficher le nom de la couleur.
La puissance du JavaScript permet de r\u00e9aliser aujourd'hui des interfaces utilisateurs tr\u00e8s complexes au sein d'un navigateur, \u00e9quivalentes \u00e0 celles produites par des logiciels externes (pensez \u00e0 la version web de Discord ou aux Google Docs, par ex.). Bien s\u00fbr, dans ces cas complexes, le serveur est aussi sollicit\u00e9 pour modifier la page, comme nous le verrons en partie 3.
En savoir plus
- le guide JavaScript de la fondation Mozilla : https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide
- le cours d'OpenClassrooms : https://openclassrooms.com/fr/courses/7696886-apprenez-a-programmer-avec-javascript
Exercice 5
- Reprenez votre page cr\u00e9\u00e9e aux exercices pr\u00e9c\u00e9dents et rajoutez du JavaScript pour la rendre dynamique. Vous \u00eates libres !
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#3-quand-la-page-est-fabriquee-a-la-demande-pour-le-client-exemple-avec-php","title":"3. Quand la page est fabriqu\u00e9e \u00e0 la demande pour le client : exemple avec PHP","text":"Rappelons que toutes les pages que nous avons cr\u00e9\u00e9es jusqu'\u00e0 pr\u00e9sent sont uniform\u00e9ment envoy\u00e9es par le serveur au client. Aucune \u00abpr\u00e9paration\u00bb de la page en amont n'a lieu sur le serveur, aucun dialogue n'a lieu avec le serveur une fois que la page a \u00e9t\u00e9 livr\u00e9e. \u00c9videmment, si le web \u00e9tait comme ceci, il ne serait qu'une gigantesque biblioth\u00e8que en consultation seule (ce fut le cas pendant longtemps, et ce qui n'\u00e9tait d\u00e9j\u00e0 pas si mal).
Les langages serveurs, parmi lesquels PHP (pr\u00e9sent sur environ 80% des serveurs), Python (via le framework Django), Java, Ruby, C#, permettent de rajouter de l'interactivit\u00e9 c\u00f4t\u00e9 serveur.
Il convient de rappeler la diff\u00e9rence fondamentale entre une page statique (c\u00f4t\u00e9 serveur) et une page dynamique (c\u00f4t\u00e9 serveur) :
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#31-page-statique-cote-serveur","title":"3.1 Page statique (c\u00f4t\u00e9 serveur) :","text":"Lors d'une requ\u00eate d'un client vers un serveur, si le client demande la page index.html
, une copie exacte du fichier index.html
est transmise au client sur sa machine.
Exemple : la page http://glassus1.free.fr/interesting.html que vous avez d\u00e9j\u00e0 consult\u00e9e se trouve telle quelle sur le serveur mis \u00e0 disposition par Free pour l'h\u00e9bergement des pages personnelles :
Depuis votre navigateur, l'affichage du code-source (par Ctrl-U) vous donnera le fichier html tel qu'il \u00e9tait stock\u00e9 sur le serveur.
"},{"location":"T6_IHM_Web/6.1_Interactions_page_web/cours/#32-page-dynamique-cote-serveur","title":"3.2 Page dynamique (c\u00f4t\u00e9 serveur) :","text":"Lors d'une requ\u00eate d'un client vers un serveur, si le client demande la page test.php
, un code html est g\u00e9n\u00e9r\u00e9 \u00e0 partir du fichier test.php
puis est transmise au client sur sa machine. Le fichier transmis ne contient plus de balises php
, il ne comporte que des balises html
classiques.
Exemple : la consultation de la page http://glassus1.free.fr/test.php va renvoyer la page suivante :
dont le code-source est :
Notez bien que ce code-source ne contient que du html
.
Allons regarder cette page du c\u00f4t\u00e9 du serveur :
Le contenu de cette page est :
<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <title>Quel jour sommes-nous</title>\n </head>\n <body>\n <p>\n <?php\n $date = date(\"d-m-Y\");\n Print(\"Nous sommes le $date\");\n ?>\n </p>\n</body>\n</html>\n
On y rep\u00e8re la balise <?php>
:
<?php\n $date = date(\"d-m-Y\");\n Print(\"Nous sommes le $date\");\n ?>\n
Ce code php
a donc g\u00e9n\u00e9r\u00e9, lors de l'appel au serveur, le code html
: Nous sommes le 13-04-2020\n
Vous pouvez tester du code PHP et la page g\u00e9n\u00e9r\u00e9e par exemple sur ce site.
Voil\u00e0 comment un serveur peut adapter la page qu'il renvoie, suivant l'utilisateur qui la demande. Nous verrons prochainement comment par des requ\u00eates le client peut envoyer des param\u00e8tres au serveur, et comment celui-ci modifie sa r\u00e9ponse en cons\u00e9quence.
En savoir plus : https://www.php.net/manual/fr/tutorial.firstpage.php
"},{"location":"T6_IHM_Web/6.2_Protocole_HTTP/cours/","title":"6.2 Protocole HTTP : \u00e9tude du chargement d'une page web","text":""},{"location":"T6_IHM_Web/6.2_Protocole_HTTP/cours/#le-protocole-http-des-requetes-et-des-reponses","title":"Le protocole HTTP : des requ\u00eates et des r\u00e9ponses","text":"HTTP (HyperText Transfer Protocol) est le protocole qui r\u00e9git la communication entre :
- le client (la machine de l'utilisateur qui souhaite obtenir une page web). On dit que le client effectue une requ\u00eate.
- le serveur (la machine sur laquelle sont stock\u00e9s les fichiers n\u00e9cessaires \u00e0 l'affichage de cette page web). Le serveur va renvoyer une r\u00e9ponse.
"},{"location":"T6_IHM_Web/6.2_Protocole_HTTP/cours/#deroule-dune-requete","title":"D\u00e9roul\u00e9 d'une requ\u00eate","text":"Prenons pour exemple la requ\u00eate d'un navigateur vers la page http://glassus1.free.fr/interesting.html
- le navigateur analyse l'url : la demande concerne la page
interesting.html
, stock\u00e9e sur le serveur glassus1.free.fr
. - une demande est pr\u00e9alablement effectu\u00e9e aupr\u00e8s pour obtenir l'adresse IP du serveur
glassus1.free.fr
(qui est en fait un sous-domaine du serveur des pages personnelles de l'op\u00e9rateur Free). Ici, l'adresse IP sera 212.27.63.111
(on la retrouvera dans la capture de la fen\u00eatre d'Outils de dev\u00e9loppement). - la requ\u00eate est effectu\u00e9e sur le port 80 de l'adresse
212.27.63.111
. - la r\u00e9ponse est envoy\u00e9e au navigateur, qui en extrait la charge utile et proc\u00e8de \u00e0 l'affichage de la page.
"},{"location":"T6_IHM_Web/6.2_Protocole_HTTP/cours/#analyse-a-laide-dun-navigateur","title":"Analyse \u00e0 l'aide d'un navigateur","text":"Observons \u00e0 partir de l'Inspecteur d'\u00e9l\u00e9ment d'un navigateur (ici Firefox) les informations qui transitent lors de la requ\u00eate et de la r\u00e9ponse.
- Point 1 : La requ\u00eate de type GET vers l'url
http://glassus1.free.fr/interesting.html
a g\u00e9n\u00e9r\u00e9 un code de r\u00e9ponse 200 OK, ce qui signifie que la requ\u00eate a \u00e9t\u00e9 trait\u00e9e et que la r\u00e9ponse contenant la page a \u00e9t\u00e9 envoy\u00e9e. Vous pouvez trouver \u00e0 l'adresse https://developer.mozilla.org/fr/docs/Web/HTTP/Status la totalit\u00e9 des codes de r\u00e9ponse possibles. Citons par exemple : - 304 Not Modified : la page n'a pas eu besoin d'\u00eatre renvoy\u00e9e, elle indique au navigateur d'aller la rechercher dans son cache. On peut obtenir ce code de r\u00e9ponse en actualisant la page actuelle
http://glassus1.free.fr/interesting.fr
(qui est une page ultra-basique, et n'\u00e9volue pas). Pour r\u00e9-obtenir un code 200, il faut faire un hard-refresh en appuyant sur Maj pendant l'actualisation. - 403 Forbidden : le client n'a pas le droit d'acc\u00e8s \u00e0 la page.
- 404 Not Found : la page demand\u00e9e est introuvable
- 500 Internal Server Error : le serveur a rencontr\u00e9 une erreur qu'il ne sait pas traiter.
- Point 2 : en observant la taille totale des donn\u00e9es transf\u00e9r\u00e9es (388 octets), on peut comprendre que la r\u00e9ponse faite par le serveur est constitu\u00e9e :
- d'un En-t\u00eate (264 octets) qui contient :
HTTP/1.1 200 OK\nDate: Wed, 22 Apr 2020 08:02:01 GMT\nServer: Apache/ProXad [Jan 23 2019 19:58:42]\nLast-Modified: Sun, 12 Apr 2020 16:39:55 GMT\nETag: \"15d7c75-7c-5e93445b\"\nConnection: close\nAccept-Ranges: bytes\nContent-Length: 124\nContent-Type: text/html\n
- du corps de la R\u00e9ponse (dont on sait d'apr\u00e8s l'en-t\u00eate qu'il p\u00e8se 124 octets). Ce corps de la r\u00e9ponse est la charge utile de la r\u00e9ponse. Elle contient ici le code html de la page :
<!DOCTYPE html>\n<html>\n<head>\n<title>Waouh</title>\n</head>\n<body>\nCeci est vraiment une jolie page web.\n</body>\n</html>\n
Remarque : on peut observer que le navigateur a aussi effectu\u00e9 (de sa propre initiative) une requ\u00eate vers un fichier favicon.ico
qui est l'icone de la page web dans les onglets du navigateur ou la barre de favoris. Ce fichier \u00e9tait bien pr\u00e9sent sur le serveur (ce n'est pas toujours le cas), il a donc \u00e9t\u00e9 envoy\u00e9 dans la r\u00e9ponse du serveur.
De mani\u00e8re g\u00e9n\u00e9rale, une requ\u00eate vers un site web moins \u00e9l\u00e9mentaire va occasionner une multitude de r\u00e9ponses.
Par exemple, l'appel au site www.lyceemauriac.fr
g\u00e9n\u00e8re 129 requ\u00eates/r\u00e9ponses diff\u00e9rentes, compos\u00e9es de fichiers html, css, js, de fichiers de fontes woff2, d'images jpg, png...
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/","title":"6.3 Requ\u00eates GET, POST et formulaires","text":""},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#1-cote-client-comment-envoyer-des-parametres-a-un-serveur","title":"1. C\u00f4t\u00e9 client : comment envoyer des param\u00e8tres \u00e0 un serveur ?","text":""},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#11-la-methode-get","title":"1.1. La m\u00e9thode GET","text":"Consid\u00e9rons le formulaire suivant, inclus dans une page html ouverte dans le navigateur du client :
Le mot de passe est :\n<form action=\"cible2.php\" method=\"get\">\n<p>\n <input type=\"password\" name=\"pass\" /> \n <input type=\"submit\" value=\"Valider\" />\n</p>\n</form>\n
Aper\u00e7u :
Explications :
- le fichier
cible2.php
est le fichier sur le serveur qui recevra les param\u00e8tres contenus dans le formulaire. - le param\u00e8tre sera nomm\u00e9
pass
et sera de type password
, ce qui signifie qu'on n'affichera pas les caract\u00e8res tap\u00e9s par l'utilisateur. On aurait pu aussi avoir un type : text
: le texte s'affiche en clair (pour les login par ex) radio
: pour une s\u00e9lection (d'un seul \u00e9l\u00e9ment) checkbox
: pour une s\u00e9lection (\u00e9ventuellement multiple)
- un bouton comportant le label \u00abValider\u00bb d\u00e9clenchera l'envoi (gr\u00e2ce au type particulier
submit
) des param\u00e8tres (ici un seul, la variable pass
) au serveur.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#test","title":"Test :","text":" - Rendez-vous sur la page http://glassus1.free.fr/ex_get.html et testez un mot de passe.
- Observez attentivement l'url de la page sur laquelle vous \u00eates arriv\u00e9s. Que remarquez-vous ?
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#la-methode-get-et-la-confidentialite","title":"La m\u00e9thode GET et la confidentialit\u00e9 :","text":"Les param\u00e8tres pass\u00e9s au serveur par la m\u00e9thode GET sont transmis dans l'url de la requ\u00eate. Ils sont donc lisibles en clair par n'importe qui.
\u00c9videmment, c'est une m\u00e9thode catastrophique pour la transmission des mots de passe. Par contre, c'est une m\u00e9thode efficace pour acc\u00e9der directement \u00e0 une page particuli\u00e8re : ainsi l'url https://www.google.fr/search?q=bordeaux nous am\u00e8nera directement au r\u00e9sultat de la recherche Google sur le mot-cl\u00e9 \u00abbordeaux\u00bb.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#12-la-methode-post","title":"1.2. La m\u00e9thode POST","text":"Dans notre code de formulaire du 1.1, modifions l'attribut method
, auparavant \u00e9gal \u00e0 \"get\"
. Passons-le \u00e9gal \u00e0 \"post\"
:
Le mot de passe est :\n<form action=\"cible2.php\" method=\"post\">\n<p>\n <input type=\"password\" name=\"pass\" /> \n <input type=\"submit\" value=\"Valider\" />\n</p>\n</form>\n
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#test_1","title":"Test :","text":" - Rendez-vous sur la page http://glassus1.free.fr/ex_post.html et testez un mot de passe.
- Observez attentivement l'url de la page sur laquelle vous \u00eates arriv\u00e9s. Que remarquez-vous ?
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#la-methode-post-et-la-confidentialite","title":"La m\u00e9thode POST et la confidentialit\u00e9 :","text":"Les param\u00e8tres pass\u00e9s au serveur par la m\u00e9thode POST ne sont pas visibles dans l'url de la requ\u00eate. Ils sont contenus dans le corps de la requ\u00eate, mais non affich\u00e9s sur le navigateur.
Donc, la transmission du mot de passe est bien s\u00e9curis\u00e9e par la m\u00e9thode POST ?
Pas du tout ! Si le protocole de transmission est du http
et non pas du https
, n'importe qui interceptant le trafic peut lire le contenu de la requ\u00eate et y trouver le mot de passe en clair.
Exemple avec Wireshark :
Le contenu de la variable \"pass\"
est donc visible dans le contenu de la requ\u00eate.
Le passage en https
chiffre le contenu de la requ\u00eate et emp\u00eache donc la simple lecture du mot de passe.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#resume-quand-utiliser-get-ou-post","title":"R\u00e9sum\u00e9 : quand utiliser GET ou POST ?","text":" - GET : la m\u00e9thode GET doit \u00eatre utilis\u00e9e quand les param\u00e8tres \u00e0 envoyer :
- n'ont pas de caract\u00e8re confidentiel.
- n'ont pas vocation \u00e0 cr\u00e9er des modifications sur le serveur (ceci est plus une bonne pratique qu'une interdiction technique)
- ne sont pas trop longs. En effet, vu qu'ils seront contenus dans l'url, il peut exister des limites de longueur sp\u00e9cifiques au navigateur. Une taille inf\u00e9rieure \u00e0 2000 caract\u00e8re est conseill\u00e9e. Si vous vous demandez \u00e0 quoi peuvent servir des url si longues, songez \u00e0 ce type d'url, (ici PythonTutor) o\u00f9 le code du programme \u00e0 analyser est contenu dans l'url : http://pythontutor.com/visualize.html#code=L%20%3D%20%5B2,%203,%206,%207,%2011,%2014,%2018,%2019,%2024%5D%0A%0Adef%20trouve_dicho%28L,%20n%29%20%3A%0A%20%20%20%20indice_debut%20%3D%200%0A%20%20%20%20indice_fin%20%3D%20len%28L%29%20-%201%0A%20%20%20%20while%20indice_debut%20%3C%3D%20indice_fin%20%3A%0A%20%20%20%20%20%20%20%20indice_centre%20%3D%20%28indice_debut%20%2B%20indice_fin%29%20//%202%0A%20%20%20%20%20%20%20%20valeur_centrale%20%3D%20L%5Bindice_centre%5D%0A%20%20%20%20%20%20%20%20if%20valeur_centrale%20%3D%3D%20n%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20indice_centre%0A%20%20%20%20%20%20%20%20if%20valeur_centrale%20%3C%20n%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20indice_debut%20%3D%20indice_centre%20%2B%201%0A%20%20%20%20%20%20%20%20else%20%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20indice_fin%20%3D%20indice_centre%20-%201%0A%20%20%20%20return%20None%0A%0Aprint%28trouve_dicho%28L,14%29%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false
-
POST : la m\u00e9thode POST doit \u00eatre utilis\u00e9e quand les param\u00e8tres \u00e0 envoyer :
- ont un caract\u00e8re confidentiel (attention, \u00e0 coupler imp\u00e9rativement avec un protocole de chiffrement).
- peuvent avoir une longueur tr\u00e8s importante (le param\u00e8tre \u00e9tant dans le corps de la requ\u00eate et non plus dans l'url, sa longueur peut \u00eatre arbitraire).
- ont vocation \u00e0 provoquer des changements sur le serveur. Ainsi, un ordre d'achat sur un site de commerce sera n\u00e9cessairement pass\u00e9 par une m\u00e9thode POST. Les navigateurs pr\u00e9viennent alors le risque de \u00abdouble commande\u00bb lors d'une actualisation malencontreuse de la page par l'utilisateur par la fen\u00eatre :
Cette fen\u00eatre est caract\u00e9ristique de l'utilisation d'une m\u00e9thode POST.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#2-cote-serveur-comment-recuperer-les-parametres-envoyes","title":"2. C\u00f4t\u00e9 serveur : comment r\u00e9cup\u00e9rer les param\u00e8tres envoy\u00e9s ?","text":"Du c\u00f4t\u00e9 du serveur, le langage utilis\u00e9 (PHP, Java...) doit r\u00e9cup\u00e9rer les param\u00e8tres envoy\u00e9s pour modifier les \u00e9lements d'une nouvelle page, mettre \u00e0 jour une base de donn\u00e9es, etc. Comment sont r\u00e9cup\u00e9r\u00e9es ces valeurs ?
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#exemple-en-php","title":"Exemple en PHP","text":"L'acronyme PHP signifie **P**HP : **H**ypertext **P**rocessor (c'est un acronyme r\u00e9cursif).
Notre exemple va contenir deux fichiers :
- une page
page1.html
, qui contiendra un formulaire et qui renverra, par la m\u00e9thode GET, un param\u00e8tre \u00e0 la page page2.php
. - une page
page2.php
, qui g\u00e9n\u00e8rera un code html
personnalis\u00e9 en fonction du param\u00e8tre re\u00e7u.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#page1html","title":"page1.html
","text":"<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <title>exemple</title>\n </head>\n <body>\n Votre OS actuel est un : \n<form action=page2.php method=\"get\">\n<p>\n <input type=\"radio\" name=\"OS\" value=\"Windows\"> Windows </input>\n <input type=\"radio\" name=\"OS\" value=\"MacOS\"> MacOS </input>\n <input type=\"radio\" name=\"OS\" value=\"GNU/Linux\"> GNU/Linux </input>\n</p>\n<p> \n <input type=\"submit\" value=\"Valider\" />\n</p>\n</form>\n </body>\n</html>\n
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#page2php","title":"page2.php
","text":" <!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <title>Le meilleur OS</title>\n </head>\n <body>\n <p>\n <?php\n if (isset($_GET['OS']))\n {\n Print(\"Vous avez raison, \");\n echo $_GET['OS'];\n Print(\" est le meilleur des OS.\");\n }\n ?>\n </p>\n\n</body>\n</html>\n
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#detail-du-fonctionnement","title":"D\u00e9tail du fonctionnement :","text":" - \u00c0 l'arriv\u00e9e sur la page
page1.html
, un formulaire de type boutons radio lui propose : - Lorsque l'utilisateur clique sur \u00abValider\u00bb, la variable nomm\u00e9e
OS
va recevoir la valeur choisie et va \u00eatre transmise par une requ\u00eate GET \u00e0 l'url donn\u00e9e par la variable action
d\u00e9finie en d\u00e9but de formulaire. Ici, le navigateur va donc demander \u00e0 acc\u00e9der \u00e0 la page page2.php?OS=MacOS
(par exemple) - Le serveur PHP qui h\u00e9berge la page
page2.php
va recevoir la demande d'acc\u00e8s \u00e0 la page ainsi que la valeur de la variable OS
. Dans le code PHP, on reconnait : - le bool\u00e9en
isset($_GET['OS'])
qui v\u00e9rifie si le param\u00e8tre OS
a bien re\u00e7u une valeur. - l'expression
$_GET['OS']
qui r\u00e9cup\u00e8re cette valeur. Si la valeur avait \u00e9t\u00e9 transmise par m\u00e9thode POST (pour un mot de passe, par exemple), la variable aurait \u00e9t\u00e9 r\u00e9cup\u00e9r\u00e9e par $_POST['OS']
. Elle n'aurait par contre pas \u00e9t\u00e9 affich\u00e9e dans l'url de la page.
- La page
page2.php?OS=MacOS
s'affiche sur le navigateur de l'utilisateur :
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#remarque","title":"Remarque","text":"L'exemple ci-dessus est un mauvais exemple : rien ne justifie l'emploi d'un serveur distant. L'affichage de ce message aurait tr\u00e8s bien pu se faire en local sur le navigateur du client, en Javascript par exemple.
L'envoi de param\u00e8tre \u00e0 un serveur distant est n\u00e9cessaire pour aller interroger une base de donn\u00e9es, par exemple (lorsque vous remplissez un formulaire sur le site de la SNCF, les bases de donn\u00e9es des horaires de trains, des places disponibles et de leurs tarifs ne sont pas h\u00e9berg\u00e9es sur votre ordinateur en local...).
La v\u00e9rification d'un mot de passe doit aussi se faire sur un serveur distant.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#exercice-attaque-par-force-brute-et-requete-get","title":"Exercice : attaque par force brute et requ\u00eate GET","text":""},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#pre-requis-1-le-module-requests-en-python","title":"Pr\u00e9-requis 1 : le module requests
en python","text":"Le module requests
permet d'aller chercher le contenu d'une page web, suivant la syntaxe ci-dessous. Testez le code ci-dessous :
import requests\np = requests.get(\"http://glassus1.free.fr/interesting.html\", verify = False)\nprint(p.text)\n
La sortie en console est :
<!DOCTYPE html>\n<html>\n\n<head>\n\n<title>Waouh</title>\n</head>\n\n<body>\nCeci est vraiment une jolie page web.\n</body>\n\n</html>\n
Notre programme Python se comporte donc \u00abcomme un navigateur\u00bb : il se rend sur une page, effectue une requ\u00eate et r\u00e9cup\u00e8re la page renvoy\u00e9e.
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#pre-requis-2-lextraction-dun-fichier-texte-sous-forme-de-liste","title":"Pr\u00e9-requis 2 : l'extraction d'un fichier texte sous forme de liste","text":"Le code ci-dessous permet de collecter dans une liste mots
l'ensemble des mots compris dans le fichier monfichiertexte.txt
(si celui-ci comprend un mot par ligne)
mots = open(\"monfichiertexte.txt\").read().splitlines()\n
"},{"location":"T6_IHM_Web/6.3_Get_Post_Formulaires/cours/#exercice","title":"Exercice :","text":"Votre objectif est de trouver le mot de passe demand\u00e9 sur la page http://glassus1.free.fr/exoBF.html
Vous allez vous appuyer sur un leak (fuite) tr\u00e8s c\u00e9l\u00e8bre de mots de passe , qui est le leak du site Rockyou. Dans la base de donn\u00e9es de ce site, 32 millions de mots de passe \u00e9taient stock\u00e9s en clair \u00af\\_(\u30c4)_/\u00af
.
Lorsque le site a \u00e9t\u00e9 pirat\u00e9 (par une injection SQL, voir le cours de Terminale), ces 32 millions de mots de passe se sont retrouv\u00e9s dans la nature. Ils sont aujourd'hui t\u00e9l\u00e9chargeables librement, et constituent un dictionnaire de 14 341 564 mots de passe diff\u00e9rents (car parmi les 32 millions d'utilisateurs, beaucoup utilisaient des mots de passe identiques). Ce fichier est t\u00e9l\u00e9chargeable ici, mais attention il p\u00e8se 134 Mo.
Nous allons utiliser un fichier beaucoup plus l\u00e9ger ne contenant que les 1000 premiers mots de passe : vous le trouverez \u00e0 l'adresse http://glassus1.free.fr/extraitrockyou.txt .
L'un de ces mots de passe est le mot de passe demand\u00e9 \u00e0 la page http://glassus1.free.fr/exoBF.html .
Lequel ?
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/","title":"Initiation \u00e0 Pygame","text":""},{"location":"T6_Mini-projets/05_Initiation_Pygame/#1-preparation-de-la-scene","title":"1. Pr\u00e9paration de la sc\u00e8ne","text":"import pygame\nfrom pygame.locals import *\n\npygame.init() # (4)\n\nfenetre = pygame.display.set_mode((640, 480)) # (1)\nfenetre.fill((10, 186, 181)) # (2)\n\nrunning = True\nwhile running: \n fenetre.fill((10, 186, 181)) # (2)\n pygame.display.flip() #(3) \n\npygame.quit()\n
- On cr\u00e9e une fen\u00eatre de taille
(640, 480)
. - On remplit la fen\u00eatre avec la couleur
(10, 186, 181)
. - Permet de rafra\u00eechir la totalit\u00e9 de la fen\u00eatre. Pour l'instant inutile car rien ne bouge...
- Initialisation du module
pygame
.
Ce code devrait vous donner ceci :
Remarques
- La ligne
from pygame.locals import *
permettra d'utiliser des variables locales d\u00e9j\u00e0 d\u00e9finies par pygame
, comme MOUSEBUTTONDOWN
, par exemple. - Durant tout le code, notre sc\u00e8ne de travail sera l'objet
fenetre
, dans lequel nous viendrons coller de nouveaux \u00e9l\u00e9ments. - Pour l'instant, notre code nous enferme dans une boucle infinie : la fen\u00eatre ne se ferme pas, il faut arr\u00eater Python depuis Thonny. Nous y remedierons bient\u00f4t.
Les \u00e9l\u00e9ments structurants d'un code pygame
pygame.init()
effectue une initialisation globale de tous les modules pygame
import\u00e9s. \u00c0 mettre au d\u00e9but du code. while running:
comme tr\u00e8s souvent dans les jeux, la structure essentielle est une boucle infinie dont on ne sortira que par la bascule d'un bool\u00e9en. Ici on restera bloqu\u00e9 dans la boucle jusqu'au moment o\u00f9 la variable running
passera \u00e0 False
. pygame.display.flip()
effectue un rafra\u00eechissement total de tous les \u00e9l\u00e9ments graphiques de la fen\u00eatre. \u00c0 mettre \u00e0 l'int\u00e9rieur de la boucle infinie, g\u00e9n\u00e9ralement \u00e0 la fin de celle-ci.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#2-apparition-dun-personnage","title":"2. Apparition d'un personnage","text":""},{"location":"T6_Mini-projets/05_Initiation_Pygame/#21-telechargement-de-limage","title":"2.1. T\u00e9l\u00e9chargement de l'image","text":"Nous allons travailler avec le sprite ci-dessous, nomm\u00e9 perso.png
. Il est issu de https://openclassrooms.com/fr/courses/1399541-interface-graphique-pygame-pour-python/1399813-premieres-fenetres
T\u00e9l\u00e9chargez-le pour le mettre dans le m\u00eame dossier que votre code pygame
.
Vous pouvez trouver sur internet un grand nombre de sprites libres de droits, au format png
(donc g\u00e9rant la transparence), dans de multiples positions (ce qui permet de simuler des mouvements fluides). Ici nous travaillerons avec un sprite unique.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#22-importation-de-limage-dans-la-fenetre","title":"2.2. Importation de l'image dans la fen\u00eatre","text":"perso = pygame.image.load('perso.png').convert_alpha()\n
La fonction convert_alpha()
est appel\u00e9e pour que soit correctement trait\u00e9 le canal de transparence (canal alpha) de notre image."},{"location":"T6_Mini-projets/05_Initiation_Pygame/#23-affichage-de-limage","title":"2.3. Affichage de l'image","text":"\u00c0 ce stade, perso
est un objet pygame
de type Surface
.
Afin de facilement pouvoir le d\u00e9placer, nous allons stocker la position de cet objet dans une variable position_perso
, gr\u00e2ce \u00e0 l'instruction perso.get_rect()
.
Notre image est devenue \u00abun rectangle\u00bb que nous allons positionner o\u00f9 nous voulons.
Par exemple, pour positionner le coin sup\u00e9rieur gauche du personnage aux coordonn\u00e9es (100, 200)
, nous \u00e9crirons :
position_perso = perso.get_rect()\nposition_perso.topleft = (100, 200)\n
Il y a d'autres instructions que topleft
: vous pouvez les retrouver ici.
Pour afficher cette image, nous allons venir le superposer aux \u00e9l\u00e9ments graphiques d\u00e9j\u00e0 dessin\u00e9s (en l'occurence : rien) avec l'instruction blit()
:
fenetre.blit(perso, position_perso)\n
\u25b8 r\u00e9capitulatif du code
import pygame\nfrom pygame.locals import *\n\npygame.init()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\nrunning = True\nwhile running: \n fenetre.fill((10, 186, 181))\n position_perso.topleft = (100, 200)\n fenetre.blit(perso, position_perso)\n pygame.display.flip()\n\npygame.quit()\n
Aper\u00e7u
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#3-gestion-des-evenements","title":"3. Gestion des \u00e9v\u00e8nements","text":"Lorsqu'un programme pygame
est lanc\u00e9, la variable interne pygame.event.get()
re\u00e7oit en continu les \u00e9v\u00e8nements des p\u00e9riph\u00e9riques g\u00e9r\u00e9s par le syst\u00e8me d'exploitation. Nous allons nous int\u00e9resser aux \u00e9v\u00e8nements de type KEYDOWN
(touche de clavier appuy\u00e9e) ou de type MOUSEBUTTONDOWN
(boutons de souris appuy\u00e9).
Pour commencer, la gestion des \u00e9v\u00e8nements nous permettra de pouvoir enfin fermer proprement la fen\u00eatre Pygame, gr\u00e2ce au code suivant :
for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n
Exercice 1
Int\u00e9grer le code ci-dessus au code pr\u00e9c\u00e9dent afin de pouvoir fermer proprement la fen\u00eatre.
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\nrunning = True\nwhile running: \n fenetre.fill((10, 186, 181))\n position_perso.topleft = (100, 200)\n fenetre.blit(perso, position_perso)\n pygame.display.flip()\n\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n\npygame.quit()\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#31-evenements-clavier","title":"3.1. \u00c9v\u00e8nements clavier","text":""},{"location":"T6_Mini-projets/05_Initiation_Pygame/#311-exemple-de-code","title":"3.1.1. Exemple de code","text":"La structure de code pour d\u00e9tecter l'appui sur une touche de clavier est, dans le cas de la d\u00e9tection de la touche \u00abFl\u00e8che droite\u00bb :
for event in pygame.event.get(): \n if event.type == KEYDOWN:\n if event.key == K_RIGHT:\n print('fl\u00e8che droite appuy\u00e9e')\n
La touche (en anglais key) \u00abFl\u00e8che Droite\u00bb est appel\u00e9e K_RIGHT
par pygame
. il ne doit y avoir qu'une seule boucle de capture d'\u00e9v\u00e8nements, donc la routine de fermeture de la fen\u00eatre doit \u00eatre dans la m\u00eame boucle :
for event in pygame.event.get():\n if event.type == KEYDOWN:\n if event.key == K_RIGHT:\n print('fl\u00e8che droite appuy\u00e9e')\n\n if event.type == pygame.QUIT:\n running = False\n
Le nom de toutes les touches peut \u00eatre retrouv\u00e9 \u00e0 l'adresse https://www.pygame.org/docs/ref/key.html.
Remarque : c'est gr\u00e2ce \u00e0 la ligne initiale
from pygame.locals import *\n
que la variable K_RIGHT
(et toutes les autres) est reconnue."},{"location":"T6_Mini-projets/05_Initiation_Pygame/#312-probleme-de-la-remanence","title":"3.1.2. Probl\u00e8me de la r\u00e9manence","text":"Quand une touche de clavier est appuy\u00e9e, elle le reste un certain temps. Parfois volontairement (sur un intervalle long) quand l'utilisateur d\u00e9cide de la laisser appuy\u00e9e, mais aussi involontairement (sur un intervalle tr\u00e8s court), lors d'un appui \u00abclassique\u00bb. Il existe donc toujours un intervalle de temps pendant lequel la touche reste appuy\u00e9e. Que doit faire notre programme pendant ce temps ? Deux options sont possibles :
- option 1 : consid\u00e9rer que la touche appuy\u00e9e correspond \u00e0 un seul et unique \u00e9v\u00e8nement, quelle que soit la dur\u00e9e de l'appui sur la touche.
- option 2 : consid\u00e9rer qu'au bout d'un certain d\u00e9lai, la touche encore appuy\u00e9e doit d\u00e9clencher un nouvel \u00e9v\u00e8nement.
Par d\u00e9faut,pygame
est r\u00e9gl\u00e9 sur l'option 1. N\u00e9anmoins, il est classique pour les jeux vid\u00e9os de vouloir que \u00ablaisser la touche appuy\u00e9e\u00bb continue \u00e0 faire avancer le personnage. Nous allons donc faire en sorte que toutes les 50 millisecondes, un nouvel appui soit d\u00e9tect\u00e9 si la touche est rest\u00e9e enfonc\u00e9e. Cela se fera par l'expression :
pygame.key.set_repeat(50)\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#32-evenements-souris","title":"3.2 \u00c9v\u00e8nements souris","text":""},{"location":"T6_Mini-projets/05_Initiation_Pygame/#321-exemple-de-code","title":"3.2.1. Exemple de code","text":"La structure de code pour d\u00e9tecter l'appui sur un bouton de la souris est :
for event in pygame.event.get(): \n if event.type == MOUSEBUTTONDOWN and event.button == 1 :\n print('clic gauche d\u00e9tect\u00e9')\n if event.type == MOUSEBUTTONDOWN and event.button == 3 :\n print('clic droit d\u00e9tect\u00e9')\n
Le clic-gauche est associ\u00e9 \u00e0 la valeur 1, le clic-droit \u00e0 la valeur 3 (le clic-molette \u00e9ventuel \u00e0 la valeur 2).
Exercice 2
Reprendre le code initial et y int\u00e9grer la capture d'\u00e9v\u00e8nements souris afin que s'affiche en console le bouton de souris appuy\u00e9.
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\npygame.key.set_repeat(50)\n\nrunning = True\nwhile running: \n fenetre.fill((10, 186, 181))\n position_perso.topleft = (100, 200)\n fenetre.blit(perso, position_perso)\n pygame.display.flip()\n\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n\n if event.type == MOUSEBUTTONDOWN and event.button == 1 :\n print('clic gauche d\u00e9tect\u00e9')\n if event.type == MOUSEBUTTONDOWN and event.button == 3 :\n print('clic droit d\u00e9tect\u00e9')\n\npygame.quit()\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#322-recuperation-des-coordonnees-de-la-souris","title":"3.2.2. R\u00e9cup\u00e9ration des coordonn\u00e9es de la souris","text":"Le tuple (abscisse, ordonn\u00e9e)
des coordonn\u00e9es de la souris sera r\u00e9cup\u00e9r\u00e9 avec l'instruction pygame.mouse.get_pos()
.
Cette fonction n'a pas besoin d'\u00eatre dans notre boucle d'\u00e9coute des \u00e9v\u00e8nements : elle peut se situer n'importe o\u00f9 dans le code.
Exercice 3
Faire afficher en console les coordonn\u00e9es de la souris.
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\npygame.key.set_repeat(50)\n\nrunning = True\nwhile running: \n fenetre.fill((10, 186, 181))\n position_perso.topleft = (100, 200)\n fenetre.blit(perso, position_perso)\n\n x, y = pygame.mouse.get_pos()\n print(x, y)\n\n pygame.display.flip()\n\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n\n if event.type == MOUSEBUTTONDOWN and event.button == 1 :\n print('clic gauche d\u00e9tect\u00e9')\n if event.type == MOUSEBUTTONDOWN and event.button == 3 :\n print('clic droit d\u00e9tect\u00e9')\n\npygame.quit()\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#33-activation-dun-framerate","title":"3.3 Activation d'un framerate","text":"Pour l'instant, notre boucle infinie tourne \u00ab\u00e0 fond\u00bb et le rafra\u00eechissement de l'affichage se fait aussi rapidement que le peut le processeur. Afin de garder le contr\u00f4le sur cet fr\u00e9quence de rafra\u00eechissement (le nombre de frames par seconde, le fameux FPS) nous allons utiliser une horloge.
clock = pygame.time.Clock()
cr\u00e9e une horloge dans le corps du programme.
Ensuite, dans la boucle, nous rajouterons
clock.tick(30)
pour r\u00e9gler (par exemple) le FPS \u00e0 30.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#4-deplacement-du-personnage","title":"4. D\u00e9placement du personnage","text":"Le d\u00e9placement d'un personnage se fera toujours par modification de ses coordonn\u00e9es (et visuellement, par effacement de la derni\u00e8re position). Ce d\u00e9placement pourra \u00eatre :
- absolu : on donne de nouvelles coordonn\u00e9es au personnage.
- relatif : on indique de combien le personnage doit se d\u00e9caler par rapport \u00e0 sa position initiale.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#41-deplacement-absolu","title":"4.1. D\u00e9placement absolu","text":"Rappel : pour afficher le personnage \u00e0 la position (300,200)
, on \u00e9crit simplement:
position_perso.topleft = (300,200)\n
Au prochain fenetre.blit(perso, position_perso)
, le personnage sera positionn\u00e9 \u00e0 cette nouvelle position.
Exercice 4
R\u00e9aliser un d\u00e9placement al\u00e9atoire, comme l'animation ci-dessous.
Vous pourrez utiliser les instructions :
pygame.time.delay(1000)
afin de ne bouger le personnage que toutes les 1000 millisecondes. randint(a,b)
du package random
, qui renvoie un entier pseudo-al\u00e9atoire entre a
et b
.
Correction import pygame\nfrom pygame.locals import *\nfrom random import randint\n\npygame.init()\nclock = pygame.time.Clock()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\nrunning = True\nwhile running :\n clock.tick(30)\n fenetre.fill((10, 186, 181))\n position_perso = (randint(0, 540), randint(0, 380))\n\n fenetre.blit(perso, position_perso)\n pygame.display.flip()\n\n pygame.time.delay(1000)\n\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n running = False\n\npygame.quit()\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#42-deplacement-relatif","title":"4.2. D\u00e9placement relatif","text":"Pour d\u00e9placer le personnage de 15 pixels vers la droite et de 10 pixels vers le haut par rapport \u00e0 sa position pr\u00e9c\u00e9dente, on \u00e9crira :
position_perso = position_perso.move(15,-10)\n
o\u00f9 position_perso
est l'objet de type rect
contenant les coordonn\u00e9es. Exercice 5
R\u00e9aliser un contr\u00f4le au clavier du personnage, comme dans l'animation ci-dessous.
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\npygame.key.set_repeat(50)\nclock = pygame.time.Clock()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\npas = 15 \n\nrunning = True\nwhile running:\n clock.tick(30)\n fenetre.fill((10, 186, 181))\n fenetre.blit(perso, position_perso)\n\n for event in pygame.event.get() : \n if event.type == KEYDOWN:\n\n if event.key == K_DOWN : \n position_perso = position_perso.move(0, pas)\n\n if event.key == K_UP :\n position_perso = position_perso.move(0, -pas)\n\n if event.key == K_RIGHT : \n position_perso = position_perso.move(pas, 0)\n\n if event.key == K_LEFT : \n position_perso = position_perso.move(-pas, 0) \n\n # routine pour pouvoir fermer \u00abproprement\u00bb la fen\u00eatre Pygame\n if event.type == pygame.QUIT:\n running = False\n\n\n pygame.display.flip() \n\npygame.quit()\n
Exercice 6
Rajouter des instructions afin que le personnage ne puisse pas sortir de la fen\u00eatre de jeu.
On utilisera les variables suivantes :
position_perso.top
: ordonn\u00e9e du haut du personnage position_perso.bottom
: ordonn\u00e9e du bas du personnage position_perso.left
: abscisse de la gauche du personnage position_perso.right
: abscisse de la droite du personnage
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\npygame.key.set_repeat(50)\nclock = pygame.time.Clock()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\npas = 15 \n\nrunning = True\nwhile running:\n clock.tick(30)\n fenetre.fill((10, 186, 181))\n fenetre.blit(perso, position_perso)\n\n if position_perso.top < 0:\n position_perso.top = 0\n\n if position_perso.bottom > 480:\n position_perso.bottom = 480\n\n if position_perso.left < 0:\n position_perso.left = 0\n\n if position_perso.right > 640:\n position_perso.right = 640\n\n\n for event in pygame.event.get() : \n if event.type == KEYDOWN:\n\n if event.key == K_DOWN : \n position_perso = position_perso.move(0, pas)\n\n if event.key == K_UP :\n position_perso = position_perso.move(0, -pas)\n\n if event.key == K_RIGHT : \n position_perso = position_perso.move(pas, 0)\n\n if event.key == K_LEFT : \n position_perso = position_perso.move(-pas, 0) \n\n if event.type == pygame.QUIT:\n running = False\n\n\n pygame.display.flip() \n\npygame.quit()\n
Exercice 7
Reprendre l'exercice pr\u00e9c\u00e9dent mais faire en sorte que le personnage r\u00e9apparaisse \u00e0 l'oppos\u00e9 de l\u00e0 o\u00f9 il est sorti.
Correction import pygame\nfrom pygame.locals import *\n\npygame.init()\npygame.key.set_repeat(50)\nclock = pygame.time.Clock()\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\nposition_perso = perso.get_rect()\n\npas = 15 \n\nrunning = True\nwhile running:\n clock.tick(30)\n fenetre.fill((10, 186, 181))\n fenetre.blit(perso, position_perso)\n\n if position_perso.top < 0:\n position_perso.bottom = 480\n\n if position_perso.bottom > 480:\n position_perso.top = 0\n\n if position_perso.left < 0:\n position_perso.right = 640\n\n if position_perso.right > 640:\n position_perso.left = 0\n\n\n for event in pygame.event.get() : \n if event.type == KEYDOWN:\n\n if event.key == K_DOWN : \n position_perso = position_perso.move(0, pas)\n\n if event.key == K_UP :\n position_perso = position_perso.move(0, -pas)\n\n if event.key == K_RIGHT : \n position_perso = position_perso.move(pas, 0)\n\n if event.key == K_LEFT : \n position_perso = position_perso.move(-pas, 0) \n\n if event.type == pygame.QUIT:\n running = False\n\n\n pygame.display.flip() \n\npygame.quit()\n
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#5-controle-avec-la-microbit","title":"5. Contr\u00f4le avec la micro:bit","text":"Pour pouvoir contr\u00f4ler notre personnage avec (par exemple) les boutons de la carte micro:bit, il va falloir :
- mettre dans la carte un programme minimal qui va se contenter d'envoyer des donn\u00e9es.
- mettre dans notre programme Pygame une instruction capable de recevoir les donn\u00e9es envoy\u00e9es par la carte.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#51-programme-a-televerser-dans-la-microbit","title":"5.1 Programme \u00e0 t\u00e9l\u00e9verser dans la micro:bit","text":"Lien vers le simulateur
from microbit import *\n\nwhile True:\n incX = accelerometer.get_x()\n incY = accelerometer.get_y()\n\n message = \"{},{}\".format(incX,incY)\n print(message)\n\n sleep(50)\n
Ce programme va envoyer, 20 fois par seconde, la valeur de l'inclinaison en X et la valeur de l'inclinaison en Y.
"},{"location":"T6_Mini-projets/05_Initiation_Pygame/#52-recuperation-des-donnees-dans-pygame","title":"5.2 R\u00e9cup\u00e9ration des donn\u00e9es dans Pygame","text":"Il faut conna\u00eetre le port utilis\u00e9 par le syst\u00e8me d'exploitation pour communiquer avec la micro:bit. Sous Linux, ce port est de la forme ttyACM0
, sous Windows il sera de la forme COM2
.
connaitre le port sous Windows
Ouvrir un terminal via cmd
et taper la commande mode
.
Une fois le programme d'envoi t\u00e9l\u00e9vers\u00e9 dans la micro:bit et le port connu, testez le programme suivant :
import serial\n\nport = \"COM2\" # \u00e0 adapter en allant voir le port utilis\u00e9 par la microbit\ns = serial.Serial(port)\ns.baudrate = 115200\n\nwhile True:\n s.flushInput()\n data = s.readline()\n data = data.decode('utf-8')\n data = data.split(',')\n incX = int(data[0])\n incY = int(data[1])\n print(incX, incY)\n
En inclinant la carte, vous devriez voir bouger les valeurs dans la console de Thonny. Observer quelles sont les valeurs minimales et maximales.
Exercice 8
\u00c0 l'aide de l'exemple pr\u00e9c\u00e9dent, modifiez le code de l'exercice 5 afin de pouvoir bouger le personnage \u00e0 l'aide de la micro:bit.
Correction import pygame \nfrom pygame.locals import *\n\nimport serial\n\nport = 'COM2' # \u00e0 adapter\ns = serial.Serial(port)\ns.baudrate = 115200 \n\n\n\npygame.init()\npygame.key.set_repeat(50)\n\nfenetre = pygame.display.set_mode((640, 480))\n\nperso = pygame.image.load('perso.png').convert_alpha()\n\nposition_perso = perso.get_rect()\nposition_perso.center = (320, 240)\npas = 10 \npygame.time.delay(500)\nclock = pygame.time.Clock()\n\nseuil = 200\n\nrunning = True\nwhile running:\n\n clock.tick(30)\n\n s.flushInput()\n data = s.readline()\n data = data.decode('utf-8')\n data = data.split(',')\n accX = int(data[0])\n accY = int(data[1]) \n\n if accY < -seuil : \n position_perso = position_perso.move(0, -pas)\n\n if accY > seuil :\n position_perso = position_perso.move(0, pas)\n\n if accX > seuil : \n position_perso = position_perso.move(pas, 0)\n\n if accX < -seuil : \n position_perso = position_perso.move(-pas, 0)\n\n if position_perso.top < 0:\n position_perso.top = 0\n\n if position_perso.bottom > 480:\n position_perso.bottom = 480\n\n if position_perso.left < 0:\n position_perso.left = 0\n\n if position_perso.right > 640:\n position_perso.right = 640\n\n\n for event in pygame.event.get() : \n if event.type == pygame.QUIT:\n running = False\n\n fenetre.fill((10, 186, 181))\n fenetre.blit(perso, position_perso)\n pygame.display.flip()\n\npygame.quit()\n
Bibliographie
- Documentation officielle de Pygame, https://www.pygame.org/docs/
- Cours d'OpenClassrooms, https://openclassrooms.com/fr/courses/1399541-interface-graphique-pygame-pour-python/1399813-premieres-fenetres.
"},{"location":"T6_Mini-projets/Attaque_BF/","title":"Attaque d'un mot de passe par force brute","text":" attention
L'activit\u00e9 ci-dessous n'est pas r\u00e9alisable sous Capytale, qui n'autorise pas l'utilisation du module requests
. Vous devez donc la r\u00e9aliser sur (par exemple) Thonny. Si vous n'avez pas (encore) Thonny sur votre ordinateur personnel, t\u00e9l\u00e9chargez-le ici
Par contre, les r\u00e9ponses aux questions pos\u00e9es doivent \u00eatre donn\u00e9es sur l'activit\u00e9 Capytale https://capytale2.ac-paris.fr/web/c/7371-1140429
Votre objectif est de trouver le mot de passe demand\u00e9 sur la page http://glassus1.free.fr/exoBF.html
Vous allez vous appuyer sur un leak (fuite) tr\u00e8s c\u00e9l\u00e8bre de mots de passe , qui est le leak du site Rockyou. Dans la base de donn\u00e9es de ce site, 32 millions de mots de passe \u00e9taient stock\u00e9s en clair.
Lorsque le site a \u00e9t\u00e9 pirat\u00e9 (par une injection SQL, voir le cours de Terminale), ces 32 millions de mots de passe se sont retrouv\u00e9s dans la nature. Ils sont aujourd'hui t\u00e9l\u00e9chargeables librement, et constituent un dictionnaire de 14 341 564 mots de passe diff\u00e9rents (car parmi les 32 millions d'utilisateurs, beaucoup utilisaient des mots de passe identiques).
Nous allons utiliser un fichier beaucoup plus l\u00e9ger ne contenant que les 1000 premiers mots de passe. Ce fichier est nomm\u00e9 extraitrockyou.txt
.
"},{"location":"T6_Mini-projets/Attaque_BF/#1-lire-les-mots-dun-fichier","title":"1. Lire les mots d'un fichier","text":""},{"location":"T6_Mini-projets/Attaque_BF/#11-telechargement-du-fichier-extraitrockyoutxt","title":"1.1 T\u00e9l\u00e9chargement du fichier extraitrockyou.txt
","text":"T\u00e9l\u00e9chargez le fichier extraitrockyou.txt. Attention, ce fichier doit \u00eatre imp\u00e9rativement situ\u00e9 dans le m\u00eame r\u00e9pertoire que le fichier du code Python que vous allez \u00e9crire.
"},{"location":"T6_Mini-projets/Attaque_BF/#12-recuperer-les-elements-du-fichier","title":"1.2 R\u00e9cup\u00e9rer les \u00e9l\u00e9ments du fichier","text":"Ouvrir un nouveau code dans Thonny et enregistrez-le \u00e0 c\u00f4t\u00e9 du fichier extraitrockyou.txt
.
La ligne suivante va stocker dans une liste liste_mdp
les 1000 mots de passe pr\u00e9sents dans le fichier extraitrockyou.txt
.
liste_mdp = open(\"extraitrockyou.txt\").read().splitlines()\n
Si vous avez l'erreur :
FileNotFoundError: [Errno 2] No such file or directory: 'extraitrockyou.txt'\n
c'est que votre code et le fichier extraitrockyou.txt
ne sont pas dans le m\u00eame r\u00e9pertoire.
Question 1
\u00c9crire un code qui affiche les 1000 mots de passe contenus dans liste_mdp
.
(rappel : vous devez aller \u00e9crire vos r\u00e9ponses sur l'activit\u00e9 Capytale https://capytale2.ac-paris.fr/web/c/7371-1140429)
"},{"location":"T6_Mini-projets/Attaque_BF/#2-utilisation-du-module-requests","title":"2. Utilisation du module requests
","text":"Le module requests
de Python permet de r\u00e9cup\u00e9rer le contenu d'une page web dont on aura donn\u00e9 l'adresse en param\u00e8tre.
Souvenez-vous par exemple de cette superbe page : http://glassus1.free.fr/interesting.html
Exc\u00e9cutez le code ci-dessous :
import requests\np = requests.get(\"http://glassus1.free.fr/interesting.html\")\nprint(p.text)\n
Question 2
\u00c9crire ce qui s'affiche en console lors de l'ex\u00e9cution du code :
import requests\np = requests.get(\"http://glassus1.free.fr/interesting.html\")\nprint(p.text)\n
Si vous avez l'erreur :
ModuleNotFoundError: No module named 'requests'\n
c'est que le module requests
n'est pas install\u00e9. Dans Thonny, aller dans Outils / G\u00e9rer les paquets et installer requests
.
"},{"location":"T6_Mini-projets/Attaque_BF/#3-proposer-un-mot-de-passe","title":"3. Proposer un mot de passe","text":"Un des 1000 mots de passe du fichier extraitrockyou.txt
est le bon. Mais comment savoir lequel ?
"},{"location":"T6_Mini-projets/Attaque_BF/#31-observation-a-la-main","title":"3.1 Observation \u00ab\u00e0 la main\u00bb","text":"Question 3
Rendez-vous sur la page http://glassus1.free.fr/exoBF.html et proposer le mot de passe mauriac
. Quelle url s'affiche alors dans la barre d'adresse ?
"},{"location":"T6_Mini-projets/Attaque_BF/#32-automatisation-dun-proposition","title":"3.2 Automatisation d'un proposition","text":"Question 4
\u00c9crire un code qui va proposer le mot de passe vacances
et afficher le texte de la page obtenue.
"},{"location":"T6_Mini-projets/Attaque_BF/#4-resolution-du-probleme","title":"4. R\u00e9solution du probl\u00e8me","text":""},{"location":"T6_Mini-projets/Attaque_BF/#41-petite-aide-sur-les-chaines-de-caracteres","title":"4.1 Petite aide sur les chaines de caract\u00e8res","text":"Pour rappel la concat\u00e9nation des chaines de caract\u00e8res permet de faire ceci :
base = \"je vous souhaite de bonnes\"\nsuite = \"vacances\"\nphrase = base + suite\n
Question 5
\u00c9crire un code qui va afficher les 1000 urls diff\u00e9rentes qui serviront \u00e0 tester tous les mots de passe du fichier extraitrockyou.txt
.
"},{"location":"T6_Mini-projets/Attaque_BF/#42-quel-est-le-bon-mot-de-passe","title":"4.2 Quel est le bon mot de passe ?","text":"Question 6
\u00c9crire un code qui d\u00e9termine le mot de passe de la page http://glassus1.free.fr/exoBF.html.
"},{"location":"T6_Mini-projets/D%C3%A9codeuses/","title":"D\u00e9codeuses du num\u00e9rique","text":" -
La BD en ligne est disponible ici.
-
Le pdf est disponible en t\u00e9l\u00e9chargement ici.
-
Les portraits sont accessibles ici.
Affectation des pr\u00e9sentations
- Alissa : Anne-C\u00e9cile Orgerie
- Ahmed : Magalie Ochs
- Antoine : Claire Mathieu
- Louka : Emmanuelle Kristensen
- Tristan : Caroline Fontaine
- Candice : Elsa Cazelles
- Elouo : Lucile Sassatelli
- Louan : Sarah Cohen-Boulakia
- Hugo : Nina Amini
- Emma : Fran\u00e7oise Conil
- Emmy : Marie-Christine Rousset
- Vincent : Pauline Maurice
- Mathias : Anne-C\u00e9cile Orgerie
"},{"location":"T6_Mini-projets/Exercice_Perseverance/","title":"Le message secret de Perseverance","text":"Lors de sa descente vers la plan\u00e8te Mars le 18/02/2021, le rover Perseverance de la Nasa a frein\u00e9 sa chute gr\u00e2ce \u00e0 un parachute qui a intrigu\u00e9 quelques internautes du forum Reddit.
Vid\u00e9o du d\u00e9ploiement du parachute :
Les zones blanches et rouge se d\u00e9composent comme ceci :
"},{"location":"T6_Mini-projets/Exercice_Perseverance/#indications","title":"Indications","text":" - Le tout premier secteur contenant un message est le secteur sur lequel est \u00e9crite la lettre D, qui est effectivement la signification de ce secteur. C'est en l'observant bien que vous comprendrez le codage qui a \u00e9t\u00e9 utilis\u00e9.
- Les autres secteurs sont marqu\u00e9s de points d'interrogation : c'est \u00e0 vous de d\u00e9couvrir ce qu'ils cachent.
- La phrase myst\u00e8re s'obtiendra en tournant en spirale depuis la lettre D, dans le sens horaire.
- La derni\u00e8re couronne (la plus \u00e0 l'ext\u00e9rieur) est un peu particuli\u00e8re, mais n'en disons pas plus...
"},{"location":"T6_Mini-projets/Exercice_Perseverance/#a-vous","title":"\u00c0 vous !","text":"Un grand bravo aux brillants redditors u/rdtwt1
et u/tend0g
.
"},{"location":"T6_Mini-projets/Exercice_Perseverance/#update-faites-votre-propre-parachute","title":"Update : faites votre propre parachute !","text":"https://sjwarner.github.io/perseverance-parachute-generator/?
"},{"location":"T6_Mini-projets/Exercice_Perseverance/#sources-attention-spoiler","title":"Sources (attention spoiler):","text":" - https://www.lemonde.fr/pixels/article/2021/02/23/des-internautes-dechiffrent-un-message-cache-dans-le-parachute-du-rover-de-la-nasa-sur-mars_6070952_4408996.html
- https://www.reddit.com/r/nasa/comments/lpy2fa/does_the_parachute_for_perseverance_have_some/goedts0/
- https://twitter.com/steltzner/status/1364076615932645379
"},{"location":"T6_Mini-projets/Github/","title":"Mise en place de GitHub","text":"Afin de travailler efficacement entre votre ordinateur personnel et votre VM du lyc\u00e9e, nous utiliser la solution GitHub.
"},{"location":"T6_Mini-projets/Github/#etape-0-creer-un-compte-github","title":"\u00c9tape 0 : cr\u00e9er un compte GitHub","text":"Cela se passe ici
"},{"location":"T6_Mini-projets/Github/#etape-1-creer-un-premier-depot-repository","title":"\u00c9tape 1 : cr\u00e9er un premier d\u00e9p\u00f4t (repository)","text":"Une fois termin\u00e9e la cr\u00e9ation de compte, GitHub vous proposera de cr\u00e9er votre premier d\u00e9p\u00f4t (on dira aussi repository, ou repo). Vous pourrez avoir autant de d\u00e9p\u00f4ts que vous voulez : \u00e0 chaque nouveau projet doit correspondre un nouveau d\u00e9p\u00f4t.
Cr\u00e9ez donc un d\u00e9p\u00f4t Projet Pygame
(ou comme vous voulez).
"},{"location":"T6_Mini-projets/Github/#etape-2-installer-github-desktop","title":"\u00c9tape 2 : installer GitHub Desktop","text":"GitHub Desktop est un logiciel qui devra \u00eatre install\u00e9 sur nos VMs (c'est fait) mais aussi sur votre ordinateur personnel de travail. Vous trouverez les liens de t\u00e9l\u00e9chargement ici.
Le r\u00f4le de GitHub Desktop va \u00eatre de synchroniser vos fichiers locaux avec le serveur distant de github.com (\u00able cloud\u00bb). Contrairement \u00e0 une solution automatique (type Dropbox ou Google Drive), la synchronisation n'est pas automatique mais manuelle. C'est \u00e0 vous d'aller uploader vos fichiers (push) ou bien de les t\u00e9l\u00e9charger (fetch).
"},{"location":"T6_Mini-projets/Github/#etape-3-configurer-github-desktop","title":"\u00c9tape 3 : configurer GitHub Desktop","text":"Il va falloir pr\u00e9ciser \u00e0 GitHub que nous avons d\u00e9j\u00e0 un compte, et un d\u00e9p\u00f4t que nous avons cr\u00e9\u00e9 plus haut. Vous pouvez vous laisser guider ou suivre ce tutoriel
"},{"location":"T6_Mini-projets/Tkinter/","title":"Introduction \u00e0 Tkinter","text":"Tkinter
est un module de Python permettant la cr\u00e9ation d'interfaces graphiques.
"},{"location":"T6_Mini-projets/Tkinter/#0-site-de-presentation-de-tkinter","title":"0. Site de pr\u00e9sentation de Tkinter","text":"Vous pouvez suivre pas \u00e0 pas l'excellent travail de Fabrice Sinc\u00e8re, disponible \u00e0 cette page :
http://f.sincere.free.fr/isn/python/cours_python_tkinter.php
Vous pouvez aussi poser des questions \u00e0 https://www.perplexity.ai/ ou une autre IA.
"},{"location":"T6_Mini-projets/Tkinter/#1-objectif-final","title":"1. Objectif final","text":""},{"location":"T6_Mini-projets/Tkinter/#2-etape-1","title":"2. \u00c9tape 1","text":"Instructions :
Tracer
doit tracer un cercle bleu (avec une bordure noire) de taille fixe (30 px). - Les boutons
Tracer
et Effacer
sont dans une frame particuli\u00e8re. - La zone de dessin mesure 480x320.
Aide :
- Exemple 6 de http://f.sincere.free.fr/isn/python/cours_python_tkinter.php
Correction from tkinter import *\nimport random\n\n\ndef cercle():\n x = random.randint(0, largeur)\n y = random.randint(0, hauteur)\n r = 30\n zone_dessin.create_oval(x-r, y-r, x+r, y+r, outline='black', fill='blue')\n\n\ndef effacer():\n zone_dessin.delete(ALL)\n\nma_fenetre = Tk()\nma_fenetre.title('Traceur de cercles')\n\n\nlargeur = 480\nhauteur = 320\nzone_dessin = Canvas(ma_fenetre, width=largeur, height=hauteur, bg='white')\nzone_dessin.pack(padx=5, pady=5)\n\nframe1 = Frame(ma_fenetre, borderwidth=2, relief=GROOVE)\nframe1.pack(side=LEFT, padx=10, pady=10)\n\nframe2 = Frame(ma_fenetre, relief=GROOVE)\nframe2.pack(side=LEFT, padx=10, pady=10)\n\nbouton_Tracer = Button(frame1, text='Tracer', command=cercle)\nbouton_Tracer.pack(side=LEFT, padx=10, pady=10)\n\nbouton_Effacer = Button(frame1, text='Effacer', command=effacer)\nbouton_Effacer.pack(side=LEFT, padx=5, pady=5)\n\nbouton_Quitter = Button(frame2, text='Quitter', command=ma_fenetre.destroy)\nbouton_Quitter.pack(side=LEFT, padx=5, pady=5)\n\nma_fenetre.mainloop()\n
"},{"location":"T6_Mini-projets/Tkinter/#3-etape-2","title":"3. \u00c9tape 2","text":"Instructions :
Couleur
doit ouvrir une boite de dialogue pour changer la couleur de remplissage.
"},{"location":"T6_Mini-projets/Tkinter/#1-variable-couleur","title":"1. Variable couleur
","text":"Pour commencer, il faut cr\u00e9er une variable dynamique couleur
qui sera plus tard modifi\u00e9e par la boite de dialogue :
couleur = StringVar() # on cr\u00e9e la variable\ncouleur.set('blue') # on l'initialise \u00e0 'blue' \n
Pour acc\u00e9der au contenu de la variable couleur
, on utilise l'instruction couleur.get()
.
Modifier la fonction cercle
pour que la couleur de remplissage soit couleur
.
"},{"location":"T6_Mini-projets/Tkinter/#2-bouton-couleur","title":"2. Bouton Couleur
","text":" Cr\u00e9er et placer un bouton Couleur
qui d\u00e9clenchera une fonction change_color
que nous \u00e9crirons plus tard.
"},{"location":"T6_Mini-projets/Tkinter/#3-fonction-change_color-et-boite-de-dialogue","title":"3. Fonction change_color
et boite de dialogue","text":"Pour int\u00e9grer la boite de dialogue de choix de couleur, il faut commencer par appeler deux fonctions / modules suppl\u00e9mentaires :
from tkinter import ttk\nfrom tkinter.colorchooser import askcolor\n
La fonction change_color
s'\u00e9crira comme ceci :
def change_color():\n colors = askcolor(title=\"Tkinter Color Chooser\")\n couleur.set(...)\n
Pour savoir ce qu'il faut \u00e9crire \u00e0 la place des pointill\u00e9s, faites des tests (avec un print
, par exemple) pour savoir \u00e0 quoi ressemble la variable colors
qui est renvoy\u00e9e par la fonction askcolor
.
Souvenez-vous ensuite que Tkinter
travaille avec les couleurs en \u00e9criture hexad\u00e9cimale et non pas RGB...
Correction from tkinter import *\nfrom tkinter import ttk\nfrom tkinter.colorchooser import askcolor\nimport random\n\n\ndef cercle():\n x = random.randint(0, largeur)\n y = random.randint(0, hauteur)\n r = 30\n zone_dessin.create_oval(x-r, y-r, x+r, y+r, outline='black', fill=couleur.get())\n\n\ndef effacer():\n zone_dessin.delete(ALL)\n\n\ndef change_color():\n colors = askcolor(title='Tkinter Color Chooser')\n couleur.set(colors[1])\n\n\nma_fenetre = Tk()\nma_fenetre.title('Traceur de cercles')\n\ncouleur = StringVar()\ncouleur.set('blue')\n\n\nlargeur = 480\nhauteur = 320\nzone_dessin = Canvas(ma_fenetre, width=largeur, height=hauteur, bg='white')\nzone_dessin.pack(padx=5, pady=5)\n\nframe1 = Frame(ma_fenetre, borderwidth=2, relief=GROOVE)\nframe1.pack(side=LEFT, padx=10, pady=10)\n\nframe2 = Frame(ma_fenetre, relief=GROOVE)\nframe2.pack(side=LEFT, padx=10, pady=10)\n\nbouton_Tracer = Button(frame1, text='Tracer', command=cercle)\nbouton_Tracer.pack(side=LEFT, padx=10, pady=10)\n\n\nbouton_Effacer = Button(frame1, text='Effacer', command=effacer)\nbouton_Effacer.pack(side=LEFT, padx=5, pady=5)\n\nbouton_Couleur = ttk.Button(frame1, text='Couleur', command=change_color)\nbouton_Couleur.pack(side=LEFT, padx=5, pady=5)\n\n\nbouton_Quitter = Button(frame2, text='Quitter', command=ma_fenetre.destroy)\nbouton_Quitter.pack(side=LEFT, padx=5, pady=5)\n\nma_fenetre.mainloop()\n
"},{"location":"T6_Mini-projets/Tkinter/#4-etape-3","title":"4. \u00c9tape 3","text":"Instructions :
- Un curseur doit permettre de modifier le rayon du cercle.
Il faut proc\u00e9der de la m\u00eame mani\u00e8re que pour la couleur.
Pensez \u00e0 utiliser IntVar
plut\u00f4t que StringVar
, car le rayon est un nombre entier.
Des indications pour l'int\u00e9gration du curseur sont \u00e0 retrouver dans l'exemple 5 du site http://f.sincere.free.fr/isn/python/cours_python_tkinter.php
"},{"location":"T6_Mini-projets/Tkinter/#5-bonus","title":"5. Bonus","text":"Remplacer le placement al\u00e9atoire par un placement au clic de souris.
"},{"location":"T7_Divers/1_Conseils_generaux/cours/","title":"Conseils de travail","text":""},{"location":"T7_Divers/1_Conseils_generaux/cours/#conditions-materielles","title":"Conditions mat\u00e9rielles","text":"Il est conseill\u00e9 de travailler avec 3 espaces:
- l'\u00e9cran de l'ordinateur partitionn\u00e9 avec les 2 premiers espaces: ce site et un IDE (Thonny par exemple);
C'est en codant qu'on apprend \u00e0 coder
Tous les exemples de code dans le cours doivent \u00eatre retap\u00e9s (r\u00e9sistez \u00e0 l'envie du copier-coller) dans Thonny, soit en fen\u00eatre de script, soit en console.
Cela permet de :
- m\u00e9moriser la syntaxe ;
- v\u00e9rifier si le code propos\u00e9 ne contient pas d'erreur ;
et le plus important :
- faire ses propres tests et modifications pour v\u00e9rifier sa bonne compr\u00e9hension.
- et un troisi\u00e8me espace essentiel : un petit cahier \u00e0 spirale et un stylo !
"},{"location":"T7_Divers/1_Conseils_generaux/cours/#script-ou-console","title":"Script ou console ???","text":"Thonny, comme la grande majorit\u00e9 des IDE Python, est compos\u00e9 de deux zones distinctes :
- la zone de script
- la console
La zone de script est asynchrone. Il ne se passera rien tant que vous n'aurez pas ex\u00e9cut\u00e9 le script (par F5 par exemple). C'est donc l'endroit o\u00f9 on va r\u00e9diger son programme.
La console est synchrone : elle r\u00e9pond d\u00e8s que vous appuyez sur la touche Entr\u00e9e. Elle sert donc aux petits tests rapides, ou bien tests post-ex\u00e9cution d'un code.
Utilisation classique du couple script / console
- On \u00e9crit son code dans la zone de script
- On l'ex\u00e9cute.
- On interroge la console pour conna\u00eetre l'\u00e9tat des variables, pour utiliser les fonctions construites dans le script.
Pour les extraits de code pr\u00e9sents sur ce site :
- tout le code qui est pr\u00e9c\u00e9d\u00e9 d'une num\u00e9rotation de ligne est \u00e0 \u00e9crire en zone de script.
Exemple :
def accueil(n):\n for k in range(n):\n print(\"bonjour\") \n
- tout le code qui est pr\u00e9c\u00e9d\u00e9
>>>
est \u00e0 taper en console.
Exemple :
>>> accueil(5)\n
"},{"location":"T7_Divers/1_Conseils_generaux/cours/#dossiers-fichiers-et-versionning","title":"Dossiers, fichiers et versionning","text":"Cette ann\u00e9e en NSI nous allons manipuler un certain nombre de fichiers. Il est important de les nommer et les classer de fa\u00e7on rigoureuse pour les retrouver rapidement et les partager.
Conseils
- Utilisez des dossiers pour classer vos fichiers. Il n'y en a jamais assez.
- Prenez l'habitude de faire plusieurs sauvegardes de vos documents (sur le r\u00e9seau du lyc\u00e9e, sur l'ENT, sur cl\u00e9 USB).
- \u00c9vitez dans les noms de fichiers et de dossiers les espaces (utilisez plut\u00f4t _ ) ainsi que les caract\u00e8res accentu\u00e9s et les caract\u00e8res sp\u00e9ciaux.
- Un nom de fichier doit \u00eatre parlant (un peu comme une variable en fait). On \u00e9vitera de nommer ses codes Python
python1.py
, python2.py
, python3.py
, etc. Mais plut\u00f4t 1NSI_T4_tri_selection.py
par exemple pour un exercice de programmation sur le tri par selection au th\u00e8me 4. - Lorsqu'on travaille sur un projet ou un programme cons\u00e9quent, il peut \u00eatre utile de conserver des archives du travail \u00e0 plusieurs \u00e9tapes de l'\u00e9laboration, plut\u00f4t que de ne conserver que la derni\u00e8re version. \u00c0 cet effet on pourra num\u00e9roter :
1NSI_projet_morpion_v1.py
, puis 1NSI_projet_morpion_v2.py
, 1NSI_projet_morpion_v3.py
, etc.
"},{"location":"T7_Divers/1_Conseils_generaux/cours/#usage-du-clavier","title":"Usage du clavier","text":"Utiliser le clavier est souvent bien plus pratique et surtout plus rapide qu'utiliser la souris. Encore faut-il apprendre \u00e0 l'apprivoiser...
La s\u00e9lection au clavier
Outre les touches DEBUT
et FIN
qui permettent d'atteindre rapidement le d\u00e9but ou la fin d'une ligne, les fl\u00e8ches directionelles servent \u00e9videmment \u00e0 se d\u00e9placer dans du texte. Mais combin\u00e9es:
- \u00e0 la touche
CTRL
: elles permettent de se d\u00e9placer de mot en mot; - \u00e0 la touche
MAJ
: elles permettent de s\u00e9lectionner un caract\u00e8re; - aux touches
MAJ
et CTRL
: elles permettent de s\u00e9lectionner un mot.
De m\u00eame, en se pla\u00e7ant en d\u00e9but d'une ligne et en combinant la touche MAJ
et FIN
, on s\u00e9lectionne la ligne enti\u00e8re.
Les raccourcis clavier
Il existe de tr\u00e8s nombreux raccourcis clavier qui permettent d'ex\u00e9cuter des t\u00e2ches courantes sans passer par les menus du logiciel. Certains sont (quasi-)universels, c'est-\u00e0-dire que ce sont les m\u00eames sur tous les logiciels, d'autres sont sp\u00e9cifiques \u00e0 chaque logiciel. Il est important d'en conna\u00eetre quelques-uns pour \u00eatre plus efficace.
Les universelsIDENavigateur Web - La triplette magique
CTRL+X
, CTRL+C
, CTRL+V
pour couper, copier, coller; CTRL+O
pour ouvrir un fichier CTRL+N
pour cr\u00e9er un nouveau document; CTRL+S
pour sauvegarder le document en cours; CTRL+MAJ+S
pour sauvegarder en pr\u00e9cisant le nom du fichier; CTRL+Z
pour annuler la derni\u00e8re action, CTRL+Y
ou CTRL+MAJ+Z
pour la r\u00e9tablir; CTRL+W
pour fermer un onglet; CTRL+Q
ou ALT+F4
pour fermer le logiciel; CTRL+A
pour s\u00e9lectionner tout (All).
\u00c0 chercher de suite lorsqu'on utilise un nouvel IDE, les raccourcis pour les actions suivantes (entre parenth\u00e8ses ceux de Thonny):
- ex\u00e9cuter le code (
F5
) - commenter/d\u00e9commenter une ligne (
CTRL+M
)
CTRL+T
pour ouvrir un nouvel onglet; CTRL+H
pour ouvrir l'historique; - combiner
CTRL
+ clic pour forcer l'ouverture d'un lien dans un nouvel onglet; - combiner
MAJ
+ clic pour forcer l'ouverture d'un lien dans une nouvelle fen\u00eatre;
sources - site de C\u00e9dric Gouygou
"},{"location":"T7_Divers/2_VM/cours/","title":"Utilisation des VMs au lyc\u00e9e","text":""},{"location":"T7_Divers/2_VM/cours/#principe","title":"Principe","text":"Afin de pouvoir travailler sous le syst\u00e8me d'exploitation libre Linux sur les machines du lyc\u00e9e (sous Windows), nous utilisons la solution de virtualisation Proxmox. De mani\u00e8re simplifi\u00e9e :
- un serveur (assez puissant) se trouve dans la salle serveur du lyc\u00e9e.
- sur cet ordinateur, un grand nombre de syst\u00e8mes d'exploitation peuvent \u00eatre d\u00e9marr\u00e9s ind\u00e9pendamment.
- l'un d'entre eux porte votre nom : c'est votre machine virtuelle (votre VM).
- vous vous connectez \u00e0 votre VM depuis un navigateur de n'importe quel ordinateur du lyc\u00e9e.
- cet ordinateur (appel\u00e9 h\u00f4te) ne va faire que recevoir le flux vid\u00e9o venu du serveur (et lui envoyer les interactions utilisateurs : souris, clavier)
- en mettant ce flux vid\u00e9o en plein \u00e9cran, on a l'illusion d'\u00eatre sous un nouveau syst\u00e8me d'exploitation. Nous allons donc travailler sous Linux, tout en restant en r\u00e9alit\u00e9 sous Windows.
"},{"location":"T7_Divers/2_VM/cours/#methode","title":"M\u00e9thode","text":" - Sur le bureau Windows, ouvrir le dossier
Programmation
. - Cliquer sur
Proxmox NSI
. - Un navigateur s'ouvre, mais une alerte de s\u00e9curit\u00e9 appara\u00eet. Cliquer sur
Param\u00e8tres avanc\u00e9s
puis sur Continuer vers le site 172.17.191.244
- Sur la fen\u00eatre de connexion
Proxmox VE Login
, renseigner ses identifiants et s\u00e9lectionner Realm Proxmox VE authentication server
. - Un messade d'avertissement appara\u00eet. Cliquer
ok
pour l'ignorer. - S\u00e9lectionner sa machine virtuelle (VM) dans la colonne de gauche.
- Cliquer sur
Start
pour d\u00e9marrer la VM. - Cliquer sur le bouton
Console
et choisir Spice
. - Cliquer sur le fichier
telechargement.vv
apparu en bas \u00e0 gauche. - Attendre (un peu).
- Si rien ne se passe au bout d'une dizaine de secondes, fermer la fen\u00eatre et cliquer de nouveau sur Spice pour ret\u00e9l\u00e9charger un nouveau fichier.
-
Remplir ses identifiants dans la fen\u00eatre de connexion :
- login : eleve
- mdp : donn\u00e9 \u00e0 l'oral
-
Basculer l'affichage en plein \u00e9cran
- Au premier lancement d'un navigateur, remplir ses identifiants Scribe, permettant d'acc\u00e9der \u00e0 internet.
"},{"location":"T7_Divers/3_Thonny/cours/","title":"Thonny","text":"Comme pour tous les langages de programmation, il n'existe pas un logiciel permettant de coder en Python, mais un tr\u00e8s (tr\u00e8s) grand nombre de logiciels diff\u00e9rents, qu'on regroupe sous le nom d'IDE (interfaces de d\u00e9veloppement)
Pour la NSI, nous conseillons Thonny :
"},{"location":"T7_Divers/3_Thonny/cours/#installer-thonny","title":"Installer Thonny","text":" -
Rendez vous sur la page https://thonny.org/
-
T\u00e9l\u00e9chargez et installez la version qui correspond \u00e0 votre syst\u00e8me d'exploitation (Windows, Mac, Linux).
"},{"location":"T7_Divers/3_Thonny/cours/#alternatives","title":"Alternatives","text":"Pyzo, PyCharm, Spyder, VisualStudioCode... impossible de toutes les citer !
"},{"location":"T7_Divers/3_Thonny/cours/#solutions-en-ligne","title":"Solutions en ligne","text":"En ligne, sans aucune installation, vous pouvez utiliser https://console.basthon.fr/
ou bien m\u00eame la console ci-dessous !
>>> ou l'IDE qui suit :
\u25b6\ufe0f \u2935\ufe0f \u2934\ufe0f "},{"location":"T7_Divers/4_Processing/cours/","title":"Processing","text":" Processing est un outil de cr\u00e9ation multim\u00e9dia utilisant le code informatique. Simple de prise en main, il a \u00e9t\u00e9 cr\u00e9\u00e9 par des artistes pour des artistes. On peut utiliser le langage Python pour entrer les instructions.
Nous l'utiliserons pour ajouter du graphisme \u00e0 nos cr\u00e9ations...
Documentation - Le site officiel (anglais)
- Un manuel d'utilisation (fran\u00e7ais)
"},{"location":"T7_Divers/4_Processing/cours/#les-bases-de-processing","title":"Les bases de Processing","text":""},{"location":"T7_Divers/4_Processing/cours/#repere","title":"Rep\u00e8re","text":"\u00c0 l'ex\u00e9cution de tout script Processing, une fen\u00eatre s'affiche avec une zone de dessin. Sa taille se d\u00e9finit \u00e0 l'aide de la fonction size
. Par exemple, pour cr\u00e9er une zone de dessin de 300 pixels sur 200 pixels, on utilisera:
size(300, 200)\n
Chaque pixel de cette zone est rep\u00e9r\u00e9e par des coordonn\u00e9es dans le rep\u00e8re suivant, dont l'origine se situe en haut \u00e0 gauche et l'axe des ordonn\u00e9es est orient\u00e9 vers le bas.
"},{"location":"T7_Divers/4_Processing/cours/#traces","title":"Trac\u00e9s","text":"Trac\u00e9s de base
point
: permet de dessiner un point (pixel). En param\u00e8tre, les coordonn\u00e9es du point. line
: permet de tracer une ligne entre deux points. En param\u00e8tres, les coordonn\u00e9es des deux points. rect
: permet de tracer un rectangle. En param\u00e8tres, les coordonn\u00e9es du sommet haut-gauche, puis la largeur et la hauteur du rectangle. ellipse
: permet de tracer une ellipse. En param\u00e8tres, les coordonn\u00e9es du centre, puis la largeur et la hauteur (mettre la m\u00eame valeur pour un cercle).
Exemples Copier-coller le code suivant et faire varier les param\u00e8tres pour bien les comprendre.
size(200, 200)\npoint(10, 60)\nline(10, 10, 100, 150)\nrect(80, 10, 20, 50)\nellipse(150, 100, 80, 40)\n
"},{"location":"T7_Divers/4_Processing/cours/#couleurs","title":"Couleurs","text":"Pinceau
background
: permet de d\u00e9finir la couleur du fond de la zone de dessin. En param\u00e8tres, les trois composantes RGB de la couleur. stroke
: permet de d\u00e9finir la couleur du pinceau (noir par d\u00e9faut) pour le contour de la forme. En param\u00e8tres, les trois composantes RGB de la couleur. noStroke
: permet de dessiner une forme sans coutour (pas de param\u00e8tre). strokeWeight
: permet de d\u00e9finir la largeur du pinceau. En param\u00e8tre, le nombre de pixel. fill
: permet de d\u00e9finir la couleur de remplissage de la forme. En param\u00e8tres, les trois composantes RGB de la couleur.
Exemples Copier-coller le code suivant et faire varier les param\u00e8tres pour bien les comprendre.
size(200, 200)\nbackground(255, 255, 255)\nstroke(255, 0, 0)\npoint(10, 60)\nline(10, 10, 100, 150)\nstroke(0, 127, 255)\nstrokeWeight(5)\nrect(80, 10, 20, 50)\nnoStroke()\nfill(204, 153, 204)\nellipse(150, 100, 80, 40)\n
"},{"location":"T7_Divers/4_Processing/cours/#exercices","title":"Exercices","text":"Exercice 9
\u00c9crire un programme qui affiche le drapeau fran\u00e7ais, comme ci-contre, dans une zone de 300 x 200 pixels.
Exercice 10
\u00c9crire un programme qui trace un quadrillage (espacement de 20 pixels).
Contrainte: en seulement 3 lignes (sans compter \u00e9ventuellement size
.
Exercice 11
Afficher une croix verte de longueur 50 centr\u00e9e au point (60 ; 40), et un cercle rouge de diam\u00e8tre 30 centr\u00e9 en (150 ; 100). On prendra 10 pixels comme \u00e9paisseur.
Exercice 12
Cr\u00e9ez un programme permettant d\u2019afficher 100 disques \u00e0 l\u2019\u00e9cran. La taille de chaque disque devra \u00eatre al\u00e9atoire (mais comprise entre 20 et 50). La couleur de chaque disque devra aussi \u00eatre al\u00e9atoire.
Avec Processing, il est tr\u00e8s simple d\u2019avoir un nombre al\u00e9atoire : random(a,b)
permet d\u2019obtenir un nombre al\u00e9atoire entre a
et b
.
source - site de C\u00e9dric Gouygou
"},{"location":"T7_Divers/4_Processing_p5/cours/","title":"Processing au lyc\u00e9e \u21d4 p5 sur Capytale","text":""},{"location":"T7_Divers/4_Processing_p5/cours/#1-explication-du-probleme","title":"1. Explication du probl\u00e8me","text":"Pour r\u00e9aliser facilement de jolis graphiques, nous utilisons sur les ordinateurs du lyc\u00e9e le logiciel Processing. Celui-ci permet d'\u00e9crire du code Python et d'avoir un rendu imm\u00e9diat dans une fen\u00eatre s\u00e9par\u00e9e.
Pour le travail \u00e0 la maison, nous utilisons le service Capytale.
Probl\u00e8me, il n'est pas possible d'\u00e9crire du code Processing dans Capytale.
"},{"location":"T7_Divers/4_Processing_p5/cours/#2-une-solution-la-librairie-p5","title":"2. Une solution : la librairie p5","text":"Si Processing n'existe pas dans Capytale, une solution tr\u00e8s similaire est disponible : la librairie p5.
Remarque
La librairie p5
incluse dans Capytale est l\u00e9g\u00e8rement diff\u00e9rente de la libraire p5
utilisable dans Thonny (ou tout autre IDE). En effet, pour pouvoir fonctionner sur Capytale, elle a \u00e9t\u00e9 en partie r\u00e9-\u00e9crite par un des d\u00e9veloppeurs de Capytale, Romain Casati.
"},{"location":"T7_Divers/4_Processing_p5/cours/#3-structure-commune-des-codes-processing-et-p5","title":"3. Structure commune des codes Processing et p5","text":"Les codes Processing que nous avons \u00e9crits jusqu'\u00e0 pr\u00e9sent sont des codes statiques. Mais l'architecture naturelle d'un code Processing ou p5 est en r\u00e9alit\u00e9 articul\u00e9e autour de deux fonctions : la fonction setup()
et la fonction draw()
.
"},{"location":"T7_Divers/4_Processing_p5/cours/#31-la-fonction-setup","title":"3.1 La fonction setup()
","text":"Comme son nom l'indique, elle va proc\u00e9der \u00e0 tous les r\u00e9glages initiaux avant de commencer le dessin : taille de la fen\u00eatre, (\u00e9ventuellement couleur d'arri\u00e8re-plan), autres r\u00e9glages.
Elle n'est ex\u00e9cut\u00e9e qu'une seule fois.
"},{"location":"T7_Divers/4_Processing_p5/cours/#32-la-fonction-draw","title":"3.2 La fonction draw()
","text":"C'est dans cette fonction que toutes les instructions de dessin seront donn\u00e9es.
Tr\u00e8s important : cette fonction est une boucle infinie. Elle est donc r\u00e9p\u00e9t\u00e9e (\u00e0 une certaine cadence qui est r\u00e9glable) jusqu'\u00e0 ce que (par exemple) l'utilisateur ferme la fen\u00eatre.
Des instructions \u00e9crites dans la fonction setup()
peuvent influer sur cette boucle infinie draw()
: notamment l'instruction noLoop()
qui permet de n'ex\u00e9cuter la fonction draw()
qu'une seule fois.
"},{"location":"T7_Divers/4_Processing_p5/cours/#4-passer-dun-code-processing-a-un-code-p5","title":"4. Passer d'un code Processing \u00e0 un code p5","text":""},{"location":"T7_Divers/4_Processing_p5/cours/#41-seulement-en-p5-linstruction-run","title":"4.1 Seulement en p5 : l'instruction run()
","text":"Un code p5 devra forc\u00e9ment se terminer par l'instruction run()
"},{"location":"T7_Divers/4_Processing_p5/cours/#42-une-difference-de-syntaxe-createcanvas-vs-size","title":"4.2 Une diff\u00e9rence de syntaxe : createCanvas()
vs size()
","text":"Pour cr\u00e9er une zone de dessin de 300 pixels sur 300 pixels :
- Processing :
size(300,300)
- p5 :
createCanvas(300,300)
"},{"location":"T7_Divers/4_Processing_p5/cours/#43-cas-particulier-des-dessins-statiques","title":"4.3 Cas particulier des dessins statiques","text":"Nos premiers codes en Processing actuellement sont statiques : ils n'ont pas d'animation. Processing accepte alors que le code ne comporte ni fonction setup()
ni fonction draw()
.
Par contre, pour faire un code statique en p5, il faudra quand m\u00eame que les fonctions setup()
etdraw()
soient pr\u00e9sentes. On indiquera l'instruction noLoop()
dans le setup()
pour que le draw()
ne soit execut\u00e9 qu'une fois.
Exemple de passage d'un code statique en Processing \u00e0 un code statique en p5 :
- en bleu : les instructions \u00e0 rajouter
- en rouge : les instructions \u00e0 modifier (il n'y en a qu'une)
- sur fond jaune : le code \u00e0 conserver
Vous pouvez aussi comparer des codes statiques Processing avec leur \u00e9quivalent en p5 dans la feuille d'exercices sur Processing.
"},{"location":"T7_Divers/5_Capytale/cours/","title":"Utilisation du service Capytale","text":"Capytale est accessible via Lyc\u00e9econnect\u00e9, il faut donc avoir ses identifiants Educonnect.
"},{"location":"T7_Divers/5_Capytale/cours/#activite-test","title":"Activit\u00e9-test :","text":" - Connectez-vous \u00e0 Lyc\u00e9eConnect\u00e9 gr\u00e2ce \u00e0 vos identifiants Educonnect.
- Cliquez sur https://capytale2.ac-paris.fr/web/c/797d-639207
- Dans la liste des ENT, choisir Lyc\u00e9eConnect\u00e9.
- Capytale apparait avec le code de l'activit\u00e9 pr\u00e9-rempli, cliquez sur
Go !
.
"},{"location":"T7_Divers/5_Exposes/cours/","title":"Figures de l'informatique","text":""},{"location":"T7_Divers/5_Exposes/cours/#ada-lovelace","title":"Ada Lovelace","text":""},{"location":"T7_Divers/5_Exposes/cours/#alan-turing","title":"Alan Turing","text":""},{"location":"T7_Divers/5_Exposes/cours/#donald-knuth","title":"Donald Knuth","text":""},{"location":"T7_Divers/5_Exposes/cours/#bill-gates","title":"Bill Gates","text":""},{"location":"T7_Divers/5_Exposes/cours/#heidi-lamar","title":"Heidi Lamar","text":""},{"location":"T7_Divers/5_Exposes/cours/#steve-jobs","title":"Steve Jobs","text":""},{"location":"T7_Divers/5_Exposes/cours/#aaron-swartz","title":"Aaron Swartz","text":""},{"location":"T7_Divers/5_Exposes/cours/#grace-hopper","title":"Grace Hopper","text":""},{"location":"T7_Divers/5_Exposes/cours/#linus-torvalds","title":"Linus Torvalds","text":""},{"location":"T7_Divers/5_Exposes/cours/#margaret-hamilton","title":"Margaret Hamilton","text":""},{"location":"T7_Divers/5_Exposes/cours/#serguei-brin","title":"Sergue\u00ef Brin","text":""},{"location":"T7_Divers/5_Exposes/cours/#larry-page","title":"Larry Page","text":""},{"location":"T7_Divers/5_Exposes/cours/#richard-stallman","title":"Richard Stallman","text":""},{"location":"T7_Divers/5_Exposes/cours/#guido-van-rossum","title":"Guido Van Rossum","text":""},{"location":"T7_Divers/5_Exposes/cours/#dennis-ritchie","title":"Dennis Ritchie","text":""},{"location":"T7_Divers/5_Exposes/cours/#john-conway","title":"John Conway","text":""},{"location":"T8_DS/DS01/","title":"DS01","text":"Exercice 1
\u00c9nonc\u00e9Correction - \u00c9crire ci-dessous les instructions afin que les valeurs respectives de
p
et de q
soient \u00e9chang\u00e9es :
>>> p = 3\n>>> q = 7\n>>>\n>>>\n>>>\n
2. Proposer une autre m\u00e9thode plus rapide \u00e0 \u00e9crire : >>> p = 3\n>>> q = 7\n>>>\n
>>> p = 3\n>>> q = 7\n>>> temp = p\n>>> p = q\n>>> q = temp\n
2.
>>> p = 3\n>>> q = 7\n>>> p, q = q, p\n
Exercice 2
\u00c9nonc\u00e9Correction - \u00c9crire ci-dessous les instructions afin que la variable
score
soit augment\u00e9e de 20: >>> score = 0\n>>> \n
- Proposer une deuxi\u00e8me instruction \u00e9quivalente :
>>> score = 0\n>>> \n
1.
>>> score = 0\n>>> score = score + 20\n
2. >>> score = 0\n>>> score += 20\n
Exercice 3
\u00c9nonc\u00e9Correction Je souhaite coder un jeu. Je vais stocker dans une variable la largeur de l'\u00e9cran (qui vaudra 640 pixels par d\u00e9faut) et dans une autre variable la hauteur de l'\u00e9cran (qui vaudra 400 pixels par d\u00e9faut).
\u00c9crire ce que peuvent \u00eatre les deux premi\u00e8res lignes de mon code :
1 \n2 \n
largeur_ecran = 640\nhauteur_ecran = 400\n
Exercice 4
\u00c9nonc\u00e9Correction On consid\u00e8re le programme suivant :
for lettre in \"LUNDI\":\n print(lettre)\n
\u00c9crire ci-dessous ce qui s'affiche en console lors de l'ex\u00e9cution de ce programme. \n
L\nU\nN\nD\nI\n
Exercice 5
\u00c9nonc\u00e9Correction On consid\u00e8re le programme suivant :
liste_langages = ['Python', 'C++', 'SmallTalk']\nfor langage in liste_langages:\n print(langage, \"est un langage orient\u00e9-objet\")\n
\u00c9crire ci-dessous ce qui s'affiche en console lors de l'ex\u00e9cution de ce programme.
\n
Python est un langage orient\u00e9-objet\nC++ est un langage orient\u00e9-objet\nSmallTalk est un langage orient\u00e9-objet\n
Exercice 6
\u00c9nonc\u00e9Correction Proposer un code pour \u00e9crire (intelligemment) les lignes suivantes :
Voici le verdict du Choixpeau Magique :\nHarry sera \u00e0 Griffondor\nHermione sera \u00e0 Griffondor\nRon sera \u00e0 Griffondor\n
\n
print('Voici le verdict du Choixpeau Magique :')\npersonnages = ['Harry', 'Hermione', 'Ron']\nfor nom in personnages:\n print(nom, 'sera \u00e0 Griffondor')\n
"},{"location":"T8_DS/DS03/","title":"DS03","text":"correction sur Capytale.
"},{"location":"T8_Liens_utiles/liens/","title":"Liens utiles","text":""},{"location":"T8_Liens_utiles/liens/#a-propos-de-la-specialite-nsi","title":"\u00c0 propos de la sp\u00e9cialit\u00e9 NSI","text":" - Le site Eduscol
"},{"location":"T8_Liens_utiles/liens/#pour-resoudre-des-enigmes","title":"Pour r\u00e9soudre des \u00e9nigmes","text":"Quelques sites de challenges/\u00e9nigmes/d\u00e9fis de programmation:
- PyD\u00e9fis
- Hackinscience
- Advent of Code
- MicroContest
"},{"location":"T8_Liens_utiles/liens/#a-propos-de-la-culture-des-sciences-de-linformatique","title":"\u00c0 propos de la culture des sciences de l'informatique","text":" -
Interstices
-
Inria
"},{"location":"T8_Liens_utiles/liens/#pour-se-former-en-autonomie","title":"Pour se former en autonomie","text":"Au cas o\u00f9 vous vous ennuieriez...
- France-IOI
- CheckIO
- CodinGame
source - site de C\u00e9dric Gouygou
"}]}
\ No newline at end of file