Sous-sections de allophysique

Python - les bases

Les bases en Python

Le parcours d'apprentissage qui est proposé ici s'articule sur 5 chapitres:

  • C1 Calculer avec le langage Python
  • C2 Variables et opérations sur ces variables
  • C3 Boucles (bornées) et listes
  • C4 Structures conditionnelles et boucles non bornées
  • C5 Fonctions
Ces chapitres seront être approfondis dans la section Python avancé.

  • Les types de base: numériques, string, booléens En python, les objets natifs de base ont pour type: nombre entier: integer ou int en Python nombre réel décimal: float chaine de caractères: str les valeurs logiques: booléen bool Lorsque l’on présente une valeur dans le programme, le langage s’adapte selon le type, comme on le verra plus loin.
  • cours sur les boucles, bornées et non bornées, notion d’itérable, fonctions natives
  • cours, parcours de liste, méthodes de liste, boucles bornées, tracé de graphique
  • cours et exercices sur les fonctions, paramètres
  • Python est-il déjà installé? Verifier si Python est installé sur votre ordinateur: Vous pouvez vérifier cela en ouvrant l’invite de commandes et en tapant: python –version Windows: Télécharger le fichier d’installation depuis le site officiel de Python. Lancer l’executable et cocher “Add Python to PATH”. Puis cliquer sur Install now Linux: Python peut être installé et géré via un gestionnaire de paquets comme apt, yum.
  • Le module Turtle permet d’avoir un environnement simple muni d’une interface graphique. La page suivante présente un aide-mémoire avec les principales instructions. Il est conseillé d’avoir bien lu et traité les exemples des pages: TP boucles et fonctions Cours sur les fonctions Premiers tracés Script initial Ces exemples utilisent une boucle bornée pour répéter des consignes (for .. in range)

Sous-sections de Bases en python

introduction aux variables

Introduction: le rôle clé des variables

Les exemples suivants montrent le rôle crucial des variables dans les algorithmes…

Compteur de passages

Un dispositif numérique, équipé d’un capteur, compteur le nombre de passage par une porte.

detecteur de passage à capteur infra rouge

detecteur de passage à capteur infra rouge

L’algorithme utilisé comporte 3 parties:

  • initialisation de la variable
  • boucle avec condition d’execution
  • modification de la variable

Il utilise la fonction: coupure_faisceau

Et la variable: i nombre de passages detectés

i = 0
repeter indefiniment:
  {
  si coupure_faisceau_lumiere():
    {
    i = i + 1
    fin si
    }
  fin repeter
  }

Point neutre Terre-Lune

Dans l’un de ses célèbres romans intitulé De la Terre à la Lune, Jules Verne (1828-1905) relate les aventures de trois héros ayant pris place à l’intérieur d’un énorme projectile qu’un gigantesque canon, baptisé Colombiad, propulse en direction de la Lune. Lors de ce périple, Jules Verne fait allusion à un point neutre, situé à une distance d = 350 000 km du centre de la Terre où les forces gravitationnelles exercées par la Terre et la Lune sur le projectile se compensent.

point neutre sur la droite Terre-Lune

point neutre sur la droite Terre-Lune

L’algorithme utilisé comporte 3 parties:

  • phase d’initialisation de la variable
  • boucle avec condition d’execution
  • modification de la variable

Il utilise les fonctions: F1 force de gravitation de la Terre, F2 force de gravitation de la Lune

Et la variable: d distance à la surface de la Terre

d = 0
repeter tant que F1 (d) > F2(d):
  {
  d = d + 1
  fin repeter
  }
afficher d

calculer en python

Les types de base: numériques, string, booléens

En python, les objets natifs de base ont pour type:

  • nombre entier: integer ou int en Python
  • nombre réel décimal: float
  • chaine de caractères: str
  • les valeurs logiques: booléen bool

Lorsque l’on présente une valeur dans le programme, le langage s’adapte selon le type, comme on le verra plus loin.

Pour vérifier le type d’un objet, on utilise la fonction type

Exemples

> type(12)
int
> type(12.0)
float
> type('12')
str
> type(True)
bool

Pour changer le type, on utilise les fonctions int, float, str. On utilise par exemple int lorsque l’on veut transformer un float ou un str en un entier:

> int('12')
12
> str(12)
'12'
> float(12)
12.0

Les nombres entiers et décimaux

Entier

Un entier: type int (ou integer). C’est un nombre qui n’a pas de point décimal. Les algorithmes utilisent en général des entiers, ce qui est avantageux pour les opérations de comparaison comme == ou !=.

valeurs possibles: 1, 2492042932330932, -23,...

Certaines opérations retournent un résultat de type entier:

expressions possibles: 13+3928, 34*2+10//3, 12%5, 2**8, ...

Un entier peut avoir une valeur aussi grande que celle que la machine peut stocker. Pour un nombre entier non signé, stocké sur 32 bits, cette valeur maximale vaut $2^{32}-1$

un nombre entier négatif: type int s’écrit avec un $-$ devant: $-10$ par exemple. Les entiers signés, codés sur 32 bits ont des valeurs qui s’étendent entre $[-2^{31},2^{31}-1]$

Décimal

un nombre décimal: type float s’écrit avec un point comme séparateur, comme par exemple: 6.02

valeurs possibles: 1.0, 249204.2932330932, -23.47,...

Les nombres exprimés avec l’opérateur e (puissance de 10), sont aussi des float, des décimaux:

> a = 12e3 # a vaut 12000
> print(a)
12000.0
> type(a)
float

La division de 2 nombres avec l’opérateur $/$ retourne toujours un type float, même avec des entiers:

> 20/8
2.5
> 20/10
2.0

Les float en Python ont une précision limitée. Ils sont généralement codés sur 15 chiffres significatifs et encodés sur 53 bits. Cela génère des imprecisions comme par exemple:

> 0.3/0.1
2.9999999999999996

Chaine de caractère

C’est une séquence constituée d’un ou plusieurs caractères, entourés de guillemets simples ou doubles.

Notez que des chiffres mis entre guillemets sont des chaines de caractères et ne peuvent pas être manipulés comme des nombres (voir plus loin).

Exemples

"Bonjour"
'Hello'
"18"
"Un longue chaine de caractères"
'une autre chaine'

caractères spéciaux

Certains caractères spéciaux ne sont pas affichés, mais permettent la mise en forme:

  • Par exemple, le caractère \n génère un retour à la ligne:
> citation_python = 'je disais, "être ou ne pas être,\ntelle est la question"'
> print(citation_python)
# affiche
être ou ne pas être,
telle est la question

addition de chaines

L’addition de chaines* (concaténation) se fait avec l’opérateur +

> print("Bonjour"+"Hello")
BonjourHello
  • L’opérateur * permet des répétitions multiples:
> print('Hi'*3)
HiHiHi
  • Ou bien avec des accolades {} dans une expression formatée. Exemples:
# Exemple 1 avec .format
m = 100
Ec = 1200
resultat = "Pour le systeme m = {} et E = {}".format(m,Ec)
print(resultat)
# affiche
# Pour le systeme m = 100 et E = 1200
# Exemple 2 avec un f-string
m = 100
Ec = 1200
resultat = f"Pour le systeme m = {m} et E = {Ec}"
print(resultat)
# affiche
# Pour le systeme m = 100 et E = 1200

L’exemple 2 illustre une chaine particulière appelée f-string. C’est une chaine:

  • préfixée par un f
  • suivie par une chaine entre guillemets "" ou ''
  • contenant des accolades {}
  • où tout texte placé entre accolades sera remplacé par la valeur de la variable correspondante.

Test d’appartenance

L’opérateur in permet de tester si une suite de caractères se trouve dans un chaine:

  • "ou" in "jour" vaut True
  • "ou" not in "jour" vaut False

Ordre lexicographique

On peut comparer les caractères ou les mots à partir de leur rang dans l’alphabet:

'A' > 'B'
# Affiche False
'A' < 'B'
# Affiche True
'sauver'>'sauveur'
# Affiche False

Les valeurs logiques

Ce sont les valeurs True et False.

opérations avec not, and et or

On peut les combiner dans des formules logiques avec les opérateurs not, and, or:

> True and False
False
> True or False
True

opérateurs de comparaison

Une opération de comparaison, utilisant les signes ==, !=, >, >=, <, <= retourne un booléen True ou False:

> 0 == 0
True
> 0 == 1
False
> 0 != 1
True

Expressions possibles: 0 == 0, 8+1 == 2 * 3, 13 >= 1, 'A'<'B', 'a'>'c', 'Sol' in 'Soleil', ...

Utiliser les opérations booléennes dans un programme

Le booléen permet un branchement dans un algorithme (voir les structures conditionnelles). Exemples:

if True:
  # instruction 1
else:
  # instruction 2

# execution du bloc d'instruction 1

if False:
  # instruction 1
else:
  # instruction 2

# execution du bloc d'instruction 2

if 10 > 1:
  # instruction 1
else:
  # instruction 2

# execution du bloc d'instruction 1

On peut souhaiter executer infiniment le même bloc d’instructions, avec l’instruction `while:

while True:
  # bloc d'instructions

Changer de type avec la fonction bool

Lors de la transformation de type avec bool ou int, le True correspond à un 1 et le False à un 0:

> bool(1)
True
> bool(0)
False
> int(True)
1
> int(False)
0

Les opérations de base

1. Un langage informatique permet de réaliser des opérations sur des valeurs. L’écriture de ces opérations peut différer de ce que l’on écrit avec la calculatrice. Voici la liste des opérateurs en Python:

opérateur rôle équivalent sur une calculatrice
+ addition $1 + 99$
- soustraction $99 - 1$
* multiplication $10 \times 10$
/ division $\tfrac{1}{3}$
// division entière pas d’équivalent
% reste de la division pas d’équivalent
** exposant $2^{4}$
e puissance de 10 (pour l’écriture en notation scientifique) $1.2E-3$ ou $1.2\times 10^{-3}$

2. Ces opérateurs peuvent aussi être appliqués sur des chaines de caractères.

opérateur rôle exemple
+ concaténation (ajoute les chaines de caractères) "Aïe" + "Aïe" + "Aïe"
* multiplication (ajoute plusieurs fois la même chaine, bout à bout "Aïe" * 3

3. Un nombre ne peut pas être ajouté à une chaine de caractères:

10 + "x"
# retourne
...
TypeError: unsupported operand type(s) for +: 'int' and 'str' )

4. Opérations logiques Une opération logique consiste à comparer 2 valeurs et tester si celles-ci sont égales, ou s’il y a une relation d’ordre entre elles. Le résultat d’une opération logique ne peut être que True ou False:

opérateur pour tester…
== l’égalité
!= l’inégalité (est différent de) !
> l’ordre supérieur
< l’ordre inférieur
>= l’ordre supérieur ou égal
<= l’ordre inférieur ou égal

ainsi, pour tester l’égalité entre 3 et 1+2, on peut écrire en python:

3 == 1+2
# retourne 
True
3 == 1+1
# retourne
False
3 > 1+1
# retourne 
True

Remarque: Le test de l’égalité n’est pas adapté pour les nombres réels. Seulement pour les nombres entiers. Ainsi, en Python, l’opération 0.1*3 == 0.3 renvoie … False!

Calcul sur des valeur entières

Les programmes informatiques préfèrent utiliser des valeurs entières pour les calculs, même si les calculs avec nombres à virgules sont possibles. Pour cette raison, les opérateurs // et % sont souvent utilisés en combinaison.

  • Rappel: La division euclidienne de a par b est définie comme ceci: a est égal au quotient de a//b multiplié par le diviseur b, augmenté du reste a%b:
$$a = (a//b)*b + a%b$$
  • Usages classiques:
    • n%2 vaut 0 si n est pair
    • n%2 vaut 1 si n est impair
    • n%10 conserve les unités
    • n//10 conserve les dizaines et supprime les unités.

travaux pratiques

TP1 Calculer en python

Liens

variables, opérations

Variables

1. Definition: Une variable sert à stocker une valeur, qui peut être un nombre, une chaine de caractère, ou autres. Une variable est identifiée par un nom, et pointe vers un espace mémoire.

affectation variable

VARIABLE = espace de STOCKAGE

Une variable est donc une zone précise de la mémoire vive de l’ordinateur (on parle d’adresse mémoire). À partir de cet emplacement, on trouvera une succession de bits dont l’agencement spécifique déterminera à la fois une valeur et un type.

2. Quel nom peut-on choisir pour une variable?: On peut choisir une lettre simple, minuscule ou majuscule, ou une chaine de caractères SANS espaces, et commençant obligatoirement par une LETTRE. Le nom peut contenir certains caractères spéciaux comme par exemple _. (ne pas utiliser le signe -, utilisé pour une soustraction entre 2 variables).

Exemples de noms de variables:

  • x
  • y
  • a
  • B
  • longueur_L1
  • nom
  • age
  • personne3
  • Score
  • Points_de_vie
  • …

L’idée est de choisir un nom assez explicite, et d’éviter d’utiliser trop souvent x, y, a, b, c, …

3. Affectation On affecte une valeur à une variable en utilisant l’opérateur =.

Par exemple, pour affecter la valeur 5 à la variable x, on fait:

x = 5

Pour vérifier la valeur d’une variable, il suffit d’écrire celle-ci:

  • soit toute seule dans une cellule du notebook
x
# retourne 
5
  • soit à la dernière ligne de la cellule du notebook:
x = 5
# retourne 
5
  • Soit avec la fonction print (ne pas mettre de guillemets)
x=5
print(x)
# retourne 
5

On peut modifier la valeur d’une variable existante. On peut méme lui affecter le résultat d’une opération:

x = 12/2
x
# retourne
6.0
# remarquer ici que la division simple retourne un float

Et utiliser la valeur de cette même variable pour l’opération:

x = 6
x = x + 1
x
# retourne
7

Affectation multiple: On peut affecter une valeur à plusieurs variables en une seule ligne, ce qui amèliore la lecture d’un script:

a = 1
b = 2

peut être remplacé par:

a, b = 1, 2

4. Opérations sur les variables Une variable a un TYPE qui est défini lors de l’affectation. Python s’adapte lorsque vous faites une affectation et choisit le type correspondant.

Pour démarrer, nous verrons les TYPES str (chaine de caractère), int (nombre entier) et float (nombre décimal, en virgule flottante).

Les opérations possibles sur une variable dépendent de son type.

  • Pour les variables de type nombre int et float, on peut utiliser les opérateurs +,-,*,/,**,//,%
  • Pour les variables de type str on peut aussi utiliser les opérateurs +,* mais le résultat est différent (opérateurs de concaténation).

Lorsque l’on modifie une variable, on affecte à nouveau à la variable le résultat de l’opération:

x = 6
x = x + 8
# x+8 vaut 14 que l'on affecte a nouveau a x
print(x)
# affiche 14

Opérateur d’affectation composée. L’instruction x = x + 8 peut être simplifiée en x += 8.

L’opérateur += réalise l’opération et l’affectation à la même varaible, x:

x = 6
x += 8
# x+8 vaut 14 que l'on affecte a nouveau a x
print(x)
# affiche 14

Il existe d’autres opérateurs d’affectation composée: -=, *=, /=.

Exemple:

x=6
x /= 2
x
# affiche 3.0

5. Variables et paramètres d’une fonction Les variables déclarées avec la fonction, entre parenthèse sont appelées paramètres. Le schéma suivant illustre l’affectation des valeurs des variables a = x et b = y lors de l’appel de la fonction additionne(x, y):

Visualiseur python

Le site pythontutor permet de visualiser le contenu des variables et leur espace de nom.

exemple 1: un espace mémoire pour chaque variable

x = 10
y = 14
x = x + 2
print(x)
exemple de représentation avec 2 variables x et y dans le main

exemple de représentation avec 2 variables x et y dans le main

Cliquer sur l’image pour lancer l’app pythontutor. Cliquer sur next pour dérouler le script pas à pas.

exemple 2: un espace mémoire pour les variables et pour les fonctions

x = 10
y = 14

# creation de la fonction avec le mot clé def
def additionne(a,b):
  return a + b

# appel de la fonction avec a = 10 et b = 14
> additionne(x,y)
24
exemple avec appel d'une fonction

exemple avec appel d'une fonction

Cliquer sur l’image pour lancer l’app pythontutor. Cliquer sur next pour dérouler le script pas à pas.

Travaux pratiques

TP2 Variables

Liens

Ce chapitre comporte 3 pages:

  • Cours sur les structures conditionnelles: Lien
  • TP3a, conditions, boucle while: Lien
  • TP3b, algorithmes utilisant boucle while et structures conditionnelles: Lien

Structures conditionnelles simples et avec alternative

Conditions

1. Définition : Une instruction conditionnelle vérifie si une certaine condition est vraie avant d’executer son code :

if instruction_conditionnelle : 
  code_à_executer

Exemple :

if prix_essence > 1.8:
  print('Trop cher')

Remarquer que l’instruction if .. condition ..: finit par 2 points :, et que la ligne suivante est indentée

Toute portion de code associée à une structure de contrôle (finissant par 2 points :) nécéssite une indentation.

2. Les blocs du programme En Python, on utilise l’indentation (le retrait de la ligne) pour rendre compte des blocs de code.

pybloc et indentation

de pybloc au script python

Le bloc de code à executer peut contenir plusieurs lignes, à condition de respecter l’indentation. (2 ou 4 espaces, ou touche TAB).

3. L’alternative if - else Une instruction if - else contient une instruction if qui s’execute si la condition est True et une clause else qui s’execute si la condition est False.

if hauteur_plant < 3 : 
  print('laisser le plant dans la serre')
else : 
  print('le mettre dehors')

4. Conditions multiples if - elif - else Un bloc if - elif - else comprend une premiere instruction if, puis une suite de conditions de tests elif si le premier test echoue, puis un bloc else qui s’execute si tous les autres tests échouent.

Même s’il n’est pas obligatoire, il est fortement recommandé de finir une série de conditions elif par le bloc else.

if hauteur_plant < 3 : 
  print('laisser le plant dans la serre')
elif hauteur_plant < 10 : 
  print('le sortir le jour')
elif hauteur_plant < 15 : 
  print('le mettre dehors')
else : 
  print('Pret pour la recolte')

Rappelez vous:

  • elif est toujours suivi d’une condition
  • else n’est pas suivi d’une condition. C’est l’alternative, dont le bloc est executé lorsqu’aucune des conditions precedentes n’est vraie.

Tests logiques

Il s’agit d’une expression booléenne qui est évaluée est qui renvoie True si elle est vrai, False sinon.

Opérateurs de comparaison

Quelques exemples de tests logiques :

age == 18   # egalité
age != 18   # inegalité
age <= 18   # inferieur ou egal
nom == 'John' # egalité de chaines

Opérateurs et combinaisons logiques

L’expression peut aussi contenir les opérateurs logiques de combinaisons: and, or, not.

L’expression suivante, A and B est evaluée à True si A vaut True, et B vaut True. Dans tous les autres cas, (A vaut False, ou B vaut False, ou A et B valent False), A and B est evaluée à False. On peut résumer tous les cas dans une table logique:

A B A and B
False False False
False True False
True False False
True True True

Pour l’opérateur logique or:

A B A or B
False False False
False True True
True False True
True True True

et pour l’opérateur not

A not A
False True
True False

Exemple:

n = int(input('entrer un nombre entier: '))
if n%2 == 0 and n > 0:
    print('vous avez entré un entier pair et positif')

Une instruction if peut également tester une valeur booléenne et exécuter son code si cette valeur vaut True, comme par exemple, ci-dessous, avec if jeu_actif:

Il n’est pas nécéssaire d’écrire == True comme ici avec if jeu_actif == True:

if jeu_actif : 
  print('jouons !')

Test sur une liste

On peut aussi vérifier si un élement existe dans une liste :

capitales = ['Paris', 'Berlin', 'Rome', 'Londres', 'Madrid']
'Paris' in capitales  
# retourne
# True car 'Paris' est dans la liste capitales

Test sur un dictionnaire

Le mot-clé in permet de tester si une clé est présente dans le dictonnaire:

dico = {'cle1':'val1','cle2':'val2','cle3':'val3'}

print('cle1' in dico)
# affiche True

print('val1' in dico)
# affiche False car `'val1'` est une valeur et non une clé.

Remarque : 0 et None

Dans le test logique, 0 et None se comportent comme s’il s’agissait de False:

ch = input('Entrez un nombre entier quelconque')
n =eval(ch)
if n:
 print("vrai")
else:
 print("faux")

Ce petit script, lorsqu’il est executé, renvoie toujours True quel que soit le nombre saisi, mais False dans les cas suivants. Si on saisit

  • 0 # zero
  • None # le type Rien

A savoir: dans certains cas, on peut faire l’économie de l’opérateur logique. Dans l’instruction conditionnelle if n, la condition vaut True dès que n est différent de 0 ou de None, ou bien n vaut True.

Ainsi, les scripts suivants sont équivalents

# script 1
# sortir = True ou bien sortir = False
if sortir:
  print('Vous pouvez sortir')

if sortir==True:
  print('Vous pouvez sortir')
# script 2
# n est un entier
if n != 0:
  print('n est different de 0')

if n:
  print('n est different de 0')

Boucles non bornées: while

1. Definition: Une boucle non bornée permet de répéter un élément de code un nombre à priori inconnu de fois.

On écrit l’instruction: while <condition d execution>:

Le bloc de code est indenté sous cette première ligne:

while <condition d execution>:
  instruction 1
  instruction 2
instruction suivante # suite du programme

Cette boucle repète l’execution d’un bloc de code (instruction 1, instruction 2), tant que la <condition> est evaluée à True. Le test sur la <condition> est réalisé à chaque itération.

Lorsque cette <condition> n’est plus réalisée, le programme passe à l’instruction suivante.

Souvent, il sera nécessaire de démarrer le programme par initier une variable (celle utile pour la condition d’execution). De sorte que cette condition d’execution soit évaluée à True, et que le bloc de cette boucel s’execute au moins une fois.

Exemple 1: Réaliser un compteur

print("Jeu du cache-cache: compte jusqu'à 10")
i = 1
while i <= 10:
  print(i)
  i = i + 1
print("c'est fini, j'arrive")
  • à la première itération, i vaut 0, donc la condition i <= 10 est évaluée à True et le bloc est executé. Le programme affiche 1 et i finit avec la valeur 2 (i = i + 1)
  • La boucle se poursuit jusqu’à ce que i soit égal à 11. Alors i <= 10 est évaluée à False et le programme poursuit APRES la boucle, avec la dernière instruction: affiche "c'est fini"

Exemple 2: reste de la division euclidienne de 40 par 3

r = 40
while r >= 3:
  r = r - 3
print('à la fin du programme, r vaut ' + str(r))
  • A la première itération, r vaut 40 donc la <condition> r > 3 est True. r est diminué de 3 et prend la valeur 37.
  • A la dernière itération, 4 >= 3 est evalué à True. r est diminué de 3 et prend la valeur 1
  • Puis r >= 3 est evalué à False. Le bloc n’est pas executé et le programme s’arrête s’il n’y a pas d’autres instructions (ou poursuit le script sinon).

2. Le problème de l’arrêt Pour le script précédent, si l’on avait remplacé la condition r >= 3 par r == 3 le programme aurait pu executer le bloc r = r - 3 indefiniment. r aurait pris successivement les valeurs 40, 37, … 4, 1, -2, -5, … etc, sans jamais prendre la valeur 0.

C’est le problème avec les boucles non bornées. Celles-ci peuvent ne pas finir, ce qui peut bloquer la machine.

Cet effet de boucle infini peut être recherché, par exemple en robotique, où l’on veut que le programme se poursuive indéfiniment. Ainsi, la structure d’un programme python sur carte microbit commence par la structure suivante:

from microbit import *

while True:
  # instructions
  # ...

Mais dans le cas général, il faudra veiller à ce que la boucle finisse à un moment donné. Par exemple, dans le script suivant, on met l’instruction break qui a pour effet d’interrompre la boucle lorsque break est executée :

while True : # boucle qui à priori ne finit jamais
  nom = input('Quel est votre nom ?')
  if nom == 'quitter':
    break
  print('Bonjour, {}'.format(nom))
print('sortie de la boucle')

Exemple:

Quel est votre nom ? John
Bonjour, John!
Quel est votre nom ? quitter
sortie de la boucle

Suite

Cours
TP3a conditions
TP3b conditions et algorithmes

Boucles bornées en Python

Definition

Une boucle bornée est un système d’instructions qui permet de répéter un certain nombre de fois toute une série d’opérations.

La syntaxe d’une boucle bornée, en langage algorithmique peut s’écrire:

Pour i allant de 0 a n-1
Faire:
   instruction 1
   instruction 2
FinPour

En python, la syntaxe correspondante est:

for i in range(n):
  instruction 1
  instruction 2

On peut représenter ce script avec des modules à assembler type scratch ou blocky):

analogie avec des briques de construction du programme

analogie avec des briques de construction du programme

Remarque

Construction de la boucle bornée

  • Le bloc d’instruction sera executé n fois. Celui-ci peut contenir une ou plusieurs instructions, du moment qu’elles sont bien positionnées dans le bloc.
  • En Python, le bloc est identifié par une indentation: un retrait par rapport au bord gauche, comprenant 2 espaces (ou 4).
  • Pour sortir du bloc, on élimine l’indentation (on revient sur le bord gauche)
bloc de retour à la fin de la boucle

bloc de retour à la fin de la boucle

  • La fonction range(n) renvoie la liste des entiers de 0 à n-1. C’est un principe général en informatique, on commence toujours à compter à partir de 0, et il faut donc s’arrêter à n-1 pour effectuer n fois la boucle.
  • Pour chaque itération, le variant i prend une nouvelle valeur de l’ensemble {0,1,2,... n-1}, et peut être utilisé dans le bloc d’instructions.
  • On peut choisir n’importe quel nom pour le variant, pas seulement i.
  • Contrairement à la boucle non bornée while, le programmeur ne s’occupe pas de faire varier i à chaque itération. Cela ce fait tout seul.

Exemple:

for i in range(2):
    print(i)
# affiche
0
1

La boucle est executée 2 fois, et affiche 0 puis 1. Pas 2.

Boucle bornée et séquence

L’instruction utilisant le mot-clé for suit la construction suivante:

for variant in iterable:
    # bloc de code à repeter

Ce que l’on appelle iterable, c’est un ensemble de valeurs que prend successivement le variant.

iterable = range(5)

Dans ce premier cas, le variant prend successivement le valeurs de l’ensemble {0,1,2,3,4}. Le variant vaut 0 lors le premiere itération, puis 1 à la deuxieme, etc …

for i in range(5):
    print(i)
# affiche
0
1
2
3
4

A tester vous-même (python): Exemple 1: utiliser la fonction range

iterable = "abc"

Dans ce deuxieme cas, le variant i prend successivement le valeurs de l’ensemble {"a","b","c"}. Le variant vaut “a” lors le premiere itération, puis “b” à la deuxieme, etc …

for i in "abc":
    print(i)
# affiche
"a"
"b"
"c"

A tester vous-même (python): Exemple 2: utiliser une séquence de type str

iterable = [1998,2018]

Les listes en python sont des sequences qui placent les valeurs entre crochets [...]. Les valeurs sont séparées par des virgules ,

L = [1998, 2018]

for annee in L:
    print('La France a gagné la coupe du monde en ', annee)

A tester vous-même (python): Exemple 3: utiliser une séquence de type list

le variant annee prend successivement le valeurs de l’ensemble {1998,2018}

On peut placer autant de valeurs que l’on souhaite dans une liste.

Boucle bornée et non bornée

Pour la boucle bornée for, il n’est pas necessaire d’ajouter une instruction dans le bloc pour que le variant change de valeur à chaque itération. Cela se fait tout seul, à chaque fois que le programme revient sur l’instruction for.

modification du variant i à chaque itération

modification du variant i à chaque itération

Exemples

Exemple 1: afficher le variant de boucle i

# Boucle bornée
for i in range(3):
  print(i)
# affiche
0
1
2

Remarque: la fonction range(3) va créer une liste itérable constituée des valeurs 0, 1, 2. Ce sont les valeurs prises successivement par le variant i dans for i in range(3)

Voici le programme équivalent, utilisant une boucle NON BORNEE while:

# Boucle non bornée
i = 0
while i<3:
    print(i)
    i = i + 1
# affiche
0
1
2

Remarque: Avec une boucle non bornée, il faut:

  • déclarer la valeur initiale du variant: i = 0
  • écrire la condition d’execution après le while, i<3
  • faire varier le variant dans la boucle while, i = i+1

Exemple 2: Ce variant peut être utilisé pour une formule mathématique, à l’intérieur de la boucle:

# boucle bornée
for i in range(3):
  x = i*7
  print(x)
# affiche la table de 7
0
7
14
# boucle non bornée
i = 0
while i < 3:
  x = i*7
  print(x)
  i = i + 1
# affiche la table de 7
0
7
14

Suite

Cours
TP3 Boucles bornées et non bornées

listes

Chaines de caractères, Listes et Boucles bornées

Chaines de caractères

1. Definition: Une chaine de caractère est une séquence ordonnée de caractères, mis entre guillements (simples ' ou doubles "). C’est le type str en python. Pour en savoir plus sur les chaines, on pourra consulter la page: google dev: chaines

On accède à un élément d’une chaine grace à sa position, appelée indice. Le premier élément a pour indice zero.

> voyelles = 'eio'
> voyelles[0]
e
> voyelles[1]
i
> voyelle[2]
o
> voyelles[-1]
o # le dernier element de la liste
> voyelles
'eio'

Un indice négatif permet d’identifier les éléments à partir de la fin: -1 pour le dernier caractère, -2 pour l’avant dernier, …

Illustration avec la chaine de caractères Hello:

exemple avec les rangs des caractères du mot Hello

exemple avec les rangs des caractères du mot Hello

2. Modifier une chaine Contrairement aux listes, il n’est pas possible de modifier un caractère dans une chaine:

> voyelles = 'eio'
> voyelles[2] = 'y'
TypeError: 'str' object does not support item assignment

3. Une fonction utile aux chaines: len La fonction len va retourner la longueur de la chaine de caractères.

> chaine = 'abc'
> len(chaine)
3

Listes

1. Definition: Une liste est une collection ordonnée d’objets. Une liste est entourée de crochets [ ]. C’est le type list en python. Pour en savoir plus sur les listes, on pourra consulter la page: google dev: listes

On accède à un élément d’une liste grace à sa position, appelée indice. Le premier élément a pour indice zero.

La liste `voyelles` est une collection contenant les caractères

La liste `voyelles` est une collection contenant les caractères

Un indice négatif donne accès à la liste à partir du dernier élément.

voyelles = ['e','i','o']
voyelles[0]
# affiche e
voyelles[1]
# affiche i
voyelle[2]
# affiche o
voyelles[-1]
# affiche o
voyelles
# affiche ['e','i','o']

2. Modifier les éléments d’une liste On ne peut modifier un élément d’une liste que si celui-ci existe. Par exemple, si l’on veut modifier l’élément “e” au rang zero de la liste voyelles par un “a”, il faut faire:

voyelles = ['e','i','o']
voyelles[0] = "a"
voyelles
# affiche ["a","i","o"]

Par contre, la liste ne contenant que 3 éléments, du rang 0 au rang 2, on ne peut pas ajouter l’élément “u” de la manière suivante:

voyelles[3] = "u"
# affiche
IndexError: list assignment index out of range

Mais alors, quelle est la bonne méthode pour ajouter un élément à une liste?

Pour ajouter un élément à une liste, il faut utiliser une méthode de liste: la méthode append

voyelles = ['e','i','o']
voyelles.append("u")
voyelles
# affiche ["e","i","o","u"]

L’écriture de la méthode append se fait avec une notation pointée: liste.append(x), où x est la valeur à ajouter à la fin de liste.

**On peut aussi utiliser l’opérateur +, mais il doit être suivi d’une autre Liste:

L = ['a','b','c']
L = L + ['d']
print(L)
# affiche ['a','b','c','d']
T = ['a','b','c']
T = T + 'd'
# affiche TypeError: can only concatenate list (not "str") to list

3. Une fonction utile aux listes: len La fonction len va retourner la longueur de la liste.

> L = ['a','b','c']
> len(L)
3

4. Autres méthodes de liste TRES utiles

Retirer un élément de liste: méthode pop

voyelles = ["e","i","o","u"]
voyelles.pop()
voyelles
# affiche ["e","i","o"]

Longueur d’une liste: fonction len

voyelles = ["e","i","o","u"]
len(voyelles)
# affiche 4 
# car la liste contient 4 éléments

5. Liste de listes Les éléments contenus peuvent aussi être une liste:

positions = [[0,0], [1,2], [2,4]]

C’est la représentation d’un tableau, qui sur un tableur peut être représenté sous la forme suivante:

Les 3 éléments de la liste positions sont [0,0], [1,2], et [2,4]

Pour accéder au premier élément [0,0], on fait:

positions[0]
# retourne
[0,0]

Pour accéder au deuxieme élément [1,2], on fait:

positions[1]
# retourne
[1,2]

Et pour acceder au premier élément du 2e élément de positions, c’est à dire à la valeur 1, on fait:

positions[1][0]
# retourne
1

Cela permet d’afficher ou modifier la valeur 1.

Boucles bornées

1. Definition: Une boucle bornée est un système d’instructions qui permet de répéter un certain nombre de fois toute une série d’opérations.

La syntaxe d’une boucle bornée, en langage algorithmique peut s’écrire:

Pour i allant de 0 a n-1
Faire:
   instruction 1
   instruction 2
FinPour

En python, la syntaxe correspondante est:

for i in range(n):
  instruction 1
  instruction 2
demonstration avec python_puzzle. La boucle realise 4 itérations.

demonstration avec python_puzzle. La boucle realise 4 itérations.

  • Remarques:

    • Le bloc d’instruction sera executé n fois. Celui-ci peut contenir une ou plusieurs instructions, du moment qu’elles sont bien positionnées dans le bloc.
    • En Python, le bloc est identifié par une indentation: un retrait par rapport au bord gauche, comprenant 2 espaces (ou 4).
    • Pour sortir du bloc, on élimine l’indentation (on revient sur le bord gauche)
    • La fonction range(n) renvoie la liste des entiers de 0 à n-1. C’est un principe général en informatique, on commence toujours à compter à partir de 0, et il faut donc s’arrêter à n-1 pour effectuer n fois la boucle.
    • Pour chaque itération, le variant i prend une nouvelle valeur de l’ensemble {0,1,2,... n-1}, et peut être utilisé dans le bloc d’instructions.
    • On peut choisir n’importe quel nom pour le variant, pas seulement i.
  • Exemple

for c in range(3):
  print(c)
# affiche
0
1
2

Remarque: range(3) va créer une liste itérable constituée des valeurs 0, 1, 2. Ce sont les valeurs prises successivement par le variant c dans for c in range(3)

2. Parcourir les éléments d’une liste L avec range(len(L))

L = ["a","b","c"]
for i in range(len(L)):
  print(i, L[i])
# affiche
0 a
1 b
2 c

Remarque: Rappelez-vous que len(L) est une fonction qui retourne la longueur de la liste L. Si L contient 3 éléments, alors len(L) vaut 3.

3. Parcourir les éléments d’une liste L avec in L

L = ["a","b","c"]
for c in L:
  print(c)
# affiche
a
b
c

Ramarque: Cette fois-ci, le variant c prend successivement toutes les valeurs de la liste L.

Conclusion: Itérable et variant de boucle bornée

Les instructions for i in range(len(L)) et for c in L ont à peu près le même objectif: celui de parcourir TOUS les éléments de la liste L.

  • Ce qui est COMMUN: c’est l’utilisation du mot clé IN, qui va créer ce que l’on appelle un itérable, c’est-à-dire une liste de valeurs qui seront proposées l’une après l’autre pour le variant de boucle.

  • Ce qui est DIFFERENT: Dans le premier cas, on utilise la fonction range, qui créé un itérable entre 0 et la valeur mise en paramètre (valeur -1 pour être exact). Ce sont par exemple les indices de la liste L.

# exemple 1
for i in range(5):
  # instruction

La boucle va s’executer 5 fois. Mais à chaque fois, le variant i prend successivement l’une des valeurs dans [0,1,2,3,4]

# exemple 2
L = [0, 10, 20, 30]
for c in L:
  # instruction

L’instruction for c in L va, elle, créer un itérable constitué des valeurs de la liste L

Le nombre d’itération sera égal au nombre len(L), soit 4. Au cours des itérations, le variant c va prendre successivement chaque valeur de L, soit [0, 10, 20, 30]

Tracer un graphique y = f(x)

Pour tracer un graphique y=f(x), il faut disposer de 2 listes de mêmes dimensions x et y. Les coordonnées des points sont alors:

  • (x[0],y[0]) pour le point M0
  • (x[1],y[1]) pour le point M1
  • …

On utilise la fonction plt.scatter (nuage de points) ou bien plt.plot (courbe) du module matplotlib.pyplot qui est importé à la premiere ligne du script de la manière suivante: import matplotlib.pyplot as plt

Les 2 listes sont positionnées entre parenthèses, dans l’ordre (liste des X, liste des Y). Ce sont les arguments de la fonction plt.scatter (ou de plt.plot).

import matplotlib.pyplot as plt
temps = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
T = [20, 20, 22, 24, 28, 32, 38, 44, 52, 60]
plt.clf()
plt.grid()
plt.scatter(temps,T)
plt.xlabel('temps(min)')
plt.ylabel('Temperature(°C)')
plt.show()

Liens

Cours
TP4 Listes

fonctions

Les fonctions

Fonction sans paramètre

1. Definition: Une fonction permet d’encapsuler un bloc d’instructions et de lui donnéer un nom:

def ma_fonction():
    # bloc de code ligne 1
    # bloc de code ligne 2

La fonction est déclarée après le mot-clé def.

Choisir un nom qui n’appartient pas à Python (aucune autre fonction porte ce nom dans le langage).

Le nom est suivi de parenthèses () et deux points :

Le bloc de code de la fonction est indenté sous la ligne def ma_fonction

Appel de fonction: On peut ensuite exécuter ce bloc en utilsant ce nom. On dit qu’on appelle cette fonction en écrivant son nom, suivi de parenthèses ().

ma_fonction()

Valeur de retour: Une fonction retourne en général une valeur. Après le mot-clé return

  • Exemple 1 Dans ce script, on definit une fonction qui retourne Hi. Les lignes commençant par le symbole # sont des commentaires, et ne sont pas executées par Python. Elles sont optionnelles.
# definition de la fonction
def hello():
  return 'Hi'

# appel de la fonction
hello()
# 'Hi'

Fonction avec paramètre

Une fonction peut avoir un ou plusieurs paramètres qui permettent de transmettre des valeurs au bloc d’instructions. A l’interieur de la fonction, ces paramètres sont traités comme des variables, mais locales: Elles n’existent pas à l’exterieur du bloc.

Il y a alors une affectation: paramètre = argument

  • Exemple 2 Dans ce script, on definit une fonction qui calcule le carré d’un nombre x.
# definition de la fonction
def carre(x):
  return x**2

# appel de la fonction
carre(5)
# retourne 25

Lors de la déclaration de la fonction, le seul paramètre attendu s’appelera x. Puis lors de l’appel de la fonction carre, l’argument choisi est 5. A l’interieur de la fonction, x vaut 5.

illustration du passage d'argument lors de l'appel de la fonction

illustration du passage d'argument lors de l'appel de la fonction

La valeur de retour est alors 25: l’intruction return x**2 évalue 5**2, soit 25, avant de retourner la valeur.

Observez comme la fonction Python avec paramètre ressemble à la déclaration d’une fonction en mathématiques:

# en math
f(x) = 10 * x + 20

On peut calculer f(x) pour toute valeur de x en remplaçant x dans $10\times x + 20$ par sa valeur. Par exemple, $f(1) = 10\times 1 + 20 = 30$

# en python
def f(x):
  return 10 * x + 20

En python, on appelle cette fonction avec la valeur $x=1$ en écrivant:

f(1)
# retourne 30

Le return correspond au signe = en langage mathématique.

Plusieurs paramètres

Lors de l’appel de la fonction, le ou les arguments passés doivent correspondre aus paramètres attendus. Ils doivent être placés dans l’ordre.

  • Exemple 3: fonction qui calcule la surface d’un rectangle lorsque l’on divise chacun de ses côtés par un même coefficient c. On aura besoin de la longueur de ses côtés x et y (les 2 premiers paramètres de la fonction). Mais aussi de la valeur c:
# definition de la fonction
def calcul_surface(x,y,c):
  S = (x/c) * (y/c)
  return S

# appel de la fonction avec x=20 et y=30, c=1.5
# 20 sera place en premier argument
# 30 sera place en 2e argument
# 1.5 sera placé au niveau du 3e argument

calcul_surface(20,30,1.5)
# retourne 266.667

Importer des fonctions

On peut étendre les fonctions du langage en important des fonctions. Celle-ci sont natives, elles font partie du langage python, mais ne sont pas chargées au démarrage.

L’un des modules très utile est, par exemple, le module math. Celui-ci contient de nombreuses fonctions. Pour importer celle qui transforme le angles de degrés en radians, il faut ajouter la ligne suivante au debut du programme:

from math import radians

Puis, pour l’utiliser, et transformer 45° en radians, on écrira plus loin dans le programme:

angle = radians(45)
print(angle)

Placer un script dans une fonction

Le programme suivant comporte quelques lignes que l’on peut avoir à répéter. Imaginons un robot, chargé de laisser entrer les personnes dont l’age est supérieur ou egal à 18:

age = input('Quel age avez-vous? ')
age = int(age)
if age >18:
    print('Vous pouvez entrer')
else:
    print('Desole, ca ne va pas etre possible')

Il sera plus efficace de placer ces lignes dans une fonction.

Les règles pour écrire une fonction à partir de ce script sont les suivantes:

  • les entrées et variables sont mises en paramètre: il s’agit de age
  • Les print sont remplacés par return
  • Il faut choisir un nom à la fonction, écrit après def
def entrer_en_discotheque(age):
  if age >=18:
      return 'Vous pouvez entrer'
  else:
      return 'Desole, ca ne va pas etre possible'

Lorsque vous executez le programme, … il ne se passe rien. Vous avez seulement chargé la fonction.

Il faut appeler la fonction pour que celle-ci soit executée, par exemple avec:

> entrer_en_discotheque(18)

Voici un exemple d’execution d’une fonction à partir du shell.

1:charger la fonction (executer cellule), 2: appel, 3: sortie

1:charger la fonction (executer cellule), 2: appel, 3: sortie

Son execution cesse lorsqu’elle arrive à l’instruction return. Le programme reprend alors son cours.

Liens

Cours
TP5a Fonctions, applications
TP5b fonctions utiles pour calculer
TP5b boucles et fonctions, traitements automatisés

lecture - ecriture fichier

au cours de ce TP, vous allez apprendre à:

  • parcourir les caractères ou les éléments d’un fichier
  • traiter les éléments un par un. Placer les éléments traités dans un fichier
  • lire/ecrire dans un fichier

Manipuler des fichiers txt en python

Parcourir des séquences

Les séquences, comme le chaines str et les listes list python peuvent être parcourues avec une boucle for. On appelle parcourir le traitement des caractères ou des éléments l’un après l’autre.

Traiter les 2 exercices suivants pour démarrer ce TP.

ex 1: (a) Afficher une image à partir d’une Liste. Compléter le script:

L1 = [' ^___^','" o o "', '===X===','   "  ']
for l in L1:
    print(...

(b) Afficher une image à partir d’une liste de listes de caractères.

L2 = [[' ', '^', '_', '_', '_', '^'], ['"', ' ', 'o', ' ', 'o', ' ', '"'], ['=', '=', '=', 'X', '=', '=', '='], [' ', ' ', ' ', '"', ' ', ' ']]

for ligne in L2:
    s = ''
    for c in ligne:
        s += ...
    print(...

Remarquer que l’on utilise ici 2 boucles imbriquées, avec 2 variants: le variant ligne puis le variant c, qui contient chaque caractère de ligne.

ex 2: Quelle est l’image cachée dans cette matrice?

M = [['20', '2F', '5C', '5F', '2F', '5C', '20'],
     ['28', '20', '2E', '20', '2E', '20', '29'],
     ['3D', '5C', '5F', '76', '5F', '2F', '3D']]

Solution partielle:

for l in M:
    s = ''
    for r in l:
        s += ...
    print(...

Rappels:

  • Conversion valeur hexa -> decimal: utiliser int(valeur,16)
  • Conversion decimal -> ascii: utiliser chr

Lecture/ecriture dans un fichier

Introduction au TP

Les manipulations qui vont suivre demandent quelques pré-requis. Vous allez tester les instructions suivantes avant de réaliser le TP sur le déchiffrement.

Tester et comprendre chacun des exemples proposés ci-dessous.

Instruction de retour à la ligne \n:

Dans une chaine de caractères, pour faire un retour ligne, on utilise la combinaison de symboles \n.

Exemple:

>>> discours = "Je sais ta passion, et suis ravi de voir\nQue tous ses mouvements cèdent à ton devoir ;"
>>> print(discours)
Je sais ta passion, et suis ravi de voir
Que tous ses mouvements cèdent à ton devoir ;

Afficher le caractère \

\ est un caractère d’echappement. C’est à dire que lorsqu’il est placé dans une chaine de caractères, il n’est pas affiché mais interprété. Pour l’afficher, il faut alors mettre 2 fois le même symbole:

>>> print('\\')
\

Décalage de 1 rang pour un caractère “a” -> “b”

  • On détermine le rang ascii du caractère: rang = ord("a")
  • On definit un nouveau caractère avec décalage dans l’alphabet: chr
>>> rang = ord("a")
>>> car = chr(rang + 1)
>>> print(car)
b

Il s’agit d’un décalage de type monoalphabétique, permettant de chiffrer un texte pour le rendre secret. Ici, la clé de chiffrement est égale à 1. (1 seul rang de décalage).

Ecrire dans un fichier txt

  • méthode 1: fonctions open et close. On créé un objet qui sert à désigner le fichier. Choisir un nom quelconque, pour l’exemple qui suit ce sera fileout. On utilise la fonction open avec pour paramètres, le nom du fichier (son chemin), suivi du caractère ‘w’ (pour write, ouverture du fichier en écriture).

On peut alors placer du texte dans le fichier à l’aide de la méthode write: fileout.write("...")

Penser alors à fermer le fichier de lecture: fileout.close()

fileout = open('exemple.txt','w')
fileout.write("Je sais ta passion, et suis ravi de voir\nQue tous ses mouvements cèdent à ton devoir ;")
fileout.close()

On peut alors vérifier le fichier et son contenu en parcourant le dossier avec l’explorateur windows.

  • méthode 2: système d’instructions with + open

Le programme suivant est équivalent à celui de la méthode 1. Avec le mot clé with, les instructions de d’écriture dans le fichier sont mis dans un bloc, et donc indentées. A la sortie de ce bloc, le fichier est automatiquement fermé, ce qui fait l’economie de l’instruction close, et evite les oublis…

with open('exemple.txt','w') as fileout:
    fileout.write("Je sais ta passion, et suis ravi de voir\nQue tous ses mouvements cèdent à ton devoir ;")
   

Lire le contenu d’un fichier txt

  • méthode 1: fonctions open et close. On créé un objet qui sert à importer le fichier. Choisir un nom quelconque, pour l’exemple qui suit ce sera file. On utilise la fonction open avec pour paramètres, le nom du fichier (son chemin), suivi du caractère ‘r’ (pour read, ouverture du fichier en lecture).

On peut alors récuperer le contenu textuel du fichier à l’aide de la méthode read. Dans l’exemple ci-dessous, on place le texte du fichier dans la variable texte.

On peut traiter cette variable comme on le souhaite, l’afficher en entier (print(texte)), ou parcourir et traiter les caractères les uns après les autres (for c in texte: ...)

Penser alors à fermer le fichier de lecture: file.close()

file = open('exemple.txt','r')
texte = file.read()
file.close()
print(texte)
  • méthode 2: système d’instructions with + open

Le programme suivant est équivalent à celui de la méthode 1. Avec le mot clé with, les instructions de lecture du fichier sont mis dans un bloc, et donc indentées. A la sortie de ce bloc, le fichier est automatiquement fermé, ce qui fait l’economie de l’instruction close, et evite les oublis…

with open('exemple.txt', 'r') as file:
    texte = file.read()
print(texte)

TP Déchiffrement d’un texte

  • Télécharger le fichier texte_chiffre.txt (faire un clic droit=> sauvegarder la cible du lien sous…)
  • le placer dans le même dossier que votre fichier python.
  • Dans le fichier texte_chiffre.txt, le texte est-il écrit en clair ou est-il chiffré?

Les chiffrements les plus anciens reposaient sur un simple décalage des caractères, comme vu dans les informations préliminaires. Par exemple, avec une clé de décalage égale à 1, le “a” devient un “b”, le “b” -> “c”, etc…

A partir des informations précédentes, écrire un script python qui devra:

  1. Ouvrir le fichier ’texte_chiffre.txt’ en LECTURE
  2. Lire le contenu et le placer dans une variable texte
  3. Ouvrir un nouveau fichier en ECRITURE, que vous appelerez ’texte_dechiffre.txt’
  4. Parcourir les caractères de texte, les uns après les autres: for c in texte:
  5. Dans la boucle for: si le caractère c est différent de \ c’est à dire c != "\\"
  • déterminer le rang ascii de c
  • definir un nouveau caractère en essayant la clé de décalage égale à -1
  • écrire ce nouveau caractère dans le fichier ’texte_dechiffre.txt’
  1. Sinon, écrire \n dans le fichier ’texte_dechiffre.txt'
  2. fermer le-s fichier-s si besoin.
  3. Vérifier alors le contenu de votre fichier ’texte_dechiffre.txt’. Si celui-ci est toujours chiffré, recommencer avec une nouvelle clé (-2, puis -3, …)

Si vous avez terminé:

  • Utiliser votre script pour créer une fonction que vous appelerez chiffre_dechiffre et qui aura 3 paramètres:
    • texte0 : le fichier texte d’origine
    • texte1 : le fichier texte de destination
    • decalage_ascii : la clé de décalage

Cette fonction devra créer un nouveau fichier texte1 à partir du texte du fichier texte0. Tous les caractères de texte1 seront définis à partir de ceux de texte0 en utilisant une clé de déclage: decalage_ascii

Exemple d’utilisation:

chiffre_dechiffre('texte_chiffre.txt','texte_dechiffre.txt',2)

Utilisez alors votre fonction pour réaliser le chiffrement d’un texte relativement long.

Suite

  • Solution du TP lecture - ecriture python

  • Projet transformer image -> ASCII: Lien

installation python

Python est-il déjà installé?

Verifier si Python est installé sur votre ordinateur:

Vous pouvez vérifier cela en ouvrant l’invite de commandes et en tapant:

python --version
  • Windows: Télécharger le fichier d’installation depuis le site officiel de Python. Lancer l’executable et cocher “Add Python to PATH”. Puis cliquer sur Install now

  • Linux: Python peut être installé et géré via un gestionnaire de paquets comme apt, yum.

  • MacOS: utiliser le gestionnaire de paquets brew.

L’installation de Python via ces gestionnaires configure souvent automatiquement le PATH. Cependant, une fois l’installation reussie, la commande python --version peut renvoyer une erreur. Dans ce cas, il faudra ajouter Python à la variable d’environnement PATH: datascientist.fr

Installer un IDE python

Dans ce tutoriel, vous allez installer un editeur Python et suivre un premier tutoriel. Vous aurez besoin d’un ordinateur, PC, Linux ou mac.

Choisir l’un des IDE python ou distribution python proposés ci dessous:

  • Thonny
  • Pyzo
  • Anaconda
  • Winpython

Vous allez faire vos premiers pas dans l’apprentissage du langage.

Thonny

L’IDE le plus simple et complet à utiliser sera Thonny:

Anaconda

Installation de la distribution python ANACONDA. Systèmes Windows, Mac OSX, Linux

Page de telechargement sur le site anaconda.com

Il n’est pas nécessaire de fournir son email pour télécharger la distribution. (skip registration)

Youtube - Installer Anaconda sur Windows Facilement

Youtube - Installer Anaconda sur Windows Facilement

Winpython

Distribution uniquement pour le système Windows

Page de telechargement sur Sourceforge

Youtube - Python: Easiest way to download, install/setup and use python (WinPython Tutorial)

Youtube - Python: Easiest way to download, install/setup and use python (WinPython Tutorial)

Suivre un tuto python

courspython.com

fonctions et Turtle

Le module Turtle permet d’avoir un environnement simple muni d’une interface graphique.

La page suivante présente un aide-mémoire avec les principales instructions.

Il est conseillé d’avoir bien lu et traité les exemples des pages:

Premiers tracés

Script initial Ces exemples utilisent une boucle bornée pour répéter des consignes (for .. in range)

Utiliser Pyzo ou bien se rendre sur le notebook Turtle

Dans une nouvelle cellule: Copier-coller le script ci-dessous. Executer et analyser celui-ci:

import turtle

t = turtle.Turtle('turtle')
t.speed(8)
t.width(2)

largeur = 100

t.pendown()
t.color('red')
t.forward(largeur)
t.left(90)
t.forward(largeur)
t.left(90)
t.forward(largeur)
t.left(90)
t.forward(largeur)
t.left(90)
t.penup()
          
turtle.done()

Pour éviter les répétitions inutiles de script, utiliser une fonction carre, qui prendra largeur en paramètre, et qui s’executera lorsque l’on écrira: carre(largeur)

import turtle

t = turtle.Turtle('turtle')
t.speed(8)
t.width(2)

def carre(largeur):
    t.pendown()
    t.color('red')
    t.forward(largeur)
    t.left(90)
    t.forward(largeur)
    t.left(90)
    t.forward(largeur)
    t.left(90)
    t.forward(largeur)
    t.left(90)
    t.penup()
          
largeur = int(input('entrer la largeur'))
carre(largeur)
turtle.done()

Un script Python devra suivre une certaine structure pour la position de l’import des modules, déclaration de variables, des fonctions, et enfin le programme principal:

premier script avec le module turtle

premier script avec le module turtle

Le programme principal finira par turtle.done(), ce qui execute le tracé.

Modifier la fonction carre: utiliser une boucle bornée

Modifier pour avoir un script qui utilise le moins de lignes possibles pour cette fonction. (Rassembler les instructions t.left + t.forward dans une boucle)

Utiliser pour cela une boucle bornée for.

question 1: recopier le script de votre fonction

Une variante du programme: dessiner un rectangle

Definir et utiliser une fonction rectangle pour tracer un rectangle. On définira une nouvelle variable longueur qui sera utile comme paramètre de la fonction.

La valeur de cette variable sera introduite par une fonction input, comme dans le script précédent.

question 2: recopier le script de votre fonction

Dessiner des rectangles

Reproduire, à l’aide de votre fonction, le dessin ci-dessous. Celui-ci forme 3 rectangles colorés de dimension $80x100$.

rectangles côte à côte

rectangles côte à côte

question 3: recopier le script de votre programme (ne pas préciser les import et les definitions de fonctions)

Utiliser un variant de boucle

On utilisera maintenant la valeur de i dans l’instruction for i in range(N):

Pour dessiner la figure suivante, on utilisera une boucle bornée, qui répète plusieurs fois le bloc de code:

  • calculer la valeur de x
  • dessiner un carré de largeur x
  • lever le stylo
  • avancer jusqu’à la prochaine position.

La valeur du paramètre x, dans la fonction carre(x), dependra du variant i.

Ecrire un programme qui réalise ce dessin, à partir d’une fonction mathématique $x = a.i + b$

question 4: recopier le script de votre programme.

Dessiner des spirales

Avec des carrés emboités

Dans un carré de côté 100, on trace un carré dont les sommets sont situés au tiers des côtés du carré initial, et on répète indéfiniment l’opération.

On utilisera une boucle non bornée while avec le variant largeur. La condition d’execution pourrait être par exemple, largeur>20:

while largeur > 20:
	# instructions

A chaque itération:

  • dessiner un carré avec la fonction carre et le paramètre largeur.
  • avancer de $1/3 \times largeur$
  • tourner de 26.565 degrés
  • reduire la largeur d’un facteur 0.745: largeur = largeur * 0.745

question 5: recopier le script de votre programme principal

Avec des segments

Ecrire une fonction spirale qui devra reproduire une figure sur le modèle de la suivante:

  • La fonction utilisera un paramètres: la longueur du segment initial
  • le nombre d’itérations N voulues

Dans la fonction spirale: utiliser une boucle (for ou while) pour executer un certain nombre de traits.

question 6: recopier le script de votre fonction

Liens

Travaux pratiques

Travaux pratiques et mini-projets

Sous-sections de Travaux pratiques

transformer image ascii

Prérequis:

  • TP1 Ascii art: utiliser des symboles pour dessiner des formes: Lien
  • TP2 Lecture/ Ecriture dans un fichier: Lien

TP3 Projet ascii art: des pixels aux symboles ascii

On va remplacer dans une image la couleur d’un pixel par un caractère ascii dont le remplissage permettra de faire varier la clarté d’un zone de l’image.

Video explicative:

lire la video

lire la video

  • Télécharger les documents sources et décompresser l’archive. Trouver dans ce dossier les fichiers Marylin-original.jpg et le module display_image

  • Ouvrir un fichier python dans le même dossier. Importer les modules suivants:

from PIL import Image
from display_image import *

Votre code devra ensuite:

  • Ouvrir en LECTURE le fichier image à traiter.
  • redimensionner cette image de façon à ce qu’elle n’ait que 500 pixels de large/haut:
with Image.open("Marylin-original.jpg") as image:
    image = image.resize((500,500))
  • déterminer une série de caractères allant dans un ordre croissant d’opacité:
    • " " l’espace correspond à un pixel blanc
    • “@” peut être choisi comme le caractère le plus noir
    • choisir des caractères intermédiaires
ascii_char = ' .:-=+....@'
  • Ouvrir en ECRITURE le ficher de destination, celui dans lequel on écrira les symboles ascii:
fileout = open("ascii_art.txt","w")
  • Comme vu dans la video:

    • Parcourir les pixels de l’image à l’aide de 2 boucles for
    • Lire la couleur de chaque pixel: rgb=image.getpixel((x,y))
    • calculer la valeur en niveau de gris du pixel à partir de sa luminosité: grey = (rgb[0]+rgb[1]+rgb[2])//3
    • attribuer à chaque pixel un caractère: calculer l’indice correspondant dans la liste ascii_char: index = grey * 9 // 255
    • puis l’écrire dans une chaine de caractères: line += ascii_char[index] + ' '
    • mettre '\n' en fin de ligne et passer à la ligne suivante.
  • Une fois la chaine de caractère terminée:

    • placer la chaine line dans le fichier ascii_art.txt: fileout.write(line)
    • fermer le fichier txt: fileout.close()

Voila, vous pouvez maintenant vérifier son contenu en l’ouvrant avec un editeur de texte, type bloc notes. Mais pour visualiser l’image représentée par ces caractères, il faudra ajouter les lignes suivantes à votre programme:

image = textfile_to_image('ascii_art.txt')
image.show()
image.save('ascii_art.png')

Liens et sources

pygame les bases

Pygame

Pygame est un module python qui offre des outils permettant de créer des jeux. C’est un programme libre, et opensource.

Le jeu Pong SOLO

Dans cette première partie, nous allons nous familiariser avec l’environnement de developpement et la programmation de type evenementielle, en temps réel. Dans ce type de programmation, il faudra afficher et mettre à jour l’image en fonction des actions du joueur, et lire régulièrement les états des touches du clavier pour detecter les appuis par le joueur.

Programmons ainsi un grand classique des jeux d’arcade: PONG

Dans la variante proposée ici, le jeu se jouera en SOLO, le but étant de renvoyer la balle vers le bord gauche de l’écran.

Dessiner la fenêtre graphique et placer un objet

Commencer par créer un nouveau projet (nouveau fichier: pong.py).

Le programme suivant va dessiner une raquette (un rectangle blanc vertical) dans une fenêtre graphique de dimension 512 x 512 pixels.

import pygame
from pygame.locals import *
from random import randint

pygame.init()
fenetre = pygame.display.set_mode((512,512))
fenetre.fill([0, 0, 0])

r1_y = 232
largeur = 16
hauteur = 128

continuer = True

while continuer :
    for event in pygame.event.get():
        if event.type == QUIT:
            continuer = False
    
    fenetre.fill([0,0,0])
    pygame.draw.rect(fenetre,(255,255,255),(450,r1_y,largeur,hauteur))
    pygame.display.update()
    pygame.time.wait(10)

pygame.quit()

Les programmes python avec le module pygame ont toujours à peu près la même structure:

  • les premières lignes contiennent les extensions à ajouter au langage python.

  • Ajouter ensuite pygame.init() pour initialiser les modules importés… et terminer le programme par pygame.quit() pour quitter la fenêtre pygame.

  • l’instruction fenetre = pygame.display.set_mode((512,512)) va créer une fenêtre graphique.

  • La boucle while continuer: c’est ici que l’on va mettre les instructions du jeu. Le booléen continuer va permettre de gérer la fin de l’execution du programme lorsque l’on ferme la fenêtre avec if event.type == QUIT: continuer = False

  • Il s’agit d’une programmation de type evenementielle: il faut tester à chaque nouvelle itération dans la boucle while quelle est la touche sur laquelle le joueur a appuyé, et modifier le décors en conséquence.

Pour dessiner un rectangle de 16 pixels en largeur sur 128 en hauteur, il faudra utiliser la fonction pygame.draw.rect. Les 3 paramètres de la fonction sont:

  • le nom donné à la fenêtre pygame: fenetre
  • un tuple constitué des 3 valeurs en code (rouge,vert,bleu): (255,255,255)
  • un tuple constitué de 4 valeurs: les coordonnées x,y du coin supérieur gauche du rectangle, sa largeur et sa hauteur: (450,r1_y,largeur,hauteur)
exemple de rectangle de dimension 4px x 24 px

exemple de rectangle de dimension 4px x 24 px

Le repère (x,y) de la fenêtre graphique a pour origine (0,0) le coin supérieur gauche. L’axe croissant des x est dirigé vers la droite, et celui des y vers le bas.

Ainsi, pour positionner un rectangle blanc de dimension 4 x 24 à la position A(115,56), la fonction s’écrirait pygame.draw.rect(fenetre,(255,255,255),(115,56,4,24)).

position du coin superieur gauche du rectangle en (115,56)

position du coin superieur gauche du rectangle en (115,56)

Contrôler le deplacement d’un objet

On veut deplacer l’objet à l’aide des touches du clavier UP et DOWN (flèches vers le HAUT/BAS):

contrôle de la raquette du jeu PONG

contrôle de la raquette du jeu PONG

Il faudra appliquer les modifications suivantes:

Rappelez vous que la coordonnée $y_A$ du rectangle est stockée dans une variable: r1_y. La valeur de cette variable est déclarée au debut du programme. Notez que pour l’instant, la raquette reste fixe, et qu’elle n’est pas contrôlable.

Pour lire les touches du clavier, il faut contrôler les evenements, c’est à dire les interactions (clavier, souris).

Pour vérifier si une touche du clavier a été enfoncée, on place l’instruction event.type == KEYDOWN dans le programme:

for event in pygame.event.get():
    if event.type == KEYDOWN:

Et enfin, pour savoir si cette touche était la flèche de direction vers le haut, c’est event.key == K_UP

if event.type == KEYDOWN:
    if event.key == K_UP:
        # deplacer vers le haut

Comment traduire en python: déplacer vers le haut?

Il faudra modifier la valeur de la variable r1_y… Pour déplacer la raquette de 8 pixels vers le haut, choisir la bonne proposition parmi les 2 suivantes:

  • r1_y = r1_y + 8
  • r1_y = r1_y - 8

A cette étape, le script du programme est alors:

import pygame
from pygame.locals import *
from random import randint

pygame.init()
pygame.key.set_repeat(1,20) # gestion appui prolongé
fenetre = pygame.display.set_mode((512,512))
fenetre.fill([0, 0, 0])

r1_y = 232
largeur = 16
hauteur = 128


continuer = True


while continuer :
    for event in pygame.event.get():
        if event.type == QUIT:
            continuer = False
        if event.type == KEYDOWN:
            if event.key == K_UP:
                # instruction qui modifie r1_y
    
    fenetre.fill([0,0,0])
    pygame.draw.rect(fenetre,(255,255,255),(450,r1_y,largeur,hauteur))
    pygame.display.update()
    pygame.time.wait(10)

pygame.quit()

Que reste t-il à faire?

  1. Si vous executez votre programme, vous pouvez voir votre raquette disparaitre par le bord supérieur de la fenêtre. Il faudra rajouter une condition pour modifier r1_y si r1_y >0. Sinon ne rien faire.
  2. Et si l’on veut faire descendre cette raquette? Utiliser alors if event.key == K_DOWN: et programmer le deplacement vers le bas. Ici aussi, ajouter une condition sur r1_y pour que la raquette ne disparaisse pas par le bord inférieur…

Enfin, lorsque tout fonctionne, vous allez vous interesser au programme de la balle rebondissante: suite du TP

Liens

jeu de rôle en console

TP python: Jeu de Rôle

Le but de ce TP est de créer un jeu avec une interface TEXTUELLE

Rappels de classe de 1ere NSI

Les entrées et sorties

voir le cours à la page https://lyceum.fr/1g/nsi/7-langages-et-programmation/3-entrees-et-sorties

texte formaté

On peut ajouter le contenu d’une variable dans du texte. Il faut pour cela utiliser un formatage. Les symboles {} devront se trouver à l’emplacement de la variable à disposer dans le texte :

Exemple : (executer la cellule suivante)

n = 18
texte = 'je viens d\'avoir {} ans'.format(n)
print(texte)

Listes

Avec la liste suivante :

mois = ['janvier','fevrier','mars','avril','mai','juin','juillet','aout']
  1. compléter la liste des mois de l’année (utiliser l’une des méthodes de liste)
  1. Quelle instruction, utilisant un indice numerique va retourner le mois ‘juin’ ?
  1. Quelle instruction permettra de retourner la liste suivante, découpée à partir de celle mois? :
['juillet','aout']
  1. Utiliser une expression formatée utilisant mois pour afficher le texte :

Le mois de juin est celui du début de l’été.

Dictionnaire

Soit un dictionnaire : dico = {1:2,3:4} ayant pour couples:

  • clé 1 : valeur 2
  • clé 3 : valeur 4

Pour accéder à la valeur 2, il faut faire :

dico[1]

Et pour accéder à la valeur 2, il faut faire :

dico[3]

Le type des clés et des valeurs peut être différent d’un entier : il peut s’agit d’une chaine de caractère, mais aussi d’une liste, d’un tuple, d’un autre dictionnaire…

Exercice : Avec le dictionnaire :

dico = {1:2,3:{4:5}}
  1. Trouver l’expression qui aura pour valeur : 5

Même exercice, mais on dispose maintenant du dictionnaire :

dico = {'1':'2','3':{'4':'5'}}`
  1. Trouver l’expression qui aura pour valeur, l’entier 5

On dispose d’un dictionnaire de nom laby contenant les données suivantes :

laby = {1:{2:{3:9,5:6},7:8}}
  1. Ecrire une série d’instructions qui permettent de parcourir les valeurs jusqu’à renvoyer la valeur 9.

Mini projet

Ecrire un programme qui permettra de parcourir la galerie de l’entrée (n°1) jusqu’à la sortie (n°9).

la galerie sera représentée par la structure :

galerie = {1:{2:{3:9,5:6},7:8}}

Le programme demande à l’utilisateur de choisir une nouvelle direction à chaque nouvelle clé visitée.

Le programme affiche les choix possibles (valeurs) pour chacune des clés visitées.

L’utilisateur choisit alors une valeur numérique en rapport avec les valeurs possibles et la saisit dans une boite de dialogue générée par la fonction input.

Une boucle while permet de répéter cette séquence tant que la valeur saisie n’est pas 9.

Le texte affiché par le programme :

vous etes au n°1
vous pouvez aller à : [2, 7]
quel est votre choix (1,..9) ? => 2
vous etes au n°2
vous pouvez aller à : [3, 5]
quel est votre choix (1,..9) ? => 3
vous etes au n°3
vous pouvez aller à : 9
quel est votre choix (1,..9) ? => 9
vous avez gagné `
Xyzzy Blast, premier jeu de rôle sur ordinateur

Xyzzy Blast, premier jeu de rôle sur ordinateur

Extension du projet (term NSI)

Ce mini projet peut être étendu. On pourra utiliser des classes pour la gestion du (des) scenario(scenatii), du (des) joueur(s).

On pourra également proposer une interface qui améliorera le confort de jeu.

Enfin, on pourra utiliser des fichiers textes (voire une base de données) pour une meilleure gestion des contenus, ou pour sauvegarder des éléments du jeu.

Xyzzy Blast, Computer History Museum

Xyzzy Blast, Computer History Museum

Aides

lire/ ecrire dans un fichier texte

Consulter la page Entrees/Sorties en python

gestion de base de données en python

pyxelstudio les bases

Pyxel studio

Le site pyxelstudio.net permet de créer un jeu de type retro-gaming, en python. Il s’agit de jeux que l’on trouvait sur console 8 bits (16 couleurs, 4 pistes audio utilisant 64 sons différents).

console Gameboy, Nitendo, 1990

console Gameboy, Nitendo, 1990

Le projet est soutenu activement, on peut consulter les démos et les télécharger depuis la page github.com/kitao/pyxel.

Pour créer notre premier jeu, nous allons utiliser l’editeur en ligne pyxelstudio.net.

Il est recommandé de créer un compte afin de retrouvez tous vos projets dans votre espace personnel. Cliquer alors sur register (en haut à droite) et renseigner vos identifiants.

Le jeu Pong SOLO

Dans cette première partie, nous allons nous familiariser avec l’environnement de developpement et la programmation de type evenementielle, en temps réel. Dans ce type de programmation, il faudra afficher et mettre à jour l’image en fonction des actions du joueur, et lire régulièrement les états des touches du clavier pour detecter les appuis par le joueur.

Programmons ainsi un grand classique des jeux d’arcade: PONG

Dans la variante proposée ici, le jeu se jouera en SOLO, le but étant de renvoyer la balle vers le bord gauche de l’écran.

Dessiner la fenêtre graphique et placer un objet

Commencer par créer un nouveau projet (new project).

Cela devrait ouvrir une nouvelle fenêtre (edition).

Lorsque vous reviendrez au tableau de bord (flèche en haut à gauche), modifiez le nom de votre projet.

Remplacer NO NAME par un nom plus evocateur, par exemple Pong raquette.

Depuis le tableau de bord, pour programmer le jeu, cliquer sur le bouton edition (le petit stylo):

La fenêtre d’edition comprend l’editeur à gauche, où l’on peut rediger le script en python, et la rendu visuel du jeu à droite. Celui-ci s’execute lorsque l’on appuie sur le bouton jaune, play:

Parmi les autres commandes de la fenêtre, repérer celle qui permet de sauvegarder et celle qui permet de revenir au tableau de bord.

Le programme suivant va dessiner une raquette (un rectangle blanc vertical) dans une fenêtre graphique de dimension 124 x 124 pixels.

import pyxel

pyxel.init(128, 128, title="Pong Solo")


def draw():
    pyxel.cls(0)  # vide la fenetre
    pyxel.rect(115, 56, 4, 24, 7)
    pyxel.text(50, 5, 'Pong raquette', 7)    # Affichage Titre 

pyxel.run(draw)

Les programmes python pour Pyxel Studio ont toujours à peu près la même structure:

  • la première ligne contient les extensions à ajouter au langage python. Il faudra ajouter au minimum le module pyxel pour notre programme.
  • l’instruction pyxel.init(128, 128, title="...") va créer une fenêtre graphique carrée de côtés 128 pixels. Ne pas modifier ces dimensions.
  • On definit une ou plusieurs fonctions pour dessiner, ou calculer de nouvelles coordonnées pour les objets. Ici, nous choisissons d’appeler cette fonction draw pour:
    • effacer l’image: pyxel.cls(0)
    • dessiner le rectangle blanc: pyxel.rect(115, 56, 4, 24, 7)
    • écrire dans la fenêtre graphique: pyxel.text(50, 5, 'Pong raquette', 7)
  • La dernière ligne, pyxel.run(draw) va executer en boucle l’appel à la fonction draw, qui est citée en paramètre. Cet appel est réalisé 30 fois par seconde. C’est ce qui donne l’impression de dessin animé lorsque l’on modifie la position d’un objet.

Pour dessiner un rectangle de 4 pixels en largeur sur 24 en hauteur, il faudra utiliser la fonction pixel.rect.

rectangle de dimension 4px x 24 px

rectangle de dimension 4px x 24 px

Pour positionner le rectangle à un endroit précis de la fenêtre graphique, ce sont les coordonnées (x,y) du coin supérieur gauche (le point A sur le schéma) qu’il faut renseigner.

Le repère (x,y) de la fenêtre graphique a pour origine (0,0) le coin supérieur gauche. L’axe croissant des x est dirigé vers la droite, et celui des y vers le bas.

Ainsi, pour positionner le rectangle de dimension 4 x 24 à la position (115,56), la fonction s’écrit pyxel.rect(115, 56, 4, 24, 7). La dernière valeur, le 7 correspond à la couleur BLANC.

position du coin superieur gauche du rectangle en (115,56)

position du coin superieur gauche du rectangle en (115,56)

Contrôler le deplacement d’un objet

On veut deplacer l’objet à l’aide des touches du clavier UP et DOWN (flèches vers le HAUT/BAS):

contrôle de la raquette du jeu PONG

contrôle de la raquette du jeu PONG

Il faudra appliquer les modifications suivantes:

  • placer la coordonnée $y_A$ du rectangle dans une variable. Appelons celle-ci r1_y par exemple.

La valeur de cette variable sera déclarée au debut du programme, après la première ligne. A cette étape, le script du programme est alors:

import pyxel

r1_y = 56

pyxel.init(128, 128, title="Pong Solo")


def draw():
    pyxel.cls(0)  # vide la fenetre
    pyxel.rect(115, r1_y, 4, 24, 7)
    pyxel.text(50, 5, 'Pong raquette', 7)

pyxel.run(draw)

Notez que pour l’instant, la raquette reste fixe, et qu’elle n’est pas contrôlable.

Pour lire les touches du clavier, il faut utiliser la fonction pyxel.btn, et préciser en paramètre la touche que l’on veut observer. Par exemple, pour lire l’état de la touche UP, ce sera pyxel.btn(pyxel.KEY_UP)

Cette fonction retourne un booléen (True/False), que l’on va placer dans une instruction conditionnelle:

if pyxel.btn(pyxel.KEY_UP):
	# deplacer vers le haut

Comment traduire en python: déplacer vers le haut?

Il faudra modifier la valeur de la variable r1_y… Pour déplacer la raquette de 2 pixels vers le haut, choisir la bonne proposition parmi les 2 suivantes:

  • r1_y = r1_y + 2
  • r1_y = r1_y - 2

Ou placer cette instruction?

Pour structurer au mieux notre programme, nous placerons les instructions de lecture du clavier et de modification des coordonnées dans une nouvelle fonction, que l’on appelera r1_move

La première ligne de cette fonction doit préciser que l’on autorise la modification de la variable r1_y, alors que cette variable a été déclarée en dehors de la fonction. Il faut placer pour cela l’instruction global r1_y.

A ce stade, le programme devient alors:

import pyxel

pyxel.init(128, 128, title="Pong Solo")
r1_y = 56

def r1_move():
    global r1_y
    if pyxel.btn(pyxel.KEY_UP):
    	r1_y = r1_y - 2

def draw():
    pyxel.cls(0)
    pyxel.rect(115, r1_y, 4, 24, 7)
    pyxel.text(50, 5, 'Pong raquette', 7)

pyxel.run(r1_move, draw)

Notez qu’à la dernière ligne, on a ajouté la fonction r1_move comme paramètre de pyxel.run. Il y a maintenant 2 fonctions à executer en continu, 30 fois par seconde pour générer le jeu en temps réel.

Que reste t-il à faire?

  1. Si vous executez votre programme, vous voyez votre raquette disparaitre par le bord supérieur de la fenêtre. Il faudra rajouter une condition pour modifier r1_y si r1_y >0. Sinon ne rien faire.
  2. Et si l’on veut faire descendre cette raquette? Utiliser alors if pyxel.btn(pyxel.KEY_DOWN): et programmer le deplacement vers le bas. Ici aussi, ajouter une condition sur r1_y pour que la raquette ne disparaisse pas par le bord inférieur…

Enfin, lorsque tout fonctionne, vous allez vous interesser au programme de la balle rebondissante. Il s’agit alors d’un nouveau projet: Suite

Liens

mastermind

Jeu du mastermind - 1ere NSI

Précisions

Pour la présentation du jeu, on pourra consulter la page: wikihow.com

Ce TP demande une bonne maitrise des concepts python de base:

Cette version du programme n’utilise pas les sequences comme les listes python. L’interface se passe dans la console python.

Principes retenus pour le jeu

  • L’ordinateur tire 4 couleurs parmis Jaune, Orange, Cyan, Rouge, Vert. Ces pions colorés sont les variables o1, o2, o3, o4. On y stocke un unique caractère, parmis (‘J’,‘O’,‘C’,‘R’,‘V’)

  • Le joueur doit proposer sa sequence de 4 couleurs. Sa première reponse est placée dans la variable j1, puis la 2e dans j2, etc… Le joueur proposera par exemple ‘J’, puis ‘O’, puis ‘C’, puis ‘R’ pour Jaune, Orange, Cyan, Rouge.

  • Si la couleur du pion est trouvée, le score Noir N augmente de 1.

  • Si l’une des couleurs est trouvée mais n’est pas à la bonne place, c’est le score blanc B qui augmente.

Commençons par les variables globales du jeu

Importer la fonction random.choice. Puis utiliser cette fonction pour réaliser le tirage aléatoire d’un caractère parmis ('J','O','C','R','V'), que l’on placera dans la variable o1.

from random import choice
o1 = choice(('J','O','C','R','V'))

Faire de même pour les 3 autres pions, o2, o3, o4.

Il s’agit de la combinaison tirée par l’ordinateur. Vous pouvez créer une chaine de caractères à partir de ces 4 variables, en les ajoutant chacune:

sequence = o1 + o2 + ... # a completer

Vous pouvez l’afficher dans la console en ajoutant la fonction print

Vous aurez aussi besoin:

  • du nombre d’essais réalisés par le joueur
  • du nombre de pions noirs calculés par l’ordinateur (4 noirs = gagné)

Ajouter alors les lignes qui affectent la valeur 0 à chacune de ces variables, essais et N

Boucle principale du jeu

Ecrire une boucle while avec pour condition d’execution:

  • le nombre d’essais est <= 12
  • N est différent de 4

Si l’une de ces conditions n’est plus réalisée, alors on sort de la boucle car la partie est terminée.

Demander au joueur de rentrer les 4 couleurs de sa proposition pour le tour. Utiliser le modèle ci-dessous et programmer j2, j3 et j4

j1 = input("entrer la couleur du pion 1 (JOCRV): ")

A cette étape du projet, votre script devrait ressembler à ceci:

from random import choice
o1 = choice(('J','O','C','R','V'))
o2 = ...
...
...
sequence = o1+o2+...
# print(sequence)
essais = ...
N = ...
while essais ... 12 and N ... 4:
    j1 = input("entrer la couleur du pion 1 (JOCRV): ")
    j2 = ...
    ...
    ...

Il faudra ensuite initialiser les variables N et B à zero, puis écrire une série de tests:

Tester pour chaque couleur donnée par le joueur, si celle-ci est bien en correspondance avec le pion de l’ordinateur, à la même place. Par exemple, j1 est il egal à o1: Augmenter alors N d’une unité.

Si le test est negatif, tester alors si la couleur proposée par le joueur est présent dans la sequence, mais occupe une autre position:

if j1 == o1:
    # instruction
elif j1 in sequence:
    # instruction

Cette fois, ce sera la variable B (pour Blanc), qui augmente d’une unité.

Rq: Lorsque le joueur propose plusieurs fois la même couleur, le test j1 in sequence peut donner de fausses detections. Ce qui surevalue la valeur de B. Pour resoudre ce problème, il faudra utiliser des listes python pour mettre en correspondance les choix joueur et choix ordinateur. Pour ce premier TP, nous allons ignorer ce problème.

Afficher ensuite B et N dans la console, augmenter le nombre d’essais d’une unité, et recommencer la boucle while

Fin de la partie

A la sortie de la boucle while, le joueur a soit gagné, soit perdu. Afficher un message dans la console.

Améliorations possibles

Le joueur pourrait donner sa sequence de couleurs en une seule fois, à l’aide d’une seule commande input. Il écrirait par exemple “JJOV”.

Pour comparer chaque couleur, avec chaque pion de l’ordinateur, à la même position: il faut alors atteindre l’une des lettres du mot “JJOV”, et la comparer à la lettre du même rang, dans la sequence de l’ordinateur.

Lorsque les pions sont en correspondance, il faudra utiliser une liste de correspondance pour marquer les positions deja evaluées.

Exemple:

ordinateur = ['J','O','C','V']
# on copie la liste ordinateur dans une nouvelle liste
# ordinateur -> correspondance
correspondance = ['J','O','C','V']
joueur = ['J','J','O','O']
  • Gestion des pions noirs: Lorsque l’on evalue la correspondance de joueur[0], on trouve que joueur[0] == ordinateur[0]. On modifie alors la liste de correspondance de la manière suivante: ['X','O','C','V'], et on poursuit avec joueur[1] == ordinateur[1]…

  • Gestion des pions blancs: Après la gestion des pions noirs, on recherche les occurences entre joueur[i] et correspond[j] avec i different de j. A chaque nouvelle occurence, on place ‘X’ dans correspond[j], pour ne pas le compter plusieurs fois.

Cela necessite d’utiliser un index pour parcourir le mot du joueur. Et une boucle bornée for pour faire evoluer le rang.

On trouvera des précisions sur ces notions au TP4 python: boucles for, ainsi qu’au cours sur les séquences.

shifumi

Jeu du Shifumi

Le pierre-feuille-ciseaux, chifoumi, pierre-papier-ciseaux ou encore roche-papier-ciseaux est un jeu dans lequel chaque joueur forme simultanément une parmi plusieurs armes symbolisées par la forme de la main et dont les rapports d’efficacité suivent un cycle : la pierre (aussi appelée « caillou » ou « roche ») battant les ciseaux, qui battent la feuille (ou « papier »), qui elle-même bat la pierre. Si les armes choisies sont les mêmes, il y a égalité. wikipedia

consulter les règles du jeu

consulter les règles du jeu

Programmer un jeu à 2 joueurs

Pour programmer le choix de l’ordinateur: On utilisera la fonction randint du module random. Tester le script suivant pour comprendre son fonctionnement:

from random import randint
for i in range(10):
    print(randint(0,2))

On utilisera le code numerique suivant:

pierre = 0, ...

pierre = 0, ...

  1. Stocker le choix de l’ordinateur dans la variable j1
  2. Demander au joueur son choix (0: pierre, 1:feuille, 2: ciseaux). Transformer la valeur en un entier et la stocker dans j2
  3. Evaluer le vainqueur, ou, préciser s’il s’agit d’un match nul, à l’aide d’une structure conditionnelle
  4. Afficher un message

Astuce

On pourra utiliser à bon escient la fonction modulo %, en remarquant:

j2 gagne si la valeur de j2 est egale à j1+1, et même plus précisemment (j1+1)%2. Vérifiez le à l’aide d’un schéma.

Python avancé

Python - concepts avancés

  • C1 Types
  • C2 Algorithmes essentiels
  • C3 Traitement de données
  • C4 Mise au point
  • C5 Projets
  • types simples int, float, str, methodes de chaines string, slice types construits listes, tuples, dictionnaires, méthodes tables de données listes de listes, tri avec clé (lambda), conversion en dictionnaires, import de fichiers csv dataframe module pandas, dataframe
  • arguments, valeur par defaut d’un argument, annotations de type, modules, docstring, lambda fonction
  • Rappels sur les algorithmes vus en classe de 1ere NSI calculer multiplier, diviser, recherche du PGCD rechercher algorithmes de parcours séquentiel et dichotomique trier tri par selection, tri par insertion algorithmes avancés algorithme glouton et de recherche des K plus proches voisins
  • traitement des donnees en table Open datas, csv, module requests, donnees en table graphique avec matplotlib Tracé de graphiques avec curseur, contexte graphique regression lineaire regression, modelisation avec scipy.optimize sql et python traitement sql et visualisation TP exoplanets.db traitement sql et visualisation a partir des donnees d’exoplanetes recherche de correlations module seaborn, visualisation, recherche de clusters dans un nuage de points kmean et exoplanetes KNN et module Scikit-learn, previsions
  • Ce chapitre comprend 2 pages de cours et une page exercices: La mise au point d’un programme: Lien 1 Création et utilisation de modules: Lien 2 La liste des projets se trouve ici Modularité Qu’est ce qu’un module ? Un module est un fichier python (d’extension .py) contenant des fonctions. En principe, il n’est pas prévu pour être executé. Pour faire référence aux fonctions de ce module, il faut l’importer depuis le script principal (ìmport module.py`).
  • Ce chapitre comprend 2 pages de cours et une page exercices: La mise au point d’un programme: Lien 1 Création et utilisation de modules: Lien 2 Exercice: Lien Programmer en Grand L’infographie ci-contre montre une mesure des lignes de code dans certains programmes conséquents. Les mesures sont en millions de ligne de code: codebase - millions lines of code visualized

Sous-sections de Python avancé

Sous-sections de Types

types simples

Les variables et les types natifs en Python

Cette page apporte des informations sur les types de base, sur les fonctions de la librairie math, sur les références, et les méthodes de chaines.

Cette rubrique contient 3 pages :

Les types natifs de base, ce sont les types numériques int et float, le type booléen bool, les chaines de caractères str, mais aussi le type None.

le type de « rien » : None

None est la valeur unique du type NoneType. Elle représente l’absence de valeur.

type(None)
# affiche <class 'NoneType'>

None est utile par exemple lorsque l’on veut terminer une fonction sans valeur de retour, ou lorsqu’une fonction ne contient pas d’instruction return (c’est alors la valeur de retour implicite) :

def f(x):
  # instructions
  return None

le type booléen : bool

bool est le type des valeurs de vérité : True et False. C’est le résultat des comparaisons (==, <, >=, …) et des expressions logiques.

type(True)
# affiche <class 'bool'>

À noter : en Python, bool est un sous-type de int : True vaut 1 et False vaut 0. C’est pourquoi True + True donne 2.

Transformer le type des données

Pour consulter le type d’une donnée : fonction type:

a = 3
# Créé un objet de type int et lui associe le nom 'a'
type(a) 
# affiche int

Pour transformer vers un autre type de base, on utilise les fonctions int, float, str:

transformer x en … fonction
integer int(x)
float float(x)
string str(x)
  • Exemple: tranformer en float:
float(3)
# affiche 3.0
float('3.8')
# affiche 3.8
  • transformer en int convertit par exemple un flottant en entier en tronquant la partie décimale du nombre (attention, ce n’est pas un arrondi) :
int(3.5)
# affiche 3
int(-3.5)
# affiche -3 (et non -4 : la troncature se fait vers 0)

ou une chaine de caractères en un entier :

int("3")
# affiche 3
int("3.5")
# ValueError : int() ne convertit que des chaines représentant un entier

Opérations sur les types numériques

Les opérateurs sur les nombres ont été vus dans le cours Python les bases.

  • Certaines fonctions natives vont enrichir les possibilités de calcul:

Exemple: arrondir : fonction round(nombre,decimales)

`round(3.1415926,2)` donne `3.14`
import math
math.sqrt(9)
# affiche 3.0
PI = math.pi
PI
# affiche 3.141592653589793
math.sin(PI/2)
# affiche 1.0
# le sinus de l'angle en radians
math.fabs(-101)
# affiche 101.0
# Renvoie la valeur absolue de (-101), toujours sous forme de float
math.isnan(PI)
# affiche False
math.isnan(float('nan'))
# affiche True
# Renvoie True si x est NaN (Not a Number)

Remarque: les nombres flottants ont une précision limitée. Par exemple 0.1 + 0.2 n’affiche pas exactement 0.3 mais 0.30000000000000004, à cause de la façon dont les flottants sont représentés en mémoire (norme IEEE 754). Il faut garder ceci en tête avant de comparer deux flottants avec ==.

Opérations sur les booléens - rappels

operateur symbole exemple d’expression resultat
intersection and True and False False
reunion or True or False True
negation not not False True
est égal à == True == False False
est différent de != True != False True

Opérations avec les chaines de caractères

Les opérateurs + et * sont autorisés dans les expressions avec les chaines de caractère.

Le + réalise une concaténation de 2 chaines. Le * répète et concatène la chaine :

a, b = 'Alan', 'Turing'
a + b 
# affiche AlanTuring
a * 3
# affiche AlanAlanAlan

Les caractères sont placés dans une chaine. On peut donc y accéder avec leur index, comme pour les Listes:

chaine = 'Hello World'
chaine[0]
# affiche 'H'
chaine[1:4]
# affiche 'ell'

On peut aussi utiliser des index négatifs (qui comptent depuis la fin de la chaine) et un pas (step) dans le slice :

chaine[-1]
# affiche 'd' (dernier caractère)
chaine[::-1]
# affiche 'dlroW olleH' (la chaine inversée)
chaine[0:11:2]
# affiche 'HloWrd' (un caractère sur deux)

Mais, contrairement aux Listes, on ne pourra pas modifier un caractère par son index:

chaine[0] = 'P'
# TypeError: 'str' object does not support item assignment

En fait, comme int et float, le type str est immuable (immutable) : une fois créée, une chaine ne peut plus être modifiée en place. Toute méthode qui semble « transformer » une chaine (upper(), replace(), …) renvoie en réalité une nouvelle chaine.

Une chaine de caractères est itérable: On peut la parcourir avec une boucle bornée. Par exemple, le script suivant élimine tous les espaces dans la chaine:

s = "Il fait beau."
res = ""
for carac in s:
  if carac != ' ':
    res = res + carac
print(res)
# affiche Ilfaitbeau.

méthodes de chaines

Les chaines sont des objets qui possèdent leurs méthodes. il est difficile de se souvenir de toutes les méthodes travaillant sur les chaînes de caractères. Aussi il est toujours utile de recourir à la documentation embarquée

help(str)

Ce qui donne:

Help on class str in module builtins:

class str(object)
 |  str(object='') -> str
 |  str(bytes_or_buffer[, encoding[, errors]]) -> str
 |  
 |  Methods defined here:
 | ...
 |  format(...)
 |      S.format(*args, **kwargs) -> str
 |      
 |      Return a formatted version of S, using substitutions from args and kwargs.
 |      The substitutions are identified by braces ('{' and '}').
 |  ...
 |  join(self, iterable, /)
 |      Concatenate any number of strings.
 |      
 |      The string whose method is called is inserted in between each given string.
 |      The result is returned as a new string.
 |      
 |      Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'
 | ...

construire une chaine avec une f-string

pour construire une chaine à partir de valeurs de variables, la syntaxe moderne et recommandée est la f-string, plus lisible que format ou la concaténation avec + :

nom, age = 'Ada', 36
chaine = f"{nom} a {age} ans"
print(chaine)
# affiche 'Ada a 36 ans'

Découpage - assemblage: split et join

Les méthodes split et join permettent de découper une chaîne selon un séparateur pour obtenir une liste, et à l’inverse de reconstruire une chaîne à partir d’une liste.

split permet donc de découper :

'abc=:=def=:=ghi=:=jkl'.split('=:=')
# affiche ['abc', 'def', 'ghi', 'jkl']

Et à l’inverse :

"=:=".join(['abc', 'def', 'ghi', 'jkl'])
# affiche abc=:=def=:=ghi=:=jkl

Remarque: Si le séparateur est un terminateur, comme par exemple ;, ou\n, il conviendra d’utiliser d’abord la méthode strip. Voir Compléments en bas de page.

Remplacement: replace

replace est très pratique pour remplacer une sous-chaîne par une autre, avec une limite éventuelle sur le nombre de remplacements :

"abcdefabcdefabcdef".replace("abc", "zoo")
# affiche zoodefzoodefzoodef
"abcdefabcdefabcdef".replace("abc", "zoo", 1)
# affiche zoodefabcdefabcdef (un seul remplacement grâce au 3e argument)

modifier la casse d’une chaine

utiliser les méthodes title() (titre), upper() (mise en majuscule), lower() (minuscule).

nom = 'charles babbage'
nom.title()
# affiche Charles Babbage
nom.upper()
# affiche CHARLES BABBAGE

Les méthodes lstrip() (à gauche), rstrip() (droite), et strip() (à droite et à gauche) suppriment les espaces en trop dans les chaines.

à tester vous-même :

nom = ' charles babbage '
nom.strip()

Compléments sur les variables et types

Valeur et référence

Les variables en Python sont des références nommées.

Une variable est donc une étiquette associée à une valeur. Ce nom est à peu près quelconque, mais pour l’ordinateur il s’agit d’une référence désignant une adresse mémoire, c’est-à-dire un emplacement précis dans la mémoire vive.

À cet emplacement est stockée une valeur typée bien déterminée.

image issue du cours sur http://www.normalesup.org/

image issue du cours sur http://www.normalesup.org/

Cette valeur peut être en fait à peu près n’importe quel « objet » susceptible d’être placé dans la mémoire d’un ordinateur, par exemple : un nombre entier, un nombre réel, un nombre complexe, un vecteur, une chaîne de caractères, un tableau, une fonction, etc.

Le programme suivant permet de consulter l’adresse mémoire d’une variable:

a = 3
# Créer un objet de type int et lui associe le nom 'a'
type(a) #=> int
# Cet objet se trouve dans la mémoire de l'ordinateur
# à un endroit que l'on peut obtenir avec `id`:
id(a) #=> La position de l'objet nommé a dans la mémoire de l'ordinateur.
# Affiche
94875962855936

Pour aller plus loin : deux noms peuvent référencer le même objet en mémoire. L’opérateur == compare les valeurs, alors que l’opérateur is compare les références (l’identité, donc le résultat de id) :

a = [1, 2, 3]
b = [1, 2, 3]
a == b   # True : mêmes valeurs
a is b   # False : deux objets distincts en mémoire
c = a
c is a   # True : c et a référencent le même objet

Typage dynamique

Python est un langage à typage dynamique, ce qui signifie qu’il n’est pas necessaire de déclarer le type de donnée que représentera une variable (c’est la différence avec le typage statique). C’est l’interpréteur qui examine la donnée tout au long de la vie du programme et choisit le type.

Affectation simple et multiple

Affectation simple :

Les termes « affecter une valeur » ou « assigner une valeur » à une variable sont équivalents. Ils désignent l’opération par laquelle on établit un lien entre le nom de la variable et sa valeur (son contenu).

Exemple : a = 2

Lorsque l’ordinateur execute cette instruction, il va :

  • créer et mémoriser un nom de variable ;
  • lui attribuer un type bien déterminé (ce point sera explicité à la page suivante);
  • créer et mémoriser une valeur particulière;
  • établir un lien (par un système interne de pointeurs) entre le nom de la variable et l’emplacement mémoire de la valeur correspondante.

Le nom d’une variable est une référence, mémorisée dans une zone particulière de la mémoire que l’on appelle espace de noms, alors que la valeur correspondante est située ailleurs.

Affectation multiple :

Il est possible de réaliser une affectation pour plusieurs variables d’un seul coup :

a, b, c = 3, True, 'hello'
b
# affiche True

Compléments sur les strings

strip ou split

Si le séparateur est un terminateur, comme par exemple ;, ou\n, la liste résultat contient alors une dernière chaîne vide. En pratique, on utilisera la méthode strip, que nous allons voir ci-dessous, avant la méthode split pour éviter ce problème.

"abc;def;ghi;jkl;".split(';')
# retourne ['abc', 'def', 'ghi', 'jkl', '']
# le dernier element de la liste est ''

alors que:

"abc;def;ghi;jkl;".strip(';')
# retourne abc;def;ghi;jkl
# on a supprime le dernier ';'
# on peut alors utiliser la methode split:
"abc;def;ghi;jkl;".strip(';').split(';')
# retourne ['abc', 'def', 'ghi', 'jkl']

PARSER une chaine de caractères

“Parser” signifie analyser et convertir un script en un format interne que l’environnement d’exécution peut interpréter. Il s’agit d’une analyse syntaxique.

Soit la chaine de caractères suivante, issue d’une requête HTTP:

'GET /search ville=nice UTC=12'

On souhaite stocker dans 4 variables différentes les informations séparées chacune par des espaces ’ ‘.

méthode utilisant un slide

c = 'GET /search ville=nice UTC=12'
C1 = c[:3]
print(C1)
# GET
C2 = c[4:11]
print(C2)
# /search
C3 = c[12:22]
print(C3)
# ville=nice
C4 = c[23:]
print(C4)
# UTC=12

méthode utilisant une boucle non bornée

On ne connait pas à priori les positions des séparateurs dans la chaine (les espaces ’ ‘). On peut faire une recherche en parcourant la chaine du premier au dernier caractère avec l’instruction while i < len(c): caract = c[i] ...

i=0
caract = c[i]

# recherche des espaces dans la chaine c
while i < len(c):
    caract = c[i]
    if caract == ' ':
        print(i)
    i = i + 1
# affiche les index tels que c[i] == ' '
# 3
# 11
# 22

Les séparateurs se trouvent aux indices 3, 11, et 22. On sait alors que les 4 informations de la chaines sont:

C1 = c[:3]
C2 = c[4:11]
C3 = c[12:22]
C4 = c[23:]

méthode split

La méthode la plus adaptée pour réaliser le parsing d’une chaine, c’est:

c.split(' ')
# retourne les elements dans une liste
# ['GET', '/search', 'ville=nice', 'UTC=12']

Suite

Cours
TP1 Types simples
TD1 Variables et types natifs

Liens

types construits

Ce chapitre comprend 4 pages:

  • Cours
  • TP decouverte: TP2
  • TP copie par valeur et reference, visualisation: TP2a
  • TP application du cours: TP2b

Cette page aborde les notions avancées sur les types construits (listes, tuples, dictionnaires). Il peut être nécessaire de consulter les notions de base sur les : boucles et listes.

Après la lecture, on traitera le TP sur les variables utilisant Pythontutor.

Les structures de données et les types construits

Les structures de données définissent la manière avec laquelle sont stockées les données dans un langage.

Les types construits, comme les listes et les dictionnaires sont construits à partir des types de bases que l’on a déjà vus. Ce sont d’autres moyens d’organiser et d’agencer les types de base dans d’autres structures.

Les types construits peuvent stocker d’autres types construits.

On distingue les types séquentiels (liste, tuple et string) des mappages (dictionnaires).

Une séquence est une structure de données qui stocke une collection d’éléments dans un ordre déterminé. On accède aux éléments par leur indice (leur rang dans la séquence).

Pour les mappages, il s’agit d’une collection de type clé:valeur. On accède à une valeur par sa clé.

Listes

Definition: Une liste est une collection ordonnée d’objets. Au niveau de la mémoire de l’ordinateur, une liste porte un nom, et fait référence à des espaces mémoire pour chaque élément de liste. Ces éléments (espaces mémoires) font eux-mêmes référence aux emplacements mémoire qui stockent les valeurs ou objets.

En python: Une liste est entourée de crochets [ ]

Les éléments contenus peuvent être de tout type.

On accède à un élément d’une liste grâce à sa position, appelée indice. Le premier élément a pour indice zero.

La liste `voyelles` est une collection contenant les caractères

La liste `voyelles` est une collection contenant les caractères

Un indice négatif donne accès à la liste à partir du dernier élément.

Construire une liste

Construire une liste de manière directe.

voyelles = ['e','i','o']
voyelles[0]
# affiche 'e'
voyelles[-1]
# affiche 'o'
voyelles[-2]
# affiche 'i'
voyelles
# affiche ['e', 'i', 'o']

Modifier un élément de liste:

Les listes sont mutables : On peut modifier un seul de ses éléments à partir de son indice :

voyelles[2] = 'y'
voyelles
# affiche ['e', 'i', 'y']

Ceci n’est pas possible avec le type natif str, qui, lui, est un type non mutable.

Construire une liste avec une boucle (accumulation)

Les boucles while etfor permettent d’itérer sur les éléments d’une séquence.

# Boucle while
squares = []
i = 0
while i <= 100:
  squares.append(i ** 2)
  i += 1

# Boucle for
squares = []
for i in range(101):
  squares.append(i ** 2)

Construire une liste par compréhension

Pour construire une liste par compréhension, on place une boucle bornée à l’INTERIEUR des crochets. Cela crée un élément dans la liste pour chaque valeur de l’itérable.

# Définition par compréhension
squares = [i ** 2 for i in range(10)]
squares
# affiche [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

On peut combiner les expressions entre les crochets, en ajoutant par exemple une condition. Ainsi, si l’on veut uniquement le carré des nombres pairs (if i % 2 == 0):

# carre des nombres pairs
squares = [i ** 2 for i in range(101) if i % 2 == 0]

Pour construire un tableau à deux dimensions (une liste de listes), on peut imbriquer deux compréhensions de liste:

M = [[0 for j in range(3)] for i in range(3)]
M
# affiche [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

Appartenance

On utilise le mot-clé in. Le test retourne True ou False

aeroports = ['CDG','ORY','LIS']
'ORY' in aeroports
# retourne True
'NY' in aeroports
# retourne False

Méthodes de listes

Pour commencer, rappelons comment retrouver la liste des méthodes définies sur le type list :

help(list)

append

append(element) ajoute un élément en fin de liste

aeroports = ['CDG','ORY','LIS']
aeroports.append('NY')
aeroports
# affiche ['CDG', 'ORY', 'LIS', 'NY']

pop

pop() supprime le dernier élément et renvoie sa valeur.

aeroports = ['CDG','ORY','LIS','NY']
aeroports.pop()
# affiche 'NY'
aeroports
# affiche ['CDG', 'ORY', 'LIS']

index

index(element) retourne la position (index) de cet élément dans la liste (ou du moins la première occurence s’il y en a plusieurs).

aeroports = ['CDG','ORY','LIS','NY']
aeroports.index('ORY')
# retourne 1

insert

insert(index, element) insère l’élément à l’index précisé.

aeroports = ['CDG','ORY','LIS','NY']
aeroports.insert(2,'LCY')
# la liste aeroports est alors
# ['CDG', 'ORY', 'LCY', 'LIS', 'NY']

remove et del

remove(element) supprime un élément d’une liste. Si l’élément apparait plusieurs fois dans la liste, seule la premiere occurence est supprimée.

del liste[indice] supprime l’élément de la liste à partir de son indice.

aeroports = ['CDG','ORY','LIS','NY']
aeroports.remove('LIS')
aeroports
# affiche ['CDG', 'ORY', 'NY']
del aeroports[0]
aeroports
# affiche ['ORY', 'NY']

extend

extend(list) est une méthode utile pour ajouter les éléments d’une autre liste, à la fin:

L1 = ['lundi','mardi']
L2 = ['mercredi','jeudi']
L1.extend(L2)
print(L1)
# affiche ['lundi', 'mardi', 'mercredi', 'jeudi']

reverse

reverse() est une méthode qui renverse la liste (en place, renvoie None)

L1.reverse()
print(L1)
# affiche ['jeudi', 'mercredi', 'mardi', 'lundi']

Autres manipulations de listes

découpe d’une liste

une découpe est une partie de liste, spécifiée à partir des indices :

etats = ['CH','GB','NL','PL','RO','SK']
etats[2:4]
# affiche ['NL', 'PL']
etats[:2] # sans specifier le premier indice
# affiche ['CH', 'GB'] # commence au début
etats[3:] # sans specifier l'indice de fin
# affiche ['PL', 'RO', 'SK'] # jusqu'à la fin

Copie d’une liste

Une copie d’une liste permet d’utiliser le contenu de la liste copiée sans affecter la liste d’origine (voir TP sur les variables). C’est une copie par valeurs.

Attention: L’instruction $L1 = L2$ est à eviter lorsque l’on veut copier une liste.

A la place, on peut :

  • la découper sans mentionner les 2 indices:
etats = ['CH','GB','NL','PL']
mes_etats = etats[:] # liste copiée par valeur dans mes_etats
  • utiliser la fonction list:
etats = ['CH','GB','NL','PL']
mes_etats = list(etats) # liste copiée par valeur dans mes_etats
  • utiliser la fonction copy:
etats = ['CH','GB','NL','PL']
mes_etats = etats.copy()

On peut alors vérifier qu’il s’agit maintenant d’une copie par valeurs :

mes_etats.append('DK')
mes_etats
# affiche ['CH', 'GB', 'NL', 'PL', 'DK']
etats
# affiche ['CH', 'GB', 'NL', 'PL']

Sans cette astuce, la copie se ferait par référence (rappelez-vous: Liste = mutable)

Trier une liste

Il y a 2 fonctions de tri :

  • La fonction sorted renvoie une copie de la liste triée dans l’ordre croissant (numérique pour des nombres, alphabétique pour des chaînes) sans modifier la liste d’origine.
L = [9, 5, 1, 3, 4]
sorted(L)
# affiche [1, 3, 4, 5, 9]

Puis:

L
# affiche toujours [9, 5, 1, 3, 4]
  • La méthode sort permet de trier la liste en place.
L = [9, 5, 1, 3, 4]
L.sort()
# L est transformee en
# [1, 3, 4, 5, 9]

Choix d’un élément aléatoire dans une liste.

Il faut importer la fonction choice de la librairie random:

from random import choice
L = [1, 10, 100, 1000]
print(choice(L))

Affiche un élément au hasard: 1, 10, 100 ou 1000.

Vider une liste

On utilise la méthode clear()

L = [9, 5, 1, 3, 4]
L.clear()
print(L)
# Affiche []

Tuples

Un tuple est entouré de parenthèses ( )

On accède à l’un des éléments à l’aide de son indice, comme pour les listes.

Par contre, le tuple est non mutable : on ne peut pas en modifier l’un de ses éléments. Il faut refaire, au besoin, une affectation complète de tout le tuple.

elementaire = ('CP','CE1','CE2')
elementaire[1]
# affiche 'CE1'
elementaire[2] = 'CM2'
# TypeError: 'tuple' object does not support item assignment
elementaire = ('CP','CE1','CM2')
elementaire
# affiche ('CP', 'CE1', 'CM2')

Non mutable mais avec des éléments mutables:

t = (0, [1, 2])
t[1].append(3)
print(t) 
# Affiche (0, [1, 2, 3]) ← le tuple n'a pas changé, mais son contenu change

L’immuabilité du tuple garantit que ses références ne changent pas, pas que les objets référencés sont eux-mêmes figés.

Mappages : les dictionnaires

Un mappage est une structure de données qui relie 2 informations ou plus, appelées paires clé : valeur. Aussi appelée table de hashage. En python, cette structure est le dictionnaire.

Un dictionnaire est entouré d’accolades { }. Les paires sont séparées par une virgule.

Création d’un dictionnaire

dic = {}     # creer un dictionnaire vide
dic = dict() # Variante
dic = {"nom": "Alice", "âge": 30} # Création d'un dictionnaire déjà peuplé

Par exemple, pour créer un dictionnaire non vide, on peut faire :

capitales = {'France':'Paris','Italie':'Rome','Allemagne':'Berlin'}

Mais on peut aussi ajouter chaque paire en faisant :

capitales = {} # dictionnaire vide
capitales['France'] = 'Paris' # creation ou ajout du couple 'France':'Paris'
print(capitales)
# affiche {'France': 'Paris'}
capitales['Italie'] = 'Rome'
print(capitales)
# affiche {'France': 'Paris', 'Italie': 'Rome'}

Dans cet exemple, les clés du dictionnaire capitales sont les pays (“France”, “Italie”…) et les valeurs sont les villes (“Paris”,“Rome”,…).

On ne peut placer comme clé d’un dictionnaire que des objets de type non mutable (on dit qu’ils doivent être hashables).

Accéder au contenu du dictionnaire

Pour les exemples qui suivent, on part de :

capitales = {'France': 'Paris', 'Italie': 'Rome'}

Une valeur associée à une clé

Pour accéder à une valeur, on utilise la clé comme index:

print(capitales['France'])
# affiche 'Paris'

Toutes les clés

Pour accéder aux clés d’un dictionnaire: on utilisera la méthode keys avec par exemple capitales.keys()

for pays in capitales.keys():
  print(pays)
# affiche
# France
# Italie
print(capitales.keys())
# affiche dict_keys(['France', 'Italie'])

ou bien, avec une version plus courte:

for pays in capitales:
  print(pays)
# affiche
# France
# Italie

Toutes les valeurs

Pour accéder aux valeurs: on utilise la méthode values, avec par exemple capitales.values()

for ville in capitales.values():
  print(ville)
# affiche
# Paris
# Rome
print(capitales.values())
# affiche dict_values(['Paris', 'Rome'])

Tous les items clé:valeur

Pour accéder aux paires clé-valeurs: méthode items, avec par exemple capitales.items()

for pays, ville in capitales.items():
  print(pays, ville)
# affiche
# France Paris
# Italie Rome
print(capitales.items())
# affiche dict_items([('France', 'Paris'), ('Italie', 'Rome')])

Dans ce dernier exemple:

  • l’iterable capitales.items() donne un nouveau tuple à chaque itération.
  • on déclare 2 variables pays et ville, qui permettent de destructurer le tuple, et récupérer le pays dans pays et la ville dans ville.

Modifier le contenu

Ajouter puis modifier un couple clé:valeur:

Exemple complet:

capitales = {'France':'Paris'}
capitales['Italie'] = 'Rome'      # ajouter
capitales['Egypte'] = 'Alexandrie'# ajouter
print(capitales)
# affiche {'France': 'Paris', 'Italie': 'Rome', 'Egypte': 'Alexandrie'}
capitales['Egypte'] = 'Le Caire'  # modifier
print(capitales)
# affiche {'France': 'Paris', 'Italie': 'Rome', 'Egypte': 'Le Caire'}

Supprimer un couple: del

del capitales['Egypte']
print(capitales)
# affiche {'France': 'Paris', 'Italie': 'Rome'}

Appartenance

key in dic # Renvoie True ou False, selon que key est ou non une cle
val in dic.values() # Renvoie True ou False, selon que val est ou non une valeur

Copier un dictionnaire

On peut utiliser la fonction dict pour faire une copie par valeur d’un dictionnaire :

mes_capitales = dict(capitales)

Sans cette astuce, la copie se ferait par référence (Dictionnaire = mutable)

Vider un dictionnaire

On peut aussi aussi utiliser la méthode clear()

Objets mutables et non mutables

En Python, il existe deux types d’objets: les mutables (listes, dictionnaires, sets, objets customisés) et les non mutables (string, int, float, bool, tuple, None).

Les mutables sont ceux qu’on peut modifier après leur création. Les non mutables sont ceux qu’on ne peut pas modifier après création.

Lorsque 2 références pointent sur le même objet, ce qui est possible avec les mutables, il faut s’attendre à ce que la modification de l’un entraine celle de l’autre (effet de bord).

C’est le mot-clé IS qui va permettre de tester si 2 noms pointent vers la même réference en mémoire:

x = ["apple", "banana", "cherry"]
y = ["apple", "banana", "cherry"]
x == y
# affiche True
x is y
# affiche False

Pour plus de précisions sur ces différences, voir le TP utilisant Pythontutor

Portée des variables

Un effet de bord est une modification d’une variable qui affecte l’état du programme en dehors de la fonction où elle a lieu. Cela peut arriver avec des variables globales, déclarées en dehors de toute fonction.

Pour une variable x non mutable, déclarée dans le corps du programme, celle-ci peut être lue dans une fonction où elle n’a pas été definie. Par contre, pour la modifier dans cette fonction, il faudra la déclarer avec global x dans cette fonction.

Exemple: lire et essayer de modifier

vies = 3

def lire():
    print(vies)
    
def modifier():
    vies=vies-1
    print(vies)
    
> lire()
3
> modifier()
UnboundLocalError: local variable 'vies' referenced before assignment

Exemple: lire et modifier en utilisant l’instruction global

vies = 3

def lire():
    print(vies)
    
def modifier():
    global vies
    vies=vies-1
    print(vies)
    
> lire()
3
> modifier()
2

Suite

Cours
TP2 decouverte du cours
TD2a les types construits, les copies par valeur et reference sur Pythontutor
TD2b le parcours de liste, compréhension de liste et tracé graphique

tables de données

Ce chapitre contient 4 pages:

  • cours
  • TP tableur: TP3a
  • TP avec visualisation, tableau de notes: TP3b
  • TP sur les sustemes scolaires européens: TP3c

Les tables de données en Python

Ce cours s’appuie sur les notions déjà vues sur les types simples et les types construits (listes, dictionnaires, mutabilité). Il prépare l’exercice sur la table des pays.

Une grande partie des données que l’on manipule en informatique se présentent sous forme de tables : un ensemble d’enregistrements (une ligne par individu, par mesure, par pays…), chacun décrit par les mêmes attributs (les colonnes). C’est le cas d’une feuille de tableur, d’une table de base de données, ou d’un fichier .csv.

Modéliser une table avec des listes

La structure la plus simple pour représenter une table en Python est une liste de listes : chaque ligne de la table est elle-même une liste.

Par convention, on place souvent en première ligne les étiquettes de colonnes (le nom de chaque attribut), puis une ligne par individu :

table = [
    ["Pays", "Nb élèves secondaire", "Jours de vacances/an", "Durée secondaire (ans)"],
    ["France", 5660000, 112, 7],
    ["Allemagne", 6900000, 65, 9],
    ["Espagne", 3500000, 105, 6],
    ["Grèce", 700000, 119, 6],
]

Accéder à une valeur

Une table étant une liste de listes, on accède à une valeur précise avec un double indiçage : table[i][j] désigne la valeur de la ligne i, colonne j.

table[0]
# affiche ['Pays', 'Nb élèves secondaire', 'Jours de vacances/an', 'Durée secondaire (ans)']
table[1]
# affiche ['France', 5660000, 112, 7]
table[1][0]
# affiche 'France'
table[1][1]
# affiche 5660000

Parcourir une table

Parcourir les lignes de données (sans l’en-tête) se fait avec une boucle bornée classique :

for ligne in table[1:]:
    print(ligne)

Pour parcourir les lignes et colonnes, on imbrique une seconde boucle, en s’appuyant sur range(len(table[0])) :

for ligne in table[1:]:
    # pour chaque ligne de datas
    for j in range(len(ligne)):
        # j est le numero de colonne
        print(table[0][j], ":", ligne[j])
    print("---")

… Affiche …

Pays : France
Nb élèves secondaire : 5660000
Jours de vacances/an : 112
Durée secondaire (ans) : 7
---
Pays : Allemagne
Nb élèves secondaire : 6900000
Jours de vacances/an : 65
Durée secondaire (ans) : 9
---
Pays : Espagne
Nb élèves secondaire : 3500000
Jours de vacances/an : 105
Durée secondaire (ans) : 6
---
Pays : Grèce
Nb élèves secondaire : 700000
Jours de vacances/an : 119
Durée secondaire (ans) : 6
---

Traitement des données en ligne

Pour les exemples qui suivent, le traitement des données d’une table porte sur ses valeurs numériques. Par exemple, avec la somme des données de chaque ligne et leur affichage:

Le parcours de la table entière nécéssite d’utiliser deux boucles imbriquées, afin de parcourir toutes les lignes (indice i), et toutes les colonnes de chaque ligne (indice j).

datas = [[5660000, 112, 7],
    [6900000, 65, 9],
    [3500000, 105, 6],
    [700000, 119, 6]]

for i in range(len(datas)):
    # on initialise s à chaque nouvelle ligne
    s = 0
    for j in range(len(datas[0])):
        s = s + datas[i][j]
    # on affiche s a la fin de chaque ligne
    print(s)

Traitement de données en colonne

On souhaite faire la somme des valeurs dans la colonne c. On propose cette fois un parcours de la table datas par élément, avec for ligne in datas:

datas = [[5660000, 112, 7],
    [6900000, 65, 9],
    [3500000, 105, 6],
    [700000, 119, 6]]

c = 1
s = 0
for ligne in datas:
    s += ligne[c]
print(s)

Copier une table

Le cours sur les types construits a montré que copier une liste par simple affectation (copie = original) crée un alias : les deux noms désignent le même objet.

Pour une liste « plate », on évite ce piège avec original[:] ou list(original). Mais pour une liste de listes, il faut être plus prudent :

donnees = table[1:]           # copie de la liste externe
# donnees vaut [['France', 5660000, 112, 7],... ['Grèce', 700000, 119, 6]]
donnees[1][1] = 0
print(table[1][1])
# affiche 0 !! table a été modifiée alors qu'on n'a modifié que "donnees"
print(table)
# [['Pays',  'Nb élèves secondaire',...], ['France', 0, 112, 7],... ['Grèce', 700000, 119, 6]]

table[1:] crée bien une nouvelle liste externe, mais ses éléments — les lignes — restent les mêmes objets que dans table. C’est une copie dite de surface (shallow copy) : seul le premier niveau est dupliqué.

Pour obtenir une copie totalement indépendante, y compris des lignes, il faut une copie profonde (deep copy), fournie par le module copy :

from copy import deepcopy

donnees = deepcopy(table[1:])
donnees[0][1] = 0
table[1][1]
# affiche 5660000  # table n'a pas été modifiée cette fois

Rechercher un extremum dans une colonne

Rechercher, par exemple, le pays ayant le plus grand nombre d’élèves (colonne d’indice 1) suit le schéma classique de recherche de maximum : on mémorise le meilleur candidat rencontré jusqu’ici, et on le met à jour à chaque ligne qui fait mieux.

meilleure_ligne = table[1]
# meilleure_ligne vaut ["France", 5660000, 112, 7]
for ligne in table[2:]:
    # a la premiere iteration
    # ligne[1] vaut 6900000
    if ligne[1] > meilleure_ligne[1]:
        meilleure_ligne = ligne

print(meilleure_ligne[0], meilleure_ligne[1])
# affiche Allemagne 6900000

Trier une table selon une colonne

Le cours sur les types construits a présenté sorted et sort pour trier une liste dans son ordre naturel. Ces deux outils acceptent en réalité un paramètre optionnel, key, qui indique selon quel critère comparer les éléments — utile ici puisqu’on ne veut pas trier des lignes entières « au hasard », mais selon une colonne précise.

key attend une fonction qui, appliquée à un élément, renvoie la valeur à utiliser pour la comparaison. Pour une fonction aussi courte, on utilise en général une fonction lambda (fonction anonyme, écrite en une ligne) plutôt qu’une fonction def complète :

lambda ligne: ligne[1]
# équivaut à une fonction sans nom qui, à une ligne, associe ligne[1]

On peut alors trier la table selon le nombre d’élèves, du plus grand au plus petit :

tri_par_effectif = sorted(table[1:], key=lambda ligne: ligne[1], reverse=True)
for ligne in tri_par_effectif:
    print(ligne[0], ligne[1])
# affiche
# Allemagne 6900000
# France 5660000
# Espagne 3500000
# Grèce 700000

Documentation (extrait) :

sorted(iterable, key=None, reverse=False)
    - key : fonction appliquée à chaque élément avant comparaison
    - reverse=True : tri décroissant plutôt que croissant

Tables et dictionnaires

Se repérer dans un dictionnaire

Les tables peuvent être représentées par des dictionnaires imbriqués.

On doit alors accéder à un élément avec un accès profond:

eleves = {'Chloé': {'maths': 12, 'nsi': 18}}
eleves['Chloé']['nsi']    # 18

Deux accès successifs : eleves['Chloé'] renvoie un dictionnaire, sur lequel on applique un second accès ['nsi'].

Entrainez vous avec cette application

Passer d’une table à des dictionnaires

Accéder à une valeur par sa position (ligne[1]) est efficace mais peu lisible : rien n’indique, à la lecture du code, que l’indice 1 correspond au nombre d’élèves. Une alternative consiste à représenter chaque ligne par un dictionnaire, où les clés sont les étiquettes de colonnes.

etiquettes = table[0]
ligne_france = table[1]

France = {
    etiquettes[0]: ligne_france[0],
    etiquettes[1]: ligne_france[1],
    etiquettes[2]: ligne_france[2],
    etiquettes[3]: ligne_france[3],
}
# affiche {'Pays': 'France', 'Nb élèves secondaire': 5660000, 'Jours de vacances/an': 112, 'Durée secondaire (ans)': 7}

On peut généraliser cette construction à toutes les lignes de la table, à l’aide d’une boucle, pour obtenir un dictionnaire de dictionnaires — une structure très courante pour représenter des données structurées :

pays_dict = {}
etiquettes = table[0]

for ligne in table[1:]:
    nom_pays = ligne[0]
    pays_dict[nom_pays] = {}
    for j in range(1, len(etiquettes)):
        pays_dict[nom_pays][etiquettes[j]] = ligne[j]

pays_dict['France']
# affiche {'Nb élèves secondaire': 5660000, 'Jours de vacances/an': 112, 'Durée secondaire (ans)': 7}

Importer une table depuis un fichier CSV

Un fichier CSV (Comma-Separated Values) stocke une table sous forme de texte : chaque ligne du fichier est une ligne de la table, et les valeurs sont séparées par un caractère précis (une virgule , le plus souvent, mais un point-virgule ; est fréquent dans les fichiers produits en France, la virgule y étant déjà utilisée comme séparateur décimal).

Le module csv de la bibliothèque standard permet de lire un tel fichier sans avoir à découper les lignes soi-même avec split :

import csv

with open('datas/classe.csv', newline='') as csvfile:
    spamreader = csv.reader(csvfile, delimiter=';')
    classe = []
    for row in spamreader:
        classe.append(row)

Décomposons ce script :

  • open('datas/classe.csv', newline='') ouvre le fichier. L’argument newline='' est recommandé par la documentation de csv pour éviter des problèmes de fin de ligne selon le système d’exploitation.
  • csv.reader(csvfile, delimiter=';') construit un objet itérable : chaque itération donne la ligne suivante du fichier, déjà découpée en liste de chaînes de caractères, selon le séparateur indiqué (ici ;).
  • La boucle for row in spamreader: parcourt ces lignes une par une, et le script les accumule dans la liste classe avec append — la même technique de construction de liste par accumulation que celle vue avec while/for dans le TP sur les listes.

À la fin, classe est une liste de listes, exactement comme la table table du début de ce cours — on peut donc lui appliquer tout ce qui vient d’être vu : parcours, copie, recherche d’extremum, tri par clé, conversion en dictionnaires.

Point de vigilance : le module csv lit toujours les valeurs comme des chaînes de caractères, y compris les nombres. Une valeur "5660000" lue dans un fichier CSV doit être convertie explicitement avec int(...) ou float(...) avant tout calcul (voir le cours sur les conversions de types).

Pour aller plus loin : le module csv propose aussi csv.DictReader, qui utilise automatiquement la première ligne du fichier comme clés et renvoie directement chaque ligne sous forme de dictionnaire — ce qui réalise en une seule instruction ce que la section précédente a construit à la main :

with open('datas/classe.csv', newline='') as csvfile:
    lecteur = csv.DictReader(csvfile, delimiter=';')
    for ligne in lecteur:
        print(ligne)
# chaque "ligne" est un dictionnaire, par exemple :
# {'Pays': 'France', 'Nb élèves secondaire': '5660000', ...}

Complexité d’accès : dictionnaires imbriqués vs listes de listes

1. Le paragraphe de cours

Un dictionnaire Python est implémenté à l’aide d’une table de hachage : chaque clé est transformée par une fonction de hachage en un indice qui pointe directement vers l’emplacement mémoire où se trouve la valeur associée. Ainsi, accéder à dico[cle] ne nécessite pas de parcourir le dictionnaire élément par élément : on calcule l’emplacement directement, ce qui donne une complexité en moyenne constante, $O(1)$, quel que soit le nombre $n$ de couples clé/valeur stockés. Cette propriété se conserve pour les dictionnaires imbriqués : accéder à dico[cle1][cle2] revient à effectuer deux accès en $O(1)$ successifs (un par niveau d’imbrication), donc une complexité globale en $O(1)$ elle aussi, indépendante de la taille du dictionnaire à chaque niveau.

Il en va tout autrement pour une liste de listes. Une liste ne connaît que des positions numériques (des indices 0, 1, 2, ...) : elle ne peut pas retrouver un élément à partir d’une « clé » sans le comparer un par un aux éléments qu’elle contient. Rechercher une valeur associée à un identifiant dans une liste de listes impose donc un parcours linéaire, de complexité $O(n)$ dans le pire des cas (et $O(n \times m)$ si l’on doit chercher dans des sous-listes de taille $m$), $n$ étant le nombre d’éléments parcourus avant de trouver (ou non) celui qui est cherché.

La différence essentielle est donc la suivante : le temps d’accès à une donnée dans un dictionnaire ne dépend (en moyenne) pas du nombre d’éléments qu’il contient, alors que dans une liste, ce temps croît avec le nombre d’éléments à parcourir. C’est ce qui justifie l’usage des dictionnaires — y compris imbriqués — dès qu’une structure de données doit permettre des recherches fréquentes par identifiant plutôt que par position.


2. Schéma

a. Dictionnaire — accès direct par hachage

flowchart LR
    K["Clé cherchée<br/>'Chloé'"] --> H["Fonction de hachage<br/>hash('Chloé')"]
    H --> I["Indice calculé<br/>ex : 5"]
    I --> B["Case n°5 de la table<br/>→ valeur associée"]

    style K fill:#e8f4ff,stroke:#3b82f6
    style H fill:#fff7e6,stroke:#f59e0b
    style I fill:#fff7e6,stroke:#f59e0b
    style B fill:#e7f9ed,stroke:#22c55e

Un seul calcul (le hachage de la clé) suffit à localiser la donnée : le nombre d’étapes ne dépend pas du nombre d’éléments stockés.

b. Liste de listes — parcours séquentiel

flowchart LR
    D["Élément cherché<br/>'Chloé'"] --> C0["case 0<br/>'Alice' ≠ 'Chloé' ?"]
    C0 -->|non| C1["case 1<br/>'Bilal' ≠ 'Chloé' ?"]
    C1 -->|non| C2["case 2<br/>'Chloé' = 'Chloé' ?"]
    C2 -->|oui, trouvé !| R["valeur associée"]

    style D fill:#e8f4ff,stroke:#3b82f6
    style C0 fill:#fdeaea,stroke:#ef4444
    style C1 fill:#fdeaea,stroke:#ef4444
    style C2 fill:#e7f9ed,stroke:#22c55e
    style R fill:#e7f9ed,stroke:#22c55e

Ici, il faut comparer la clé cherchée à chaque élément, un par un, jusqu’à la trouver (ou parcourir toute la liste si elle est absente) : le nombre d’étapes croît avec le nombre d’éléments stockés.

3. Exemple chiffré : mesure du temps d’exécution

Le code ci-dessous compare, pour des tailles croissantes de données, le temps nécessaire pour rechercher un élément :

  • dans un dictionnaire (recherche par clé) ;
  • dans une liste de listes de la forme [[identifiant, valeur], [identifiant, valeur], ...] (recherche par parcours).
import time

def construire_dictionnaire(n):
    return {f'id_{i}': i for i in range(n)}

def construire_liste_de_listes(n):
    return [[f'id_{i}', i] for i in range(n)]

def recherche_dictionnaire(dico, cle):
    return dico[cle]

def recherche_liste(liste, cle):
    for identifiant, valeur in liste:
        if identifiant == cle:
            return valeur
    return None

tailles = [1000, 10000, 100000, 1000000]

print(f"{'taille':>10} | {'temps dict (s)':>15} | {'temps liste (s)':>16}")
for n in tailles:
    dico = construire_dictionnaire(n)
    liste = construire_liste_de_listes(n)
    cle_cherchee = f'id_{n - 1}'  # dernier élément : pire cas pour la liste

    debut = time.perf_counter()
    recherche_dictionnaire(dico, cle_cherchee)
    temps_dict = time.perf_counter() - debut

    debut = time.perf_counter()
    recherche_liste(liste, cle_cherchee)
    temps_liste = time.perf_counter() - debut

    print(f"{n:>10} | {temps_dict:>15.8f} | {temps_liste:>16.8f}")

Résultat attendu (ordre de grandeur, les valeurs exactes dépendent de la machine) :

    taille |  temps dict (s) |  temps liste (s)
      1000 |      0.00000030 |       0.00003500
     10000 |      0.00000030 |       0.00035000
    100000 |      0.00000030 |       0.00350000
   1000000 |      0.00000030 |       0.03500000

Interprétation : le temps de recherche dans le dictionnaire reste (à peu près) constant quelle que soit la taille n, conformément à la complexité $O(1)$. Le temps de recherche dans la liste de listes, lui, est multiplié par 10 à chaque fois que n est multiplié par 10 : il croît linéairement avec n, conformément à la complexité $O(n)$.

Suite

Cours
TP3a Tableur
TP3b Tableau de notes et algorithmes (Visualisation)
TP3c Systemes scolaires européens

dataframe

Les bases avec pandas

présenter les données, calculer sur des colonnes

Pandas va permettre de lire et de modifier des tableaux (DataFrames). Chaque colonne de ton DataFrame sera appelée « descripteur ». La manipulation d’un dataframe peut ressembler à celle d’une base de données (voir SQL).

Exemple: La table suivante est issu de l’import d’une base de données d’exoplanètes:

Cette table fera l’objet d’une étude spécifique: ici

Présenter les résultats: CSV => Dataframe

Importer les données depuis un fichier csv

  • Les courbes de transit vont permettre de mesurer les valeurs de profondeur de transit $\delta$ et de durée de transit $\tau$.
  • Ces valeurs seront reportées dans un fichier csv avec les autres informations sur les planètes et leur étoile. Utiliser un tableur. Attention à bien utiliser des points comme séparateur décimal.
tableau rempli à l'aide d'un tableur

tableau rempli à l'aide d'un tableur

  • Exporter (ou enregistrer) en format csv.

On peut vérifier en ouvrant le fichier csv que les données sont mises dans un format particulier (séparation à l’aide d’un point virgule…)

fichier csv

fichier csv

  • L’import depuis pandas se fait alors de la manière suivante: (rien de plus simple)
df = pd.read_csv('exoplanetes.csv',sep=';')
df

Ajouter les colonnes utiles aux calculs

un dataframe se comporte comme un dictionnaire dont les clefs sont les noms des colonnes et les valeurs sont des séries:

G = 6.67e-11
R_Jup = 71e6 
M_Jup = 6.9911e7
df['tau']=(df['fin_transit']-df['debut_transit'])*24*3600
df['delta']=1-df['lum_min']

df['M_star']=7.158780e+29 # pour TOI-270
df['R_star']=257512600.0  # pour TOI-270
df['R_p']= np.sqrt(df['delta']) * df['R_star']
df['radius']=df['R_p']/R_Jup # pour exprimer en R_Jup
# vitesse planete : V_p = 2*R_star/tau
df['V_p']= 2*df['R_star']/df['tau']
# rayon orbital : r = G*M_star/V_p**2
df['r_orb']= G * df['M_star']/df['V_p']**2
# periode revolution: T = 2*np.pi*r/V_p
df['T'] = 2*np.pi*df['r_orb']/df['V_p'] # en s
df['T_jours'] = df['T']/(24*3600)  # en jours terrestres
df

Autres méthodes (compléments)

Importer les données d’une liste ou d’un dictionnaire python

Les données relatives à la planète peuvent être mises dans une liste dont l’ordre pourrait être par exemple:

'planete','etoile','M_star','R_star','delta','tau','date_debut_transit'

Par exemple, ci-dessous, dans la liste planete1: (la date de debut de transit est sous forme annee,mois,jour,heure)

planete1 = ['TOI 270-01','TOI 270',Msol*0.36,Rsol * 0.37,0.0044,4600,(2024,6,23,5)]
df1 = pd.DataFrame([planete1],columns=['planete','etoile','M_star','R_star','delta','tau','date_debut_transit'])
df

Les calculs se font en créant une nouvelle colonne dans le dataframe. Par exemple, pour le calcul du rayon de la planète (en fonction de delta):

df1['R_p']= np.sqrt(df1['delta']) * df1['R_star']
df1

On peut créer également un Dataframe à l’aide d’un dictionnaire: (remplacer les valeurs None par celles de la planète)

planete2 = {
    'planete':'TOI 270-02',
    'etoile':'TOI 270',
    'M_star':None,
    'R_star':None,
    'delta':None,
    'tau':None,
    'date_debut_transit':None
}
df2 = pd.DataFrame([planete2])
df2

Remarque: On peut ajouter plusieurs planètes dans la liste, avec par exemple: pd.DataFrame([planete1,planete2,...])

On peut alors ajouter les 2 Dataframes dans un nouveau tableau. Il s’agit d’une opération de concaténation:

pd.concat([df1,df2],ignore_index = True)

Remarques:

  • le premier paramètre de la fonction doit être un itérable: toujours mettre la ligne entre []
  • Les tableaux concaténés peuvent avoir des nombres de colonnes différents. La valeur placée dans le tableau est alors NaN. Cette valeur peut être modifiée par la suite.
  • le paramètre ignore_index = True permet de recréer une numérotation de l’index et eviter les doublons. Dans l’exemple proposé ici, cela permet d’eviter d’avoir 2 lignes avec l’index 0.

fusionner des tableaux aux etiquettes différentes

Les tableaux doivent avoir les mêmes etiquettes de colonne si on veut ajouter leur ligne l’une sous l’autre. Dans le cas contraire, il faudra renommer les colonnes.

utile après l’import d’une base de données/sql

D = {
    'planete':'TOI 270-01',
    'etoile': 'TOI 270'
    }
df_new_line = pd.DataFrame.from_dict([D])
df_new_line
df_new_line_2 = pd.DataFrame([{'_name':'TOI 270-02','star_name':'TOI 270'}])
df_new_line_2
df_new_line_2 = df_new_line_2.rename(columns={'_name': 'planete','star_name':'etoile'})
df_new_line_2
df = pd.concat([df_new_line,df_new_line_2],ignore_index=True)
df

Reduire le dataframe: iloc

Le dataframe se manipule comme un numpy.array avec iloc:

On place alors les bornes des indices de lignes, puis de colonnes pour reduire le dataframe:

$$df.iloc[ligne\\_debut:ligne\\_fin+1,colonne\\_debut:colonne\\_fin+1]$$

Par exemple, pour reduire le df aux lignes 0 à 9, et en prenant toutes les colonnes:

df.iloc[0:10, :]

Pour reduire le dataframe aux colonnes 2 et 4, en prenant toutes les lignes:

df.iloc[:, [2,4]]

Langage de requête

Projection (SELECT en sql): reduire le nombre de colonnes (equivalent de select en sql)

df[['_name','mass']]
df

Selection selon un critère (WHERE =,>, … en sql): lignes (équivalent de where en sql)

df[df['mass']>=1]

Selection à partir d’une liste de noms, comme en SQL: WHERE .. IN ( valeur1, valeur2, … )

names = ['TOI-270 d','TOI-270 b','TOI-270 c']
df_p = df[df['_name'].isin(names)]

Recherche d’un motif, equiv SQL de LIKE ‘motif%’:

# Equivalent de LIKE en SQL
df[df['_name'].str.startswith('TOI-270')]

Trier le dataframe selon une colonne, par ordre decroissant, equiv SQL de ORDER BY … DESC

df.sort_values('mass', ascending=False, inplace=True, ignore_index=True)

base de données d’exoplanetes et python

Fonctions

Ce cours comprend 2 pages:

  • Cours sur les fonctions: Lien
  • TP4: Lien

Un cours de niveau débutant sur les fonctions se trouve à la page suivante: Lien

Les fonctions permettent de rendre le script plus efficace, plus facile à lire et à vérifier. Une bonne pratique est de faire régulièrement du remaniement de son code : c’est-à-dire ré-écrire les parties du programme qui fonctionnent et les mettre dans une fonction ou un module. Cela évite aussi les répétitions. On remplace alors le code par un appel à une fonction.

Généralités

Tous les langages de programmation fournissent un large ensemble de fonctions prêtes à être utilisées. Nous avons déjà rencontré diverses fonctions prédéfinies, de la librairie standard : print, input, range, len.

Définition : Une fonction est un bloc de code auquel on donne un nom en vue de le réutiliser. L’appel de son nom exécute tout le bloc de code que cette fonction contient.

Pour créer une fonction, il faut la définir avec le mot clé def, suivi du nom de la fonction, d’une paire de parenthèses suivies de :.

Return

La fonction peut retourner une valeur. Celle-ci est alors mise après le mot clé return.

def salut():
  """Accueillir tout le monde"""
  return 'bonjour tout le monde'

On appelle cette fonction à l’aide de son nom, suivi des parenthèses :

salut()
# retourne (et affiche) 'bonjour tout le monde'

Fonction python et fonction mathématique

On peut programmer une fonction pour qu’elle retourne la valeur y = f(x).

Exemple: soit la fonction mathématique $f : x \mapsto 3x^2+2$

Le script python correspondant sera:

def f(x):
    return 3*x**2+2

Pour exécuter la fonction avec x=5, on fait: f(5)

Et cela retourne … $3\times 5^2+2$, soit 77.

Le mot-clé return joue, dans le script, un rôle analogue à celui du signe = dans l’écriture mathématique $y = f(x)$.

Docstring

Il est d’usage, dans les bonnes pratiques, d’ajouter une chaîne de documentation, à la première ligne de la fonction : le Docstring.

Le Docstring est accessible à l’aide de la fonction help :

def salut():
  """Accueillir tout le monde"""
  return 'bonjour tout le monde'

> help(salut)
# affiche
Help on function salut in module __main__:

salut()
    Accueillir tout le monde

Pour plus d’informations sur le Docstring, et principalement le Prototypage, consulter la page mise au point

Passage d’argument

Définitions

Un paramètre est une information dont la fonction a besoin pour s’exécuter. Un argument est une valeur transmise à une fonction.

Les paramètres sont placés à l’intérieur des parenthèses dans la définition de la fonction.

def salut(nom):
  """Accueillir tout le monde par son nom"""
  return f'bonjour {nom}'

Lors de l’appel de la fonction, on place l’argument entre parenthèses :

salut('Brendon')
# retourne (affiche) 'bonjour Brendon'

Portée des variables

internes

Lors de l’exécution de la fonction, la valeur 'Brendon' est affectée à la variable nom : nom = 'Brendon'.

Seulement, la variable nom est une variable interne à la fonction, et n’existe que dans celle-ci. Elle n’est pas définie en dehors.

>>> salut('Brendon')
'bonjour Brendon'
>>> nom
NameError: name 'nom' is not defined

La portée des paramètres et des variables déclarées dans la fonction est limitée à la fonction elle-même. Ce sont des variables locales.

externes

Les variables déclarées dans le main sont accessibles à l’intérieur d’une fonction, en lecture.

Pour les modifier depuis l’intérieur de la fonction, deux cas se distinguent :

  • si la variable désigne un objet mutable (une liste, un dictionnaire…), on peut modifier son contenu par un effet de bord, sans rien déclarer de particulier ;
  • pour réaffecter la variable elle-même — qu’elle soit mutable ou non — il faut la déclarer explicitement avec le mot-clé global à l’intérieur de la fonction (voir le cours sur les types construits, qui détaille ce mécanisme).

Exemple:

x = 9

def ajouter_un():
  global x
  x = x + 1
  return x

ajouter_un()
print(x)
# affiche 10

Arguments positionnés

Lorsqu’une fonction a besoin de plusieurs valeurs, ces dernières doivent correspondre aux paramètres qu’elle attend. Les arguments doivent être placés dans l’ordre des valeurs reçues.

def publier_msg(message,user):
  """publier le message de l'utilisateur"""
  return f'{user} : {message}'

Que l’on appelle en renseignant les 2 arguments :

publier_msg('Ok pour moi','Branda')
# retourne (affiche) 'Branda : Ok pour moi'

Rq : il existe aussi la possibilité d’utiliser des arguments non positionnés, et nommés: voir ci-dessous.

Arguments non positionnés

On peut appeler la fonction avec des arguments non positionnés, mais, alors, il faudra nommer les paramètres. Par exemple, ici, on inverse la position des arguments, mais comme ceux-ci sont nommés, l’affectation aux paramètres est bien respectée:

def servir_cafe(client,nombre):
  """servir le nombre de cafés voulus au client"""
  return f'{client} commande {nombre} café(s)'

> servir_cafe(nombre=10,client="Fred")
'Fred commande 10 café(s)'

Valeur par défaut

Définir la valeur par défaut d’un paramètre dans une fonction permet à l’appel de la fonction d’utiliser cette valeur, sauf si une autre valeur est spécifiée à l’appel.

Lorsqu’il y a plusieurs arguments, il faudra mettre le-s paramètre-s avec valeur-s par défaut à la fin :

def servir_cafe(client,nombre=1):
  """servir le nombre de cafés voulus au client"""
  return f'{client} commande {nombre} café(s)'

Exemple d’utilisation :

servir_cafe('George')
# on utilise la valeur du paramètre par defaut = 1
# retourne 'George commande 1 café(s)'
servir_cafe('Jean',2)
# cette fois, on précise la valeur 2
# retourne 'Jean commande 2 café(s)'

Spécifier une fonction

On a vu que pour déclarer et construire une fonction, il faut:

  • déclarer le nom de la fonction et ses eventuels paramètres après la commande def
  • placer les paramètres entre (), dans un ordre précis
  • terminer la première ligne, def ...: par 2 points :
  • indenter le bloc de code de la fonction
  • placer eventuellement un commentaire, à partir de la première ligne du bloc de la fonction, sur une ou plusieurs lignes, afin de préciser son comportement: """commentaire sur plusieurs lignes"""
  • finir par une eventuelle valeur de retour, après le return

On peut aller plus loin dans ce que l’on appelle la spécification de la fonction, en utilisant des annotations de type:

Depuis Python 3.5, on peut préciser, dans la définition d’une fonction, le type attendu pour chaque paramètre ainsi que le type de la valeur renvoyée. On parle d’annotations de type (type hints).

def nom_fonction(parametre: type_attendu) -> type_de_retour:
    ...

Exemple :

def f(x: float) -> float:
    return 3 * x ** 2 + 2

Ces annotations rendent la fonction plus facile à comprendre et à utiliser correctement (on sait, sans lire le corps de la fonction, ce qu’elle attend et ce qu’elle renvoie). Elles sont également exploitées par des outils externes (éditeurs de code, vérificateurs de type comme mypy) pour détecter des erreurs avant l’exécution.

Attention, piège classique : ces annotations sont purement indicatives. Python ne les vérifie pas et ne convertit pas automatiquement les arguments reçus vers le type annoncé.

f(5)
# affiche 77   (un int, pas un float !)

Rien n’empêche d’appeler f avec un entier alors que x est annoté float : aucune erreur, aucune conversion, le calcul se fait simplement avec la valeur reçue. L’annotation est une indication à l’intention du programmeur (et des outils d’analyse), pas une contrainte imposée par l’interpréteur.

On peut combiner une annotation de type avec une valeur par défaut :

def servir_cafe(client: str, nombre: int = 1) -> str:
    """servir le nombre de cafés voulus au client"""
    return f'{client} commande {nombre} café(s)'

Pour aller plus loin : les annotations d’une fonction sont accessibles via son attribut __annotations__, un peu comme le Docstring est accessible via help :

f.__annotations__
# affiche {'x': <class 'float'>, 'return': <class 'float'>}

Vérifier réellement les préconditions : assert et raise

Puisque les annotations de type ne sont pas contrôlées par Python, il faut, si l’on veut réellement garantir qu’une fonction reçoit des arguments valides, écrire ce contrôle soi-même. Deux outils permettent de le faire, avec un usage différent.

assert vérifie qu’une condition est vraie, et interrompt le programme avec une AssertionError si ce n’est pas le cas :

def double(x: int) -> int:
    assert isinstance(x, int), "x doit être un entier"
    return x * 2

double(2.5)
# AssertionError: x doit être un entier

assert est surtout destiné à vérifier des conditions qui ne devraient jamais être fausses si le programme est correct — des invariants internes, utiles pendant le développement et les tests. Un détail important : les instructions assert peuvent être désactivées globalement au lancement de Python (option -O), auquel cas elles ne sont plus exécutées du tout. Il ne faut donc jamais s’appuyer sur assert pour une vérification qui doit rester active en toutes circonstances, en particulier pour valider une donnée saisie par un utilisateur.

raise lève explicitement une exception, d’un type que l’on choisit, et reste toujours actif, quelles que soient les options de lancement.

Dans l’exemple suivant, j’utilise la fonction isinstance pour verifier si x (le premier argument de la fonction) est de type int, (le 2e argument):

def double(x: int) -> int:
    if not isinstance(x, int):
        raise TypeError("x doit être un entier")
    return x * 2

double(2.5)
# TypeError: x doit être un entier

En résumé : on préfère assert pour des vérifications de mise au point (aides au débogage, à retirer mentalement de la logique du programme), et raise pour valider de façon fiable les entrées d’une fonction destinée à être réellement utilisée — par exemple par d’autres personnes, ou dans un programme final. La fonction isinstance(objet, type), qui renvoie True si objet est bien une instance de type, est l’outil le plus courant pour ce genre de vérification.

Importer des fonctions

Modules : fonctions dans un fichier séparé

Une fonction peut être placée dans un autre fichier. On a alors:

  • un fichier principal (le programme main)
  • un ou plusieurs fichiers annexes (modules)

Ces fonctions ne deviennent accessibles que si on les importe.

Utiliser le mot clé import pour importer un module et accéder à toutes ou partie de ses fonctions.

Le programme principal doit alors faire référence aux modules. On utilise l’une des 3 manières proposées ci-dessous:

import module
from module import *
import module as alias

Il est préconisé de ne charger que les fonctions utiles du module:

from module import fonction

La manière avec laquelle on utilise la fonction dépend de l’import du module.

Les exemples suivants sont issus du cours https://www.courspython.com/modules.html

import appel de la fonction commentaire
import puissance u = puissance.carre(a)
from puissance import carre, cube u = carre(a) on importe uniquement les fonctions nécessaires
from puissance import * u = carre(a) déconseillée car elle “pollue” l’espace de nom
import puissance as pu u = pu.carre(a) import du module avec un alias
from puissance import carre as ca u = ca(a) import d’une fonction d’un module et on lui donne un alias
import package1.module1 u = package1.module1.carre(a) import d’une partie du package (le dossier)

Modules

Dans un projet plus grand, les fonctions peuvent être mises dans des modules (des fichiers séparés). On doit alors les importer pour bénéficier d’une extension du langage. Certains modules très utiles: math, turtle, random, …

Tout fichier Python peut être importé. C’est particulièrement facile lorsque les fichiers sont dans le même répertoire. Supposons que A.py et B.py le soient, on peut mettre dans B.py l’instruction from A import * : toute fonction (ou variable) déclarée dans A.py sera alors utilisable dans B.py.

if __name__ == "__main__"

Cette syntaxe idiomatique de Python permet de n’exécuter du code présent dans un fichier/module que si ce fichier/module est directement exécuté. Ce code N’est PAS exécuté lorsque ce fichier/module est importé. Cette approche est généralement utilisée pour inclure du code de test dans un module.

def ma_fonction():
    ...

if __name__ == "__main__":
    # Ce bloc n'est exécuté que si on lance ce fichier, pas s'il est importé depuis un autre module
    ma_fonction()

Lambda fonction: fonctions anonymes

On peut avoir recours aux fonctions anonymes pour des tâches ponctuelles qui ne nécessitent pas la création d’une fonction complète.

La syntaxe est la suivante:

lambda arguments : expression

Les arguments sont les paramètres de la fonction et l’expression calcule la valeur de retour.

Remarquez l’absence d’utilisation du mot-clé return, contrairement à une fonction classique.

Exemple:

>>> square = lambda x : x ** 2
>>> square(2)
4

Les fonctions lambda peuvent être utilisées pour trier une liste selon une clé spécifique: doc officielle

>>> nodes = [('A', 20), ('B', 15), ('C', 12), ('D', 10), ('E', 8), ('F', 5), ('G', 2)]
>>> nodes.sort(key= lambda x: x[1])
>>> nodes
[('G', 2), ('F', 5), ('E', 8), ('D', 10), ('C', 12), ('B', 15), ('A', 20)]

Alors que le tri sur la même liste, sans clé de tri, va donner:

>>> nodes = [('A', 20), ('B', 15), ('C', 12), ('D', 10), ('E', 8), ('F', 5), ('G', 2)]
>>> nodes.sort()
>>> nodes
[('A', 20), ('B', 15), ('C', 12), ('D', 10), ('E', 8), ('F', 5), ('G', 2)]

Liens

Cours les fonctions
TP4

algorithmes essentiels

Rappels sur les algorithmes vus en classe de 1ere NSI

Sous-sections de algorithmes essentiels

calculer

multiplier sans le signe *

Addition répétée : on ajoute a à un total, b fois.

def multiplier(a, b):
    resultat = 0
    for _ in range(b):
        resultat += a
    return resultat

Exemple : multiplier(6, 4) → 6+6+6+6 → 24

diviser sans le signe /

Soustractions répétées : on retire b à a tant que c’est possible (division euclidienne : quotient et reste).

def diviser(a, b):
    quotient = 0
    reste = a
    while reste >= b:
        reste -= b
        quotient += 1
    return quotient, reste

Exemple : diviser(17, 5) → (3, 2) car 17 = 5×3 + 2

PGCD euclide

Le PGCD de a et b est égal au PGCD de b et a % b. On répète jusqu’à obtenir un reste nul. Cette méthode repose sur la propriété suivante:

S’il existe un diviseur commun pour a et b, alors ce diviseur est aussi commun à a, b et a-b. Donc également à a%b:

def pgcd(a, b):
    while b != 0:
        a, b = b, a % b
    return a

Exemple : pgcd(48, 18) → 48%18=12 → 18%12=6 → 12%6=0 → PGCD = 6

Méthode de Horner

La factorisation de Horner:

Supposons que l’on ait à convertir le mot binaire $1110$ en décimal, ou plus généralement $b_0 b_1 b_2 b_3$ en décimal:

\(b_{0}\cdot 2^{3}+b_{1}\cdot 2^{2}+b_{2}\cdot 2^{1}+b_{3}\cdot 2^{0}\)

On peut factoriser par 2 au fur et à mesure :

\(=\left(b_{0}\cdot 2^{2}+b_{1}\cdot 2^{1}+b_{2}\right)\times 2+b_{3}\) \(=\left(\underline{(b_{0}\times 2+b_{1})}\times 2+b_{2}\right)\times 2+b_{3}\)

On devine la structure de suite recurence pour la suite :

  • Le premier bloc souligné \(\underline{(b_{0}\times 2+b_{1})}\), c’est votre étape \(u_{2}\).
  • Pour passer à la suite, on prend ce bloc, on le multiplie par 2, et on ajoute le terme suivant.

C’est exactement la définition de \(u_{n+1} = 2u_n + b_{n+1}\).

On peut alors proposer le programme suivant:

def horner(binaire:str)->int:
    # binaire est un mot binaire du type "1110"
    s = 0
    for bit in binaire:
        s = 2*s + int(bit)
    return s

ou bien:

def horner_recursif(binaire):
    if binaire=="":
        return 0
    bit = int(binaire[-1])
    return 2*horner_recursif(binaire[:-1]) + bit

Lien

rechercher

La connaissance des algorithmes suivants est exigée pour les étudiants en NSI. Le langage python propose des fonctions pour chacun d’eux. Mais, parfois, il est demandé à l’étudiant d’écrire ou compléter le script pour ces fonctions.

Parcours séquentiel

On parcourt la structure élément par élément, du début à la fin.

algorithmes de recherche

Exemple avec une liste, avec un dictionnaire

# liste : renvoie l'indice de la valeur, ou -1 si absente
def recherche_liste(liste, valeur):
    for i in range(len(liste)):
        if liste[i] == valeur:
            return i
    return -1

# dictionnaire : renvoie la clé associée à la valeur
def recherche_dict(d, valeur):
    for cle in d:
        if d[cle] == valeur:
            return cle
    return None

recherche d’occurences

def compter_occurrences(liste, valeur):
    compteur = 0
    for element in liste:
        if element == valeur:
            compteur += 1
    return compteur

calcul d’une somme ou moyenne

def somme(liste):
    total = 0
    for element in liste:
        total += element
    return total

def moyenne(liste):
    return somme(liste) / len(liste)

recherche d’un extremum (min, max)

def maximum(liste):
    m = liste[0]
    for element in liste:
        if element > m:
            m = element
    return m

Recherche dichotomique

S’applique uniquement sur une liste triée. On compare la valeur cherchée à l’élément central puis on réduit la zone de recherche de moitié à chaque étape.

def dichotomie(liste, valeur):
    gauche, droite = 0, len(liste) - 1
    while gauche <= droite:
        milieu = (gauche + droite) // 2
        if liste[milieu] == valeur:
            return milieu
        elif liste[milieu] < valeur:
            gauche = milieu + 1
        else:
            droite = milieu - 1
    return -1

A retenir : recherche séquentielle en O(n), recherche dichotomique en O(log n).

Liens

algorithmes de tri


tri par insertion

On construit la partie triée au fur et à mesure : chaque nouvel élément est inséré à sa place parmi les précédents.

def tri_insertion(liste):
    for i in range(1, len(liste)):
        valeur = liste[i]
        j = i - 1
        while j >= 0 and liste[j] > valeur:
            liste[j + 1] = liste[j]
            j -= 1
        liste[j + 1] = valeur
    return liste

Exemple : [5, 2, 4, 1] → [2, 5, 4, 1] → [2, 4, 5, 1] → [1, 2, 4, 5]

tri par selection

A chaque étape, on cherche le minimum du reste de la liste et on l’échange avec le premier élément non trié.

def tri_selection(liste):
    for i in range(len(liste)):
        indice_min = i
        for j in range(i + 1, len(liste)):
            if liste[j] < liste[indice_min]:
                indice_min = j
        liste[i], liste[indice_min] = liste[indice_min], liste[i]
    return liste

Exemple : [5, 2, 4, 1] → [1, 2, 4, 5] (le 1 puis le 2 sont placés successivement en tête)

A retenir : les deux algorithmes ont une complexité en O(n²) dans le pire des cas.

Algorithmes avancés


Algorithme glouton

A chaque étape, on fait le choix qui semble le meilleur sur le moment, sans revenir en arrière. Ne donne pas toujours la solution optimale, mais est simple et rapide.

Exemple classique : le rendu de monnaie. On utilise toujours la plus grande pièce/billet possible.

def rendu_monnaie(a_rendre, pieces):
    pieces.sort(reverse=True)  # du plus grand au plus petit
    resultat = []
    for p in pieces:
        while a_rendre >= p:
            resultat.append(p)
            a_rendre -= p
    return resultat

Exemple : rendu_monnaie(78, [50, 20, 10, 5, 2, 1]) → [50, 20, 5, 2, 1]

Limite : avec un système de pièces mal choisi, le glouton peut ne pas être optimal (ex. rendre 6 avec [4, 3, 1] donne 4+1+1 au lieu de 3+3).

Recherche des K plus proches voisins

Pour classer une nouvelle donnée, on calcule sa distance à toutes les données connues, puis on regarde les k voisins les plus proches : la classe majoritaire parmi eux devient la prédiction.

from math import sqrt

def distance(p1, p2):
    return sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)

def k_plus_proches_voisins(donnees, nouveau_point, k):
    # donnees : liste de (point, classe)
    distances = []
    for point, classe in donnees:
        distances.append((distance(point, nouveau_point), classe))
    distances.sort()
    k_voisins = distances[:k]
    classes = [classe for _, classe in k_voisins]
    return max(classes, key=classes.count)  # classe majoritaire

Exemple : donnees = [((1,1), "A"), ((2,1), "A"), ((5,5), "B")] puis k_plus_proches_voisins(donnees, (1,2), 2) → "A" (les 2 voisins les plus proches sont de classe A)

A retenir : le choix de k est important — trop petit, sensible au bruit ; trop grand, mélange des classes éloignées.

fichiers Entrees/Sorties

Entrées/Sorties en console

Sortie en console

La fonction print permet l’affichage d’une valeur en console, quel qu’en soit le type.

On peut afficher un texte simple, ou composé de plusieurs parties, par concaténation de chaine :

clan = 'Vikings'
message = 'Fight Invaders'
print('We are the ' + clan + ' who say' + ' "'+ message + '!"')
# affiche 
# We are the Vikings who say "Fight Invaders!"

Le problème de cette méthode de concaténation est que chaque partie composant la chaine doit être de type str. Cela est possible avec la fonction str(variable, mais il existe une méthode plus efficace : formater la chaine.

La méthode str.format() sur les chaines de caractères :

La methode de base :

clan = 'Vikings'
message = 'Fight Invaders'
print('We are the {} who say "{}!"'.format(clan, message))
# affiche 
# We are the Vikings who say "Fight Invaders!"

On peut aussi préciser le nombre de caractères ou de chiffres attendus, le type de données, etc.

Exemple : affichage d’une table

for x in range(1, 11):
    print('{:2d} {:3d} {:4d}'.format(x, x*x, x*x*x))
# affichage : 
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

Cela permet d’aligner des chaînes dans une largeur de taille fixe.

Entrées au clavier : input

La fonction input met le programme en pause et attend que l’utilisateur entre une donnée.

nom = input('Quel est votre nom ? ')
print('Bonjour, {}'.format(nom))

Toutes les données saisies sont converties en chaîne. Il est donc necessaire de convertir les données numériques dans le type approprié avant de les utiliser :

prix = input('Combien coute ce camion ?')
prix = float(prix)
if prix < 10000:
  print('Ok, je le prends.')

Lire le contenu d’un fichier

Repertoire courant

Selon l’IDE python choisi, vous pouvez avoir des difficultés pour ouvrir un fichier. L’interpreteur peut considérer que le repertoire courant n’est pas celui du fichier en cours d’execution, et ne trouve pas votre fichier data, qui se trouve dans le même dossier.

Pour resoudre ce problème, vous pouvez ajouter les lignes suivantes:

import os

dir_path = os.path.dirname(os.path.abspath(__file__))
print('init:',dir_path)

os.chdir(dir_path)
#sys.path.append(dir_path)
print('after:',os.getcwd())
print('conten:t',os.listdir())

Le module os apporte les fonctions:

  • chdir: changer de repertoire courant pour le chemin utilisé par l’interpreteur
  • getcwd: chemin du repertoire courant
  • listdir: contenu du repertoire courant

Fichier txt

On utilise la fonction open de la librairie standart en python:

La fonction open crée donc un fichier. Elle renvoie un objet de la classeTextIoWrapper. Par la suite, nous allons utiliser des méthodes de cette classe pour interagir avec le fichier. Il existe 2 méthode pour utiliser open:

  • méthode 1: fonctions open et close. On créé un objet qui sert à importer le fichier. Choisir un nom quelconque, pour l’exemple qui suit ce sera file. On utilise la fonction open avec pour paramètres, le nom du fichier (son chemin), suivi du caractère ‘r’ (pour read, ouverture du fichier en lecture).

On peut alors récuperer le contenu textuel du fichier à l’aide de la méthode read. Dans l’exemple ci-dessous, on place le texte du fichier dans la variable texte.

On peut traiter cette variable comme on le souhaite, l’afficher en entier (print(texte)), ou parcourir et traiter les caractères les uns après les autres (for c in texte: ...)

Penser alors à fermer le fichier de lecture: file.close()

file = open('exemple.txt','r')
texte = file.read()
file.close()
print(texte)
  • méthode 2: système d’instructions with + open

Le programme suivant est équivalent à celui de la méthode 1. Avec le mot clé with, les instructions de lecture du fichier sont mis dans un bloc, et donc indentées. A la sortie de ce bloc, le fichier est automatiquement fermé, ce qui fait l’economie de l’instruction close, et evite les oublis…

with open('exemple.txt', 'r') as file:
    texte = file.read()
print(texte)

Exemple de programme : lire un fichier .txt avec un seul mot par ligne, et créer une liste mots

# initialisation de la liste vide
mots = []

# Lecture du fichier txt et remplissage de la liste
with open('liste_francais.txt', encoding='iso-8859-1') as f:
    for mot in f.read().splitlines():
        mots.append(mot)
  • open : renvoyer un objet TextIOWrapper
  • as : « en tant que »

Le mot-clé with permet de créer un “context manager” (gestionnaire de contexte) qui vérifie que le fichier est ouvert et fermé, même si des erreurs se produisent pendant le bloc.

Plus d’informations : https://python.sdv.univ-paris-diderot.fr/07_fichiers/

Caractères speciaux

Certains caractères sont fort utiles lors de l’écriture de fichiers texte afin d’organiser les données. Le symbole ; est très utilisé comme séparateur de colonnes pour une matrice, on utilise également le passage à la ligne ou la tabulation. Comme ce ne sont pas des caractères « visibles », ils ont des codes :

  • \ caractère d’echappement (par exemple pour écrire des guillemets dans une chaine)
  • \n : passage à la ligne
  • \t : tabulation, indique un passage à la colonne suivante dans le format tsv (Tabulation-separated values).

Lors de la lecture d’un fichier, on peut avoir besoin de supprimer ces caractères spéciaux:

table = []
# Lecture du fichier
with open('datas/rne-cm.csv', encoding='utf-8') as f:
    for line in f.read().splitlines():
        table.append(line)

table[2]
# affiche
'32\tGers\t\t\t32249\tMauvezin\tPASCOLINI\tJean-Marc\tM\t'
print(table[2])
# affiche
32 Gers   32249 Mauvezin PASCOLINI Jean-Marc M
len(table[2])
# affiche 
1

L’import des données n’a pas placé les valeurs comme des éléments de liste. Il faudrait découper la chaine de caractères au niveau des espaces:

On peut alors remplacer l’instruction table.append(line) par table.append(line.split('\t')), ce qui découpe la chaine au niveau des \t:

with open('datas/rne-cm.csv', encoding='utf-8') as f:
    for line in f.read().splitlines():
        table.append(line.split('\t'))
table[2]
# affiche
['32',
 'Gers',
 '',
 '',
 '32249',
 'Mauvezin',
 'PASCOLINI',
 'Jean-Marc',
 'M',...]

Bien entendu, il faudra adapter l’argument de la fonction split en fonction du caractère de séparation utilisé dans le fichier:

Pour le contenu suivant, il faudra utiliser line.split(';')

;2020;2021;2022;2023;2024;total
seconde;480;495;420;465;465;
premiere;420;525;420;510;465;
terminale;495;480;420;435;435;
;;;;;;

Fichier csv

Le module csv permet de reduire d’une ligne l’import des données (choisir le bon delimiter):

import csv
table = []
with open('ficher.csv', 'r') as file:
    reader = csv.reader(file, delimiter=',')
    for row in reader:
        table.append(row)
  • Souvent, la première ligne ne concerne que l’en-tête (descripteurs).
  • Le reste des données, numériques doivent être converties en float
  • Supposons que les données contiennent les valeur de x pour la première colonne, et y la deuxième colonne:
x = []
y = []
for i in range(1,len(table[1:])):
    x.append(float(table[i][0]))
    y.append(float(table[i][1]))

Ecrire dans un fichier

  • méthode 1: fonctions open et close. On créé un objet qui sert à désigner le fichier. Choisir un nom quelconque, pour l’exemple qui suit ce sera fileout. On utilise la fonction open avec pour paramètres, le nom du fichier (son chemin), suivi du caractère ‘w’ (pour write, ouverture du fichier en écriture).

On peut alors placer du texte dans le fichier à l’aide de la méthode write: fileout.write("...")

Penser alors à fermer le fichier de lecture: fileout.close()

fileout = open('exemple.txt','w')
fileout.write("Je sais ta passion, et suis ravi de voir\nQue tous ses mouvements cèdent à ton devoir ;")
fileout.close()

On peut alors vérifier le fichier et son contenu en parcourant le dossier avec l’explorateur windows.

  • méthode 2: système d’instructions with + open

Le programme suivant est équivalent à celui de la méthode 1. Avec le mot clé with, les instructions de d’écriture dans le fichier sont mis dans un bloc, et donc indentées. A la sortie de ce bloc, le fichier est automatiquement fermé, ce qui fait l’economie de l’instruction close, et evite les oublis…

with open('exemple.txt','w') as fileout:
    fileout.write("Je sais ta passion, et suis ravi de voir\nQue tous ses mouvements cèdent à ton devoir ;")
   

Exemple avec une liste => fichier

animaux2 = ["poisson", "abeille", "chat"]
with open("zoo2.txt", "w") as filout:
    for animal in animaux2:
         filout.write(animal)

à la ligne 2 : ouverture du fichier zoo2.txt en mode écriture, avec le caractère w pour write.

Si nous ouvrons le fichier zoo2.txt avec un éditeur de texte, voici ce que nous obtenons :

poissonabeillechat

Ce n’est pas exactement le résultat attendu. Le script peut être amélioré en utilisant une écriture formatée, comme vu plus haut, à la dernière ligne du script :

         filout.write("{}\n".format(animal))

Ce qui donne maintenant, à l’ouverture du fichier :

poisson
abeille
chat

Exemple issu de la page python.sdv.univ-paris-diderot.fr/07_fichiers

Tableau de données

  • convertir les données en chaine de caractère formatée:
descripteurs = ['courant','tension','puissance']
datas = [[0.100,2.00,0.200],[0.200,4.00,0.400]]
tab = ""
for title in descripteurs:
    # ajout des descripteurs en tete du tableau
    tab = tab + title + ','
for i in range(len(datas)):
    # saut de ligne
    tab = tab + '\n'
    for j in range(len(datas[0])):
        tab = tab + datas[i][j] + ','
  • exporter avec une extension csv
with open("fichier_datas.csv", "w") as filout:
    filout.write(tab)

Exporter des données (sauvegarde)

Il peut être utile de sauvegarder des données en cours de travail, comportant des paramètres que l’on veut retrouver lors d’une prochaine session de travail.

Utiliser le module pickle pour écrire, puis lire une structure de donnée python, comme un dictionnaire ou une liste:

import pickle

Exemple:

dico = {'b10' : 479.01,
        'b11' : 479.19,
        'b20' : 479.89,
        'b21' : 479.91}
  • Ecriture:
with open(fichier_export,'wb') as f1:
    pickle.dump(dico,f1)
  • Lecture:
with open('sauvegarde','rb') as f2:
    dico = pickle.load(f2)

Liens

traitement

Sous-sections de traitement

traitement des donnees en table

Liste de dictionnaires

Les epreuves pratiques proposent de nombreux exemples de traitement de données en liste de dictionnaires. Se référer aux sujets de 2026.

Open Datas, liste de listes

Un exemple de données ouvertes

Plateforme ouverte des données publiques françaises

Plateforme ouverte des données publiques françaises

Le Répertoire National des Élus (RNE) a pour finalité le suivi des titulaires d’un mandat électoral. Il est renseigné et tenu à jour par les préfectures et hauts commissariats et par les services du ministère de l’intérieur, notamment sur la base des éléments fournis par les élus lors de la phase d’enregistrement des candidatures.

Données du RNE pour les conseillers municipaux - extrait en csv

Données du RNE pour les conseillers municipaux - extrait en csv

Les données du RNE sont structurées par mandat. Neuf fichiers sont publiés ici :

1. les conseillers municipaux ;

  1. les conseillers communautaires ;
  2. les conseillers départementaux ;
  3. les conseillers régionaux ;
  4. les membres des assemblées des collectivités à statut particulier ;
  5. les représentants au Parlement européen ;
  6. les sénateurs ;
  7. les députés ;
  8. les maires.

En bas de page, vous pourrez observer les réutilisations de ces documents:

exemples de réutilisation des données ouvertes sur les elus municipaux

exemples de réutilisation des données ouvertes sur les elus municipaux

Ouvrir les données jugées d’intérêt public, c’est encourager leur réutilisation par tout un chacun. Cela permet d’encourager la transparence démocratique, de bénéficier de services au quotidien ou de prendre des décisions plus éclairées.

Exploration et traitement de données

Télécharger sur le site gouvernemental le fichier ldes élus municipaux ; , au format .csv

Ouvrir un nouveau notebook, ou bien un nouveau fichier dans votre IDE python (Spyder ou Pyzo). Déplacer le fichier *.csv dans le même dossier que le notebook/fichier python.

Lire et stocker le contenu du fichier dans une liste python que vous appelerez table.

On pourra s’aider:

du dernier paragraphe de la page Python les bases > entrées / sorties pour importer le fichier csv. du TP sur les algorithmes de recherche dans un dictionnaire: voir TP ici

Une fois la liste des élus importée dans une liste python:

Dans votre editeur python, explorer la liste table pour qu’elle affiche les informations sur la longueur, sur les premiers élus.

Si vous choisissez le bon caractère de séparation des données, vous devriez obtenir quelque chose d’approchant (la mise à jour est régulière, et les données peuvent différer):

> len(table)
490805
> table[1]
['32', 'Gers','','','32249','Mauvezin','MASAROTTI',
 'Sylvie','F', ...]

*Chaque élément de table est constitué d’une liste, avace chaque valeur séparée par une virgule ,

Si par contre, vous identifiez mal le caractère de séparation, vous allez obtenir quelque chose comme cela:

> len(table)
1
> table[1]
['32\tGers\t\t\t32249\tMauvezin\tMASAROTTI\tSylvie\tF']

ou peut-être:

> len(table)
1
> table[1]
['32;Gers;;;32249;Mauvezin;MASAROTTI;Sylvie;F']

Question 1: Quels sont les rangs auxquels se trouvent le numero de departement, ainsi que celui du sexe de l’élu ‘H’/‘F’?

Explorer pour définir l’ordre dans lequel sont classés les élus.

Fonction recherche

Ecrire une fonction recherche qui recherche le premier élu dans un departement donné. La fonction recherche aura pour seul argument la variable textuelle dpt correspondant au departement recherché.

Cette fonction prend les éléments du tableau un par un, en commençant par le debut, et recherche la premiere occurence (le premier élu de ce departement).

Par exemple:

> recherche('06')
363891

Question 2: Pourquoi la fonction retourne t-elle un entier (par exemple 363891)?

Question 3: Quelle est le numero de ligne du dernier élu du departement 06 (utiliser la fonction recherche)?

Fonction pariteHF

Ecrire une fonction pariteHF qui compte le nombre d’élus Hommes et le nombre d’élues Femmes pour un departement donné. La fonction renvoie alors le couple de valeurs H/F.

Exemple:

> score_M,score_F = pariteHF('34')
> score_M,score_F
(3143, 2646)

Question 4: Donner le script de cette fonction.

Graphique

Représenter alors cette parité dans votre notebook sur un diagramme circulaire.

On s’aidera du lien suivant pour représenter des diagrammes avec Matplolib.

exemple de diagramme sur la proportion des élus H/F

exemple de diagramme sur la proportion des élus H/F

Prolongement

Rechercher si, pour l’un des departements, le ratio ‘F’/‘M’ est supérieur à 1.

Faire un compte rendu avec les réponses, les scripts et graphiques. Utiliser un editeur de texte.

Suggestion de projet

Utiliser une API en python avec le module request, et charger directement le fichier de données. Une API est une interface logicielle qui permet de se « connecter » à un service, ou un serveur.

Exemple issu de realpython.com

>>> import requests
>>> response = requests.get("https://randomuser.me/api/")
>>> response.text
'{"results":[{"gender":"female",
"name":{"title":"Ms","first":"Isobel","last":"Wang"}...'

Cette méthode permet de consulter la version la plus recente, mise à jour sur le serveur. On peut imaginer de nombreuses applications (météo, prix du carburant, …)

graphique avec matplotlib

Tracé de graphiques avec curseur

La documentation complète de matplotlib.pyplot: Lien

module: D’abord importer le module:

import matplotlib.pyplot as plt

Curseur: Ajouter Cursor si vous avez besoin de faire un relevé sur le graphique:

from matplotlib.widgets import Cursor

Script minimal: voici un exemple de tracé de 2 courbes superposées:

  • l’une de type nuage de points scatter (points non reliés)
  • l’autre de type plot (points reliés entre eux)
%matplotlib qt
plt.clf()
axes = plt.gca()
plt.scatter(x_gli,signal_lissage,color='silver',marker='.',label='luminosité')
#plt.grid(True,which='both')
#plt.legend(loc='best')
#plt.title('moyenne glissante')


plt.plot(x_gli,Y_fit,color='red',label='courbe fit')
#plt.grid(True,which='both')
#plt.legend(loc='best')
cursor = Cursor(axes, useblit=True, color='red', linewidth=2)
plt.show()

lignes optionnelles:

  • %matplotlib qt va détacher le graphique du flux du notebook, et permettre d’utiliser le curseur (fenêtre graphique qt)
  • La fonction gca permet de gérer les axes et curseur.
  • La fonction clf permet d’effacer la figure courante et de remettre les réglages graphiques à zero.
  • grid pour afficher une grille
  • legend pour ajouter un encadré avec la légende (les labels)

regression lineaire

Regression linéaire

Principe

La regression linéaire consiste à déterminer une fonction y = a.x + b dans un nuage de points (x,y), à condition que ceux-ci semblent suffisament alignés. Cette fonction permettra alors de faire des prédictions sur la valeur y selon celle de x.

Exemple de données brutes

Commencer par importer les données de l’exemple 1: datas.csv

Placer le fichier dans le même dossier que votre fichier de travail, que vous appelerez regression.py

import csv
table = []
with open('fichier.csv', 'r') as file:
    reader = csv.reader(file, delimiter=',')
    for row in reader:
        table.append(row)

Vérifier la nature des données importées en affichant les premières lignes:

>>> table[:10]

Dans ce premier exemple, nous allons travailler sur une partie des données. Celles-ci ne contiennent que des informations numériques. On limite le traitement aux 90 premieres valeurs:

x = []
y = []
for i in range(90):
    x.append(float(table[i][0]))
    y.append(float(table[i][1]))

Voir maintenant l’allure en traçant le graphique (x,y): (méthode vue ici)

import matplotlib.pyplot as plt
plt.clf()
axes = plt.gca()
plt.scatter(x,y,color='silver',marker='.',label='Signal brut')
plt.grid(True,which='both')
plt.xlim(0,100)
plt.ylim(0,5)
plt.legend(loc='best')
plt.title('Signal avec bruit')
plt.show()

Questions: Les points présentent-ils un certain alignement? Sur quelle-s partie-s de la courbe bruitée?

Mettre en place la regression linéaire

On commence par definir le modèle mathématique. Ici, celui d’une application affine.

def fit_func(x,a,b):
    return a*x+b

La regression linéaire consiste à calculer les valeurs des coefficient a et b. C’est l’outil scipy_optimize.curve_fit qui va ajuster les coefficients de regression, sur le nuage de points selectionnés.

from scipy.optimize import curve_fit
# placer des valeurs dans les coefficients a et b
a = 0
b = 0
borne_inf = ??
borne_sup = ??
# calculer les parametres
params, mcov =curve_fit(fit_func,x[borne_inf:borne_sup],y[borne_inf:borne_sup])
a = params[0]; b=params[1]

Pour que l’exemple fonctionne, il faudra placer des valeurs pour les bornes inferieures et superieures, par exemple:

borne_inf = 0
borne_sup = 90

Une fois que le programme a calculé ces coefficients, remplir une liste Y_fit avec les valeurs de regression. On utilise bien sûr la fonction du modèle, fit_func:

Y_fit=[]
for i in range(borne_inf,borne_sup):
    Y_fit.append(fit_func(x[i],a,b))

Il reste à verifier la qualité de la regression en affichant:

  • le nuage de points (x,y)
  • la courbe modélisée (x[borne_inf:borne_sup],Y_fit)
plt.clf()
axes = plt.gca()
plt.scatter(x,y,color='silver',marker='.',label='Signal brut')
plt.grid(True,which='both')
plt.xlim(0,100)
plt.ylim(0,5)
plt.legend(loc='best')
plt.title('Signal avec bruit')
plt.plot(x[borne_inf:borne_sup],Y_fit,color='red',label='courbe fit')
plt.show()

Application

On va appliquer le traitement sur une autre partie du nuage de points. Les données simulent le cours d’un actif numérique sur plusieurs jours:

  • x: numéro du jour, sur plus d’une année (500 jours?)
  • y: valeur de l’actif en dollards

Utiliser le même fichier datas.csv, que vous allez cette fois exploiter en entier.

La valeur montre des fluctuations quotidiennes, mais aussi un premier maximum obtenu après 90 jours. Il s’agit de ce que l’on nomme un ATH, ou “All time high”, qui désigne le pic historique d’un actif financier.

exemple de courbe montrant plusieurs ATH - www.blog.bim.finance

exemple de courbe montrant plusieurs ATH - www.blog.bim.finance

La fin du relevé montre une nouvelle tendance haussière. C’est sur cette dernière partie du nuage de points que vous allez faire une regression linéaire.

Utiliser la courbe de regression linéaire pour faire une prediction: quel sera le jour où la valeur de l’actif sera le même que lors de son précédent ATH?

sql et python

Base de données exoplanetes.db

Principe

Nous allons utiliser un script Python pour nous connecter à la base de données exoplanetes.db et tester quelques requêtes en langage SQLite.

Nous utiliserons la librairie sqlite3 de Python.

Il est conseillé d’utiliser l’IDE Spyder, ou bien Jupyter Notebook pour editer et interpréter les scripts écrits en Python.

La base de données doit être téléchargée ici : exoplanetes.db

extrait de la base de données

extrait de la base de données

Script de base

import sqlite3

try:
    conn = sqlite3.connect('exoplanetes.db')
    cur = conn.cursor()
    print("Base de données crée et correctement connectée à SQLite")

    sql = "SELECT sqlite_version();"
    cur.execute(sql)
    res = cur.fetchall()
    print("La version de SQLite est: ", res)
    


except sqlite3.Error as error:
    print("Erreur lors de la connexion à SQLite", error)


cur.close()
conn.close()
print("La connexion SQLite est fermée")

Rappel: Le mécanisme try ... except est détaillé à la page mise au point d’un programme Python

Voici la traduction de ce script en langage naturel:

essayer:
  connexion a la base de donnees exoplanetes.db
  creation d un curseur SQL
  Afficher ("Base de données cree et correctement connectee à SQLite")
  executer la requete SQL "SELECT sqlite_version();"
  affecter le resultat de la requête dans la variable res

si une erreur survient:
  Afficher ("La version de SQLite est: ", sqlite3.Error)

sinon:
  # autres requetes SQL

fermeture du curseur
fermeture de la connexion
Afficher ("La connexion SQLite est fermée")

Explorer la base de données

  • L’instruction suivante permet d’explorer la base de données:

"PRAGMA table_info(planetes_es);"

Q1. Ajouter cette requête à votre script python pour afficher les attributs de la table planetes_es de la base de données exoplanetes.db

  • Voici un extrait de la reponse à cette requête:
[(0, '_name', 'VARCHAR(38)', 1, None, 1), (1, 'planet_status', 'VARCHAR(9)', 1, None, 0), (2, 'mass', 'NUMERIC(19, 14)', 0, None, 0), (3, 'radius', 'NUMERIC(19, 14)', 0, None, 0), ...]

Q2. Quel est l’attribut du nom des planetes de cette table?

Q3. Ecrire une instruction en python qui affiche uniquement la liste des attributs. Mettre cette liste dans une liste nommée L

['_name',
 'planet_status',
 'mass',
 'radius',
 'orbital_period',
 'semi_major_axis',
 'eccentricity',
 'discovered',
 'detection_type',
 'molecules',
 'star_name',
 'star_distance',
 'star_mass',
 'star_radius',
 'star_sp_type',
 'star_age',
 'star_teff',
 'star_magnetic_field']

On peut améliorer la présentation des résultats, et mettre la table retournée dans un dataframe. On utilise alors la liste L des attributs (question précédente). Voir tuto dataframe

# Toutes les données relatives aux étoiles dont le nom commence par Kepler-89
import numpy as np
import pandas as pd
sql = "select * from planetes_es where _name like 'Kepler-89%'"
cur.execute(sql)
res = cur.fetchall()
df = pd.DataFrame(res,columns=L)
df

Et pour obtenir une vue avec certaines colonnes:

sql = "select _name,mass,radius from planetes_es"
cur.execute(sql)
res = cur.fetchall()
df = pd.DataFrame(res,columns=['_name','mass','radius'])
df

On peut souhaiter éliminer les lignes pour lesquelles les renseignements ne sont pas complets (lignes avec Nan):

df.dropna(how='any', inplace=True)

Et ajouter des colonnes au dataframe, comme par exemple le calcul de la masse volumique de la planète: (attention, les valeurs de la table sont referencées à celles de Jupiter)

R_Jup = 71e6 
M_Jup = 1.898e27
df['rho']=df['mass']*M_Jup/(4/3*np.pi*(df['radius']*R_Jup)**3)
df

Q4. Cette base est-elle bien modélisée, respecte t-elle bien les contraintes d’intégrité vues en cours? Pq?

Q5. Tester quelques unes des requêtes sur cette base. Par exemple:

  1. Toutes les données relatives à l’étoile Kepler-89 b
  2. Tous les noms des planètes dont la masse est plus de 10 fois supérieure à celle de Jupiter (Indiquer quelles sont ces planètes dans l’extrait de la table)
  3. Les planètes ainsi que le nom de l’étoile hôte, dont l’étoile est située à moins de 40 pc de la Terre.
  4. Les noms des 20 étoiles les plus proches de la Terre où des planètes ont été détectées.
  5. Nombre total de planètes dans la table (utiliser COUNT(*))
  6. Nombre total d’étoiles dans la table (utiliser COUNT(DISTINCT ... ))
  7. Table des planètes qui n’ont été détectées ni par “Radial Velocity”, ni par “Primary Transit”
  8. Le nombre de planètes qui n’ont été détectées ni par “Radial Velocity”, ni par “Primary Transit”
  9. Moyenne des distances entre le Soleil et les différentes étoiles de la table (utiliser AVG). Attention à ne compter qu’une seule fois chacune des étoiles.
  10. Table des planètes où le type de l’étoile est G … (utiliser LIKE "G%")
  11. Nom des planètes et distances au soleil, où de l’eau a été détectée (utiliser LIKE)

Etude graphique

La recherche de dépendances entre grandeurs se fera en traçant un graphique, avec différents essais pour les axes x,y: On peut chercher par exemple la dépendance masse volumique <-> rayon:

%matplotlib qt
plt.clf()
axes = plt.gca()
x = df['radius']
y = df['rho']
z = df['_name']
plt.scatter(x,y,color='silver',marker='.',label='Rho')

# ajout d'une etiquette
for x, y, z in zip(x, y, z):
    axes.text(x, y, f"({z})", fontsize=8)
cursor = Cursor(axes, useblit=True, color='red', linewidth=2)
plt.show()

Superposer les données des exoplanètes découvertes par TOI-270 avec la BDD

Commencer par selectionner et nettoyer les données issues de la base de données:

# BDD - Toutes exoplanetes
sql = "PRAGMA table_info(planetes_es);"
cur.execute(sql)
res = cur.fetchall()
L = [ligne[1] for ligne in res]
sql = "select * from planetes_es"
cur.execute(sql)
res = cur.fetchall()
df0 = pd.DataFrame(res,columns=L) # table entiere
df0 = df0[['_name','orbital_period','radius']] # projection sur les colonnes utiles
df0.dropna(how='any', inplace=True) # retirer les lignes avec datas non renseignées
df0

importer et traiter les données issues des observations Cette partie est détaillée à la page données en dataframe

df = pd.read_csv('donnees_planetes.txt',sep=';')
G = 6.67e-11
R_Jup = 71e6 
M_Jup = 6.9911e7
df['tau']=(df['fin_transit']-df['debut_transit'])*24*3600
df['delta']=1-df['lum_min']

df['M_star']=7.158780e+29
df['R_star']=257512600.0
df['R_p']= np.sqrt(df['delta']) * df['R_star']
df['radius']=df['R_p']/R_Jup
# vitesse planete : V_p = 2*R_star/tau
df['V_p']= 2*df['R_star']/df['tau']
# rayon orbital : r = G*M_star/V_p**2
df['r_orb']= G * df['M_star']/df['V_p']**2
# periode revolution: T = 2*np.pi*r/V_p
df['T'] = 2*np.pi*df['r_orb']/df['V_p']
df['T_jours'] = df['T']/(24*3600)
df

Tracer les 2 nuages de points

%matplotlib qt
plt.clf()
axes = plt.gca()
"""nuage de points df issu de la BDD
"""
x = df['radius']
y = df['orbital_period']
z = df['_name']
plt.scatter(x,y,color='silver',marker='.',alpha=0.5)


   
"""nuage de points df_p issu des observations
"""
x_p = df_p['radius']
y_p = df_p['orbital_period']
z_p = df_p['_name']

plt.scatter(x_p,y_p,color='red',marker='o',label='Rho')
for x, y, z in zip(x_p, y_p, z_p):
    axes.text(x, y, f"({z})", fontsize=8)
plt.xscale('log')
plt.yscale('log')
plt.xlabel('radius')
plt.ylabel('orbital_period')
cursor = Cursor(axes, useblit=True, color='red', linewidth=2)
plt.show()
orbital_period vs radius en echelle log

orbital_period vs radius en echelle log

Partager la fenêtre graphique en plusieurs graphiques

Travail: le script ci-dessous permet de visualiser plusieurs graphiques sur la même sortie. Adapter le script pour sélectionner les grandeurs correlées.

plt.figure(figsize=(12, 8))
plt.subplot(221)

x = 'semi_major_axis'
y = 'orbital_period'
plt.scatter(dataset[x],dataset[y], marker="o", s=25)
plt.xlabel(x)
plt.ylabel(y)
#plt.xscale('log')
#plt.yscale('log')
plt.xticks(())
plt.yticks(())
#plt.legend(loc="best")


plt.subplot(224)
x = 'semi_major_axis'
y = 'orbital_period'
plt.scatter(dataset[x],dataset[y], marker="o", s=25)
plt.xlabel(x)
plt.ylabel(y)
#plt.xscale('log')
#plt.yscale('log')
plt.xticks(())
plt.yticks(())



plt.subplot(222)
x = 'semi_major_axis'
y = 'orbital_period'
plt.scatter(dataset[x],dataset[y], marker="o", s=25)
plt.xlabel(x)
plt.ylabel(y)
#plt.xscale('log')
#plt.yscale('log')
plt.xticks(())
plt.yticks(())

plt.subplot(223)
x = 'semi_major_axis'
y = 'orbital_period'
plt.scatter(dataset[x],dataset[y], marker="o", s=25)
plt.xlabel(x)
plt.ylabel(y)
#plt.xscale('log')
#plt.yscale('log')
plt.xticks(())
plt.yticks(())


plt.show()

Et maintenant…

  • Vous savez placer les nouvelles exoplanètes sur un graphique en nuage de points, au milieu des autres planètes de la base de données.
  • Vous savez sélectionner la représentation qui donnera le plus d’informations:
exemple de représentations à partir de différents choix d'axes

exemple de représentations à partir de différents choix d'axes

Une voie d’étude serait de rechercher des clusters (regroupements) de planètes pour certains choix d’axes, et d’associer nos exoplanètes à celles-ci.

Une autre voie possible serait d’intégrer la Terre, avec toutes ses caractéristiques connues, dans la table de la base de données. On établirait alors un coefficient, appelé Indice de Similarité avec la Terre (IST), qui permettrait de trier ces planètes selon l’IST décroissant: Lien vers l’étape 5

TP exoplanets.db

PARTIE 1: Base de données exoplanetes.db

Principe

Nous allons utiliser un script Python pour nous connecter à la base de données exoplanetes.db et tester quelques requêtes en langage SQLite.

Nous utiliserons la librairie sqlite3 de Python.

Utiliser un IDE comme Pyzo, Spyder, ou bien Jupyter Notebook pour editer et interpréter les scripts écrits en Python.

La base de données, issue du site exoplanet.eu doit être téléchargée ici : exoplanetes.db

Script de base

Connexion à la BDD

import sqlite3

try:
    conn = sqlite3.connect('exoplanets_migrated.db')
    cur = conn.cursor()
    print("Base de données crée et correctement connectée à SQLite")

    sql = "SELECT sqlite_version();"
    cur.execute(sql)
    res = cur.fetchall()
    print("La version de SQLite est: ", res)
    


except sqlite3.Error as error:
    print("Erreur lors de la connexion à SQLite", error)

Table planets

Pour avoir des informations sur la table:

sql = """
    PRAGMA table_info(planets);
    """
try:
    cur.execute(sql)
    res = cur.fetchall()
    print(f"{'Attribut':<20} {'Domaine':<10}")
    print("-" * 30)
    for row in res:
        print(f"{row[1]:<20} {row[2]:<10}")


except sqlite3.Error as error:
    print("Erreur lors de la connexion à SQLite", error)

Résultat:

Attribut             Domaine   
------------------------------
planet_id            INTEGER   
name                 TEXT      
planet_status        TEXT      
mass                 REAL      
radius               REAL      
orbital_period       REAL      
semi_major_axis      REAL      
eccentricity         REAL      
discovered           INTEGER   
detection_type       TEXT      
molecules            TEXT      
star_id              INTEGER

table stars

Travail: Adapter le script précédent pour avoir les informations de la table stars

Selection avec jointure

La requête suivante va donner les informations sur les premières exoplanètes de la table, ainsi que leur étoile, avec jointure entre les 2 tables.

try:
    sql = """
        SELECT p.name, p.mass, p.radius, s.star_name, s.star_teff
        FROM planets p
        JOIN stars s ON p.star_id = s.star_id
        LIMIT 5;
    """
    cur.execute(sql)
    res = cur.fetchall()
    print(f"{'Planète':<20} {'Masse':<10} {'Rayon':<10} {'Étoile':<15} {'Teff'}")
    print("-" * 60)
    for row in res:
        print(f"{str(row[0]):<20} {str(row[1]):<10} {str(row[2]):<10} {str(row[3]):<15} {row[4]}")
    


except sqlite3.Error as error:
    print("Erreur lors de la connexion à SQLite", error)

A Faire: Executer le script précédent pour obtenir…

Planète              Masse      Rayon      Étoile          Teff
------------------------------------------------------------
11 Com b             None       None       11 Com          4742.0
11 Oph b             21.0       None       11 Oph          2375.0
11 UMi b             None       None       11 UMi          4340.0
14 And b             None       None       14 And          4813.0
14 Her b             None       None       14 Her          5311.0

PARTIE 2: Requetes diverses sur la BDD

Explorer la base de données

Aidez vous du script précédent, que vous modifierez pour repondre aux questions ci-dessous. Sélectionnez en au moins 4.

  1. (table stars) Toutes les données relatives à l’étoile Kepler-89 b
  2. (table planets) Tous les noms des planètes dont la masse est plus de 10 fois supérieure à celle de Jupiter (Indiquer quelles sont ces planètes dans l’extrait de la table)
  3. (tables planets ET stars) Les planètes ainsi que le nom de l’étoile hôte, dont l’étoile est située à moins de 40 pc de la Terre.
  4. (tables planets ET stars) Les noms des 20 étoiles les plus proches de la Terre où des planètes ont été détectées.
  5. (table planets) Nombre total de planètes dans la table planets (utiliser COUNT(*))
  6. (table stars) Nombre total d’étoiles dans la table stars
  7. (table planets) Table des planètes qui n’ont été détectées ni par “Radial Velocity”, ni par “Primary Transit”
  8. (table planets) Le nombre de planètes qui n’ont été détectées ni par “Radial Velocity”, ni par “Primary Transit”
  9. (table stars) Moyenne des distances entre le Soleil et les différentes étoiles de la table (utiliser AVG). Attention à ne compter qu’une seule fois chacune des étoiles.
  10. (tables planets ET stars) Table des planètes où le type de l’étoile est G … (utiliser LIKE "G%")
  11. (tables planets ET stars) Nom des planètes et distances au soleil, où de l’eau a été détectée (utiliser LIKE)
  12. (tables planets ET stars) Le classement des étoiles, par ordre décroissant de leur nombre de planètes. (GROUP BY, ORDER BY). Limiter à 10 étoiles.

Traitement

Ajouter une colonne masse volumique

Travail: Commencer par créer une nouvelle colonne density dans la table planets, et afficher les attributs de cette table:

sql1 = """
    ALTER TABLE planets ADD COLUMN "density" REAL;
    """
sql2 = """
    PRAGMA table_info(planets);
    """
  • Executer le SQL:
try:
    
    cur.execute(sql1)
    cur.execute(sql2)
    res = cur.fetchall()
    print(f"{'Attribut':<20} {'Domaine':<10}")
    print("-" * 30)
    for row in res:
        print(f"{row[1]:<20} {row[2]:<10}")
    


except sqlite3.Error as error:
    print("Erreur lors de la connexion à SQLite", error)

Les données de la table planets sont relative à Jupiter. On rappelle que:

RJup = 71e6      # en m
MJup = 1.898e27  # en kg

La masse volumique de Jupiter est alors:

$$\rho = \tfrac{MJup}{\tfrac{4}{3}\times \pi \times (RJup)^3}$$

On peut définir une densité pour la planète comme le rapport $\tfrac{\rho_{planete}}{\rho_{Jupiter}} = \tfrac{mass}{radius^3}$.

On ajoutera simplement dans la colonne density

$$density = \tfrac{mass}{radius^3}$$

Travail: Ecrire la requête sql1 (UPDATE SET) pour calculer la density de chaque planète. Le calcul de $x^y$ peut necessiter l’ajout de la fonction power dans le langage SQL si celle-ci n’est pas implémentée (POWER):

conn.create_function("power", 2, lambda x, y: x**y if x != None and y!=None else None )
sql1 = """
        UPDATE planets SET density=mass/power(radius,3) 
       """

Travail: Récuperer ensuite les valeurs de la table (sql2), et afficher par ordre decroissant de densité. Executer les 2 requêtes (voir script complet ci-dessous)

Rq: fonctions mathematiques en SQL ici

Classement des planètes par densité décroissante

Obtenir le tableau suivant avec le classement des planètes par densité décroissante:

Planète              Masse      Rayon      Density            
------------------------------------------------------------
Kepler-57 c          6.95       0.138      2644.5241987281925
Kepler-57 b          18.86      0.195      2543.5357979736677
Kepler-52 c          10.41      0.164      2360.0390301939897
Kepler-59 b          2.05       0.098      2178.0890615304843
...

On peut utiliser le script ci-dessous (compléter la requête SQL):

conn.create_function("power", 2, lambda x, y: x**y if x != None and y!=None else None )
try:
    sql1 = """
        UPDATE planets SET density=mass/power(radius,3) 
       """
    sql2= """
        SELECT ... from planets order by ... DESC;
    """
    cur.execute(sql1)
    cur.execute(sql2)
    res = cur.fetchall()
    print(f"{'Planète':<20} {'Masse':<10} {'Rayon':<10} {'density':<15}")
    print("-" * 60)
    for row in res[:10]:
        # on limite la sortie à 10 planètes
        print(f"{str(row[0]):<20} {str(row[1]):<10} {str(row[2]):<10} {str(row[3]):<15}")
    


except sqlite3.Error as error:
    print("Erreur lors de la connexion à SQLite", error)

Etude graphique

La recherche de dépendances entre grandeurs se fera en traçant un graphique, avec différents essais pour les axes x,y.

On utilisera le resultat res de la requete precedente. C’est un tableau avec pour colonnes les nom, masse, rayon, densité.

On peut chercher par exemple la dépendance masse <-> rayon.

import matplotlib.pyplot as plt
plt.clf()
axes = plt.gca()
x = [P[1] for P in res] # mass
y = [P[2] for P in res] # radius

plt.scatter(x,y,color='silver',marker='.')
plt.xlabel('mass')
plt.ylabel('radius')
axes.set_xscale("log", base=10);
# ajout d'un marqueur "Jupiter"
z = "Jupiter"
MJ, RJ = 1,1
plt.plot(MJ,RJ,marker='o',color='red')
axes.text(MJ, RJ, f"({z})", fontsize=8)
plt.show()

Analyser chaque partie de ce script:

  • (1) Que font les instructions: x = [P[1] for P in res] et y = [P[2] for P in res] ?
  • (2) Comment adapter ces instructions pour tracer un graphique mass/densité?
  • (3) Pourquoi met-on l’echelle des abscisses en logarithme: axes.set_xscale("log", base=10)?
  • (4) Compléter ce script pour placer un marqueur de couleur bleue à l’emplacement de la Terre. Ajouter l’etiquette “Terre”

PARTIE 4: Méthode KNN

Calcul des valeurs m et r pour la Terre

R_Jup = 71e6  # m
M_Jup = 1.898e27 # kg
M_earth = 5.9724e24
R_earth = 6378.137e3
x_T = M_earth/M_Jup
y_T = R_earth/R_Jup
print(x_T,y_T)

Et recupération des valeurs de la table planets

try:
    sql= """
        SELECT name, mass, radius from planets;
    """
    cur.execute(sql)
    res = cur.fetchall()
    print(f"{'Planète':<20} {'Masse':<10} {'Rayon':<10}")
    print("-" * 60)
    for row in res[:10]:
        # on limite la sortie à 10 planètes
        print(f"{str(row[0]):<20} {str(row[1]):<10} {str(row[2]):<10}")
    
except sqlite3.Error as error:
    print("Erreur lors de la connexion à SQLite", error)

Visualisation

On adoptera la visualisation des axes : x = masse (en echelle logarithmique) et y = rayon.

Pour adapter les valeurs à ce système de coordonnées, on aura besoin de la fonction suivante:

def coordonnees_cercle_xlog_y(x_center, y_center, radius):
    # Cercle adapté à l'échelle logarithmique
    x_center_log = np.log10(x_center)
    theta = np.linspace(0, 2*np.pi, 100)
    # Points du cercle en coordonnées (log(x), y)
    x_circle_log = x_center_log + radius * np.cos(theta)
    y_circle = y_center + radius * np.sin(theta)
    # Reconvertir x en échelle normale
    x_circle = 10**x_circle_log
    return x_circle, y_circle

Puis, pour le tracé:

import matplotlib.pyplot as plt
import numpy as np

plt.clf()
axes = plt.gca()
x = [P[1] for P in res] # mass
y = [P[2] for P in res] # radius
plt.scatter(x,y,color='silver',marker='.')
plt.xlabel('mass')
plt.ylabel('radius')
axes.set_xscale("log", base=10)

# ajout d'une etiquette Jupiter
z = "Jupiter"
MJ, RJ = 1,1
plt.plot(MJ,RJ,marker='o',color='red')
axes.text(MJ, RJ, f"({z})", fontsize=8)

# ajout d'une etiquette Terre
z2 = "Terre"
plt.plot(x_T,y_T,marker='o',color='blue')
axes.text(x_T, y_T, f"({z2})", fontsize=8)

# Tracer le cercle autour de la Terre
x_circle,y_circle = coordonnees_cercle_xlog_y(x_T,y_T,0.3)
plt.plot(x_circle, y_circle, color='gold', linewidth=1.5)



plt.show()

Travail: Obtenir le graphique en nuage de points masse-rayon. Ajouter les instructions dans ce script pour tracer un autre cercle, centré autour de Jupiter.

Détermination des plus proches voisins

fonction distance_knn pour SQL

A Faire: Copier-coller la fonction suivante dans votre programme

# Distance KNN SQL
def distance_knn_sql(x, y):
    """
    Calcule la distance euclidienne à la Terre dans l'espace (log(masse), rayon)
    Compatible avec SQLite create_function
    
    Parameters:
    x : masse de la planète
    y : rayon de la planète
    
    Returns:
    distance : distance euclidienne à la Terre (ou None si données manquantes)
    """
    if x is None or y is None or x <= 0:  # log nécessite x > 0
        return None
    
    import math
    x_log = math.log10(x)
    x_T_log = math.log10(x_T)
    
    distance = math.sqrt((x_log - x_T_log)**2 + (y - y_T)**2)
    
    return distance

# Enregistrement de la fonction dans SQLite
conn.create_function("distance_knn", 2, distance_knn_sql)

nouvelle colonne distance

Travail:

  • (1) Créer une nouvelle colonne distance_terre dans la table planets :cur.execute("""ALTER TABLE ... ADD COLUMN ...""")
  • (2) Ajouter le script suivant, que vous devrez compléter et executer
# Calculer la distance pour toutes les planètes
cur.execute("""
    UPDATE planets 
    SET distance_terre = ... ...(mass, radius)
""")

# Puis pour sélectionner les K plus proches voisins
K = 5
cur.execute(f"""
    SELECT name, mass, radius, ... ...(mass, radius) as distance
    FROM planets
    WHERE ... ...(mass, radius) IS NOT NULL
    ORDER BY ...
    LIMIT {K}
""")
res = cur.fetchall()

Questions:

  • (1) Combien de planètes sont à l’intérieur du cercle de rayon 0.3, centré autour de la Terre?
  • (2) Quelle est l’exoplanète la plus ressemblante à la Terre?

Suite

Compléments

  • Fiche memo matplotlib et QCM: labex.io

recherche de correlations

Etape 6: Analyse graphique

Utiliser le tableau de données des planètes: dataset.csv

Importer les librairies et les datas:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import Cursor
import seaborn as sns

df = pd.read_csv('dataset.csv')
df
liste ordonnée par IST decroissant

liste ordonnée par IST decroissant

Utiliser une librairie de traitement de données python

Seaborn Python est une bibliothèque (un ensemble de modules) de visualisation de données en Python.

Pandas dataframe.corr() est une fonction qui calcule les correlations de paires à partir des séries (valeurs des colonnes) du dataframe.

La méthode de calcul est proposée ici

credit - datatab.net

credit - datatab.net

Principe:

  • on commence par créer une matrice de correlation à partir des colonnes de la table (dataframe). Aux intersections ligne/colonne on donne le résultat de la correlation entre les 2 séries (fonction corr)
  • puis on affiche cette matrice, en superposant des couleurs: fonction heatmap
corr = df.corr()
sns.heatmap(corr,cmap='coolwarm',annot=True,linewidth=0.9)
plt.show()
seaborn - matrice de correlation sur les colonnes du dataset

seaborn - matrice de correlation sur les colonnes du dataset

On voit par exemple que les grandeurs radius et orbital_period ne présentent pas de correlation (0.076), le maximum étant 1:

>>> corr['orbital_period']['radius']
0.076

Rechercher des clusters de planètes

On peut aussi utiliser la méthode pandas.plotting qui donne les nuages de point en miniature:

from pandas.plotting import scatter_matrix
import matplotlib.pyplot as plt
scatter_matrix(df,figsize=(8,8))
plt.show()

Rq: Les diagonales affichent les histogrammes pour les données de la série.

On a vu ici une autre manière de partager la fenêtre en plusieurs graphiques, et mettre les axes en echelle logarithmique:

Placer nos planètes étudiées

Choisir des axes avec des données correlées.

Pour commencer, filter les données pour les planètes à mettre en evidence: la Terre, ainsi que celles de TOI:

names = ['TOI-270 d','TOI-270 b','TOI-270 c','earth']
df_p = df[df['_name'].isin(names)]
df_p
tableau des planetes à repérer dans le graphique

tableau des planetes à repérer dans le graphique

Puis utiliser le script suivant pour superposer 2 nuages de points, dont l’un en couleur:

%matplotlib qt
plt.clf()
axes = plt.gca()
"""nuage de points df issu de la BDD
"""
x = df['radius']
y = df['orbital_period']
z = df['_name']
plt.scatter(x,y,color='silver',marker='.',alpha=0.5)


   
"""nuage de points df_p issu des observations
"""
x_p = df_p['radius']
y_p = df_p['orbital_period']
z_p = df_p['_name']

plt.scatter(x_p,y_p,color='red',marker='o',label='Rho')
for x, y, z in zip(x_p, y_p, z_p):
    axes.text(x, y, f"({z})", fontsize=8)
plt.xscale('log')
plt.yscale('log')
cursor = Cursor(axes, useblit=True, color='red', linewidth=2)
plt.show()
orbital_period vs radius en echelle log

orbital_period vs radius en echelle log

à vous de jouer

Faire un choix d’axes pertinent, afin de trouver des clusters d’exoplanètes et les comparer avec nos planètes d’étude.

Suite

  • Analyse, segmentation des données en clusters et previsions avec le module scikit-learn: étape 7

kmean et exoplanetes

Utiliser le module Scikit-learn

Que fait ce module?

Scikit-learn est une bibliothèque libre Python destinée à l’apprentissage automatique. Cette bibliothèque propose une série d’outils pour l’étude des données en table comme:

  • la regression linéaire
  • la classification
  • le clustering
  • …

Nous allons utiliser cette bibliothèque pour rechercher des dépendances entre les données des exoplanètes connues. Le travail de représentation graphique nous a montré que ces planètes se regroupent en clusters sur les diagrammes en nuages de points. (echelle log).

Scikit-learn va nous aider à determiner des classes d’exoplanètes (tellurique, gazeuse, similaire aux étoiles). Nous rappelons que la table dataset.csv contient les données des exoplanètes, de leurs étoiles, ainsi que les données ajoutées (Terre et système TOI_270).

Vous pouvez télécharger le dossier complet ici: sources.zip, contenant:

  • le fichier de dependances requirment.txt
  • la table dataset.csv
  • le notebook intro_IA.ipynb

Prérequis: Ce notebook demande d’être familiarisé avec les types np.array, et pandas.dataframe.

Apprentissage non supervisé

Les classes des astres ne sont pas renseignés dans la table dataset.csv. Pourtant, il apparait évident que ces astres se regroupent en amas, donc certainement en familles.

radius - mass en echelle log. Données issues du fichier dataset.csv

radius - mass en echelle log. Données issues du fichier dataset.csv

Le principe de la recherche de cluster par scikit-learn utilise la fonction kmeans de recherche de plus proches voisins. Elle peut être testé avec le script minimum ci-dessous:

import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# Génération de données aléatoires (non étiquetées)
np.random.seed(42)
data = np.random.rand(100, 2)  # 100 points avec 2 caractéristiques

# Création et entraînement du modèle K-Means
kmeans = KMeans(n_clusters=3, random_state=42)  # 3 clusters
kmeans.fit(data)

# Récupération des résultats
labels = kmeans.labels_  # Les clusters attribués à chaque point
centroids = kmeans.cluster_centers_  # Les centres des clusters

# Visualisation des clusters
plt.scatter(data[:, 0], data[:, 1], c=labels, cmap='viridis', s=50, alpha=0.7)
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', marker='X', s=200, label='Centroids')
plt.title("Clustering avec K-Means")
plt.xlabel("Caractéristique 1")
plt.ylabel("Caractéristique 2")
plt.legend()
plt.show()
exemple de resultat donné par la recherche de clusters (données aléatoires)

exemple de resultat donné par la recherche de clusters (données aléatoires)

La fonction kmeans utilise l’algorithme de LLoyd. La recherche d’un centre de cluster (centroïd) pourrait se faire par recherche exhaustive, mais alors, la complexité serait très importante et le temps de calcul rapidement divergent avec le nombre de points. Dans cet algorithme, la recherche est basée sur un algorithme glouton. Celui-ci va chercher à minimiser une grandeur appelée inertie, qui est calculée comme la distance du centroïd à ses voisins. Enfin, les points sont segmentés en plusieurs clusters, tels que la variance est à peu près identique pour le calcul de l’inertie.

Données de la table dataset.csv

Comme dans l’activité précédente: importer les données de la table:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('dataset.csv')
df

Réduire la table aux colonnes masse, rayon, nom:

df_reduit = df[['mass','radius','_name']]
df_reduit = df_reduit.dropna()
# echelle log
# rappel: les données sont normalisées par rapport à Jupiter
x = np.log(df_reduit['mass'])
y = np.log(df_reduit['radius'])

L = []
for x, y in zip(x, y):
    L.append([x,y])

L[:10]
# Affichage --------------------
[[-5.761407122499511, -2.409803828596342],
 [-4.567874401244395, -2.4079456086518722],
 [-5.0206856299497575, -2.4079456086518722],
 [-5.506572305368496, -2.406835114367845],
 [-5.8781358618009785, -2.419118909249997],
 [-3.101092789211817, -2.419118909249997],
 [-6.16581793425276, -2.372685720673535],
 [-5.4398809308698235, -2.3622289459215606],
 [-5.910806644090528, -2.3580978029243043],
 [-3.669469060594113, -2.4651040224918206]]
# ------------------------------

Recherche de cluster par apprentissage automatisé (Kmean: recherche des plus proches voisins)

import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# données (non étiquetées)

data = np.array(L)  

# Création et entraînement du modèle K-Means
kmeans = KMeans(n_clusters=3, random_state=50)  # 3 clusters
kmeans.fit(data)

# Récupération des résultats
labels = kmeans.labels_  # Les clusters attribués à chaque point
centroids = kmeans.cluster_centers_  # Les centres des clusters

# Visualisation des clusters
plt.scatter(data[:, 0], data[:, 1], c=labels, cmap='viridis', s=5, alpha=0.7)
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', marker='X', s=200, label='Centroids')
plt.title("Clustering avec K-Means")
plt.xlabel('mass')
plt.ylabel('radius')
plt.legend()
plt.show()
segmentation en 3 clusters

segmentation en 3 clusters

On peut alors vérifier la valeur donnée aux 3 étiquettes (classes) , ainsi que le nombre d’items dans chaque classe:

valeurs, comptes = np.unique(labels, return_counts=True)
valeurs,comptes
# Affichage --------------------
(array([0, 1, 2], dtype=int32), array([156, 381, 493]))
# ------------------------------
  • classe 0: couleur violette = les étoiles
  • classe 1: couleur verte = planètes telluriques
  • classe 2: couleur jaune = planète gazeuses

Superposer les exoplanètes de TOI_270 et celles de la Terre

Selection des planètes TOI_270 ainsi que la Terre dans la table dataset.csv:

names = ['TOI-270 d','TOI-270 b','TOI-270 c','earth']
df_p = df[df['_name'].isin(names)]
"""nuage de points df_p issu des observations
"""
x_p = np.log(df_p['mass'])
y_p = np.log(df_p['radius'])
z_p = df_p['_name']

Superposition des données de df_p:

plt.clf()
axes = plt.gca()
# data et labels sont calculés plus haut 
plt.scatter(data[:, 0], data[:, 1], c=labels, cmap='viridis', s=5, alpha=0.7)
plt.scatter(x_p,y_p,color='red',marker='o')
for x0, y0, z0 in zip(x_p, y_p, z_p):
    axes.text(x0+0.4, y0*1.1, f"({z0})", fontsize=10)
plt.xlabel('mass')
plt.ylabel('radius')
plt.show()
superposition des planètes du système TOI_270 et de la Terre

superposition des planètes du système TOI_270 et de la Terre

Prévision des classes pour les planètes de TOI_270

Prediction pour la planète Jupiter

  • Documentation: La fonction Kmeans du module scikit-learn

  • En pratique:

kmeans.predict([[0,0]])
# Affichage --------------------
array([2], dtype=int32)
# ------------------------------

Jupiter est de classe 2 (cluster jaune)

Planètes du tableau reduit x_p, y_p

Liste = []
for i,j,k in zip(x_p,y_p,z_p):
    Liste.append((i,j,k))
Liste = np.array(Liste)
Liste
# Affichage --------------------
array([['-5.761407122499511', '-2.409803828596342', 'earth'],
       ['-5.115995809754082', '-2.1959753579357875', 'TOI-270 b'],
       ['-4.074541934925921', '-1.6607312068216509', 'TOI-270 d'],
       ['-3.872802292274865', '-1.5329399414613754', 'TOI-270 c']],
      dtype='<U32')
# ------------------------------

Prediction à partir des données:

# reduction du tableau aux 2 colonnes masse et rayon
couples_xp_yp = Liste[:,:2]
# prediction
kmeans.predict(couples_xp_yp)
# Affichage --------------------
array([1, 1, 1, 1], dtype=int32)
# ------------------------------

Comme attendu d’après le graphique précedent, les 4 planètes du tableau df_p sont de classe 1. (cluster vert)

modularité

Ce chapitre comprend 2 pages de cours et une page exercices:

  • La mise au point d’un programme: Lien 1
  • Création et utilisation de modules: Lien 2

La liste des projets se trouve ici

Modularité

Qu’est ce qu’un module ?

Un module est un fichier python (d’extension .py) contenant des fonctions. En principe, il n’est pas prévu pour être executé. Pour faire référence aux fonctions de ce module, il faut l’importer depuis le script principal (ìmport module.py`).

Quand utiliser un module ?

Lorsque vous réalisez un projet en python, votre script s’agrandit, et vous aurez certainement le besoin de séparer votre code dans plusieurs fichiers.

Ainsi, il vous est facile de réutiliser des fonctions écrites pour un programme dans un autre sans avoir à les copier.

Mettre son programme sous forme de modules

On a vu la différentes manières d’importer un module dans le cours Python > Fonctions

On peut souhaiter, par exemple, créer une représentation graphique des nombres premiers dans une fenêtre turtle. On souhaite diviser les fonctions dans 2 fichiers:

  • le fichier executable (appelé le fichier main): imaginons que vous lui donniez le nom nombresPrem.py. Ce fichier ne contiendra que les fonctions relatives au calcul des nombres premiers. On y mettre aussi l’instruction qui appelera la fonction de dessin du module. C’est elle qui construira et dessinera dans la fenêtre graphique.
  • le fichier module de nom fcts_turtle.py qui contiendra toutes les fonctions utiles pour la représentation graphique. On supposera que ce fichier contient la fonction ulam qu’il faudra appeler pour declencher le tracé.

Le dossier contient alors:

Le fichier principal nombresPrem.py sera organisé comme ceci:

#####partie import des modules############
import fcts_turtle

#####variables globales####################
# declaration des variables globales

#######definition des fonctions############
# def des fonctions du fichier main
# pour le calcul des nombres premiers

######corps du programme : ################
### à executer si fichier main ############
if __name__=='__main__':
    # calcul d'une liste de nombres premiers
    # appel de la fonction de dessin du module:
    fcts_turtle.ulam(liste_premiers,N)
###########################################

Il est recommandé de mettre les instructions du programme principal dans un bloc avec le test if __name__=='__main__':

Ceci permet d’importer le contenu du fichier sans déclencher son execution; et permettre de realiser des tests sur les fonctions. Voir tests sur les modules avec unittest

Le module fcts_turtle.py :

"""
    DOCSTRING
"""
#####partie import des modules externes###
import turtle

#######definition des fonctions du module#
# fonction de dessin de la fenêtre
# fonction ulam(liste_premiers,N)
##########################################

Remarque : Il est essentiel que le module comprenne un docstring BIEN documenté.

Gérer les modules

depuis le shell python

Il est possible de parcourir les dossiers du disque dur, travailler sur les fichiers, etc, comme avec un shell Unix. Depuis le notebook ou bien depuis un shell python, il faut commencer par importer le module os. Les instructions utiles sont :

  • listdir() pour lister
  • getcwd() pour obtenir le chemin (CWD = « Current Working Directory »)
  • chdir() pour changer de dossier
import os
os.listdir() 
# renvoie la liste des fichiers et dossiers:
['fenDestroy.py',
 'fcts_turtle.py',
 'tk_turtle.py',
 '__pycache__',
 'spirale_ulam.py',
 'nombresPrem.py']
os.getcwd()
# donne le chemin du dossier courant
'/Users/nom_user/Applications/python/dessins'
os.chdir('..') # permet de remonter au dossier parent
os.getcwd()
# affiche '/Users/nom_user/Applications/python`
os.chdir(`dessin/turtle`) # se deplacer dans un sous dossier
os.getcwd()
# affiche '/Users/nom_user/Applications/python/dessins/turtle`

Une différence avec le shell Unix est le traitement des noms de fichiers et dossiers qui sont mis entre guillemets. Ce sont des chaines de caracteres pour python.

Afficher le contenu et l’aide d’un module

depuis le shell python, se placer dans le repertoire contenant le module ou adapter le chemin, puis:

  • importer le module
  • lister les fonctions contenues dans le module avec dir(nom_du_module)

Exemple avec le module fcts_python.py:

import fcts_turtle
dir(fcts_turtle)
# affiche
['fenDestroy.py',
 'fcts_turtle.py',
 'tk_turtle.py',
 '__pycache__',
 'spirale_ulam.py',
 'nombresPrem.py']

Afficher les fonctions et le Docstring du module et des fonctions: help(nom_du_module):

import fcts_turtle
help(fcts_turtle)
# affiche :
Help on module fcts_turtle:

NAME
    fcts_turtle

FUNCTIONS
    close_window()
    
    ulam(premiers, N, L=220, h=220)

Rq: Notez que le fichier est bien enregistré avec une extension .py et pourtant on ne la précise pas lorsqu’on importe le module.

Et si le Docstring du module est présent:

import fcts_turtle
help(fcts_turtle)
# affiche:
Help on module fcts_turtle:

Help on module fcts_turtle:

NAME
    fcts_turtle - module pour visualiser les nombres premiers

DESCRIPTION
    fonctions utiles pour tracer une spirale avec turtle.

FUNCTIONS
    close_window()
    
    ulam(premiers, N, L=220, h=220)
        represente la spirale de Ulam
        
        Params
        ------
        premiers: list
            les nombres premiers
        N: int
            derniere valeur de la spirale
        L: int
            dimension du rectangle en largeur. 220px par defaut
        h: int
            dimension du rectangle en hauteur. 220 px par defaut
        
        Principe
        --------
        Les nombres sont ecrits sur la spirale. En rouge si le nombre est premier, en noir sinon.
        
        Appel
        -----
        ulam(premiers,100) # tracé de la spirale avec la liste de nombres premiers mis en argument, jusqu'à N=100.

Créer le Docstring d’un module

Un docstring est un commentaire multi-lignes utilisé pour documenter des modules, des classes, des fonctions et des méthodes. Il doit s’agir de la première déclaration du composant qu’il décrit.

Une bonne docstring de fonction doit contenir tout ce dont un utilisateur a besoin pour utiliser cette fonction. Une liste minimale et non exhaustive serait :

  • ce que fait la fonction,
  • ce qu’elle prend en argument,
  • ce qu’elle renvoie.

En pratique

  • démarrer le fichier par un commentaire multi-lignes qui documente le module
  • ajouter le prototype de chaque fonction selon la méthode vu dans le cours langage/mise au point

Voici un exemple de commentaire multi-lignes pour présenter le module (mis à la premiere ligne du fichier):

"""module pour visualiser les nombres premiers

fonctions utiles pour tracer une spirale avec turtle.
"""

ce qui renvoie à l’aide de la commande help(module):

Help on module fcts_turtle:

NAME
    fcts_turtle - module pour visualiser les nombres premiers

DESCRIPTION
    fonctions utiles pour tracer une spirale avec turtle.

FUNCTIONS
    (prototype de chaque fonction)

Liens

mise au point

Ce chapitre comprend 2 pages de cours et une page exercices:

  • La mise au point d’un programme: Lien 1
  • Création et utilisation de modules: Lien 2
  • Exercice: Lien

Programmer en Grand

L’infographie ci-contre montre une mesure des lignes de code dans certains programmes conséquents. Les mesures sont en millions de ligne de code:

codebase - millions lines of code visualized

codebase - millions lines of code visualized

On peut ajouter qu’il y a omniprésence de programmes longs dans des systèmes critiques : finance, transports, économie, santé… La moindre erreur peut coûter « cher » : on aimerait qu’un programme s’exécute correctement dans toutes les situations…

Maintenir le code, travailler en équipe demande également une certaine méthodologie.

Pour programmer en grand, c’est à dire programmer avec plusieurs fichiers, il faudra adopter les bonnes pratiques, c’est à dire:

  • documenter ses fonctions
  • procéder par étapes, en ajoutant des tests structurels pour aider au developpement
  • utiliser des modules pour ses fonctions et classes
  • tester ses fonctions, vérifier qu’elles fonctionnent correctement.
du script aux tests unitaires, une démarche de projet

du script aux tests unitaires, une démarche de projet

En Python, pour créer une cohérence dans le code, il est recommandé d’utiliser un guide de style. Il s’agit de PEP8, présenté par exemple sur python.sdv.univ-paris-diderot.

Spécification d’un algorithme ou d’une fonction

Spécifier un algorithme signifie qu’on le décrit avec précision. On spécifie chacun des composants, structures de données et fonctions.

  • La documentation peut-être en consultation dans un document externe au programme (un fichier readme.md, une page sur wikipedia, …). Cette documentation peut alors fournir un pseudo-code, c’est à dire une série d’instruction avec des conventions de langages empruntées aux principaux langages existants, sans toutefois être rédigée dans un langage particulier.
  • Mais cela peut-être réalisé aussi au sein même du code du programme ou de la fonction. On y ajoute alors des informations facultatives lors de la déclaration de la fonction ou dans le docstring.

De manière générale, la spécification va comprendre :

  • Le nom donné à cet algorithme. Ce nom doit être explicite, en rapport avec la tâche effectuée par l’algorithme
  • Une description du résultat de cet algorithme, ainsi que la manière avec laquelle on va s’y prendre
  • Le type et la nature des données en entrée
  • Le type et la nature des données en sortie
  • eventuellement, le type et la nature des variables internes.

Documentation externe à l’aide d’un pseudo-code

Le pseudo langage adopté est celui utilisé dans wikipedia : exemple

Exemple de pseudo langage: recherche_du_maximum

"""
L'algorithme recherche la valeur maximale dans la liste.
variables en entrée : 
------------------
:ma_liste : list, une liste de valeurs entieres, uniques, mises dans un ordre aléatoires.
:max : int, stocke la valeur maximale actuelle. Initialisé à 0.
Sortie :
------
:max : int, prend la valeur de l'élément le plus grand de la liste
Principe : 
--------
on parcourt la liste avec une boucle bornée.
si la valeur la valeur de max est inferieure à la valeur courante, max est actualisée avec cette valeur courante
Exemple:
> recherche_maximum([0,2,3,1])
3
--------
"""
max := 0
pour i allant du premier au dernier element de ma_liste faire
    si i > max  
        max := i
    fin
fin
afficher max

Nous allons adapter cette spécification, prévue pour expliquer des algorithmes, à nos fonctions écrites en python.

Documentation interne

La spécification au sein même de la fonction se fait en 2 temps:

  • lors de la déclaration
  • juste après la déclaration, dans le prototype (docstring) de la fonction.

Dans la déclaration de la fonction (prototype)

Une fonction doit être déclarée avant son utilisation. Cette déclaration est le prototype de la fonction. Le prototype doit indiquer à l’utilisateur le nom de la fonction, le type de la valeur de retour et le type des paramètres.

Pour de nombreux langages, ce prototypage est explicite, et cela provoque une erreur de compilation si ce prototypage n’est pas correct.

Exemple de déclaration d’une fonction en langage ADA :

function A_Rect(larg : natural ; long : natural) return natural is
  A : natural ; 
begin
  A:= larg * long;
  return A;
end A_Rect ;

En pratique: en Python, ces déclarations sont facultatives, mais on pourra les ajouter dans la première ligne, de la manière suivante:

def a_rect(larg: float, longueur: float) -> float:
    a = larg * longueur
    return a

Remarquez la difference avec la déclaration minimale suivante, qui n’apporte pas d’information sur les types:

def a_rect(larg, longueur):
    ...

Docstring d’une fonction

En python, on pourra construire le docstring dans le commentaire, mis tout de suite après la déclaration de la fonction :

def a_rect(larg,long):
    """Le produit de 2 nombres.
    Renvoie le produit des 2 nombres passés en argument
    
    :param larg : int ou float
           la largeur du rectangle
           
    :param long : int ou float
           la longueur du rectangle
    
    :return a: int ou float
            larg * long
    
    Exemple
    -------
    >>> a_rect(2,3)
    6
    """
    a = larg * long
    return a

Pour accéder au contenu du docstring depuis le shell python, il faudra charger le fichier: > from fichier import *, puis utiliser help:

> help(a_rect)

Pour sortir de la fenêtre de l’aide, appuyer sur la touche q.

On pourra consulter la page du site Lyceum pour plus d’informations.

Prévoir et gérer les erreurs

Gérer les erreurs: lire le Traceback

L’exécution d’un programme peut provoquer une erreur, une exception. Lorsque c’est le cas, l’exécution s’arrête immédiatement et l’interpréteur Python affiche une trace d’erreur.

Cette dernière fournit des informations quant au chemin d’exécution qui a mené jusqu’à l’erreur et sur la cause de cette dernière.

La console affiche Traceback, qui marque le début de la trace d’erreur.

On peut distinguer 3 types d’erreurs :

  • erreur de syntaxe
  • erreur d’execution
  • erreur de logique
def inverse (x):
    y = 1.0 / x
    return y

a = inverse(2)
print(a)
b = inverse(0)
print(b)

L’interpréteur Python affiche ce qu’on appelle la pile d’appels ou pile d’exécution. La pile d’appel permet d’obtenir la liste de toutes les fonctions pour remonter jusqu’à celle où l’erreur s’est produite.

ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-24-bdb719052d31> in <module>
      5 a = inverse(2)
      6 print(a)
----> 7 b = inverse(0)
      8 print(b)

<ipython-input-24-bdb719052d31> in inverse(x)
      1 def inverse (x):
----> 2     y = 1.0 / x
      3     return y
      4 
      5 a = inverse(2)

ZeroDivisionError: float division by zero

Connaitre les messages d’exception

Les messages d’exception affichés par le Traceback.

message type erreur
SyntaxError parenthèse, crochet ou guillemet mal fermé
IndentationError mauvaise indentation
ZeroDivisionError division par zero
NameError nom de fonction ou de variable mal orthographié
IndexError accès à une position en dehors d’une liste
AttributeError accès à une méthode ou à un attribut inconnu. Exemple: ’list’ object has no attribute ‘appand’
TypeError types incompatibles pour l’opération demandée. Exemple: unsupported operand type(s) for ‘-’: ‘range’ and ‘int’
ValueError une valeur est inappropriée pour une certaine opération
KeyError Une clé est utilisée pour accéder à un élément d’un dictionnaire dont elle ne fait pas partie

Anticiper les erreurs: Les tests STRUCTURELS

les tests structurels, vont verifier le fonctionnement interne du programme. Leur rôle est par exemple de couvrir les différentes branches conditionnelles, les limites d’une boucle, les types de données possibles pour une opération, …

Ces tests vont aider à programmer en grand, car ils vont fournir des moyens de contrôle à différentes étapes. Ils vont aussi guider l’utilisateur de vos fonctions grâce aux messages d’erreurs et arrêts du programme.

Attention, il s’agit de trouver des erreurs, plutôt que de prouver que ça marche. C’est une validation expérimentale du programme.

On placera des pré-conditions et post-conditions autour de la fonction à tester. Ce sont des tests structurels, qui vont arrêter le programme et spécifier le type d’erreur, pour aider à debugger.

Assertions: assert

Les assertions sont les hypothèses avec vérification.

Le rajout provisoire d’assertions dans le script va permettre d’anticiper sur les erreurs possibles de logique.

Le mécanisme d’assertion est là pour empêcher des erreurs qui ne devraient pas se produire, en arrêtant prématurément le programme. C’est un mode de programmation défensif, dans lequel on vérifie les préconditions.

Méthode : assert <expression logique>, 'commentaire facultatif'

L’expression logique doit être egale à True pour que le programme se poursuive.

Exemple avec une erreur d’execution :

def inverse (x):
    assert x != 0, 'argument nul'
    y = 1.0 / x
    return y

Lorsque l’on execute la fonction inverse avec zero comme argument, le programme s’arrête et renvoie le message suivant dans le Traceback:

inverse(0)

AssertionError : argument nul

Mais l’interêt réside surtout dans l’utilisation d’assertion pour prévenir une possible erreur logique:

On souhaite maintenant obtenir le même comportement (arrêt pour une valeur sortant de l’ensemble de définition d’une fonction) pour la fonction de conversion de degré Celsius en degré Kelvin. En effet, il n’y aurait aucun sens de convertir une température inférieure à la température correspondant au zéro absolu. (exemple issu de univ.lille)

def en_kelvin(c) :
    """
      conversion en kelvin d'une température donnée en Celsius
      C.U. c doit être supérieure au zéro absolu.

    """
    assert c>-273.15, "valeur inferieure au zero absolu"
    return 9*c/5+32

Alors :

en_kelvin(-500)
# Affichage
AssertionError valeur inferieure au zero absolu

Déclencher des exceptions Raise

L’instruction raise permet au programmeur de déclencher une exception spécifique. Son utilisation diffère un peu de assert, car la condition qui déclenche l’arrêt du programme devra être ajoutée:

Exemple:

def inverse (x):
    if x == 0:
        raise ValueError
    y = 1.0 / x
    return y

inverse(0)

Puis:

> inverse(0)
---
Traceback (most recent call last):
  File "<input>", line 7, in <module>
  File "<input>", line 3, in inverse
ValueError

Notez que le type d’erreur exprimé après l’instruction raise est librement choisie par le programmeur, mais elle doit exister dans le langage Python. (IndexError, SyntaxError, ValueError, …)

Gestion des exceptions: try-except

Le mécanisme try-except va combiner des pré-conditions et post-conditions.

On pourra consulter les compléments sur la gestion des exceptions:

Le mécanisme des exceptions permet au programme de « rattraper » les erreurs, de détecter qu’une erreur s’est produite et d’agir en conséquence afin que le programme ne s’arrête pas.

Afin de rattraper l’erreur, on insère le code susceptible de produire une erreur entre les mots clés try et except.

Méthode :

try:
    # ... instructions à protéger
except:
    # ... que faire en cas d'erreur
else:
    # ... que faire lorsque aucune erreur n'est apparue
finally: 
    # ... ce que l’on réalise quel que soit le fonctionnement precedent

L’instruction try fonctionne comme ceci.

  • Premièrement, la clause try (instruction(s) placée(s) entre les mots-clés try et except) est exécutée.
  • Si aucune exception n’intervient, la clause except est sautée et l’exécution de l’instruction try est terminée.
  • Si une exception intervient pendant l’exécution de la clause “try”, le reste de cette clause est sauté. Si son type correspond à un nom d’exception indiqué après le mot-clé except, la clause “except” correspondante est exécutée, puis l’exécution continue après l’instruction try.

Exemple 1:

def inverse(x):
    y = 1.0 / x
    return y


try:
    a = inverse(2)
    print(a)
    b = inverse(0)  # déclenche une exception
    print(b)
except:
    print("le programme a déclenché une erreur")

# affiche : 
0.5
le programme a déclenché une erreur

Testez le vous-même: créez une liste d’entiers pour x. Et essayez (try) de mettre dans une nouvelle liste les valeurs retournées par inverse, à moins (except) que la valeur de x soit nulle.

Exemple 2: Si on veut convertir un caractère en entier, cela génère une erreur de type ValueError:

>>> int(input("Please enter a number: "))
Please enter a number: q
ValueError: invalid literal for int() with base 10: 'q'

On peut utiliser un mecanisme d’exception pour rattraper cette erreur possible:

while True:
     try:
         x = int(input("Please enter a number: "))
         break
     except ValueError as typ:
         print("Oops!  That was no valid number.  Try again...: {}".format(typ))
print('=> vous avez entré le nombre {}'.format(x))

Executons ce script:

Please enter a number: d
Oops!  That was no valid number.  Try again...: invalid literal for int() with base 10: 'd'
Please enter a number: Z
Oops!  That was no valid number.  Try again...: invalid literal for int() with base 10: 'Z'
Please enter a number: 2
=> vous avez entré le nombre 2

Programmer des tests FONCTIONNELS

tests fonctionnels: ils verifient qu’un programme ou une partie du programme se comportent correctement, et se conforment à leur specification.

Fonctionnel: avec un Doctest

Le doctest est un module qui recherche dans le prototypage (docstring) de la fonction ce qui pourrait s’apparenter à des tests sur la fonction.

On écrit alors une simulation d’un essai directement dans le docstring, en écrivant de manière explicite les 3 chevrons. Ainsi que la valeur attendue pour des arguments choisis. (voir le paragraphe précédent)

Comme par exemple:

>>> a_rect(2,3)
6

Cette information sera placée dans le docstring de la fonction, et servira à anticiper des erreurs commises lors de la programmation.

Pour déclencher les tests sur la fonction, on ajoutera alors à la suite du script les lignes suivantes:

if __name__ == "__main__":
    import doctest
    doctest.testmod()

Supposons que l’on ait fait une erreur dans la fonction a_rect sur la valeur calculée, et que l’on ait écrit:

    # a = long * larg
    a = long * long
    return a

Exemple complet:

def aire(larg,long):
    """
    >>> a_rect(2,3)
    6
    """
    # a = long * larg
    a = long * long
    return a

if __name__ == "__main__":
    import doctest
    doctest.testmod()

Lorsque l’on execute le fichier, la console affichera:

Failed example:
    a_rect(2,3)
Expected:
    6
Got:
    9

Documentation officielle :Lien

Fonctionnel: avec un module de test unitaires: unittest

Définition: Un test unitaire est un test réalisé sur une portion du programme, typiquement sur une fonction.

Le module unittest offre des outils de test de code, comme la classe TestCase. Le but est de vérifier que votre code génère des résultats corrects, conformes au attentes.

Exemple

import unittest

def add(x,y):
    return x + y

class MyTest(unittest.TestCase):
    def test_add(self):
        self.assertEqual(add(3,4), 7)

if __name__ == '__main__':
    unittest.main()

Explications

On commence par importer le module unittest.

Les noms des classes de test se terminent généralement par TestCase (scenario de test). La classe créée pour le test, MyTest doit être une classe enfant de unittest.TestCase, d’où l’instruction class MyTest(unittest.TestCase):

Chaque test à créer est une méthode. Toute méthode dont le nom commence par test_ est exécutée lors du test. La méthode test_add appelle donc la fonction add avec les arguments 3 et 4, puis vérifie que son résultat est conforme, grâce à un test d’assertion assertEqual.

Ici, le test reussit:

En console:

Ran 1 tests, passed: 1 failed: 0

On ajoute maintenant un deuxième test:

import unittest

def add(x,y):
    return x + y

class MyTest(unittest.TestCase):
    def test_add1(self):
        self.assertEqual(add(3,4), 7)
        
    def test_add2(self):
        self.assertEqual(add(3,4), 8)

if __name__ == '__main__':
    unittest.main()

Le deuxième test échoue. On peut remonter jusqu’à l’erreur dans le Traceback qui est affiché en console:

# Traceback
Fail: Expected 7 to equal 8
Tests failed in  MyTest.test_add2  
Ran 2 tests, passed: 1 failed: 1

Le module unittest fournit d’autres fonctions comme par exemple assertRaises. La liste complète est ici

  def test_split(self):
    s = 'hello world'
    # check that s.split fails when the separator is not a string
    self.assertRaises(TypeError,s.split,1)

Console: Test reussi

Ran 1 tests, passed: 1 failed: 0

Explications

La fonction split prend en argument un caractère et decoupe la chaine de caractères au niveau de ce caractère. (et retourne une liste).

Par exemple:

s = 'hello world'
print(s.split(' '))
# affiche
['hello','world']

L’argument DOIT être un caractère et non un nombre entier ou autre type. Sinon, l’execution génère un TypeError:

s = 'hello world'
print(s.split(1))
# affiche
TypeError          Traceback (most recent call last)
<ipython-input-32-6acfb0b512b4> in <module>
      1 s = 'hello world'
----> 2 print(s.split(1))
TypeError: must be str or None, not int

Or, ici, on fait le test d’assertion suivant: on vérifie si lorsque l’on appelle la fonction s.split avec l’argument 1, cela génère un TypeError, ce qui est VRAI. Donc le test REUSSI!

Par contre, avec self.assertRaises(TypeError,s.split,' '), cela echoue…

Fail: 
Tests failed in  MyTest.test_split  
Ran 1 tests, passed: 0 failed: 1

Testez ces exemples

Ces exemples peuvent être testés dans l’éditeur en ligne Trinket.

Modifiez le programme deposé sur Trinket pour separer dans 2 fichiers: le fichier de test et le fichier contenant la fonction à tester.

Autres tests

En fait, unittest.TestCase propose plusieurs méthodes d’assertion que nous utiliserons dans nos tests unitaires.

Méthode Explications
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) x is True
assertFalse(x) x is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a, b)
assertNotIsInstance(a, b) not isinstance(a, b)
assertRaises(exception, fonction, *args, **kwargs) Vérifie que la fonction lève l’exception attendue.

Exercice

On souhaite traiter un ensemble de données issues d’un capteur (robot). Les données sont mises dans 2 listes:

  • une liste pour les positions: x = [0, 1.0, 1.2, 1.4, ...]
  • une liste pour le temps: t = [0.0, 0.0123, 0.0247, 0.0247, 0.0320, ...]

On cherche à définir la vitesse du robot au cours du temps dans une 3e liste. Les valeurs sont calculées à partir de la loi:

$$v[i] = \tfrac{x[i+1] - x[i]}{t[i+1]-t[i]}$$

Les valeurs du temps peuvent générer des erreurs mathématiques (temps égaux pour $t_{i+1}$ et $t_i$).

Utiliser un mécanisme de prevention des erreurs et testez votre programme.

Suite

Sources

NSI term

Agenda

Rentrée

Semaine du 01/09/26

Semaine du 08/09/26

  • Les types construits en python Lien vers TP2
  • TD1 fiche de TD sur les types construits (Listes): pdf

Semaine du 15/09/26

Semaine du 22/09/26

Semaine du 05/10/26

Semaine du 12/10/26

  • Cours sur les algos de tri: Lien et version pdf
  • Exercices sur PROUVER un algorithme et raisonnement par recurence: pdf
  • TP algos de tri: Lien
  • Orientation (académie de Nice): Lien vers la page
    • Complexité Complexité, notation de landau, algorithmes de recherche et de tri algorithmes de tri tris quadratiques, tri fusion, complexite diviser pour regner methode diviser pour regner, exponentiation rapide, tri fusion rotation quart de tour images matricielles, rotation, methode diviser pour regner algorithmes avancés algorithme d’optimisation, glouton, dynamique algorithme de Boyer Moore algorithme de Boyer Moore de recherche d’un motif dans une sequence calculer sur un algorithme calculabilite, decision, preuves
    • Paradigmes des langages Impératif Fonctionnel on ne trouve ni affectation (ou assignation), ni séquence (succession inconditionnelle de deux instructions). Récursif Objet langages mathematiques langages mathematique, chiffres, operateurs, logique recursivité cours recursivite programmation orientée objet cours POO, classe, instanciation, accesseur getter et mutateur setter
    • types abstraits type abstrait, liste chainee, tableau statique Pile pile, structures lineaires, expression correctement parenthesee Files et Listes autres structures lineaires, File, listes chainees graphes graphes, morphologie, implementation algorithmes de parcours d’un graphe parcours en profondeur, en largeur arbres arbres, binaires, implementations
    • fichiers gestion des fichiers par le systeme d’exploitation systeme d’exploitation processus, ordonnancement, interblocage graphes et internet Modéliser le réseau internet, graphes, équipement, adresses IP, tables de routage protocoles de routage routage statique et dynamique, ospf etat de liens, rip vecteur de distance chiffrement symetrique securisation des communications, chiffrement symetrique, code cesar, analyse frequentielle chiffrement asymetrique chiffrement asymetrique, RSA, HTTPS TP table de routage TP Filius simulation d’un reseau, table de routage
    • bases de donnees relationnelles structuration des donnees, cles primaires et etrangeres, schema d’une relation langage SQL cours langage sql TP prenoms sql application du cours sql, base de donnees des prenoms TP romans sql TP avec SGBD sqlitebrowser, livres, bibliotheque SQL - python TP page web interactive avec base de donnees, python sqlite, module Flask TP base de libreoffice TP utilisant le SGBD BASE de libreoffice, films
    • Les exercices présentés ici peuvent différer de leur énoncé d’origine. tableaux et bases en python listes et tuple, dictionnaires, tableaux, bases en python donnees structurees 1 structures lineaires PILES, parenthesage, POO donnees structurees 2 arbres, parcours, tri par insertion et tri fusion, récursivité Files structures lineaires Files algorithmique récursivité, chaine de caractères, random.choice algo et recursivite recherche dichotomique, complexité, récursivité architecture architecture, binaire, ordonnancement, commandes Unix BDD SQL bases de donnees, sql securite chiffrement symetrique, asymetrique, RSA, https, codage des caracteres, XOR, chiffrement, securite des transmissions reseaux reseaux, adresses IP, masque de sous-reseau, blockchain POO programmation orientee objet Graphes graphes, parcours, itineraires, récursivité Arbres arbre, parcours
    • Exercices classiques pour se préparer à l’epreuve. algos essentiels bases en python, listes, dictionnaires, recherche, min, max repondeur telephonique generer un dictionnaire de contacts et mesurer les performances de recherche
    • Recherche Exoplanetes ASTEP, exoplanetes, sequences Courbes de transit exploration des dossiers et fichier avec le module os, analyse courbe de transit, moyenne glissante dataframes calcul des caracteristique de l’exoplanete projet Dominos interface graphique TKinter, POO, dominos Pygame Snake interface IHM avec pygame, liste chainee Jeu du Morpion Projets utilisant les tableaux python version TNSI arts numeriques turtle, arts graphiques numeriques ABR applications arbre binaire de recherche, inventaire et rangement
    • GO: presentation Thèmes et articles Préparer l’entretien Le Grand Oral Découvrir l’épreuve du Grand Oral Présentation de l’épreuve et Foire aux Questions: http://quandjepasselebac.education.fr/faq-grand-oral/ La durée de l’epreuve est de 20 minutes, partagés en: 10 min d’exposé oral. 10 min d’entretien Construire sa question en rapport avec la spécialité NSI L’élève doit proposer 2 questions au jury, qui choisira celle qui sera presentée par le candidat. Ces questions portent obligatoirement sur les 2 spécialités de terminale, en combinaison. (une spécialité par question, ou 2 specialités représentées sur l’une des 2 questions, et une ou deux spé pour la 2e question).

    Sous-sections de NSI term

    algorithmes

    Sous-sections de algorithmes

    Complexité

    Travaux pratiques:

    • étude comparée des algorithmes de recherche:
      • version 1 utilisant time.time() (chronométrage) et numpy (courbe des fonctions): Lien
      • version 2 utilisant %%timer: Lien
    • étude comparée des algorithmes de tri: Lien
    • algorithmes de recherche des nombres premiers: Lien Feuille d’exercices en version pdf

    Cout spatial et temporel

    L’execution d’un algorithme nécessite l’utilisation des ressources de l’ordinateur:

    • complexité en temps : temps de calcul pour executer les operations. On supposera qu’il correspond au nombre d’opérations effectuées par le programme.
    • complexité spatiale : occupation de la mémoire pour contenir et manipuler le programme et ses données. Peut s’exprimer en nombre de mots mémoires.

    Complexité temporelle

    C’est une estimation du temps d’execution d’un programme, independamment de la machine. En pratique, cela correspond au nombre d’opérations effectuées par le programme.

    Pour evaluer la complexité temporelle, on peut mettre en evidence plusieurs opérations fondamentales. Le temps d’éxecution d’un algorithme resolvant ce genre de problème est toujours proportionnel au nombre de ces opérations :

    Pour le tri, par exemple : ces opérations fondamentales sont le nombre de comparaisons entre 2 élements et le nombre de deplacements de ces élements.

    Complexité spatiale

    Il faut souvent définir une mesure sur les données qui réflète la quantité d’informations contenues. Exemple : nombre de chiffre des nombres, le nombre d’éléments manipulés, dimension d’une matrice, nombre de noeuds d’un graphe… C’est la complexité spatiale.

    Evaluer la complexité (temporelle)

    Principe

    Étant donnée que la durée d’exécution d’un algorithme peut varier entre différentes entrées, on considère généralement la complexité temporelle dans le cas le plus défavorable, qui correspond à la durée maximale.

    Par exemple, avec l’algorithme de recherche séquentielle, ce temps correspondrait à trouver l’élément dans la liste comme s’il occupait la dernière position (voir plus loin).

    La complexité d’un algorithme sera alors (sauf mention contraire) exprimée sous la forme : O(g(n)). Ce qui correspond à la complexité asymptotique, dans le pire des cas (sa borne supérieure).

    En pratique, on ne comptera que les opérations estimées importantes : T(n). Les opérations qui ne changent pas selon les nuances du langage utilisées lors de la programmation (boucle while et boucle for…) mais qui changent selon le problème. Ce nombre d’opérations sera appelé T(n).

    On en déduira alors la classe de complexité asymtotique g(n) (voir tableau plus loin). Puis la complexité dans le pire des cas O(g(n)).

    Instructions élémentaires T(n)

    T(n) est la somme des unités de mesure, comptée pour chaque instruction.

    Une unité de mesure peut-être :

    • une addition
    • une soustraction
    • une multiplication, une division, Mod (%), Div
    • une opération arithmétique simple (sans appel de fonctions)
    • une comparaison, les opérations booléennes (et,ou,non)
    • une affectation
    • des opérations de lectures et écritures simples

    Exemple:

    Le programme multiplie devra écrire dans une liste la série de nombres correspondants à la table de multiplication de b. Pour les n premiers termes.

    Exemple avec une boucle bornée

    Supposons pour cet exemple que seules les opérations multiplier et additionner sont significatives. On compte le nombre de ces opérations pour les fonctions suivantes.

    def multiplie1(b,n):
      L= []
      for i in range(n):
        L.append(b*i)
      return L

    La première étape est d’identifier les séquences dans un algorithme. Si votre algorithme est composé des séquences :

      I1
      I2
      I3
      ...
    $$T(n) = T(I_1) + T(I_2) + T(I_3) + ...$$

    il y a 3 séquences I1, I2, I3 :

    # sequence I1
      L=[]
    # sequence I2
      for i in range(n):
        y = b * i
        L.append(y)
    # sequence I3
      return L

    La séquence I1 contient une seule instruction élémentaires (affectation = ). I3 ne contient pas d’instruction significative. I2 est une séquence comprenant 3 operations :

    • opération * pour b * i
    • affectation =
    • affectation append

    De ce fait :

    $$T(n) = 1 + 3\times n$$

    Boucle non bornée : variant de boucle

    Le principe est le même pour une boucle non bornée (non conditionnelle), mais il est moins facile de déterminer le nombre d’itérations de la boucle. Pour ce faire, la méthode classique est d’étudier plus en détails le variant de boucle. On détermine :

    • La valeur initiale du variant de boucle ;
    • Sa valeur finale ;
    • De combien il diminue strictement à chaque étape.

    On peut alors en déduire le nombre d’itérations de la boucle.

    Exemple : Avec multiplie2, le variant de boucle, c’est i. Sa valeur passe de n - 1 à 0. La boucle est executée n fois. Et le nombre d’instructions significatives dans la boucle est de 2 :

    $$T(n) = 2 \times n$$
    def multiplie2(b,n)
      i = 0
      while i < n : 
        y = b * i
        L.append(y)
        i = i + 1
      return L

    La fonction semble réaliser plus d’opérations que la première implémentation, d’où la petite différence pour la valeur de T(n) avec les deux fonctions precedentes.

    Ici, on peut évaluer T(n) = 2 + 5n

    Cette différence ne vient que d’une différence des details d’implémentation du même algorithme, et ne doit pas être considérée pour le calcul de la complexité.

    g(n): Limite asymptotique en n

    Lorsque l’on étudie la complexité d’une fonction ou d’un algorithme, on s’intéressera souvent à son comportement pour de grandes taille du paramètre d’entrée n. Car si pour des données de petite dimension, la qualité de l’algorithme importe peu, pour de grandes tailles de données, la différence de performance peut être énorme. On dit que l’on observe le comportement asymtotique de T(n), c’est à dire pour n qui tend vers de grandes valeurs.

    On aura besoin de définir plusieurs niveaux de description:

    • T(n), qui représente le nombre d’opérations significatives réalisées par cette fonction : par exemple $T(n) = 2\times n$.
    • g(n) est une approximation de T(n). Ici, $g(n) = n$
    • La complexité O(g(n)) détermine la classe de complexité de la fonction, dans le pire des cas. Dans le cas de nos 3 fonctions multiplie, ce sera à chaque fois O(n). La complexité est linéaire.

    La petite différence d’implementation de ces 2 fonctions est visible en calculant T(n), mais pas en déterminant g(n) ni O(g(n)).

    Règles pour estimer la complexité O(g(n))

    Règles

    • Poser n = “la taille des paramètres”.
    • Enoncer les instructions que vous compterez comme significatives
    • définir des blocs d’instructions dans le script
    • Ne compter que les instructions essentielles, à partir d’une unité de mesure: noter la somme des instructions élémentaires T(n).
    • Pour chacune des boucles du programme, repérer le variant de boucle et calculer le nombre d’itérations : combien de fois on passe dans la boucle.
    • Si T(n) contient une somme de termes, conserver uniquement le plus divergent.
    • Prendre pour g(n) une fonction approchée de T(n). Ne pas considérer les multiplicateurs C : si T(n) = C.f(n), alors g(n) = f(n). Par exemple, si $T(n) = 3\times n$, prendre g(n) = n
    • Sauf précision contraire, la complexité demandée est la complexité au pire en temps.

    Remarques :

    • C’est souvent le genre du problème qui va décider de ce qui constitue une instruction significative: Pour un algorithme de tri, ce sera : le nombre de comparaison de deux éléments, et le déplacement de deux éléments.
    • En faisant varier le degré de précision dans la mesure du nombre d’instruction élémentaires, on fait varier aussi le degré d’abstraction, c’est à dire l’independance par rapport à l’implementation de cet algorithme.

    Principales classes de la complexité

    Ces complexités sont classées par temps d’execution croissant de l’agorithme correspondant.

    complexité classe
    Θ(1) temps constant
    Θ(log n) logarithmique en base 2 : log2(n)
    Θ(n) linéaire
    Θ(n*log n) quasi linéaire
    Θ($n^2$) quadratique, polynômial
    Θ($n^3$) cubique, polynômial
    Θ($2^n$) exponentiel (problème très difficiles)

    On peut observer l’evolution des courbes t(n) en fonction de n (nombre de données). t(n) sera le temps linéaire:

    1 et log(n) : log(n) a une croissance faible

    1 et log(n) : log(n) a une croissance faible

    n*log(n) et n ont une croissance comparable

    n*log(n) et n ont une croissance comparable

    n**2

    n**2

    n**3

    n**3

    2**n

    2**n

    Les problèmes à résoudre ont le plus souvent un nombre n de données bien supérieur à 15, comme présenté sur le dernier graphique. Les effets de convergence sont donc encore plus marqués.

    Approfondir la notion de complexité : voir annexe1

    Exemple: la recherche dans une liste triée

    Enoncé du problème2

    Supposons que le problème posé soit de trouver un nom X dans un annuaire téléphonique qui consiste en une liste triée alphabétiquement. On peut s’y prendre de plusieurs façons différentes. En voici deux :

    1. Recherche linéaire : parcourir les pages dans l’ordre (alphabétique) jusqu’à trouver le nom X cherché. C’est l’algorithme de lecture exhaustif, aussi appelé algorithme de recherche linéaire.
    2. Recherche dichotomique : ouvrir l’annuaire au milieu, si le nom qui s’y trouve est plus loin alphabétiquement que le nom cherché, regarder avant, sinon, regarder après. Refaire l’opération qui consiste à couper les demi-annuaires (puis les quarts d’annuaires, puis les huitièmes d’annuaires, etc.) jusqu’à trouver le nom cherché.

    Algorithme de lecture exhaustif (recherche linéaire)

    Cet algorithme pourrait fonctionner même si les éléments (mots, cartes, valeurs…) sont rangés dans le désordre : il s’agit de parcourir tous les mots, du premier au dernier, jusqu’à tomber sur le mot recherché dans cet liste ou annuaire.

    Illustration avec un jeu de cartes non trié: Cherchons la dame de coeur dans la main d’un joueur.

    main du joueur

    main du joueur

    On suppose que la seule manière de parcourir le jeu du joueur est de retourner les cartes une à une. On s’arrête si on trouve la carte. Ou bien si on arrive à la fin sans avoir trouvé la bonne carte.

    La fonction suivante réalise une recherche linéaire de la valeur X sur une liste L de valeurs numériques. Pour la recherche d’une carte dans un jeu de cartes, ou d’un nom X dans un dictionnaire, il faudra adpater légèrement le script, mais la structure est la même.

    def recherche(X,L):
        """
        recherche une valeur dans une liste et renvoie l'indice si la valeur est trouvée, -1 sinon
        Params :
        -------------------
        X : int, valeur à trouver
        L : list, une liste de valeurs entieres, dans un ordre quelconque.
        Sortie : 
        ------
        j : int, indice de la position de la valeur dans la liste
        Principe :
        --------
        on parcourt la liste avec une boucle non bornée, tant que X n'est pas trouvé dans la liste
        on augmente la valeur de j à chaque nouvelle itération
        """
        j = 0
        n = len(L)
        while j<n and X!=L[j]:
            j += 1
        if j==n : return -1
        return j

    Pour evaluer la complexité de cette fonction, on suivra la méthode suivante:

    evaluer la taille des paramètres n

    Pour chacune de ces méthodes il existe un pire des cas et un meilleur des cas.

    • Dans le meilleur des cas, le nom X est trouvé dès l’ouverture de l’annuaire: il n’y aura alors qu’une seule étape.
    • Supposons que l’annuaire contienne N = 30 000 noms, si le mot recherché est le dernier du dictionnaire, le pire cas, cela demandera 30 000 étapes. La complexité est proportionnelle au nombre n. On la note O(n), ça veut dire que dans le pire des cas, le temps de calcul est de l’ordre de grandeur de n.

    faire le détail des opérations réalisées et calculer T(n)

    L’algorithme est constitué de 3 blocs d’instruction :

    # bloc I1
    j = 0
    n = len(L)
    # bloc I2
    while j<n and X!=L[j]:
      j += 1
    # bloc I3
    if j==n : return -1
    return j

    Les éléments significatifs pour analyser le nombre d’opérations sont :

    • le nombre d’itérations
    • le nombre d’opérations par itération

    I1 contient 2 instructions.

    I3 contient 2 instructions (une comparaison et une instruction return)

    Pour le bloc I2 : La variant de boucle, c’est n-j qui doit être >0 pour que la boucle continue.

    Si la condition X!=L[j] n’est jamais realisée, cette boucle est alors executée n fois, avec j qui varie de 0 à n-1.

    L’instruction j+=1 peut compter pour une instruction

    Chacune des conditions d’arrêt j<n et X!=L[j] peuvent être considérées comme significatives. Il y aura alors 3 instructions par itération.

    On aura, dans ce que l’on appelle le PIRE des cas (l’élément n’est pas trouvé): $T_2 (n) = 3\times n$

    On fait alors la somme des 3 termes : $T(n) = T_1 (n) + T_2 (n) + T_3 (n)$

    $$T(n) = 2 + 3\times n + 2$$

    Calcul de la complexité

    • Complexité dans le meilleur et le pire des cas: Le nombre d’opérations T(n) se situe entre Min(n) et Max(n)

      • Min(n) = 7 : meilleur des cas (l’élément cherché occupe la premiere position dans la liste)
      • et Max(n) = n : pire des cas (l’élément cherché n’est pas dans la liste)

    En notation de Landau, on écrit que la complexité (dans le pire des cas) est: O(n)

    Algorithme de recherche dichotomique

    Programme python itératif

    Principe

    L’algorithme de recherche dichotomique a été traité en classe de math pour rechercher la position sur l’axe des x qui donne une image nulle par la fonction f : Lien vers l’activité de Y Monka sur maths-et-tiques.fr

    L’idée est de réduire l’intervale des abscisses de moitié à chaque itération, jusqu’à ce que l’encadrement [a,b] de la valeur x soit inférieur à l’intervale de confiance voulu (valeur ε) : jusqu’à ce que : $b-a < \epsilon$

    On va adapter le raisonnement réalisé avec la recherche du zero de la manière suivante :

    Soit une liste L d’objets triés dans l’ordre croissant (une liste de mots, ou de cartes à jouer…), et un objet X à trouver dans cette liste : On recherche la position (l’indice) de X dans la liste L en procédant par dichotomie si :

    • On part d’un intervale [a,b] sur les indices de la liste.
    • On calcule le milieu (ou du moins la valeur proche) m = (b-a) // 2
    • si X se trouve dans la partie inférieur, c’est à dire si X < L[m] : on prend l’intervale [a,m]
    • sinon on prend l’intervale [m,b]

    A chaque itération, l’intervale est réduit de moitié. Le programme s’arrête lorsque l’intervale ne contient qu’un seul indice (a et b son égaux).

    Illustration avec un jeu de cartes trié : rechercher la Dame de coeur

    recherche dans un jeu de cartes triées

    recherche dans un jeu de cartes triées

    Le script python complet

    def rechDico(L, X):
        gauche = 0
        droite = len(L) 
        trouve = False
        while gauche <= droite and not trouve:
            # On se place au milieu de la liste
            milieu = (gauche + droite) // 2 
            # il, s'agit d'une division entière
            if L[milieu] == X:
              #print(élément, "trouvé à l'indice:", milieu , liste[milieu]) 
              trouve = True
            # on arrête la boucle
            elif L[milieu] < X: 
              gauche = milieu + 1
            else:
                droite = milieu - 1
                #print(élément, "non trouvé")
        if not trouve : 
            return -1 
        return milieu

    Complexité

    • La dimension des données sera prise comme egale à len(L). Appelons cette valeur n.
    • Le variant de boucle, c’est $droite-gauche$, qui vaut au départ n, et 0 à la fin de la boucle, si la valeur n’a pas été trouvée (pire des cas).
    • Les instructions essentielles de la boucle, ce seront les comparaisons
      • L[milieu] == X
      • et L[milieu] > X

    Pour simplifier le raisonnement, disons qu’il n’y a qu’une seule instruction essentielle par itération.

    A la fin de la première itération, le variant de boucle vaut n/2.

    On peut alors exprimer le nombre d’opérations T(n) pour cet algorithme comme égal à :

    $$T(n) = 1 + T(n/2)$$

    On aura, avec le même raisonnement,

    $$T(n/2) = 1 + T(n/4)$$

    Et ainsi de suite jusqu’à ce que n//2, et le variant de boucle, soient egaux à 0.

    On a alors $T(n) = 1 + 1 + ...$ un nombre de fois égal au nombre de divisions par 2 de n, nécessaires pour amener n à 0. Cette valeur est egale à $log_2(n)$.

    La complexité est alors O(log(n)).

    Programme python recursif

    def rechDichoAux(tabTrie,x,debut,fin):
        if debut == fin :
            if tabTrie[debut] == x:
                return debut
            else:
                return -1
        else:
            milieu= (fin-debut)//2
            if x <= tabTrie[debut+milieu]:
                return rechDichoAux(tabTrie,x,debut,debut+milieu)
            else : return rechDichoAux(tabTrie,x,debut+milieu+1,fin)
    
    def rechDich(tab,x):
        n=len(tab)
        return rechDichoAux(tab,x,0,n-1)

    On peut alors tester le programme (jupyter notebook):

    tab = [23, 34, 45, 56, 67, 104]
    rechDich(tab,67)
    4

    Complexité

    Le second algorithme demandera dans le pire des cas de séparer en deux l’annuaire, puis de séparer à nouveau cette sous-partie en deux, ainsi de suite jusqu’à n’avoir qu’un seul nom. Le nombre d’étapes nécessaire sera le nombre entier qui est immédiatement plus grand que $log_2 (N)$, qui vaut 15 lorsque N=30 000.

    La complexité est alors O(log2(N))

    Le tri par insertion

    Principe

    On recherche le plus petit élément et on le met à sa place (en l’échangeant avec le premier). On recherche le second plus petit et on le met à sa place, etc.

    def tri_selection(L):  
      n = len(L)
      for i in range(0, n - 1):
        #recherche le plus petit élément de i à la fin
        mini = i
        for j in range(i + 1, n):
          if L[j] < L[mini]:
            mini = j
        #échanger les cases i et mini
        tmp = L[i]
        L[i] = L[mini]
        L[mini] = tmp 

    Description: boucle externe et boucle interne

    Dans la boucle externe: On pose i comme position droite du tableau déjà trié. La valeur L[i] sera permutée avec la plus petite valeur trouvée dans la partie droite du tableau, celle non triée.

    Dans la boucle interne. Le variant j représente l’index dans la partie droite, non triée du tableau. Le tableau non trié commençant au rang i+1, j va varier de i+1 à len(L). On recherche le rang de la plus petite valeur, rang que l’on appelle mini. La plus petite valeur est alors L[mini].

    Permutations

    Une fois identifié la valeur mini: On permute L[i] avec L[mini]. Pour permuter 2 valeurs, il faut utiliser une 3e variable, appelée tmp:

        tmp = L[i]
        L[i] = L[mini]
        L[mini] = tmp

    Complexité du tri par sélection

    La boucle interne est executée n-1 fois, vu qu’elle est appelée à chaque itération de la boucle externe: for i in range(0, n - 1).

    Dans la boucle interne, supposons que les opérations significatives sont celles de comparaison: if L[j] < L[mini]. On compte alors 1 seule opération à chaque itération de la boucle interne.

    Pour la première itération de la boucle externe, i=0. Donc, pour la boucle interne, la boucle for s’écrit for j in range(1, n). Il y a alors n-1 itérations.

    Pour la deuxième itération de la boucle externe, i=1. Pour la boucle interne, on a alors for j in range(2, n). Il y a alors n-2 itérations.

    Le nombre d’itérations de la boucle interne vaut n-1. On a alors n-1 termes pour le calcul de T(n), dont les valeurs iront de n-1 à 1:

    $$T(n) = (n-1) + (n-2) + ... + 1$$

    Il s’agit d’une somme de n-1 termes d’une suite arithmétique, tels que $u_0 = 1$ et $u_{n-1} = n-1$

    La complexité, exprimée en notation de Landau est donc $O(n^2)$. La classe de complexité est donc quadratique.

    L'essentiel à retenir

    Complexité temporelle

    Definition

    C’est une estimation du temps d’execution d’un programme, independamment de la machine, et des details d'implementation. En pratique, cela correspond au nombre d’opérations effectuées par le programme. Ce nombre d’opérations dépendant de la taille n des données en entrée, on évalue d'abord une fonction T(n).

    Ensuite, on fera une simplification de T(n) que l'on note g(n)
    g(n) peut être égal à 1, log(n), n, n.log(n), n2, ... 2n

    Notation de Landau

    Le plus souvent, il s’agira d’estimer la complexité dans le pire des cas, exprimée sous la forme : O(g(n)).

    Pour l’exemple sur la fonction multiplie, la complexité est notée O(n) en notation de Landau.

    Lorsqu’il est possible de déterminer une valeur exacte de la complexité, la notation devient Θ(g).

    Règles pour estimer la complexité O(g(n))

    • Poser n = “la taille des paramètres”.
    • Ne compter que les instructions essentielles, à partir d'une unité de mesure: noter la somme T(n)
    • Pour chacune des boucles du programme, repérer le variant de boucle et calculer le nombre d’itérations : combien de fois on passe dans la boucle.
    • Si T(n) contient une somme de termes, conserver uniquement le plus divergent.
    • Prendre pour g(n) une fonction approchée de T(n). Ne pas considérer les multiplicateurs C : si T(n) = C.f(n), alors g(n) = f(n). Par exemple, si T(n) = 3*n, prendre g(n) = n.
    • Sauf précision contraire, la complexité demandée est la complexité au pire en temps.

    Principales classes de complexité

    Ces complexités sont classées par temps d’execution croissant de l’agorithme correspondant.

    complexité classe
    Θ(1) temps constant
    Θ(log n) logarithmique en base 2 : log2(n)
    Θ(n) linéaire
    Θ(n*log n) quasi linéaire
    Θ(n2) quadratique, polynômial
    Θ(n3) cubique, polynômial
    Θ(2n) exponentiel (problème très difficiles)

    Exercices

    Feuille d’exercices en version pdf

    Exercice 1

    Déterminer la complexité des fonctions suivantes en terme de nombre d’additions et de soustractions. On donnera d’abord la valeur exacte T(n) puis l’ordre de grandeur O(n).

    def truc(n): 
      res=0
      for i in range(0,n): 
        res +=1
      return res
    
    
    def machin(n):
      res=truc(n)
      for i in range(0,n):
        res -=1 
      return res
    
    def chose(n):
      res=0
      for i in range(n):
        res+=machin(i) 
      return res
    
    def fonctionFinale(n):
      res =[]
      for i in range(0,n):
        res.append(chose(n)) 
      return res

    Exercice 2: TP sur la recherche dans une liste de mots

    On donne deux algorithmes de recherche dans une liste de mots.

    Vous aller comparer l’efficacité de la recherche de ces 2 algorithmes lorsque l’on cherche un mot dans une liste (dictionnaire français).

    L’énonce du TP se trouve ici: version 1 et ici: version 2

    Exercice 3:3

    Dans un groupe de n individus , une star est quelqu’un que tout le monde connait mais qui ne connait personne. Pour trouver une star, s’il en existe une, vous ne pouvez poser aux individus de ce groupe que des questions du type : « connaissez-vous x ? ».

    1. Combien de stars au maximum peut-il exister dans un groupe ?
    2. Donner un algorithme trouvant une star s’il en existe une (ou déterminant qu’il n’en existe pas) et de coût linéaire (en prenant comme mesure de la complexité le nombre de questions posées).

    Exercice 4 :

    Le problème est de déterminer à partir de quel étage d’un immeuble sauter par une fenêtre est fatal. Vous êtes dans un immeuble à n étages (numérotés de 1 à n) et vous disposez de k étudiants. Il n’y a qu’une opération possible pour tester si la hauteur d’un étage est fatale : faire sauter un étudiant par la fenêtre. S’il survit, vous pouvez le réutiliser ensuite, sinon vous ne pouvez plus.

    Vous devez proposer un algorithme pour trouver la hauteur à partir de laquelle un saut est fatal en faisant le minimum de sauts.

    • Donnée: on suppose k > n

    Compléments sur le Calcul de T(n)

    Pour calculer la complexité d’une boucle bornée. Soit (deb,fin) ∈ Z2, considérons une boucle de type for i in range(deb, fin):

    Alors la complexité de cette boucle est :

    $$\sum_{i=deb}^{fin-1} C_i$$

    où C représente la complexité de l’itération4 i

    Boucles

    Pour faire un calcul exact du nombre d’opération, il faut compter:

    • l’initialisation de la variable utilisée comme variant de boucle
    • l’incrémentation de cette variable
    • la comparaison avec la valeur d’arrêt

    Parfois, le calcul de la complexité ne doit pas dépendre du type de boucle, et donc du type d’algorithme. Ces opérations ne sont alors pas comptées.

    Instructions conditionnelles

    conditionnel simple

    Si Condition Alors :
      I ;

    Dans le cas défavorable, où l’expression conditionnelle revoie True, le bloc d’instruction I est exécuté. On a alors :

    $$T (n) = Tcondition (n) + T_I (n)$$
    • T(n) représente le nombre total d’instructions
    • Tcondition(n) représente le nombre d’instructions nécessaire pour tester la condition (qui peut-être 1 s’il s’agit par exemple d’une simple comparaison entre deux expressions arithmétiques).
    • TI représente le nombre d’instructions dans I.

    Conditionnel avec alternative

    Si Condition Alors :
      I1 ;
    Sinon :
      I2;

    Dans le cas défavorable, on comptera :

    $$T (n) = Tcondition (n) + max (T_{I_1} (n), T_{I_2} (n))$$

    Compléments sur la notations de Landau

    • Notation O : la borne superieure : g domine f on note f = O(g) s’il existe un nombre réel positif a et un rang n de fn tels que f(n) ≤ a.g(n) :
    $$\exists c \in \mathbb{R}^+, tels \quad que\quad \forall n_o \in \mathbb{N}, |f(n_o)|\leq c.|g(n)| $$

    En pratique, la recherche de la complexité revient à déterminer cette fonction (ou cette suite) g. On note la complexité O(g). On ignore l’eventuel coefficient multiplicateur c et on ne conserve que le terme le plus divergent dans le cas où g contienne plusieurs termes. T(n) = O(g(n)).

    Pour l’exemple précédent, la complexité est notée O(n) en notation de Landau.

    • Notation Θ : Lorsqu’il est possible de déterminer une valeur exacte de la complexité, la notation devient Θ(g).

    • Complexité en moyenne Θ(g(n)):

    $$Moy_A(n) = \sum_{d \in D_n} p(d).coût_A(d)$$

    où p(d) est la probabilité que l’on ait la donnée d en entrée de l’algorithme.

    et coût_A(d) représente la complexité en temps de l’algorithme A sur la donnée d.

    Liens


    1. wikipedia : analyse de la complexité : wikipedia.org/wiki/Analyse_de_la_complexité_des_algorithmes ↩︎

    2. recherche linéaire et dichotomique : document eduscol 1ere NSI ↩︎

    3. Exercice issu de ENS Lyon, Marc De Visme & Laureline Pinault: Algorithmique, exos corrigés ↩︎

    4. itération : succession d’états dans un processus ↩︎

    algorithmes de tri

    Ce cours comporte plusieurs parties

    Algorithmes de tri

    Les activités de tri sont très fréquents en informatique. Dans un projet informatique, on préfère qu’un programme passer du temps à trier les données plutôt qu’à les rechercher.

    On presente dans ce chapitre TROIS algorithmes de tri. Mais il en existe de très nombreux, dont l’efficacité diffère grandement. Voici un aperçu de la durée comparée de quelques algorithmes de tri, selon la nature de la liste à trier:

    comparatif de performance de quelques algorithmes de tri

    comparatif de performance de quelques algorithmes de tri

    Nombre d’éléments « n » Nombre d’opérations pour un tri en « O(n²) » Durée pour un tri en « O(n²) »
    10 100 100 ns
    100 10 000 10 us
    1 000 1 000 000 1 ms
    10 000 100 000 000 100 ms
    100 000 10 000 000 000 10 s
    1 000 000 1 000 000 000 000 16 min 40 s
    10 000 000 100 000 000 000 000 27 heures
    100 000 000 10 000 000 000 000 000 115 jours
    1 000 000 000 1 000 000 000 000 000 000 31 ans
    8 000 000 000 (population mondiale) 64 000 000 000 000 000 000 1984 ans

    Pour un algorithme de complexité O(n.log(n)), la durée de tri d’un ensemble de 8 000 000 000 valeurs prendrait 4 min!

    tableau issu de podcastscience.fm

    Le tri par insertion

    Principe

    Pour cet algorithme, trier, c’est déplacer chaque élément, en suivant un ordre de la gauche vers la droite, et l’insérer dans la partie déjà triée (à sa gauche), à sa place. C’est un peu la manière avec laquelle on range les cartes à jouer au debut d’une partie:

    main d'une partie de cartes

    main d'une partie de cartes

    • Hypothèse : l’élément non rangé est le j. Tous les autres éléments sont rangés jusqu’à j.
    • Il faut d’abord conserver sa valeur à l’aide d’une variable temp
    • On décale tous les éléments i, depuis le rang j jusqu’à l’élément dont la valeur est inférieure à celle de j (et donc de temp), en redescendant.
    animation sur le tri par insertion

    animation sur le tri par insertion

    Sur l’animation: on devine le script de la boucle interne:

    1. Dans la partie non triée, selectionner la premiere carte. La reserver en laissant la place libre
    2. faire glisser les cartes de la partie gauche (triée) vers la droite pour laiser la place libre à la carte à insérer (correspond à un copier-coller des cartes i-1 => i)
    3. insérer la carte réservée à sa place.
    def tri_insertion(L):
        for j in range(1,len(L)):
            temp = L[j]
            i = j
            while i>0 and L[i-1]>temp:
                L[i]=L[i-1]
                i-=1
            L[i]=temp

    Preuve de correction

    Montrons qu’à la fin d’un tour de boucle, les valeurs de la liste sont triées jusqu’au rang j inclus:

    • au début, j vaut 0. Il ne se passe rien.
    • puis j vaut 1. temp vaut L[1]. Dans la boucle secondaire (while), à la ligne 5, si L[0] > temp, alors L[1] = L[0] puis L[0] = temp. La liste est alors triée jusqu’à j = 1 inclus.
    • supposons qu’à la fin du tour j-1, les valeurs sont triées jusqu’à j-1 inclus. Il faut alors montrer que, lors du tour j, la valeur temp (qui vaut L[j]) sera insérée au bon endroit.

    Pour aider le raisonnement, on utlisera le tableau exemple suivant:

    liste triée jusqu'au rang j = 3

    liste triée jusqu'au rang j = 3

    Cas n°1: Soit L[j] >= L[0]:

    Après la ligne 4, on entre dans la boucle while. A la fin de cette boucle, avant la ligne 8, on a la configuration milieu pour la liste.

    Alors la boucle n’est plus executée car L[i-1] > temp vaut False, donc, ligne 9: L[i] = temp. La liste est alors dans la configuration fin de boucle sur l’image suivante.

    liste triée jusqu'au rang j = 4 inclus

    liste triée jusqu'au rang j = 4 inclus

    Cas 2: L[j] < L[0]: prendre l’élement au rang j = 5 de la liste précédente.

    On verifie que while quitte pour i = 0 et que la clé temp est bien insérée dans la case 0. La liste est bien triée jusqu’à j = 5 inclus.

    Conclusion: Lorsque la boucle for execute son dernier tour, j designe la dernière case, et on a bien montré que la liste sera bien triée jusqu’à cette case. Donc la liste est entièrement triée.

    Complexité

    Calcul du nombre d’opération

    Supposons que la taille de la liste est n.

    Les opérations significatives sont:

    • l’affectation
    • la comparaison
    • l’une des opérations arithmetiques: +, -, *, /

    La boucle forest executée n fois.

    Dans le pire des cas, où la liste classerait les éléments dans l’ordre décroissant, T(n) sera alors:

    $$T_1(n) = n \times 2~(lignes~3~et~4)+ n~(ligne~8)$$

    $$T_2(n) = [2~(ligne~5) + 2~(ligne~6)+2~(ligne~7)]\times[1+2+ ... +(n-1)]$$

    $$T(n) = T_1 + T_2$$

    Soit

    $$T(n) = 3n + 6\times \tfrac{n\times(n-1)}{2}$$$$T(n) = 3n^2$$

    La complexité est donc $O(n^2)$. (coût quadratique). Et si la liste est déjà triée, le nombre d’opérations est quand même T(n) = 5.n (coût linéaire).

    Evaluation rapide de la complexité

    On peut compter le nombre de déplacements / affectations réalisés pour trier les valeurs de la liste, en fonction de la valeur j:

    j nombre d’opérations dans le pire des cas
    1 3
    2 4
    3 5
    4 6
    … …
    n-1 n+1

    La somme de cette série arithmétique est alors $S_n = (n+4)\times(n-1)/2$

    Soit $O(n^2)$ pour la complexité asymptotique.

    Le tri par selection

    Tri par selection du plus petit élement

    Sur un tableau de n éléments (numérotés de 0 à n-1), le principe du tri par sélection est le suivant :

    • rechercher le plus petit élément du tableau, et l’échanger avec l’élément d’indice 0 ;
    • rechercher le second plus petit élément du tableau, et l’échanger avec l’élément d’indice 1 ;
    • continuer de cette façon jusqu’à ce que le tableau soit entièrement trié (jusqu’au rang n-2).
    animation sur le tri par selection

    animation sur le tri par selection

    Sur l’animation: on devine le script de la boucle interne:

    1. On selectionne la premiere carte de la partie non triée
    2. On observe la première carte à sa droite
    3. Si la carte marquée est inférieure à la carte du debut, on marque la nouvelle carte (et on retire la marque de la precedente marquée)
    4. Une fois arrivée au bout de la liste: si la carte marquée est différente de la carte selectionnée (donc inférieure), on permute les 2 cartes.
    def tri_selection(T):
        for j in range(0,len(T)-1) :
            indiceDuMin = j # (1)
            for k in range(j+1,len(T)) : # (2)
                if T[k]< T[indiceDuMin] : 
                    indiceDuMin=k # (3)
            if indiceDuMin != j : # (4)
                T[j],T[indiceDuMin]=T[indiceDuMin],T[j]

    Tri par selection du plus grand élément

    Dans cette variante du tri par selection, la liste est triée depuis le plus grand élément jusqu’au plus petit.

    On modifie pour cela la fonction select: on remplace les instructions ndiceDuMin=debut et T[k]< T[indiceDuMin] afin de rechercher la valeur max et non celle min.

    def tri_selection_plus_grand(T) :
        for j in range(0,len(T)-1) :
            indiceDuMax = j # (1)
            for k in range(j+1,len(T)) : # (2)
                if T[k] > T[indiceDuMax] : 
                    indiceDuMax=k # (3)
            if indiceDuMax != j : # (4)
                T[j],T[indiceDuMax]=T[indiceDuMax],T[j]

    Exemple

    Le tri peut aussi se faire à partir du rang des caractéres dans l’alphabet (lexicographique).

    Soit la liste à trier [‘T’, ‘I’, ‘M’, ‘O’, ‘L’, ‘E’, ‘O’, ‘N’] La liste prend successivement les valeurs:

    j Liste à la fin de select nombre de comparaisons effectuées
    0 [‘T’, ‘I’, ‘M’, ‘O’, ‘L’, ‘E’, ‘O’, ‘N’] 7
    1 [‘T’, ‘O’, ‘M’, ‘I’, ‘L’, ‘E’, ‘O’, ‘N’] 6
    2 [‘T’, ‘O’, ‘O’, ‘I’, ‘L’, ‘E’, ‘M’, ‘N’] 5
    3 [‘T’, ‘O’, ‘O’, ‘N’, ‘L’, ‘E’, ‘M’, ‘I’] 4
    4 [‘T’, ‘O’, ‘O’, ‘N’, ‘M’, ‘E’, ‘L’, ‘I’] 3
    6 [‘T’, ‘O’, ‘O’, ‘N’, ‘M’, ‘L’, ‘E’, ‘I’] 2
    7 [‘T’, ‘O’, ‘O’, ‘N’, ‘M’, ‘L’, ‘I’, ‘E’] 1

    Tri à l’aide d’une clé: voir TP

    Complexité

    On peut compter le nombre de déplacements / affectations réalisés pour trier les valeurs de la liste, en fonction de la valeur i. Pour simplifier, on compte N = le nombre d’opérations d’affectations dans la boucle interne.

    Pour l’exemple ci-dessus, ce nombre T(8) = 2 + 3 +’ 4 + 5 + 6 + 7 = 27

    De manière plus générale: $T(n) = \tfrac{n \times (n-1)}{2}$, ce qui fait une complexité $O(n^2)$

    Le tri fusion

    Principe

    Le tri pas fusion procède en 2 étapes distinctes. Il s’agit d’un algorithme de type récursif. Au cours de la descente, la liste de valeurs non triées est divisée en 2 parties égales (ou presque) à chaque appel recursif. Puis, lors de la remontée, ces listes, triées sont interclassées, comme vu sur l’animation suivante:

    animation sur l'interclassement de 2 listes triées

    animation sur l'interclassement de 2 listes triées

    C’est donc sur la remontée que l’on range les éléments par valeur croissante.

    Sur l’animation: on devine le script de la fonction d’interclassement:

    1. comparer les valeurs des bords gauche de chaque sous liste triée
    2. ajouter le plus petit élément des 2 sous listes dans une troisieme liste
    3. déplacer le bord gauche de la sous liste dont on a selectionné l’élément

    L’algorithme est naturellement décrit de façon récursive.

    • Si le tableau n’a qu’un élément, il est déjà trié.
    • Sinon, séparer le tableau en deux parties à peu près égales.
    • Trier récursivement le sous-tableau de gauche avec ce même algorithme du tri
    • Trier récursivement le sous-tableau de droite avec ce même algorithme du tri
    • Fusionner les deux tableaux triés en un seul tableau trié.
    introduction au tri fusion

    introduction au tri fusion

    def interclassement(L1,L2):
        lN = []
        n1, n2 = len(L1),len(L2)
        i1, i2 = 0,0
        while i1<n1 and i2<n2:
            if L1[i1] <= L2[i2]:
                lN.append(L1[i1])
                i1 += 1
            else:
                lN.append(L2[i2])
                i2 += 1
        return lN + L1[i1:] + L2[i2:]
        
    def tri3(L):
        if len(L) <=1:
            return L
        m = len(L)//2
        gauche = tri3(L[:m])
        droite = tri3(L[m:])
        return interclassement(gauche,droite)

    Le tri fusion est traité en détail au chapitre diviser pour regner

    Suite

    • TP: les algos de tri, tri à partir d’une clé

    • Cours:[diviser pour regner]

    Liens

    diviser pour regner

    Prérequis :

    Diviser pour regner

    C’est une technique informatique qui consiste à :

    1. Diviser : découper un problème initial en sous-problèmes de tailles équivalentes;
    2. Régner : résoudre les sous-problèmes (récursivement ou directement s’ils sont assez petits) ;
    3. Combiner : calculer une solution au problème initial à partir des solutions des sous-problèmes.

    Cette méthode, lorsqu’elle s’applique, fournit un algorithme de complexité plus réduite, et donc plus efficace.

    Definition : Un problème est de type diviser pour regner si sa resolution se ramène à celle de un ou plusieurs problèmes indépendants dont la taille des entrées passe de n à n/2, ou une fraction de n. Ou bien, si la division en plusieurs problèmes permet de réduire la durée necessaire pour sa resolution.

    Exemple introductif : téléphone en chaîne

    Les 15 joueuses d’une équipe de volleyball ont la liste des joueuses de l’équipe avec leur numéro de téléphone. La capitaine reçoit l’information que le prochain match a été déplacé. Il faut prévenir toutes les autres joueuses.

    • Solution 1 : la capitaine se charge d’appeler toutes les autres joueuses. Et si elle passe 5 minutes au téléphone avec chacune d’entre-elles…

    Question à propos de la solution 1 : En combien de temps (noté t1) l’ensemble de l’équipe est informé? En déduire la complexité de cette solution en fonction de n (taille de l’équipe)

    • Solution 2 : Une solution plus efficace et plus confortable pour la capitaine est qu’elle divise la liste de joueuses en deux moitiés. Elle appelle alors la première joueuse de chacune des deux listes obtenues. Elle leur donne l’information de report de match et leur demande à leur tour de faire la même chose : diviser en deux la demi-liste à laquelle elles appartiennent, appeler la première joueuse de chacune des parties et ainsi de suite … jusqu’à ce qu’il n’y ait plus personne à prévenir.
      Représentons l’arbre des appels pour la liste de 15 joueuses numérotées de 1 à 15.
    arbre binaire des appels

    arbre des appels

    Question à propos de la solution 2: Si on suppose qu’un appel téléphonique dure 5 min. En combien de temps (noté t2) l’ensemble de l’équipe est informé ? En déduire la complexité de cette solution en fonction de n (taille de l’équipe)

    Conclusion: La solution 2 illustre bien la méthode Diviser pour regner puisqu’à chaque nouvel appel telephonique, le nombre de joueuses contactées avec le même message va doubler. La durée necessaire pour la resolution du problème initial (téléphoner à toutes les joueuses) est alors réduite de manière significative.

    Exponentiation

    L’exponentiation consiste à trouver une méthode pour calculer x à la puissance n, SANS utiliser l’opérateur puissance. L’idée est de se rappocher de l’algorithme utilisé par le processeur d’un ordinateur, qui n’utilise que les 3 opérateurs de base pour effectuer les calculs (+,-,*).

    Programme itératif $x^n$

    def exp1(n,x) : 
      """
      programme qui donne x^n en sortie
      n : entier
      x : reel
      exp1 : reel
      """
      acc=1
      for i in range(n):
        acc*=x
      return acc
    Complexité
    La boucle for est exécutée n fois. Il y a, à chaque itération, une opération arithmétique qui est réalisée (multiplication par x), et une affectation (le résultat est affecté à acc).
    Il y a donc au total : 2n + 1 opérations.
    La complexité est O(n).

    Programme récursif $x^n$

    def exp2(n,x):
        """
        n : entier
        x : reel
        exp2 : reel
        """
        if n==0 : return 1
        else : return exp2(n-1,x)*x

    On pourrait montrer que la complexité est aussi O(n).

    Exponentiation rapide $x^n$

    application de la méthode diviser pour regner

    Comme de nombreux algorithmes utilisant cette méthode, celui-ci fait des appels recursifs. Mais à la différence du précédent, l’appel recursif se fait avec un paramètre que l’on divise par 2 (le paramètre n). C’est ce qui fait que le nombre d’appels récursifs est plus réduit. On retrouve l’étape 3 évoquée en introduction (la combinaison des sous problèmes) lorsque l’on réalise l’opération : return y*y ou bien return x*y*y.

    def exp3(n,x):
        """
        programme plus efficace que le precedent car
        le nombre d'operations est log2(n)
        """
        if n== 0 : return 1
        else :
            y = exp3(n//2,x)  # on prend la valeur inferieure de n/2
            if n%2==0:
                return y*y
            else : return x*y*y
    Complexité
    Prenons pour exemple n = 8 :
    Dans la phase de descente: exp3(8,x) appelle exp3(4,x) appelle exp3(2,x) qui appelle exp3(1,x) puis exp3(0,x).
    Dans la phase de remontée: Une seule opération est réalisée à chaque appel recursif : y*y
    C'est comme si l'on dupliquait le résultat de chaque multiplication (voir représentation en arbre plus bas)
    • exp3(0,x) retourne 1
    • exp3(1,x) retourne x * 1 * 1
    • exp3(2,x) retourne x * x
    • exp3(4,x) retourne x2 * x2
    • exp3(8,x) retourne x4 * x4
    Le nombre d'opérations est le nombre de divisions par 2 qu'il faut faire pour reduire n à 0. Ce nombre est justement egal à : $$log_2(n)$$

    exponentiation rapide: représentation en arbre

    représentation en arbre

    L’exponentiation rapide peut être utilisée pour des “multiplications” plus compliquées, comme la multiplication de matrices, la composition de fonctions,... Dans ces cas, il ne faut pas oublier de compter le coût de la multiplication dans les calculs, qui n’est pas toujours constant.

    Le Tri Fusion

    Principe

    Le tri fusion est un autre algorithme de tri. Celui-ci présente l’avantage d’utiliser la méthode Diviser pour Regner.

    Les étapes 1 et 2 de la méthode Diviser pour Regner consistent à diviser la liste en 2 sous-listes, de manière recursive, jusqu’à obtenir des listes de 1 élément.

    Le tri fusion est réalisé par la fonction fusion suivante:

    def fusion(L):
        if len(L) <=1:
            return L
        m = len(L)//2
        gauche = fusion(L[:m])
        droite = fusion(L[m:])
        return interclassement(gauche,droite)

    L’étape 3, enfin consiste à interclasser les sous-listes deux à deux.

    def interclassement(L1,L2):
        lN = []
        n1, n2 = len(L1),len(L2)
        i1, i2 = 0,0
        while i1<n1 and i2<n2:
            if L1[i1] <= L2[i2]:
                lN.append(L1[i1])
                i1 += 1
            else:
                lN.append(L2[i2])
                i2 += 1
        return lN + L1[i1:] + L2[i2:]

    La fonction fusion ressemble à celle du parcours récursif d’un arbre dans lequel, pour un noeud contenant une liste L:

    • le fils gauche est la sous-liste de gauche (la première moitié de L)
    • le fils droit est la sous-liste de droite (la deuxième moitié de L)

    Le traitement se faisant APRES les 2 appels recursifs (gauche puis droite), le parcours s’apparente à celui appelé POSTFIXE.

    tri fusion

    parcours de l'arbre pour le tri fusion

    Etude du tri fusion sur la liste L = [1,10,8,4,3,6]

    Question 1: Compléter la séquence avec l’ordre des branches parcourues et les sous-listes à chaque noeud, jusqu’à ce que tout le sous-arbre gauche soit “divisée”.

    La remontée dans la pile d’appels commence lorsque l’on arrive à une sous-liste d’un seul élément pour droite.

    La fonction interclassement prend deux listes en paramètres, L1 et L2, et retourne une seule liste avec les éléments de L1 et L2, mais classés.

    Question 2: Décrire les étapes jusqu’à ce que la liste L soit triée.

    La complexité de la fonction interclassement est O(n), où n est égal à la taille de chaque sous-liste.

    Question 3: Expliquer pourquoi, lors de la fusion, la complexité au rang n est donnée par la formule de recurence:

    $$T(n) = T(\tfrac{n}{2}) + n$$

    Question 4: En déduire la complexité du tri fusion.

    Complexité du tri fusion

    Le tri fusion est un tri qui est optimal du point de vue de la complexité temporelle: il est de l’ordre O(N*log(N)). On ne peut pas trouver un algorithme plus efficace en temps.

    Analyse simplifée: A chaque étape de la remontée, lors de l’interclassement:

    • si l’on compte le nombre d’affectations: Il y a n affectations (n éléments partagés en 2 sous listes, à placer dans une nouvelle liste). Le nombre d’étapes est egal à $log_2(n)$. Ce qui fait un nombre d’opérations proportionnel à $n \times log_2(n)$.
    • Pour le nombre de comparaisons: Ce nombre est inférieur, à chaque étape, au nombre n d’éléments de la liste à trier. Le nombre de comparaisons est donc $< n \times log_2(n)$

    On peut donc considérer que le tri fusion a une complexité asymptotique $n \times log_2(n)$

    Remarque: l’inconvenient majeur de cet algorithme est qu’il demande beaucoup de ressources spatiales, du fait de la construction de nombreuses sous-listes pour réaliser le tri. Ce n’est pas un tri en place, comme on a pu le voir avec les algorithmes essentiels vus en classe de 1ere NSI.

    Liens

    rotation quart de tour

    Télécharger le dossier de travail: TP_rotation_image.zip

    Coder une image numérique

    Qu’est ce qu’une image numériques?

    Rappels de SNT: Une image numérique est constituée de pixels colorés (ou noirs et blanc). Le fichier comportant l’image numérique contient alors une succession de valeurs qui codent la couleur de chaque pixels: lire le cours de SNT, paragraphe codage de l'image

    Librairie PIL

    Pour manipuler les images, nous pouvons utiliser le module PIL de Python. Celui-ci permet de traiter les pixels d’une image, un par un. Souvent, il faudra parcourir l’image pixel par pixel, sur toute la largeur et toute la hauteur. Cela est possible avec deux boucles imbriquées, à condition de connaitre ses dimensions largeur, hauteur:

    from PIL import Image
    imageSource=Image.open("crabePortrait.bmp")
    largeur,hauteur=imageSource.size
    
    for y in range(hauteur): # y varie de 0 à hauteur - 1
        for x in range(largeur): # x varie de 0 à largeur - 1
            # traitement pixel (x,y)

    Les boucles for vont effectuer un parcours:

    • sur y (position en hauteur qui varie de 0 à hauteur-1)
    • sur x (position en largeur qui varie de 0 à largeur-1)

    Le pixel (0,0) est en haut sur le coin gauche.

    imageSource est une instance de la classe Image et possède une methode getpixel((x,y)) qui renvoie la valeur du pixel pour l’argument (x,y). S’utilise de la manière suivante:

    # lecture
    p = imageSource.getpixel((x,y))
    # ecriture
    planPixels.putpixel((x,y),p)

    Manipuler les pixels de l’image

    Nous allons travailler sur l’image suivante: crabePortrait.bmp.

    image de dimension 247 * 330 en format bitmap, RGB 3 octets

    image de dimension 247 * 330 en format bitmap, RGB 3 octets

    Défi n°1: explorer la structure de données

    A vous de jouer: ouvrir le fichier rotation_crabe.py, analyser le script, puis, à l’aide de la fonction copie_image, faire une copie de l’image crabe_portrait.bmp

    Vérifier le contenu des données pour quelques uns des points de l’image: afficher la valeur de p si x < largeur//10 et y < hauteur //10

    Laquelle des structures de données représente le mieux le format des données:

    • [124,90,120]
    • (124,90,120)
    • #7C5A78?

    Rotation d’une image: permutation de pixels

    Défi n°2: Coordonnées pour une rotation droite

    principe de la rotation horaire d'un quart de tour

    principe de la rotation horaire d'un quart de tour

    Répondre aux Questions:

    1. Quelles sont les coordonnées des points A et B avant transformation?
    2. Quelles sont les nouvelles positions des points A’ et B’ après transformation: Pour un pixel situé initialement en (x,y), quelles sont ses coodonnées (x’,y’) après transformation?

    Défi n°3: Rotation droite d’une image

    En vous inspirant de la fonction copie_image, écrire une fonction rotation_droite qui réalise la rotation d’un quart de tour dans le sens horaire, comme sur l’image ci-dessus.

    Permuter les zones d’une image

    On cherche maintenant à effectuer cette transformation, SANS utiliser de nouvelle image planPixels comme précédemment.

    On utilisera l’image suivante (carrée) pour cette méthode: woody.jpg

    image woody.jpg

    image woody.jpg

    Le fichier de travail sera rotation_woody.py

    Défi n°4: permutation de blocs

    la fonction echange_quadrant permet d’echanger les pixels de 2 zones carrées de même dimensions.

    exemple: echange des blocs A et B

    exemple: echange des blocs A et B

    Les zones échangées seront les 4 parties marquées A, B, C et D sur l’image ci-dessous.

    image d'origine

    image d'origine

    Pour effectuer une rotation droite dans l’image, on va effectuer 3 permutations SUCCESSIVES sur les zones ABCD de l’image:

    trois permutations réalisées sur les subdivisions de l'image

    trois permutations réalisées sur les subdivisions de l'image

    1. Pour échanger les zones A et B d’une image, et visualiser le résultat, utiliser la fonction permutation_blocs_A_B.
    2. Ecrire les fonctions permutation_blocs_B_D et permutation_blocs_C_D. Appliquer les transformations pour obtenir une rotation droite des blocs de l’image woody.jpg.

    Rotation par la méthode Diviser pour Régner

    La fonction rotate permet de faire tourner l’image d’un quart de tour par une méthode de type diviser pour régner:

    Tourner l’image d’un quart de tour, c’est permuter les 4 parties d’une image dont on a permuté l’interieur de ses 4 parties…

    Une fois la partie divisée executée (appels recursifs), lorsque les subdivisions de l’image sont constituées d’un seul pixel, les pixels sont déplacés (règne) à l’aide de 3 permutations successives, selon le schéma suivant:

    trois permutations réalisées sur les subdivisions de l'image

    trois permutations réalisées sur les subdivisions de l'image

    Il sont alors recombinés pour reformer l’image, tout en suivant les mêmes permutations, mais avec des blocs de pixels plus gros (fusion).

    Le but est d’obtenir l’image suivante, à l’aide de la fonction quart_tour:

    image finale

    image finale

    Défi n°5: rotation d’une image par la méthode Diviser pour régner

    1. Compléter la fonction rotate pour obtenir une image à l’endroit de woody.
    2. Expliquer pourquoi cette méthode s’apparente à la famille Diviser pour régner. (On pourra s’aider des schémas ci-dessous, et les remettre dans l’ordre pour repondre).
    image a

    image a

    image b

    image b

    image c

    image c

    image d

    image d

    efficacité de la méthode

    Evaluons l’efficacité de cet algorithme

    • Est-il plus rapide ou plus lent que votre premier algorithme?
    • Le nombre d’opérations significatives suit une loi de recurence: $T(n) = 4 \times T(\tfrac{n}{2}) + C \times n^2$ Cela confirme t-il votre reponse à la question pécédente?

    On rappelle que l’intérêt de la méthode est surtout de ne PAS utiliser de nouvelle image planPixels comme précédemment. Il s’agit d’une transformation en place.

    Liens et aides

    • En cas de difficulté, consulter la page et les videos du site: monlyceenumerique.fr, aller à la partie sur la rotation des images.

    algorithmes avancés

    Pré requis

    • Complexité : lien
    • Récursivité : lien

    On verra dans cette page:

    • la programmation dynamique
    • les algorithmes gloutons
    • un exemple d’algorithme avec recherche locale. Pour la résolution d’un problème de TSP (Traveling salesman problem)
    • Les classes de problèmes de decision, P, NP, NP-complet

    Programmation dynamique

    Principe de la méthode

    La programmation dynamique permet de résoudre plus efficacement des problèmes d’optimisation.

    La programmation dynamique consiste à résoudre un problème en le décomposant en sous-problèmes, puis à résoudre les sous-problèmes, des plus petits aux plus grands en stockant les résultats intermédiaires, et en suivant une règle d’optimalité. La solution donnée par un algorithme glouton est optimale, mais n’est pas forcement la solution la plus optimale au problème.

    Cela diffère des algorithmes de type diviser pour régner par le fait que les sous-problèmes considérés ne sont pas nécessairement indépendants. Pour les algorithmes de type diviser pour régner, on partitionne le problème en sous problèmes indépendants, qui seront résolus recursivement. Puis on combine leurs solutions pour résoudre le problème initial. Mais cela peut revenir à résoudre plusieurs fois le même sous-problème, et peut être parfois inefficace.

    Pour la méthode de programmation dynamique, on va se rappeler des sous-problèmes résolus (de leurs solutions), et eviter de les re-calculer.

    Cette méthode a été introduite au début des années 1950 par Richard Bellman.

    Comment s’y prendre pour mémoriser les solutions?

    La méthode demande alors de mémoriser ce résultat intermédiaire dans un dictionnaire ou un tableau afin de le réutiliser au besoin. Sans avoir besoin de les recalculer. La complexité spatiale augmente, mais celle temporelle diminue.

    Cette méthode s’appelle : la mémoïzation.

    Elle va permettre d’eviter la répétition des calculs que l’on voit dans l’exemple suivant, le triangle de Pascal. Sans cette reduction, la compléxité de l’algorithme est exponentielle (voir l’arbre des calculs, présenté plus bas).

    Ce problème de répétitions a été vu avec l’exemple du calcul des termes de la suite de Fibonacci.

    Limites de la méthode diviser pour regner : le triangle de Pascal

    Principe

    En mathématiques, le triangle de Pascal est une présentation des coefficients binomiaux dans un triangle. Il fut nommé ainsi en l’honneur du mathématicien français Blaise Pascal. Il est connu sous l’appellation « triangle de Pascal » en Occident, bien qu’il fût étudié par d’autres mathématiciens, parfois plusieurs siècles avant lui.

    triangle de Pascal

    premières lignes du triangle de Pascal

    Cette figure permet de calculer les coefficients binomiaux d’un polynôme (x+y) à la puissance n:

    $$\begin{matrix}\begin{align}n=2, (x+y)^2 & = x^2+2xy+y^2\\\n=3, (x+y)^3 & = x^3+3x^2y+3xy^2+y^3\\\n=4, (x+y)^4 & = x^4+4x^3y+6x^2y^2+4xy^3+y^4\end{align}\end{matrix}$$

    voir compléments sur la page wikipedia : Lien

    Un coefficient quelconque du triangle, situé à la ligne i et à la colonne j est calculé à partir de la formule de récurrence : (i et j superieurs à 1)

    $$C\left(\begin{matrix}i\\\j\end{matrix}\right)=C\left(\begin{matrix}i-1\\\j-1\end{matrix}\right)+C\left(\begin{matrix}i-1\\\j\end{matrix}\right)$$

    Algorithme récursif non optimisé

    Les algorithmes de type diviser pour regner sont souvent exprimés de manière recursive.

    def pascal_recur(n,p):
        # calcul d'un coefficient par recursivité
        if p==0:return 1
        if p>n:
            return 0
        else:
            return pascal_recur(n-1,p) + pascal_recur(n-1,p-1)
    
    def pascal(n):
        T = [[0] * (n+1) for p in range(n+1)]
        for n in range(n+1):
            for k in range(n+1):
                T[n][k] = pascal_recur(n,k)
        return T

    On peut alors tester le programme:

    > pascal(9)
    
    [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
     [1, 2, 1, 0, 0, 0, 0, 0, 0, 0],
     [1, 3, 3, 1, 0, 0, 0, 0, 0, 0],
     [1, 4, 6, 4, 1, 0, 0, 0, 0, 0],
     [1, 5, 10, 10, 5, 1, 0, 0, 0, 0],
     [1, 6, 15, 20, 15, 6, 1, 0, 0, 0],
     [1, 7, 21, 35, 35, 21, 7, 1, 0, 0],
     [1, 8, 28, 56, 70, 56, 28, 8, 1, 0],
     [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]]

    On remarque que l’on calcule souvent les mêmes coefficients binomiaux :

    arbre de calculs binomiaux

    arbre de calcul des coefficients pour n=4 p=2

    On voit que certains termes, comme celui (n=2, p=1) est calculé plusieurs fois. Dans les branches (n=3, p=1) et (n=3, p=2). Cela est du au fait que les 2 branches de l’arbre sont indépendantes.

    La mémoïzation consistera alors à stocker dans un tableau les solutions pour les sous-problèmes afin de ne pas les recalculer…

    Algorithme avec mémoïzation

    Chaque valeur du triangle n’est calculée qu’une seule fois.

    def trianglePascal(n):
        T = [[0] * (n+1) for p in range(n+1)]
        for n in range(n+1):
            for k in range(n+1):
                if k == 0:
                    T[n][0] = 1
                else:
                    T[n][k] = T[n-1][k-1] + T[n-1][k]
        return T

    L’algorithme non recursif, avec mémoïzation est plus efficace.

    Problèmes de décision et algorithmes gloutons

    Un algorithme glouton est un algorithme qui suit le principe de réaliser, étape par étape, un choix optimum local, afin d’obtenir un résultat optimum global.

    Le problème du rendu de monnaie

    Le problème du rendu de monnaie est un problème d’algorithmique. Il s’énonce de la façon suivante : étant donné un système de monnaie (pièces et billets), comment rendre une somme donnée de façon optimale, c’est-à-dire avec le nombre minimal de pièces et billets ?

    Par exemple, la meilleure façon de rendre 7 euros est de rendre un billet de cinq et une pièce de deux, même si d’autres façons existent (rendre 7 pièces de un euro, par exemple).

    caisse rendu monnaie

    Image by conmongt-pixabay

    Voir l’animation sur le site mpechaud.fr

    Sur l’animation, l’algorithme traite TOUTES les combinaisons de rendu de monnaie. L’arbre des appels recursifs montre que la complexité de cette méthode croit exponentiellement avec la taille des paramètres d’entrée.

    Contrairement aux problèmes étudiés précédement (tri d’un tableau, calcul de xn…), où il y avait toujours une unique solution, dans les problèmes d’optimisation, il peut y avoir des solutions valides (satisfaisant les contraintes) non optimales, une ou plusieurs solutions (valides), optimales (minimisant/maximisant une certaine mesure), voire pas du tout de solution valide.

    Si la taille du ou des paramètres en entrée est importante, il n’y a pas d’algorithme déterministe efficace. (on ne peut pas trouver LA solution au problème en parcourant toutes les solutions possibles car la complexité est trop grande). Voir paragraphe suivant sur la recherche exhaustive.

    On utilise alors d’autres stratégies, qui donneront parfois une solution, parfois une solution optimale. C’est ce que l’on réalise avec l’utilisation d’un algorithme glouton.

    Le problème du rendu de monnaie est NP-difficile relativement au nombre de pièce et billet du système monétaire considéré. (voir annexe).

    Algorithme exhaustif

    Une première méthode, SANS stratégie, pourrait être d’envisager TOUTES les combinaisons. On pourrait alors imaginer que l’on commence par rendre la monnaie avec une des pieces de la caisse (pas forcément la plus haute), puis on choisit une autre piece possible (egale ou moins haute), … Jusqu’à ce que la somme à rendre soit nulle. On envisage ainsi toutes les combinaisons possibles, ce qui, avec une valeur élevée de la somme à rendre, et un grand nombre de pieces dans la caisse, va donner un très grand nombre de combinaisons. On selectionne enfin la meilleure des solutions (celle optimale).

    Par exemple, pour rendre 7 euros, voici toutes les combinaisons possibles (la solution optimale étant la première):

    • 5 + 2
    • 5 + 1 + 1
    • 2 + 2 + 2 + 1
    • 2 + 2 + 1 + 1 + 1
    • 2 + 1 + 1 + 1 + 1 + 1
    • 1 + 1 + 1 + 1 + 1 + 1 + 1

    On peut représenter cette recherche de solutions à l’aide d’un arbre: La racine est la somme à rendre. On descend dans l’arbre en faisant des choix, ce qui diminue la somme. Lorsque l’on arrive sur une feuille avec 0, c’est que l’on a trouvé une solution. La solution otimale est donnée ici en rendant 4 pieces de 7 (trajectoire presque verticale de 28 à 0):

    wikipedia - Problème_du_rendu_de_monnaie

    wikipedia - Problème_du_rendu_de_monnaie

    1. Représenter, comme sur l’image ci-dessus, une partie de l’arbre des combinaisons pour rendre un montant égal à 15, en choisissant une à une chaque piece de la caisse [1, 7, 9]. Quelle est la trajectoire dans cet arbre selon la méthode gloutonne? Quel est le choix optimal?

    Un programme python exprimerait le rendu sous forme de liste:

    > rendu(7,[5,2,1])
    # 6 solutions
    [[5, 2],
     [5, 1, 1],
     [2, 2, 2, 1],
     [2, 2, 1, 1, 1],
     [2, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1]]
    > rendu(14,[10,5,2,1])
    # 19 solutions
    [[10, 2, 2],
     [10, 2, 1, 1],
     [10, 1, 1, 1, 1],
     [5, 5, 2, 2],
     [5, 5, 2, 1, 1],
     [5, 5, 1, 1, 1, 1],
     [5, 2, 2, 2, 2, 1],
     [5, 2, 2, 2, 1, 1, 1],
     [5, 2, 2, 1, 1, 1, 1, 1],
     [5, 2, 1, 1, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2, 2, 2],
     [2, 2, 2, 2, 2, 2, 1, 1],
     [2, 2, 2, 2, 2, 1, 1, 1, 1],
     [2, 2, 2, 2, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
    rendu(21,[20,10,5,2,1])
    # 44 solutions
    [[20, 1],
     [10, 10, 1],
     [10, 5, 5, 1],
     [10, 5, 2, 2, 2],
     [10, 5, 2, 2, 1, 1],
     [10, 5, 2, 1, 1, 1, 1],
     [10, 5, 1, 1, 1, 1, 1, 1],
     [10, 2, 2, 2, 2, 2, 1],
     [10, 2, 2, 2, 2, 1, 1, 1],
     [10, 2, 2, 2, 1, 1, 1, 1, 1],
     [10, 2, 2, 1, 1, 1, 1, 1, 1, 1],
     [10, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 1],
     [5, 5, 5, 2, 2, 2],
     [5, 5, 5, 2, 2, 1, 1],
     [5, 5, 5, 2, 1, 1, 1, 1],
     [5, 5, 5, 1, 1, 1, 1, 1, 1],
     [5, 5, 2, 2, 2, 2, 2, 1],
     [5, 5, 2, 2, 2, 2, 1, 1, 1],
     [5, 5, 2, 2, 2, 1, 1, 1, 1, 1],
     [5, 5, 2, 2, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 2, 2, 2, 2, 2, 2, 2, 2],
     [5, 2, 2, 2, 2, 2, 2, 2, 1, 1],
     [5, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1],
     [5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1],
     [5, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1],
     [2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1],
     [2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

    heuristique glouton

    Le problème est traité de cette manière en 1ere NSI:

    Une caisse contient un nombre suffisant de pieces pour rendre la monnaie. Cette caisse est représentée par une liste triée en ordre croissant, et sera parcourue de la piece de valeur la plus élevée vers la moins élevée.

    Supposons que l’on dispose d’une fonction recursive, qui pour chaque piece de la caisse fait le choix suivant:

    • soit la piece est inférieure à la monnaie à rendre: alors on soustrait la piece à la somme à rendre et on appelle la fonction de manière récursive avec cette même caisse, et la nouvelle somme à rendre.
    • soit la piece est supérieure à la somme à rendre. on retire la piece de la caisse. Et on appelle de manière récursive la fonction avec la nouvelle caisse, et la même somme.

    La condition de base sera: la liste de pieces est vide.

    On utilisera une liste rendu pour placer les pieces rendues.

    def rendre_monnaie(somme,pieces,rendu):
        if pieces == []:
            return rendu
        if pieces[-1]<=somme:
            rendu.append(pieces[-1])
            return rendre_monnaie(somme-pieces[-1],pieces,rendu)
        else:
            pieces.pop()
            return rendre_monnaie(somme,pieces,rendu)
    
    rendre_monnaie(49,[1,2,5,10,20,50,100],[])
    # affiche 
    # [20, 20, 5, 2, 2]

    Un système monétaire non canonique:

    1. Que renvoie la fonction pour rendre 53 pences avec le système imperial où pieces = [240,60,30,24,12,6,3,1] ?
    2. Le rendu est-il optimal avec cette méthode? Ou bien existe t-il une autre façon de rendre la monnaie, avec moins de pieces?

    Conclusion: Suivant le système de pièces, l’algorithme glouton est optimal ou pas. Dans le système de pièces européen (en centimes : 1, 2, 5, 10, 20, 50, 100, 200), où l’algorithme glouton donne la somme suivante pour 37 : 20+10+5+2, on peut montrer que l’algorithme glouton donne toujours une solution optimale. wikipedia

    Algorithme glouton vs programmation dynamique

    Un algorithme glouton fait un choix local immédiat et irrévocable à chaque étape, sans revenir en arrière. Pour le rendu de monnaie, il prendrait systématiquement la plus grande pièce possible. C’est simple et rapide, mais pas toujours optimal.

    Exemple : rendre 15 avec {1, 7, 9} → le glouton prend 9, puis 6 × 1 = 7 pièces.

    La programmation dynamique construit au contraire un tableau de solutions optimales pour tous les sous-problèmes, en s’appuyant à chaque étape sur les résultats déjà calculés. Elle garantit l’optimum.


    Algorithme de programmation dynamique — rendu de monnaie

    On cherche à rendre un montant x avec un minimum de pièces, choisies parmi n valeurs possibles.

    Approche ascendante : on construit une table de solutions optimales pour tous les montants de 0 à x. On commence par les petits montants, puis on monte progressivement. Chaque montant est rendu de manière optimale en s’appuyant sur les résultats déjà calculés.

    Principe : pour rendre le montant w, il faut au moins une pièce, à choisir parmi les n pièces disponibles. Une fois cette pièce choisie de valeur p, le montant restant w - p est strictement inférieur à w — on sait donc déjà le rendre de façon optimale (c’est déjà dans le tableau). Il suffit d’essayer les n possibilités et de retenir celle qui minimise le nombre total de pièces :

    $$dp[w] = \min_{p \in \text{pièces},\ p \leq w} \left( dp[w - p] + 1 \right)$$

    Exemple : rendre 15 avec des pièces de {1, 7, 9}

    Remplissage du tableau ligne par ligne

    dp[i][w] = nombre minimum de pièces pour rendre exactement w avec les i premiers types de pièces. ∞ signifie “impossible”.

    Ligne 0 — sans pièce :

    • dp[0][0] = 0 : rendre 0€ ne nécessite aucune pièce
    • dp[0][w] = ∞ pour tout w > 0 : impossible de rendre quoi que ce soit sans pièce

    Ligne 1 — pièces disponibles : {1} :

    • dp[1][w] = w pour tout w : il faut exactement w pièces de 1€

    Ligne 2 — pièces disponibles : {1, 7} :

    • Pour w < 7 : la pièce de 7€ est inutilisable → on recopie la ligne 1
    • Pour w ≥ 7 : on compare “ne pas prendre la pièce de 7€” (dp[1][w]) et “la prendre” (dp[2][w-7] + 1) :
      • w = 7 : min(7, dp[2][0]+1) = min(7, 1) = 1
      • w = 8 : min(8, dp[2][1]+1) = min(8, 2) = 2
      • w = 9 : min(9, dp[2][2]+1) = min(9, 3) = 3
      • w = 10 : min(10, dp[2][3]+1) = min(10, 4) = 4
      • w = 11 : min(11, dp[2][4]+1) = min(11, 5) = 5
      • w = 12 : min(12, dp[2][5]+1) = min(12, 6) = 6
      • w = 13 : min(13, dp[2][6]+1) = min(13, 7) = 7
      • w = 14 : min(14, dp[2][7]+1) = min(14, 2) = 2
      • w = 15 : min(15, dp[2][8]+1) = min(15, 3) = 3

    Note : quand on “prend” la pièce de 7€, on consulte dp[2][w-7] (et non dp[1][w-7]), car on peut réutiliser la même pièce autant de fois qu’on veut.

    Ligne 3 — pièces disponibles : {1, 7, 9} :

    • Pour w < 9 : la pièce de 9€ est inutilisable → on recopie la ligne 2
    • Pour w ≥ 9 : on compare “ne pas prendre la pièce de 9€” (dp[2][w]) et “la prendre” (dp[3][w-9] + 1) :
      • w = 9 : min(dp[2][9], dp[3][0]+1) = min(3, 1) = 1
      • w = 10 : min(dp[2][10], dp[3][1]+1) = min(4, 2) = 2
      • w = 11 : min(dp[2][11], dp[3][2]+1) = min(5, 3) = 3
      • w = 12 : min(dp[2][12], dp[3][3]+1) = min(6, 4) = 4
      • w = 13 : min(dp[2][13], dp[3][4]+1) = min(7, 5) = 5
      • w = 14 : min(dp[2][14], dp[3][5]+1) = min(2, 6) = 2
      • w = 15 : min(dp[2][15], dp[3][6]+1) = min(3, 7) = 3

    Tableau complet

    w=0 w=1 w=2 w=3 w=4 w=5 w=6 w=7 w=8 w=9 w=10 w=11 w=12 w=13 w=14 w=15
    sans pièce 0 ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞
    + pièce 1€ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
    + pièce 7€ 0 1 2 3 4 5 6 1 2 3 4 5 6 7 2 3
    + pièce 9€ 0 1 2 3 4 5 6 1 2 1 2 3 4 5 2 3

    La réponse se lit dans la dernière case : dp[3][15] = 3 pièces (7 + 7 + 1).


    Complexité

    Comment cet algorithme parvient-il à reduire le nombre de combinaisons pour rendre la monnaie?

    Le tableau comporte n × W cases (ici 3 × 15 = 45), chacune calculée en temps constant. La complexité est donc O(n · W) — à comparer avec la méthode exhaustive en O(2ⁿ) :

    n W O(n · W) O(2ⁿ)
    10 100 1 000 1 024
    30 500 15 000 ≈ 10⁹
    100 500 50 000 ≈ 10³⁰

    Pour des instances réalistes, la programmation dynamique est des milliards de fois plus rapide que la recherche exhaustive.

    Remarques:

    • La subtilité importante : O(n·W) ressemble à du polynomial, mais W peut être très grand. Si les poids sont exprimés en grammes et que le sac fait 100 kg, W = 100 000. C’est pour ça que le sac à dos reste un problème dit NP-complet dans le cas général, c’est-à-dire difficile à résoudre. Cependant pour certains systèmes de monnaie dits canoniques, l’algorithme glouton est optimal.
    • Regarder aussi: le probleme de l’allocation des ressources pour un systeme d’exploitation: l’algorithme du banquier

    Le problème du sac à dos

    Un problème très similaire est celui du sac-à-dos. Supposons que vous découvriez la caverne d’Ali Baba (et des 40 voleurs), il y a une infinité d’objets de valeur v1, v2, · · · , vn mais chaque objet de valeur vi a un poids de pi. Comment remplir votre sac-à-dos avec le contenu qui rapportera le plus, sachant que votre sac ne supporte qu’un poids W?

    probleme du sac a dos

    illustration du probleme du sac à dos

    Voir l’article et l’animation sur Interstices

    Adapter la stratégie du rendu de monnaie

    Heuristique gloutonne

    Structure de données:

    rendu de monnaie sac à dos
    [Nbre de piece, [pieces de 1, pieces de 2, pieces de 5, …]] [Gains cumulés, [articles 1, articles 2, articles 3, …]]

    Exemple:

    Déterminer le choix idéal pour un sac à dos de capacité 32kg, avec les objets suivants, proposés en nombre infini: `[{“valeur”: 7, “poids”:17},{“valeur”: 4, “poids”:11},{“valeur”: 3.1, “poids”:9},{“valeur”: 1, “poids”:3.5}]

    Objets 1 2 3 4
    valeur 7 4 3.1 1
    poids (kg) 17 11 9 3.5
    ratio val/poids 0.41 0.36 0.34 0.29

    La stratégie, sur le modèle du rendu de monnaie sera la suivante:

    • classer les objets dans l’ordre décroissant de leur taux de valeur (taux de valeur = valeur / masse). Ainsi le premier élément de la liste sera celui ayant le meilleur rapport valeur/masse.
    • on prend le premier élément de la liste, puis le deuxième, etc., tant que le sac peut encore les contenir.

    Algorithme de type programmation dynamique

    Nous allons chercher à adapter ici aussi l’algorithme vu pour le rendu de monnaie:

    Algorithme:

    rendu de monnaie sac à dos
    Pour toute valeur de montant i jusqu’à x Pour tout poids i jusqu’à W
    Pour tout montant de piece de la caisse Pour tout objet (vi, pi) du tresor
    Test 1: le montant de la piece est-il < i? Test 1: Le poids de l’objet est-il < i?
    Test 2: Si j’ajoute la piece pour rendre la monnaie, le nombre de pieces rendues sera-t-il inférieur à celui stocké pour i? (le reste de la somme à rendre a deja été calculé precedemment) Test 2: Si je prend l’objet, le montant total rapporté est-il supérieur à la valeur stockée pour i?
    Si oui: rendre la piece Si oui: prendre l’objet

    Cela reviendra à remplir le tableau suivant, de manière ascendante:

    • Commencer par le sac de plus petite capacité.
    • Pour chaque objet de poids < capacité du sac:
      • prendre l’objet.
      • Compléter le sac avec la solution optimale déjà trouvée dans le tableau.
    • Choisir parmi les solutions trouvées, celle de gain optimal.
    • Continuer avec un sac de capacité supérieure.
    capacité du sac (kg) Liste des objets (valeur,poids) coût cumulé ($)
    4, 5, 6 [(1,3.5)] 1
    7,8 [(1,3.5), (1,3.5)] 2
    9 .. ..
    10 .. ..
    11 .. ..
    12 .. ..
    13 .. ..
    14 .. ..
    15 .. ..
    16 .. ..
    17 .. ..
    18 .. ..

    Le problème du voyageur du commerce

    énoncé du problème

    le problème du voyageur de commerce, est un problème d’optimisation qui, étant donné une liste de villes, et des distances entre toutes les paires de villes, détermine un plus court circuit qui visite chaque ville une et une seule fois.

    Malgré la simplicité de son énoncé, il s’agit d’un problème d’optimisation pour lequel on ne connait pas d’algorithme permettant de trouver une solution exacte rapidement dans tous les cas. Plus précisément, on ne connait pas d’algorithme en temps polynomial, et sa version décisionnelle (pour une distance D, existe-t-il un chemin plus court que D passant par toutes les villes et qui termine dans la ville de départ ?) est un problème NP-complet. Voir annexe pour précisions.

    Pour résoudre ce problème, une heuristique gloutonne construit une seule solution, par une suite de décisions définitives sans retour arrière, parmi ces méthodes on cite le plus proche voisin, la plus proche insertion, la plus lointaine insertion et la meilleure insertion. Il n’est pas certain que la méthode donne la meilleure solution.

    La figure suivante aide à la resolution. La solution optimale est celle qui va joindre tous les noeuds du graphe, une seule fois. (Cycle hamiltonien)
    Des solutions possibles, mais non optimales sont celles qui permettent de visiter tous les noeuds une seule fois, mais dont la distance parcourue cumulée n’est peut-être pas la plus courte.

    cycle hamiltonien

    illustration de la recherche d'un cycle hamiltonien dans un graphe.

    Mais une illustration plus concrête est celle par exemple du problème de la tournée du candidat pour les élections présidentielles aux état-unis:

    tournée du candidat à la presidentielle

    tournée du candidat à la presidentielle

    On voit que la recherche d’une solution en comparant tous les tours qu’il est mathématiquement possible de faire n’est pas raisonnable. La complexité est trop importante.

    Exemple: solution gloutonne

    Un voyageur cherche un itinéraire passant par toutes les villes du tableau, et qui minimise la distance totale parcourue. Les villes peuvent être visitées dans n’importe quel ordre mais aucune ne doit être négligée, et le visiteur doit revenir à la fin à sa ville de départ.

    Le voyageur part de Nancy et souhaite visiter Metz, Paris, Reims et Troyes, avant de retourner à Nancy.

    Voici un tableau donnant les distances kilométriques entre chacune des ces villes.

    Nancy Metz Paris Reims Troyes
    Nancy 55 303 188 183
    Metz 55 306 176 203
    Paris 303 306 142 153
    Reims 188 176 142 123
    Troyes 183 203 153 123
    1. Quelle est la stratégie gloutonne à mettre en oeuvre ?
    2. Mettez en oeuvre cette stratégie et donnez la solution.
    3. Calculez la distance totale pour le parcours Metz - Reims - Paris - Troyes (départ et arrivée à Nancy sous-entendus)
    4. Que dire de la solution gloutonne ?

    Méthode itérative d’amélioration: algorithme de recherche locale k-opt

    L’algorithme k-opt est un algorithme de recherche locale proposé par Georges A. Croes en 19581 pour résoudre le problème du voyageur de commerce en améliorant une solution initiale. On représente le tour par un graphe connexe.

    à chaque étape, on supprime deux arêtes de la solution courante et on reconnecte les deux tours ainsi formés. Cette méthode permet, entre autres, d’améliorer le coût des solutions en supprimant les arêtes sécantes lorsque l’inégalité triangulaire est respectée (voir figure ci-contre). Sur le schéma de droite, la route {a, b, e, d, c, f, g} est changée en {a, b, c, d, e, f, g} en inversant l’ordre de visite des villes e et c. Il n’est toutefois pas certain que la solution trouvée soit également optimale lorsque l’on additionne ces morceaux de tours.. source: wikipedia: 2-opt.

    Plus généralement, lorsqu’on inverse l’ordre de parcours de deux villes, il faut aussi inverser l’ordre de parcours de toutes les villes entre ces deux villes.

    algorithme 2-opt TSP

    Résumé. L’essentiel à retenir

    Programmation dynamique

    L’idée de la programmation dynamique, c’est de gagner en efficacité. On cherche à reduire la complexité temporelle et spatiale.

    Les problèmes à resoudre:

    • peuvent être décomposés en sous-problèmes
    • présentent un chevauchement des sous-problèmes.

    Par exemple, pour la suite de Fibonacci, ou le triangle de Pascal, les coefficients de la suite ou du triangle sont calculés à partir des précédents, ceux de rang inférieur(sous problèmes). En stockant ces valeurs dans une liste, on peut les réutiliser sans les calculer à nouveau.

    Algorithmes gloutons

    Un algorithme glouton dépend du problème que l’on cherche à resoudre. Il n’y a pas d’algorithme glouton universel. Il permet de trouver une solution à un problème d’optimalité. Il part du principe que l’on peut trouver une solution approchante pour un problème NP-complet, en utilisant une stratégie et en faisant des choix. Chacun de ces choix semble être le meilleur sur le moment.

    Les choix realisés sont:

    • rendre la piece de monnaie la plus grande possible, d’abord.
    • prendre l’objet de plus grand ration prix/poids, d’abord.

    Programmation dynamique

    Il s’agit maintenant d’une stratégie ascendante, utilisant des résultats optimum, établis pour de plus petit cas, afin de resoudre de plus gros.

    • pour le rendu de monnaie: commencer par résoudre le problème d’optimalité pour rendre de plus petites sommes. Puis, on utilise cette solution pour rendre une partie des sommes plus importantes.

    • pour le problème du sac à dos: de commencer par remplir un sac de plus petite contenance. Puis, on utilise ce résultat pour compléter de plus gros sacs.

    On fait des choix à chaque étape, mais selon une stratégie bien définie, et qui ne change plus, en esperant que la somme des solutions intermédiaires va donner finalement une solution optimale. Mais on n’en est pas sûr. Et on ne revient pas en arrière.

    Algorithme avec recherche locale

    Pour le problème du TSP (Traveling salesman problem, ou problème du voyageur du commerce), on peut utiliser un algorithme de recherche locale, comme le k-opt. Celui-ci va cette fois remettre en doute les choix précédents.

    Les étapes et leurs liens peuvent être représentés par un graphe connexe.

    L’un des algorithmes existant pour la resolution, le 2-opt, va rechercher un minimum local pour un morceau de tour constitué de quelques noeuds. L’algorithme procède par permutation des arêtes entre noeuds. Et il conserve le morceau de tour de plus courte distance.

    Il s’agit d’une succession de choix qui determine la solution.

    Le k-opt est une méthode itérative d’amélioration. Elle est souvent utilisée après une phase constructive (qui peut être gloutonne) pour affiner le résultat. le k-opt s’arrête quand il ne peut plus améliorer la solution immédiate, mais cela ne garantit pas que c’est la meilleure solution absolue. (illustre la notion d’optimum local vs optimum global)

    Complexité

    Rappels

    Complexité temporelle d’un algorithme. Il s’agit du nombre d’opérations élémentaires executées par l’algorithme dans un pire cas (une instance en entrée qui demande le plus de calculs). Cette complexité est exprimée en fonction de la “taille de l’entrée”. Par exemple, nous avons vu des algorithmes de tri avec des complexité en O(n2) ou en O(nlogn) avec n la longueur du tableau en entrée.

    Pour l’exemple du voyageur du commerce: Le nombre de solutions possibles, où les villes sont toutes parcourues une fois, il y a un nombre TRES élevé d’alternatives:

    Supposons un graphe à 50 sommets qui représente la carte de ces villes. Il y a 49! possibiltés. Ce qui fait 6,08.1062 solutions.

    Si l’ordinateur évalue une solution en 0,1 ms, cela fait 6,08.1058s, soit 1,9.1049 siecles de calculs !! (L’Univers a 14 milliards d’années).

    Les algorithmes des problèmes de décision sont classés selon leur complexité:

    Problèmes P: probleme faciles à trouver

    Un problème est dit polynomial si il existe un algorithme pour le résoudre dont la complexité peut s’exprimer comme un polynôme de la taille de l’entrée. L’ensemble des problèmes polynomiaux est noté P et est considéré comme un ensemble de problèmes “faciles” (ils peuvent être résolus relativement efficacement).

    Un exemple de problème polynomial est celui de la connexité dans un graphe. Étant donné un graphe à n sommets (on considère que la taille de la donnée, donc du graphe, est son nombre de sommets), il s’agit de savoir si toutes les paires de sommets sont reliées par un chemin. Un algorithme de parcours en profondeur construit un arbre couvrant du graphe à partir d’un sommet. Si cet arbre contient tous les sommets du graphe, alors le graphe est connexe.(wikipedia)

    Problèmes NP: problèmes faciles à vérifier

    Une autre classe de problèmes importante est celle des problèmes dont on peut tester en temps polynomial si une solution est valide (par exemple, je vous donne un tableau et vous devez non pas le trier mais me dire si il est déjà trié ou non). Cette classe s’appelle NP pour Non déterministe Polynomial.

    Supposons que vous soyez chargé de loger un groupe de quatre cents étudiants. Le nombre de places est limité, seuls cent étudiants se verront attribuer une place dans la résidence universitaire. Pour compliquer les choses le doyen vous a fourni une liste de paires d’étudiants incompatibles, et demande que deux étudiants d’une même paire ne puissent jamais apparaître dans votre choix final. wikipedia.

    Produire une telle liste à partir de zéro paraît tellement difficile qu’elle en est même impraticable, car le nombre de façons de regrouper cent étudiants parmi quatre cents dépasse le nombre d’atomes de l’univers !. Par contre, une fois que l’on vous fournit une solution, il est facile de montrer que celle-ci est juste ou fausse.

    Si un problème est connu comme étant NP et si une solution au problème est connue, la démonstration de l’exactitude de la solution peut toujours être réduite à une vérification P (temps polynomial). Les algorithmes de cette classe sont non déterministes.

    Existe t-il pour les problèmes connus de la classe NP un algorithme susceptible de trouver une solution et de complexité polynomiale. On n’en est pas sûr. Peut-être que cette apparente difficulté ne fait que refléter le manque d’ingéniosité de nos programmeurs.

    Le problème de savoir si P = NP est un des problèmes du millénaire de l’institut de mathématiques Clay. Informellement, il s’agit de savoir si vérifier efficacement qu’une “solution à un problème est bien une solution valide” revient à “pouvoir trouver efficacement une solution valide au problème.”

    Problèmes NP-complets

    Les problèmes dits NP-complets sont des problèmes au moins aussi difficiles que les plus difficiles de la classe NP.

    source: page P=NP wikipedia

    source: page P=NP wikipedia

    Exemples: le voyageur du commerce, le calcul de solutions optimales en économie (enoncé semblable mais à une echelle plus grande que celui du sac à dos), ou dans les processus de fabrication ou de transport…

    Tous les algorithmes connus pour résoudre des problèmes NP-complets ont un temps d’exécution exponentiel en la taille des données d’entrée dans le pire des cas, et sont donc inexploitables en pratique même pour des instances de taille modérée.

    Les classes P, NP, NP-complet ne concernent stricto sensus que les problèmes de décision. Donc quand on dit que le problème du voyageur de commerce est NP-complet, il faut l’entendre : dans sa version « décisionnelle », qui est : est-il possible de trouver un chemin qui passe par toute les villes et qui soit de longueur inférieure à L? De manière générale, tous les problèmes d’optimisation sous contrainte, comme ceux vus plus haut, sont aussi des problèmes de décision.

    Trouver un algorithme qui résout un problème NP-complet, comme le problème du voyageur de commerce, en temps polynomial, suffirait à démontrer que P = NP, ce serait alors toute une série de problèmes très importants qui se trouveraient résolus. Sans exhiber un algorithme, une preuve pourrait donner des indices précieux pour construire un tel algorithme. wikipedia.

    Annexes

    Programmes python du rendu de monnaie

    algo naîf vu en classe de 1ere

    def estvide(ensemble):
        """
        fonction qui teste si un ensemble est vide
        retourne True si vide
        False sinon
        """
        vide = True
        for i in ensemble:
            vide = False
        return vide
    
    def rendre(cost,caisse):
        """
        fonction qui rend la monnaie sur une somme cost (int) selon le 
        contenu de la caisse (une variable de type set)
        en commençant par la plus grande des pieces.
        caisse : la caisse du commerçant (set)
        rendu : ce que rend le commerçant (dict)
        à chaque itération de la boucle, on retire la piece de l'ensemble caisse 
        qui est utilisée jusqu'à ce que caisse soit vide
        """
        ### initialisation ###
        rendu = {}
        for i in caisse : 
            rendu[i] = 0
        
        while not estvide(caisse):
            piece = max(caisse)
            n = cost//piece
            cost = cost - n*piece
            rendu[piece] = n
            caisse.remove(piece)       
        return rendu

    essais

    >>> caisse = {1,2,5,10,20,50}
    >>> rendre(93,caisse) # OK optimal
    {1: 1, 2: 1, 5: 0, 10: 0, 20: 2, 50: 1}
    >>> caisse = {1,10,15}
    >>> rendre(21,caisse) # non optimal
    {1: 6, 10: 0, 15: 1}

    algo glouton recursif

    (non donné)

    algorithme en programmation dynamique

    import copy
    def renduMonnaieProgDyn(x,c) :
        """
        c : caisse avec les genres de pieces à rendre par ex [1,2,5,10]
        x : montant à rendre
        res : tableau contenant : [nbe pieces rendues,[nb pieces de pieces de A, nb de B, nb de C]]
        temp : nombre de pieces rendues
        """
        n = len(c)
        res = [[x, [0 for j in range(n)]] for i in range(x + 1)]  # initialisation de la table avec des x 
        # x pieces rendues correspond à la plus mauvaise des reponses (par ex que des pieces de 1)
        res[0][0] = 0
        for i in range(1,x+1) :  # valeur du montant à rendre : recherche pour TOUT montant
            for j in range(n) : # parcours de la caisse
                if i >= c[j] : # rendre de la monnaie avec cette piece
                    temp = 1 + res[i - c[j]][0] # rend une piece du type de celle de rang j
                    # le nbe de piece au total est egal à 1 + le nbe de piece pour rendre le reste (deja calc)
                    
                    if res[i][0]>=temp:
                        res[i][0] = temp   # nombre de pieces rendues
                        res[i][1] = copy.deepcopy(res[i-c[j]][1])   # copier le nb de pieces de A , de B, de C pour le rendu de monnaie
                        # monnaie du montant i-c[j]
                        # ici il faudra copy.deepcopy pour faire une copie par valeur
                        res[i][1][j] += 1 # ajouter 1 au nombre de pieces de c[j] utilisées
                        print(f'i: {i:2}, j: {j:2}, res[{i}]: {res[i]}, temp: {temp}' )
        return res[x]

    Algorithme exhaustif

    Programme utilisé pour determiner toutes les combinaisons possibles de rendu de monnaie. Complexité exponentielle…

    def rendu_expo(somme,caisse,rendu=[]):
        if somme==0:
            solutions.append(sorted(rendu, reverse=True))
        for i in range(len(caisse)):
            if caisse[i]<=somme:
                rendu_expo(somme-caisse[i],caisse[i:],rendu+[caisse[i]])
            else:
                rendu_expo(somme,caisse[1:],rendu)
    def unique(L):
        # pour eliminer les doublons de la liste
        T = []
        T.append(L[0])
        for sol in L:
            if sol not in T:
                T.append(sol)
        return T
    
    solutions=[]
    rendu_expo(53,[30,24,12,6,3,1])
    solution_min = unique(solutions)
    print(len(solution_min))
    solution_min

    Le problème du sac à dos

    Résolution

    import copy
    
    def sacADosRemise(W, s) :
        n = len(s)
        res = [[0, [0 for j in range(n)]] for i in range(W + 1)] # format [valeur totale,[nb_o1, nb_o2, nb_o3, nb_o4]]]
        for i in range(1,W +1) :
            j=0
            while (j < n) and (i-s[j][1]>=0) :
                if res[i - s[j][1]][0] + s[j][0] > res[i][0] :
                    res[i][0] = res[i - s[j][1]][0] + s[j][0]
                    res[i][1] = copy.deepcopy(res[i - s[j][1]][1])
                    res[i][1][j] += 1
                j+=1
        return res[W]

    essais:

    > W = 15
    > s = [(1,2),(2,3),(4,5),(6,8)] # ensemble de couples (valeur, poids)
    > sacADosRemise(W,s)
    [12, [0, 0, 3, 0]]

    Liens

    calculer sur un algorithme

    Calculabilité

    Dans le chapitre précédent, sur la complexité, l’objet d’étude principal etait l’algorithme. On en a fait une mesure de son efficacité: un algorithme est plus efficace s’il est plus rapide (donc de classe de complexité plus faible).

    En calculabilité, le problème devient l’objet central.

    Voir le cours d’algorithmique de Pierre Antoine Champin, CNRS: definition très claire de la notion de Problème comme une classe.

    Le Problème de Décision - Voyages au pays des maths | ARTE

    Le Problème de Décision - Voyages au pays des maths | ARTE

    On a souvent l’impression que pour chaque problème on peut trouver un algorithme de solution. Ce n’est pas le cas : pour des nombreux probèmes naturels et intéressants il n’existe pas d’algorithme. Ces problèmes sont non calculables. Cette notion a évolué dans l’histoire de l’informatique au cours des étapes suivantes:

    Charles Babbage (1791 – 1871), professeur à Cambridge, construit la machine différentielle et la machine analytique. La dernière peut être considérée comme précurseur des ordinateurs modernes, consistant d’une unité de contrôle, une unité de calcul, une mémoire, ainsi que l’entrée-sortie.

    Charles Babbage (1791 – 1871) - wikipedia

    Charles Babbage (1791 – 1871) - wikipedia

    Ada Lovelace (1815 – 1852) travaille avec Babbage et préconise l’utilisation de la machine analytique pour la résolution de problèmes mathématiques. C’est le premier langage informatique, énoncé avant même l’existance d’une machine. Elle est considérée comme premier programmeur du monde.

    Ada Lovelace (1815 – 1852)

    Ada Lovelace (1815 – 1852)

    David Hilbert (1862 – 1943), professeur à Göttingen, présente en 1920 un programme de recherche visant à clarifier les fondaments des mathématiques : “tout enoncé mathématique peut être soit prouvé soit refuté”. Plus tard il enonce le “Entscheidungsproblem” : On doit pouvoir montrer de façon “mécanique” si un enoncé mathématique est vrai ou faux.

    Pour cela, on s’appuie sur un systèmes d’axiomes censés fonder les mathématiques. A partir de ce système d’axiomes, on n’aura jamais des démonstrations contradictoires d’une proposition (d’un problème, d’un énoncé de mathématique).

    Selon lui, tout est décidable, selon le terme qui sera employé plus tard.

    David Hilbert (1862 – 1943)

    David Hilbert (1862 – 1943)

    Kurt Gödel (1906 – 1978), un des logiciens les plus fameux de l’histoire, répond en 1931 négativement quand au programme proposé par Hilbert. Il affirme qu’un systeme logique, aussi puissant soit-il, admet des propositions (des problèmes) ne pouvant être ni infirmées ni confirmées à partir des axiomes de la théorie. Ces propositions sont qualifiées d’indécidables.

    Il s’agit du théorème d’incomplétude.

    Paradoxalement, on sait que certaines de ces propositions indécidables sont vraies, mais on ne peut le démontrer.

    Kurt Gödel (1906 – 1978)

    Kurt Gödel (1906 – 1978)

    Alan Turing (1912 – 1954) et Turing cherche s’il n’y aurait pas au moins une procédure mécanique pour trouver quelles sont les propositions que l’on peut effectivement déduire d’un système d’axiomes, c’est à dire de décider de leur vérité (équivalent du problème de décision). Il part du principe que ce qu’un humain peut déduire est équivalent à ce qu’une machine peut déduire. Ainsi, il suffit de décrire convenablement une machine idéale pour préciser ce qu’est une procédure systématique. Cette machine idéale sera la machine de Turing. Il montre, par un raisonnement logique que cette machine ne peut pas démontrer toutes les propositions d’un système d’axiomes (indécidabilité).

    Alan Turing (1912 – 1954) - wikipedia

    Alan Turing (1912 – 1954) - wikipedia

    Définitions

    Qu’est ce qu’un problème?

    Informatiquement, problème sera synonyme de fonction. Un problème est caractérisé par:

    • Le nom du problème
    • des données d’entrée, que l’on appelle instance du problème.
    • une question mathématique posée sur ces données d’entrée.

    Rq : Ne pas confondre problème et algorithme le résolvant. Il peut y avoir plusieurs algorithmes qui resolvent le même problème (calculent la même fonction).

    Les problèmes s’énoncent de la manière la plus générale possible. On peut les désigner comme des classes, possédant de multiples instances (celles pour lesquelles on place des valeurs à la place des varaibles).

    Problème 1

    • Donnée : Un ensemble N d’entiers naturels
    • Question : Déterminer les nombres pairs dans cet ensemble.

    Instance 1: Quels sont les nombres pairs dans l’ensemble [1,2,3,4]?

    Problème 2

    • Donnée : Un ensemble N d’entiers naturels
    • Question : Déterminer les nombres premiers de cet ensemble.

    Instance 2: Le nombre 137 est-il premier?

    Problème 3

    • Donnée : Un programme C.
    • Question : Le programme est-il syntaxiquement correct ?

    Ce dernier exemple de problème suggère qu’un algorithme est une donnée comme une autre. En effet, le script qui traduit l’algorithme est écrit dans un langage. Et la machine va le lire et l’interpréter à l’aide d’un autre programme. Pour ce programme, le script est une donnée (interpréteurs, compilateurs).

    Calculabilité

    Qu’est-ce que c’est “calculable”?

    • En mathématique : Une fonction f : ℕ → ℕ est calculable s’il existe un programme/algorithme qui calcule f: si la fonction f est définie sur une entrée x, alors l’algorithme doit renvoyer la valeur f(x), et si f n’est pas définie, l’algorithme doit boucler sur l’entrée x.
    • En algorithmique: on dira qu’une fonction est calculable si elle peut être programmée dans l’un ou l’autre des langages de programmation usuels.

    La première fonction explicite non calculable a été décrite par Turing en 1936. Il s’agit du problème de l’arrêt : étant donné un algorithme A et une entrée x, il s’agit de déterminer si A s’arrête ou non sur l’entrée x (i.e A ne boucle pas sur l’entrée x).

    Théorème : Le problème de l’arrêt est incalculable.

    Qu’est ce que la “terminaison”? On dit qu’un programme termine s’il ne boucle pas, c’est-à-dire qu’il renvoie bien un résultat.

    Problèmes de décision décidables

    Problèmes de décision

    Il existe une catégorie de problèmes que l’on appelle : problèmes de décision. Dire que le problème est decidable, c’est dire qu’il existe un programme Python permettant de calculer f(n) pour tout entier n, en un temps fini.
    Ou bien : P est décidable s’il existe un algorithme qui pour chaque x dit “OUI” ou “NON” à la question : “Est-ce que P(x) est vrai ?”.
    Tous les problèmes mathématiques (voir plus haut) peuvent être énoncés comme des problèmes de décision: voir page wikipedia., avec le Passage de problème d’optimisation à problème de décision.

    Pour les problèmes 1 et 2 vus auparavent, on peut les énoncer sous la forme:

    • instance du Problème 1
    • Donnée : Un nombre entier positif n en base 2.
    • Question : n est-il pair?

    autre exemple:

    • instance du Problème 2
    • Donnée : Un nombre entier positif n en base 10.
    • Question : n est-il premier?

    Les problèmes 1 et 2 sont énoncés comme un problème de décision.

    En conséquence, le problème de la décision, c’est-à-dire la recherche d’une procédure qui indique dans chaque contexte, et au bout d’un temps fini, si une propriété est vraie ou fausse, est équivalent à la construction d’un algorithme qui calcule pour chaque fonction f et pour chaque argument x de f, la valeur y telle que y = f(x). Autrement dit, le problème de la décision est équivalent au problème du calcul.

    décidables ou indécidables?

    Les fonctions, ou propriétés bien énoncées1 en langages mathématique sont-elles toutes décidables? La reponse est : Non, il n’existe pas de telle méthode, comme cela a été démontré en 1931 par Kurt Gödel (voir plus haut).

    L’indecidabilité c’est l’impossibilité absolue et définitivement démontrée de résoudre par un procédé général de calcul un problème donné.

    Imaginons qu’il existe des programmes qui calculent si un programme termine. Ces programmes prendraient une fonction A comme paramètre, et une donnée x d’entrée de cette fonction.

    Si A s’arrête sur l’entrée x, le programme termine peut renvoyer True. Mais si ce n’est pas le cas, le programme ne répondra jamais. À quel moment décide-t-on qu’il n’a pas encore répondu, c’est qu’il ne répondra jamais ? On n’a aucun moyen de le faire, et c’est ce que prouve le théorème de Turing.

    decidabilité youtube

    Décidabilité et indécidabilité : Problème de l'arrêt | Rachid Guerraoui

    Exemple de problème non décidable :

    • Problème
    • Donnée : Un programme C.
    • Question : Le programme s’arrête-t-il toujours ?

    Preuve d’un algorithme

    terminaison et correction

    Prouver le bon fonctionnement d’un algorithme nécessite de vérifier deux propriétés :

    1. premièrement : la terminaison : prouver que l’algorithme se termine.
    2. deuxièmement : la correction : si l’algorithme se termine, il fait bien ce qu’on attend de lui (correction partielle).

    D’après ce qui a été vu auparavent, il n’EXISTE PAS d’algorithme capable de calculer la terminaison ou la correction d’un programme. Ce sera à vous de PROUVER un algorithme, à partir de méthodes exposées ici.

    méthodes pour les algorithmes itératifs

    Pour la terminaison : étude du VARIANT de boucle

    Il faudra exhiber, pour chaque boucle while, un VARIANT de boucle.

    Pour la correction :

    Exhiber un INVARIANT de boucle qui permet de montrer le résultat voulu.

    Invariant de boucle : on appelle invariant d’une itération toute propriété, vraie à l’initialisation, et qui demeure conservée quand on passe d’un état quelconque à son successeur.

    Algorithme recursif

    Dans le cas des algorithmes récursifs, ces méthodes sont spécifiques.

    terminaison

    Le (ou l’un des) paramètre(s) appelé(s) par la fonction recursive doit avoir une relation d’ordre descendante. C’est à dire que ce paramètre doit être de plus en plus petit à chaque appel de la fonction dans le corps de la fonction récurente.

    correction partielle

    Il faut montrer que si les appels internes à l’algorithme font ce qu’on attend d’eux, alors l’algorithme entier fait ce qu’on attend de lui. La preuve de correction se fait à partir d’une demonstration par recurrence :

    • On commence à établir la preuve pour le rang n = 0, puis n = 1.
    • il faut montrer que si on peut prouver la correction pour une suite de rang n-1, on aboutira à la preuve de correction pour une suite de rang n.

    Exemples

    Exemple 1: fonction somme

    Script

    La fonction suivante réalise la somme des termes d’une liste.

    def somme(L):
        s=0
        for k in range(len(L)):
            s = s + L[k]
        return s

    terminaison

    Le script contient une boucle bornée. La variable k augmente d’une unité à chaque itération. De k=0 jusqu’à len(L)-1. La boucle s’arrêtera lorsque k atteindra len(L) -1, ce qui arrivera forcement.

    correction

    On considère l’invariant de boucle énoncé ainsi : “pour un indice k, s est égal à la somme de L[:k]”. C’est à dire à:

    L[0] + L[1] + L[2] + … + L[k-1]

    • A l’entrée dans la boucle : s = 0. Ce qui est attendu puisque l’on n’a pas encore additionné le premier terme L[0].
    • Pour une valeur k. On suppose que s est egal à la somme des termes de L[:k-1]. Alors, à la ligne 4, on ajoute L[k] à s. Donc s est bien égal à la somme de L[:k].
    • A la fin de la boucle, k vaut len(L)-1, et c’est justement l’indice du dernier élément de la liste. s sort alors avec pour valeur la somme de TOUS les termes de la liste L. CQFD

    Exemple 2: Recherche dichotomique

    Definition

    La recherche dichotomique consiste à diviser par 2 l’ensemble de recherche. Pour cela, on définit le milieu de l’intervalle de recherche, puis on conserve:

    T[borne_inf : milieu] si T[milieu] > x
    T[milieu : borne_sup] si T[milieu] < x

    Exemple: On recherche un mot commençant par la lettre c dans le dictionnaire. Les lettres du dictionnaire sont dans l’ensemble [a .. z].
Il s’agit d’une liste [‘a’,‘b’,‘c’,’d’, ..’m’, ..,‘x’,‘y’,‘z’]. 
Comme il s’agit d’une liste dont les indices vont de 0 à 25: Le milieu, c’est 25//2 soit 12. la lettre c a un rang inférieur à 12 (lettre m). Donc, dans une première étape de recherche, on prendra la liste entre les rangs 0 et 12 pour rechercher c.

    def recherche_dicho(T,x):
        """
        :param T: sorted list of elements
        :param x: element
        :return: int, index of x in the list
               else -1
        """
        i_min = 0
        i_max = len(T) - 1
        while (i_max >= i_min):
            mid = (i_min + i_max)//2
            if T[mid] == x:
                return mid
            elif T[mid] < x:
                i_min = mid +1
            else:
                i_max = mid -1
        return -1

    Terminaison de la fonction de recherche dichotomique

    Dans le pire des cas, l’intervalle va se réduire jusqu’à se limiter à un seul élément. Celui dont l’index est mid. Avec i_min == i_max

    Si l’élément recherché est dans la liste: Cet élément est alors la valeur recherchée x, et la fonction se termine en retournant la valeur de l’index de x dans la liste, mid.

    Si l’élément recherché n’est pas dans la liste: alors, soit i_min prend la valeur de mid+1, soit i_max prend la valeur de mid-1. On a alors i_min > i_max, qui est la condition d’arrêt de la boucle.

    Efficacité de la recherche dichotomique

    Le nombre d’opérations de comparaison, dans le pire des cas, est proportionnel à log(N). N étant égal à la taille de la liste. Et log(N) étant egal au nombre de divisions par 2 qu’il faut effectuer pour que N arrive à 1:

    100 -> 50 -> 25 -> 13 -> 7 -> 4 -> 2 -> 1 (6 à 7 divisions)

    On dit que la complexité est logarithmique.

    Preuve de correction

    voir le document sur eduscol.education.fr, pages 4 et 5: [eduscol.education.fr/document/30064/download]((https://eduscol.education.fr/document/30064/download)

    Résumé

    • Un Problème: Ensemble Nom + Données d’entrée + Question
    • Pour la suite: Problème = Fonction
    • L’ensemble des algorithmes, donc des fonctions calculables, est dénombrable. Un algorithme est une approche étape par étape pour résoudre un problème.
    • L’ensemble des fonctions est indénombrable, donc il existe des fonctions incalculables.
    • Calculable: il existe une fonction f programmable dans un langage courant (python)
    • Calculable = Décidable: un problème calculable peut être traduit en un problème équivalent décidable. La différence est que, pour un problème calculable, on doit calculer une image f(x), alors que pour un problème décidable, la fonction retourne une valeur booléenne (True,False). Le problème est exprimé différemment.
    • Indécidable (ou incalculable): c’est l’impossibilité définitivement démontré de résoudre par un algorithme un problème donné.
    • Le problème de l’arrêt est un exemple de fonction incalculable.
    • L’étude de la terminaison d’une fonction est liée à l’étude de sa complexité. Il faut pouvoir évaluer si un problème décidable, l’est en un temps raisonnable.
    • Il n’existe pas de programme permettant de savoir si une fonction termine, et si elle fait bien ce qui est attendu d’elle. C’est pour cela qu’il faudra savoir prouver une fonction. Pour cela, il faudra:
      • démontrer que la fonction termine. On s’aide souvent d’un VARIANT de boucle.
      • démontrer la correction de cette fonction, c’est à dire qu’elle fait bien ce que l’on attend d’elle. On s’aide souvent d’un INVARIANT de boucle.

    Liens : généralités

    Liens pour approfondir

    Notes


    1. ceci fait reference au theoreme de completude énoncé par Gödel. Une théorie mathématique pour laquelle tout énoncé est décidable est dite complète, sinon elle est dite incomplète. D’où le Premier Théorème d’incomplétude de Gödel “Dans n’importe quelle théorie récursivement axiomatisable, cohérente et capable de « formaliser l’arithmétique », on peut construire un énoncé arithmétique qui ne peut être ni prouvé ni réfuté dans cette théorie. Il n’existe donc aucune théorie mathématique complète.” (Premier Théorème d’incomplétude de Gödel) ↩︎

    langages

    Paradigmes des langages

    Impératif

    Fonctionnel

    on ne trouve ni affectation (ou assignation), ni séquence (succession inconditionnelle de deux instructions).

    Récursif

    Objet

    Sous-sections de langages

    langages mathematiques

    Langages mathematiques

    Pourquoi 1 + 1 = 2 ?

    Pour comprendre cette opération, il faut déjà comprendre la signification de chacun des symboles utilisés, les chiffres 1 et 2, et les opérateurs + et =

    • 1
    • +
    • =
    • 2

    Ainsi, pour apprendre à compter à une machine, il faudra lui expliquer comment les nombres se succèdent, et quel rôle jouent chaque opérateur sur ces nombres.

    Les chiffres

    Les symboles des chiffres nous sont ainsi intuitifs, mais, dans l’idée d’une construction du langage mathématique, il doit exister une règle qui nous dit:

    • que le successeur immédiat de 1, dans l’ensemble des entiers naturels, est le 2 et non le 3. (et qu’il existe aussi la notion de predecesseur)
    • que le plus petit des entiers naturels est le 0

    Cet article du site automaths détaille ainsi la construction de l’ensemble des entiers naturels par des axiomes.

    Comment sont placés les successeurs pour

    Comment sont placés les successeurs pour

    Giuseppe Peano (1858-1932) est un mathématicien et linguiste italien. Il a repertorié les caractéristiques structurelles des nombres naturels dans une liste d’axiomes énoncés dans la symbolique logique. Aujourd’hui, ces axiomes constituant le langage mathématique traitent tous les signes mathématiques et logiques, et jouent un rôle analogue à celui de la grammatisation dans les langues naturelles.

    Giuseppe Peano (1858-1932)

    Giuseppe Peano (1858-1932)

    Une fois établie la construction de l’ensemble des entiers naturels selon Peano, nous allons nous intéresser aux axiomes définissant les symboles + et =.

    l’égalité, ou l’identité =

    L’identité est définie par 2 propriétés:

    • a = b, b = c → a = c
    • a1 = a2 → f(a1) = f(a2)

    l’addition +

    Voir l’article Qu’est-ce que ça veut dire additionner ? du site automaths.

    On y lira que 0 + 1 = 1 est l’un des axiomes définissant l’addition, et s’écrit en langage axiomatique:

    $$0 + S_0 = S_0$$
    L'addition: la réunion de 2 ensembles

    L'addition: la réunion de 2 ensembles

    Questions

    • Q1: Qui était Giuseppe Peano et qu’a-t-il cherché à montrer à propos des entiers naturels?
    • Q2: Qui était le mathématicien Kurt Gödel, et qu’a-t-il apporté à la théorie sur le langage mathématique initiée par Giuseppe Peano? En particulier, ce que l’on appelle la complétude d’un système d’axiomes ?
    • Q3: A quoi peut-on comparer un axiome mathématique? Y-a-t-il quelque chose d’équivalent dans les langues naturelles?
    • Q4: Qu’est ce que l’addition +?
    • Q5: Qu’est ce que l’égalité =? Commenter les 2 propriétés qui la définissent.

    Conclusion

    Les mathématiques sont formées:

    • d’un ensemble de valeurs, comme par exemple l’ensemble des entiers naturels $\mathbb{N}$
    • de relations entre les éléments de cet ensemble. Comme par exemple la relation de successeur vue plus haut.
    • de règles sur ces valeurs. Ces règles définissent les opérateurs sur ces valeurs.

    Dans le chapitre suivant, on verra que l’on peut créer un langage mathématique pour le traitement de l’information.

    Calcul propositionnel

    On va avoir besoin d’ajouter aux ensembles de nombres un nouvel ensemble particulier: un ensemble contenant 2 éléments contenant les valeurs de verité vrai / faux. Cela nous permettra d’utiliser des machines pour automatiser le raisonnement. C’est à dire pour produire des démonstrations, et ainsi de prouver des propositions.

    Le calcul propositionnel est un ensemble de règles permettant un nombre fini d’étapes pour démonter si une proposition est VRAIE ou FAUSSE.

    Les Propositions contiennent des affirmations telles que:

    • le moteur est en marche
    • la vanne de sécurité est ouverte
    • la cuve fuit, etc…

    On remplace ces affirmations par des symboles neutres, qui prennent l’un des 2 états: VRAI ou FAUX. Cet état est choisi pour établir une certaine cohérence avec l’information à traduire du monde exterieur (moteur en marche = VRAI, …)

    Les propositions vont combiner ces affirmations à l’aide d’opérateurs logiques. Cela va constituer une formule.

    Une propriété faisant intervenir n éléments offre $2^n$ interprétations envisageables.

    La formule doit prendre les valeurs VRAI pour toutes les interprétations de l’énoncé.

    Dans ce paragraphe, on étudie les propositions en tant que telles, et les liens qui peuvent exister entre elles, sans se préoccuper du contenu de ces propositions.

    On rappelle qu’une proposition est un énoncé pouvant être Vrai ou Faux. On dit alors que les deux valeurs de vérité d’une proposition sont « vrai » et « faux ».

    Equivalence logique

    Définition

    Deux propositions équivalentes P et Q sont deux propositions ayant les mêmes valeurs de vérité.

    Cette phrase peut se visualiser dans un tableau appelé table de vérité dans lequel on fait apparaître les différentes valeurs de vérité possibles pour le couple (P, Q) (Vrai et Vrai, Vrai et Faux, …) et, en correspondance, les valeurs de vérité de la proposition P ⇔ Q. Ainsi, la table de vérité de l’équivalence logique P ⇔ Q est :

    P Q P <=> Q
    F F V
    F V F
    V F F
    V V V

    On peut ainsi lire, deuxième ligne, que si P est vraie et Q est fausse, P ⇔ Q est fausse. L’équivalence logique joue pour les propositions, le rôle que joue l’égalité pour les nombres. Les expressions 3 + 2 et 5 ne sont pas identiques et pourtant on écrit 3+2 = 5. De même, les propositions (x2 = 1) et (x = 1 ou x = −1) ne sont pas identiques et pourtant on écrit (x2 = 1) ⇔ (x = 1 ou x = −1).

    Implication

    Definition

    Si P et Q sont deux propositions, on définit l’implication logique : P ⇒ Q par sa table de vérité.

    P Q P => Q
    F F V
    F V V
    V F F
    V V V

    P et Q deux propositions. (P ⇒ Q) ⇔ (nonP ∨ Q). P ⇒ Q est fausse dans l’unique cas où P est vraie et Q est fausse: si P (est vraie) alors forcément Q (est vraie aussi). Mais pas réciproquement.

    Exemple: Lorsque le facteur dépose une lettre, le chien aboie. Parmi les interprétations envisageables pour cet énoncé, il se peut que le chien aboie alors que le facteur n’a PAS deposé de lettre.

    Négation d’une proposition

    Soit P une proposition. On définit sa négation, notée nonP (ou ⌉P), à partir de sa table de vérité.

    P nonP
    V F
    F V

    Exemple: Je ne lave pas mon linge (nonL ou -L) s’il pleut (P)

    On peut exprimer cette proposition à partir des affirmation L (je lave mon linge) et P (il pleut), à l’aide de l’opérateur implication => :

    $$P \Rightarrow -~L$$

    Les connecteurs logiques « ET » et « OU »

    Soient P et Q deux propositions. On peut définir les propositions « P ou Q », notée P ∨ Q, et « P et Q », notée P ∧ Q par les tables de vérité ci-dessous.

    P Q P ∧ Q P ∨ Q
    F F F F
    F V F V
    V F F V
    V V V V

    Remarque: Le connecteur logique OU n’a pas le sens du OU exclusif. En effet, on peut voir que lorsque P est vraie et Q est vrai, alors P∨Q est vraie

    Combinaisons de propositions

    Tout énoncé peut s’écrire en utilisant uniquement la conjonction ∧ et la négation (par exemple, P ⇔ Q est la proposition non(P ∧ nonQ) ∧ non(Q ∧ nonP)). Ce résultat a une importance en électronique et en informatique.

    Un problème mathématique

    En classe de mathématiques, un problème mathématique comprend un énoncé (la description d’un situation) suivi d’une ou plusieurs questions. Il est généralement demandé pour répondre aux questions posées d’effectuer des calculs avec les données contenues dans l’énoncé.

    Toute question ne peut pas forcément s’énoncer dans un langage mathématique.

    En informatique, pour un problème donné, on cherche à trouver une procédure pour le résoudre. On doit pouvoir traiter cette procédure à l’aide d’une machine. Si cette procedure existe, et si le nombre d’actions réalisées par la machine n’est pas infini, alors le problème peut être résolu. (fonction calculable selon les données de l’énoncé).

    Exercices sur les procédures de calcul

    Ex 1: Trouver une procédure pour calculer 2 + 3

    On utilisera uniquemement les propositions suivantes:

    • les entiers naturels s’expriment selon la théorie axiomatique vue en classe: SS0 succede à S0 qui succede à 0…
    • définitions axiomatique de l’addition
    • variables

    On considère qu’il existe une fonction d’affichage

    Ex 2: Trouver une procédure pour calculer 3 - 2

    Mêmes outils que pour l’exercice 1. La relation de prédecesseur est également connue.

    Exercices sur le calcul propositionnel

    Exercice 1: Le Soleil brille

    En utilisant les affirmations S (le soleil brille), P (il pleut), B (il bruine), A (il y a un arc en ciel), O (il a un vent d’Ouest), E (il y a du vent d’Est), traduire dans la logique des propositions suivantes:

    1. La bruine est une forme de pluie.
    2. S’il pleut et que le soleil brille en même temps, alors il y a un arc en ciel.
    3. Si le vent d’ouest amène la pluie, on n’a jamais vu qu’un vent d’est soit porteur de pluie.

    Exercice 2:

    Représenter dans le formalisme de la logique des propositions les théorèmes de géométrie suivants:

    1. Si un triangle est équilatéral alors il est isocèle.
    2. Un triangle rectangle n’est jamais équilatéral. Un carré est à la fois un parallélogramme et un rectangle.
    3. Un losange n’est ni un quadrilatère rectangle ni un triangle.

    Exercice 3:

    Lors de ses aventures au pays des merveilles rapportées par Lewis Carroll, Alice est souvent accompagnée par le chat de Cheshire. Ce félin énigmatique s’exprime sous la forme d’affirmations logiques qui sont toujours vraies. Alice se trouve dans un corridor dont toutes les portes à sa taille sont fermées. La seule porte ouverte est nettement trop petite pour qu’elle puisse l’emprunter. Une étagère est fixée au-dessus de cette porte. Le chat dit alors à Alice: «L’un des flacons posés sur cette étagère contient un liquide qui te permettra de prendre une taille plus adéquate. Mais attention, les autres flacons peuvent contenir un poison fatal.»

    Trois flacons sont effectivement posés sur l’étagère. Le premier est rouge, le second jaune, le troisième bleu. Une étiquette est collée sur chaque flacon. Alice lit l’inscription figurant sur chaque étiquette:

    • Flacon rouge: le flacon jaune contient un poison; le bleu n’en contient pas;
    • Flacon jaune: si le flacon rouge contient un poison, alors le bleu aussi;
    • Flacon bleu: je ne contiens pas de poison.

    Nous noterons R, J et B les variables propositionnelles correspondant au fait que les flacons rouge, jaune et bleu contiennent un poison.

    Nous noterons $I_R$, $I_J$ et $I_B$ les propositions correspondant aux inscriptions sur les flacons rouge, jaune et bleu.

    On résoudra les questions suivantes en utilisant une table de vérité.

    Exprimez les formules $I_R$, $I_J$ et $I_B$ sous la forme de formules dépendant de R, J et B.

    1. Les inscriptions sur les trois flacons sont-elles compatibles?
    2. Si les trois inscriptions sont vraies, est-ce qu’un ou plusieurs flacons contiennent un poison?
    3. Dans le cas où aucun des trois flacons ne contient un poison, est-ce qu’une ou plusieurs inscriptions sont fausses?

    Enoncé d’origine (issu du site emse.fr

    • Flacon rouge: le flacon jaune contient un poison; le bleu n’en contient pas;
    • Flacon jaune: si le flacon rouge contient un poison, alors le bleu aussi;
    • Flacon bleu: je ne contiens pas de poison, mais au moins l’un des deux autres si.

    Compléments sur les Mathématiques

    • notes issues d’un cours d’Université math.UNICE

    Les mathématiques actuelles sont bâties de la façon suivante :

    • on part d’un petit nombre d’affirmations, appelées axiomes, supposées vraies à priori (et que l’on ne cherche donc pas à démontrer) ;
    • on définit ensuite la notion de démonstration (en décidant par exemple de ce qu’est une implication, une équivalence…) ;
    • on décide enfin de qualifier de vraie toute affirmation obtenue en fin de démonstration et on appelle « théorème » une telle affirmation (vraie). A partir des axiomes, on obtient donc des théorèmes qui viennent petit à petit enrichir la théorie mathématique. En raison des bases (les axiomes) non démontrées, la notion de « vérité » des mathématiques est sujette à débat.

    Axiome. Un axiome est un énoncé supposé vrai à priori et que l’on ne cherche pas à démontrer. Ainsi, par exemple, Euclide a énoncé cinq axiomes (« les cinq postulats d’Euclide »), qu’il a renoncé à démontrer et qui devaient être la base de la géométrie (euclidienne). Le cinquième de ces axiomes a pour énoncé : « par un point extérieur à une droite, il passe une et une seule droite parallèle à cette droite ».

    Aujourd’hui, ces axiomes constituant le langage mathématique traitent tous les signes mathématiques et logiques, et jouent un rôle analogue à celui de la grammatisation dans les langues naturelles.

    Proposition (ou assertion ou affirmation). Une proposition est un énoncé énoncé auquel on peut attribuer une valeur de vérité vrai ou faux. Par exemple, « tout nombre premier est impair » et « tout carré de réel est un réel positif » sont deux propositions. Il est facile de démontrer que la première est fausse et la deuxième est vraie. Le mot proposition est clair : on propose quelque chose, mais cela reste à démontrer. Une proposition est construite à partir des axiomes du langage.

    Théorème. Un théorème est une proposition vraie (et en tout cas démontrée comme telle). On utilise aussi en informatique le terme d’assertion pour une proposition vraie.

    Définition: souvent équivalent à axiome

    Conjecture: proposition que l’on suppose vraie sans parvenir à la démontrer. (et qu’il est peut être impossible de démontrer).

    Voici la liste des plus célèbres conjectures Pour exemple, la conjecture de Goldbach

    Tout nombre entier pair supérieur à 3 peut s’écrire comme la somme de deux nombres premiers.

    Illustration de la

    Illustration de la

    Liens

    recursivité

    Le cours comprend:

    Récursivité

    Principe

    Un algorithme récursif est un algorithme qui fait appel à lui-même dans le corps de sa propre définition. Ce principe est aussi appelé : de l’autoréférence. (traité dans la partie autres applications de la page 2 du cours).

    Cependant, cette premiere definition pourrait faire penser qu’une fonction récursive va s’appeler indéfiniment, et créer sans arrêt les mêmes figures, ou les mêmes traitements.

    Ce n’est pas tout à fait cela.

    Pour une fonction récursive, il y a plus que de la simple autoréférence:

    • Il y a transmission de valeurs entre 2 étapes de la pile d’appels recursifs.
    • Une valeur va remonter d’un niveau $n$ vers le niveau $n-1$ qui l’a appelé.
    • On remonte la pile d’appels parce que la fonction contient une condition de fin (appelée condition de base).
    • enfin, les traitements ne sont pas tous identiques parce les arguments de la fonction changent à chaque nouvel appel recursif.

    Analyse d’un exemple: itératif => récursif

    Considérons une fonction ajoute2_iter qui prend N comme paramètre, et qui ajoute N fois 2.

    Algorithme itératif

    Supposons que nous souhaitions éviter la multiplication. L’algorithme itératif utilisera alors une boucle bornée:

    def ajoute2_iter(N):
      """ajoute 2 un nombre N de fois
      """
      s = 0
      for i in range(N):
        s = s + 2
      return s

    Résultat

    >>> ajoute2_iter(4)
    8

    Algorithme récursif

    Rappel de math: Une suite est une succession ordonnée d’éléments, comme par exemple 1, 2, 4, 8, 16. On s’interesse ici à une suite en définissant un terme à l’aide du terme précédent. (suite récurente)

    exemple de duite recursive, exprimée en langage mathématique

    exemple de duite recursive, exprimée en langage mathématique

    (a) Pour calculer le terme de rang n d’une suite, on définit un cas de base, un démarrage avec le premier terme de la suite:

    $$u_0 = 0$$

    Dans la fonction, ce demarrage vient avec le système d’instructions:

      if N==0 : 
            return 0

    (b) Puis vient la relation de récurence sur les éléments de la suite $u_n$:

    $$u_{n+1} = 2 + u_n$$

    ou encore:

    $$u_{n} = 2 + u_{n-1}$$

    On va adapter cette dernière relation dans l’appel de la fonction: return 2 + ajoute2(N-1)

    Le script entier est alors:

    def ajoute2(N):
        """fonction qui s'appelle elle-meme N fois
        """
        if N==0 : 
            return 0
        else:
            return 2 + ajoute2(N-1)

    Résultat

    >>> ajoute2(4)
    8

    Une pile d’appels

    ajoute2(4) = 2 + ajoute2(3)
        ajoute2(3) = 2 + ajoute2(2)
            ajoute2(2) = 2 + ajoute2(1)
                ajoute2(1) = 2 + ajoute2(0)
                    ajoute2(0) = 0

    Cette succession d’appels peut se resumer par une pile d’appels, où les éléments sont mis de bas en haut, les uns après les autres lors des appels recursifs successifs:

    | ajoute2(0) |
    | ajoute2(1) |
    | ajoute2(2) |
    | ajoute2(3) |
    | ajoute2(4) |

    Puis, après le return 0, la valeur 0 est retournée à ajoute2(1) = 2 + 0, qui retourne 2. La valeur 2 est retournée à ajoute2(2). Au cours de cette descente dans la pile, les éléments sont traités de haut en bas.

    | ajoute2(0) |
    | ajoute2(1) |      | ajoute2(1) |
    | ajoute2(2) |  ->  | ajoute2(2) |  -> ...
    | ajoute2(3) |      | ajoute2(3) |
    | ajoute2(4) |      | ajoute2(4) |

    A la fin, ajoute2(4) = 2 + 2 + 2 + 2 + 0 = 8

    Principe d’un algorithme récursif

    L’algorithme récursif comprend 2 parties importantes:

    • La Base : c’est le cas pour lequel le problème se resoud immediatement, par exemple :
      if N==0 : 
            return 0

    dans le script ajoute2: le problème se resoud immediatement pour N == 0).

    • L’Hérédité : calcul à partir de paramètres plus “petits” : return 2 + ajoute2(N-1).

    Une définition plus générale serait que, pour l’hérédité, il y a un appel recursif avec un argument qui se rapproche plus de la condition de base. (pour la terminaison).

    def fonction_recursive(param):
      if <cas de base> : 
        return value
      else:
        # instructions
        fonction_recursive(f(param))

    Remarque: Une instruction conditionnelle est incluse dans le corps de la fonction pour forcer la fonction à retourner sans que l’appel de récurence soit exécuté (La Base). Sans cela, le programme pourrait tourner en boucle…

    Comparatif itératif - récursif

    Une grande partie des problèmes peut se résoudre avec une implémentation récursive, comme avec une implémentation itérative. L’une ou l’autre peut paraître plus ou moins naturelle suivant le problème, ou suivant les habitudes du programmeur.

    Itératif Récursif
    Principe Permet d’executer plusieurs fois l’ensemble des instructions La fonction s’appelle elle-même
    Format L’itération comprend l’initialisation, la condition, l’exécution de l’instruction dans une boucle et la mise à jour (incrémenter et décrémenter) la variable de contrôle. Seule la condition de terminaison est spécifiée.
    Terminaison L’instruction d’itération est exécutée plusieurs fois jusqu’à ce qu’une certaine condition soit atteinte. Si la fonction ne converge pas vers une condition appelée (cas de base), elle conduit à une récursion infinie.
    Taille du script L’itération rend le script plus long Taille du script réduite

    Enfin, l’algorithme récursif utilise une pile d’appels, comme vu sur l’animation suivante:

    animation recursivité additions successives

    animation issue de l'application pythontutor

    Il est facile de traiter des suites avec la méthode récursive:

    • factorielle
    • suite de Fibonacci.

    exemple : factorielle

    programme itératif

    def fact(n):
      res = 1
      for i in range(1,n+1):
        res=res*i
      return res 

    a. terminaison : l’algorithme consiste en une boucle qui execute n itérations.

    • Le convergent n-i decroit strictement à chaque itération et on sort de la boucle quand il vaut 0.
    • Chaque iteration contient un nombre fini d’opérations élémentaires : 1 mutiplication et 1 affectation. Donc il termine après 2n+1 operations.

    b. correction : On prouve par recurrence sur le nombre d’iterations qu’apres la ieme iteration de la boucle for : res=i! Preuve par récurrence :

    • après la 1ere itération, res = 1 ! (OK)
    • Hypothèse de récurrence : (H.R.) supposons qu’après la ieme itération, res=i ! Montrons qu’après la (i+1)ieme iteration, res=(i+1)! :
    • avant la (i+1)e iteration, res = i !
    • La (i+1)e iteration multiplie res par i+1, donc après la (i+1)e iteration, $res= i! \times (i+1) = (i+1)!$
    • Après n iterations, res contient n ! donc le resultat est celui attendu.

    Programme recursif

    On a la relation de récurence suivante:

    $$u_n = n \times u_{n-1}$$

    La relation d’heredité est alors return n*fact_recur(n-1)

    Le premier terme est:

    $$u_0 = 1$$

    et le script de la fonction recursive:

    def fact_recur(n):
      if (n==0) :return 1 else: return n*fact_recur(n-1)

    On pourrait représenter la pile d’execution de cette fonction de la manière suivante :

    Appel à fact_recur(4)
    | 4*fact_recur(3) = ? 
    | Appel à fact_recur(3)
    | | 3*fact_recur(2) = ? 
    | | Appel à fact_recur(2)
    | | | 2*fact_recur(1) = ? 
    | | | Appel à fact_recur(1)
    | | | | 1*fact_recur(0) = ? 
    | | | | Appel à fact_recur(0) 
    | | | | Retour de la valeur 1
    | | | | 1*1
    | | | Retour de la valeur 1
    | | | 2*1
    | | Retour de la valeur 2
    | | 3*2
    | Retour de la valeur 6
    | 4*6
    Retour de la valeur 24

    Dans le cas d’un algo recursif, pas de convergent ni d’invariant de boucle. On prouve par recurrence sur n.

    a. Teminaison: si n=0, fact(0) fait un test et renvoie 1, sans appel recursif.

    Hypothèse de récurrence: fact(n) termine après n appels recursifs. Montrons que fact(n+1) termine après (n+1) appels recursifs:

    • fact(n+1) fait un test n+1>0 donc on passe au else puis on appelle fact(n) par recurrence qui termine apres n appels recursifs. Finallement fact(n+1) termine après (n+1) appels recursifs.

    b. correction: par recurrence fact(n) = n ! :

    • pour n = 0 : fact(n) = fact(0) = 1 = 0! (OK)
    • si vrai pour n, alors $fact(n+1) = (n+1)*fact(n)$ et par hyp H.R., $fact(n) = n!$ donc $(n+1)*n! = (n+1)!$ (OK)

    Complexité

    Calcul de la complexité : Soit T(n) le nombre d’opérations fondamentales. Pour une fonction récurrente, c’est le nombre de résolution de la fonction de récurence. On a T(n) = T(n-1) + 1 donc T(n) = n

    Analyser un algorithme récursif

    Preuve de correction d’un algorithme récursif

    Alan Turing (1912 – 1954) énonce ainsi son principe d’indéciablité de la terminaison d’un algorithme(1936): L’indecidabilite c’est l’impossibilité absolue et définitivement démontrée de résoudre par un procédé général de calcul un problème donné.

    La terminaison, ainsi que la correction ou la complexité doivent être prouvées par des arguments mathématiques.

    • terminaison : recherche du convergent
    • correction / validité : recherche de l’invariant de boucle pour démontrer sa (non) variation selon un argument de recurence
    • puis finir en montrant que l’invariant de boucle ou bien le resultat obtenu repond bien à la specification de l’algorithme

    Complexité d’un algorithme recursif

    Pour un algorithme récursif, on compte le nombre d’appel récursif et il suffit en général de se ramener à une relation définissant une suite récurente. On se ramène souvent à évaluer une relation du type :

    $$T_n = a \times T_{f(n)} + T$$

    où :

    • $T_n$ est la complexité pour une donnée de taille n ; a est le nombre d’appel récursif ;
    • f(n) décrit la variation de n dans l’appel récursif;
    • T est la complexité des calculs hors appel récursif.
    relation de récurrence sur T solution comportement asymtotique
    T(n) = T(n-1) + b T(n) = T(0) + b×n (somme de termes constants) O(n)
    T(n) = a×T(n-1) + b, a ≠ 1 $T(n) = a^n × (T(0) – b/(1-a)) + b/(1-a)$ (suite géométrique) $O(a^n)$
    T(n) = T(n-1) + a×n + b T(n) = T(0) + a×n×(n+1)/2 + n×b (suite arithmetique pour le 2e terme) $O(n^2)$
    T(n) = T(n/2) + b $T(n) = T(1) + b×log_2 (n)$ $O(log_2 n)$

    Application 1: suite de Fibonacci

    La suite de Fibonacci est une suite récurente d’ordre 2: On calcule l’un de ses termes à l’aide des deux termes précédents.

    Définitions

    Fibonacci était le surnom de Léonard de Pise (1170 -1250) . Il a posé un problème dans lequel il cherche à calculer le nombre de couples de lapins au bout de n années, lorsqu’ils se reproduisent selon les règles suivantes :

    • Lors de la première année, l’éleveur démarre avec un couple de lapins nouveaux nés.
    • Un couple de lapins donne naissance à un nouveau couple tous les ans, à partir de la 2ème année (la 1ère année, il est trop jeune).

    On peut compléter le tableau suivant présentant l’effectif de ces couples de lapins :

    numero de l’année nombre de couples de l’année précédente nouveau nombre de couples
    0 0 0
    1 0 1
    2 1 1 + 0 = 1
    3 1 1 + 1 = 2
    4 2 2 + 1 = 3
    5 3 3 + 2 = 5
    6 … …

    On définit la suite ($f_n$) des nombres de Fibonacci par :

    $$\left\\{\begin{matrix}\begin{align}f\_0 & =0\\\f\_1 & =1\\\f\_{n+1} & =f\_{n}+f\_{n-1}, \forall n \in \mathbb{N}^+\end{align}\end{matrix}\right.$$

    Les nombres de Fibonacci apparaissent aussi dans la croissance des plantes. Le nombre de pétales des différentes fleurs est souvent un nombre de la suite de Fibonacci. On remarque que l’ angle entre deux primordia successifs, tend vers L’ANGLE D’OR, et que plus les nombres successifs sont grands, plus le rapport s’approche du NOMBRE D’OR.

    Algorithme itératif

    def fibonacci(n) :
        """
        fonction qui prend en paramètre n, entier sup ou egal à O.
        cette fonction utilise une variable f de type tableau.
        A la fin, cette fonction retourne f[n], le terme de rang n du 
        tableau f qui contient les éléments entiers calculés selon l'algorithme 
        de fibonacci où l'élement de rang i est la somme des elements i-1 et i-2.
        """
        f = []
        f.append(0)
        f.append(1)
        if n<2:return f[n]
        for i in range (2,n+1): 
            f.append(f[i-1] + f[i-2])
        return f[n]

    Exercice : Ecrire un programme qui permet d’afficher tous les nombres de la suite de Fibonacci, du rang 0 au rang n=10.

    Algorithme récursif

    def fibo(n):
        """
        algo recursif
        """
        if (n==0) : return 0
        if (n==1) : return 1
        return fibonacci(n-1) + fibonacci(n-2)

    Parfois, l’algorithme récursif n’est pas le plus performant: Pour l’exemple de la suite de Fibonacci, on constate que les mêmes calculs sont répétés plusieurs fois, comme fibo(2) dans le cas présent pour N = 4):

    pile d'appels pour la suite de fibonacci recursive

    pile d'appels pour la suite de fibonacci recursive

    Application 2: recherche du PGCD

    La méthode de recherche du PGCD utilise aussi une suite récurente d’ordre 2: On calcule l’un de ses termes à l’aide des deux termes précédents.

    Problème

    Etant donné deux entiers naturels n et m, calculer leur pgcd (plus grand commun diviseur)

    algorithme d’Euclide

    Euclide propose l’algorithme suivant:

    1. Calculez le reste r dans la division de a par b
    2. Si r est nul alors le pgcd est b
    3. Sinon recommencer l’étape 1 avec a = b et b = r

    Exemple d’exécution : a = 32, b = 12 :

    – 32 = (2 x 12) + 8

    – 12 = (1 x 8) + 4

    – 8 = (2 x 4) + 0

    On a donc pgcd(32, 12) = 4

    La page dédiée sur wikipedia propose une illustration géométrique de cette méthode. Un couple d’entiers est vu comme un rectangle, dont le PGCD est la longueur du côté du plus grand carré permettant de carreler entièrement ce rectangle:

    Explication géométrique de l'algorithme d'Euclide sur les entiers 21 et 15. - source wikipedia

    Explication géométrique de l'algorithme d'Euclide sur les entiers 21 et 15. - source wikipedia

    Algorithme PGCD itératif

    def euclide(a,b):
        """
        a et b sont des entiers, a > b
        euclide retourne un entier qui est le PGCD de a et b
        """
        r = a % b
        while r>0 :
            a = b
            b = r
            r = a % b
        return b

    Preuve de l’algorithme itératif

    a. Terminaison : on utilise une boucle non bornée avec y qui est le convergent. On affecte à y le reste de la division par y (c’est donc inferieur à y). y décroit ainsi jusqu’à 0, ce qui est la condition de fin de la boucle.

    b. Correction : Tout diviseur commun de a et b divise aussi r = a - bq, et réciproquement tout diviseur commun de b et r divise aussi a = bq + r. Donc le calcul du PGCD de a et b se ramène à celui du PGCD de b et r. l’invariant de boucle, c’est donc : euclide(a,b) = euclide(b, a modulo b)

    C’est ce qui est réalisé par la fonction, puisque l’on a comme valeurs pour les couples (x,y) successivement :

          (a,b)
          (b, a mod b)
          (a mod b, (a mod b) mod (a mod b))...
          (* , 0)

    algorithme recursif

    Le PGCD d’Euclide calcule une suite définie par une récurence à 2 termes:

    $r_0 = a$

    $r_1 = b$

    $r_2 = r_0 \\% ~r_1$

    $r_{n+1} = r_{n-1} \\% r_n$

    def PGCD(a,b):
      """
      PGCD : entier correspondant au plus grand diviseur commun de a par b
      a et b : entiers tels que a > b
      """
      if b == 0 : return a
      else:
        r = a % b
        return PGCD(b,r)

    Suite du cours

    Aller à la page 2 du cours.

    La récursivité intervient aussi dans de nombreux problèmes où elle s’impose comme la méthode la plus adaptée, pour ne pas dire la seule. Un exemple historique est celui des tours de Hanoi. Un jeu inventé par Edouard Lucas, vers 1880. Son traitement sur ordinateur a fait sensation, grâce à la simplicité de son script récursif…

    Exercices

    Ex 1 :

    On place un capital exprimé en euros égal à $w_0 = 1500$ avec un taux d’intérêt égal à 4,5% par an et on note $w_n$ le capital obtenu au bout de n années.

    1. Exprimer $w_n$ en fonction de $w_{n-1}$.
    2. Ecrire le script récursif d’une fonction capital qui calcule le montant du capital à l’année n. Cette fonction aura pour paramètres n et t, le taux d’interêt.
    3. Calculer grâce à cette fonction la valeur du capital au bout de 10 ans.
    4. Au bout de combien d’années le capital initial aura-t-il doublé ?

    Exercice adapté de la page bibmath.net

    Ex 2 : Dessin recursif

    Soit la relation de recurence suivante:

    $$u_{n+1} = \tfrac{8u_n}{9} + \tfrac{1}{9}$$

    Le premier terme de la suite est $u_0 = 0$

    Script python

    Ecrire en python le script de la fonction recursive correspondante, qui calcule au rang n le nombre $u_n$. Appeler cette fonction f.

    Application géométrique

    On considère un carré de côté 1. On le partage en 9 carrés égaux, et on colorie le carré central. Puis, pour chaque carré non-colorié, on réitère le procédé. On note $u_n$ l’aire coloriée après l’étape n. La suite $u_n$ est $u_{n+1} = \tfrac{8u_n}{9} + \tfrac{1}{9}$

    Quelle est la limite de la suite $u_n$?

    Exercice adapté de la page bibmath.net

    Ex 3 : longueur d’une liste

    algorithme itératif :

    La fonction suivante calcule la longueur d’une chaine de caractères seq passée en argument.

    def len_iterative(seq): 
        """
        Return the length of a list (iterative) 
        """
        count = 0
        for elt in seq:
            count = count + 1 
        return count

    Réaliser la preuve de cet algorithme.

    algorithme récursif

    a. Montrer que la relation de récurence $u_{n+1} = 1 + u_n$ permet de compter de 1 en 1.

    b. Soit la chaine de caractères s = "abcd". On veut supprimer le premier caractère de s à l’aide d’un slice python. Quelle est l’instruction python correspondante?

    c. Ecrire le script python de l’algorithme récursif

    Aide pour l’écriture de l’algorithme recursif : la fonction récursive s’appelera len_recursive, et aura pour argument seq. Si on veut passer en argument la liste seq de laquelle on retire le premier élément, on fait : len_recursive(seq[1:]). Il faudra alors s’inspirer de la relation de récurence suivante lors de l’appel recursif:

    $$u_{n+1} = 1 + u_n$$

    Ex 4 : Exponentiation

    Etudions l’exponentiation à travers deux exemples.

    def exp1(n,x) : 
      """
      programme qui donne x^n en sortie sans utiliser **
      n : entier
      x : reel
      exp1 : reel
      """
      acc=1
      for i in range(1,n+1):
        acc*=x
      return acc
    
    def exp2(n,x):
        """
        n : entier
        x : reel
        exp2 : reel
        """
        if n==0 : return 1
        else : return exp2(n-1,x)*x
    1. Combien de produits sont necessaires pour calculer une puissance n-ième avec la fonction exp1 ?
    2. Pour la fonction exp2 : Soit $u_n$ le nombre de produits nécessaires pour calculer une puissance n-ième. Quelle est la relation de récurrence vérifiée par $u_{n+1}$ ? $$u_{n+1} = u_n + ...$$
    3. En déduire la complexité pour chacune de ces 2 fonctions.

    Ex 5: dichotomie recursif

    la méthode de dichotomie pour calculer la racine d’une fonction. Soit une fonction f : R → R continue, dont on sait qu’elle a une racine et une seule sur un intervalle [a, b]. On cherche une valeur approchée de cette racine. voir figure ci-dessous

    principe de la dichotomie

    principe de la dichotomie

    Soit c = (a + b)/2, qui divise l’intervalle initial en deux parties égales. On calcule f(c) et on compare son signe à f(a) et f(b). La racine est nécessairement dans le sous-intervalle aux bornes duquel la fonction f prend deux valeurs de signes opposés (ou éventuellement nulles toutes les deux). On est donc conduit à répéter la recherche sur l’intervalle [a, c], qui est similaire au premier, d’où le caractère récursif de cet algorithme. La récursion doit être stoppée lorsque la valeur |f (c)| est inférieure à une tolérance ε que l’on fixe en fonction de la précision souhaitée.

    def dichotomie_recursive(fonction,a,b,epsilon):
        c = (a+b)*0.5
        fc = fonction(c)
        if abs(fc) < epsilon:
            return c
        else:
            if fc*fonction(a) <= 0:
                return dichotomie_recursive(fonction,a,c,epsilon)
            else:
                return dichotomie_recursive(fonction,c,b,epsilon)

    On utilise la fonction dichotomie_recursive pour la fonction f(x):

    def f(x):
        return x**2-2.0

    On fait alors:

    > dichotomie_recursive(f,0.0,2.0,1e-3))
    1.4140625
    1. Interpreter le résultat obtenu.
    2. Que valent chacun des paramètres de la fonction lors du premier appel avec dichotomie_recursive(f,0.0,2.0,1e-3)) ?
    3. Que valent chacun des paramètres lors du premier appel recursif par cette fonction?
    4. A quel moment cette fonction va-t-elle finir?
    5. Prouver la terminaison de cette fonction.
    6. Soit un tableau contenant des nombres entiers triés par ordre croissant :
    import numpy.random
    import numpy
    N = 50
    L = numpy.random.randint(0,200,N)
    L = numpy.sort(L)

    Écrire une fonction qui permet d’insérer un nombre entier x dans cette liste. La recherche de l’emplacement d’insertion doit se faire par dichotomie. Pour faire l’insertion juste avant l’élément d’indice i :

    L1 = numpy.insert(L,i,x)

    Cela renvoie un nouveau tableau avec l’élément inséré.

    Suite

    • suite du cours: Lien

    Autres exercices avec editeur online

    Lien vers la page des exercices

    Liens

    programmation orientée objet

    Cette séquence comprend:

    • un cours sur la POO: Lien
    • une fiche d’exercices: pdf
    • TP Jeu des 7 familles: Lien (Sans interface graphique)
    • TP sur trajectoires de projectiles: Lien
    • TP sur la programmation d’un jeu de Dominos: Lien. (Sans interface graphique)
    • fiche les bonnes pratiques en POO: Lien

    Programmation objet

    Principe

    En programmation orientée objet, on cherche à organiser les données avec la volonté de se rapprocher de l’architecture d’objets physiques.

    Un objet physique, comme par exemple, une planche de skateboard, possède des caractéristiques propres.

    chalk custom board

    image: CHALK CUSTOM BOARD : L’ART D’HABILLER UN SKATE (urban art)

    Une planche, malgré la diversité, est toujours constituée:

    • d’un deck (court, long)
    • d’un tail (plat, relevé)
    • de trucks (hauts, bas)
    • de roues (à gommes tendres, dures)
    • d’une décoration (image sous le deck)

    C’est son état.

    Cette planche peut repondre egalement à un ensemble de messages, qui forment ce que l’on appelle l’interface de l’objet. C’est au travers de ces méthodes que l’on peut interagir avec l’objet, ou que les objets peuvent interagir entre eux.

    On peut lui associer une méthode skateboard_pour_parc qui renvoie True si la planche est de type street ou False si la planche est de type cruising, ou prevue pour la decoration.

    Un objet comprend donc :

    • une partie figée qui représente son état, et qui est constituée de champs ou attributs.
    • une partie dynamique qui décrit son comportement, à l’aide de déclarations de méthodes, qui doivent répondre à des messages.

    Classe et instance de classe

    La structure interne des objets et les messages auxquels ils repondent sont définis dans une classe. Une classe décrit les méthodes de création d’objets de ce type (on parle d’instance de classe), et les méthodes auxquelles répondront les objets de ce type dans la reception des messages.

    Avec l’exemple précédent, la classe Skateboard pourrait contenir:

    • les méthodes de création des instances des différents skateboards. On y définit les attributs pour chaque nouvelle planche de skateboard que l’on créé. Chaque planche de skate constitue une instance de classe.
    • les méthodes de la classe skateboard, qui repondent aux messages du genre: skateboard_pour_parc? Un message est constitué du nom de la méthode, et permet d’interagir avec celui-ci. Ces méthodes sont accessibles à tous les skates qui sont des instances de la classe skateboard.

    En python, la création d’une classe commence par le mot clé class suivi du nom de la classe, de deux points et d’une indentation.

    class Skateboard:

    Toute la partie indentée contient les méthodes de création des instances de cette classe et les méthodes de cette classe.

    Lors de la programmation, on devra faire référence à l’instance de l’objet sur lequel on travaille: le mot clé self permet ceci en python.

    La méthode de création d’un objet est définie par def __init__ suivi au minimum de l’argument self, et eventuellement d’autres arguments.

    class Skateboard:
        def __init__(self,deck='court',
                    tail='releve',
                    truck='bas',
                    roues='dures',
                    deco='None'):
            self.deck = deck
            self.tail = tail
            self.truck = truck
            self.roues = roues
            self.deco = deco

    Les attributs des objets de cette classe sont définis dans cette méthode. Ils sont codés sous la forme self.attribut, et peuvent faire référence aux arguments passés lors de l’instanciation.

    Enfin, chaque méthode de classe est définie à l’aide de: def nom_de_la_methode. Celle-ci prend aussi au minimum, l’argument self.

    Script complet:

    class Skateboard:
        def __init__(self,deck='court',tail='releve',truck='bas',roues='dures',deco='None'):
            self.deck = deck
            self.tail = tail
            self.truck = truck
            self.roues = roues
            self.deco = deco
            
        def skateboard_pour_parc(self):
            if self.deck == 'court' and self.tail == 'releve' and self.roues == 'dures':
                return True
            else:
                return False

    On instancie alors un premier skateboard de la manière suivante:

    >>> mon_premier_skate = Skateboard()

    Le programme interprete alors l’instruction: Skateboard.__init__(mon_premier_skate), c’est à dire qu’il execute la méthode de classe Skateboard.__init__, avec le paramètre self=mon_premier_skate.

    skateboard classic

    un premier skateboard bien classique

    Et on envoie le message suivant:

    >>> mon_premier_skate.skateboard_pour_parc()
    True

    Le programme interprete alors l’instruction: Skateboard.skateboard_pour_parc(mon_premier_skate),

    Instanciation d’un second skateboard:

    skateboard cruiser

    un skateboard cruiser

    >>> mon_sector_9 = Skateboard('long','plat','haut','molles','Marley')
    >>> mon_sector_9.skateboard_pour_parc()
    False

    La méthode __repr__()

    Cette méthode __repr__ s’utilise pour donner une représentation plus lisible de l’objet lorsqu’on veut l’afficher avec la fonction print.

    Exemple 1: On essaie d’afficher notre instance de classe mon_sector_9 créée plus haut:

    >>> print(mon_sector_9)
    <__main__.Skateboard object at 0x7fc6b0847550>

    Ce n’est pas très explicite pour un humain. On préfèrera souvent choisir un descriptif personnalisé. Nous allons programmer la chaine de caractères qui sera renvoyée lors du print.

    On ajoute maintenant à la classe Skateboard la méthode __repr__() qui sera appelée lorsque l’on utilise print(objet):

    class Skateboard:
        def __init__(...
        ...
    
        def __repr__(self):
            if self.skateboard_pour_parc():
                return "skateboard de type {} qui permet de rider en parc".format(self.deck)
    
            else:
                return "skateboard de type {} qui ne permet pas de rider en parc".format(self.deck)

    On construit à nouveau l’instance de classe mon_sector_9, et on fait print(mon_sector_9):

    >>> mon_sector_9 = Skateboard('long','plat','haut','molles','Marley')
    >>> print(mon_sector_9)
    skateboard de type long qui ne permet pas de rider en parc

    Remarquer que l’appel à la méthode skateboard_pour_parc se fait en identifiant l’objet qui possède cette méthode: self.skateboard_pour_parc(). Et ici, on n’ajoutera pas de nouvel argument. (On ne met pas self en argument lors du message envoyé à cet objet).

    Surcharge d’une fonction de la librairie standard: Ce que l’on vient de réaliser est une surcharge de la fonction print de la librairie standard.

    Mais il existe d’autres méthodes de surcharge, prévues pour les opérateurs, ainsi que pour certaines fonctions. On pourra se référer au lien suivant pour approfondir le sujet.

    Encapsulation: getter et setter

    Lire un attribut: accesseur ou getter

    L’utilisateur du programme ne devrait pas utiliser la méthode pointée précédente nom_objet.nom_attribut, permettant d’accéder aux valeurs des attributs: on ne veut pas forcement que l’utilisateur ait accès à la représentation interne des classes.

    Pour utiliser ou modifier les attributs, on utilisera de préférence des méthodes dédiées dont le rôle est de faire l’interface entre l’utilisateur de l’objet et la représentation interne de l’objet (ses attributs).

    Les attributs sont alors en quelque sorte encapsulés dans l’objet, c’est à dire non accessibles directement. la liste des méthodes devient une sorte de mode d’emploi de la classe.

    Pour obtenir la valeur d’un attribut nous utiliserons la méthode des accesseurs (ou “getters”) dont le nom est généralement : getNom_attribut().

    Exemple:

    class Skateboard:
        def __init__(...
        ...
        
        def getTail(self):
          return self.tail

    En console, une fois l’instance de classe mon_sector_9 définie, on fait:

    >>> mon_sector_9.getTail()
    `long`

    Modifier des attributs : les mutateurs ou setters

    De la même manière, pour modifier la valeur d’un attribut, on devrait utiliser une méthode dédiée. Le nom de cette méthode commence en principe par set:

    Exemple:

    class Skateboard:
        def __init__(...
        ...
        
        def setDeco(self, deco):
          self.deco = deco

    En console:

    >>> mon_sector_9.setDeco = 'repeinte'

    Docstrings

    Chaque classe définit ses propres manières de stocker, d’acceder et de manipuler les données. C’est le Docstring qui permettra de prendre connaissance des détails, comme par exemple celui de la classe Sept_Familles:

    class Sept_Familles:
        """
        NAME
            Sept_Familles
        DESCRIPTION
            constructeur pour les cartes du jeu
        PARAMETERS
            famille (str): nom de la famille
            qui(str): membre de la famille 
                choix parmi ('Grand-père','Grand-mère','Pére','Mère','Fils','Fille')
        FUNCTIONS
            get_Attributs
        """

    On peut alors prendre connaissance du docstring en faisant:

    >>> help(Sept_Familles)

    Interface

    L’interface d’une classe est représentée par le diagramme suivant:

    Une représentation d'une classe

    Une représentation d'une classe

    La suite en TP

    • TP Jeu des 7 familles: Lien (Sans interface graphique)
    • TP sur trajectoires de projectiles: Lien
    • TP sur la programmation d’un jeu de Dominos: Lien. (Sans interface graphique)

    Liens

    Sous-sections de Structures de données

    types abstraits

    Ce cours comporte plusieurs parties:

    • les types abstraits: Lien, liste chainée et tableau statique
    • TP utilisant la notion de tableau statique: Lien, moyenne glissante.
    • Cours sur les Piles: une structure linéaire: Lien
    • exercices en ligne (TP) sur les Piles: Lien
    • Cours sur les Files et autres structures linéaires: Lien

    Types abstraits

    La résolution d’un problème par un programme nécessite:

    • de définir les données du problème
    • d’utiliser des instructions du langage sur ces données

    Souvent, la résolution du problème demande d’arranger ces données dans un type abstrait, afin d’avoir une résolution plus efficace.

    Un type abstrait est défini par son interface, qui est indépendante de son implémentation.

    Les types abstraits sont des types structurés. On a déjà vu des types structurés natifs: les types séquences de texte (string), les types séquentiels (listes, tuples), et les mappages (dictionnaires).

    Un type abstrait est caractérisé par une interface de programmation qui permet de manipuler les données de ce type. Sans pour autant avoir connaissance du contenu des fonctions proposées par l’interface.

    Spécifier un type abstrait, c’est définir son interface, sans prejuger de la façon dont ses opérations sont implémentées.

    Implémenter, c’est fournir le code de ces opérations. Plusieurs implémentations peuvent correspondre à la même spécification. On verra dans ce chapitre la programmation dans un style fonctionnel. Il viendra plus tard la programmation par objet.

    On verra dans un premier temps, deux exemples de types abstraits: Les listes chainées et les tableaux. Dans un chapitre ultérieur, nous verrons les types abstraits Piles, Files, et Graphes.

    Listes chaînées

    Une liste chaînée est une séquence ordonnée d’éléments. L’avantage sur un tableau (la Liste native en Python), c’est qu’en parcourant la Liste chainée, quelle que soit la profondeur de parcours, celle-ci présente la même structure.

    On peut donc lui associer des méthodes ou fonctions, qui seront indépendantes de cette profondeur. Que l’on pourra utiliser de la même manière à chaque niveau de la liste chainée.

    classes à parcourir après le collège

    classes à parcourir après le collège

    classes à parcourir après la 2nde

    classes à parcourir après la 2nde

    La liste L précédente représente la chaine: "2nde" -> "1ere" -> "Term" -> "Univ

    L = ("Univ",("Term",("1ere",("2nde", ()))))

    La liste chainée L contient 2 éléments (tete, queue) et queue est elle-même une liste chainée, contenant aussi (tete, queue). Le dernier élément: (tete, ()).

    On utilisera par exemple une liste chainée lorsqu’il y a une filiation entre les éléments, et surtout, lorsque l’on doit souvent INSERER ou SUPPRIMER des éléments qui ne sont pas forcement à la fin de la liste.

    L’interface d’une liste chainée

    L’interface fournit certaines fonctions.

    fonctions qui implémentent la liste chainée L nom
    créer une liste vide creer_liste()
    questionner si la liste est vide liste_vide(L)
    insérer un élément e en tête de liste et retourne une nouvelle liste inserer_tete(L,e)
    retourne l’élément de tête (premier élément) tete(L)
    retourne la liste privée de son premier élément (retourne donc le 2e élément) queue(L)
    insere un nouvel element_a_inserer juste avant l’élement recherché dans la liste insere(L,element_recherche,element_a_inserer)
    retourne une liste python avec tous les éléments de la liste chainée elements_liste(L)

    Le contenu de ces fonctions va dépendre de l’implémentation choisie par le programmeur.

    Par exemple, si l’on choisit d’implémenter la liste chainée par un tuple, on aura pour la premiere fonction:

    def creer_liste():
      return ()

    Alors que si l’on choisit plutôt une liste:

    def creer_liste():
      return []

    Généralités sur les listes chainées

    Une liste chainée est un objet:

    • non mutable: on peut la modifier en partie (ajout/suppression d’un élément), mais sa copie se fait par valeur.

    • dynamique: on peut modifier sa taille après création, par exemple en faisant: L = inserer(L, e), mais cela va créer un nouvel objet.

    • les éléments ont une relation d’ordre entre eux.

    • on peut atteindre un élément au rang i en temps proportionnel à i, avec une boucle par exemple.

    Mémoire: Contrairement aux tableaux, les éléments d’une liste chaînée ne sont pas placés côte à côte dans la mémoire. Chaque case pointe vers une autre case en mémoire, qui n’est pas nécessairement stockée juste à côté.

    L’interface d’une liste chainée doit aussi proposer l’insertion d’un élément au rang i, en temps constant. (Intercaler cet élément entre 2 éléments de la liste). Ceci ne peut pas être réalisé avec l’implémentation vue plus haut.

    Nous verrons d’autres implémentations pour ce type abstrait.

    Attention: les listes chaînées et les Listes Python sont différentes, il ne s’agit pas des mêmes objets.

    Tableaux, choix d’une structure de données native en python

    Les tableaux statiques sont des structures de données de taille fixe, où chaque donnée est du même type. C’est comme ceci que sont représentées les collections dans des langages comme C, Java, Ocaml, …

    La taille du tableau est fixe à sa création : on ne peut pas l’agrandir ou le réduire sans en recréer un nouveau.

    Un tableau peut être représenté en Python à l’aide d’une liste (type list), un tuple (type tuple), ou bien une matrice numpy (numpy.array).

    List python

    Les tableaux en python sont implémentés par le type list, qui est en réalité un tableau dynamique: leur taille est variable, et les éléments stockés peuvent être de types différents (idem pour Javascript). Pour utiliser le type list en tant que tableau statique, on s’interdira les aspects dynamiques.

    1. Création

    On rappelle que, pour créer une liste python, on peut utiliser les techniques suivantes:

    • création par extension: en listant les éléments du tableau: T = [1,2,3]
    • par concaténation: On peut utiliser une somme d’éléments à l’aide des opérateurs + et *, par exemple: T = [0] * 100
    • par compréhension: on s’appuie sur un itérateur (fonction génératrice), exemple: T = [i for i in range(ord('A'), ord('Z')+1], ou T = [x**2 for x in range(1,11)]
    • par ajout dans une table vide (append)
    • à l’aide de la fonction list: codes = list(range(ord('A'), ord('Z')+1), T = list('bonjour')
    1. Manipuler On accède à un élément d’un tableau à l’aide d’un indice, qui peut être positif: T[1] est le deuxière élément par exemple, T[0] étant le premier. Ou bien à l’aide d’un entier négatif, ce qui fait que T[len(T)-1] est le même que T[-1]

    2. Parcourir

    • Le plus simple est de parcourir directement par élément
    for elem in L:
      print(elem)
    • parcourir par indice:

    Très utile si on veut modifier les valeurs lors du parcours:

    for i in range(len(T)):
      T[i] += 1

    ou bien lorsque l’on veut parcourir 2 tableaux à la fois:

    prenoms = ['Agnes','Kev','Sam']
    age = [34,28,21]
    for i in range(len(prenoms)):
      print("prenom: {}, age:{}".format(prenoms[i],age[i]))

    numpy.array

    En Python, les tableaux fixes peuvent être implémentés via la classe array du module numpy.

    La dimension est fixée à la construction. Les indices commencent à 0.

    import numpy as np
    t = np.array([1, 2, 3, 4])
    print(t[1])  # Affiche 2

    Pour des tableaux à plusieurs dimensions: On peut accéder aux éléments d’un array A en utilisant la syntaxe A[i, j] , où i et j sont respectivement le numéro de ligne et le numéro de colonne de l’élément au sein du tableau. L’opérateur : permet de sélectionner plusieurs éléments, voire tout une ligne ou colonne.

    Tuple

    Pour un tuple, celui-ci contiendra 2 données:

    • la liste des valeurs, de dimension fixe. On mettra None pour les valeurs non renseignés.
    • la valeur de la taille de la liste.

    Par exemple:

    T = ([6, 7, 8, None, None], 5)

    C’est alors un objet qui est:

    • statique: sa taille ne varie pas une fois celui-ci créé
    • non mutable: mais avec un élément qui lui, peut être mutable:

    On ne peut pas modifier T[0] ou T[1]. Ce sont les éléments d’un tuple.

    Mais on peut modifier en partie T[0], par exemple avec une instruction du genre: T[0][i] = x. La copie de T[0] se fait par reference.

    Un tableau peut servir à implémenter une grille de notes par exemple:

    Tableau de notes

    Tableau de notes

    Supposons, pour simplifier, que le tableau ne contient que les notes de Kyle:

    Tableau des notes de Kyle

    Tableau des notes de Kyle

    On peut représenter cet ensemble de notes par le tableau:

    T = ([6, 7, 8, None, None], 5)

    Petits rappels sur le tuples:

    • Construction par extension:
    fruits = ('pommes','oranges')
    • Construction par concaténation:
    t = ()
    t = t + (1,) # ne pas oublier , sinon cela génère une list
    t = t + (2,)
    print(t)
    (1,2)
    • Construction par compréhension:
    carres = tuple(x**2 for x in range(1,11))
    # ne pas oublier de mettre tuple au debut
    • avec la fonction list:
    codes = list(range(ord('A'),ord('Z')+1))
    lettres_bonjour = list('bonjour')

    L’interface d’un tableau

    fonctions qui implémentent un tableau T (Array) nom
    taille du tableau taille(T)
    demander l’élément au rang i element(T,i)
    remplacer l’élément au rang i par e remplacer(T,i,e)

    Tableaux multidimentionnels

    hugo = [21, 1400, 0]
    richard = [54, 2800, 2]
    emilie = [27, 3700, 3]
    tableau = [hugo, richard, emilie]

    Alors, pour accéder à l’un des éléments, on fait: tableau[ligne i][colonne j]:

    List et tuple

    >>> tableau[0][1] # correspond à la 2e (j=1) note de hugo (i=0)
    1400 

    Array

    >>> tab1 = np.array([[1, 2],
        [3, 4],
        [5, 6]])
    # tab1 est un array de 3 lignes et 2 colonnes
    >>> tab2 = np.array([[1, 2, 3],
        [4, 5, 6]])
    # tab2 est un array de 2 lignes et 3 colonnes
    >>> np.ones((3, 5))
    # un tableau de 3x5 rempli de 1
    >>> np.zeros((4, 4))
    # un tableau de 4 lignes et de 4 colonnes contenant que des 0

    Tableaux dynamiques et tableaux statiques

    Les tableaux vus ci-dessus sont des tableaux statiques: leur taille ne peut pas être modifiée. Dans le cas où l’on ait besoin d’agrandir le tableau, il faut le copier dans un nouveau tableau, plus grand.

    Python implémente naturellement un autre type de tableau, que l’on appelera dynamique: Les Listes Python. Ce problème de dimension n’apparait pas dans les Listes Python, qui apportent de surcroit des méthodes bien pratiques comme append et pop.

    Exercices sur les listes

    On propose l’implémentation suivante pour les listes chainées:

    def creer_liste():
      """exemple: 
      L = creer_liste()
      """
      return ()
    
    def liste_vide(L):
      """exemple: 
      liste_vide(L)
      """
      return L == ()
    
    def inserer_tete(L,e):
      """exemple:
      L = inserer_tete(L,e)
      """
      return (e,L)
    
    def tete(L):
      """exemple:
      L = (1,(2,()))
      tete(L) -> 1
      """
      return L[0]
    
    def queue(L):
      """exemple:
      L = (1,(2,()))
      queue(L) -> (2,())
      """
      return L[-1]
    
    def inserer(L,element_recherche,element_a_inserer):
      """exemple:
      L = (1,(2,()))
      inserer(L,2,3) -> (1,(3,(2,())))
      """
      Liste_des_elements = []
      # recherche
      while element_recherche != tete(L):
        Liste_des_elements.append(tete(L))
        L = queue(L)
      # insertion
      L = inserer_tete(L,element_a_inserer)
      for i in range(len(Liste_des_elements)-1,-1,-1):
        L = inserer_tete(L,Liste_des_elements[i])
      return L
    
    def elements_liste(L):
      Liste_des_elements = []
      while not liste_vide(L):
        element = tete(L)
        L = queue(L)
        Liste_des_elements.append(element)
      return Liste_des_elements
      
      

    Exercice 1: parcours scolaire

    Le parcours scolaire est un type abstrait qui s’apparente à une Liste. Les éléments sont disposés dans cette Liste sous la forme:

    ('Terminale', ('Premiere', ('Seconde', ())))

    L’interface propose les fonctions suivantes:

    creer_liste, liste_vide, inserer, tete, queue.

    1. Quelles instructions, utilisant l’interface, vont créer la Liste parcours_lycee de la manière suivante: ('Terminale', ('Premiere', ('Seconde', ())))?

    2. Quelle instruction va permettre de connaitre la dernière classe visitée lors du parcours scolaire?

    3. Que retourne queue(parcours_lycee)? (choisir)

    • la première classe du parcours scolaire
    • le parcours scolaire sans la dernière année

    4. Que retourne le script suivant?

    while not liste_vide(parcours_lycee):
      print(tete(parcours_lycee))
      parcours_lycee = queue(parcours_lycee)

    5. On souhaite utiliser ce type abstrait pour décrire le parcours universitaire. Quelle serie d’instructions va créer la structure de données du parcours qui ira de Licence 1 à Master 2? Cette liste s’appelera parcours_univ

    6. On souhaite maintenant créer une liste unique appelée scolarite, issue de la jonction des deux listes, parcours_lycee et parcours_univ. Ecrire le script correspondant.

    Exercice 2: composition d’un train

    On cherche à implémenter la construction d’un train pour voyageurs, motrice et wagons, à l’aide d’une liste chainée.

    Le train suit l’ordre suivant:

    • motrice
    • wagon_1
    • wagon_2
    • wagon_3

    1. Qu’est ce qui est affiché par le programme suivant?

    L1 = creer_liste()
    L1 = inserer_tete(L1,'motrice')
    print(L1)
    L1 = inserer_tete(L1,'wagon_1')
    print(L1)
    L1 = inserer_tete(L1,'wagon_2')
    print(L1)
    L1 = inserer_tete(L1,'wagon_3')
    print(L1)

    2. Quelle instruction de l’interface de liste faut-il utiliser pour consulter la nature du dernier wagon du train?

    3. La fonction elements_liste va retourner les éléments de la liste chainée, en une liste python. Quelle instruction, utilisant elements_liste, va retourner la liste ['wagon_3', 'wagon_2', 'wagon_1','motrice']?

    4. INSERTION: On souhaite modifier la liste L1 et intercaler wagon_bar entre le wagon_1 et le wagon_2.

    • Quelle instruction utilisant la fonction insere de l’interface de liste va modifier L1 de cette façon?
    • Quelle sera l’objet retourné?
    • Repérer les différentes parties de cette fonction.

    5. Supprimer le wagon de queue à l’aide d’une instruction de l’interface.

    Exercice 3: separation d’une liste

    1. Compléter la fonction separe qui sépare les éléments d’une liste en deux listes selon s’ils sont inférieurs (strictement) ou supérieurs (et égal) à une valeur v:

    def separe(L,v):
      L_inf = creer_liste()
      L_sup = creer_liste()
      while not liste_vide(L):
        # à completer
        # utilise les fonctions tete, queue et insere_tete
        # 
        # 
      return L_inf, L_sup

    2. Compléter alors le programme au niveau du repère ICI. Le programme affiche les 2 listes une fois celles-ci séparées. La liste L contiendra les valeurs à séparer.

    L = creer_liste()
    for elem in [1,3,20,18,16,11,101,12,15,2,5,4,2,8,1]:
        L = inserer_tete(L,elem)
    
    v = 12 
    # ICI, appel de la fonction separe
    L_inf, L_sup = separe(L,v)
    print(L_inf)
    print(L_sup)
    # (1, (3, (11, (2, (5, (4, (2, (8, (1, ())))))))))
    # (20, (18, (16, (101, (12, (15, ()))))))

    Exercices sur les Tableaux statiques

    On propose l’implémentation suivante pour les tableaux statiques:

    T = (['lundi','mardi','mercredi','jeudi','vendredi'],5)
    
    def taille(T):
      """exemple:
      > taille(T)
      > 5
      """
      return T[1]
    
    def element(T,i):
      """exemple:
      > element(T,3)
      > 'jeudi'
      """
      return T[0][i]
    
    def remplacer(T,i,e):
      """exemple:
      > remplacer(T,2,'jour des enfants')
      > T
      > (['lundi','mardi','jour des enfants','jeudi','vendredi'],5)
      """
      # à completer

    Exercice 1: Utiliser l’interface du tableau

    Tableau de notes

    Tableau de notes

    1. Soit le tableau qui implémente les notes de Kyle dans les matières C1, C2, C3:

    T = ([6, 7, 8], 3) 

    a. Ecrire l’instruction qui retourne la note de Kyle dans la matière C3.

    b. Kyle n’a pas eu 8, mais 12/20 dans la matière C3. Ecrire l’instruction qui modifie sa note 8 en 12, à partir d’une fonction de l’interface des tableaux.

    c. Compléter le script donné plus haut pour cette fonction.

    d. Ecrire le script d’une fonction moyenne qui calcule la moyenne des notes du tableau T.

    2. Soit le tableau suivant qui implémente les notes de Kyle, Sean, Quentin et Zinedine dans les matières C1, C2, C3:

    T = ([[6, 7, 8],
          [10, 0, 10],
          ['?', '?', '?'],
          ['?', '?', '?']], (4,3))

    a. Recopier le tableau T et remplacer les ‘?’ par les bonnes valeurs (utiliser l’image plus haut). Que signifie le tuple (4,3) placé comme 2e élément du tableau?

    b. Utiliser l’instruction taille de l’interface pour donner le nombre d’élèves dans le tableau. Puis le nombre de colonnes (matières):

    n_eleves = taille(...)
    n_matieres = taille(...)

    2c. Modifier la fonction remplacer pour que celle-ci modifie la note dans la matière voulue pour un élève donné.

    Par exemple: Pour modifier la note de la colonne 2 de l’élève au rang 0 (premiere ligne):

    Si on veut lui mettre 12, on fera: remplacer(T,0,2,12)

    remplacer(T,0,2,12)
    T
    # affiche 
    ([[6, 7, 12],
     [10, 0, 10],
     ['?', '?', '?']
     ['?', '?', '?']], ..)

    3. Quelle instruction, utilisant la fonction moyenne va retourner la moyenne des notes de Zinedine?

    4. moyenne_matiere Programmer la fonction moyenne_matiere qui va calculer la moyenne sur une matière pour la colonne j d’une matrice M.

    Pour programmer cette fonction moyenne_matiere(M,j), il faudra:

    • Faire la somme $M[0][j] + M[1][j] + M[2][j] + M[3][j]$. Utiliser un accumulateur s dans une boucle bornée.
    • Diviser s par le nombre de notes
    • retourner la valeur

    Exercice 2: moyenne glissante et tableau statique

    énoncé à la page suivante.

    Liens et prolongements

    Pile

    Ce cours comporte:

    • les types abstraits: Lien
    • Cours sur les Piles: Lien
    • Cours sur les Files et listes: Lien
    • exercices en ligne (TP) sur les Piles: Lien

    Structure linéaire : La Pile

    Les structures de données

    Definition: Une structure de données est une manière de stocker, d’accéder à, et de manipuler des données (comme les types list ou dict de Python).

    Definition: Un type abstrait décrit essentiellement une interface, indépendamment du langage de programmation.

    Un premier exemple

    La pile est une manière de ranger les données.

    Elle correspond exactement à l’image traditionnelle d’une pile de cartes ou d’assiettes posée sur une table. En particulier, on ne peut accéder qu’au dernier élément ajouté, qu’on appelle le sommet de la pile.

    L’illustration suivante montre que c’est la structure de données à adopter si l’on veut sortir d’un labyrinthe…

    parcours utilisant une pile

    parcours pour sortir d'un labyrinthe

    Le labyrinthe peut être modélisé par les coordonnées de ses noeuds, ainsi qu’une liste de directions possibles (ouvertures) pour chacun de ses noeuds :

    labyritnhe modelisation

    modelisation d'un labyrinthe

    En observant l’animation de la tortue dans le labyrinthe, on peut supposer que la pile des sommets visités (les cases du labyrinthe) sont, dans l’ordre :

    (4,0), (3,0), (3,1), (3,2), (4,2), (4,1) …

    puis le chemin inverse jusqu’au sommet (3,0) :

    (4,2), (3,2), (3,1), (3,0), …

    Une fois revenu au sommet (3,0), on reprend l’exploration vers (2,0), (2,1),…

    Il s’agit d’une méthode d’exploration du labyrinthe de type parcours en profondeur. L’algorithme est expliqué en détail à la page : SNT algorithmes graphe : parcours en profondeur

    turtle

    fil d'ariane

    La tortue suit son chemin jusqu’à arriver à une impasse (ou un sommet déjà visité). Alors, elle doit être capable de revenir sur ses traces. C’est pour cela qu’elle mémorise son parcours dans une pile, qu’elle pourra remonter (c’est à dire dépiler) au besoin. Cette pile de sommets visités correspond au fil d’Ariane, rendu célèbre par la mythologie (Thésée et le Minautore).

    Lorsqu’elle s’avance plus en profondeur dans le labyrinthe, vers des sommets encore non explorés, elle empile.

    Lorsqu’elle revient sur ses traces, elle dépile (elle retire des sommets de la pile).

    empiler depiler

    pile de sommets du labyrinthe

    Lorsque la tortue arrive à la case (4,1), l’impasse, la pile a alors la configuration pile a (voir schéma plus bas).

    Elle revient jusqu’à (3,0).

    Après avoir dépilé (4,1),(4,2),(3,2),(3,1), la pile est alors la pile b.

    Puis, lorsqu’elle est parvenu à une bifurcation vers une nouvelle direction, elle poursuit son exploration (et empile à nouveau) : pile c. Qu’il faudra encore prolonger pour atteindre la sortie (en bas à droite).

    pile DFS

    pile du parcours en profondeur

    Deuxieme exemple : une expression correctement parenthésée

    Principe : On lit l’expression de gauche à droite et on empile au fur et à mesure les caractères ouvrants : [, {, (. On dépile lorsqu’on lit le caractère fermant correspondant. A la fin, la pile doit être vide.

    Dans l’exemple suivant, on voit que l’expression [a+(b+c)] est correctement parenthesée. Ce qui ne serait pas le cas pour [a+(b+c]).

    Définitions

    La pile: interface

    La pile est une structure de données appropriée quand :

    • On veut stocker des éléments dont le nombre est variable, et inconnu à l’avance.
    • On peut ou on doit se contenter d’accéder au dernier élément stocké.

    Dans d’autres cas, il faudra utiliser une autre structure de données, comme par exemple un tableau.

    Une Pile est une structure de données linéaire (les données sont rangées sur un ligne ou une colonne). Le dernier élément entré sera aussi le premier à sortir (Last In First Out : LIFO).

    Les méthodes (= fonctions) disponibles pour cette structure sont :

    • construction (d’une pile vide)
    • test d’une pile vide (renvoie True si la pile est vide)
    • ajout d’un élément (empiler = push), mis au sommet de la pile
    • retire le premier élément de la pile, celui au sommet (dépiler = pop) si la pile est non vide et renvoie cet élément.
    • lire le sommet de la pile

    Implémenter un pile en Python en langage natif

    Le type List en Python possède déjà toutes les méthodes d’une pile :

    pile = []           # creation d'une pile
    pile == []          # tester si la pile est vide
    pile.append(valeur) # empile valeur dans la pile
    pile.pop()         # depiler l'element au sommet
    pile[-1]            # lire l'element au sommet de la pile

    Lorsque l’on fait référence à une structure de données de type pile en traduisant un algorithme en Python, il faudra se contenter de ces 5 instructions.

    Créer une nouvelle Interface

    Les types abstraits, comme les piles, sont définis par leur interface (comment on s’en sert) plutôt que par leur implémentation (comment ils fonctionnent). Ils permettent d’étudier des algorithmes indépendamment du langage utilisé.

    Rappels:

    • L’interface de la structure de données décrit de quelle manière on peut la manipuler, par exemple en utilisant append pour le type list ou get pour le type dict.

    • L’implémentation de la structure de données, contient le code de ces méthodes (comment fait Python). Il n’est pas nécessaire de connaître l’implémentation pour manipuler la structure de données.

    On verra ici deux manières d’implémenter la pile.

    Implémentation fonctionnelle

    Pour traduire un algorithme utilisant cette structure pile, il peut être préférable de définir des instructions portant les noms de ces 5 instructions:

    def Pile():
      """creation d'une pile vide à l'aide de l'instruction : 
      pile = Pile()
      """
      return []
    
    def est_vide(pile)
      # à compléter
    
    def empile(valeur,pile):
      # à compléter
    
    def depile(pile):
      # à completer
    
    def sommet(pile):
      # à completer

    Implémentation en Programmation Objet

    On peut créer un type (= une classe) Pile personnelle en Python.

    Les méthodes (fonctions) déclarées précédemment sont alors associées à l’objet Pile. L’appel d’une méthode se fait à l’aide de l’instruction :

    pile = Pile()
    pile.est_vide()
    pile.empile(valeur)
    pile.depile()
    pile.sommet()

    Voir le cours sur la programmation orientée objet.

    Rappel : Objet = type mutable. Quelle que soit la façon avec laquelle la pile est implémentée, il faudra se souvenir que celle-ci est un objet mutable. Cela a des conséquences sur la manière avec laquelle la pile est passée en argument d’une fonction, et comment cette fonction modifie la pile.

    Pile et recursivité

    Tout algorithme récursif peut être mis sous forme d’algorithme itératif avec une structure de données en pile.

    Voir le cours sur la recursivité

    Exercices sur les piles

    voir la page exercices

    Autres structures linéaires

    Lien vers la page Listes et Files

    Liens

    Files et Listes

    Ce cours comporte 2 chapitres prérequis:

    Et plusieurs parties:

    • les types abstraits: Lien
    • les Piles: une structure linéaire: Lien
    • exercices en ligne (TP) sur les Piles: Lien
    • autres structures linéaires: Lien

    Et plusieurs notebooks:

    Structures de données: rappels

    Les piles, files et listes sont des structures de données linéaires. Ce sont des types abstraits.

    Structure de données linéaire : les données sont rangées sur un ligne ou une colonne.

    Un type abstrait décrit essentiellement une interface, indépendamment du langage de programmation.

    Files

    Definition et interface

    Une file (queue ou FIFO pour first in, first out) est une collection d’objets munie des opérations suivantes:

    • savoir si la file est vide (is_empty);
    • ajouter un élément dans la file (enfiler ou enqueue) en temps constant;
    • retirer et renvoyer l’élément le plus ancien de la file (defiler ou dequeue).

    C’est une structure de données utilisée en informatique pour par exemple gérer la file d’attente lors de la gestion des impressions.

    exemple de gestion d'une file d'attente

    exemple de gestion d'une file d'attente

    Implémentations en python natif

    L’implementation d’une File est imparfaite avec une liste en python pour l’opération de defiler. On peut utiliser l’instruction file.pop(0):

    > F = []
    > F.append(1)
    > F.append(2)
    > F.append(3)
    > print(F)
    [1,2,3]
    > F.pop(0)
    > print(F)
    [2,3]

    Le problème est que celle-ci ne s’effectue pas en temps constant.

    Implémentation avec l’extension deque

    La bibliothèque standard possède toutefois un module nommé collections qui contient quelques structures de données supplémentaires, dont le type deque, qui est une implémentation de file:

    from collection import deque
    f = deque()
    f.append("Premier")
    f.append("Deuxieme")
    print(f.popleft())
    f.append("Troisieme")
    while f:
      print(f.popleft())

    affiche:

    Deuxieme
    Troisieme

    Listes

    Principe

    Le types abstrait Liste ne concerne pas le type list en python. C’est une liste chaînée (ou liste liée): une structure de données composées d’une séquence d’éléments de liste.

    Ces éléments sont aussi appelés noeuds ou maillons.

    La tête d’une liste est son premier maillon. La queue d’une liste, son dernier.

    Chaque maillon M contient:

    • une valeur, de n’importe quel type.
    • un lien (ou pointeur) vers le maillon suivant de la séquence.

    Il s’agit d’une structure linéaire, mais dans laquelle les éléments n’occupent pas à priori, des positions contigües dans la mémoire:

    illustration:

    elements d

    elements dans une liste

    Pour relier ces éléments ensembles, dans une même structure de données, il faut alors utiliser des pointeurs.

    liste chainée grâce aux pointeurs

    liste chainée grâce aux pointeurs

    L’élément A pointe sur B, qui pointe sur C, qui pointe sur D. D, lui, ne pointe sur … rien!

    La plupart du temps, le lien du dernier maillon a pour valeur None en python, signifiant un pointeur sur rien.

    Interface

    On trouve en général les opérations suivantes pour l’interface d’une Liste:

    • est_vide : renvoie True si Liste vide
    • taille : renvoie le nombre de maillons de la séquence
    • get_dernier_maillon
    • get_maillon_indice
    • ajouter_debut
    • inserer_apres
    • ajouter_fin
    • supprimer_apres
    • …

    Implémentation en POO

    L’implémentation est plus naturelle en programmation orientée objet voir le chapitre POO

    Un maillon est une instance de la classe Maillon

    class Maillon:
      def __init__(self):
        self.val = None
        self.suiv = None

    Une Liste est une instance de la classe Liste

    class Liste:
      def __init__(self):
        self.tete = None

    Son attribut tete est de type Maillon , ou bien vaut None si la liste est vide.

    Cette classe ne comporte pour l’instant que sa définition de la variable tete, mais elle est créée pour contenir, plus tard, l’implementation des différentes méthodes prévues par l’interface.

    liste chainée

    illustration d'une liste chainée

    On peut alors créer une liste ainsi :

    ma_liste = Liste()
    M1, M2, M3 = Maillon(), Maillon(), Maillon()
    M1.val = 'A'
    M2.val = 'C'
    M3.val = 'D'
    M1.suiv = M2
    M2.suiv = M3
    M3.suiv = None
    ma_liste.tete = M1

    Questions: à votre avis, que vaut L.tete.val ?

    et que vaut L.tete.suiv.val?

    Interêt et inconvenient par rapport aux listes en python

    L’interface d’une liste chainée fournit des méthodes plus efficaces que la Pile, la File ou le tableau, lorsque l’on veut par exemple: insérer, ou supprimer un élément dans la séquence.

    insertion liste chainée

    insertion dans une liste

    Cette opération est prévue par l’interface d’une liste chainée => O(n): inserer_apres(i), où i est l’indice de l’élément après lequel on veut insérer.

    Avec une liste python, qui implémente la Pile (voir cours) cela necessite de décaler toutes les valeurs de rang supérieur à i . C’est une opération qui est évaluée en O($n^2$) pour sa complexité asymptotique.

    Il s’agit du même problème lorsque l’on veut supprimer après i.

    Un autre avantage est la possibilité de faire pointer le dernier élément sur le premier de la liste. On créé ainsi une liste périodique.

    Inconvénient: Pour accéder à un maillon de rang i dans une liste chainée, il faut remonter la liste depuis le premier élément (celui de tête), jusqu’à celui de rang i. Et cela se fait avec une complexité asymtotique O(n).

    Exercices

    Editeur sur capytale2.ac-paris.fr

    Exercice 1: Créer une liste chainée

    1. Completer le script ci-dessous pour créer une liste chainée appelée ma_liste qui contiendra la éléments suivants:

    'Premier', 'Troisieme', 'Quatrieme'

    Vous devrez créer les maillons M1, M2, M3 et renseigner leur contenu M.val:

    class Maillon:
      def __init__(self):
        self.val = None
        self.suiv = None
        
    class Liste:
      def __init__(self):
        self.tete = None
    
    # a compléter

    2. Tester dans la console les instructions suivantes:

    >>> ma_liste.tete.val
    >>> ma_liste.tete.suiv.val
    >>> ma_liste.tete.suiv.suiv.val

    3. Rendez-vous sur pythontutor.com

    liste chainée et pythontutor

    liste chainée et pythontutor

    Dans la fenêtre d’edition de pythontutor: Coller les lignes ci-dessous et executer le script pas à pas

    class Maillon:
      def __init__(self):
        self.val = None
        self.suiv = None
        
    class Liste:
      def __init__(self):
        self.tete = None
        
    L = Liste()
    M1, M2, M3 = Maillon(), Maillon(), Maillon()
    M1.suiv = M2
    M2.suiv = M3
    M1.val = 'A'
    M2.val = 'C'
    M3.val = 'D'
    L.tete = M1

    4. Ajouter les lignes suivantes et dérouler le programme ligne par ligne:

    s = L.tete
    s.val = '1'
    print(L.tete.val)
    print(M1.val)

    Qu’affiche la console? Ce résultat était-il prévisible? Pourquoi? (la copie s = L.tete se fait-elle par valeur ou bien par référence)

    Exercice 2: afficher les éléments de liste

    On cherche à parcourir les éléments d’une liste chainée L.

    On propose un premier algorithme itératif. Celui-ci stocke l’élément de tête de L dans une variable M.

    Puis une boucle non bornée parcourt les différents maillons de L jusqu’à ce que M.suiv soit None, marquant le maillon de queue.

    On affiche alors les valeurs M.val de ces maillons avec print.

    Et on passe au maillon suivant: M = M.suiv

    1. Ecrire le script itératif.

    2. Adapter ce script pour en faire une fonction recursive qui prend en paramètre un maillon M, et affiche toutes les valeurs jusqu’à la fin de la liste. La condition d’arrêt (Base) sera M.suiv is None.

    La fonction doit renvoyer une chaine de caractères fabriquée de la manière suivante : A => ... => ... => D

    Compléter après le return:

    class Maillon:
      def __init__(self):
        self.val = None
        self.suiv = None
        
    class Liste:
      def __init__(self):
        self.tete = None
        
    L = Liste()
    M1, M2, M3 = Maillon(), Maillon(), Maillon()
    M1.suiv = M2
    M2.suiv = M3
    M1.val = 'A'
    M2.val = 'C'
    M3.val = 'D'
    L.tete = M1
    
    def affiche(M):
        if M.suiv is None:
            return str(M.val)  # affiche la valeur de queue
        else:
    
        .....

    3. Comment appeler cette fonction afin qu’elle affiche TOUS les éléments de la liste L, du premier (tête) au dernier? Tester avec la liste ACD décrite dans le cours.

    Exercice 3: Insertion d’un élément

    insertion liste chainée

    insertion dans une liste

    Soit la liste chainée L: ‘A’ => ‘C’ => ‘D’

    On souhaite maintenant modifier la séquence de L créée dans l’exercice 2. On va insérer un élément de valeur B à la $2^e$ position:

    A => B => C => D

    Ajouter dans votre programme les instructions qui permettront de:

    1. Créer un nouveau maillon M2.

    2. Affecter ‘B’ comme valeur à M2.

    3. Modifier le lien M2.suiv pour que celui-ci pointe vers le 3e élément de ma_liste.

    4. Modifier le lien L.tete.suiv pour recréer la liste chainée. (ou bien celui de M1, ce qui revient à la même chose).

    5. Utiliser la fonction affiche pour afficher les éléments de L.

    6. Que se passerait-il avec cette fonction affiche si on mettait M4.suiv = M1? (liste chainée circulaire).

    Correction des exercices

    Exercice 1

    # correction de l'exercice 1
    class Maillon:
      def __init__(self):
        self.val = None
        self.suiv = None
        
    class Liste:
      def __init__(self):
        self.tete = None
        
    ma_liste = Liste()
    M1, M2, M3 = Maillon(), Maillon(), Maillon()
    M1.val = 'Premier'
    M2.val = 'Troisieme'
    M3.val = 'Quatrieme'
    M1.suiv = M2
    M2.suiv = M3
    M3.suiv = None
    ma_liste.tete = M1
    
    print(ma_liste.tete.val)
    print(ma_liste.tete.suiv.val)
    print(ma_liste.tete.suiv.suiv.val)
    
    s = ma_liste.tete
    s.val = '1'
    print(ma_liste.tete.val)
    print(M1.val)

    Exercice 2

    # Correction de l'exercice 2 en ligne question 2.1
    M = L.tete
    while not M.suiv is None:
        print(M.val)
        M = M.suiv
    print(M.val)

    Pour le script recursif:

    # Correction de l'exercice 2.2 en ligne
    
    def affiche(M):
        if M.suiv is None:
            return str(M.val)
        else:
            return str(M.val) + '=>' + affiche(M.suiv)
    
    
    # Correction question 2.3 en ligne
    >>> print(affiche(L.tete))
    'A=>B=>C=>D'

    Exercice 3

    (à venir)

    Liens

    graphes

    Ce cours comporte plusieurs pages:

    Graphes

    Les graphes et les arbres permettent de construire des schémas qui mettent en évidence une structure sur des données.

    modelisation reseau social

    graphe modelisant un reseau social

    Complexité et morphologie d’un graphe - définitions

    On appelle graphe la donnée d’un ensemble fini V de points (ou sommets du graphe, vertices en anglais) et d’un ensemble E de liens entre ces points.

    $$G = (V,E)$$

    L’ensemble E de liens peut être vu comme une relation R sur V × V. Il peut être représenté par une matrice d’adjacence.

    • Lorsque cette relation est symétrique (c’est à dire que l’existence d’un lien entre un sommet s1 et un sommet s2 est réciproque) le graphe est dit non orienté. Un lien est appelé une arête.

    • Lorsque cette relation n’est pas symétrique, le graphe est dit orienté. On parle alors d’arc entre deux sommets.

    graphe orienté/non orienté

    graphe orienté/non orienté

    Un chemin C est une suite consécutive d’arêtes: C = {s0s1, s1s2, …, sk-1sk} avec C ⊂ E.

    Des poids peuvent être associés aux liens d’un graphe, par exemple pour représenter la distance. Il s’agit alors d’un graphe pondéré.

    Un graphe peut servir à modéliser un reseau d’ordinateurs, un reseau social, les distances entre villes par la route…

    Lorsqu’un graphe non orienté est en un seul morceau, c’est à dire lorsqu’il existe pour tous sommets s1 et s2 un chemin les reliant, le graphe est dit connexe.

    graphes connexe/non connexe

    graphes connexe/non connexe

    Des poids peuvent être associés aux liens d’un graphe, par exemple pour représenter la distance. Il s’agit alors d’un graphe pondéré.

    exemple de graphe pondéré

    exemple de graphe pondéré

    Et lorsqu’un chemin mène d’un sommet s à lui-même, on parle de cycle.

    cycle dans un graphe

    cycle dans un graphe

    Mesures sur un graphe

    • Ordre: le nombre de ses sommets
    • taille : le nombre de ses arêtes
    • degré d’un sommet s: nombre d’arêtes qui relient ce sommet à d’autres sommets.

    Pour un graphe orienté, le degré d’un sommet est le nombre d’arcs qui sont dirigés vers ce sommet.

    • un graphe est dit complet si tous ses sommets sont connectés entre eux deux-à-deux. Pour N sommets, cela correspond à un nombre d’arcs égal à: (graphe non orienté)
    $$\tfrac{N \times (N-1)}{2}$$
    • La densité D d’un graphe est une indication générale de sa connectivité et indique s’il y a beaucoup ou peu d’arêtes. C’est le rapport entre le nombre d’arêtes existantes et leur nombre possible:
    $$D = \tfrac{2.A}{N \times (N-1)}$$

    Le graphe est creux si sa densité est proche de zero, et dense si elle se rapproche de 1.

    • Diamètre d’un graphe: plus longue distance entre sommets du graphe. Voir plus loin.

    Application: Choisir la structure de donnée adaptée

    Question: Pour chacun des exemples suivants, choisir le type de graphe adapté parmi: graphe orienté/non orienté, pondéré, non connexe, sans cycle. Précisez également ce que représentera un sommet, et ce qui sera une arête.

    • un reseau de villes reliées par des routes, comportant l’information de leur longueur (en km). Toutes les villes sont supposées être reliées par au moins une route. Ces routes sont toutes en double sens.
    • un reseau social de type Facebook, où les participants ont des liens d’amitié entre-eux. Ce lien est réciproque (si Marcel est ami avec Justine, alors Justine est aussi amie avec Marcel). Les sous-reseaux ne sont pas tous reliés entre eux. (Il existe au moins deux groupes A et B complètement indépendants: aucune des personnes de A n’est amie avec celles de B).
    • un reseau social de type Twitter: les participants ont des folowers. Cette relation n’est pas réciproque. Les folowers suivent les participants qui partagent les même centres d’intérêt.
    • une partie de jeu de morpion (tic-tac-toe), où les états de la partie sont liés aux états suivants possibles.

    Implémentations

    Plusieurs modes de représentation sont possibles pour stocker des graphes: matrices d’adjacence, listes des voisins, des successeurs ou des prédécesseurs. On peut les classer en 2 catégories:

    • Les représentations matricielles
    • Les représentations sous forme de liste chainée

    Liste de voisins et matrice d’adjacence

    Liste de voisins

    Un exemple simple présente ici un graphe créé à partir d’une liste de voisins: [[1, 2], [0, 2, 3], [0, 1, 3], [1, 2]]

    La première sous-liste correspond aux liens que forme le sommet 0. Ici, c’est donc avec les sommets 1 et 2.

    C’est aussi la représentation d’une liste chainée.

    Liste d’adjacence

    Cette liste L peut aussi être mise sous forme d’une matrice M:

    M = [[0, 1, 1, 0], [1, 0, 1, 1], [1, 1, 0, 1], [0, 1, 1, 0]]

    ce qui forme une matrice, en présentant les sous-listes l’une sous l’autre:

    $$\begin{pmatrix} 0 & 1 & 1 & 0 \\\ 1 & 0 & 1 & 1 \\\ 1 & 1 & 0 & 1 \\\ 0 & 1 & 1 & 0 \end{pmatrix}$$

    Avec la premiere sous-liste [0, 1, 1, 0] le sommet 0 est lié aux sommets 1 et 2, ce qui est signifié par le 1 aux index 1 et 2.

    graphe correspondant à la matrice M

    graphe correspondant à la matrice M

    Cette représentation en matrice est particulièrement adaptée aux graphes pondérés. On remplace alors le 1 dans la matrice par le poids de l’arête.

    Question: représenter le graphe pondéré dont la matrice d’adjacence est donnée ci-dessous:

    $$\begin{pmatrix} 0 & 10 & 10 & 9 \\\ 10 & 0 & 5 & 10 \\\ 10 & 5 & 0 & 10 \\\ 9 & 10 & 10 & 0 \end{pmatrix}$$

    Matrice de distance entre sommets

    Une matrice d’adjacence peut aussi indiquer la distance entre sommets. Soit le reseau social ci-dessous:

    un reseau social

    un reseau social

    Exemple issu de la page PythonLycee - auteur Franck CHEVRIER

    Simplifions la représentation de ce reseau social en un Graphe:

    avec etiquettes aux sommets

    avec etiquettes aux sommets

    Et utilisons la matrice d’adjacence pour indiquer le plus cours chemin d’un sommet à l’autre.

    matrice des distances entre sommets

    matrice des distances entre sommets

    Ainsi, une fois la matrice établie, nous pouvons en déduire le diamètre de ce graphe (plus grande longueur entre 2 sommets du graphe). Ici, cette distance vaut 3.

    Dans un graphe plus grand, la détermination du plus court chemin entre 2 sommets necessite une méthode basée sur un algorithme. Par exemple, l’algorithme BFS ou bien l’agorithme de Dijkstra.

    Graphe avec étiquette

    On utilisera un dictionnaire comme structure de données. Les clés étant les étiquettes des sommets, et les valeurs, la liste des sommets adjacents:

    D = {‘a’: [ ‘b’, ‘c’], ‘b’: [ ‘a’, ‘c’, ’d’], ‘c’: [ ‘a’, ‘b’, ’d’], ’d’ : [ ‘b’, ‘c’]}

    graphe correspondant au dictionnaire D

    graphe correspondant au dictionnaire D

    Question: Représenter la matrice d’adjacence équivalente.

    Liste (chainée) de successeurs

    Cette représentation est particulièrement adaptée aux graphes orientés.

    graphe orienté

    graphe orienté

    On peut représenter un graphe avec une liste chaînée des successeurs:

    sommet => liste de sommets liés suivants

    0 => 1, 2
    1 => ...
    2 => ...
    3 => ...

    Le sommet 0 aura alors 2 successeurs, les noeuds 1 et 2.

    Question: Compléter la liste de successeurs

    L’implémentation utilise le même principe que pour une liste chainée linéaire. Sauf qu’ici, le nombre de successeur est supposé être supérieur à 1.

    Il y aura alors plus d’un attribut suiv. Supposons que le degré sortant maximum est égal à 3:

    class Sommet:
    	def __init__(self,val,suiv1=None,suiv2=None,suiv3=None):
    		self.val = val # etiquette du sommet
    		self.suiv1 = suiv1
    		self.suiv2 = suiv2
    		self.suiv3 = suiv3
    
    S2 = Sommet(2)
    S1 = Sommet(1)
    S0 = Sommet(0,1,2)

    Liste (chainée) de predecesseurs

    Il peut être necessaire d’établir aussi, pour chaque sommet, une liste de predecesseurs:

    sommet => liste de sommets liés précédents

    0 => None
    1 => 0 
    2 => ... 
    3 => ...

    Question: Compléter la liste de prédécesseurs

    Modéliser le réseau internet

    Lien vers la page: réseau internet

    Cas particulier d’un arbre: un graphe hierarchique

    Lien vers la page arbres

    Liens

    adaptés à la term NSI

    plus loin, pour approfondir

    algorithmes de parcours d'un graphe

    Parcourir un graphe

    Principe

    Le parcours d’un graphe va donner une liste d’arcs ou de sommets visités, dans un certain ordre.

    Cet ordre va dépendre de l’algorithme employé: Pour des parcours de type largeur ou profondeur, on suppose que l’on peut revenir sur ses pas. La liste de sommets ne représente pas un chemin.

    On appelera chemin une suite continue de sommets (ou d’arcs) consécutifs dans le graphe, sans retour en arrière, c’est à dire sans revenir vers un sommet déjà visité.

    Parcours d’un graphe en largeur BFS

    • Principe: BFS (Breadth-First Search): Il s’agit d’une exploration du graphe G, de proche en proche, en explorant tous les chemins, depuis la distance de longueur 1 du sommet, puis la distance 2, …
    • Algorithme : voir définition en bas de page1
    • Graphe : voir définitions à la page Graphes

    Voici le programme python de parcours en largeur d’un graphe:

    • Programme de type itératif:
    from collections import deque
    
    def BFS(d,s,visited=[], queue=deque()):
            queue.append(s)
            while queue:
                v = queue.popleft()
                if v not in visited:
                    visited.append(v)
                    unvisited = [n for n in d[v] if n not in visited]
                    queue.extend(unvisited)
                    print(queue)
            return visited

    Parcours d’un graphe non pondéré

    Soit G(V,E) un graphe de sommets V = {A,B,C,D,E,F,G,H,I,J} et d’arêtes E.

    On note la distance entre 2 sommets quelconques u et v dans le graphe G :

    $$dist_G(u,v)$$

    Pour le graphe exemple suivant (Graphe 1), la distance du sommet A au sommet J, vaut au minimum 4 (chemin A, B, E, I, J). Mais cela depend du chemin. Ainsi :

    $$dist_G(A,J)=4$$

    .

    graphe illustratif

    Graphe 1 : exemple

    Calculons toutes les distances dans ce graphe : L’algorithme de parcours en largeur (Breadth-First Search BFS)

    Principe : Pour déterminer la longueur de tous les chemins du graphe, il va falloir le parcourir. Lors du parcours, certains sommets seront colorés, pour nous rappeler qu’ils ont été parcouru (rouge), ou en cours de parcours (vert).

    On aura besoin de conserver une liste L des sommets à explorer.

    On commence l’exploration en partant d’un sommet r. Voici la méthode :

    1. Colorer en VERT le sommet r pour se rappeler qu’il a déjà été partiellement traité.
    2. Parcourir le graphe depuis r jusqu’à l’un de ses voisins u, non coloré en vert ou rouge. Colorer u en VERT.
    3. Noter la distance du sommet de départ r vers le sommet u en cours d’exploration : distG(r,u) = 1 si le sommet voisin u est adjacent.
    4. Ajouter le nom du sommet u à droite dans la liste L: L = [r,u]
    5. Si r a d’autres sommets adjacents, revenir au point 2 et explorer un autre de ces sommets (points 2, 3, 4).
    6. Si r n’a plus de sommet adjacent non visité, colorer r en rouge. Retirer r de la liste (premier sommet, à gauche dans la liste L). L ayant une structure de FILE, on dit que l’on défile r.

    On poursuit ensuite l’exploration à partir du nouveau premier sommet v adjacent de u. La distance de r à v est alors : distG(r,v) = distG(r,u) + 1 (point 3).

    Lorsque la liste L est vide, l’exploration est terminée et toutes les distances entre r et les autres sommets est connue.

    Exemple :

    A partir du graphe 1 défini plus haut, on démarre l’exploration à partir du sommet r = E.

    Celui ci est coloré en VERT.

    La méthode vue plus haut permet de rapidement établir la liste L = [E,B,F,H,I] à partir des sommets adjacents à E. Les sommets B,F,H,I sont à une distance 1 du sommet E. On a par exemple distG(E,B) = 1. Ces sommets sont colorés en VERT.

    Une fois cette première partie de l’exploration terminée, on retire E de la liste L, et on colore le sommet en rouge.

    premiere partie parcours BFS

    L = [B,F,H,I]

    On note la distance au sommet E pour chacun des sommets visités, le symbole ∞ pour ceux qui ne l’ont pas encore été:

    exploration depuis le sommet… A B C D F G H I J
    E ∞ 1 ∞ ∞ 1 ∞ 1 1 ∞

    On se déplace maintenant sur le sommet B, qui est le premier de la liste.

    L’exploration de ses sommets adjacents continue, à conditions que ceux-ci soient blancs, sinon, on passe à un autre sommet. Ici, on fait l’exploration des sommets A,C,D. Ceux-ci sont colorés en VERT, et ajoutés à la liste L:

    $$L = [F,H,I,A,C,D]$$

    Les distances de E à chacun de ces nouveaux noeuds sont enregistrées : distG(E,A) = 2, tout comme distG(E,C) et distG(E,D). Le tableau suivant donne les distances depuis le sommet E:

    exploration depuis le sommet… A B C D F G H I J
    B 2 2 2 ∞ ∞

    Les distances déjà connues ne sont pas modifiées. On laisse un blanc dans le tableau.

    On colore ensuite le sommet B en rouge et on le retire de la liste L.

    premiere partie parcours BFS

    L = [F,H,I,A,C,D]

    Ensuite, depuis le sommet F: on explore le graphe jusqu’au sommet G, seul sommet adjacent encore blanc.

    On a alors distG(E,G) = 2, puis le sommet F est mis en rouge et retiré de la liste:

    $$L = [H,I,A,C,D,G]$$
    exploration depuis le sommet… A B C D F G H I J
    F 2 ∞

    On poursuivra l’exploration par le sommet H, suivant dans la liste. Ce qui permettra de définir le dernier chemin jusqu’à J, et noter distG(E,J) = 2:

    exploration depuis le sommet… A B C D F G H I J
    H 2

    A la fin du traitement, on peut représenter à l’aide d’un arbre tous les chemins issus de l’exploration du graphe :

    arbre parcours BFS

    arbre du parcours BFS

    Pour réaliser cet arbre, il y aura 2 méthodes:

    • Soit la construction d’un tableau des sommets visités au fur et à mesure de l’exploration (vu plus haut)
    • Soit remonter chaque étape du parcours du graphe le parent du sommet visité. (voir fiche d’exercices). Ainsi, il aura faudra se rappeler que le sommet D a pour parent le noeud B (D est marqué dans le tableau dont l’entrée est B). Et le sommet B a lui même pour parent le sommet E. Ainsi, en remontant le chemin, on sait que le chemin de E à D passe par B : E => B => D.

    Pour aller plus loin (term NSI)

    • Consulter la page du parcours en largeur sur wikipedia

    • Algorithme de Dijkstra (plus court chemin dans un graphe pondéré)

    • Application de l’algorithme BFS au parcours dans un labyrinthe:

    maze BFS

    video: Maze Pathfinder - Breadth First Search (BFS)

    Parcours d’un graphe en profondeur (DFS)

    Principe: L’exploration DFS (Depth-First Search) retourne une liste de sommets, parcourus en plongeant dans la profondeur du graphe. Le prochain sommet visité est un des successeurs du sommet courant, avec un retour en arrière lorsque’il n’y a pas de nouveau successeur, ou bien lorsque celui-ci a deja été visité.

    Voici les 2 programmes python de parcours en profondeur d’un graphe:

    • récursif:
    def DFS(d,s,visited=None):
        if visited==None:visited=[]
        visited.append(s)
        for v in d[s]:
            if v not in visited:
                DFS(d,v,visited)
        return visited
    • Itératif:
    def DFS_ite(d,s,visited=[], stack=[]):
            stack.append(s)
            while stack:
                v = stack.pop()
                if v not in visited:
                    visited.append(v)
                    unvisited = [n for n in d[v] if n not in visited]
                    stack.extend(inverse(unvisited))
            return visited
    
    def inverse(L):
    	# fonction utile pour avoir le meme ordre de parcours 
    	# des sommets adjacents, pour les fonctions DFS et DFS_ite
        return [L[i] for i in range(len(L)-1,-1,-1)]

    Remarque: La fonction inverse est utile pour avoir les mêmes parcours DFS, en itératif et récursif. On peut la programmer comme ci-dessus, ou bien en utilisant un slice de la manière suivante: stack.extend(univisited[::-1])

    L = [1,2,3,4]
    L = L[::-1] # copie par valeur de la liste inversée
    print(L)
    # affiche [4,3,2,1]

    Principe

    Soit un graphe G = (V,E) et r un sommet de G, point de départ de l’exploration. Le parcours en profondeur du graphe va permettre de visiter tous les noeuds du graphe, mais selon un chemin où l’on plonge dans la profondeur du graphe. Le prochain sommet visité sera un sommet fils non encore visité.

    A chaque étape, c’est à dire à chaque arête suivie, il faudra mémoriser le parent du nouveau sommet visité. (une fois celui-ci placé dans la liste des sommets parcourus, pas découverts). Cela permettra de revenir en arrière. On utilisera pour cela une structure de PILE. On reviendra en arrière en dépilant le dernier sommet de la liste.

    Lorsque le chemin mène à une impasse, (il n’y a plus de sommet fils non visité), lorsque l’on est sur un bord du graphe, alors on remonte d’un niveau, vers un sommet parent, avant de poursuivre l’exploration.

    En pratique :

    • tous les sommets ont d’abord colorés en BLANC.
    • On colore chaque noeud u visité en VERT.
    • Lorsque tous les noeuds fils de u sont visités, on colore celui-ci en ROUGE.

    Illustration : Avec le graphe suivant, on démarre l’exploration du noeud G :

    graphe parcours profondeur

    exemple de graphe pour le parcours en profondeur

    La première étape est la phase de descente : On peut démarrer l’exploration par le sommet voisin A ou B. Les deux sont possibles. Ils sont de couleur BLANCHE.

    Supposons que l’on commence l’exploration par B (on aurait tout aussi bien choisir le A). On colore alors B en VERT.

    On poursuit l’exploration par les sommets suivants : D,C,A (il y a d’autres possibiltés) :

    graphe parcours profondeur

    étape 1

    Le sommet A est un bord du graphe : il n’y a pas de noeud fils BLANC. On remonte alors d’un niveau : jusqu’au sommet C. Celui ci ne presente pas davantage de voisin BLANC. A et C sont colorés en ROUGE et on remonte à D.

    On peut alors poursuivre l’exploration vers E :

    graphe parcours profondeur

    étape 2

    Depuis le sommet E, on peut visiter F et I. Choisissons F (mais on pourrait choisir également I) :

    graphe parcours profondeur

    étape 3

    On poursuit l’exploration jusqu’en I. Tous les sommets sont visités, et l’exploration est terminée.

    graphe parcours profondeur

    fin du parcours

    Le schéma suivant illustre le parcours réalisé à partir des arêtes empruntées. Il s’agit d’un arbre couvrant le graphe :

    graphe parcours profondeur

    arbre couvrant

    Applications

    Le parcours d’un graphe en profondeur s’apparente à un algorithme de type retour sur trace, ou backtracking. C’est le comportement de joueur que l’on a lorsque l’on a droit à un nouvelle chance :

    • Dans un jeu d’echec, lorsque l’on joue contre l’ordinateur, une option permet de revenir en arrière. On peut revenir un coup en arrière et prendre une meilleure option. L’ordinateur construit un graphe au fur et à mesure du jeu avec les coups joués ainsi que la configuration du jeu, afin de permettre ce backtracking.
    • Lorsque l’on joue à un jeu de labyrinthe (illustration site zestedesavoir): Si on arrive dans une impasse, on adopte là aussi un algorithme de type retour sur trace. On revient jusqu’au noeud parent (le croisement précédent) afin d’explorer une nouvelle voie. Et si toutes ces voies sont sans issues, on remonte encore d’un niveau (le croisement précédent encore celui ci).

    Parcourir un graphe pour trouver TOUS les chemins

    Il s’agit d’une variante du parcours en profondeur.

    Pour un graphe G, le problème s’énonce de la manière suivante:

    Pour un sommet de départ A, créer un nouveau chemin pour chaque sommet adjacent à A de la manière suivante:

    • Commencer le chemin avec la liste de sommets [A]
    • Si le sommet adjacent est un nouveau sommet, n’appartenant pas déjà un chemin.
      • ajouter le nouveau sommet adjacent au chemin, par exemple [A,B]
      • ajouter ce chemin à la liste des chemins
      • continuer avec cette même méthode depuis le sommet adjacent (appel recursif avec le sommet adjacent comme nouveau départ, et placer chemin en paramètre)

    A la fin, retourner la liste des chemins.

    Illustration:

    départ du sommet A

    départ du sommet A

    poursuite du chemin vers B

    poursuite du chemin vers B

    Script:

    def parcours(G, depart,lst_chemins, chemin = []):
        if chemin == []:
            chemin = [depart]
        for sommet in G[depart]:
            if sommet not in chemin:
                lst_chemins.append(chemin + [sommet])
                parcours(G, sommet, lst_chemins, chemin + [sommet])
        return lst_chemins

    Graphe: implémentation à l’aide d’un dictionnaire de listes d’adjacence

    G = {'A':['B','F'],
        'B':['A','C','D','G'],
        'C':['B','E'],
        'D':['B','I'],
        'E':['C','I'],
        'F':['A','G','H'],
        'G':['B','F','I'],
        'H':['F','I'],
        'I':['D','E','G','H']}

    Exemple:

    > lst_chemins = []
    > parcours(D,1,lst_chemins)
    [['A', 'B'],
     ['A', 'B', 'C'],
     ['A', 'B', 'C', 'E'],
     ['A', 'B', 'C', 'E', 'I'],
     ['A', 'B', 'C', 'E', 'I', 'D'],
     ['A', 'B', 'C', 'E', 'I', 'G'],
     ['A', 'B', 'C', 'E', 'I', 'G', 'F'],
     ['A', 'B', 'C', 'E', 'I', 'G', 'F', 'H'],
     ['A', 'B', 'C', 'E', 'I', 'H'],
     ['A', 'B', 'C', 'E', 'I', 'H', 'F'],
     ['A', 'B', 'C', 'E', 'I', 'H', 'F', 'G'],
     ['A', 'B', 'D'],
     ['A', 'B', 'D', 'I'],
     ['A', 'B', 'D', 'I', 'E'],
     ...
     ... ]

    Liens


    1. algorithmes : ce sont des méthodes qui, exécutées pas à pas, permettent d’obtenir un résultat final à partir de données de départ. ↩︎

    arbres

    Ce cours comporte plusieurs pages:

    Arbres

    Définitions

    Un arbre est constitué de noeuds organisés de manière hierarchique: c’est un graphe non orienté, connexe, sans cycle, dans lequel on a choisi un noeud particulier appelé la racine.

    Chaque noeud peut être étiqueté par une information.

    Un arbre est donc un cas particulier des graphes. Voir la page suivante sur les graphes

    On parle de descendants pour les noeuds fils.

    Des exemples d’arbres:

    • l’arbre généalogique est un bon exemple. Le vocabulaire sur la structure des arbres s’inspire d’ailleurs de la génélogie (père-fils).
    family tree sur freepik.com/genealogie

    family tree sur freepik.com/genealogie

    Les noeuds sont …les couples.

    • L’arbre représentant les sytèmes de dossiers sur ordinateur (dossiers et sous-dossiers puis fichiers)Ci-dessous l’arborescence de fichiers dans un raspberry-Pi:
    arborescence linux

    arborescence linux

    • arbre représentant des expressions arithmétiques

    expression arithmetique

    Retrouver l'expression arithmetique correspondante

    Les arbres sont très utilisés en informatique, d’abord parce que les données sont souvent hierarchisées, et se prêtent bien à cette structure. Mais aussi parce que l’accès à ces données est alors plus efficace: la recherche d’une valeur se fait en O(log(n)) dans le cas moyen, où n est la taille de l’arbre.

    Caractéristiques d’un arbre

    caracteristiques d

    exemple d'arbre binaire et vocabulaire

    • Dans un arbre, chaque valeur est stockée dans un nœud. On appelle parfois cette valeur une clé.
    • Les nœuds sont connectés par des arêtes, ou branches qui représentent une relation de type “parent (prédécesseur est le terme exact) – fils”.
    • Chaque noeud ne possède qu’un seul noeud parent (sauf le noeud racine).
    • La racine est le seul nœud qui n’a pas de prédécesseur.
    • Les nœuds qui n’ont pas de fils sont appelés des feuilles.
    • Des nœuds qui ont le même père sont appelés des frères.
    • Un sous-arbre c’est une portion de l’arbre. C’est une notion utile pour la recursivité.
    • Le niveau d’un nœud est la distance qui le sépare de la racine… Sachant que le niveau de la racine est 0 et que le niveau d’un nœud quelconque c’est 1+ le niveau de son père.
    • La hauteur d’un arbre, ou sa profondeur est égale au niveau (à la profondeur) du noeud le plus profond. Selon la convention proposée ici (le niveau de la racine vaut 0), la hauteur correspond aussi au plus grand nombre de branches depuis la racine jusqu’à l’une de ses feuilles.
    • Le degré d’un arbre est egal au plus grand des degrés de ses noeuds.
    • Un arbre de degré égal à 1 est … une liste.
    degré d

    Quel est le degré de cet arbre?

    • La taille d’un arbre est son nombre de noeuds.
    dimensions d

    dimensions d'un arbre

    Arbres binaires

    • Arbre binaire: arbre de degré égal à 2. Chaque noeud a au plus 2 fils: le fils droit et le fils gauche.
    • Arbre binaire équilibré: pour chaque noeud interne, les sous-arbres gauche et droit ont une même hauteur (ou qui diffère d’une unité).
    • Arbre binaire complet: tous les niveaux de l’arbre sont remplis.

    La taille d’un arbre binaire peut alors se déduire de la formule, qui prend la profondeur p en paramètre:

    $$T = \sum_{0}^{n-1} 2^p = 2^n-1$$

    sous arbres droit et gauche

    definition recursive des arbres binaires

    arbre complet

    arbre complet

    Implémenter en python

    On utilisera l’arbre suivant pour l’implémentation en python:

    exemple d

    exemple d'arbre binaire de taille 9

    Comme vu pour les graphes, on pourra utiliser des listes imbriquées, un dictionnaire, ou une classe (programmation objet).

    Liste

    Un noeud peut être représenté par une liste imbriquée [clé,fils gauche,fils droit].

    Et comme les fils gauche ou fils droit sont des noeuds, on y mettra une nouvelle liste imbriquée [clé,fils gauche,fils droit].

    Pour les feuilles, la liste s’écrit: [clé,None,None].

    Le petit arbre suivant peut être représenté par ['r',[‘a’,None,None],[‘b’,None,None]]`

    petit arbre de taille 3

    petit arbre de taille 3

    Avec l’arbre de taille 9 donné en exemple:

    arbre9 = [3,[...,..,..],[...,..,..]]

    Question: compléter cette liste.

    Classe

    La classe suivante va permettre d’implémenter les arbres binaires:

    class ArbreBinaire:
        def __init__(self, valeur):
            self.valeur = valeur
            self.fils_gauche = None
            self.fils_droit = None

    On n’a donné ici que le constructeur, mais il est possible d’y ajouter les méthodes qui permettront de retourner une valeur (getter), ou d’ajouter un noeud (setter); ou encore de déterminer les dimensions de l’arbre.

    Avec l’arbre de taille 9 vu plus haut, la classe peut s’utiliser de la manière suivante (avec la notation pointée qui n’est pas recommandée):

    racine = ArbreBinaire(8)
    noeud1 = ArbreBinaire(3)
    noeud2 = ArbreBinaire(10)
    noeud3 = ArbreBinaire(1)
    ...
    racine.fils_gauche = noeud1
    racine.fils_droit = noeud2
    noeud1.fils_gauche = noeud3
    ...

    Ou bien, en supposant que vous ayez ajouté deux méthodes de classe ajoute_fils_gauche et ajoute_fils_droit:

    racine = ArbreBinaire(8)
    noeud1 = ArbreBinaire(3)
    noeud2 = ArbreBinaire(10)
    noeud3 = ArbreBinaire(1)
    ...
    racine.ajoute_fils_gauche(noeud1)
    racine.ajoute_fils_droit(noeud2)
    noeud1.ajoute_fils_gauche(noeud3)

    Parcours

    Definition: Un parcours est un algorithme qui appelle une fonction, ou un méthode sur tous les noeuds d’un arbre.

    L’ordre sur les noeuds dans lequel la méthode est appelée doit être fixé. Il y a plusieurs choix, qui diffèrent par la seule position de l’instruction Afficher clef [ r ]

    L’algorithme opère alors un traitement sur chacune des clés de l’arbre, dans un ordre choisi. Ici, on cherche à Afficher la clef.

    Mais on peut remplacer cette instruction par un traitement sur les valeurs: ajouter 1 pour compter les clés par exemple.

    Parcours postfixe

    ParcoursPostfixe ( Arbre binaire T de racine r ) 
      ParcoursPostfixe(Arbre de racine fils_gauche[r]) 
      ParcoursPostfixe(Arbre de racine fils_droit[r])
      Afficher clef [ r ]

    Parcours préfixe

    ParcoursPréfixe ( Arbre binaire T de racine r ) 
      Afficher clef [ r ]
      ParcoursPréfixe(Arbre de racine fils_gauche[r]) 
      ParcoursPréfixe(Arbre de racine fils_droit[r])

    Parcours infixe

    ParcoursInfixe ( Arbre binaire T de racine r ) 
      ParcoursInfixe(Arbre de racine fils_gauche[r]) 
      Afficher clef [ r ]
      ParcoursInfixe(Arbre de racine fils_droit[r])
    exemples de parcours

    exemples de parcours

    Parcours en largeur

    Les trois algorithmes vus plus haut s’apparent à une exploration de type parcours en profondeur. C’est la position de l’instruction de traitement qui amène les différences entre ces 3 parcours.

    Un arbre est un graphe. On peut donc lui appliquer l’algorithme de parcours en largeur vu dans une leçon précédente.

    Rappel:

    from collections import deque
    
    def BFS_ite(d,s,visited=[], queue=deque()):
            queue.append(s)
            while queue:
                v = queue.popleft()
                if v not in visited:
                    visited.append(v)
                    unvisited = [n for n in d[v] if n not in visited]
                    queue.extend(unvisited)
                    print(queue)
            return visited

    t

    Travaux pratiques

    Sur Capytale

    => Lien vers le notebook

    Sur Google Colab

    • telecharger le fichier module hierarchyP (faire un clic droit et enregistrer sous…)
    • utiliser le lien suivant pour acceder au notebook colab

    Notebook avec un IDE local

    Liens

    • cours de l’Université Paris Sud: Lien

    architecture

    Sous-sections de architecture

    fichiers

    Gestion des fichiers et systemes d’exploitation

    Pourquoi des fichiers?

    Le processeur et le coeur du système d’exploitation (le noyau) s’associent pour optimiser au mieux l’usage de la mémoire principale grâce aux espaces de mémoire virtuelle, alloués au processus. Cependant cette mémoire est de taille limitée, et ne conserve pas son état lors d’une coupure de l’alimentation. Pour répondre à ces problèmes, le système d’exploitation propose à l’utilisateur et au processus un système de fichiers.

    Un fichier est une zone mémoire physique de taille limitée stockant des données de manière persistante.

    Cette mémoire dite secondaire, est une mémoire de stockage ou mémoire de masse. Elle peut être un disque dur un CD une carte mémoire SD etc. Ces données stockées sur un tel support doivent pouvoir être relus une fois la mémoire RAM éteinte. On peut aussi vouloir déplacer un disque et l’utiliser sur un système d’exploitation qui n’a aucune information a priori sur le contenu de ce disque.

    Les applications ont justement besoin de fichiers pour stocker leurs programmes et pour sauvegarder des données.

    Système de fichiers, organisation dans le disque physique

    On peut distinguer deux types de fichiers:

    • les fichiers texte écrit en ascii ou UTF-8. Chaque octet ou chaque mot de 16 bits correspond à un caractère.
    • les fichiers binaires. Le fichier n’est qu’une liste de nombres sans sens si on ne connaît pas le format et le logiciel associé. Ce format est annoncé par une extension.

    Chaque fichier a un nom, dont une extension (obligatoire sous Windows facultatif sous Linux): txt, docx, html, json, jpg, mp3, …

    Un fichier est une collection de données numériques qui se partagent entre des données (principales), et des métadonnées (quelques dizaines d’octets). Les metadonnées sont la taille, la date de création et/ou de modifications, le propriétaire, les droits d’accès, et l’adresse sur le disque.

    Le système de fichiers gère la structuration le nommage l’accès la protection et l’implantation des fichiers, avec les adresses des blocs sur le disque physique.

    Plusieurs systèmes de fichiers co-existent (FAT32 et NTFS pour Windows, EXT4 Linux). Ces informations sur le contenu du disque ainsi que sur les fichiers sont rappelés dans un super bloc, au début de la partition, ce qui permet de déplacer le disque et le lire avec un autre système. Il comporte toutes les informations nécessaires à la compréhension de son système de fichiers.

    Le rôle du système d’exploitation

    Le système d’exploitation vérifie les droits d’accès en lecture/écriture/exécution. Il peut verrouiller tout ou partie d’un fichier, ainsi que l’accès simultané en écriture à un même fichier par deux processus, ce qui pourrait le corrompre. Enfin, il copie une partie du fichier, la plus interessante selon le processus, sur la mémoire RAM. Au final, un processus n’a jamais vraiment accès au fichier lui-même, mais à une représentation, sur la RAM.

    Pour faciliter l’accès aux fichiers, les systèmes d’exploitation présentent ceux-ci selon une arborescence de dossiers appelés aussi repertoires.

    Pour accéder à un fichier, il faut donc indiquer un chemin.

    Un dossier est alors un simple fichier indiquant les fichiers et les dossiers (donc des fichiers), à l’interieur.

    L’opération dite de montage revient à associer à un dossier un système de fichiers différents. Cela se fait lorsque l’on connecte par exemple une clé usb.

    Les systèmes d’exploitation graphiques (MS Windows, Linux Ubuntu, Mac OS, …) disposent de logiciel d’exploration des fichiers, et associent à chaque type de fichier un pictogramme appelé icône.

    Linux

    Sous Linux, tout est fichier. Il y a 4 catégories de fichiers:

    • fichiers normaux (fichiers textes, sources de programmes, fichiers binaires, …)
    • fichiers répertoires: des fichiers containers, qui contiennent des références vers d’autres fichiers
    • fichiers speciaux: situés sous /dev, ce sont les points d’accès vers les peripheriques.
    • les fichiers liens symboliques: ne contiennent qu’une référence vers un autre fichier. (les raccourcis sous windows) Cela permet d’avoir un même fichier, à differents emplacements, avec des noms différents.

    Ainsi, lorsque l’on branche un nouveau disque physique, un chemin d’accès est defini dans l’arborescence du système (par exemple /media/fred)

    Windows

    Dans le monde Windows, contrairement aux systèmes Linux, les partitions et périphériques de stockage possèdent leur propre arborescence, dont la racine porte un nom d’une seule lettre : A: C: D: …

    Manipulation des fichiers et dossiers

    Les systèmes d’exploitation courants possédent une interface graphique et ont des logiciels d’exploration évolués et intuitifs (Explorateur de fichiers sous Windows, Gestionnaire de fichiers sous Ubuntu, …). L’explorateur permet de:

    • naviguer aisément dans l’arborescence,
    • déplacer/copier/coller des fichiers et des dossier, y compris par glisser/déposer,
    • *lancer des applications et ouvrir des documents, obtenir des informations avancées sur les fichiers et dossier (métadonnées),
    • réaliser des recherches de fichiers et dossiers,
    • créer de nouveaux documents,
    • …

    Mais ce n’est pas la seule façon de naviguer dans l’arborescence: les systèmes d’exploitation permettent aussi de réaliser ces fonctions en ligne de commande, à partir d’un terminal (une fenêtre qui interface l’utilisateur avec un interpreteur).

    Suite

    Liens

    systeme d'exploitation

    Systeme d’exploitation

    En informatique, un système d’exploitation (souvent appelé OS — de l’anglais Operating System) est un ensemble de programmes qui dirige l’utilisation des ressources d’un ordinateur par des logiciels applicatifs. Lien Wikipedia

    Il reçoit des demandes d’utilisation des ressources de l’ordinateur — ressources de stockage des mémoires (par exemple des accès à la mémoire vive, aux disques durs), ressources de calcul du processeur central, ressources de communication vers des périphériques (pour parfois demander des ressources de calcul au GPU par exemple ou tout autre carte d’extension) ou via le réseau — de la part des logiciels applicatifs. Le système d’exploitation gère les demandes ainsi que les ressources nécessaires évitant les interférences entre les logiciels.

    Processus et blocages

    Définitions

    Exécution d’un programme: le lancement d’un programme entraîne des lectures et écritures dans des registres et une partie de la mémoire. Le microprocesseur réalise des opérations sur les données mises dans les registres.

    Un processus représente une instance d’exécution d’un programme dans une machine donnée, qui a sa propre zone mémoire virtuelle.

    Les états d’un processus

    Les systèmes d’exploitation sont capables de gérer l’execution de plusieurs processus en même temps. En réalité, ce n’est pas tout à fait en même temps: pour gérer ce chacun son tour, les systèmes d’exploitation attribuent des états au processus.

    Ces états sont résumés ci-dessous.

    • Lorsqu’un processus est créé, il démarre dans l’état prêt: il attend l’accès au processeur.
    • Le processus obtient, grâce au systeme d’exploitation, l’accès au processeur. Il passe alors dans l’état élu.
    • Alors qu’il est élu, le processus peut avoir besoin d’attendre une ressource quelconque comme, par exemple, une ressource en mémoire ou sur le disque dur. Il doit alors quitter momentanément le processeur pour que celui-ci puisse être utilisé à d’autres tâches (le processeur ne doit pas attendre!). Le processus passe donc de l’état élu à l’état bloqué. (c’est un blocage)
    • Lorsque le processus a obtenu la ressource attendue mais s’est fait prendre sa place dans le processeur par un autre processus, il se met en attente: C’est l’état prêt, en attente que la place se libère. Cette étape, de bloqué à prêt est l’opération de déblocage.
    • Le passage de l’état prêt vers l’état élu constitue l’opération d’élection.
    • Un processus ne pourra terminer que s’il est déjà dans l’état élu.

    mecanisme d'election

    mecanisme d'election

    Un processus peut créer un ou plusieurs nouveaux processus. Il y a alors une filiation père-fils.

    Chaque processus possède un numéro PID qui lui est attribué automatiquement. Il possède aussi un PPID qui est le numéro d’identification du processus père.

    Ordonnancement

    Plusieurs processus peuvent être dans l’état prêt: comment choisir celui qui sera élu?

    L’ordonnanceur (sheduler) classe les processus prêts dans une file et les fait passer du statut prêt à élu (et inversement). Il planifie l’exécution des processus.

    Dans les systèmes d’exploitation, l’ordonnanceur désigne le composant du noyau du système d’exploitation choisissant l’ordre d’exécution des processus sur les processeurs d’un ordinateur. Cette organisation permet d’occuper au mieux le (ou les) processeurs.

    gestion des processus

    gestion des processus

    Il existe plusieurs politiques d’ordonnancement dont le choix va dépendre des objectifs du système. Voici quelques exemples:

    • Premier arrivé, premier servi: simple, mais peu adapté à la plupart des situations.
    • Plus court d’abord: très efficace, mais il est la plupart du temps impossible de connaître à l’avance le temps d’exécution d’un processus.
    • Priorité: le système alloue un niveau de priorité aux processus (SCHED_FIFO sur Linux). Cependant des processus de faible priorité peuvent ne jamais être élus.
    • Tourniquet: un quantum de temps est alloué à chaque processus (SCHED_RR sous Linux). Si le processus n’est pas terminé au bout de ce temps, il est mis en bout de file en état prêt.
    • Un système hybride entre tourniquet et priorité qu’on retrouve dans les systèmes Unix.

    Interblocage

    Concurents mal synchronisés

    L’ordonnanceur fait passer les processus de élu à commuté. Mais Il peut y avoir une situation où 2 processus sont interbloqués car:

    • P1 possède la ressource R1 mais souhaite R2: commutation pour P2
    • P2 possède la ressource R2 mais souhaite R1: commutation pour P1

    Dans cette situation, les deux processus légers sont définitivement bloqués.(wiki)

    Des solutions de détection/guérison peuvent être mises en place.

    Définition sur Wikipedia

    Deux processus en concurrence pour deux ressources dans un ordre opposé. Voici une chronologie possible qui mène à un interblocage.

    A) Un seul processus se déroule.

    B) Le processus ultérieur doit attendre.

    C) Un blocage se produit lorsque le premier processus verrouille la première ressource en même temps que le second processus verrouille la seconde ressource.

    D) Le blocage peut être résolu en annulant et en redémarrant le premier processus.

    Modélisation par un graphe orienté

    Il y a interblocage lorsque des cycles sont présents dans le graphe réalisé de la manière suivante:

    • un arc de la ressource Ri au processus Pj signifie que le processus Pj a obtenu la ressource
    • un arc Pj vers Ri signifie que le processus Pj demande la ressource Ri.
    interblocage - wikipedia

    interblocage - wikipedia

    Exemple: le processus P1 utilise la ressource R2 qui est attendue par le processus P2 qui utilise la ressource R1, attendue par P1.

    Illustration d’un interblocage routier

    saurez vous modéliser la situation suivante par un graphe présentant un cycle?

    saurez vous modéliser la situation suivante par un graphe présentant un cycle?

    Gestion des tâches par une même application

    Un thread est un élément d’un processus qui va partager avec un programme l’espace des données et va s’exécuter de façon simultané avec d’autres thread. On parle aussi de processus légers.

    Plusieurs threads peuvent exister dans le même processus. Ces threads partagent la mémoire et l’état du processus. En d’autres termes: ils partagent le code ou les instructions et les valeurs de ses variables.

    partage des ressources par 3 threads

    partage des ressources par 3 threads

    Ils peuvent aussi causer de multiples problèmes (accès concurent, interblocage).

    On a vu un problème identique sur la gestion concurente des accès à une même ressource sur le chapitre sur les SGBD.

    TP Terminal Linux et gestion des processus

    TP 1: les bases du terminal Linux

    Voir l’énoncé du TP à l’adresse suivante: TP NSI

    • explorateur en ligne de commande
    • utilisateurs, groupes, droits

    TP 2: processus

    Pour ce TP, utiliser le terminal Linux du TP 1.

    1. Créer un nouveau fichier test.sh
    $ touch test.sh
    $ nano test.sh
    1. Editer le fichier à l’aide de l’editeur nano
    #!/bin/sh
    echo Hello World
    • CTRL X puis Y puis valider le nom du fichier pour sortir
    1. Executer le fichier
    $ test.sh

    Il faudra peut-être modifier les droits en execution pour ce fichier:

    • Vérifier que vous avez les droits en execution sur le fichier:
    $ ls -l

    Vous devriez avoir x pour les droits d’execution sur ce fichier en tant que user. Sinon, saisir la commande suivante:

    # chmod u+rx test.sh

    … et contrôlez que vous avez ajouté x à user (et même r). Puis executer le fichier.

    1. Modifier le fichier et créer une boucle infinie

    Modifier le script test.sh avec les commandes suivantes:

    #!/bin/sh
    while true
    do
    	sleep 1
    done

    et executer le script en mode détaché:

    $ test.sh &
    1. vérifier alors les processus actifs avec la commande top
    • Relever les valeurs du PID et du PPID du programme qui boucle en tâche de fond: test.sh
    • Sortir de top: q
    1. Tuer le programme
    $ kill {PID}
    1. Vérifier que le processus est bien Dead…

    Liens

    graphes et internet

    Ce cours comporte plusieurs pages:

    Modéliser le réseau internet

    réseau internet

    Le reseau internet repose sur :

    • l’usage de datagrammes pour transmettre l’information
    • le routage de ces datagrammes par des ordinateurs spécialisés, … les routeurs.

    Le reseau internet est un reseau qui connecte entre eux des reseaux, à l’echelle mondiale. Voir lien vers la page Reseaux de seconde SNT pour revisions

    Le datagramme: les informations échangées

    Dans le modèle TCP/IP, les ordinateurs peuvent établir et réaliser une communication selon plusieurs couches, qui cloisonnent les logiciels et technologies utilisées. D’après la norme, les couches vont de la plus haute (couche 7: l’utilisateur) à la plus basse (couche 1: support physique).

    Lorsque vous envoyez une requête ou un fichier à une machine distante, les logiciels installés vont fabriquer des trames de 1500 octets, dont le datagramme contient les données utiles pour la transmission (dont l’adresse IP du destinataire et de l’emetteur), et les informations à transmettre, le tout sous format binaire.

    Souvent, les informations à transmettre occupent un poids trop important pour être placées dans une trame de 1500 octets. Il faudra alors plus d’une trame pour envoyer les différents paquets, qui devront être reconstruits à l’arrivée.

    Durant le trajet à travers les différentes couches du modèle OSI, 4:application, 3:transport, 2:internet et 1: hôte-réseau , le datagramme subira des modifications et chaque couche rajoutera ce qu’elle voudra:

    • La couche 4:transport va ajouter les informations utiles pour contrôler l’arrivée l’ordre des paquets envoyés: résolu par le protocole TCP.
    • La couche 3:internet va ajouter les informations utiles pour interconnecter les réseaux: résolu par le protocole IP.

    Ce mécanisme s’appelle l’encapsulation, car les données de la couche 2 vont contenir celles de la couche 3, etc…

    Ainsi, à la sortie de la couche 2, la requête HTTP issue de votre navigateur est transformée en une série de données que l’on peut segmenter en:

    [en-tête Ethernet, wifi ou 4G][en-tête IP][en tête TCP][requête HTTP][checksum Ethernet]

    La machine distante, qui reçoit cette trame, va alors repondre immédiatement en envoyant un accusé de reception.

    principe de l

    principe de l'emission - reception d'une trame sur internet

    envoi d'un accusé de reception

    envoi d'un accusé de reception

    Les machines

    Les machines reliées dans le réseau internet peuvent être:

    • un ordinateur (machine hôte)
    • une imprimante
    • un commutateur (switch) : mis en reseau de manière centralisée, n’a pas d’adresse IP, agit au niveau de la couche 2, connecte les machines dans le sous-reseau, sert à envoyer les trames au destinataire direct, ne possède pas d’adresse IP.
    • routeur : transporte les paquets même s’ils ne lui sont pas adressés directement, choisit la meilleure route, joint plusieurs réseaux, agit au niveau de la couche 3.

    Un routeur possède plusieurs cartes réseaux. Chacune de ces cartes réseau est liée à une interface, possédant une adresse IP, en rapport avec le sous-reseau auquel l’interface est reliée.

    Sur le routeur suivant, il y a 3 ports ethernet, ainsi qu’une antenne wifi. Ce qui fait 4 cartes reseau:

    routeur de la marque Siretta

    routeur de la marque Siretta

    On suppose qu’une carte reseau propose une seule interface (une porte vers le sous-reseau directement relié), et possède donc une seule adresse IP.

    Adresse IP

    Dans le reseau internet, les reseaux et les machines sont identifiés par un numéro unique, l’adresse IP. Pour être exact, ce sont les cartes reseaux des machines qui possèdent une adresse IP.

    Pour plus de précisions sur l’adressage IP ainsi que le masque de sous-reseau, voir la video sur IP et masque sous-reseau (L. Guerin) :

    video sur IP et masque sous-reseau (L. Guerin)

    video sur IP et masque sous-reseau (L. Guerin)

    Une adresse IP de la norme IPv4 est un nombre binaire codé sur 32 bits, soit 4 octets. Le nombre d’adresses possibles est alors de plus de 4 milliards.

    Exemple d’adresse IPv4 exprimée à l’aide de 4 valeurs décimales (0-255):

    192.168.0.1/24

    La notation utilisant CIDR composé d’une adresse IPv4 et d’une indication sur le masque de sous réseau. Par exemple : 192.168.0.1/24 signifie :

    • Adresse IP : 192.168.0.1
    • Masque de sous-réseau en notation CIDR : 24
    • partie reseau de l’adresse: 24 premiers bits, c’est à dire les octets 192.168.0
    • partie machine de l’adresse IP: les 8 derniers bits (32 - 24), soit le dernier octet: .1

    Machines appartenant à un même reseau

    Definition: Deux machines sont sur le même réseau si et seulement si, les parties réseau de leur adresse IP sont identiques.

    Les derniers caractères /24 correspondent au masque de sous-reseau. Ils signifient que le reseau contenant la machine a une adresse codée sur les 24 premiers bits (192.168.0). Et que les 8 derniers bits constituent l’adresse de la machine dans ce reseau (il s’agit donc du .1 final).

    Le masque de sous-reseau peut être aussi exprimé sous la forme binaire. Les N premiers chiffres du masque valent alors 1 et les autres (jusqu’au 32e) valent 0. Par exemple:

    /8 correspond à 11111111 00000000 00000000 00000000.

    Il est alors plus commode d’écrire l’equivalent décimal pour chacun des bits:

    255.0.0.0

    Remarque sur la norme IPv6

    Pour la norme IPv6, ce nombre est sur 128 bits, soit 16 octets. Exemple d’adresse IPv6 exprimée en hexadécimal (32 caractères): 2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b

    Exercices sur les adressages IP:

    Voir l’exercice n°4 du sujet de Baccalaureat: centres etrangers 2021: étude d’un reseau informatique

    Voir l’exercice n°1 du sujet de Baccalaureat: Metropole Sept 2021: reseau d’ordinateurs

    Table de routage (reseau local)

    Chaque routeur reçoit des données et doit décider à qui les transmettre. Pour cela, il dispose de tables de routage construites soit statiquement (par un humain), soit dynamiquement (par un programme).

    Lorsqu’il reçoit un message (une trame), il lit l’adresse IP du destinataire et le redirige dans la bonne direction:

    • soit le routeur est directement relié au bon reseau, contenant le destinataire: le message va alors circuler par la carte reseau correspondante (l’adresse Passerelle (Gateway)).
    • soit l’adresse lui est inconnue: c’est sa table de routage qui va lui dire à quel autre routeur l’envoyer.

    La table de routage contiendra donc:

    1. les adresses IP des reseaux et des passerelles (cartes reseaux) auxquels le routeur est directement relié.
    2. l’adresse IP 0.0.0.0 (celle d’internet) sera associée à la passerelle qui fera circuler le message vers internet. Ce sera l’adresse IP du routeur voisin qui pourra acheminer ce message vers internet.
    3. les adresses IP des reseaux auxquels le routeur n’est pas directement lié. La passerelle sera l’adresse de la carte reseau du routeur voisin qui mène à ces reseaux.

    Exemple: Dans cette représentation, on donne l’adresse des réseaux lorsqu’il y a plusieurs connexions. Par exemple 192.168.1.0/24 pour le reseau en bas à gauche. Pour toutes les machines connectées, on ne donne que la partie adresse machine. Il s’agit du dernier octet de l’adresse IP.

    système n°1

    système n°1

    La table de routage du routeur 1 est alors:

    reseau à rejoindre passerelle (Gateway)
    192.168.0.0/24 192.168.0.254
    192.168.1.0/24 192.168.1.254
    0.0.0.0 192.168.1.253
    10.0.0.0/24 192.168.0.253

    Remarque: La table de routage du logiciel Filius donne également l’adresse 127.0.0.0/ 255.255.255.255. Cette adresse est réservé pour le bouclage, c’est-à-dire l’auto-adresse d’un hôte, également connue sous le nom d’adresse localhost. Cette adresse IP de bouclage est entièrement gérée par et dans le système d’exploitation et ne renvoie pas vers un port du routeur.

    Voir l’exercice n°1 du sujet de Baccalaureat: Metropole Sept 2021: Architecture de reseau d’ordinateurs, table de routage

    TP : simulation d’un reseau à l’aide du logiciel Filius

    • Le TP de 1ere NSI se trouve à l’adresse suivante
    • Le TP de terminale se trouve à l’adresse suivante

    Modélisation du réseau par un graphe

    Considérons système informatique constitué de:

    • 4 réseaux LAN
    • Un switch par reseau
    • plusieurs machines hôtes, partagées dans les 4 reseaux
    • une passerelle vers internet

    Les adresses IP indiquées sur le schéma suivant concernent toutes les cartes reseaux des machines. Les routeurs possèdent une carte reseau par interface reseau.

    exemple d

    exemple d'un reseau de sous-reseaux

    Dans cet exemple, voici la liste des adresses IP des différents reseaux:

    reseau adresse IP symbole utilisé dans le graphe
    reseau 0 192.168.0.0 S0
    reseau 1 192.168.1.0 S1
    reseau 2 100.10.42.0 S2
    reseau 3 165.124.42.101 S3
    internet 192.168.4.0 internet

    Et celle des différentes machines

    machine adresse IP symbole utilisé dans le graphe
    routeur 1 côté reseau 0 192.168.0.1 R1
    routeur 1 côté reseau 1 192.168.1.1 R1
    routeur 2 côté reseau 1 192.168.1.2 R2
    routeur 2 côté reseau 2 100.10.42.1 R2
    routeur 3 côté reseau 1 192.168.1.3 R3
    routeur 3 côté reseau 3 165.124.42.1 R3
    routeur 4 côté reseau 3 165.124.42.254 R4
    routeur 4 côté internet 192.168.4.1 R4

    exercice complet ici

    Liens

    Videos présentées dans cette page

    Autres documents

    protocoles de routage

    Ce cours comporte plusieurs pages:

    Routage statique et dynamique

    Pour un reseau de petite dimension, on peut envisager d’utiliser une table de routage statique, comme vue dans le cours graphes et internet.

    Par contre, pour des reseaux de grande taille, il faudra une méthode permettant de construire et mettre à jour cette table de manière dynamique. Il existe 2 protocoles pour réaliser cela, RIP et OSPF.

    Ces protocoles vont permettre aux routeurs d’échanger des informations entre eux, afin d’avoir un aperçu des réseaux autour d’eux. Ils vont déterminer le meilleur chemin en fonction de l’état du réseau. Ils se basent sur un critère, ou plutôt un coût associé à chaque chemin: il s’agira du nombre de sauts (routeurs traversés) ou bien de l’estimation de la durée d’acheminement (loi sur le débit).

    Ces protocoles doivent eviter les boucles de routage, et corriger les données de routage selon l’evolution du reseau (nouvelles machines, ou pannes, engorgement).

    Chaque modification du reseau va entrainer un temps d’echange entre les routeurs, jusqu’à ce que ceux-ci finissent par établir une nouvelle table de routage.

    Routages dynamiques: Les routeurs vont s’adapter à un réseau qui évolue au cours du temps (ajout ou suppression de routes, panne d’un routeur, etc..). Pour cela les routeurs se transmettent des informations pour qu’ils puissent mettre à jour leur table de routage.

    Activité

    Pour chacune des videos, au cours de leur visionnage, prendre en notes pour repondre aux questions suivantes:

    Le routage à vecteurs de distance

    Video (Youtube): Mooc de l'INT (institut des Mines Télécom)

    Video (Youtube): Mooc de l'INT (institut des Mines Télécom)

    Les routage à états de liens

    Video (Youtube): Mooc de l'INT (institut des Mines Télécom)

    Video (Youtube): Mooc de l'INT (institut des Mines Télécom)

    1. Pour le routage étudié, un routeur connait-il la carte globale du reseau (quel routeur est connecté à tel autre)?
    2. Pour le routage étudié, s’agit-il des protocoles RIP ou OSPF?
    3. communique t-il avec ses voisins directs, ou avec l’ensemble du reseau?
    4. communique t-il aux autres routeurs de gros ou petits volumes d’informations pour établir sa table de routage?
    5. un routeur, connait-il le chemin exact pour atteindre n’importe quel routeur du reseau?
    6. connait-il le nombre de sauts pour atteindre n’importe quel routeur du reseau?
    7. selectionne t-il le routeur voisin qui va donner le plus court chemin en nombre de saut / en durée d’acheminement? (Question de l’exercice n°4 du sujet de baccalaureat 2021, Polynesie)
    8. Comment met-il à jour sa table de routage lorsqu’il y a une modification du reseau?

    Routage à vecteur de distance

    exemple de table de routage à vecteur de distance

    exemple de table de routage à vecteur de distance

    Un vecteur de distance est une donnée constituée de (adresse du reseau, nombre de sauts, gateway)

    Coût associé au chemin: Le nombre de sauts (routeurs traversés)

    Exemple de protocole: Routing Information Protocol, RIP (basé sur l’algorithme de Bellman et Ford)

    Mise à jour de la table de routage: Les routeurs envoient leur table de routage (complète ou non), aux routeurs voisins de façon périodique. Lorsque le routeur reçoit la table de routage du voisin, il met à jour sa table à partir de ces informations: pour chaque vecteur de distance donné par le routeur voisin, il incrémente la valeur du nombre de sauts d’une unité, et compare avec sa table:

    • Si le coût est inférieur à celui de sa propre table, ou s’il s’agit d’une nouvelle adresse, il remet celle-ci à jour en considérant ce nouveau chemin.
    • Si le coût de l’une de ses entrées dans la table semble augmenter, il peut aussi s’agir d’une modification du reseau (panne, route coupée…). Il met à jour le nouveau coût pour son vecteur de distance.

    Ainsi, les informations vont circuler de proche en proche, très rapidement. Le routeur ne connait pas la route précise pour atteindre une adresse dans le reseau, mais la passerelle à prendre pour optimiser le coût du chemin (distance, ou métrique la plus petite).

    Inconvenients de cette méthode:

    • il peut survenir des problèmes de convergence des données en cas de coupure d’une route sur le reseau (boucles, voir video). Le temps de convergence, même sans ce problème de boucle est relativement long. D’autant plus que le reseau est grand.
    • Il peut y avoir des itinéraires qui bouclent (voir video plus haut).

    Protocole RIP: (Routing Information Protocol). Issu des travaux de Bellman-Ford (publiés en 1956 et 1958), il a été développé par l’université de Californie. Il est utilisé initialement pour ARPAnet, ce qui en fait son grand succès.

    • RIP utilise une métrique à nombre de sauts (hop en anglais, correspond au nombre de routeurs à traverser pour arriver à destination). Le nombre de sauts est limité à 15.
    • Chaque routeur envoie sa table de routage à ses voisins toutes les 30 secondes.
    • Si une route n’est pas actualisée pendant 180s, elle est supprimée de la table
    Video (Youtube): simulateur RIPLAY

    Video (Youtube): simulateur RIPLAY

    Routage à états de liens

    exemple de table de routage à états de liens

    exemple de table de routage à états de liens

    Coût associé au chemin: homogène à une durée d’acheminement, calculé sur le débit des différentes sections du chemin. Dépend de l’encombrement, état du réseau, …

    Exemple de protocole: Open Shortest Path First, OSPF: algorithme à état de liaison, basé sur la recherche du plus court chemin (Dijkstra).

    Mise à jour de la table de routage: Le routeur envoie des petits messages, de type bonjour dans le reseau, et mesure la durée de reponse. Il construit un paquet spécial contenant les informations qu’il vient de découvrir, avant de la diffuser à tous les autres routeurs. Il établit ainsi une table avec, pour chaque adresse la mention d’une métrique qui depend du debit de chaque liaison, et déduit le plus court chemin vers chaque destination à partir de l’algorithme de Dijkstra. La métrique est obtenue en additionnant les coûts de chaque liaison.

    Avantages:

    • Plus de problème de boucle puisque la mise à jour des routeurs se fait simultanément.
    • En théorie, pas de limitation de la taille du réseau.

    Inconvénient : Les tables de routage croissent avec le nombre de routeurs dans un réseau. Ce qui nécessite plus de mémoire au sein des routeurs et plus de temps pour explorer les tables.

    Exercice n°3 du sujet de baccalaureat Metropole-2 2022: représentations binaires et protocoles de routage. (RIP, OSPF), minimiser le nombre de routeurs à traverser pour une requête.

    Exercice n°3 du sujet de baccalaureat Metropole-2 2023: réseau Arpanet

    Exercice n°2 du Centres etrangers J1 2024: reseaux, adresses IP, …

    Débit

    Le debit est la vitesse à laquelle sont échangées les données, expimée en bits/s (ou kb/s, Mb/s…). Le débit se définit par le rapport du nombre de données circulant (en bits), par la durée (s).

    $$D = \tfrac{N}{s}$$

    Pour assurer une navigation correcte sur Internet ou regarder la télé ou des vidéos en streaming, le debit minimum doit être de 8Mb/s.

    En 2022, l’objectif est de fournir en france, à tous les foyers, le THD (très haut débit), soit 30Mb/s.

    Avec la fibre, ce débit est encore dépassé (quelques centaines de Mb/s).

    de nombreux sites proposent un test de debit pour votre connexion internet

    de nombreux sites proposent un test de debit pour votre connexion internet

    La notion de coût d’une liaison (OSPF)

    $$cout = \tfrac{10^8}{debit}$$
    Type de réseau Coût par défaut
    FDDI, FastEthernet 1
    Ethernet 10 Mbps 10
    E1 (2,048 Mbps) 48
    T1 (1,544 Mbps) 65
    64 Kbps 1562
    56 Kbps 1758
    19.2 Kbps 5208

    voir complements sur developpez.com

    Liens

    Videos présentées dans cette page

    Autres documents

    chiffrement symetrique

    Ce chapitre contient plusieurs pages:

    • sécuriser les communications: Lien 1
    • chiffrement asymetrique: Lien 2
    • TP sur les nombres premiers: Lien 3
    • Projet sur le hack ethique et le chiffrement RSA: Lien 4

    Chiffrements symétriques

    du chiffrement de Cesar à celui de la machine Enigma…

    Vocabulaire

    • Chiffrer: transformer les caractères d’un texte pour le rendre incompréhensible, sauf pour celui qui possède la clé de chiffrement.
    • Déchiffrer: transformer le texte chiffré en texte clair à l’aide de la clé de chiffrement
    • Décrypter: transformer le texte chiffré en texte clair sans posséder la clé.
    • Cryptologie: science du secret: possède deux branches
      • cryptographie: étude de l’art du chiffrement
      • cryptanalyse: analyse des méthodes de chiffrement pour les casser (décrypter)

    à quoi sert le chiffrement?

    Le chiffrement a pour but de protéger nos données, nos communications, mais aussi de signer nos messages et de s’assurer que l’on communique bien avec la bonne personne:

    • Authentification: L’authentification est la procédure qui consiste, pour un système informatique, à vérifier l’identité d’une entité (personne, programme, machine).
    • L’intégrité des données désigne le fait que les données ne soient pas modifiées au cours d’une communication ou de leur stockage.
      Ainsi, si vous envoyez un texte chiffré sur un canal non sécurisé, le texte chiffré pourra être intercepté et altéré par un attaquant avant d’atteindre son destinataire. Pour contrôler cette intégrité, on associe au message une valeur de contrôle.
    • La confidentialité: Le chiffrement permet de protéger la confidentialité de vos données à l’aide d’une clé secrète.

    Chiffrement symétrique - definition

    Le chiffrement symétrique utilise la même clé (ou la même table) pour chiffrer et déchiffrer le message. L’algorithme peut être connu par l’adversaire. Mais le secret repose sur celui de la clé.

    Le chiffrement par décalage, ou chiffre de Caesar

    Principe

    Le chiffre de César fonctionne par décalage des lettres de l’alphabet.

    Chiffrement par décalage - wikipedia

    Chiffrement par décalage - wikipedia

    Cet algorithme de chiffrement utilise une fonction périodique pour transformer les rangs de chaque lettre:

    a b c d e f g h i j k l m n o p q r s t u v w x y z
    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

    Le chiffrement par substitution monoalphabetique utilise une fonction avec modulo:

    $$x \rightarrow x + cle ~[26]$$

    La fonction utilisée est une fonction périodique, issue de l’arithmétique modulaire.

    Compléter l’algorithme du chiffrement de César. On suppose qu’il existe une clé c correspondant au décalage utilisé. Le message clair est m et le message chiffré est m_chiffre

    m_chiffre = ""
    Pour chaque lettre l du message m:
      l_chiffre = ...
      m_chiffre = ...

    On peut utiliser les fonctions numero(l:str)->int et caractere(n:int)->str

    monosubstitution par décalage ou par substitution: Une lettre du message clair va t-elle donner différentes lettres chiffrées, ou une seule?

    Facilité du décryptage

    Pour decrypter le message, on peut tester une à une toutes les clés, jusqu’à découvrir un message intelligible:

    m_dechiffre = ""
    pour chaque valeur i dans {0,25}:
        pour chaque lettre l de m_chiffre:
            l_dechiffre = ...
            m_dechiffre = ...

    Décryptage par FORCE BRUTE: Combien y-a-t-il de clés possibles à essayer pour celui qui réalise le décryptage? Conclure.

    Substitution monoalphabetique utilisant une table

    Le chiffrement par monosubstitution a été également utilisé par différentes méthodes utilisant une table.

    Carré de Polybe - le mot « bonjour » est ainsi chiffré par le carré de Polybe :12 34 33 24 34 45 42 - wikipedia

    Carré de Polybe - le mot « bonjour » est ainsi chiffré par le carré de Polybe :12 34 33 24 34 45 42 - wikipedia

    Le code issu du carré de Polybe a été utilisé par les prisonniers, qui transmettaient leur message en tapant sur les murs Tap code

    Vous trouvez ces méthodes de chiffrement trop simpliste? Regardez alors sa déclinaison avec le chiffrement de Playfair

    VIDEO: chiffrement de Playfair - youtube - Astuces et tutoriels

    VIDEO: chiffrement de Playfair - youtube - Astuces et tutoriels

    Decryptage par analyse fréquentielle

    Le problème avec ce type de chiffrement monoalphabetique, est qu’il est possible de repérer comment sont transformées certaines lettres à partir de l’analyse fréquentielle du message chiffré.

    On peut alors utiliser la frequence des lettres pour dechiffrer et comparer avec la frequence moyenne dans une langue. (200 caracteres suffisent). Il y a aussi tout un tas de statistique, comme les lettres uniques, doubles lettres, finales, etc… C’est un marqueur suffisant pour savoir comment le code est fait.

    frequence des lettres en français, calculée sur la lecture de plusieurs ouvrages classiques (10 millions de caracteres)

    frequence des lettres en français, calculée sur la lecture de plusieurs ouvrages classiques (10 millions de caracteres)

    Cette analyse frequentielle est plus difficile (mais pas impossible) dans le cas du chiffrement de Playfair, car celui-ci utilise une methode de substitution d’un groupe de 2 lettres: c’est une substitution polyalphabetique. Le nombre de combinaisons possibles avec 2 lettres est alors de $26^2 = 676$.

    Substitution polyalphabétique

    Principe

    Polyalphabetique: Se dit d’un chiffre où un groupe de n lettres est codé par un groupe de n symboles. Le chiffrement Playfair, vu plus haut s’apparente à une substitution polyalphabetique, puisqu’il substitue des digrammes (groupes de 2 lettres) dans le texte d’origine.

    Contrairement aux chiffrements monoalphabetiques, qui sont des chiffrements par flot (caractères transformés un à un), les chiffrements polyalphabetiques réalisent un chiffrement par blocs (plusieurs caractères transformés en une fois).

    L’exemple suivant montre une polysubstitution simple avec une clé de longueur 3 qui va décaler les lettres de l’alphabet :

    On définit la clé ‘123’ qui indique que le premier caractère sera décalé d’une position, le second de 2 et le troisième de 3 positions, etc.

    Le mot : WIKIPEDIA donne donc dans ce cas XKNJRHEKD.

    Mais si on chiffre le mot : AAAAAAAAA cela donnera BCDBCDBCD. La lettre A ne donne pas toujours la même correspondance chiffrée.

    Chiffrement de Vigenère:

    Le chiffrement de Vigenère utilise ce principe de décalage à partir d’une clé exprimée par un mot.

    image issue du site books.openedition.org

    image issue du site books.openedition.org

    C’est souvent ce type de codage qui est proposé dans la litterature et le cinema.

    affiche du film Benjamin Gates et le Tresor des Templiers

    affiche du film Benjamin Gates et le Tresor des Templiers

    Décryptage

    L’analyse des fréquences est moins pertinente lorsque le message a été chiffré avec un chiffrement polyalphabétique (qui tend à rendre aléatoire la fréquence des lettres).

    Si on parvient à découvrir la périodicité, on peut en déduire la longueur de la clé. La connaissance de la longueur de la clé est essentielle pour pouvoir pratiquer l’analyse frequentielle: Une même lettre ne donne pas toujours le même caractère chiffré.

    Le decryptage par force brute repose sur l’essai de toutes les clés possibles, par combinaison sur tous les caractères de la clé. Si celle-ci a une longueur n, cela va faire $X^n$, où X est la longueur de l’alphabet. C’est une fonction exponentielle.

    La fonction de dechiffrage est alors executée un nombre de fois correspondant à $X^n$, dans le pire des cas.

    La machine Enigma

    Enigma: machine électromécanique portative servant au chiffrement et au déchiffrement - wikipedia

    Enigma: machine électromécanique portative servant au chiffrement et au déchiffrement - wikipedia

    La machine utilise des rotors qui sont mis en position selon une clé. L’alphabet est chiffré selon la position initiale de ces rotors. Ceux-ci se décalent lors de l’utilisation.

    Des branchements permettent d’ajouter des permutations des caractères.

    Tout ceci modifie l’alphabet chiffré et augmente sérieusement la complexité.

    Comme tout chiffrement symétrique, déchiffrer se fait avec la même machine, à condition d’utiliser la même clé.

    Son utilisation la plus célèbre fut celle faite par l’Allemagne nazie, avant et pendant la Seconde Guerre mondiale, la machine étant réputée inviolable selon ses concepteurs.

    Le principe de la machine Enigma était connu. Le concepteur savait à l’avance que certains modèles pourraient être volés par les alliés. Ce qui fit son efficacité, c’est le nombre immense de combinaisons possibles pour les réglages initiaux de la machine et le choix de la clef brute du message.

    Les cryptanalystes britanniques, dont Alan Turing

    Exercices

    Substitution monoalphabétique: Code de César

    • Question 1: Quelle clé a été utilisée pour chiffer ce texte (avec l’algorithme de César)?
    $$jyfwavnyhwopl hwwspxbll$$
    • Question 2: Décrypter ce message.

    • Question 3: Proposer un programme en python qui chiffre un message clair m en un message codé selon la clé numérique c.

    Aide:

    • La fonction ord('x') retourne un entier correspondant à la position d’un caractère dans la table ascii.
      Par exemple, ord('A') retourne 65, ord('B') retourne 66,…

    • La fonction chr(N) retourne le caractère de rang N: chr(65) retourne ‘A’.

    Substitution polyalphabétique: Chiffrement de Playfair

    A partir des explications données dans la video:

    • Question 1: Construisez la matrice pour l’algorithme de Playfair avec la clé estienne.
    • Question 2: Chiffrer le message: ACTIONREACTION
    • Question 3: S’agit-il d’une méthode utilisant la substitution monoalphabetique, ou polyalphabetique?
    • Question 4: Avec cette méthode, le decryptage est-il possible par analyse fréquentielle?

    Frequences des lettres dans un texte

    La fonction suivante retourne une liste de 26 valeurs de type float, donnant dans l’ordre de l’alphabet, la frequence pour chaque lettre dans un texte:

    def freq(m):
        frequences = [0]*26
        n = len(m)
        for c in m:
        ...
    • Question 1: Compléter le script de la fonction freq.

    Soient les deux textes chiffrés suivants:

    a.

    DGFHTMOMEIAMTLMFGOKFGOKEGDDTRWEIAKZGFGFSTEKGOMLASTTIFGFOSTLMFTFGOKMGWMFGOKRTSAJWTWTAWDTFMGFDAOLTWMOSSAFGOKETWKRWFDTEIAFMROAZSGMOFKOTFFTXAWMLARGWETWKJWAFROSDOAWSTAWDAMOFHGWKDTSTEITKSADAOF

    b.

    YOHGMVMFCBRBGWFNIZZPSURWFUOIPUWYITFANIETGGDOCKACPQEBEWPMXEMKVGRAILKWWXZOCILGPMQOVCGEGMYEBQRYACJMWXULFRVQMDCYLZFYZMYTPCRFDCRJNSFIHIQGRZEPRCVWMDILKGYDQORVFMXMCRCNIMUGRBKRBOOIUGPQCBVZNEYACE
    • Question 2: L’un des 2 a été chiffré avec un algorithme de substitution mon-alphabetique, et l’autre, poly-alphabétique. Lequel est mono-alphabétique?

    • Question 3: Tracer un histogramme à partir du texte chiffré en mono-substitution. On donne un exemple de script ci-dessous pour réaliser le graphique:

    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = fig.add_axes([0, 0, 1, 1])
    
    etiquettes = ['a', 'b', 'c', 'd', 'e']
    valeurs = [23, 17, 35, 29, 12]
    
    # Affichage des données
    ax.bar(etiquettes, valeurs)
    
    plt.title("Histogramme")  # Titre du graphique
    plt.ylabel('Nombre')  # Titre de l'axe y
    plt.xlabel('alphabet')
    plt.show()  # Affichage d'une courbe

    Chiffrement symétrique par la fonction XOR

    exercice inspiré de la page sur le chiffrement de glassus.github.io

    • Question 1: La fonction XOR est la fonction du OU EXCLUSIF.

    Donner la table de vérité de la fonction XOR

    • Question 2: A partir des lignes suivantes, vérifier que l’opérateur ^ en python réalise la fonction XOR sur 2 nombres écrits en valeur décimale:
    > 3 ^ 4
    7
    > 4 ^ 5
    1
    • Question 3: Programmer la fonction xor en python qui retourne le resultat de XOR appliqué aux 2 paramètres a et b.

    Exemple:

    >>> xor(0,1)
    1
    >>> xor(53,23)
    34
    >>> xor(34,23)
    53
    • Question 4: Peut-on utiliser la fonction XOR pour chiffrer PUIS dechiffrer un message, avec la MEME clé de chiffrement? Expliquer à partir de l’exemple ci-dessus.

    • Question 5: On s’interresse maintenant à la programmation de la fonction XOR pour chiffrer un message à partir d’un masque:

    $$message = "CETTEPHRASEESTVRAIMENTTRESTRESLONGUEMAISCESTFAITEXPRES"$$

    Le masque (correspond à la clé) aura une longueur inférieur au message. On utilise le masque selon la méthode de chiffrement polyalphabetique vue en cours.

    Le chiffrement demande de faire correspondre les caractères avec des nombres entiers. On utilisera pour cela un alphabet de 32 caractères ($2^5$). Chaque lettre de l’alphabet correspondra alors à un nombre compris entre 0 et 31.

    • Question 6: Lorsque l’on place 2 entiers inférieurs à 32 dans la fonction XOR, celle-ci retourne un entier également inférieur à 32. Pourquoi? (Representer ces nombres en binaire, sur un octet, et verifier cette affirmation)

    • Question 7: Compléter la fonction chiffre(message, masque) qui chiffre message en le XORant avec masque.

    Cette fonction doit pouvoir aussi servir à déchiffrer le message chiffré.

    alphabet=[chr(i+ord('A')) for i in range(26)] + ['*','/','@','&','!','à']
    def chiffre(message, masque):
        assert len(message)>=len(masque)
        message_chiffre = ""
        for i in range(len(message)):
            indice_lettre = alphabet.index(message[i])
            indice_masque = ...
            val = xor(...,...)
            message_chiffre+=alphabet[val]
        return ...
    • Question 8: Utiliser la fonction chiffre pour effectuer le chiffrement puis le dechiffrement du message.

    • Question 9: Pensez vous que cette méthode de chiffrement est assez resistante face à une attaque de cryptoanalyse? Si oui, pourquoi?

    Liens

    Documentation, sitographie

    chiffrement asymetrique

    Ce chapitre contient plusieurs pages:

    • sécuriser les communications: Lien 1
    • chiffrement asymetrique: Lien 2
    • TP sur les nombres premiers: Lien 3
    • Projet sur le hack ethique et le chiffrement RSA: Lien 4

    Chiffrements asymétriques

    Pour le chiffrement symétrique, le seul secret, c’est la clé de chiffrement. Cette clé doit avoir, pour des raisons pratiques, une longueur raisonnable (64, 128, 256 bits). Ce chiffrement permet de communiquer de manière confidentielle, ou de préserver la confidentialité de nos données sur un disque dur.

    L’un des inconvénients du chiffrement symétrique est le nombre de clés important qu’il faut par couple d’utilisateur, à l’echelle d’internet. De plus, comment assurer l’echange de clés entre participants de manière sûre?

    L’autre problème avec le seul chiffrement symétrique, c’est qu’il ne permet pas de repondre aux besoins d’authentification (reconnaitre l’identité) et d’authenticité (le message n’a pas été modifié).

    Pour comprendre ces termes, on utilise le scenario suivant. Alice et Bob sont 2 personnes qui veulent echanger des messages de manière sécurisée. Une 3e personne, appelée Trudy joue le rôle d’un attaquant.

    Le trio Alice - Bob - Trudy

    Le trio Alice - Bob - Trudy

    Le chiffrement asymétrique utilise plusieurs clés, une pour le chiffrement, et une autre pour le dechiffrement. Il repose sur des propriétés mathématiques de l’arithmetique modulaire. (voir principe du chiffrement RSA: wikipedia)

    Principe du chiffrement RSA

    Confidentialité

    Il doit y avoir 2 clés. L’une de ces clés doit rester secrête, et conservée par l’expediteur du message: c’est la clé privée. L’autre clé utile pour le chiffrement et le dechiffrement est partagée: elle est dite publique. On peut indifféremment chiffrer avec la clé publique et déchiffrer avec celle privée, ou l’inverse.

    VIDEO chiffrement asymetrique (demarrer à 4min28) - chaine ScienceEtonnante

    VIDEO chiffrement asymetrique (demarrer à 4min28) - chaine ScienceEtonnante

    Ainsi, comme la clé de Bob est publique, Alice peut utiliser cette clé pour chiffrer le message qu’elle veut lui envoyer, un peu comme si elle mettait le message dans un coffre (celui de Bob). Et Bob, qui possède la clé privée correspondante (la clé de son coffre) peut alors déchiffrer le message d’Alice.

    Chiffrement asymetrique

    Chiffrement asymetrique

    Confidentialité:

    Alice : C = chiffrement(m,Bob_public_key) => Bob

    Puis, pour Bob:

    m = dechiffrement(C,Bob_private_key)

    Authentification

    On peut utiliser cet algorithme pour authentifier l’auteur du message, et réaliser une signature numérique.

    Imaginons que Bob utilise sa clé privée pour chiffrer un message M. Il l’envoie à Alice, qui, en utilisant la clé publique de Bob, pourra le déchiffrer. Elle pourra ainsi s’assurer que Bob en est bien à l’origine et que son contenu n’a pas été modifié.

    En effet, comme il est le seul à posséder la clé privée, ce message M vient bien de Bob.

    Compléter la situation où Bob envoie un message de type Bonjour à Alice, en utilisant sa clé privée:

    Bonjour Alice - via chiffrement asymetrique

    Bonjour Alice - via chiffrement asymetrique

    Le point faible de cet échange vient de la distribution de la clé publique entre Bob et Alice.

    Cet échange n’est réellement sécurisé qu’à la condition que la clé publique de Bob, vienne bien de Bob. Et que personne ne se soit introduit dans la discussion pour substituer la clé publique de Bob par la sienne (attaque de l’homme du milieu).

    Compléter la situation suivante où Eve réalise une attaque dite de l’homme du milieu. Elle envoie au préalable sa propre clé publique à Alice et Bob. Puis elle se fait passer pour chacun des 2 lors de la discussion.

    Bonjour Alice, bonjour Bob - Eve

    Bonjour Alice, bonjour Bob - Eve

    Authentification:

    Bob : D = chiffrement(signature,Bob_private_key) => Alice

    Puis pour Alice:

    signature = dechiffrement(D,Bob_public_key)

    Organismes de certification

    Pour s’authentifier, Bob doit d’abord envoyer à Alice un certificat, qui contient sa clé publique mais aussi d’autres informations qui permettent de verifier la validité de ce certificat, en particulier l’emetteur: le nom de l’autorité de certification, une infrastructure à clé publique (PKI) qui a validé l’identité de Bob.

    Certificats: Les navigateurs permettent d’ouvrir les pages des sites qui ont pu être authentifiés. Pour faire ceci, les navigateurs intègrent un certain nombre de certificats reconnus. Pour les autres, ils utilisent une chaine de certification: les navigateurs font confiance à certaines autorités de certification, qui ont au préalable, certifié leurs clients (possesseurs de sites web).

    Si la chaine de confiance est rompue, votre navigateur affiche cette image qui va certainement vous dissuader de poursuivre votre navigation:

    certificat non reconnu

    certificat non reconnu

    En pratique, le certificat est un ensemble d’informations sur le propriétaire du domaine, la durée de validité, l’algorithme utilisé pour l’authentification, la clé publique, et surtout l’emetteur. Lorsqu’Alice reçoit le certificat que lui envoie Bob, elle consulte l’emetteur du certificat pour verifier qu’il s’agit bien du bon certificat, que celui-ci appartient bien à Bob.

    procedure d'echange de certificat

    procedure d'echange de certificat

    Complément sur RSA (Grand Oral)

    VIDEO - sciences etonnantes. L'Algorithme qui Sécurise Internet (entre autres...)

    VIDEO - sciences etonnantes. L'Algorithme qui Sécurise Internet (entre autres...)

    Alice veut envoyer un message à Bob

    • Elle doit d’abord lui envoyer sa clé publique:

    Lors de la confection de la clé publique e, le propietaire de la clé utilise la valeur de 2 entiers p et q premiers entre eux (secrets). En principe, p et q sont très grands (plus de 100 chiffres). Supposons pour l’exemple p=3 et q=11.

    Le proprietaire calcule le module de chiffrement n=p*q. Ici, n=33. Ce calcul est très facile pour lui, alors qu’il est très difficile de trouver p et q en connaissant n. C’est sur cette difficulté que repose la robustesse de RSA.

    Il calcule ensuite l’indicatrice d’Euler: f=(p-1)*(q-1) et détermine l’exposant public e qui doit être premier avec f.

    Par exemple, ici, f=20. On peut choisir e=3,7,9,13,…

    La couple (e,n) sera alors la clé publique d’Alice. Choisissons (3,33).

    • Bob reçoit la clé. Il l’utilise pour chiffre son message. Supposons que le message est le caractère F, le 6e caractère de l’alphabet. m=6. Alors le chiffrement se fait à l’aide de la relation: $m^e [n]$

    En suivant l’exemple,

    $$E(m) = 6^3 [33] = 18$$

    Bob va alors transmettre 18, qui est le message chiffré.

    • Alice va alors déchiffrer le message avec sa clé privée.

    Elle possède pour cela une clé constituée d’un exposant privé d qui est calculée comme inverse modulaire de e (modulo $(p-1).(q-1)$):

    $$e.d = 1 + k\times(p-1)(q-1)$$

    Pour dechiffrer le message M, elle fait: $M^d (mod n)$ où n=p.q

    On exploite la propiété qui veut que $(M^e)^d = M (mod~n)$

    Exemple: d=7 car $7 \times 3=21 = 20 + 1$, 7 est inverse modulaire de 3 modulo 20.

    On a alors: $M^d [33] = 6$, Alice retrouve le message clair envoyé par Bob.

    Avec les algorithmes classiques, casser la factorisation croit exponentiellement avec la longueur de la clé.

    Principe d’une communication securisée HTTPS

    Lors d’une communication HTTPS: les objectifs d’authentification, authenticité et de confidentialité sont remplis. Lors du protocole de communication, les chiffrements asymétriques et symétriques sont tous 2 utilisés:

    Que Se Passe-t-il Entre un Navigateur Web (client) et un Serveur ?

    • le client demande au serveur que celui-ci s’authentifie (1)
    • Le serveur envoie au navigateur une copie de son certificat SSL (2)
    • Le navigateur vérifie s’il fait confiance à ce certificat SSL. Si oui,le client envoie de manière sécurisée une clé de session qui servira pour la communication (3). L’envoie de la clé se fait à l’aide du chiffrement asymétrique (RSA). Le client utilise la clé publique du serveur pour cet envoi.
    • Cette clé sera utilisée pour des chiffrements symétriques entre le client et le serveur (4).
    établissement d'une communication securisée - OVH

    établissement d'une communication securisée - OVH

    Signature numérique: Lorsqu’on utilise sa propre clé privée pour envoyer un message, et qu’une autorité de certification peut garantir l’origine de cette clé privée, alors ce message envoyé a valeur de signature numérique. Il permet d’authentifier l’emetteur du message.

    Fonction de hachage: intégrité

    Une fonction de hachage est un algorithme qui prend en entrée une chaine de caractères de longueur quelconque, et qui retourne en sortie une chaine de caractères de longueur n fixée, appelée empreinte. Il est presque impossible de retrouver la chaine de caractères d’origine à partir de cette empreinte, tant la diffusion est importante suite à la modification d’une partie même infime du texte à chiffrer par cette méthode.

    Une application classique de l’utilisation de la fonction de hachage est le stockage de mots de passe, ou bien la verification de l’intégrité d’un message envoyé (comme un checksum). Mais aussi pour la constitution d’une blockchain:

    Voir: L’utilité du hachage pour la chaîne de blocs: rapport du Sénat

    Dans la blockchain, chaque bloc contient le hash du bloc précédent, les données des nouvelles transactions, et le nouveau hash constitué à partir de ces données (hash du bloc precedent + transactions).

    Blockchain

    Une blockchain est un registre, une grande base de données qui a la particularité d’être partagée simultanément avec tous ses utilisateurs (constituant les noeuds d’un réseau distribué), tous également détenteurs de ce registre, et qui ont également tous la capacité d’y inscrire des données, selon des règles spécifiques fixées par un protocole informatique très bien sécurisé grâce à la cryptographie. Il est impossible d’effacer ou modifier ce qui a déjà été écrit dans ce registre. En pratique, une chaîne de blocs (blockchain) est une base de données qui contient l’historique de tous les échanges effectués entre ses utilisateurs depuis sa création. economie.gouv

    La sécurité vient du consensus (PoW, Proof of Work) des validateurs lorsque de nouveaux ajouts sont proposés. La validation consiste en un calcul long et difficile sur les données de l’historique de la blockchain. Une fois qu’il y a consensus (un commun accord), un nouveau bloc est ajouté, et la base de données (la blockchain) est alors proposée à tous les noeuds du reseau. (mise à jour).

    Cette tâche “ingrate” realisée par les validateurs est remunérée. Le bloc contient ainsi l’adresse de cryptomonnaies, qui sont partagées entre validateurs: Un registre distribué doit être accompagné d’une cryptomonnaie (propriétaire ou utilisée à partir d’un autre registre) afin de fournir des incitations pour maintenir opérationnels les programmes de validation et de synchronisation.

    Pour résumer, une blockchain est un registre regroupant les transactions et adresses possédants des Bitcoins (ou autre cryptomonnaie), sécurisé par un protocole de validation par calcul et consensus.

    La technologie “blockchain” s’est développée pour soutenir des transactions réalisées via les cryptomonnaies/crypto-actifs. Mais d’autres domaines et secteurs d’activités, marchands ou non marchands, publics ou privés, utilisent déjà la chaîne de blocs (blockchain) ou prévoient de le faire dans les années à venir: Dans le secteur de l’assurance par exemple, l’apport de la blockchain tient par exemple à l’automatisation des procédures de remboursement.

    Il est possible de lire dans la blockchain. On utilise pour cela un explorateur de blocs.

    video sciences etonnantes - blockchain

    video sciences etonnantes - blockchain

    Il existe un autre type de validation, le PoS (Proof of Stake, ou preuve d’enjeu), qui permet d’augmenter grandement le flux de transactions. La blockchain Ethereum par exemple a effectué sa transition de la preuve de travail (PoW) vers une preuve d’enjeu (PoS) en septembre 2022. Pour participer à la sécurisation du réseau d’une blockchain PoS, il suffit d’avoir accumulé une quantité suffisante de jetons de la cryptomonnaie échangée sur le réseau. Plus une personne possédera de jetons d’une cryptomonnaie, plus on considérera que la sécurité du réseau est un enjeu important pour elle. Il y aura alors plus de chances d’être sélectionné (il y a une part d’aleatoire) pour produire un nouveau bloc et obtenir une récompense, en jetons.

    Exercices

    Nombre de clés:

    Un groupe de n personnes souhaitent communiquer entre elles, chacune, deux à deux. Elles souhaitent utiliser un moyen de communication sécurisé par un chiffrement symétrique. Combien de clés différentes seront nécessaires?

    Méthode de chiffrement de Vigenère.

    Si on appliquait cette méthode à un alphabet de 95 caractères (les caractères ascii):

    1. Combien de clés différentes peuvent exister avec 4 caractères?
    2. Combien de temps cela prendrait-il au maximum pour déchiffrer un message par recherche exhaustive (force brute), si le temps de calcul pour le déchiffrement est de 1 milliseconde par clé?

    Mots de passe

    1. Combien de mots de passe différents de 10 caractères peuvent être générés à l’aide des 95 caractères ascii?

    2. Avec un ordinateur capable de tester 1 million de mots de passe par seconde, combien de temps cela lui prendra t-il pour explorer l’ensemble des combinaisons?

    3. Expliquer ce qu’est une attaque par recherche exhaustive.

    4. Pour les proriétaires d’un site internet, vaut-il mieux conserver dans la base de données, les mots de passe des clients, ou bien le hachage de chacun de ces mots de passe?

    RSA

    1. Quel est la valeur de $8^7$ modulo 40?
    2. Verifier que 55 est decomposable en produit de 2 nombres premiers p et q. Calculer (p-1)*(q-1)
    3. Soit la clé publique $e=3$. Quel est l’inverse de $e$ modulo 40? Appeler ce nombre $d$.
    4. Chiffrer le message M = 5 avec la clé publique e, selon $M^e(mod~ 55)$
    5. Dechiffrer $M^e(mod~ 55)$ avec la clé privée d, selon la même fonction que précédemment.
    6. Dans un protocole de chiffement asymétrique, les algorithmes de chiffrement et de déchiffrement sont-ils les mêmes?
    7. Dans un protocole de chiffrement asymétrique, toutes les personnes possédant la clé publique de Bob peuvent lui envoyer un message?
    8. Dans un protocole d’authentification, toutes les personnes possédant la clé publique de Bob peuvent vérifier sa signature émise?
    9. Supposons que Bob envoie à Alice un message chiffré de la manière suivante: C = chiffrement(m,Bob_public_key). Est-ce qu’Alice peut authentifier Bob avec ce message?
    10. Supposons que Bob envoie à Alice un message chiffré de la manière suivante: C = chiffrement(m,Bob_private_key). Est-ce que ce message est confidentiel?

    Liens

    TP table de routage

    Rappels de NSI 1ere: logiciel Filius

    Ce TP a été vu en 1ere NSI à la seance suivante. On cherche à créer un système de 2 sous-réseaux locaux. Ces reseaux auront pour adresses: 198.168.0.0 et 192.168.2.0

    C’est à dire que toutes les machines du réseau 198.168.0.0 auront en commun les 3 octets 198.168.0 et toutes les machines du reseau 198.168.2.0 auront en commun les octets 198.168.2.

    • Le sous-réseau 192.168.0.0 comportera un switch et 3 ordinateurs M1, M2 et M3. Ces machines auront pour adresses IP:

      • 192.168.0.1
      • 192.168.0.2
      • 192.168.0.3
    • Le sous-réseau 192.168.2.0 comportera un switch et 3 ordinateurs M4, M5 et M6. Ces machines auront pour adresses IP:

      • 192.168.2.1
      • 192.168.2.2
      • 192.168.2.3

    Votre système devrait ressembler à l’image suivante:

    systeme de 2 sous-reseaux sans routeur

    systeme de 2 sous-reseaux sans routeur

    • Tester alors la commande ping depuis la machine M1 vers celle M6 du 2e sous-reseau.

    • Installer les logiciels utiles sur les machine M1 et M6 pour faire communiquer les machines. Pour faire cela: Démarrer la simulation:

    démarrer
    • Puis faire un double clic sur chacune des machines, et installer le logiciel ligne de commandes.
    console installation logiciel

    console d'installation de logiciels

    • tester alors les commandes suivantes depuis la machine M1:

      • ipconfig : vérifier la correspondance de l’adresse IP de la machine M1

      • ping 192.168.0.2 : pour établir et tester une connexion avec la machine M2

      • traceroute 192.168.0.2 : pour établir le trajet qui mène jusqu’à M2

      • Tester alors les commandes ping et traceroute vers une adresse de machine inexistante dans le réseau. Par exemple 192.168.0.4

    Qu.1a: Quels messages indiquent que la communication M1->M2 est possible, alors que M1-> 192.168.0.4 ne l’est pas?

    Qu.1b: La machine M6 est-elle accessible depuis M1? Pourquoi?

    Vous constatez que l’accès à M6 n’est pas possible. En effet, votre système doit disposer d’un routeur, une machine capable de faire interface entre 2 reseaux…

    • Modifier le système en ajoutant un routeur:

      • clic droit sur le Switch2 : faire supprimer tous les cables
      • ajouter le routeur
      • paramétrer le routeur:

      clic sur le routeur

      renseigner les adresses des 2 reseaux sur l’interface du routeur:

      • 192.168.0.254 du côté du reseau 192.168.0.0 (à gauche)
      • 192.168.2.254 du côté du reseau 192.168.2.0 (à droite)
    adresses des reseaux

    adresses des reseaux

    cocher routage automatique:

    option routage automatique

    option routage automatique

    • Pour chacun des ordinateurs du sous-reseau 1, M1, M2, M3, renseigner l’adresse de l’interface reseau 1 du routeur: mettre 192.168.0.254 dans le champs passerelle. Ce sera l’adresse IP de la carte reseau du routeur, du côté du reseau 192.168.0.0 (on met 254 à la place de 0 pour l’adresse routeur).
    renseigner l

    renseigner l'adresse reseau pour chaque ordinateur

    • Même travail pour M4, M5, M6: renseigner la passerelle 192.168.2.254
    • refaire le cablage

    Qu.1c: Pourquoi le routeur de votre système informatique possède t-il 2 adresses IP?

    Qu.1d: Démarrer le système et tester alors la commande ping de M1 vers M6, puis de M6 vers M1. Que constatez-vous? Pourquoi?

    En cas de difficultés: on pourra consulter la video Filius 2 de David Roche

    Simulation d’un reseau avec Filius (version term NSI): Routage statique

    1. Avec le logiciel Filius, construire les réseaux ci-dessous :

    système 2

    système 2

    2. Vous devrez renseigner les adresses IP des machines, ainsi que les masques de sous-reseau.

    • Tester avec un ping si un ordinateur du réseau R1 peut communiquer avec un autre ordinateur du réseau R1. Conclure.
    • Tester avec un ping si un ordinateur du réseau R1 peut communiquer avec un autre ordinateur du réseau R2. Conclure.

    Remarque : Toutes les machines appartenant au même réseau devront posséder la même adresse réseau sinon elles ne pourront pas communiquer ensemble, même si elles sont bien physiquement reliées.

    3. Ne pas utiliser le routage automatique. Compléter les adresses IP des passerelles. Tester à nouveau avec un ping si un ordinateur du réseau R1 peut communiquer avec un autre ordinateur du réseau R2. Puis avec avec un ordinateur du réseau R3. Conclure.

    4. Mettre en place le réseau R4. (Adresse IP et passerelle). Tester avec un ping si un ordinateur du réseau R1 peut communiquer avec un ordinateur du réseau R3.

    5. Comment modifier la table de routage du routeur A ?

    6. Comment modifier est la table de routage du routeur G ?

    Aide pour renseigner la table de routage

    On cherche à renseigner pour le routeur A la route à prendre pour acheminer un paquet vers le reseau 192.168.4.0

    exemple de systeme à 2 routeurs

    exemple de systeme à 2 routeurs

    Dans la table de routage du routeur A, il faudra ajouter une nouvelle entrée, et renseigner la passerelle pour rejoindre ce reseau éloigné:

    exemple de nouvelle entrée dans la table de routage du routeur A

    exemple de nouvelle entrée dans la table de routage du routeur A

    Alors, à condition de renseigner également le routeur B, avec la passerelle vers le reseau 192.168.0.0, les ordinateurs des 2 reseaux devraient communiquer ensemble.

    exemple de nouvelle entrée dans la table de routage du routeur B

    exemple de nouvelle entrée dans la table de routage du routeur B

    Liens

    Sous-sections de bases de donnees

    bases de donnees relationnelles

    Plan du cours:

    Le langage de requêtes:

    • illustration des actions sur une table avec un tableur: les prix Nobels. Opérations de recherche, filtre et tri sur une table: Lien
    • Cours langage SQL et TD sur une base de données de prenoms: Lien, exercices: pdf

    La structuration des données:

    • Bases de données, règles pour construire une BDD en plusieurs tables, TP sur la creation d’une BDD cinéma (Base de Libre Office): Lien
    • Problèmes d’intégrité, modele entité-relation (2): Lien, cours pdf et exercices
    • SGBD, gestion de l’accès concurentiel, Lien

    Travaux pratiques

    • TP requêtes sur une table de prenoms: Lien
    • TP sur la gestion d’une base de données de romans de sciences fiction, utilisant SQLite Browser
    • TP sur le langage SQL avec des requetes sur une base de données. Différents thèmes sont proposés : Lien
      • enquete de police
      • villes du monde
      • séries Netflix
      • exoplanètes
    • TP sur la creation d’un serveur avec gestion d’un formulaire en python/SQL: page 6

    Bases de données relationnelles

    Une base de données est une collection de données qui vont être partagées entre plusieurs services, serveurs, utilisateurs.

    Le modèle entité-association

    La première étape pour aboutir à un modèle permettant de stocker les données dans une base consiste à identifier les objets et définir leurs liens.

    Cette modélisation repose sur des principes mathématiques mis en avant par E.F. Codd (1923 - 2003, un informaticien britannique), et c’est cette modélisation qui est implémentée dans les bases de données.

    Entité

    on désigne par entité tout objet identifiable et pertinent pour l’application. Par exemple, pour la base de donnée précédente, les entités sont:

    • Films: les films
    • Réalisateurs: les réalisateurs

    Pour chacune des entités, les individus ou objets ont en commun les même propriétés. Ce sont des tables, aussi appelées relations.

    Attributs

    Les entités sont caractérisées par des propriétés appelées attributs. Un attribut est désigné par un nom et prend ses valeurs dans un domaine énumérable. (notion à rapprocher du type en Python).

    On exprime ici chaque attribut par son couple nom: domaine (domaine = type). Ces attributs doivent être insécables, ce qui empêche d’en choisir un du genre adresse (qui se decomposerait alors en n° + rue + ville).

    Pour l’entité Films, ces attributs sont Titre et Annee.

    Domaines

    Les valeurs mises dans une cellule sont élémentaires. Il ne peut s’agir de types construits comme des listes.

    • INT ou INTEGER : un entier
    • FLOAT(x) : un nombre décimal avec x définissant la précision (nombre de bits de codage de la mantisse)
    • REAL est un synonyme standard de FLOAT(24)
    • CHAR(n) : chaine d’au plus n caractères
    • VARCHAR(n)
    • DATE une date

    Association

    Une association représente un lien entre les entités.

    Il y a un lien représenté par le verbe a réalisé entre les entités Réalisateurs et Films.

    On distingue:

    • L’association binaire fonctionnelle: chaque occurence de l’entité A est liée à au plus une occurence de l’entité B. C’est équivalent à dire A=>B (la connaissance de A détermine celle de B). Dans ce cas, c’est la table A qui possède un attribut FOREIGN KEY qui pointe vers un attribut clé primaire de la table B.
    association binaire fonctionnelle

    association binaire fonctionnelle

    • L’association non fonctionnelle: Une occurence de A peut être liée à plus d’une occurence de B.
    association binaire non fonctionnelle

    association binaire NON fonctionnelle

    Vocabulaire employé dans le domaine des bases de données

    Voici l’ensemble des mots utilisés, avec leur correspondance

    Terme du modèle Terme de la représentation par table
    Relation Table
    n-uplet ligne
    Nom d’attribut Nom de colonne
    Valeur d’attribut Cellule
    Domaine Type

    La structuration des données

    Clé (ou identifiant)

    Une clé est un attribut d’une relation.

    clé primaire : une clé conçue pour identifier de manière unique les éléments d’une table. Si un attribut est considéré comme clef primaire, on ne doit pas trouver dans toute la relation 2 fois la même valeur pour cet attribut.

    Dans la situation fréquente où on a du mal à déterminer quelle est la clé d’un type d’entité ; on crée un identifiant abstrait appelé id (un numéro séquentiel) indépendant de tous les autres attributs.

    Dans une table, l’un des attributs peut être la clé primaire d’une autre table. Il s’agit alors d’une clé étrangère. Cet attribut permet de faire reference à un enregistrement dans une autre table, et caractérise parfaitement cette autre entité.

    Exemple: idMES est la clé étrangère dans la relation Films:

    Titre Annee idMES
    Hana-bi 1997 1
    Big fish 2003 2
    Edward aux mains d’argent 1990 2

    La relation Réalisateur:

    idMES NomMES PrenomMES AnneeNaiss
    1 Kitano Takeshi 1947
    2 Burton Tim 1958
    3 Tarantino Quentin 1963

    La base de données doit se conformer aux contraintes d’intégrité référentielles:

    Contraintes d’intégrité

    Une contrainte d’intégrité est une règle qui définit la cohérence d’une donnée ou d’un ensemble de données de la BD.

    Les contraintes d’intégrité liées aux clés primaires et étrangères sont:

    1. Contrainte de relation: chaque relation doit comporter une clé primaire.
    2. Clé etrangère: traduit une association. Elle doit être la clé primaire de l’autre relation à laquelle elle se réfère. Cette autre relation doit contenir l’élément auquel on veut se référencer AVANT de faire référence.
    3. Modification: on ne doit pas faire de modification de la clé primaire d’une occurence si celle-ci est liée.

    En pratique, ces contraintes sont définies au moment de la création d’une table.

    PRIMARY KEY : contrainte de clé primaire. Définit l’attribut comme la clé primaire

    FOREIGN KEY : contrainte de clef étrangère. Assure l’intégrité de référence. Cette clé étrangère n’est pas primaire pour la relation étudiée mais elle est la clé primaire d’une autre relation.

    En option, on peut ajouter des contraintes d’unicité ou de validité avec UNIQUE ou CHECK, ou autres:

    NOT NULL: contrainte d’obligation de valeur. Les éléments de la colonne doivent forcément être renseignés

    UNIQUE : la contrainte d’unicité, permet de s’assurer qu’une autre clef pourrait remplacer la clef primaire: interdit que deux tuples de la relation aient la même valeur pour l’attribut.

    REFERENCES nom table (`nom colonne) : contrôle l’intégrité référentielle entre l’attribut de la table et ses colonnes spécifiées

    CHECK (condition) : contrainte de validation. Il s’agit d’une assertion, qui contrôle la validité de la valeur de l’attribut spécifié dans la condition. Permet de restreindre les valeurs de la-les colonnes qui la-les composent.

    CREATE TABLE 
    AUTEURS
    (id INT, nom TEXT, prenom TEXT, ann_naissance INT, langue_ecriture TEXT, PRIMARY KEY (id));
    creation de la table AUTEURS sous sqldbrowser

    creation de la table AUTEURS sous sqldbrowser

    D’après la règle énoncée sur la contrainte de clé étrangère, la table LIVRES doit être créée APRES celle AUTEURS (à cause de la contrainte REFERENCES):

    CREATE TABLE LIVRES
    (id INT, titre TEXT, id_auteur INT, ann_publi INT, note INT, PRIMARY KEY (id), FOREIGN KEY (id_auteur) REFERENCES AUTEURS(id))

    Schéma d’une relation

    Une relation possède un nom, et se compose de colonnes désignées par un nom d’attribut avec des valeurs d’un certain domaine.

    Le schéma d’une relation: peut être représenté par un diagramme (une table), donnant les noms des relations, les attributs, leur domaine, et la mention de la clé primaire. Mais on préfère donner ce schéma sous forme d’un ensemble de tuples: $S = ((A_1,domaine_1, (A_2,domaine_2) ...(A_n,domaine_n))$ où les $A_i$ sont les attributs.

    Exemple: le schéma de la relation Films est:

    films((id_film,int),(titre,str),(date,int),(id_rea,int))

    Lorsqu’une base de données comporte plusieurs tables, l’ensemble des schémas de ces relations s’appelle le schéma relationnel de la base de données.

    Donner le schéma relationnel: Un schéma relationnel est un diagramme. On y représente les noms des relations, les attributs, leur domaine, les clés primaires soulignées et les clés étrangères précédées d’un # dans des tableaux, puis faire une flèche pour indiquer de quelle table la clé étrangère est la clé primaire.

    schéma relationnel de la base de données définie plus haut sur les Films et Réalisateurs de cinéma:

    schéma relationnel de la base de données films-realisateurs, base de libreoffice

    schéma relationnel de la base de données films-realisateurs, base de libreoffice

    TP Browser SQL: Base, SQLite Browser, Access

    Base de données sur FILMS et REALISATEURS

    voir TP à la page suivante

    Compléments

    Définitions

    Le degré d’une relation est le nombre d’attributs (ou de colonnes) et le cardinal d’une relation est le nombre de tuples (ou de lignes).

    Le schéma d’une relation: peut être représenté par un diagramme (une table), donnant les noms des relations, les attributs, leur domaine, et la mention de la clé primaire. Mais on peut aussi donner ce schéma sous forme d’un ensemble de tuples: $S = ((A_1,domaine_1, (A_2,domaine_2) ...(A_n,domaine_n))$ où les $A_i$ sont les attributs.

    Exemple: le schéma de la relation Films est: $$Film((Titre,str),(Annee,int))$$

    Une table R, ou relation est un ensemble fini de n-uplets $(x_1, x_2, ... x_n)$ où les xi prennent leurs valeurs dans Ai.

    Une occurence (ou élément d’une table R) est une ligne dans un tableau. On l’appelle aussi un enregistrement, ou un n-uplet.

    Lorsqu’une base de données comporte plusieurs tables, l’ensemble des schémas de ces relations s’appelle le schéma relationnel de la base de données.

    Donner le schéma relationnel: Une relation est un objet abstrait, on peut la représenter de différentes manières. Une représentation naturelle est le graphe entre les entités, représentant les relations et les associations.

    Une association binaire entre les entités $E_1$ et $E_2$ est un ensemble de couples ($e_1$, $e_2$) avec $e_1$∈$E_1$ et $e_2$∈$E_2$.

    Cette association peut être représentée à l’aide d’une clé etrangère, ou peut necessiter la création d’une nouvelle relation (et donc d’un nouveau tableau) pour répondre aux contraintes d’intégrité.

    Règles de conception d’une base de données

    • Unicité: Toute entité donne lieu à une table dont la clé primaire est l’identifiant de l’entité.
    • Toute association binaire fonctionnelle est implémentée par la presence d’une clé étrangère dans la table, qui représente l’entité origine de la dépendance fonctionnelle.
    • Normalisation: Toute association non fonctionnelle génère une nouvelle table dont la clé primaire est l’ensemble des clés primaires des tables qu’elle relie. Un exemple d’association non fonctionnelle, c’est lorsqu’une information apparait plusieurs fois, et necessiterait de modifier plusieurs lignes s’il fallait effectuer un changement.

    Remarque: la clé d’une association (binaire) entre une entité E1 et une entité E2 est le couple constitué de la clé e1 de E1 et de la clé e2 de E2.

    langage SQL

    Langage SQL

    SQL: structured query langage = langage de requêtes structuré est un langage informatique de dialogue avec une base de données relationnelle (un fichier qui organise les données sur une ou plusieurs tables).

    Une requête est une question posée à une base de données. Nous allons voir comment sont écrites les requêtes de base en SQL. Une requête est la traduction d’une relation écrite en algèbre relationnelle.

    L’algèbre relationnelle est un outil créé par le chercheur E. Codd (1970) pour manipuler les tables dans le modèle relationnel. Ses principales opérations sont: SELECTIONNER certaines colonnes (Projection) ou certaines lignes (selection) d’une table, mais aussi de combiner 2 tables.

    Chaque opération SQL prend en entrée une ou plusieurs tables et renvoie une table.

    version pdf

    version pdf

    Voyons dans un premier temps les requêtes utiles pour CREER, SUPPRIMER, REMPLIR et MODIFIER la table

    Creation, modification de table

    CREATE TABLE “nom_table” (schema relation);

    Créons la table:

    Nom_eleve Classe Math Anglais Info
     Kevin 209 16 17 18
    Zoe 209 5 15 17
    Toto 210 4 6 NULL
    CREATE TABLE IF NOT EXISTS Table_notes (
    	Nom_eleve		TEXT PRIMARY KEY,
    	Classe INTEGER,
    	Math		REAL,
    	Anglais		REAL,
    	Info		REAL);

    CREATE TABLE va permettre d’indiquer le schéma d’une relation, avec ses Attributs et Domaines. Les types (ou domaines) les plus courants sont parmi:

    • INTEGER, entier positif ou nul
    • TEXT, CHAR(n), chaine de caractères
    • DATE, format de date du type YYYY-MM-DD
    • REAL, une valeur décimale

    On peut ajouter des contraintes (constraints) en paramètre : PK (Primary Key), UNIQUE (dans une colonne, les valeurs doivent être uniques à chaque ligne), AUTOINCREMENT, NOT NULL (doit comprendre une valeur), DEFAULT ‘Not Applicable’ (la valeur mise par défaut si vide).

    CREATE TABLE etat_civil (
       id INTEGER PRIMARY KEY, 
       name TEXT UNIQUE,
       date_of_birth TEXT NOT NULL,
       date_of_death TEXT DEFAULT 'Not Applicable';)

    INSERT INTO “nom_table” (Attributs) VALUES (n-uplet1), (n-uplet2), …;

    On insère les valeurs dans la table:

    INSERT INTO "Table_notes" VALUES
    ("Doe", 16, 17, 18),
    ("Zoe", 12, 15, 17),
    ("Toto", 4, 6, NULL);

    ("Doe", 16, 17, 18) est un argument contenant les valeurs à insérer.

    Remarque: si un enregistrement n’existe pas, il faudra mettre NULL

    UPDATE <table> SET <attribut = valeur> WHERE <attribut = valeur>

    Pour modifier des valeurs

    UPDATE Table_notes
    SET Math = 18
    WHERE Nom = "Doe";

    DELETE FROM <table> WHERE <condition>

    Supprimer des lignes

    DELETE FROM Table_notes
    WHERE Math <= 14;

    ALTER TABLE <table> ADD COLUMN <Attribut Domaine>

    pour modifier la table

    ALTER TABLE Table_notes ADD COLUMN Biologie INTEGER;

    pour Renommer une colonne:

    ALTER TABLE nom_table
    RENAME COLUMN ancien_nom TO nouveau_nom

    pour Renommer la table:

    ALTER TABLE table_name
    RENAME TO new_table_name

    DROP TABLE <table>

    Supprimer une table

    DROP TABLE Table_notes;

    Les CLAUSES SQL

    Les mots-clefs SELECT, FROM, WHERE, GROUP BY, HAVING et ORDER BY sont appelés des clauses.

    clauses SQL sur la tables des romans

    clauses SQL sur la tables des romans

    SELECT <attributs> FROM nom_table

    SELECT est la commande qui retourne la table selon les attributs choisis. Il s’agit d’une Projection comme type d’opération relationnelle.

    Une projection est un type de sélection où seulement une partie des attributs des tables choisies est retenue pour le résultat.

    FROM est la table concernée.

    Pour avoir toutes les colonnes, faire:

    SELECT * FROM Table_notes

    ou bien seulement certaines:

    SELECT Math, Nom_eleve AS Nom FROM Table_notes

    On peut renommer une colonne avec l’alias AS, et choisir un nom plus pratique.

    SELECT DISTINCT retourne les éléments de manière unique.

    Et limiter le nombre de lignes à 10 par exemple:

    SELECT * FROM Table_notes LIMIT 10

    SELECT DISTINCT <attributs> FROM nom_table

    L’ajout du mot-clé DISTINCT, ne va retourner qu’une seule fois les lignes pour chaque valeur d’une colonne donnée. Il n’y aura pas de doublon, seule la première occurence est retournée.

    WHERE <condition>

    La clause WHERE permet de SELECTIONNER des lignes à partir de conditions dans les requêtes, mais aussi de realiser des JOINTURES (voir plus loin)

    SELECT Nom_eleve
    FROM Table_notes
    WHERE Math > 14 OR Info >= 18;

    Exercice: Représenter la table Table_notes (En-tête et contenu de la colonne) qui sera retournée par cette requête.

    AVG SUM MIN MAX COUNT

    Ce sont des fonctions d’agregation, qui retournent un resultat évalué sur la colonne issue de la SELECTION

    Exemple1: Combien d’élèves ont plus de 15 en math dans la table Table_notes?

    SELECT COUNT(*) FROM Table_notes WHERE Math > 15

    Exemple2: Combien de romans de l’auteur id_auteur =5 y-a-t-il dans la table romans?

    SELECT count(*) FROM romans WHERE id_auteur = 5
    • COUNT(*) va compter le nombre de lignes pour la selection donnée
    • SUM(attribut) va faire la somme pour les valeurs de l’attribut et pour la selection donnée
    • AVG(attribut) calcule la moyenne
    • MIN(attribut) retourne la valeur min, MAX(attribut) la vakeur max

    Exercice: Ecrire la requête qui calcule la moyenne de math pour tous les élèves de la table Table_notes

    GROUP BY <uneTable.attribut1>

    Permet de regrouper des lignes les unes avec les autres.

    Pour regrouper des lignes d’une table selon un attribut, il faut que ces lignes aient la même valeur pour cet attribut.

    GROUP BY s’utilise avec des agrégats.

    Exemple: Quel total de notes figure dans la table romanspour chaque auteur?

    SELECT SUM(note) FROM romans GROUP BY id_auteur

    Exercice: Ecrire une requête qui calcule la moyenne des notes obtenues par écrivain sur la table Romans.

    ORDER BY <colonne> ASC [DESC]

    Trions les lignes par ordre croissant des notes en math:

    SELECT Nom, Math
    FROM Table_notes
    ORDER BY Math ASC;

    Sinon par ordre descendant: ORDER BY Math DESC

    Exercice: Représenter le tableau retourné par la requête écrite en exemple.

    Exercice: Ecrire une requête qui calcule la moyenne des notes obtenues par écrivain sur la table Romans et qui classe ces auteurs par ordre de note moyenne décroissante.

    Remarque: On peut aussi rajouter une clause sur le nombre de lignes retournées avec LIMIT <nombre> Très pratiques pour de grandes tables.

    ‘GROUP BY … HAVING`

    La clause HAVING permet d’effectuer une selection sur des valeurs issues de regroupements.

    Par exemple, on ne pourra pas écrire:

    select count(*) from UEFA group by pays where count(*)>18

    mais:

    select count(*) from UEFA group by pays having count(*)>18

    WHERE <colonne> LIKE <motif> et WHERE <colonne> IN <tuple>

    LIKE

    On peut faire une recherche dans une table selon certains motifs. Pour cela, on utilise WHERE ... LIKE <suivi de caractères spéciaux>.

    Caractères spéciaux:

    • le caractère % représente 0, 1 ou plus de caractères
      • %s permet d’obtenir toutes chaines qui finissent par s, mais aussi le caractère unique s.
    • le caractère _ représente un caractère unique
      • ro_e permet d’obtenir robe ou bien rose

    Exercice: Dans la relation Eleves de schéma `((prenom, TEXT), (nom, TEXT), (nais, DATE), (rue, TEXT), (numero, INTEGER), (CP, INTEGER), (ville, TEXT), (email, TEXT)):

    1. Définir une requête qui permet d’obtenir tous les élèves nés en 2002
    1. Définir une requête qui permet d’obtenir tous les élèves habitant dans le département des Alpes Maritimes.
    2. Définir une requête qui permet d’obtenir tous les élèves ayant un compte e-mail chez l’opérateur laposte (du type pseudo@laposte.net)

    IN

    Pour faire une recherche dans une table selon une liste de critères, on utilise le mot clé IN On peut par exemple rechercher les élèves qui habitent Nice, Saint-Laurent ou Cagnes-sur-mer dans la table Eleves:

    SELECT nom, prenom
    FROM Eleves
    WHERE ville IN ('Nice', 'Saint-laurent', 'Cagnes-sur-mer')

    Remarque: Cette syntaxe peut être ajoutée à l’opérateur NOT, ce qui fait NOT IN.

    On peut avoir besoin d’extraire un groupe de lettres du texte. On utilise alors la fonction substr. Les paramètres attendus sont:

    • nom de l’attribut
    • rang du premier caractere (commence à 1)
    • rang du dernier caractere.

    Exemple: Recherche des élèves dont les noms commencent par ‘a’, ‘b’ ou ‘c’:

    SELECT nom, prenom
    FROM Eleves
    WHERE substr(nom, 1, 1) IN ('a', 'b', 'c')

    Exercice:

    Ecrire une requête sur la table Eleves qui retourne les noms des élèves dont la famille habite dans les départements (‘06’, ‘83’, ‘05’)

    Jointure

    Pour eviter les redondances, on a vu qu’il était préférable de répartir les données sur plusieurs tables, chaque table modélisant UNE seule entité.

    La jointure permet de mettre en relation plusieurs tables, par l’intermédiaire des liens qui existent en particuler entre la clé primaire de l’une et la clé étrangère de l’autre. La jointure est une opération de sélection car elle permet de ne retenir que les enregistrements pour lesquels la valeur de la clé primaire d’une table correspond à la valeur de la clé étrangère d’une autre table.

    exemple de jointure entre 2 tables

    exemple de jointure entre 2 tables

    Pour joindre 2 tables complètes:

    • 1ere méthode:
    SELECT *
    FROM orders
    JOIN customers
      ON orders.customer_id = customers.customer_id;

    à la 4e ligne : on declare comment les 2 tables sont combinées : on veut faire correspondre la colonne ìd_customersde la table orders avec celle ìd_customersde la table customers.

    Comme le nom d’une colonne va se retrouver dans de nombreuses tables, on utilisera la syntaxe : table_name.column_name

    • 2e méthode:
    SELECT *
    FROM orders, customers
    WHERE orders.customer_id = customers.customer_id;

    TP prenoms sql

    TP1 sur la base des stations de métro

    Se rendre à la page de Quentin Fortier, professeur en classes preparatoires https://sql-exercices.github.io/ et choisir (à gauche), l’exercice sur le métro parisien. Celui-ci propose de travailler sur une base de données à une seule table.

    La page se présente comme ceci.

    credit: fortierq Quentin Fortier

    credit: fortierq Quentin Fortier

    Pour chacune des questions, placer vos requêtes en bas de la page, et vérifier avec le bouton VALIDER.

    TP2 sur la table des prenoms

    Télécharger la table en format csv

    Le site de l’insee propose une page avec les fichiers des prenoms de l’état civil: Lien

    Un fichier d’extension .sql a été généré à partir de ces données. Téléchargez le ici.

    Ouverture du fichier: Deux options possibles

    Local: DB Browser for Sqlite

    • Lancez votre gestionnaire de base de données (DB Browser for Sqlite). Si besoin, une version portable se trouve ici

    • Dans le menu: Import: Database from SQL file…

    • Ouvrir le fichier qui se trouve dans vos Documents.

    • Le logiciel vous demande alors quel sera le nom de la base de données. Choisir: prenoms.

    En ligne: sqliteonline.com

    gestionnaire en ligne sqliteonline.com

    Affichage de la table

    Pour la suite, les instructions seront données pour le logiciel en local: DB Browser for Sqlite.

    Dans la partie supérieure gauche, observez 4 onglets qui permettent de choisir entre:

    • Database Structure
    • Browse Data
    • Edit Pragmas
    • Execute SQL

    Choisir Database structure: nom de la table et des différents attributs

    présentation des différentes tables et attributs

    présentation des différentes tables et attributs

    Choisir Browse Data: observer le contenu e la table

    parcourir les valeurs de la table

    parcourir les valeurs de la table

    Choisir Execute SQL

    La fenêtre permet alors de placer une requete en langage SQLite. Le résultat dans une autre fenêtre, juste au dessous.

    Afficher les premières lignes de la table afin de prendre connaissance des étiquettes des colonnes:

    SELECT * FROM prenoms LIMIT 10;

    Executer avec le bouton d’execution.

    Travail

    Ecrire et tester une à une les instructions qui permettent de:

    1. Afficher les dix premières lignes de la table
    2. Afficher les lignes correspondant à l’année 2000. Là encore, mieux vaut ne demander que les 10 premières lignes…
    3. Afficher les prénoms des garçons nés en 2000 (limiter à 50).
    4. Combien de fois le prénom Nicolas a-t-il été donné en 2000 ?
    5. Afficher les 10 prénoms de fille les plus donnés en 2000 rangés dans l’ordre décroissant du nombre de fois où ils ont été donnés. Utiliser les mots-clés: SELECT FROM WHERE ORDER BY DESC LIMIT
    6. Afficher les lignes des prénoms de garçons donnés entre 2000 et 2020 (inclus l’un et l’autre). Utiliser un AND pour tester l’encadrement des années.
    7. Afficher le nombre de prénoms différents de garçons donnés depuis 2000. SELECT COUNT(*) FROM WHERE
    8. Afficher le nombre de naissances de garçons observées en 2020.
    9. Afficher le nombre de filles et le nombre de garçons apparaissant dans la table. SELECT SUM(nombre) FROM GROUP BY
    10. Quel est le prénom, pour un certain sexe, en distinguant par exemple “Camille (fille)” et “Camille (garçon)”, qui a été le plus donné durant une année donnée ? En quelle année ? SELECT FROM ORDER BY DESC LIMIT
    11. En quelle année y-a-t-il eu le plus de naissances ? SELECT SUM(nombre) FROM GROUP BY ORDER BY DESC LIMIT
    12. Quels sont les 10 prénoms les plus donnés en France au cours du XXI-ème siècle en cours? SELECT SUM(nombre) FROM GROUP BY ORDER BY DESC LIMIT

    Autres travaux pratiques SQL

    Table unique

    Exercice sur les nouilles japonaises. Interface en ligne par N. Revéret sur forge.apps.education.fr

    Pays, villes et langues parlées, plusieurs tables

    Exercice sur le langage SQL rédigés par N. Revéret sur forge.apps.education.fr. Interface en ligne.

    Liens

    TP romans sql

    TP SQL

    Nous allons créer (ou télécharger) une petite base de données à deux tables pour nous exercer aux requêtes SQL.

    Utiliser SQLite Browser

    • Créer une Nouvelle Base de données: bibliotheque.sqlite (ajouter .sqlite)
    • Editer la definition de la table selon l’image suivante
    table AUTEURS

    table AUTEURS

    • Fichier > Exporter > Exporter la base de données sous format SQL. Enregistrer le fichier avec le nom bibliotheque.sql (ajouter l’extension .sql)
    • Ouvrir le fichier bibliotheque.sql avec un editeur de texte (Notepad++ ou autre)
    • Ajouter les instructions de creation d’une nouvelle table LIVRES de schéma:
    (id INT, titre TEXT, id_auteur INT, ann_publi INT, note INT, PRIMARY KEY (id), FOREIGN KEY (id_auteur) REFERENCES AUTEURS(id));
    • Ajouter les entrées suivantes à chacune des tables:
    INSERT INTO AUTEURS
    (id,nom,prenom,ann_naissance,langue_ecriture)
    VALUES
    (1,'Orwell','George',1903,'anglais'),
    (2,'Herbert','Frank',1920,'anglais'),
    (3,'Asimov','Isaac',1920,'anglais'),
    (4,'Huxley','Aldous',1894,'anglais'),
    (5,'Bradbury','Ray',1920,'anglais'),
    (6,'K.Dick','Philip',1928,'anglais'),
    (7,'Barjavel','René',1911,'français'),
    (8,'Boulle','Pierre',1912,'français'),
    (9,'Van Vogt','Alfred Elton',1912,'anglais'),
    (10,'Verne','Jules',1828,'français');

    et

    INSERT INTO LIVRES
    (id,titre,id_auteur,ann_publi,note)
    VALUES
    (1,'1984',1,1949,10),
    (2,'Dune',2,1965,8),
    (3,'Fondation',3,1951,9),
    (4,'Le meilleur des mondes',4,1931,7),
    (5,'Fahrenheit 451',5,1953,7),
    (6,'Ubik',6,1969,9),
    (7,'Chroniques martiennes',5,1950,8),
    (8,'La nuit des temps',7,1968,7),
    (9,'Blade Runner',6,1968,8),
    (10,'Les Robots',3,1950,9),
    (11,'La Planète des singes',8,1963,8),
    (12,'Ravage',7,1943,8),
    (13,'Le Maître du Haut Château',6,1962,8),
    (14,'Le monde des Ā',9,1945,7),
    (15,'La Fin de l’éternité',3,1955,8),
    (16,'De la Terre à la Lune',10,1865,10);
    • sauvegarder ;-)

    Utiliser l’application SQLite (non installée sur PC du lycée)

    La ligne de commande SQLite permet d’entrer deux types de commandes :

    • Les commandes spéciales pour la ligne de commande. Elles débutent toutes par un point (il ne faut pas qu’il y ait d’espace avant ni après le point pour que la commande fonctionne). Par exemple, .open, .show, .backup, .exit et toutes les autres commandes listées par .help. (voir la documentation SQLite ainsi que Command Line Shell For SQLite). Et la version windows
    • Les requêtes SQL, par exemple CREATE, SELECT, INSERT, UPDATE, DELETE. Chacune doit se terminer par un point-virgule.

    Voici comment combiner ces deux types de commandes afin de vérifier la liste des tables de la base de données sélectionnée puis créer et afficher les enregistrements :

    Pour démarrer sqlite, sous Windows, rechercher le fichier sqlite.exe

    Dans la console: l’invite de commande commence alors par sqlite>

    • Les instructions suivantes permettent d’ouvrir et executer le fichier bibliotheque.sql, afficher les tables, puis fermer (si besoin) l’application sqlite:
    sqlite> .read bibliotheque.sql
    sqlite> .tables
    AUTEURS LIVRES
    sqlite> .exit
    • Pour représenter la table en mode markdown:
    sqlite> .read bibliotheque_auteurs.sql
    sqlite> .mode markdown
    sqlite> select *
       ...> from LIVRES;

    Ce qui devrait afficher:

    table en format markdown

    table en format markdown

    *Comme vous l’avez remarqué:

    • lorsque vous écrivez select *, le retour à la ligne n’execute pas le script, mais attend la fin de l’instruction, jusqu’au point virgule ; final.
    • les requêtes et instructions SQL peuvent être écrites directement dans l’application sqlite, comme dans le fichier d’extension .sql. Il faudra alors le lire dans la console avec .read <nom_du_fichier>.

    Utiliser une application en ligne

    • Aller sur la page sqlonline.com
      sqlonline.com

      sqlonline.com

    • Cliquer sur Import, puis choisir un fichier d’extension .sql, comme par exemple bibliotheque.sql
    • Utiliser alors la fenêtre SQLite pour tester les instructions suivantes.

    Tester quelques requêtes SQL

    INSERT … VALUES

    Ajoute une entrée

    sqlite> insert into LIVRES
       ...> (id,titre,id_auteur,ann_publi,note)
       ...> VALUES
       ...> (17,'Cinq semaines en ballon',10,1862,5);

    Vérifier alors la modification en faisant: SELECT * FROM LIVRES

    UPDATE … WHERE

    Mise à jour d’une valeur

    sqlite> UPDATE LIVRES
       ...> SET note=6 
       ...> WHERE id=17;

    DELETE … WHERE

    • Supprimer une ou plusieurs occurences:
    sqlite> DELETE FROM LIVRES WHERE titre='Cinq semaines en ballon';
    • supprimer la derniere occurence:
    DELETE FROM LIVRES WHERE id=(SELECT Max(id) from LIVRES);

    Remarques

    • La dernière requête utilise une instruction imbriquée, mise entre parenthèses de la clause WHERE id=(SELECT ...)
    • l’instruction DELETE FROM LIVRES permet de supprimer tous les n-uplets de la table, mais pas de remettre à zero le compteur. Pour une remise à zero du compteur, il faut aussi effacer le seul élément de la table sqlite_sequence, créée dans la base de donnée en même temps que la première table.

    SELECT … WHERE

    Selectionner une partie de la table, en nommant les attributs:

    sqlite> SELECT titre, ann_publi
       ...> FROM LIVRES
       ...> WHERE note=10;

    JOINTURE

    Tester le script suivant:

    sqlite> SELECT titre,id_auteur,ann_publi,nom,prenom
       ...> FROM LIVRES
       ...> INNER JOIN AUTEURS ON LIVRES.id_auteur = AUTEURS.id;

    Vous remarquerez que les attributs peuvent être issus des 2 tables.

    On pourra aussi ajouter une condition sur l’année de publication du livre:

    sqlite> SELECT titre,id_auteur,ann_publi,nom,prenom
       ...> FROM LIVRES
       ...> INNER JOIN AUTEURS ON LIVRES.id_auteur = AUTEURS.id;
       ...> WHERE ann_publi>1950

    A vous de jouer

    1. Afficher tous les livres, avec titre, année de parution et note, dont la note est supérieure ou égal à 8.
    2. Afficher tous les livres, avec leur titre et leur année de parution, écrits par Phillip K.Dick.
    3. Ajouter à la clause précédente l’instruction de classement par année de publication: ORDER BY ann_publi

    Ressources

    SQL - python

    Serveur SQL

    Necessité d’une interface

    Nous avons utilisé le programme SQLite, ou SQLiteBrowser pour faire interface entre l’utilisateur et la base de données, sur le modèle suivant:

    SQLite comme interface

    SQLite comme interface

    Selon cette architecture, lorsque vous recherchez un billet de train, vous utilisez un logiciel qui fera directement l’interface:

    À titre d’exemple, considérons une application fictive de recherche d’horaires de train.

    tableau des horaires de trains © REUTERS.

    tableau des horaires de trains © REUTERS.

    Voici un scénario possible de fonctionnement de cette application :

    1. L’application demande à l’utilisateur : « Quelle est la ville de départ ? ».
    2. L’utilisateur répond « Caussade ».
    3. L’application demande à l’utilisateur : « Quelle est la ville d’arrivée ? ».
    4. L’utilisateur répond « Brive-la-Gaillarde ».
    5. L’application envoie au SGBD la requête SQL :
    SELECT heureDep, heureArr FROM trains
    WHERE villeDep = ’Caussade’ AND villeArr = ’Brive-la-Gaillarde’;
    1. Le SGBD répond au programme en envoyant l’ensemble de tuples {(15h47, 17h22); (18h21, 19h58)}
    2. Le programme affiche à l’utilisateur : Résultats pour le trajet Caussade -> Brive-la-Gaillarde
    Premier train : 15h47 -> 17h22
    Second train : 18h21 -> 19h58

    Ce scenario semble plausible. En réalité, nous verrons qu’il y a une couche intermédiaire de plus: l’application web, côté serveur.

    Architecture Client-Serveur Web

    Le serveur et ses clients sont des applications distinctes qui s’échangent des informations. Lorsque la connexion est établie, l’application cliente peut interroger le serveur en lui envoyant une requête (une instruction).

    Il s’agit par exemple de demander une page web. Mais il peut aussi s’agir d’un besoin de services mettant en jeu la lecture, suppression ou modification d’une information dans une base de données.

    Le serveur exécute alors la requête en recherchant les données correspondantes dans la base, puis il expédie en retour une certaine réponse au client. Il compose la page web avant de la distribuer au client s’il s’agissait d’un protocole http.

    La communication entre le client et le serveur est donc faite de requêtes et de réponses.

    client - serveur

    client - serveur

    Un serveur web est une application qui s’execute sur une machine et qui ecoute un port specifique.

    Une application web est un programme stocké sur un serveur distant auquel on accede via une connexion au reseau, via http. Celui-ci peut faire interface avec une base de données, fabrique les pages web à la volée pour le client. Ce client a besoin d’un navigateur pour se connecter à cette application web. L’application web utilise comme langage de programmation un langage dédié, comme Python, PHP, node, C, ou autre.
    Alors que la ressource côté client est, elle, programmée en HTML, Javascript, et CSS.

    Qu'est ce qu'une application web - video de la chaine WayToLearnX

    Qu'est ce qu'une application web - video de la chaine WayToLearnX

    Un exemple de page statique

    Le fichier suivant, formulaire.txt génère un formulaire. Lorsque l’on appuie sur le bouton, les valeurs des champs nom et pass sont transmises par methode POST.

    exemple de page statique

    exemple de page statique

    Mais ici, ces valeurs ne peuvent pas être récupérées. Cela nécessiterait un script écrit en langage serveur. (voir plus haut).

    Vous pouvez ouvrir ce fichier en le télechargeant dans vos documents, puis:

    • changer l’extension .txt => .html
    • ouvrir avec votre navigateur web

    Serveur Python

    Librairie http.server

    Il est possible d’écrire en Python une application web. Le plus simple est d’utiliser les librairies http.server et cgi, directement intégrées au langage.

    Une fois le script server.py lancé, le client pourra se connecter au serveur local à l’adresse http://localhost:8800.

    Pour lancer votre serveur local, télécharger, et mettre dans vos documents le fichier server.py, puis executer à partir d’un IDE comme Spyder par exemple.

    Librairie cgi

    L’utilisation d’un formulaire ou la création de pages web dynamique nécessite d’importer la librairie cgi.

    Les instructions de création de la page web seront mises dans un fichier d’extension .py.

    Pour que le serveur compile et exécute le code source de votre fichier.py, il faudra naviguer vers ce fichier grâce à l’URL http://localhost:8800/fichier.py.

    Dans ce fichier, CGI permet de générer des pages web sur le champ, en fonction des actions du client. (Par exemple le chargement du formulaire lors de l’appui sur le bouton).

    Il suffira d’utiliser la fonction print pour afficher les éléments HTML dans la page du client.

    A vous de tester: Dans un fichier que vous nommerez store.py:

    • Mettre les lignes suivantes dans le fichier:
    # coding: utf-8
    #! /usr/bin/python
    import cgi
    import cgitb
    import html
    cgitb.enable()
    
    form = cgi.FieldStorage()
    print("Content-type: text/html; charset=utf-8\n")
    
    titre_formulaire = "<h2>Entrez les identifiants des clients</h2>"
    
    titre_table = "<h2>Table clients</h2>"
    
    html1 = """
    """
    
    html2 = """
    """
    
    html3 = """
    """
    
    print(html1)
    print(titre_formulaire)
    print(html2)
    print(titre_table)
    print(html3)
    • Ajouter les instructions en HTML entre les guillemets affectés à html1, html2 et html3 (partager le script html en 3 parties).
    • Demander l’execution du script à l’aide du navigateur. Le formulaire affiché doit être identique à celui de la page formulaire.html précédent.

    Python + SQL

    Contenant son propre SGBDR intégré, Python dispose de manière native de la librairie sqlite3 au moment de l’écriture de ce TP. Il faudra importer ce module avec par exemple:

    import sqlite3 as lite

    Puis créer un objet-connexion vers la base de données clients.db, à l’aide de la fonction-fabrique connect():

    con = lite.connect('clients.db')

    Cet objet assurera l’interface entre votre programme et la base de données.

    Pour dialoguer en SQL avec cet objet con, on utilisera encore un autre objet-interface que l’on appelle un curseur. Il s’agit d’une sorte de tampon mémoire intermédiaire, destiné à mémoriser temporairement les données en cours de traitement, ainsi que les opérations que vous effectuez sur elles, avant leur transfert définitif dans la base de données. Cette technique permet d’annuler et de revenir en arrière dans le traitement, sans que la base de données n’en soit affectée.

    cur = con.cursor()

    La requête est exprimée dans une chaîne de caractères, que nous transmettons au curseur par l’intermédiaire de sa méthode execute():

    cur.execute("CREATE TABLE IF NOT EXISTS clients_login(id INTEGER, name TEXT, pass TEXT)")

    Tant que le curseur reste ouvert, vous pouvez bien entendu ajouter des enregistrements supplémentaires :

    cur.execute("INSERT INTO clients_login VALUES(1,?,?)",(nom,mdp))

    Il sera souvent necessaire d’utiliser les contenus de variables python. Il est cependant fortement déconseillé de faire appel aux techniques ordinaires de formatage des chaînes, car cela peut ouvrir une faille de sécurité dans vos programmes, en y autorisant les intrusions par la méthode de piratage connue sous le nom de SQL injection. D’où la séquence d’instruction: VALUES(1,?,?)",(nom,mdp)).

    Pour récuperer le contenu d’une table de la base de données: La méthode Fetchall (est )une alternative à Fetchone), permet de récupérer d’un coup l’ensemble du résultat d’une requête:

    rows = cur.fetchall

    La variable rows est alors une liste de listes. (les n-uplets de la table)

    Le transfert dans la base de données sera déclenché par la méthode commit de l’objet connexion :

    conn.commit()

    A vous de jouer:

    • Ajouter la librairie sqlite3
    • Ajouter les lignes suivantes après avoir défini le Content-type du document client:
    con = None
    con = lite.connect('clients.db')
    with con:
        cur = con.cursor()
        cur.execute("CREATE TABLE IF NOT EXISTS clients_login(id INTEGER, name TEXT, pass TEXT, PRIMARY KEY(id AUTOINCREMENT))")
        cur.execute("SELECT * FROM clients_login")
        rows = cur.fetchall()
    • Ajouter les instructions Python de lecture des champs du formulaire à l’aide de la fonction form.getvalue, ainsi que l’echange avec la base de données:
    if (form.getvalue("name") != None) :
        nom = html.escape(form.getvalue("name"))
        mdp = html.escape(form.getvalue("pass"))
        
        with con:
            cur = con.cursor()
            cur.execute("INSERT INTO clients_login (name,pass) VALUES(?,?)",(nom,mdp))
            con.commit()
    • Ajouter à l’interieur de cette structure conditionnelle les instructions qui modifieront la variable titre_paragraphe. On veut afficher en tête de page:

    Soit: Entrez les identifiants des clients Lorsque les champs de formulaire sont vides.

    champs du formulaire video

    champs du formulaire video

    exemple de page statique

    exemple de page statique

    Soit: VALIDER la saisie: {} => {} Lorsque les champs name et pass ont été renseignés. Les symboles {} devront être remplacés par leur valeur à l’aide d’une expression formatée en python. (utiliser .format).

    champs du formulaire renseigné

    champs du formulaire renseigné

    exemple de page statique

    exemple de page statique

    • Enfin, modifier la variable table_affiche pour afficher dans le tableau TOUS les éléments de la table clients_login
    table_affiche = '<h2>Table clients</h2><table border=1><tr>'
      
    table_affiche += '<td>ID</td><td>nom</td><td>Pass</td>'
    table_affiche+= '</tr>'
    for row in rows:
        table_affiche += '<tr>'
        for i in row:
            table_affiche += '<td>'+str(i)+'</td>'
        table_affiche += '</tr>'
    table_affiche += '</table>'

    Mini projet

    A partir de la base de données du TP précédent, vous allez créer une nouvelle page utilisant des boutons radio. Ces boutons radio permettront de choisir les noms clients à afficher, en partageant l’alphabet en 3 parties. La page devrait ressembler à l’image ci-dessous:

    page avec selection par boutons radio

    page avec selection par boutons radio

    Aides :

    Frameworks Flask et Django

    Pour des projets d’applications web plus conséquents, on pourra se tourner vers des frameworks qui vont créer un environnement de travail plus complet:

    • Flask
    • Django
    • Pyramid

    Une presentation plus complète des différences entre ces frameworks ici: Django vs Flask vs Pyramid: Choosing a Python Web Framework

    Choosing a Python Web Framework @airpair

    Choosing a Python Web Framework @airpair

    Ressources

    TP base de libreoffice

    schéma relationnel de la base de données films-realisateurs, base de libreoffice

    schéma relationnel de la base de données films-realisateurs, base de libreoffice

    TP Browser SQL: Base, SQLite Browser, Access

    Base de données sur FILMS et REALISATEURS

    Base de Libre Office

    Démarrage

    Lancer Libre Office > Base. Au demarrage:

    • choisir “Créer une nouvelle base de données”
    • nommer cette base de données. Par exemple films_cultes. L’extension placée par le logiciel est .obd

    Structurer et renseigner les données

    Commençons par créer les 2 tables films et realisateurs.

    créer une nouvelle table

    créer une nouvelle table

    remplir les champs nom et domaine pour chaque attribut

    remplir les champs nom et domaine pour chaque attribut

    1: selectionner la colonne de l'attribut id_films, 2: clic droit, choisir Primary Key

    1: selectionner la colonne de l'attribut id_films, 2: clic droit, choisir Primary Key

    1: sauvegarder la table, 2: renseigner le nom: films

    1: sauvegarder la table, 2: renseigner le nom: films

    faire de même pour créer la table realisateurs

    faire de même pour créer la table realisateurs

    On va maintenant créer une association entre les 2 tables.

    menu Tools: choisir Relationships

    menu Tools: choisir Relationships

    1: ajouter chacune des tables dans le canvas, 2: cliquer sur films.id_rea et le glisser sur realisateurs.id_rea

    1: ajouter chacune des tables dans le canvas, 2: cliquer sur films.id_rea et le glisser sur realisateurs.id_rea

    bravo! vous avez créé l'association entre les 2 tables

    bravo! vous avez créé l'association entre les 2 tables

    La clé secondaire films.id_rea est maintenant liée à la clé primaire realisateurs.id_rea.

    Il reste maintenant à renseigner les données pour chacune des tables. Commencer par celle realisateurs. Car les tables sont liées par l’attribut realisateurs.id_rea

    1: clic droit sur la table realisateurs, 2: open

    1: clic droit sur la table realisateurs, 2: open

    renseigner les données

    renseigner les données

    id_rea nom prenom annee_naissance
    1 Kitano Takeshi 1947
    2 Burton Tim 1958
    3 Tarantino Quentin 1963
    4 Tati Jacques 1907
    5 Hitchcock Alfred 1899
    6 Almodovar Pedro 1949
    7 Kitamura Ryûhei 1969
    puis ouvrir la table films

    puis ouvrir la table films

    id_film titre date id_rea
    1 Hana-bi 1997
    2 Big fish 2003
    3 Edward aux mains d’argent 1990
    4 Sonatine 1993
    5 Pulp Fiction 1995
    6 Play Time 1967
    7 Vertigo 1958
    8 Psychose  1960
    9 Parle avec elle 2002
    10 Mon oncle 1958
    11 Volver 2006
    12 Reservoir Dogs 1992
    13 Alive 2003
    14 Godzilla: Final Wars 2004
    renseigner les données

    renseigner les données

    Requêtes sur la base de données

    Les requêtes seront réalisées en mode interactif pour démarrer.

    Choisir 1. Database Queries puis 2. Design View

    Choisir 1. Database Queries puis 2. Design View

    Ajouter les tables films et realisateurs dans le canvas

    Ajouter les tables films et realisateurs dans le canvas

    construire la requête comme sur l'image ci-contre

    construire la requête comme sur l'image ci-contre

    passer en mode SQL avec le bouton (jaune) de la barre de menu

    passer en mode SQL avec le bouton (jaune) de la barre de menu

    Executer la requête SQL avec le bouton (vert)

    Executer la requête SQL avec le bouton (vert)

    Observer la vue présentée par le logiciel (tableau). Cette vue peut être obtenue avec une instruction plus simple en SQL. Mettre les symboles -- devant l’instruction SQL pour la mettre en commentaire.

    Ajouter l’instruction SQL: SELECT * FROM films

    Executer. Vous obtenez le même résultats…

    saisie directe d'une requête SQL

    saisie directe d'une requête SQL

    Tester une nouvelle requête en mode Design View

    nouvelle requête

    nouvelle requête

    Cette fois, on ajoute une clause sur la valeur de id_rea. Mais sans afficher l’attribut (Visible non coché).

    Recopier la requête SQL générée. Executer.

    nouvelle requête

    nouvelle requête

    Pour cette nouvelle requête en mode visuel, on selectionne des attributs des 2 tables. On applique certaines clauses.

    En mode SQL: Remarquer que la clause "films"."id_rea" = "realisateurs"."id_rea" s’est mise automatiquement.

    Recopier cette requête SQL.

    Executer.

    Questions: Ecrire les requêtes SQL pour…

    1. Afficher toute la table films
    2. Corriger la date de parution du film Vertigo (se renseigner sur le net)
    3. Afficher tous les attributs du-des film-s dont le réalisateur est le 1er de la table realisateurs
    4. tous les titres des films sortis après 1970 mais avant 2002
    5. le titre du film, la date de sortie le nom du realisateur pour id_rea egal à 2
    6. tous les noms des auteurs de films qui ont sorti des films après 1960, mais pas Jacques Tati.
    7. l’année de naissance du réalisateur de Reservoir Dogs ?
    8. Le nombre de films du réalisateur “Hitckock”
    9. Inventer une nouvelle information à partir de cette base de donnée, necessitant une jointure entre les tables.

    SQLite DBrowser

    Vous pouvez aussi construire les 2 tables avec SQLite DBrowser:

    • Commencer par construire la table realisateurs, puis celle films. Bien renseigner les clés primaires (PK) pour ces 2 tables, ainsi que la clé étrangère pour films
    • ajouter les lignes à chaque table, ici aussi, en commençant par realisateurs

    Solutions

    Tester alors les instructions SQL suivantes… Recopier ensuite l’instruction et expliquer dans chaque cas ce qui est renvoyé:

    • requête 1: SELECT * FROM films
    • requête 3:
    SELECT * FROM films
    where ID_rea=1
    • requête 4:
    SELECT * FROM films
    where ID_rea=1 or Date>2003
    • requête 5: Deux possibiltés:
    select titre, date, last_name from realisateurs, films 
    where films.id_rea = 2 and films.id_rea = realisateurs.id_rea

    ou bien, en précisant la jointure avec INNER JOIN

    SELECT titre, date, realisateurs.last_name  FROM films
    INNER JOIN realisateurs on films.id_rea = realisateurs.id_rea
    where films.id_rea = 2;

    Compléments

    La table en version sqlite se trouve ici: films.db

    sujets bac ecrit

    Les exercices présentés ici peuvent différer de leur énoncé d'origine.

    Sous-sections de sujets bac ecrit

    tableaux et bases en python

    Bac 2021 Amerique Nord: Exercice 3

    Cet exercice porte sur les tableaux et sur la programmation de base en Python.

    tableau python bases

    On rappelle que len est une fonction qui prend un tableau en paramètre et renvoie sa longueur. C’est-à-dire le nombre d’éléments présents dans le tableau.

    Exemple : len([12, 54, 34, 57] vaut 4.

    Le but de cet exercice est de programmer différentes réductions pour un site de vente de vêtements en ligne.

    On rappelle que si le prix d’un article avant réduction est de x euros,

    • son prix vaut 0,5x si on lui applique une réduction de 50%,
    • son prix vaut 0,6x si on lui applique une réduction de 40%,
    • son prix vaut 0,7x si on lui applique une réduction de 30%,
    • son prix vaut 0,8x si on lui applique une réduction de 20%,
    • son prix vaut 0,9x si on lui applique une réduction de 10%.

    Dans le système informatique du site de vente, l’ensemble des articles qu’un client veut acheter, appelé panier, est modélisé par un tableau de flottants.

    Par exemple, si un client veut acheter un pantalon à 30,50 euros, un tee-shirt à 15 euros, une paire de chaussettes à 6 euros, une jupe à 20 euros, une paire de collants à 5 euros, une robe à 35 euros et un short à 10,50 euros, le système informatique aura le tableau suivant :

    tab = [30.5, 15.0, 6.0, 20.0, 5.0, 35.0, 10.5]``

    Question 1

    A. Écrire une fonction Python total_hors_reduction ayant pour argument le tableau des prix des articles du panier d’un client et renvoyant le total des prix de ces articles.

    B. Le site de vente propose la promotion suivante comme offre de bienvenue : 20% de réduction sur le premier article de la liste, 30% de réduction sur le deuxième article de la liste (s’il y a au moins deux articles) et aucune réduction sur le reste des articles (s’il y en a). Recopier sur la copie et compléter la fonction Python offre_bienvenue prenant en paramètre le tableau tab des prix des articles du panier d’un client et renvoyant le total à payer lorsqu’on leur applique l’offre de bienvenue.

    def offre_bienvenue ( tab ):
      """ tableau -> float """
      somme =0
      longueur =len(tab )
      if longueur > 0 :
        somme = tab [0]*...
      if longueur > 1 :
        somme = somme + ...
      if longueur > 2 :
        for i in range (2, longueur ):
          somme =...
      return ...

    Pour toute la suite de l’exercice, on pourra utiliser la fonction total_hors_reduction même si la question 1 n’a pas été traitée.

    Question 2

    Lors de la période des soldes, le site de vente propose les réductions suivantes :

    • si le panier contient 5 articles ou plus, une réduction globale de 50%,
    • si le panier contient 4 articles, une réduction globale de 40%,
    • si le panier contient 3 articles, une réduction globale de 30%,
    • si le panier contient 2 articles, une réduction globale de 20%,
    • si le panier contient 1 article, une réduction globale de 10%.

    Proposer une fonction Python prix_solde ayant pour argument le tableau tab des prix des articles du panier d’un client et renvoyant le total des prix de ces articles lorsqu’on leur applique la réduction des soldes.

    Question 3

    A. Écrire une fonction minimum qui prend en paramètre un tableau tab de nombres et renvoie la valeur minimum présente dans le tableau.

    B. Pour ses bons clients, le site de vente propose une offre promotionnelle, à partir de 2 articles achetés, l’article le moins cher des articles commandés est offert.

    Écrire une fonction Python offre_bon_client ayant pour paramètre le tableau des prix des articles du panier d’un client et renvoyant le total à payer lorsqu’on leur applique l’offre bon client.

    Question 4

    Afin de diminuer le stock de ses articles dans ses entrepôts, l’entreprise imagine faire l’offre suivante à ses clients : en suivant l’ordre des articles dans le panier du client, elle considère les 3 premiers articles et offre le moins cher, puis les 3 suivants et offre le moins cher et ainsi de suite jusqu’à ce qu’il reste au plus 2 articles qui n’ont alors droit à aucune réduction.

    Exemple : Si le panier du client contient un pantalon à 30,50 euros, un tee-shirt à 15 euros, une paire de chaussettes à 6 euros, une jupe à 20 euros, une paire de collants à 5 euros, une robe à 35 euros et un short à 10,50 euros, ce panier est représenté par le tableau suivant :

    tab = [30.5, 15.0, 6.0, 20.0, 5.0, 35.0, 10.5]

    Pour le premier groupe (le pantalon à 30,50 euros, le tee-shirt à 15 euros, la paire de chaussettes à 6 euros), l’article le moins cher, la paire de chaussettes à 6 euros, est offert. Pour le second groupe (la jupe à 20 euros, la paire de collants à 5 euros, la robe à 35 euros), la paire de collants à 5 euros est offerte. Donc le total après promotion de déstockage est 111 euros. On constate que le prix après promotion de déstockage dépend de l’ordre dans lequel se présentent les articles dans le panier.

    A. Proposer un panier contenant les mêmes articles que ceux de l’exemple mais ayant un prix après promotion de déstockage différent de 111 euros.

    B. Proposer un panier contenant les mêmes articles mais ayant le prix après promotion de déstockage le plus bas possible.

    C. Une fois ses articles choisis, quel algorithme le client peut-il utiliser pour modifier son panier afin de s’assurer qu’il obtiendra le prix après promotion de déstockage le plus bas possible ? On ne demande pas d’écrire cet algorithme.

    Bac 2021 Metropole Sept: Exercice 2

    Principaux thèmes abordés : structure de données (tableaux, dictionnaires) et langages et programmation (spécification). tableaux dictionnaire python bases

    Objectif de l’exercice :

    Les Aventuriers du Rail© est un jeu de société dans lequel les joueurs doivent construire des lignes de chemin de fer entre différentes villes d’un pays.

    La carte des liaisons possibles dans la région Occitanie est donnée en annexe 1 de l’exercice 2. Dans l’annexe 2 de l’exercice 2, les liaisons possédées par le joueur 1 sont en noir, et celles du joueur 2 en blanc. Les liaisons en gris sont encore en jeu.

    Codages des structures de données utilisées :

    • Liste des liaisons d’un joueur : Toutes les liaisons directes (sans ville intermédiaire) construites par un joueur seront enregistrées dans une variable de type “tableau de tableaux”. Le joueur 1 possède les lignes directes “Toulouse-Muret”, “Toulouse-Montauban”, “Gaillac-St Sulpice” et “Muret-Pamiers” (liaisons indiquées en noir dans l’annexe 2 de l’exercice 2). Ces liaisons sont mémorisées dans la variable ci-dessous.
    liaisonsJoueur1 = [["Toulouse","Muret"],
                       ["Toulouse","Montauban"],
                       ["Gaillac","St Sulpice"],
                       ["Muret","Pamiers"]] 

    Remarque : Seules les liaisons directes existent, par exemple [“Toulouse”,“Muret”] ou [“Muret”,“Toulouse”]. Par contre, le tableau [“Toulouse”,“Mazamet”] n’existe pas, puisque la ligne Toulouse-Mazamet passe par Castres.

    • Dictionnaire associé à un joueur : On code la liste des villes et des trajets possédée par un joueur en utilisant un dictionnaire de tableaux. Chaque clef de ce dictionnaire est une ville de départ, et chaque valeur est un tableau contenant les villes d’arrivée possibles en fonction des liaisons possédées par le joueur. Le dictionnaire de tableaux du joueur 1 est donné ci-dessous :
    DictJoueur1 = {
                  "Toulouse":["Muret","Montauban"],
                  "Montauban":["Toulouse"],
                  "Gaillac":["St Sulpice"],
                  "St Sulpice":["Gaillac"],
                  "Muret":["Toulouse","Pamiers"],
                  "Pamiers":["Muret"]}

    Question 1

    Expliquer pourquoi la liste des liaisons suivante n’est pas valide :

    tableauliaisons = [["Toulouse","Auch"], ["Luchon","Muret"], ["Quillan","Limoux"] ]

    Question 2

    Cette question concerne le joueur n°2 (Rappel : les liaisons possédées par le joueur n°2 sont représentées par un rectangle blanc dans l’annexe 2 de l’exercice 2).

    A. Donner le tableau liaisonsJoueur2, des liaisons possédées par le joueur n°2.

    B. Recopier et compléter le dictionnaire suivant, associé au joueur n°2 :

    DictJoueur2 = {
                  "Toulouse":["Castres","Castelnaudary"],
                  …
                  }

    Question 3

    À partir du tableau de tableaux contenant les liaisons d’un joueur, on souhaite construire le dictionnaire correspondant au joueur. Une première proposition a abouti à la fonction construireDict ci-dessous

    def construireDict(listeLiaisons):
      """
      listeLiaisons est un tableau de tableaux représentant la
      liste des liaisons d'un joueur comme décrit dans le problème
       """
      Dict={}
      for liaison in listeLiaisons :
        villeA = liaison[0]
        villeB = liaison[1]
        if not villeA in Dict.keys() :
          Dict[villeA]=[villeB]
        else :
          destinationsA = Dict[villeA]
          if not villeB in destinationsA :
            destinationsA.append(villeB)
      return Dict 

    A. Écrire sur votre copie un assert dans la fonction construireDict qui permet de vérifier que la listeLiaisons n’est pas vide.

    B. Sur votre copie, donner le résultat de cette fonction ayant comme argument la variable liaisonsJoueur1 donnée dans l’énoncé et expliquer en quoi cette fonction ne répond que partiellement à la demande.

    C. La fonction construireDict, définie ci-dessus, est donc partiellement inexacte. Compléter la fonction construireDict pour qu’elle génère bien l’ensemble du dictionnaire de tableaux correspondant à la liste de liaisons données en argument. À l’aide des numéros de lignes, on précisera où est inséré ce code.

    1282 × 862

    1282 × 862

    1318 × 878

    1318 × 878

    Corrigé

    Question 1

    Cette liste n’est pas valide à cause de la liaison ["Luchon","Muret"]. Il n’existe pas de liaison directe entre Luchon et Muret : la ligne passe par St Gaudens. Il faudrait donc deux liaisons, ["Luchon","St Gaudens"] et ["St Gaudens","Muret"].

    Les deux autres liaisons, Toulouse-Auch et Quillan-Limoux, sont bien des liaisons directes.

    Question 2

    A. D’après l’annexe 2, le joueur 2 possède cinq liaisons (en blanc) :

    liaisonsJoueur2 = [["Toulouse","Castres"],
                       ["Castres","Mazamet"],
                       ["Toulouse","Castelnaudary"],
                       ["Castelnaudary","Carcassonne"],
                       ["Tarbes","St Gaudens"]]

    B. Chaque liaison peut être parcourue dans les deux sens. Chaque ville apparaît donc comme clé, avec toutes les villes auxquelles elle est reliée :

    DictJoueur2 = {
                  "Toulouse":["Castres","Castelnaudary"],
                  "Castres":["Toulouse","Mazamet"],
                  "Mazamet":["Castres"],
                  "Castelnaudary":["Toulouse","Carcassonne"],
                  "Carcassonne":["Castelnaudary"],
                  "Tarbes":["St Gaudens"],
                  "St Gaudens":["Tarbes"]}

    Question 3

    Pour les références, on numérote les lignes de la fonction de 1 (def construireDict...) à 16 (return Dict). Les lignes 2 à 5 correspondent à la docstring, et la ligne 6 est Dict={}.

    A. On insère l’assertion après la docstring, entre les lignes 5 et 6 :

    assert len(listeLiaisons) > 0, "la liste des liaisons est vide"

    On peut aussi écrire assert listeLiaisons != [].

    B. Avec liaisonsJoueur1 en argument, la fonction renvoie :

    {"Toulouse":["Muret","Montauban"],
     "Gaillac":["St Sulpice"],
     "Muret":["Pamiers"]}

    La fonction ne répond que partiellement à la demande, car elle ne traite chaque liaison que dans un seul sens, de villeA vers villeB. Il manque donc les trajets retour. Par exemple, la clé "Montauban" est absente, alors que Montauban est reliée à Toulouse. De même, "Muret" devrait contenir "Toulouse" en plus de "Pamiers".

    C. Il faut faire le même traitement dans l’autre sens, de villeB vers villeA. On insère le code suivant après la ligne 15, au même niveau d’indentation que le premier if de la ligne 10, donc à l’intérieur de la boucle for :

        if not villeB in Dict.keys() :
          Dict[villeB]=[villeA]
        else :
          destinationsB = Dict[villeB]
          if not villeA in destinationsB :
            destinationsB.append(villeA)

    Fonction complète corrigée :

    def construireDict(listeLiaisons):
      """
      listeLiaisons est un tableau de tableaux représentant la
      liste des liaisons d'un joueur comme décrit dans le problème
      """
      assert len(listeLiaisons) > 0, "la liste des liaisons est vide"
      Dict={}
      for liaison in listeLiaisons :
        villeA = liaison[0]
        villeB = liaison[1]
        # sens villeA -> villeB
        if not villeA in Dict.keys() :
          Dict[villeA]=[villeB]
        else :
          destinationsA = Dict[villeA]
          if not villeB in destinationsA :
            destinationsA.append(villeB)
        # sens villeB -> villeA
        if not villeB in Dict.keys() :
          Dict[villeB]=[villeA]
        else :
          destinationsB = Dict[villeB]
          if not villeA in destinationsB :
            destinationsB.append(villeA)
      return Dict

    Appliquée à liaisonsJoueur1, cette fonction renvoie bien le dictionnaire DictJoueur1 donné dans l’énoncé.

    Bac 2021 Metropole Sept: Exercice 5

    Principaux thèmes abordés : Traitement de données en tables (CSV) et langages et programmation (spécification).

    tableau python bases csv

    Afin d’améliorer l’ergonomie d’un logiciel de traitement des inscriptions dans une université, un programmeur souhaite exploiter l’intelligence artificielle pour renseigner certains champs par auto-complétion. Il s’intéresse au descripteur « genre » (masculin, féminin ou indéterminé).

    Pour cela il propose d’exploiter les dernières lettres du prénom pour proposer automatiquement le genre.

    Pour vérifier son hypothèse, il récupère un fichier CSV associant plus de 60 000 prénoms du monde entier au genre de la personne portant ce prénom. En utilisant seulement la dernière lettre, le taux de réussite de sa démarche est de 72,9% avec la fonction définie ci-dessous :

    def genre(prenom):
      liste_M = ['f', 'd', 'c', 'b', 'o', 'n', 'm', 'l', 'k',
              'j', 'é', 'h', 'w', 'v', 'u', 't', 's', 'r',
              'q', 'p', 'i', 'þ', 'z', 'x', 'ç', 'ö', 'ã',
              'â', 'ï', 'g']
    liste_F = ['e', 'a', 'ä', 'ü', 'y', 'ë']
    
      if prenom[len(prenom)-1].lower() in liste_M :
        return "M"
      elif prenom[len(prenom)-1].lower() in liste_F :
        return "F"
      else :
        return "I"
    # Pour rappel, C.lower() convertit le caractère C en minuscule.

    1. Appropriation

    A. Expliquer ce qu’est un fichier CSV.

    B. Donner le type de l’argument prenom de la fonction genre, et le type de la réponse renvoyée.

    2. Développement

    Pour effectuer son étude sur les prénoms à partir du fichier CSV, le programmeur souhaite utiliser la bibliothèque csv.

    A. La bibliothèque csv est un module natif du moteur python. Donner, dans ce cas, l’instruction d’importation.

    B. Au cours du développement de son projet, le programmeur souhaite insérer une assertion sur l’argument donné à la fonction. Proposer une assertion sur le type de l’argument qui corrige une erreur lorsque le type ne correspond pas à celui attendu.

    C. Avant le déploiement de sa solution, le programmeur décide de rendre sa fonction plus robuste. Pour cela il veut remplacer l’assertion proposée dans la question 2.B) par une gestion de l’argument pour éviter toutes erreurs empêchant la poursuite du programme. Proposer alors une ou plusieurs instructions en Python utilisant l’argument afin de s’assurer que la fonction se termine quel que soit le type de l’argument.

    3. Améliorations

    En prenant en compte les deux dernières lettres du prénom, il parvient à augmenter son taux de réussite à 74,4%. Pour cela, son étude du fichier CSV lui permet de créer deux listes : liste_M2 pour les terminaisons de deux lettres associées aux prénoms masculins et liste_F2 pour les prénoms féminins. Sur votre copie, recopier et modifier la structure conditionnelle (lignes 8 à 13) de la fonction genre afin de prendre en compte les terminaisons de deux lettres des listes liste_M2 et liste_F2.

    Bac 2021 Etranger1: Exercice 2

    Notion abordée : structures de données (dictionnaires)

    dictionnaires python bases tuple

    Une ville souhaite gérer son parc de vélos en location partagée. L’ensemble de la flotte de vélos est stocké dans une table de données représentée en langage Python par un dictionnaire contenant des associations de type id_velo: dict_velo où id_velo est un nombre entier compris entre 1 et 199 qui correspond à l’identifiant unique du vélo et dict_velo est un dictionnaire dont les clés sont : "type", "etat", "station".

    Les valeurs associées aux clés "type", "etat", "station"de dict_velo sont de type chaînes de caractères ou nombre entier :

    • "type" : chaîne de caractères qui peut prendre la valeur “electrique” ou “classique”
    • "état" : nombre entier qui peut prendre la valeur 1 si le vélo est disponible, 0 si le vélo est en déplacement, -1 si le vélo est en panne
    • "station": chaînes de caractères qui identifie la station où est garé le vélo.

    Dans le cas où le vélo est en déplacement ou en panne, "station" correspond à celle où il a été dernièrement stationné.

    Voici un extrait de la table de données :

    flotte = {
      12 : {"type" : "electrique", "etat" : 1, "station" : "Prefecture"},
      80 : {"type" : "classique", "etat" : 0, "station" : "Saint-Leu"},
      45 : {"type" : "classique", "etat" : 1, "station" : "Baraban"},
      41 : {"type" : "classique", "etat" : -1, "station" : "Citadelle"},
      26 : {"type" : "classique", "etat" : 1, "station" : "Coliseum"},
      28 : {"type" : "electrique", "etat" : 0, "station" : "Coliseum"},
      74 : {"type" : "electrique", "etat" : 1, "station" : "Jacobins"},
      13 : {"type" : "classique", "etat" : 0, "station" : "Citadelle"},
      83 : {"type" : "classique", "etat" : -1, "station" : "Saint-Leu"},
      22 : {"type" : "electrique", "etat" : -1, "station" : "Joffre"}
      }

    flotte étant une variable globale du programme.

    Toutes les questions de cet exercice se réfèrent à l’extrait de la table flotte fourni cidessus. L’annexe 1 présente un rappel sur les dictionnaires en langage Python.

    Question 1

    • 1.a. Que renvoie l’instruction flotte[26] ?
    • 1.b. Que renvoie l’instruction flotte[80]["etat"] ?
    • 1.c. Que renvoie l’instruction flotte[99]["etat"] ?

    Question 2

    Voici le script d’une fonction :

    def proposition(choix):
     for v in flotte:
      if flotte[v]["type"] == choix and flotte[v]["etat"] == 1:
        return flotte[v]["station"]
    • 2.a. Quelles sont les valeurs possibles de la variable choix ?
    • 2.b. Expliquer ce que renvoie la fonction lorsque l’on choisit comme paramètre l’une des valeurs possibles de la variable choix.

    Question 3

    • 3.a. Écrire un script en langage Python qui affiche les identifiants (id_velo) de tous les vélos disponibles à la station "Citadelle".
    • 3.b. Écrire un script en langage Python qui permet d’afficher l’identifiant (id_velo) et la station de tous les vélos électriques qui ne sont pas en panne.

    Question 4

    On dispose d’une table de données des positions GPS de toutes les stations, dont un extrait est donné ci-dessous. Cette table est stockée sous forme d’un dictionnaire.

    Chaque élément du dictionnaire est du type: 'nom de la station' : (latitude, longitude)

    stations = {
      'Prefecture' : (49.8905, 2.2967) ,
      'Saint-Leu' : (49.8982, 2.3017),
      'Coliseum' : (49.8942, 2.2874),
      'Jacobins' : (49.8912, 2.3016)
      }

    On admet que l’on dispose d’une fonction distance(p1, p2) permettant de renvoyer la distance en mètres entre deux positions données par leurs coordonnées GPS (latitude et longitude).

    Cette fonction prend en paramètre deux tuples représentant les coordonnées des deux positions GPS et renvoie un nombre entier représentant cette distance en mètres.

    Par exemple, distance((49.8905, 2.2967), (49.8912, 2.3016)) renvoie 9591

    Écrire une fonction qui prend en paramètre les coordonnées GPS de l’utilisateur sous forme d’un tuple et qui renvoie, pour chaque station située à moins de 800 mètres de l’utilisateur :

    • le nom de la station ;
    • la distance entre l’utilisateur et la station ;
    • les identifiants des vélos disponibles dans cette station. Une station où aucun vélo n’est disponible ne doit pas être affichée.
    Corrigé

    Question 1

    1.a. flotte[26] renvoie le dictionnaire associé à la clé 26 :

    {"type" : "classique", "etat" : 1, "station" : "Coliseum"}

    1.b. flotte[80] vaut {"type" : "classique", "etat" : 0, "station" : "Saint-Leu"}, donc flotte[80]["etat"] renvoie 0 (le vélo est en déplacement).

    1.c. La clé 99 n’existe pas dans le dictionnaire flotte. L’instruction provoque une erreur : KeyError: 99.

    Question 2

    2.a. La fonction compare choix à flotte[v]["type"]. Les valeurs possibles sont donc les deux types de vélo : "electrique" ou "classique".

    2.b. La fonction parcourt les vélos de la flotte dans l’ordre. Elle renvoie le nom de la station du premier vélo trouvé qui est du type demandé et disponible (etat == 1). Le return interrompt la boucle dès le premier vélo trouvé.

    Avec l’extrait fourni :

    • proposition("electrique") renvoie "Prefecture" (vélo 12) ;
    • proposition("classique") renvoie "Baraban" (vélo 45, car le vélo 80 est en déplacement).

    Si aucun vélo ne correspond, la boucle se termine sans rencontrer de return, et la fonction renvoie None.

    Question 3

    3.a.

    for id_velo in flotte:
        if flotte[id_velo]["station"] == "Citadelle" and flotte[id_velo]["etat"] == 1:
            print(id_velo)

    Remarque : avec l’extrait fourni, ce script n’affiche rien. Le vélo 41 est en panne et le vélo 13 est en déplacement.

    3.b. Un vélo n’est pas en panne si son état est différent de -1. Il peut donc être disponible ou en déplacement.

    for id_velo in flotte:
        if flotte[id_velo]["type"] == "electrique" and flotte[id_velo]["etat"] != -1:
            print(id_velo, flotte[id_velo]["station"])

    Affichage obtenu :

    12 Prefecture
    28 Coliseum
    74 Jacobins

    Question 4

    def stations_proches(position):
        """
        position : tuple (latitude, longitude) de l'utilisateur
        renvoie une liste de tuples (nom_station, distance, liste_velos_disponibles)
        pour les stations à moins de 800 m ayant au moins un vélo disponible
        """
        resultat = []
        for nom in stations:
            d = distance(position, stations[nom])
            if d < 800:
                # recherche des vélos disponibles dans cette station
                velos_dispo = []
                for id_velo in flotte:
                    if flotte[id_velo]["station"] == nom and flotte[id_velo]["etat"] == 1:
                        velos_dispo.append(id_velo)
                # on ne garde la station que si au moins un vélo est disponible
                if len(velos_dispo) > 0:
                    resultat.append((nom, d, velos_dispo))
        return resultat

    Exemple d’utilisation :

    for nom, d, velos in stations_proches((49.8930, 2.2950)):
        print(nom, d, "m - vélos disponibles :", velos)

    Affichage obtenu :

    Prefecture 303 m - vélos disponibles : [12]
    Coliseum 560 m - vélos disponibles : [26]
    Jacobins 513 m - vélos disponibles : [74]

    La station Saint-Leu est à environ 751 m, donc à moins de 800 m, mais elle n’est pas affichée : aucun vélo n’y est disponible (le vélo 80 est en déplacement et le vélo 83 est en panne).

    Le principe est le suivant. Pour chaque station, on calcule sa distance à l’utilisateur. Si cette distance est inférieure à 800 m, on construit la liste des identifiants des vélos disponibles (etat == 1) garés dans cette station. On n’ajoute la station au résultat que si cette liste n’est pas vide.

    donnees structurees 1

    Bac 2024 Asie J2: Exercice 2

    Cet exercice porte sur la programmation orientée objet et les structures de données linéaires. POO pile

    Cet exercice est composé de 2 parties indépendantes.

    Dans cet exercice, on appelle parenthèses les couples de caractères (), {} et []. Pour chaque couple de parenthèses, la première parenthèse est appelée la parenthèse ouvrante du couple et la seconde est appelée la parenthèse fermante du couple.

    On dit qu’une expression (chaine de caractères) est bien parenthésée si:

    • chaque parenthèse ouvrante correspond à une parenthèse fermante de même type ;
    • les expressions comprises entre parenthèses sont des expressions bien parenthésées.

    Par exemple, l’expression tab[2*(i + 4)] - tab[3] est bien parenthésée.

    En revanche, l’expression tab[2*(i + 4] - tab[3) n’est pas bien parenthésée, car la première parenthèse fermante ] devrait correspondre à la dernière parenthèse ouvrante (.

    1. Déterminer si l’expression [2*(i+1)-3) for i in range(3, 10)] est bien parenthésée. Justifier votre réponse.

    Partie A

    On peut observer que, si les parenthèses vont par couple, une expression bien parenthésée contient autant de parenthèses ouvrantes que de parenthèses fermantes.

    On se propose d’écrire une fonction qui vérifie si une chaine de caractères est bien parenthésée.

    1. Écrire une fonction compte_ouvrante qui prend en paramètre une chaine de caractères txt et qui renvoie le nombre de parenthèses ouvrantes qu’il contient.
    2. Écrire une fonction compte_fermante qui prend en paramètre une chaine de caractères txt et qui renvoie le nombre de parenthèses fermantes qu’il contient.
    3. En utilisant les deux fonctions précédentes, écrire une fonction bon_compte qui prend en paramètre une chaine de caractères txt et qui renvoie True si txt a autant de parenthèses ouvrantes que parenthèses fermantes et False sinon.
    4. Donner un exemple de chaine de caractères pour laquelle bon_compte renvoie True alors qu’elle n’est pas bien parenthésée.

    Partie B

    Comme l’algorithme précédent n’est pas suffisant, on se propose d’implémenter un algorithme utilisant une structure linéaire de pile.

    On se propose d’écrire une classe Pile qui implémente la structure de pile.

    class Pile:
    def __init__(self):
      self.contenu = []
    
      def est_vide(self):
        return len(self.contenu) == 0
     
      def empiler(self, elt):
        ...
    
      def depiler(self):
        if self.est_vide():
          return "La pile est vide."
        return ...
    1. Compléter les lignes 9 et 14 du code précédent pour que la méthode empiler permette d’empiler un élément elt dans une pile et que la méthode depiler permette de dépiler une pile en renvoyant l’élément dépilé. Vous n’écrirez que le code des deux méthodes.

    Un algorithme permettant de vérifier si une expression est bien parenthésée consiste à:

    • créer une pile vide p ;
    • parcourir l’expression en testant chaque caractère : – si c’est une parenthèse ouvrante, on l’empile dans p ; – si c’est une parenthèse fermante, on dépile p ;
      • si les deux caractères correspondent à un couple de parenthèses, on continue le parcours,
      • sinon l’expression n’est pas bien parenthésée ; – sinon on continue le parcours.

    Si l’expression a été entièrement parcourue, on teste la pile ; l’expression est bien parenthésée si la pile est vide.

    1. Déterminer le nombre de comparaisons effectuées si on applique l’algorithme précédent à la chaine de caractères tab[2*(i + 4)] - tab[3]. En déduire le nombre maximum de comparaisons effectuées si on applique l’algorithme précédent à une chaine de caractères de taille n (attention aux comparaisons de la classe pile).

    2. Écrire une fonction est_bien_parenthesee qui prend en paramètre une chaine de caractères et qui implémente l’algorithme précédent.

    Bac 2022 Polynesie: Exercice 4

    Cet exercice traite du thème « structures de données », et principalement des piles. POO pile

    La classe Pile utilisée dans cet exercice est implémentée en utilisant des listes Python et propose quatre éléments d’interface :

    • Un constructeur qui permet de créer une pile vide, représentée par [] ;
    • La méthode est_vide() qui renvoie True si l’objet est une pile ne contenant aucun élément, et Falsesinon ;
    • La méthode empiler qui prend un objet quelconque en paramètre et ajoute cet objet au sommet de la pile. Dans la représentation de la pile dans la console, cet objet apparaît à droite des autres éléments de la pile ;
    • La méthode depiler qui renvoie l’objet présent au sommet de la pile et le retire de la pile.

    Exemples :

    >>> mapile = Pile()
    >>> mapile.empiler(2)
    >>> mapile
    [2]
    >>> mapile.empiler(3)
    >>> mapile.empiler(50)
    >>> mapile
    [2, 3, 50]
    >>> mapile.depiler()
    50
    >>> mapile
    [2, 3] 

    La méthode est_triee ci-dessous renvoie True si, en dépilant tous les éléments, ils sont traités dans l’ordre croissant, et False sinon.

    def est_triee(self):
      if not self.est_vide() :
        e1 = self.depiler()
        while not self.est_vide():
          e2 = self.depiler()
          if e1 ... e2 :
            return False
          e1 = ...
        return True

    Question 1

    Recopier sur la copie les lignes 6 et 8 en complétant les points de suspension.

    On créé dans la console la pile A représentée par [1, 2, 3, 4]

    Question 2

    A. Donner la valeur renvoyée par l’appel A.est_triee().

    B. Donner le contenu de la pile A après l’exécution de cette instruction.

    On souhaite maintenant écrire le code d’une méthode depileMaxd’une pile non vide ne contenant que des nombres entiers et renvoyant le plus grand élément de cette pile en le retirant de la pile.

    Après l’exécution de p.depileMax(), le nombre d’éléments de la pile p diminue donc de 1.

    def depileMax(self):
      assert not self.est_vide(), "Pile vide"
      q = Pile()
      maxi = self.depiler()
      while not self.est_vide() :
        elt = self.depiler()
        if maxi < elt :
          q.empiler(maxi)
          maxi = ...
        else :
          ...
      while not q.est_vide():
        self.empiler(q.depiler())
      return maxi

    Question 3

    Recopier sur la copie les lignes 9 et 11 en complétant les points de suspension.

    On créé la pile B représentée par [9, -7, 8, 12, 4] et on effectue l’appel B.depileMax().

    Question 4

    A. Donner le contenu des piles B et q à la fin de chaque itération de la boucle while de la ligne 5.

    B. Donner le contenu des piles B et q avant l’exécution de la ligne 14.

    C. Donner un exemple de pile qui montre que l’ordre des éléments restants n’est pas préservé après l’exécution de depileMax.

    On donne le code de la méthode traiter():

    def traiter(self):
    q = Pile()
    while not self.est_vide():
    q.empiler(self.depileMax())
    while not q.est_vide():
    self.empiler(q.depiler())

    Question 5

    A. Recopier le code avec la bonne indentation.

    B. Donner les contenus successifs des piles B et q

    • avant la ligne 3,
    • avant la ligne 5,
    • à la fin de l’exécution de la fonction traiter lorsque la fonction traiter est appliquée sur la pile B contenant [1, 6, 4, 3, 7, 2].

    C. Expliquer le traitement effectué par cette méthode.

    Bac 2022 Metropole 1: Exercice 1

    Cet exercice composé de deux parties A et B, porte sur les structures de données. pile

    Partie A : Expression correctement parenthésée

    On veut déterminer si une expression arithmétique est correctement parenthésée. Pour chaque parenthèse fermante “)” correspond une parenthèse précédemment ouverte “(”.

    Exemples :

    • L’expression arithmétique “(2 + 3) × (18/(4 + 2))” est correctement parenthésée.
    • L’expression arithmétique “(2 + 3) × (18/(4 + 2” est non correctement parenthésée.

    Pour simplifier les expressions arithmétiques, on enregistre, dans une structure de données, uniquement les parenthèses dans leur ordre d’apparition.

    On appelle expression simplifiée cette structure.

    1158 × 248

    1158 × 248

    Question 1

    Indiquer si la phrase « les éléments sont maintenant retirés (pour être lus) de cette structure de données dans le même ordre qu’ils y ont été ajoutés lors de l’enregistrement » décrit le comportement d’une file ou d’une pile. Justifier.

    Pour vérifier le parenthésage, on peut utiliser une variable controleur qui :

    • est un nombre entier égal à 0 en début d’analyse de l’expression simplifiée ;
    • augmente de 1 si l’on rencontre une parenthèse ouvrante “(” ;
    • diminue de 1 si l’on rencontre une parenthèse fermante “)”.

    Exemple : On considère l’ expression simplifiée A : “( )( ( ) )” Lors de l’analyse de l’expression A, controleur (initialement égal à 0) prend successivement pour valeur 1, 0, 1, 2, 1, 0. Le parenthésage est correct.

    Question 2

    Écrire, pour chacune des 2 expressions simplifiées B et C suivantes, les valeurs successives prises par la variable controleur lors de leur analyse.

    • Expression simplifiée B : " ((( )( )"
    • Expression simplifiée C : “(( )))(”

    Question 3

    L’expression simplifiée B précédente est mal parenthésée (parenthèses fermantes manquantes) car le controleur est différent de zéro en fin d’analyse.

    L’expression simplifiée C précédente est également mal parenthésée (parenthèse fermante sans parenthèse ouvrante) car le controleur prend une valeur négative pendant l’analyse.

    Recopier et compléter uniquement les lignes 13 et 16 du code ci-dessous pour que la fonction parenthesage_correct réponde à sa description.

     def parenthesage_correct(expression):
        """fonction retournant True si l'expression arithmétique
        simplifiée (str) est correctement parenthésée, False
        sinon.
        Condition: expression ne contient que des parenthèses
        ouvrantes et fermantes """
        controleur = 0
        for parenthese in expression: #pour chaque parenthèse
          if parenthese == '(':
            controleur = controleur + 1
          else:# parenthese == ')'
            controleur = controleur - 1
            if controleur ... : # test 1 (à recopier et compléter)
              #parenthèse fermante sans parenthèse ouvrante
              return False
        if controleur ... : # test 2 (à recopier et compléter)
            return True #le parenthésage est correct
          else:
            return False #parenthèse(s) fermante(s) manquante(s)

    Partie B : Texte correctement balisé

    On peut faire l’analogie entre le texte simplifié des fichiers HTML (uniquement constitué de balises ouvrantes et fermantes ) et les expressions parenthésées : Par exemple, l’expression HTML simplifiée :

    "<p><strong><em></em></strong></p>" est correctement balisée.

    On ne tiendra pas compte dans cette partie des balises ne comportant pas de fermeture comme <br> ou <img …>.

    Afin de vérifier qu’une expression HTML simplifiée est correctement balisé, on peut utiliser une pile (initialement vide) selon l’algorithme suivant :

    On parcourt successivement chaque balise de l’expression :

    • lorsque l’on rencontre une balise ouvrante, on l’empile ;
    • lorsque l’on rencontre une balise fermante :
    • si la pile est vide, alors l’analyse s’arrête : le balisage est incorrect ,
    • sinon, on dépile et on vérifie que les deux balises (la balise fermante rencontrée et la balise ouvrante dépilée) correspondent (c’est-à-dire ont le même nom) si ce n’est pas le cas, l’analyse s’arrête (balisage incorrect).

    Exemple : État de la pile lors du déroulement de cet algorithme pour l’expression simplifiée "<p><em></p></em>" qui n’est pas correctement balisée.

    État de la pile lors du déroulement de l’algorithme - 1242 × 258

    État de la pile lors du déroulement de l’algorithme - 1242 × 258

    Question 4

    Cette question traite de l’état de la pile lors du déroulement de l’algorithme.

    A. Représenter la pile à chaque étape du déroulement de cet algorithme pour l’expression "<p><em></em></p>" (balisage correct).

    B. Indiquer quelle condition simple (sur le contenu de la pile) permet alors de dire que le balisage est correct lorsque toute l’expression HTML simplifiée a été entièrement parcourue, sans que l’analyse ne s’arrête.

    Question 5

    Une expression HTML correctement balisée contient 12 balises. Indiquer le nombre d’éléments que pourrait contenir au maximum la pile lors de son analyse.

    Bac 2022 Metropole 2: Exercice 2

    Cet exercice porte sur les structures de données. pile recursivité

    La poussette est un jeu de cartes en solitaire. Cet exercice propose une version simplifiée de ce jeu basée sur des nombres.

    On considère une pile constituée de nombres entiers tirés aléatoirement. Le jeu consiste à réduire la pile suivant la règle suivante : quand la pile contient du haut vers le bas un triplet dont les termes du haut et du bas sont de même parité, on supprime l’élément central.

    Par exemple :

    • Si la pile contient du haut vers le bas, le triplet 1 0 3, on supprime le 0.
    • Si la pile contient du haut vers le bas, le triplet 1 0 8, la pile reste inchangée.

    On parcourt la pile ainsi de haut en bas et on procède aux réductions. Arrivé en bas de la pile, on recommence la réduction en repartant du sommet de la pile jusqu’à ce que la pile ne soit plus réductible. Une partie est « gagnante » lorsque la pile finale est réduite à deux éléments exactement.

    Voici un exemple détaillé de déroulement d’une partie.

    1128 × 412

    1128 × 412

    Question 1

    A. Donner les différentes étapes de réduction de la pile suivante :

    524 × 394

    524 × 394

    B. Parmi les piles proposées ci-dessous, donner celle qui est gagnante.

    952 × 468

    952 × 468

    L’interface d’une pile est proposée ci-dessous. On utilisera uniquement les fonctions figurant dans le tableau suivant :

    Structure de données abstraite : Pile
    creer_pile_vide() renvoie une pile vide
    est_vide(p) renvoie True si p est vide, False sinon
    empiler(p, element) ajoute element au sommet de p
    depiler(p) retire l’élément au sommet de p et le renvoie
    sommet(p) renvoie l’élément au sommet de p sans le retirer de p
    taille(p) renvoie le nombre d’éléments de p

    Question 2

    La fonction reduire_triplet_au_sommet permet de supprimer l’élément central des trois premiers éléments en partant du haut de la pile, si l’élément du bas et du haut sont de même parité. Les éléments dépilés et non supprimés sont replacés dans le bon ordre dans la pile.

    Recopier et compléter sur la copie le code de la fonction reduire_triplet_au_sommet prenant une pile p en paramètre et qui la modifie en place. Cette fonction ne renvoie donc rien.

    def reduire_triplet_au_sommet(p):
      a = depiler(p)
      b = depiler(p)
      c = sommet(p)
      if a % 2 != .... :
        empiler(p, ...)
      empiler(p, ...) 

    Question 3

    On se propose maintenant d’écrire une fonction parcourir_pile_en_reduisant qui parcourt la pile du haut vers le bas en procédant aux réductions pour chaque triplet rencontré quand cela est possible.

    A. Donner la taille minimale que doit avoir une pile pour être réductible.

    B. Recopier et compléter sur la copie :

    def parcourir_pile_en_reduisant(p):
      q = creer_pile_vide()
      while taille(p) >= ....:
        reduire_triplet_au_sommet(p)
        e = depiler(p)
        empiler(q, e)
      while not est_vide(q):
        .............
        .............
      return p

    Question 4

    Partant d’une pile d’entiers p, on propose ici d’implémenter une fonction récursive jouer renvoyant la pile p entièrement simplifiée. Une fois la pile parcourue de haut en bas et réduite, on procède à nouveau à sa réduction à condition que cela soit possible. Ainsi :

    • Si la pile p n’a pas subi de réduction, on la renvoie.
    • Sinon on appelle à nouveau la fonction jouer , prenant en paramètre la pile réduite.

    Recopier et compléter sur la copie le code ci-dessous :

    def jouer(p):
      q = parcourir_pile_en_reduisant(p)
      if .............. :
        return p
      else:
        return jouer(...)

    donnees structurees 2

    Bac 2022 Polynesie: Exercice 5

    Cet exercice traite du thème « algorithmique », et principalement des algorithmes sur les arbres binaires.

    arbre binaire hauteur

    On manipule ici les arbres binaires avec trois fonctions :

    • est_vide(A) qui renvoie True si l’arbre binaire A est vide, False s’il ne l’est pas ;
    • sous_arbre_gauche(A) qui renvoie le sous-arbre gauche de l’arbre binaire A ;
    • sous_arbre_droit(A) qui renvoie le sous-arbre droit de l’arbre binaire A.

    L’arbre binaire renvoyé par les fonctions sous_arbre_gauche et sous_arbre_droit peut éventuellement être l’arbre vide.

    On définit la hauteur d’un arbre binaire non vide de la façon suivante :

    • si ses sous-arbres gauche et droit sont vides, sa hauteur est 0 ;
    • si l’un des deux au moins est non vide, alors sa hauteur est égale à 1 + M, où M est la plus grande des hauteurs de ses sous-arbres (gauche et droit) non vides.

    Question 1

    A. Donner la hauteur de l’arbre ci-dessous.

    304 × 232

    304 × 232

    B. Dessiner sur la copie un arbre binaire de hauteur 4.

    La hauteur d’un arbre est calculée par l’algorithme récursif suivant :

    Algorithme hauteur(A):
      test d'assertion : A est supposé non vide
      si sous_arbre_gauche(A) vide et sous_arbre_droit(A) vide:
        renvoyer 0
      sinon, si sous_arbre_gauche(A) vide:
        renvoyer 1 + hauteur(sous_arbre_droit(A))
      sinon, si ... :
        renvoyer ...
      sinon:
        renvoyer 1 + max(hauteur(sous_arbre_gauche(A)),
        hauteur(sous_arbre_droit(A)))

    Question 2

    Recopier sur la copie les lignes 7 et 8 en complétant les points de suspension.

    Question 3

    On considère un arbre binaire R dont on note G le sous-arbre gauche et D le sous-arbre droit. On suppose que R est de hauteur 4 et G de hauteur 2.

    A. Justifier le fait que D n’est pas l’arbre vide et déterminer sa hauteur.

    B. Illustrer cette situation par un dessin.

    Soit un arbre binaire non vide de hauteur h. On note n le nombre de nœuds de cet arbre. On admet que $h+1 \leqslant n \leqslant 2^{h+1}−1$.

    Question 4

    A. Vérifier ces inégalités sur l’arbre binaire de la question 1.A.

    B. Expliquer comment construire un arbre binaire de hauteur h quelconque ayant h+1 nœuds.

    C. Expliquer comment construire un arbre binaire de hauteur h quelconque ayant $2^{h+1}−1$ nœuds.

    Indication : $2^{h+1}−1 = 1+2+4+...+2^h$

    L’objectif de la fin de l’exercice est d’écrire le code d’une fonction fabrique(h, n) qui prend comme paramètres deux nombres entiers positifs h et n tels que $h+1 \leqslant n \leqslant 2^{h+1}−1$, et qui renvoie un arbre binaire de hauteur h à n nœuds.

    Pour cela, on a besoin des deux fonctions suivantes:

    • arbre_vide(), qui renvoie un arbre vide ;
    • arbre(gauche, droit) qui renvoie l’arbre de fils gauche gauche et de fils droit droit.

    Question 5

    Recopier sur la copie l’arbre binaire ci-dessous et numéroter ses nœuds de 1 en 1 en commençant à 1, en effectuant un parcours en profondeur préfixe.

    546 × 322

    546 × 322

    La fonction fabrique ci-dessous a pour but de répondre au problème posé. Pour cela, la fonction annexe utilise la valeur de n, qu’elle peut modifier, et renvoie un arbre binaire de hauteur hauteur_max dont le nombre de nœuds est égal à la valeur de n au moment de son appel.

    def fabrique(h, n):
      def annexe(hauteur_max):
        if n == 0 :
          return arbre_vide()
        elif hauteur_max == 0:
          n = n - 1
          return ...
        else:
          n = n - 1
          gauche = annexe(hauteur_max - 1)
          droite = ...
          return arbre(gauche, droite)
      return annexe(h)

    Question 6

    Recopier sur la copie les lignes 7 et 11 en complétant les points de suspension.

    Bac 2022 Metropole 1: Exercice 4

    Cet exercice, composé de deux parties A et B, porte sur le parcours des arbres binaires, le principe “diviser pour régner” et la récursivité.

    arbre parcours File récursivité

    Cet exercice traite du calcul de la somme d’un arbre binaire. Cette somme consiste à additionner toutes les valeurs numériques contenues dans les nœuds de l’arbre.

    L’arbre utilisé dans les parties A et B est le suivant :

    314 × 252

    314 × 252

    Partie A : Parcours d’un arbre

    Question 1

    Donner la somme de l’arbre précédent. Justifier la réponse en explicitant le calcul qui a permis de l’obtenir.

    Question 2

    Indiquer la lettre correspondante aux noms ‘racine’, ‘feuille’, ‘nœud’, ‘SAG’ (Sous Arbre Gauche) et ‘SAD’ (Sous Arbre Droit). Chaque lettre A, B, C, D et E devra être utilisée une seule fois.

    Arbre avec les lettres à associer - 578 × 310

    Arbre avec les lettres à associer - 578 × 310

    Question 3

    Parmi les quatre propositions A, B, C et D ci-dessous, donnant un parcours en largeur d’abord de l’arbre, une seule est correcte. Indiquer laquelle.

    • Proposition A : 7 - 6 - 4 - 3 - 9 - 2 - 1
    • Proposition B : 3 - 6 - 7 - 4 - 2 - 9 - 1
    • Proposition C : 3 - 6 - 2 - 7 - 4 - 9 - 1
    • Proposition D : 7 - 4 - 6 - 9 - 1 - 2 – 3

    Question 4

    Écrire en langage Python la fonction somme qui prend en paramètre une liste de nombres et qui renvoie la somme de ses éléments.

    Exemple : somme([1, 2, 3, 4]) est égale à 10.

    Question 5

    La fonction parcourir(arbre) pourrait se traduire en langage naturel par :

    parcourir(A):
      L = liste_vide
      F = file_vide
      enfiler A dans F
      Tant que F n est pas vide
        défiler S de F
        ajouter la valeur de la racine de S dans L
          Pour chaque sous arbre SA non vide de S
            enfiler SA dans F
      renvoyer L

    Donner le type de parcours obtenu grâce à la fonction parcourir.

    Partie B : Méthode ‘diviser pour régner’

    diviser pour regner

    Question 6

    Parmi les quatre propositions A,B, C et D ci-dessous, indiquer la seule proposition correcte.

    En informatique, le principe diviser pour régner signifie :

    • Proposition A: diviser une fonction en deux fonctions plus petites
    • Proposition B: utiliser plusieurs modules
    • Proposition C: séparer les informations en fonction de leur types
    • Proposition D: diviser un problème en deux problèmes plus petits et indépendants.

    Question 7

    L’arbre présenté dans le problème peut être décomposé en racine et sous arbres :

    376 × 258

    376 × 258

    Indiquer dans l’esprit de ‘diviser pour régner’ l’égalité donnant la somme d’un arbre en fonction de la somme des sous arbres et de la valeur numérique de la racine.

    Question 8

    Écrire en langage Python une fonction récursive calcul_somme(arbre). Cette fonction calcule la somme de l’arbre passé en paramètre. Les fonctions suivantes sont disponibles :

    • est_vide(arbre) : renvoie True si arbreest vide et renvoie False sinon ;
    • valeur_racine(arbre) : renvoie la valeur numérique de la racine de arbre;
    • arbre_gauche(arbre) : renvoie le sous arbre gauche de arbre;
    • arbre_droit(arbre) : renvoie le sous arbre droit de arbre.

    Bac 2022 Metropole 2: Exercice 1

    Cet exercice porte sur les arbres binaires de recherche, la programmation orientée objet et la récursivité.

    ABR POO récursivité

    Dans cet exercice, la taille d’un arbre est le nombre de nœuds qu’il contient. Sa hauteur est le nombre de nœuds du plus long chemin qui joint le nœud racine à l’une des feuilles (nœuds sans sous-arbres). On convient que la hauteur d’un arbre ne contenant qu’un nœud vaut 1 et la hauteur de l’arbre vide vaut 0.

    Question 1

    On considère l’arbre binaire représenté ci-dessous:

    Figure 1 - 390 × 370

    Figure 1 - 390 × 370

    A. Donner la taille de cet arbre.

    B. Donner la hauteur de cet arbre.

    C. Représenter sur la copie le sous-arbre droit du nœud de valeur 15.

    D. Justifier que l’arbre de la figure 1 est un arbre binaire de recherche.

    E. On insère la valeur 17 dans l’arbre de la figure 1 de telle sorte que 17 soit une nouvelle feuille de l’arbre et que le nouvel arbre obtenu soit encore un arbre binaire de recherche. Représenter sur la copie ce nouvel arbre.

    Question 2

    On considère la classe Noeud définie de la façon suivante en Python :

    class Noeud:
      def __init__(self, g, v, d):
        self.gauche = g
        self.valeur = v
        self.droit = d

    A. Parmi les trois instructions (A), (B) et (C) suivantes, écrire sur la copie la lettre correspondant à celle qui construit et stocke dans la variable abr l’arbre représenté ci-contre.

    (A) abr=Noeud(Noeud(Noeud(None,13,None),15,None),21,None)

    (B) abr=Noeud(None,13,Noeud(Noeud(None,15,None),21,None))

    (C) abr=Noeud(Noeud(None,13,None),15,Noeud(None,21,None))

    B. Recopier et compléter la ligne 7 du code de la fonction ins ci-dessous qui prend en paramètres une valeur v et un arbre binaire de recherche abr et qui renvoie l’arbre obtenu suite à l’insertion de la valeur v dans l’arbre abr. Les lignes 8 et 9 permettent de ne pas insérer la valeur v si celle-ci est déjà présente dans abr.

    def ins(v, abr):
      if abr is None:
        return Noeud(None, v, None)
      if v > abr.valeur:
        return Noeud(abr.gauche,abr.valeur,ins(v,abr.droit))
      elif v < abr.valeur:
        return ............................................
      else:
        return abr 

    Question 3

    La fonction nb_sup prend en paramètres une valeur v et un arbre binaire de recherche abr et renvoie le nombre de valeurs supérieures ou égales à la valeur v dans l’arbre abr.

    Le code de cette fonction nb_sup est donné ci-dessous :

    def nb_sup(v, abr):
      if abr is None:
        return 0
      else:
        if abr.valeur >= v:
          return 1+nb_sup(v, abr.gauche)+nb_sup(v, abr.droit)
        else:
          return nb_sup(v, abr.gauche)+nb_sup(v, abr.droit)

    A. On exécute l’instruction nb_sup(16, abr) dans laquelle abr est l’arbre initial de la figure 1. Déterminer le nombre d’appels à la fonction nb_sup.

    B. L’arbre passé en paramètre étant un arbre binaire de recherche, on peut améliorer la fonction nb_sup précédente afin de réduire ce nombre d’appels. Écrire sur la copie le code modifié de cette fonction.

    Bac 2023 Centres etrangers J4

    (extrait du sujet) tri fusion

    Le grossiste enregistre dans la liste sommes les montants des commandes, avant réduction, que des clients ont passées dans son magasin.

    Par exemple : sommes = [140, 78, 115, 94, 46, 108, 55, 53]

    Il va utiliser la méthode de tri-fusion pour trier la liste sommes dans l’ordre croissant. L’algorithme du tri-fusion est naturellement décrit de façon récursive (dans toute la suite, on supposera pour simplifier que le nombre d’éléments de la liste est une puissance de 2) :

    • si la liste n’a qu’un ou aucun élément, elle est déjà triée,
    • sinon:
      • on sépare la liste initiale en deux listes de même taille,
      • on applique récursivement l’algorithme sur ces deux listes,
      • on fusionne les deux listes triées obtenues en une seule liste triée.

    On trouve ci-dessous un exemple de déroulement de cet algorithme pour la liste [140,78,115,94] de 4 éléments :

    division et tri fusion

    division et tri fusion

    {.class width=1072 height=478px}

    a. Appliquer sur votre copie, de la même façon que dans l’exemple précédent, le déroulement de l’algorithme pour la liste suivante : [46, 108, 55, 53]

    On rappelle que l’appel L.append(x) ajoute l’élément x à la fin de la liste L et que len(L) renvoie la taille de la liste L.

    b. La fonction fusion ci-dessous renvoie une liste de valeurs triées à partir des deux listes liste1 et liste2 préalablement triées. Ecrire sur la copie l’instruction à placer à la ligne 4 du code de la fonction fusion :

    script de la fonction fusion

    script de la fonction fusion

    {.class width=820 height=562px}

    Choisir parmi les propositions:

    while i1 < len(liste1) and i2 < len(liste2):
    while i1 < len(liste1) or i2 < len(liste2):

    Justifiez votre choix.

    c. Recopier et compléter sur la copie la fonction récursive tri_fusion suivante, qui prend en paramètre une liste non triée et la renvoie sous la forme d’une nouvelle liste triée.

    On utilisera la fonction fusion de la question précédente.

    Exemple : tri_fusion([140,115,78,94]) doit renvoyer [78,94,115,140]

    Aide Python : si L est une liste, l’instruction L[i:j] renvoie la liste constituée des éléments de L indexés de i à j-1. Par exemple, si L=[5,4,8,7,3], L[2:4] vaut [8,7].

    def tri_fusion(liste):
      if len(liste)<=1:
        return liste
      # a completer

    Bac 2021 Polynesie Exercice 1

    Algorithmes de tri insertion tri fusion complexité

    Cet exercice traite principalement du thème « algorithmique, langages et programmation ». Le but est de comparer le tri par insertion (l’un des algorithmes étudiés en 1ère NSI pour trier un tableau) avec le tri fusion (un algorithme qui applique le principe de « diviser pour régner »).

    Partie A : Manipulation d’une liste en Python

    1. Donner les affichages obtenus après l’exécution du code Python suivant.
    notes = [8, 7, 18, 14, 12, 9, 17, 3]
    notes[3] = 16
    print(len(notes))
    print(notes)
    1. Écrire un code Python permettant d’afficher les éléments d’indice 2 à 4 de la liste notes

    Partie B : Tri par insertion

    Le tri par insertion est un algorithme efficace qui s’inspire de la façon dont on peut trier une poignée de cartes. On commence avec une seule carte dans la main gauche (les autres cartes sont en tas sur la table) puis on pioche la carte suivante et on l’insère au bon endroit dans la main gauche.

    1. Voici une implémentation en Python de cet algorithme. Recopier et compléter les lignes 6 et 7 surlignées (uniquement celles-ci).
    def tri_insertion(liste):
      """ trie par insertion la liste en paramètre """
      for indice_courant in range(1,len(liste)):
        element_a_inserer = liste[indice_courant]
        i = indice_courant - 1
        while i >= 0 and liste[i] > ................. :
          liste[...........] = liste[...........]
          i = i - 1
        liste[i + 1] = element_a_inserer

    On a écrit dans la console les instructions suivantes :

    notes = [8, 7, 18, 14, 12, 9, 17, 3]
    tri_insertion(notes)
    print(notes)

    On a obtenu l’affichage suivant : [3, 7, 8, 9, 12, 14, 17, 18]

    On s’interroge sur les étapes lors de l’exécution de tri_insertion(notes)

    1. Donner le contenu de la liste notes après le premier passage dans la boucle for.
    2. Donner le contenu de la liste notes après le troisième passage dans la boucle for.
    3. Quelle est la complexité algorithmique de cet algorithme dans le meilleur des cas? (celui où la liste en paramètre est déjà triée). Justifiez.

    Partie C : Tri fusion

    L’algorithme de tri fusion suit le principe de « diviser pour régner ».

    1. Si le tableau à trier n’a qu’un élément, il est déjà trié.
    2. Sinon, séparer le tableau en deux parties à peu près égales.
    3. Trier les deux parties avec l’algorithme de tri fusion.
    4. Fusionner les deux tableaux triés en un seul tableau.

    source wikipedia

    1. Cet algorithme est-il itératif ou récursif ? Justifier en une phrase.
    2. Expliquer en quelques lignes comment faire pour rassembler dans une main deux tas déjà triés de cartes, la carte en haut d’un tas étant la plus petite de ce même tas ; la deuxième carte d’un tas n’étant visible qu’après avoir retiré la première carte de ce tas.

    À la fin du procédé, les cartes en main doivent être triées par ordre croissant.

    Une fonction fusionner a été implémentée en Python en s’inspirant du procédé de la question précédente. Elle prend quatre arguments : la liste qui est en train d’être triée, l’indice où commence la sous-liste de gauche à fusionner, l’indice où termine cette sous-liste, et l’indice où se termine la sous-liste de droite.

    1. Voici une implémentation de l’algorithme de tri fusion. Recopier et compléter les lignes 8, 9 et 10 surlignées (uniquement celles-ci).
    from math import floor
    
    def tri_fusion (liste, i_debut, i_fin):
      """ trie par fusion la liste en paramètre depuis
      i_debut jusqu’à i_fin """
      if i_debut < i_fin:
        i_partage = floor((i_debut + i_fin) / 2)
        tri_fusion(liste, i_debut, ..............................)
        tri_fusion(liste, .............................., i_fin)
        fusionner(liste, ..............., ............., .............) 

    Remarque : la fonction floor renvoie la partie entière du nombre passé en paramètre.

    1. Expliquer le rôle de la première ligne du code de la question précédente.

    Partie D : Comparaison du tri par insertion et du tri fusion

    Voici une illustration des étapes d’un tri effectué sur la liste [3, 41, 52, 26, 38, 57, 9, 49]

    Figure 1 - 500 × 400

    Figure 1 - 500 × 400

    1. Quel algorithme a été utilisé : le tri par insertion ou le tri fusion ? Justifier.

    2. Identifier le tri qui a une complexité, dans le pire des cas, en $O(n^2)$ et identifier le tri qui a une complexité, dans le pire des cas, en $O(n log_2 n)$.

    Remarque : n représente la longueur de la liste à trier.

    Justifier brièvement ces deux complexités.

    Files

    Bac 2023 Centres Etrangers: Exercice 3

    Cet exercice porte sur les structures de Files

    Files

    Simon est un jeu de société électronique de forme circulaire comportant quatre grosses touches de couleurs différentes : rouge, vert, bleu et jaune.

    Le jeu joue une séquence de couleurs que le joueur doit mémoriser et répéter ensuite. S’il réussit, une couleur parmi les 4 est ajoutée à la fin de la séquence. La nouvelle séquence est jouée depuis le début et le jeu continue. Dès que le joueur se trompe, la séquence est vidée et réinitialisée avec une couleur et une nouvelle partie commence.

    Exemple de séquence jouée : rouge => bleu => rouge => jaune => bleu

    Dans cet exercice nous essaierons de reproduire ce jeu.

    Les quatre couleurs sont stockées dans un tuple nommé couleurs :

    couleurs = ("bleu", "rouge", "jaune", "vert")

    Pour stocker la séquence à afficher nous utiliserons une structure de file que l’on nommera sequence tout au long de l’exercice.

    La file est une structure linéaire de type FIFO (First In First Out). Nous utiliserons durant cet exercice les fonctions suivantes :

    Fonction Description
    creer_file_vide() renvoie une file vide
    est_vide(f) renvoie True si f est vide False sinon
    enfiler(f, element) ajoute element en queue de f
    defiler(f) retire l’element en tête de f et le renvoie
    taille(f) renvoie le nombre d’elements de f

    En fin de chaque séquence, le Simon tire au hasard une couleur parmi les 4 proposées. On utilisera la fonction randint(a,b) de la bibliothèque random qui permet d’obtenir un nombre entier compris entre a inclus et b inclus pour le tirage aléatoire. Exemple : randint(1,5) peut renvoyer 1, 2, 3, 4 ou 5.

    1. Recopier et compléter, sur votre copie, les … des lignes 3 et 4 de la fonction ajout(f) qui permet de tirer au hasard une couleur et de l’ajouter à une séquence. La fonction ajout prend en paramètre la séquence f ; elle renvoie la séquence f modifiée (qui intègre la couleur ajoutée au format chaîne de caractères).
    def ajout(f):
    	couleurs = ["bleu","rouge","jaune","vert"]
    	indice = randint(...)
    	enfiler(...,...)
    	return f

    En cas d’erreur du joueur durant sa réponse, la partie reprend au début ; il faut donc vider la file sequence pour recommencer à zéro en appelant vider(sequence) qui permet de rendre la file sequence vide sans la renvoyer.

    1. Ecrire la fonction vider qui prend en paramètre une séquence f et la vide sans la renvoyer.

    Le Simon doit afficher successivement les différentes couleurs de la séquence. Ce rôle est confié à la fonction affich_seq(sequence), qui prend en paramètre la file de couleurs sequence, définie par l’algorithme suivant :

    • on ajoute une nouvelle couleur à sequence ;
    • on affiche les couleurs de la séquence, une par une, avec une pause de 0,5 s entre chaque affichage

    Une fonction affichage(couleur) (dont la rédaction n’est pas demandée dans cet exercice) permettra l’affichage de la couleur souhaitée avec couleur de type chaîne de caractères correspondant à une des 4 couleurs. La temporisation de 0,5 s sera effectuée avec la commande time.sleep(0.5). Après l’exécution de la fonction affich_seq, la file sequence ne devra pas être vidée de ses éléments.

    1. Recopier et compléter, sur la copie, les … des lignes 4 à 10 de la fonction affich_seq(sequence) ci-dessous :
    def affiche_seq(sequence):
    	stock = ceer_file_vide()
    	ajout(sequence)
    	while not est_vide(sequence):
    		c = ...
    		...
    		time.sleep(0.5)
    	while ... : 
    		...
    1. Nous allons ici créer une fonction tour_de_jeu(sequence) qui gère le déroulement d’un tour quelconque de jeu côté joueur. La fonction tour_de_jeu prend en paramètre la file de couleurs sequence, qui contient un certain nombre de couleurs.
    • Le jeu électronique Simon commence par ajouter une couleur à la séquence et affiche l’intégralité de la séquence.
    • Le joueur doit reproduire la séquence dans le même ordre. Il choisit une couleur via la fonction saisie_joueur().
    • On vérifie si cette couleur est conforme à celle de la séquence.
    • S’il s’agit de la bonne couleur, on poursuit sinon on vide sequence.
    • Si le joueur arrive au bout de la séquence, il valide le tour de jeu et le jeu se poursuit avec un nouveau tour de jeu, sinon le joueur a perdu et le jeu s’arrête. La fonction tour_de_jeu s’arrête donc si le joueur a trouvé toutes les bonnes couleurs de sequence dans l’ordre, ou bien dès que le joueur se trompe. Après l’exécution de la fonction tour_de_jeu, la file sequence ne devra pas être vidée de ses éléments en cas de victoire.

    a. Afin d’obtenir la fonction tour_de_jeu(sequence) correspondant au comportement décrit ci-dessus, recopier le script ci-dessous et :

    • Complétez le …
    • Choisir parmi les propositions de syntaxes suivantes lesquelles correspondent aux ZONES A, B, C, D, E et F figurant dans le script et les y remplacer (il ne faut donc en choisir que six parmi les onze) :
    vider(sequence)
    defiler(sequence)
    enfiler(sequence,c_joueur)
    enfiler(stock,c_seq)
    enfiler(sequence, defiler(stock))
    enfiler(stock, defiler(sequence))
    affich_seq(sequence)
    while not est_vide(sequence):
    while not est_vide(stock):
    if not est_vide(sequence):
    if not est_vide(stock):
    def tour_de_jeu(sequence):
    	ZONE A
    	stock = creer_file_vide()
    	while not est_vide(sequence):
    		c_joueur = saisie_joueur()
    		c_seq = ZONE B
    		if c_joueur ... c_seq:
    			ZONE C
    		else:
    			ZONE D
    	ZONE E
    	    ZONE F

    b. Proposer une modification pour que la fonction se répète si le joueur trouve toutes les couleurs de la séquence (dans ce cas, une nouvelle couleur est ajoutée) ou s’il se trompe (dans ce cas, la séquence est vidée et se voit ajouter une nouvelle couleur). On pourra ajouter des instructions qui ne sont pas proposées dans la question a

    algorithmique

    Bac 2022 Polynesie: Exercice 1

    Cet exercice traite du thème «programmation», et principalement de la récursivité. récursivité chaine str choice

    On rappelle qu’une chaîne de caractères peut être représentée en Python par un texte entre guillemets "" et que :

    • la fonction len renvoie la longueur de la chaîne de caractères passée en paramètre ;
    • si une variable ch désigne une chaîne de caractères, alors ch[0] renvoie son premier caractère, ch[1] le deuxième, etc. ;
    • l’opérateur + permet de concaténer deux chaînes de caractères.

    Exemples :

    >>> texte = "bricot"
    >>> len(texte)
    6
    >>> texte[0]
    "b"
    >>> texte[1]
    "r"
    >>> "a" + texte
    "abricot"

    On s’intéresse dans cet exercice à la construction de chaînes de caractères suivant certaines règles de construction.

    Règle A : une chaîne est construite suivant la règle A dans les deux cas suivants:

    • soit elle est égale à “a” ;
    • soit elle est de la forme “a”+chaine+“a”, où chaine est une chaîne de caractères construite suivant la règle A.

    Règle B : une chaîne est construite suivant la règle B dans les deux cas suivants :

    • soit elle est de la forme “b”+chaine+“b”, où chaine est une chaîne de caractères construite suivant la règle A ;
    • soit elle est de la forme “b”+chaine+“b”, où chaine est une chaîne de caractères construite suivant la règle B.

    On a reproduit ci-dessous l’aide de la fonction choice du module random.

    >>>from random import choice
    >>>help(choice)
    Help on method choice in module random:
    choice(seq) method of random.Random instance
     Choose a random element from a non-empty sequence.

    La fonction A() ci-dessous renvoie une chaîne de caractères construite suivant la règle A, en choisissant aléatoirement entre les deux cas de figure de cette règle.

    def A():
      if choice([True, False]):
        return "a"
      else:
        return "a" + A() + "a"

    Question 1

    A. Cette fonction est-elle récursive ? Justifier.

    B. La fonction choice([True, False]) peut renvoyer False un très grand nombre de fois consécutives. Expliquer pourquoi ce cas de figure amènerait à une erreur d’exécution. Dans la suite, on considère une deuxième version de la fonction A. À présent, la fonction prend en paramètre un entier n tel que, si la valeur de n est négative ou nulle, la fonction renvoie "a". Si la valeur de n est strictement positive, elle renvoie une chaîne de caractères construite suivant la règle A avec un n décrémenté de 1, en choisissant aléatoirement entre les deux cas de figure de cette règle.

    def A(n):
      if ... or choice([True, False]) :
        return "a"
      else:
        return "a" + ... + "a"

    Question 2

    A. Recopier sur la copie et compléter aux emplacements des points de suspension ... le code de cette nouvelle fonction A.

    B. Justifier le fait qu’un appel de la forme A(n) avec n un nombre entier positif inférieur à 50, termine toujours.

    On donne ci-après le code de la fonction récursive B qui prend en paramètre un entier n et qui renvoie une chaîne de caractères construite suivant la règle B.

    def B(n):
      if n <= 0 or choice([True, False]):
        return "b" + A(n-1) + "b"
      else:
        return "b" + B(n-1) + "b"

    On admet que :

    • les appels A(-1) et A(0) renvoient la chaîne "a";
    • l’appel A(1) renvoie la chaîne "a" ou la chaîne "aaa";
    • l’appel A(2) renvoie la chaîne "a", la chaîne "aaa" ou la chaîne "aaaaa".

    Question 3

    Donner toutes les chaînes possibles renvoyées par les appels B(0), B(1) et B(2).

    On suppose maintenant qu’on dispose d’une fonction raccourcir qui prend comme paramètre une chaîne de caractères de longueur supérieure ou égale à 2, et renvoie la chaîne de caractères obtenue à partir de la chaîne initiale en lui ôtant le premier et le dernier caractère.

    Par exemple :

    >>> raccourcir("abricot")
    "brico"
    >>> raccourcir("ab")
    ""

    Question 4

    A. Recopier sur la copie et compléter les points de suspension ... du code de la fonction regleA ci-dessous pour qu’elle renvoie True si la chaîne passée en paramètre est construite suivant la règle A, et False sinon.

    def regleA(chaine):
      n = len(chaine)
      if n >= 2:
        return chaine[0] == "a" and chaine[n-1] == "a" and
              regleA(...)
      else:
        return chaine == ...

    B. Écrire le code d’une fonction regleB, prenant en paramètre une chaîne de caractères et renvoyant True si la chaîne est construite suivant la règle B, et False sinon.

    Exercice 2 24-NSIJ2ME1

    Cet exercice porte sur la programmation orientée objets, les tris, les algorithmes gloutons, la récursivité et les assertions.

    récursivité POO glouton prog dynamique

    Cet exercice est composé de trois parties dont les deux dernières sont indépendantes entre elles. Dans cet exercice, l’entête des fonctions est décrit avec le type des objets en paramètre et le type de l’objet renvoyé. Ainsi la fonction puissance qui prend un paramètre flottant x et un entier n puis qui renvoie le flottant x**n a pour entête puissance(x: float, n: int) -> float

    Une entreprise transporte des marchandises. Elle souhaite maximiser son profit en optimisant le remplissage de ses moyens de transport. On considère qu’un moyen de transport est limité par son volume (exprimé en litres). Chaque marchandise est caractérisée par son prix (en euros) et son volume indivisible (en litres).

    Supposons qu’on ait trois marchandises caractérisées par les couples (prix, volume) suivants : 𝑚𝑚1 =(100,10), 𝑚𝑚2 =(100,10) et 𝑚𝑚3 =(250,20). Si le moyen de transport peut encore charger 25 litres, il vaut mieux charger la marchandise numéro 3 qui rapporte 250 € à l’entreprise plutôt que charger les marchandises numéros 2 et 3 qui rapportent 200 € au total pour le même espace utilisé.

    Partie A – Quelques outils

    Nous souhaitons définir une classe Marchandise dont chaque instance définit une marchandise possédant deux attributs entiers prix et volume.

    1. Compléter le constructeur qui renvoie un objet Marchandise. Utiliser le mot-clé assert afin qu’une exception soit levée si le paramètre v n’est pas strictement positif. On rappelle que si condition est une expression Python booléenne s’évaluant à True ou False, l’instruction assert condition déclenche une exception quand la condition s’évalue à False.
    class Marchandise:
      def __init__(self, p: int, v: int) -> 'Marchandise':
        ...
    1. Donner une instruction qui permet de créer une variable m1 représentant une marchandise d’un volume de 7 litres coûtant 20 €.

    2. Proposer une méthode ratio(self) -> float qui renvoie le ratio prix/volume d’une marchandise.

    3. Proposer une fonction prixListe(tab: list) -> int qui renvoie le prix cumulé de l’ensemble des marchandises formant le tableau tab.

    Partie B – Première approche de rangement

    Le transporteur souhaite maximiser son profit. On considère que nous avons les quatre marchandises définies par les couples (prix, volume) suivants : 𝑚𝑚1 =(40,20), 𝑚𝑚2 =(210,70), 𝑚𝑚3 =(160,40) et 𝑚𝑚4 =(50,50).

    1. Préciser toutes les combinaisons de marchandises possibles si on ne dépasse pas un volume de 100 litres et le prix associé. En déduire la combinaison de marchandises qui maximise le prix.

    Une première méthode appelée ChargementGlouton consiste à trier les marchandises dans l’ordre décroissant de leur prix volumique (ratio prix/volume), puis transporter en priorité les marchandises avec le plus grand prix volumique. Si une marchandise est trop volumineuse pour être transportée, on essaie avec la marchandise ayant le prix volumique juste inférieur, ce jusqu’à ce qu’aucune marchandise ne puisse rentrer. Ainsi, en notant v_restant le volume disponible et m_i la $(𝑖 +1)^e$ marchandise une fois les marchandises triées, l’algorithme peut s’écrire:

    ChargementGlouton
    n = nombre de marchandises
    POUR i ALLANT de 0 à n-1 FAIRE
    | SI volume de m_i <= v_restant ALORS
    | | charger m_i
    | | v_restant = v_restant - volume de m_i
    TRANSPORTER le chargement prévu

    Le tri dans l’ordre décroissant des prix volumiques donne 𝑚𝑚3 , 𝑚𝑚2, 𝑚𝑚1, 𝑚𝑚4. Si le moyen de transport accepte 100 litres de chargement, l’algorithme charge 𝑚𝑚3 et 𝑚𝑚1 pour un prix de 200 € (à comparer avec la combinaison trouvée précédemment pour maximiser le prix).

    Par la suite, on rappelle que dans l’implémentation Python, les marchandises sont définies par des instances de la classe Marchandise.

    On donne quelques qualificatifs : dichotomique, glouton, graphique, insertion, maximum, récursif, tri.

    1. Indiquer, sans justification, le qualificatif qui s’applique le mieux à l’algorithme précédent.

    2. Recopier et compléter la fonction tri(tab: list) -> None ci-dessous afin qu’elle trie en place un tableau contenant des objets de type Marchandise selon l’ordre décroissant des ratios. Ainsi, tab[0] doit contenir la marchandise avec le plus haut ratio prix/volume après l’appel tri(tab).

    def tri(tab: list) -> None:
      n = len(tab)
      for i in range(1, n):
        marchandise = tab[i]
        j = i-1
        while ... and ... > ... :
          tab[j+1] = ...
          j = ...
        tab[j+1] = marchandise
    1. Sans justifier, préciser le nom de ce tri, ainsi que son coût temporel dans le pire des cas (constant, logarithmique, linéaire, quasi-linéaire (𝑛𝑛 log2 𝑛𝑛), quadratique, cubique ou exponentiel).
    2. Recopier et compléter la fonction charge suivante qui applique l’algorithme ChargementGlouton décrit plus haut.
    def charge(tab: list, volume: int) -> list:
      tri(tab)
      chargement = []
      n = len(tab)
      for ...
        if ...
          ...
          ...
      return ...

    Partie C – Rangement optimisé par récursivité

    L’algorithme précédent ne renvoie pas toujours une solution optimale. On peut donc suivre un algorithme récursif. On note n le nombre de marchandises et on souhaite implémenter la fonction récursive chargeOptimale d’entête :

    chargeOptimale(tab: list, v_restant: int, i: int) -> list

    Un appel à cette fonction doit permettre de calculer la charge optimale pour un transport de volume v_restant utilisant les marchandises à partir de l’indice i :

    • si i >= n, toutes les marchandises ont été essayées et il n’en reste plus d’autres disponibles. L’appel récursif renvoie la liste vide ;
    • si i < n et la marchandise d’indice i est de volume strictement supérieur au volume restant, l’appel récursif renvoie le résultat de l’appel effectué avec le même volume restant mais avec la marchandise suivante, c’est-à-dire chargeOptimale(tab, v_restant, i+1) ;
    • si i < n et la marchandise d’indice i est de volume inférieur ou égal au volume restant, il existe deux options possibles : – Option 1 soit on utilise la marchandise i, auquel cas le chargement contiendra cette marchandise et celles du résultat de l’appel récursif à partir de la prochaine marchandise et d’un volume restant strictement inférieur, – Option 2 soit on n’utilise pas la marchandise i, auquel cas le chargement sera le résultat de l’appel récursif avec le même volume restant mais à partir de la marchandise suivante.

    On garde l’option de chargement qui maximise le prix transporté.

    1. Compléter le code de la fonction chargeOptimale dont le principe a été décrit ci-avant.
    def chargeOptimale(tab: list, v_restant: int, i: int) -> list:
      if i>=...:
        return ...
      else:
        if tab[i].volume > v_restant:
          return chargeOptimale(tab, v_restant, i+1)
        else:
          option1 = chargeOptimale(tab, ..., ...)
          option2 = [tab[i]] + chargeOptimale(tab, ..., ...)
          if prixListe(option1) > prixListe(option2):
            return ...
          else:
            return ...

    algo et recursivite

    Sujet Métropole Sept 1 : 2021 - Exercice 2

    Principaux thèmes abordés : algorithmique (recherche dichotomique) et langages et programmation (récursivité)

    dichotomie récursivité complexité

    On veillera à mettre sur la copie toutes les réponses.

    Partie A : La recherche dichotomique

    1. La recherche d’un élément dans un tableau avec une méthode dichotomique ne peut se faire que si le tableau est trié.

    a. Vrai

    b. Faux

    2. Le coût d’un algorithme de recherche dichotomique est :

    a. Constant : Complexité O(1)

    b. Linéaire : Complexité O(n)

    c. Logarithmique : Complexité O(log(n))

    3. Justifier pourquoi l’entier fin–deb est un variant de boucle qui montre la terminaison du programme de recherche dichotomique de l’annexe 1 de l’exercice 2.

    Partie B : La recherche dichotomique itérative

    Le programme de recherche dichotomique de l’annexe 1 de l’exercice 2 est utilisé pour effectuer des recherches dans une liste.

    Dans l’ensemble de cette partie, on considère la liste :

    Lnoms = ["alice", "bob","etienne", "hector", "lea", "nathan", "paul"].

    1. Expliquer pourquoi en ligne 2, on a «fin = len(liste)-1» plutôt que «fin = 6».

    2. En Python, l’opérateur // donne le quotient de la division euclidienne de deux nombres entiers. Proposer un algorithme pour obtenir ce quotient.

    3. Donner la trace complète de l’exécution rechercheDicho("lea", Lnoms) en complétant le tableau ci-dessous sur votre copie :

    Debut Fin M condition deb <= fin valeur renvoyée

    4. Sur votre copie, modifier le code du corps de la fonction rechercheDicho() pour qu’elle renvoie aussi la position (indice) de l’élément cherché ou -1 si l’élément n’est pas trouvé.

    On pourra indiquer sur la copie le numéro des lignes modifiées, à supprimer ou à insérer s’il y a lieu.

    Partie C : La recherche dichotomique récursive

    1. Donner la définition d’une fonction récursive en programmation.

    2. Écrire en langage naturel ou en python, l’algorithme de recherche dichotomique d’un élément dans une liste, triée de façon croissante, en utilisant une méthode récursive. Il renverra True si l’objet a été trouvé, False sinon.

    ANNEXE 1

    On considère la fonction de recherche dichotomique suivante :

    def rechercheDicho (elem, liste):
      """
      Cette fonction indique si un élément se trouve dans un
      tableau.
      Elle utilise la méthode de recherche dichotomique.
      Elle prend en arguments :
      - elem : élément à rechercher de type string
      - liste : liste d'éléments de type string triée
      par ordre croissant
      Elle renvoie un booléen correspondant à la présence ou
      non de l'élément
      """
      deb = 0
      fin = len(liste)-1
      m = (deb+fin)//2
      while deb <= fin :
        if liste[m] == elem :
          return True
        elif liste[m] > elem :
          fin = m-1
        else :
          deb = m+1
        m = (deb+fin)//2
      return False 

    Sujet Métropole Sept 2 2021 Exercice 4

    Cet exercice porte sur la programmation en général et la récursivité en particulier. tableau permutation récursivité

    On s’intéresse dans cet exercice à un algorithme de mélange des éléments d’une liste.

    1. Pour la suite, il sera utile de disposer d’une fonction echange qui permet d’échanger dans une liste lst les éléments d’indice i1 et i2. Expliquer pourquoi le code Python ci-dessous ne réalise pas cet échange et en proposer une modification.
    def echange(lst, i1, i2):
     lst[i2] = lst[i1]
     lst[i1] = lst[i2]
    1. La documentation du module random de Python fournit les informations ci-dessous concernant la fonction randint(a,b) :
    Renvoie un entier aléatoire N tel que a <= N <= b. 

    Parmi les valeurs ci-dessous, quelles sont celles qui peuvent être renvoyées par l’appel randint(0, 10) ?

    0   1   3.5   9   10  11
    1. Le mélange de Fischer Yates est un algorithme permettant de permuter aléatoirement les éléments d’une liste. On donne ci-dessous une mise en œuvre récursive de cet algorithme en Python.
    from random import randint
    
    def melange(lst, ind):
      print(lst)
      if ind > 0:
        j = randint(0, ind)
        echange(lst, ind, j)
        melange(lst, ind-1) 

    a. Expliquer pourquoi la fonction melange se termine toujours.

    b. Lors de l’appel de la fonction melange, la valeur du paramètre ind doit être égale au plus grand indice possible de la liste lst.

    Pour une liste de longueur n, quel est le nombre d’appels récursifs de la fonction melange effectués, sans compter l’appel initial ?

    c. On considère le script ci-dessous :

    lst = [v for v in range(5)]
    melange(lst, 4)

    On suppose que les valeurs successivement renvoyées par la fonction randint sont 2, 1, 2 et 0.

    Les deux premiers affichages produits par l’instruction print(lst) de la fonction melange sont :

    [0, 1, 2, 3, 4]
    [0, 1, 4, 3, 2]

    Donner les affichages suivants produits par la fonction melange.

    d. Proposer une version itérative du mélange de Fischer Yates.

    architecture

    Bac 2022 Polynesie: Exercice 2

    Cet exercice traite du thème « architecture matérielle », et principalement d’ordonnancement et d’expressions booléennes.

    ordonnancement logique

    Un système est composé de 4 périphériques, numérotés de 0 à 3, et d’une mémoire, reliés entre eux par un bus auquel est également connecté un dispositif ordonnanceur. À l’aide d’un signal spécifique envoyé sur le bus, l’ordonnanceur sollicite à tour de rôle les périphériques pour qu’ils indiquent le type d’opération (lecture ou écriture) qu’ils souhaitent effectuer, et l’adresse mémoire concernée.

    Un tour a lieu quand les 4 périphériques ont été sollicités. Au début d’un nouveau tour, on considère que toutes les adresses sont disponibles en lecture et écriture.

    Si un périphérique demande l’écriture à une adresse mémoire à laquelle on n’a pas encore accédé pendant le tour, l’ordonnanceur répond “OK” et l’écriture a lieu. Si on a déjà demandé la lecture ou l’écriture à cette adresse, l’ordonnanceur répond “ATT” et l’opération n’a pas lieu.

    Si un périphérique demande la lecture à une adresse à laquelle on n’a pas encore accédé en écriture pendant le tour, l’ordonnanceur répond “OK” et la lecture a lieu. Plusieurs lectures peuvent avoir donc lieu pendant le même tour à la même adresse.

    Si un périphérique demande la lecture à une adresse à laquelle on a déjà accédé en écriture, l’ordonnanceur répond “ATT” et la lecture n’a pas lieu.

    Ainsi, pendant un tour, une adresse peut être utilisée soit une seule fois en écriture, soit autant de fois qu’on veut en lecture, soit pas utilisée.

    Si un périphérique ne peut pas effectuer une opération à une adresse, il demande la même opération à la même adresse au tour suivant.

    Question 1

    Le tableau donné en annexe 1 indique, sur chaque ligne, le périphérique sélectionné, l’adresse à laquelle il souhaite accéder et l’opération à effectuer sur cette adresse. Compléter dans la dernière colonne de cette annexe, à rendre avec la copie, la réponse donnée par l’ordonnanceur pour chaque opération.

    On suppose dans toute la suite que :

    • le périphérique 0 écrit systématiquement à l’adresse 10 ;
    • le périphérique 1 lit systématiquement à l’adresse 10 ;
    • le périphérique 2 écrit alternativement aux adresses 11 et 12 ;
    • le périphérique 3 lit alternativement aux adresses 11 et 12 ;

    Pour les périphériques 2 et 3, le changement d’adresse n’est effectif que lorsque l’opération et réalisée.

    Question 2

    On suppose que les périphériques sont sélectionnés à chaque tour dans l’ordre 0 ; 1 ; 2 ; 3. Expliquer ce qu’il se passe pour le périphérique 1.

    Les périphériques sont sollicités de la manière suivante lors de quatre tours successifs :

    • au premier tour, ils sont sollicités dans l’ordre 0 ; 1 ; 2 ; 3 ;
    • au deuxième tour, dans l’ordre 1 ; 2 ; 3 ; 0 ;
    • au troisième tour, 2 ; 3 ; 0 ; 1 ;
    • puis 3 ; 0 ; 1 ; 2 au dernier tour.
    • Et on recommence…

    Question 3

    A. Préciser pour chacun de ces tours si le périphérique 0 peut écrire et si le périphérique 1 peut lire.

    B. En déduire la proportion des valeurs écrites par le périphérique 0 qui sont effectivement lues par le périphérique 1.

    On change la méthode d’ordonnancement : on détermine l’ordre des périphériques au cours d’un tour à l’aide de deux listes d’attente ATTL_L et ATT_E établies au tour précédent.

    Au cours d’un tour, on place dans la liste ATT_L toutes les opérations de lecture mises en attente, et dans la liste d’attente ATT_E toutes les opérations d’écriture mises en attente.

    Au début du tour suivant, on établit l’ordre d’interrogation des périphériques en procédant ainsi :

    • on interroge ceux présents dans la liste ATT_L, par ordre croissant d’adresse,
    • on interroge ensuite ceux présents dans la liste ATT_E, par ordre croissant d’adresse,
    • puis on interroge les périphériques restants, par ordre croissant d’adresse.

    Question 4

    Compléter et rendre avec la copie le tableau fourni en annexe 2, en utilisant l’ordonnancement décrit ci-dessus, sur 3 tours.

    Les colonnes e0 et e1 du tableau suivant recensent les deux chiffres de l’écriture binaire de l’entier n de la première colonne.

    nombre n écriture binaire de n sur deux bits e1 e0
    0 00 0 0
    1 01 0 1
    2 10 1 0
    3 11 1 1

    L’ordonnanceur attribue à deux signaux sur le bus de données les valeurs de e0 et e1 associées au numéro du circuit qu’il veut sélectionner. On souhaite construire à l’aide des portes ET, OU et NON un circuit pour chaque périphérique.

    Chacun des quatre circuits à construire prend en entrée deux signaux e0 et e1, le signal de sortie s valant 1 uniquement lorsque les niveaux de e0 et e1 correspondent aux bits de l’écriture en binaire du numéro du périphérique correspondant.

    Par exemple, le circuit ci-dessous réalise la sélection du périphérique 3. En effet, le signal s vaut 1 si et seulement si e0 et e1 valent tous les deux 1.

    470 × 138

    470 × 138

    Question 5

    A. Recopier sur la copie et indiquer dans le circuit ci-dessous les entrées e0 et e1 de façon à ce que ce circuit sélectionne le périphérique 1.

    566 × 170

    566 × 170

    B. Dessiner un circuit constitué d’une porte ET et d’une porte NON, qui sélectionne le périphérique 2. c. Dessiner un circuit permettant de sélectionner le périphérique 0.

    1252 × 590

    1252 × 590

    1252 × 788

    1252 × 788

    bac 2021 candidat libre exercice 3

    cmd unix

    La commande UNIX ps présente un cliché instantané des processus en cours d’exécution.

    Avec l’option −eo pid,ppid,stat,command, cette commande affiche dans l’ordre l’identifiant du processus PID (process identifier), le PPID (parent process identifier), l’état STAT et le nom de la commande à l’origine du processus.

    Les valeurs du champ STAT indique l’état des processus :

    R : processus en cours d’exécution

    S : processus endormi

    Sur un ordinateur, on exécute la commande ps −eo pid,ppid,stat,command et on obtient un affichage dont on donne ci-dessous un extrait:

    À l’aide de cet affichage, répondre aux questions ci-dessous.

    1. Quel est le nom de la première commande exécutée par le système d’exploitation lors du démarrage?
    2. Quels sont les identifiants des processus actifs sur cet ordinateur au moment de l’appel de la commande ps? Justifier la réponse.
    3. Depuis quelle application a-t-on exécuté la commande ps? Donner les autres commandes qui ont été exécutées à partir de cette application.
    4. Expliquer l’ordre dans lequel les deux commandes python programme1.py et python programme2.py ont été exécutées.
    5. Peut-on prédire que l’une des deux commandes python programme1.py et python programme2.py finira avant l’autre?

    bac 2021 candidat libre exercice 2 sujet 2

    ordonnancement

    Les états possibles d’un processus sont : prêt, élu, terminé et bloqué.

    1. Expliquer à quoi correspond l’état élu.

    2. Proposer un schéma illustrant les passages entre les différents états.

    On suppose que quatre processus C₁, C₂, C₃ et C₄ sont créés sur un ordinateur, et qu’aucun autre processus n’est lancé sur celui-ci, ni préalablement ni pendant l’exécution des quatre processus.

    L’ordonnanceur, pour exécuter les différents processus prêts, les place dans une structure de données de type file. Un processus prêt est enfilé et un processus élu est défilé.

    Parmi les propositions suivantes, recopier celle qui décrit le fonctionnement des entrées/sorties dans une file :

    • Premier entré, dernier sorti
    • Premier entré, premier sorti
    • Dernier entré, premier sorti

    On suppose que les quatre processus arrivent dans la file et y sont placés dans l’ordre C₁, C₂, C₃ et C₄.

    Les temps d’exécution totaux de C₁, C₂, C₃ et C₄ sont respectivement 100 ms, 150 ms, 80 ms et 60 ms.

    Après 40 ms d’exécution, le processus C₁ demande une opération d’écriture disque, opération qui dure 200 ms. Pendant cette opération d’écriture, le processus C₁ passe à l’état bloqué.

    Après 20 ms d’exécution, le processus C₃ demande une opération d’écriture disque, opération qui dure 10 ms. Pendant cette opération d’écriture, le processus C₃ passe à l’état bloqué.

    Sur la frise chronologique donnée en annexe (à rendre avec la copie), les états du processus C₂ sont donnés.

    Compléter la frise avec les états des processus C₁, C₃ et C₄.

    Annexe de l’exercice 2

    Annexe de l’exercice 2

    On trouvera ci-dessous deux programmes rédigés en pseudo-code.

    Verrouiller un fichier signifie que le programme demande un accès exclusif au fichier et l’obtient si le fichier est disponible.

    Programme 1 Programme 2
    Verrouiller fichier_1 Verrouiller fichier_2
    Calculs sur fichier_1 Verrouiller fichier_1
    Verrouiller fichier_2 Calculs sur fichier_1
    Calculs sur fichier_1 Calculs sur fichier_2
    Calculs sur fichier_2 Déverrouiller fichier_1
    Calculs sur fichier_1 Déverrouiller fichier_2
    Déverrouiller fichier_2
    Déverrouiller fichier_1
    1. En supposant que les processus correspondant à ces programmes s’exécutent simultanément (exécution concurrente), expliquer le problème qui peut être rencontré.

    2. Proposer une modification du programme 2 permettant d’éviter ce problème.

    BDD SQL

    Bac 2024 Amerique du Nord: Exercice 3

    Cet exercice porte sur le langage SQL et les bases de données.

    sql

    Un pharmacien nouvellement installé décide de créer son propre système de gestion des médicaments qu’il délivre à ses clients. Pour sa base de données relationnelle, il a déjà élaboré la première relation à l’aide des données indiquées sur les cartes vitales de ses deux premiers clients :

    client (id_client : INT,
    nom_client : VARCHAR(30),
    prenom_client : VARCHAR(30), 
    num_secu_sociale : VARCHAR(15))
    1. Écrire le résultat de l’exécution de la requête SQL suivante :
    SELECT nom_client, prenom_client
    FROM client
    ORDER BY nom_client;

    Pour écrire la relation medicament, il doit utiliser les informations fournies par la notice des médicaments. En voici une ci-dessous :

    Informations extraites de la notice du médicament Paracétamol 1 gramme CP.

    Informations extraites de la notice du médicament Paracétamol 1 gramme CP.

    La relation medicament suivante a été obtenue à l’aide de ces notices :

    medicament (id_medic : INT,
      nom_medic : VARCHAR(30),
      categorie : VARCHAR(20),
      conditionnement : INT,
      quantite : INT, prix : FLOAT)

    La table des médicaments de son officine est présentée ci-dessous.

    1. Écrire une requête SQL permettant d’afficher les noms de tous les médicaments dont le prix est strictement inférieur à 3 euros. Madame Martin présente au pharmacien une nouvelle ordonnance :
    Ordonnance de Madame Sophie Martin.

    Ordonnance de Madame Sophie Martin.

    Il saisit les informations de cette ordonnance dans la relation ordonnance, chaque médicament prescrit correspondant à un enregistrement dans la table ci-dessous.

    1. Ecrire une requête SQL permettant d’ajouter les informations de la carte vitale de sa troisième cliente présentée ci-dessous :
    Image de la carte vitale extraite de la page wikipédia

    Image de la carte vitale extraite de la page wikipédia

    1. Donner les attributs qui doivent être déclarés comme clés étrangères de la relation ordonnance et en préciser l’utilité.
    2. Indiquer, pour les lignes 7 et 8 de la table ordonnance, le nombre de boites prescrites.
    3. Écrire la requête SQL mettant à jour la quantité du médicament Acide ascorbique en stock dans l’officine du pharmacien suite au passage de Madame Martin.
    4. Calculer le coût total des médicaments fournis à Madame Martin (on ne demande pas d’écrire une requête ici, mais de calculer le coût total en justifiant le calcul).
    5. Écrire la requête SQL permettant d’afficher le nom du médicament pour l’ordonnance ayant l’id_ordo numéro 6.

    Bac 2022 Polynesie: Exercice 3

    Cet exercice traite du thème « base de données », et principalement du modèle relationnel et du langage SQL.

    sql

    L’énoncé de cet exercice peut utiliser les mots du langage SQL suivants :

    CREATE TABLE, SELECT, FROM, WHERE, JOIN ON, INSERT INTO, VALUES, UPDATE, SET, DELETE, COUNT, DISTINCT, AND, OR, AS, ORDER BY, ASC, DESC

    Un site web recueille des données de navigation dans une base de données afin d’étudier les profils de ses visiteurs.

    Chaque requête d’interrogation d’une page de ce site est enregistrée dans une première table dénommée Visites sous la forme d’un 5-uplet : (identifiant, adresse IP, date et heure de visite, nom de la page, navigateur).

    Le chargement de la page index.html par 192.168.1.91 le 12 juillet 1998 à 22h48 aura par exemple été enregistré de la façon suivante :

    (1534, "192.168.1.91", "1998-07-12 22:48:00", "index.html", "Internet explorer 4.1").

    La commande SQL ayant permis de créer cette table est la suivante:

    CREATE TABLE Visites (
      identifiant INTEGER NOT NULL UNIQUE,
      ip VARCHAR(15),
      dateheure DATETIME,
      nompage TEXT,
      navigateur TEXT
    );

    Question 1

    A. Donner une commande d’interrogation en langage SQL permettant d’obtenir l’ensemble des 2-uplets (adresse IP, nom de la page) de cette table.

    B. Donner une commande en langage SQL permettant d’obtenir l’ensemble des adresses IP ayant interrogé le site, sans doublon.

    C. Donner une commande en langage SQL permettant d’obtenir la liste des noms des pages visitées par l’adresse IP 192.168.1.91

    Ce site web met en place, sur chacune de ses pages, un programme en javascript qui envoie au serveur, à intervalle régulier de 15 secondes, le temps en secondes de présence sur la page. Ces envois contiennent tous la valeur de identifiant correspondant au chargement initial de la page.

    Par exemple, si le visiteur du 12 juillet 1998 est resté 65 secondes sur la page, celle-ci a envoyé au serveur les 4 doublets (1534, 15), (1534, 30), (1534, 45) et (1534, 60).

    Ces données sont enregistrées dans une table nommée Pings créée avec la commande ci-dessous :

    CREATE TABLE Pings (
      identifiant INTEGER,
      duree INTEGER
    );

    En plus de l’inscription d’une ligne dans la table Visites, chaque chargement d’une nouvelle page provoque l’insertion d’une ligne dans la table Pings comprenant l’identifiant de ce chargement et une durée de 0.

    Les attributs identifiant des tables Visites et Pings partagent les mêmes valeurs.

    Question 2

    A. De quelle table l’attribut identifiant est-il la clé primaire ?

    B. De quelle table l’attribut identifiant est-il une clé étrangère ?

    C. Par conséquent, quelles vérifications sont automatiquement effectuées par le système de gestion de base de données ?

    Question 3

    Le serveur reçoit le doublet (identifiant, duree) suivant : (1534, 105). Écrire la commande SQL d’insertion qui permet d’ajouter cet enregistrement à la table Pings. On envisage ensuite d’optimiser la table en se contentant d’une seule ligne par identifiant dans la table Pings : les valeurs de l’attribut duree devraient alors être mises à jour à chaque réception d’un nouveau doublet (identifiant, duree).

    Question 4

    A. Écrire la requête de mise à jour permettant de fixer à 120 la valeur de l’attribut duree associée à l’identifiant 1534 dans la table Pings.

    B. Expliquer pourquoi on ne peut pas être certain que les données envoyées par une page web, depuis le navigateur d’un client, via plusieurs requêtes formulées en javascript, arrivent au serveur dans l’ordre dans lequel elles ont été émises.

    C. En déduire qu’il est préférable d’utiliser une requête d’insertion plutôt qu’une requête de mise à jour pour ajouter des données à la table Pings.

    Question 5

    Écrire une requête SQL utilisant le mot-clef JOIN et une clause WHERE, permettant de trouver les noms de toutes les pages qui ont été consultées plus d’une minute par au moins un utilisateur.

    Bac 2022 metropole1: Exercice 2

    Cet exercice porte sur les bases de données.

    sql

    On pourra utiliser les mots clés SQL suivants : SELECT, FROM, WHERE, JOIN, ON, INSERT, INTO, VALUES, UPDATE, SET, AND.

    Nous allons étudier une base de données traitant du cinéma dont voici le schéma relationnel qui comporte 3 relations :

    • la relation individu (id_ind, `nom, prenom, naissance)
    • la relation realisation (id_rea, titre, annee, type)
    • la relation emploi (id_emp, description, #id_ind, #id_rea)

    Les clés primaires sont en gras et les clés étrangères sont précédées d’un #.

    Ainsi emploi.id_ind est une clé étrangère faisant référence à individu.id_ind.

    Voici un extrait des tables individu et realisation :

    1310 × 330

    1310 × 330

    Question 1

    On s’intéresse ici à la récupération de données dans une relation.

    a A. Écrire ce que renvoie la requête ci-dessous :

    SELECT nom, prenom, naissance
    FROM individu
    WHERE nom = 'Crog';

    B. Fournir une requête SQL permettant de récupérer le titre et la clé primaire de chaque film dont la date de sortie est strictement supérieure à 2020.

    Question 2

    Cette question traite de la modification de relations.

    A. Dire s’il faut utiliser la requête 1 ou la requête 2 proposées ci-dessous pour modifier la date de naissance de Daniel Crog. Justifier votre réponse en expliquant pourquoi la requête refusée ne pourra pas fonctionner.

    Requête 1:

    UPDATE individu
    SET naissance = '02-03-1968'
    WHERE id_ind = 688 AND nom = 'Crog' AND prenom = 'Daniel';

    Requête 2:

    INSERT INTO individu
    VALUES (688, 'Crog', 'Daniel', '02-03-1968'); 

    B. Expliquer si la relation individu peut accepter (ou pas) deux individus portant le même nom, le même prénom et la même date de naissance.

    Question 3

    Cette question porte sur la notion de clés étrangères.

    A. Recopier sur votre copie les demandes ci-dessous, dans leur intégralité, et les compléter correctement pour qu’elles ajoutent dans la relation emploi les rôles de Daniel Crog en tant que James Bond dans le film nommé ‘Casino Impérial’ puis dans le film ‘Ciel tombant’.

    INSERT INTO emploi
    VALUES (5400, 'Acteur(James Bond)', ... );
    INSERT INTO emploi
    VALUES (5401, 'Acteur(James Bond)', ... );

    B. On désire rajouter un nouvel emploi de Daniel Crog en tant que James Bond dans le film ‘Docteur Yes’.

    Expliquer si l’on doit d’abord créer l’enregistrement du film dans la relation realisation ou si l’on doit d’abord créer le rôle dans la relation emploi.

    Question 4

    Cette question traite des jointures.

    A. Recopier sur votre copie la requête SQL ci-dessous, dans son intégralité, et la compléter de façon à ce qu’elle renvoie le nom de l’acteur, le titre du film et l’année de sortie du film, à partir de tous les enregistrements de la relation emploi pour lesquels la description de l’emploi est 'Acteur(James Bond)'.

    SELECT ...
    FROM emploi
    JOIN individu ON ...
    JOIN realisation ON ...
    WHERE emploi.description = 'Acteur(James Bond)';

    B. Fournir une requête SQL permettant de trouver toutes les descriptions des emplois de Denis Johnson (Denis est son prénom et Johnson est son nom). On veillera à n’afficher que la description des emplois et non les films associés à ces emplois.

    Exercice 2 25-NSIJ2ME1:

    Cet exercice porte sur les bases de données relationnelles, le langage SQL et la programmation.

    sql python tableaux sqlite

    Partie A

    sql

    Une ludothèque municipale a décidé de moderniser sa gestion en créant une base de données informatique. Cette base de données permettra de suivre les jeux disponibles, les emprunts effectués par les adhérents, ainsi que les avis laissés sur les différents jeux. Pour commencer, quatre tables principales ont été identifiées : jeu, adhérent, emprunt et avis. Ces tables et leurs relations vont permettre de stocker toutes les informations essentielles au bon fonctionnement de la ludothèque. On va considérer que la ludothèque n’a qu’un exemplaire de chaque jeu (deux jeux de la ludothèque ne peuvent donc pas avoir le même nom).

    La base de données de la ludothèque

    La base de données de la ludothèque

    Dans la figure ci-dessus, les clés primaires de chacune des tables sont soulignées et les clés étrangères sont précédées du symbole #.

    Dans cet exercice, on pourra utiliser les clauses du langage SQL pour :

    • construire des requêtes d’interrogation à l’aide de SELECT, FROM, WHERE (avec les opérateurs logiques AND, OR) et JOIN ... ON ;
    • construire des requêtes d’insertion et de mise à jour à l’aide de UPDATE, INSERT et DELETE;
    • affiner les recherches à l’aide de DISTINCT et ORDER BY;
    • réaliser des agrégations à l’aide de COUNT, SUM ou AVG.

    Par exemple, l’instruction SQL suivante donne le nombre de jeux présents dans la table jeu:

    SELECT COUNT(nomJeu) FROM jeu;

    1. Expliquer pourquoi on ne peut pas prendre l’attribut nom comme clé primaire pour la relation adherent.
    2. Décrire ce que donne la requête SQL suivante :
    SELECT nomJeu, editeur
    FROM jeu
    ORDER BY nomJeu;

    Lorsque qu’un jeu est emprunté et n’a pas encore été rendu, la valeur de l’attribut dateRendu de la table emprunt est à NULL.

    1. Écrire une requête permettant de connaitre le nom de tous les jeux qui sont en cours d’emprunt.
    2. Écrire une requête SQL pour afficher le nom et le prénom de tous les adhérents qui ont emprunté le jeu “Catan”.
    3. Claire VOYANT, adhérente de longue date à cette ludothèque, a emprunté le jeu “Catan” et l’a rendu le 3 juin 2025. Lors de l’emprunt, la valeur de id_emprunt était 1538. Écrire une requête SQL qui a permis de mettre à jour la base de données afin qu’elle prenne en compte que ce jeu a été rendu. Toutes les dates de la base de données sont écrites sous le format 'AAAA-MM-JJ'.
    4. Écrire une requête SQL qui permet de trouver le nom et la catégorie de tous les jeux de la ludothèque sortis à partir de 2010 et dont l’âge minimum est strictement inférieur à 10 ans.

    On modifie la table avis pour ajouter une note (entier 0-5) pour chaque jeu à l’aide de l’attribut note.

    1. Ecrire une requête sql qui calcule la moyenne des notes obtenues pour le jeu “Catan”.

    La ludothèque décide d’organiser des événements. Pour cela, elle ajoute une relation evenement à sa base de données. En outre, pour chaque événement, elle souhaite garder en mémoire une trace des adhérents qui y ont participé. À cette fin, elle complète sa base avec une relation participation.

    La base de données de la ludothèque actualisée

    La base de données de la ludothèque actualisée

    1. Proposer les clés étrangères de la table participation en précisant le nom des attributs auxquels elles font référence.
    2. Proposer une requête qui identifie les adherants qui ont participé à l’evenement de nom “concours_pokemon”.
    3. Ecrire la requête qui compte le nombre de participations par membre aux differents evenements (GROUP BY id_adherant), et retourne une liste ordonnée de manière décroissante de participations pour ces membres.

    Partie B

    python tableaux sqlite

    Le programme Python suivant permet de créer la liste de tous les jeux empruntés, sachant que, dans celle-ci, un jeu va apparaître autant de fois qu’il a été emprunté.

    import sqlite3
    
    # Connexion à la base de données
    connection = sqlite3.connect("ludotheque.db")
    # creation d'un curseur pour recuperer les donnees des requetes
    curseur = connection.cursor()
    
    # Exécution de la requête
    curseur.execute("SELECT nomJeu FROM emprunt")
    
    # Récupération des résultats
    jeux = curseur.fetchall()
    
    liste = []
    # Création de la liste des jeux empruntés
    for jeu in jeux:
      liste.append(jeu[0])
    
    # Fermeture de la connexion
    curseur.close()
    connection.close()
    1. Écrire un script Python permettant de créer le dictionnaire dict_emprunts qui, à chaque jeu emprunté, associe le nombre de fois où il a été emprunté.

    On veut créer un podium des jeux les plus souvent empruntés. Comme il peut y avoir des égalités à la première, deuxième ou troisième place, il peut y avoir plus de trois jeux sélectionnés sur le podium.

    Par exemple, si le dictionnaire des emprunts est :

    dict_emprunts = {
    "Terraforming Mars": 25,
    "Codenames": 22,
    "Agricola": 18,
    "Puerto Rico": 18,
    "Caylus": 18,
    "Dominion": 22,
    "Dixit": 12,
    }

    il y aura sur le podium les jeux “Agricola”, “Puerto Rico” et “Caylus” puis les jeux “Dominion” et “Codenames” et enfin le jeu “Terraforming Mars”.

    Pour modéliser ce podium en Python, on va utiliser une liste de trois listes. Pour l’exemple précédent, cette liste sera :

    [["Agricola", "Puerto Rico", "Caylus"], ["Dominion", "Codenames"], ["Terraforming Mars"]]

    1. Proposer un script Python permettant de générer ce podium.

    securite

    Bac 2021 Centres étrangers 2: Exercice 3

    Thèmes abordés : conversion décimal/binaire, table de vérité, codage des caractères

    binaire logique ascii xor chiffrement

    L’objectif de l’exercice est d’étudier une méthode de cryptage d’une chaîne de caractères à l’aide du codage ASCII et de la fonction logique XOR.

    1. Le nombre 65, donné ici en écriture décimale, s’écrit 01000001 en notation binaire. En détaillant la méthode utilisée, donner l’écriture binaire du nombre 89.

    2. La fonction logique OU EXCLUSIF, appelée XOR et représentée par le symbole $\bigoplus$, fournit une sortie égale à 1 si l’une ou l’autre des deux entrées vaut 1 mais pas les deux.

    On donne ci-contre la table de vérité de la fonction XOR:

    Si on applique cette fonction à un nombre codé en binaire, elle opère bit à bit.

    Poser et calculer l’opération : $11001110 \bigoplus 01101011$

    3. On donne, ci-dessous, un extrait de la table ASCII qui permet d’encoder les caractères de A à Z. On peut alors considérer l’opération XOR entre deux caractères en effectuant le XOR entre les codes ASCII des deux caractères. Par exemple : ‘F’ XOR ‘S’ sera le résultat de $01000110 \bigoplus 01010011$.

    On souhaite mettre au point une méthode de cryptage à l’aide de la fonction XOR.

    Pour cela, on dispose d’un message à crypter et d’une clé de cryptage de même longueur que ce message. Le message et la clé sont composés uniquement des caractères du tableau ci-dessus et on applique la fonction XOR caractère par caractère entre les lettres du message à crypter et les lettres de la clé de cryptage.

    Par exemple, voici le cryptage du mot ALPHA à l’aide de la clé YAKYA :

    Ecrire une fonction xor_crypt(message, cle) qui prend en paramètres deux chaînes de caractères et qui renvoie la liste des entiers correspondant au message crypté.

    Aide :

    • On pourra utiliser la fonction native du langage Python ord(c) qui prend en paramètre un caractère c et qui renvoie un nombre représentant le code ASCII du caractère c.
    • On considère également que l’on dispose d’une fonction écrite xor(n1,n2) qui prend en paramètre deux nombres n1 et n2 et qui renvoie le résultat de n1 ⊕ n2.

    4. On souhaite maintenant générer une clé de la taille du message à partir d’un mot quelconque. On considère que le mot choisi est plus court que le message, il faut donc le reproduire un certain nombre de fois pour créer une clé de la même longueur que le message.

    Par exemple, si le mot choisi est YAK pour crypter le message ALPHABET, la clé sera YAKYAKYA.)

    Créer une fonction generer_cle(mot,n) qui renvoie la clé de longueur n à partir de la chaîne de caractères mot.

    5. Recopier et compléter la table de vérité de $(𝑬𝟏 \bigoplus 𝑬𝟐) \bigoplus 𝑬𝟐$.

    A l’aide de ce résultat, proposer une démarche pour décrypter un message crypté.

    Exercice 3 25-NSIJ2ME1

    Cet exercice porte sur la programmation de base en Python, la sécurisation des communications et les réseaux.

    python bases logique chiffrement https

    Partie A - La méthode du masque jetable

    Dans cette partie, on s’intéresse à une méthode de chiffrement dite du masque jetable.

    Voici ce que l’on peut lire sur le site Wikipédia :

    Le chiffrement par la méthode du masque jetable consiste à combiner le message en clair avec une clé présentant les caractéristiques très particulières suivantes :

    • la clé doit être une suite de caractères au moins aussi longue que le message à chiffrer ;
    • les caractères composant la clé doivent être choisis de façon totalement aléatoire ;
    • chaque clé, ou « masque », ne doit être utilisée qu’une seule fois (d’où le nom de masque jetable). Illustrons cette méthode par un exemple : on souhaite chiffrer le message HELLO avec la clé aléatoire, ou « masque », WMCKL.

    Pour cela, on attribue un nombre à chaque lettre, par exemple le rang dans l’alphabet, de 0 à 25.

    Lettre A B C D E F G H I J … Y Z
    Rang 0 1 2 3 4 5 6 7 8 9 … 24 25

    Ensuite, on additionne la valeur du rang de chaque lettre du message avec la valeur du rang correspondante dans le masque.

    Enfin, si le résultat est supérieur à 25 on soustrait 26 (calcul dit « modulo 26 »). Ainsi, le chiffrement du message HELLO avec la clé WMCKL donne le message chiffré DQNVZ comme le montre l’illustration suivante.

    Exemple de chiffrement par la méthode du masque jetable - wikipedia

    Exemple de chiffrement par la méthode du masque jetable - wikipedia

    Dans cet exercice, on ne travaillera que sur des chaînes de caractères écrites en majuscules non accentuées (les 26 caractères allant de ‘A’ à ‘Z’).

    1. Chiffrer, par la méthode du masque jetable, le message LIBRE à l’aide de la clé EYQMT.

    En Python, on crée une fois pour toute la variable alphabet qui sera accessible et utilisable dans toutes les fonctions. Celle-ci contient la liste des 26 lettres de l’alphabet rangées dans l’ordre alphabétique :

    alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']

    1. Écrire une fonction Python indice qui prend pour paramètre une liste L et renvoie l’indice de element dans la liste L.

    On supposera que chaque élément de la liste L n’y apparaît qu’une seule fois et que element est bien présent dans la liste L.

    Par exemple, l’appel indice(alphabet, 'K') renvoie l’entier 10.

    1. Écrire une fonction Python lettres_vers_indices qui prend pour paramètre une chaîne de caractères et renvoie, dans l’ordre, la liste des indices de ces caractères dans l’alphabet. Par exemple, l’appel lettres_vers_indices('HELLO') renvoie la liste d’entiers [7, 4, 11, 11, 14].

    On dispose également d’une fonction indices_vers_lettres, qu’on ne demande pas d’écrire, permettant de convertir une liste d’entiers, compris entre 0 et 25, en une chaîne de caractères.

    Par exemple, l’appel indices_vers_lettres([3, 16, 13, 21, 25]) renvoie la chaîne de caractères ‘DQNVZ’.

    Ci-après, on donne une fonction Python chiffrement incomplète, qui, à partir d’un message msg et d’une clé cle entrés en paramètres, renvoie la chaîne de caractères représentant le message chiffré par la méthode du masque jetable.

    def chiffrement(msg, cle):
    	assert len(cle) >= len(msg), 'impossible'
    	indices_msg = lettres_vers_indices(msg)
    	indices_cle = lettres_vers_indices(cle)
    	n = len(msg)
    	indices_msg_chiffre = []
    	for k in range(n):
    		ind = ...
    	if ind >= 26:
    			ind = ...
    		indices_msg_chiffre.append(ind)
    	msg_chiffre = indices_vers_lettres(...)
    	return msg_chiffre
    1. Recopier et compléter les lignes 7 à 13 de la fonction chiffrement.
    2. Indiquer, en justifiant, ce que l’on observe lors de l’appel chiffrement('RESEAU', 'GFTZ').

    On s’intéresse maintenant au déchiffrement d’un message chiffré par la méthode du masque jetable.

    Par exemple, le déchiffrement du message DQNVZ avec la clé WMCKL donne le message HELLO.

    1. Déchiffrer le message GMEDH avec la clé FVEIT.
    2. Expliquer comment procéder pour déchiffrer un message lorsqu’on connaît la clé.

    On souhaite maintenant écrire, en Python, une fonction dechiffrement qui permet de déchiffrer un message chiffré par la méthode du masque jetable.

    Pour cela, on s’inspire de la fonction chiffrement dans laquelle les paramètres ainsi que les lignes 2 à 5 sont inchangées. On décide cependant de remplacer, ligne 6, le nom de la variable indices_msg_chiffre par le nom plus explicite indices_msg_dechiffre. 8. Adapter les lignes 6 à 13 de la fonction chiffrement pour obtenir la nouvelle fonction dechiffrement.

    Partie B - Sécurisation des communications

    1. Expliquer la différence entre un algorithme de chiffrement symétrique et un algorithme de chiffrement asymétrique.

    Alice souhaite envoyer un message à Bob par l’intermédiaire d’un réseau informatique en utilisant un algorithme de chiffrement asymétrique.

    Pour cela, Bob envoie à Alice sa clé publique. Alice chiffre ensuite le message à l’aide de la clé publique de Bob qu’elle vient de recevoir, puis elle envoie ce message chiffré à Bob.

    1. Indiquer comment Bob peut déchiffrer le message que lui envoie Alice.
    2. Expliquer comment une tierce personne pourrait se faire passer pour Alice sans que Bob ne s’en aperçoive.
    3. Expliquer brièvement le fonctionnement du protocole HTTPS.
    4. Expliquer pourquoi, pour sécuriser intégralement les communications sur Internet, on utilise le protocole HTTPS plutôt qu’un chiffrement asymétrique.

    reseaux

    Exercice 3 25-NSIJ2ME1

    binaire masque logique ping

    Partie C - Réseaux

    Bob et Marc travaillent pour une petite compagnie d’assurances.

    Leurs postes de travail font partie d’un même réseau local géré par l’administratrice système qui dispose du bloc d’adresses IPv4 192.168.110.0/24.

    La notation /24 situé à la suite de l’adresse 192.168.110.0 signifie que le masque de sous-réseau du réseau de cette entreprise est 255.255.255.0 :

    les trois premiers octets d’une adresse IP sur ce réseau permettent donc d’identifier la partie réseau de l’adresse, alors que le dernier octet permet d’identifier la partie hôte et est propre à chaque machine sur le réseau.

    Ce sous-réseau permet donc d’attribuer 256 adresses IPv4 différentes.

    L’administratrice choisit alors d’attribuer, en représentation décimale, l’identifiant 115 pour la partie hôte du poste de travail de Bob et l’identifiant 153 pour celui de Marc.

    Depuis son poste de travail, Marc souhaite tester la communication avec celui de Bob.

    Pour cela, il exécute la commande ping 192.168.100.115 et obtient l’affichage suivant :

    --- 192.168.100.115 ping statistics ---
    4 packets transmitted, 0 received, 100% packet loss, time
    3060ms
    1. Expliquer l’affichage obtenu et corriger l’erreur de Marc.

    Afin d’améliorer les performances et la sécurité du réseau de l’entreprise, l’administratrice système décide de séparer le réseau local en plusieurs sous-réseaux et de les relier entre eux par des routeurs. Pour cela, elle modifie le masque de sous-réseau qui devient 11111111.11111111.11111111.11100000, donné ici en représentation binaire.

    1. Donner la représentation décimale de ce masque de sous-réseau.

    Pour obtenir l’adresse IPv4 du sous-réseau auquel appartient une machine, il suffit d’appliquer l’opérateur binaire ET, bit à bit, entre le masque de sous-réseau et l’adresse IPv4 de la machine.

    Par exemple, prenons le dernier octet de l’adresse IPv4 de Bob dont la représentation binaire est 01110011 : en appliquant bit à bit l’opérateur binaire ET entre cet octet et l’octet correspondant dans le masque, on obtient le dernier octet de l’adresse du sous- réseau, soit 01100000.

    Le poste de travail de Bob est donc sur le sous-réseau d’adresse 192.168.110.96.

    1. Indiquer le nombre total d’adresses IPv4 pouvant être attribuées sur le sous- réseau d’adresse 192.168.110.96 sur lequel se trouve Bob.

    L’administratrice système attribue maintenant l’adresse IPv4 192.168.110.134 au poste de travail de Zoé, nouvelle employée de la compagnie d’assurances.

    1. Donner la représentation binaire du nombre 134.

    Depuis son poste de travail, Zoé exécute les deux commandes suivantes :

    • commande n°1 : ping 192.168.110.115 ;
    • commande n°2 : ping 192.168.110.153.
    1. Indiquer, en justifiant, laquelle de ces deux commandes a produit l’affichage : 4 packets transmitted, 4 received, 0% packet loss, time 3002ms

    Bac 2022 Metropole1: Exercice 3

    Cet exercice porte sur les représentations binaires et les protocoles de routage.

    binaire routage routage

    Question 1

    Une adresse IPv4 est représentée sous la forme de 4 nombres séparés par des points. Chacun de ces 4 nombres peut être représenté sur un octet.

    A. Donner en écriture décimale l’adresse IPv4 correspondant à l’écriture binaire :

    11000000.10101000.10000000.10000011

    B. Tous les ordinateurs du réseau A ont une adresse IPv4 de la forme : 192.168.128._ _ _ , où seul le dernier octet (représenté par _ _ _ ) diffère. Donner le nombre d’adresses différentes possibles du réseau A.

    Question 2

    On rappelle que le protocole RIP cherche à minimiser le nombre de routeurs traversés (qui correspond à la métrique). On donne les tables de routage d’un réseau informatique composé de 5 routeurs (appelés A, B, C, D et E), chacun associé directement à un réseau du même nom obtenues avec le protocole RIP :

    1234 × 916

    1234 × 916

    A. Donner la liste des routeurs avec lesquels le routeur A est directement relié.

    B. Représenter graphiquement et de manière sommaire les 5 routeurs ainsi que les liaisons existantes entre ceux-ci.

    Question 3

    Le protocole OSPF est un protocole de routage qui cherche à minimiser la somme des métriques des liaisons entre routeurs.

    Dans le protocole de routage OSPF le débit des liaisons entre routeurs agit sur la métrique via la relation : $metrique = \tfrac{10^8}{debit}$ dans laquelle le débit est exprimé en bit par seconde (bps).

    On rappelle qu’un kbps est égal à $10^3$ bps et qu’un Mbps est égal à $10^6$ bps.

    A. Recopier sur votre copie et compléter le tableau suivant :

    Débit 100 kbps 500 kbps ? 100 Mbps
    Métrique associé 1000 ? 10 1

    1230 × 644

    1230 × 644

    Les nombres présents sur les liaisons représentent les coûts des routes avec le protocole OSPF.

    B. Indiquer le chemin emprunté par un message d’un ordinateur du réseau F à destination d’un ordinateur du réseau I. Justifier votre réponse.

    C. Recopier et compléter la table de routage du routeur F.

    D. Citer une unique panne qui suffirait à ce que toutes les données des échanges de tout autre réseau à destination du réseau F transitent par le routeur G. Expliquer en détail votre réponse.

    Question 4 (sup hors bac)

    A. Donner les caractéristiques du graphe de réseaux schématisé plus haut.

    On donne cette fois le tableau constitué à partir de l’algorithme de Dijkstra, appliqué à ce même graphe de reseaux:

    • le colonnes représentent les sommets à atteindre
    • les lignes sont les sommets de départ
    • On renseigne dans les cases la distance cumulée depuis le noeud F, jusqu’au noeud de la colonne, en passant par le noeud adjacent de la ligne. Par exemple, I peut être atteint en venant du noeud K avec une longueur de 13.
    G H I J K L
    F 5
    G
    H 6
    I
    J 8 8 11
    K 13
    L

    B. Représenter le graphe des chemins pour explorer depuis F les autres noeuds, en suivant le chemin le plus court.

    C. Ce graphe représente l’arbre couvrant du graphe. Donner les caractéristiques de cet arbre.

    D. Quel est le chemin le plus court pour aller de F à G?

    E. Même question, mais cette fois pour aller de H à K.

    bac 2024 metropole1 exercice 2

    Cet exercice traite de protocoles de routage, de sécurité des communications et de base de données relationnelle.

    routage

    Une agence de voyage propose des croisières en bateau. Chaque croisière a un nom unique et passe par quatre escales correspondant à des villes qui ont elles aussi des noms différents. Pour gérer les réservations de ses clients, l’agence utilise une base de données.

    Partie A

    L’agence de voyage possède deux bureaux distincts. Elle passe par un prestataire de service qui héberge sa base de données et utilise un système de gestion de base de données relationnelle. Vous trouverez ci-après un schéma du réseau entre les deux bureaux de l’agence de voyage et le prestataire. On peut y voir les différents routeurs (nommés de A à I) ainsi que le coût des liaisons entre eux.

    Topologie du réseau

    Topologie du réseau

    1. Donner deux services rendus par un système de gestion de bases de données relationnelles.

    Le protocole RIP (Routing Information Protocol) est un protocole de routage qui minimise le nombre de routeurs par lesquels les paquets transitent.

    Le protocole OSPF (Open Shortest Path First) est un protocole de routage qui minimise le coût du transit des paquets. Ce coût s’evalue grâce à la loi:

    $$cout = \tfrac{18^8}{Debit}$$
    1. Donner la route suivie par une requête issue du bureau numéro 1 jusqu’au prestataire si on utilise le protocole RIP.
    2. Le debit d’une liaison, utilisé pour le calcul du coût, s’exprime en bits par seconde. Donner une définition de ce qu’est le débit
    3. Calculer le coût pour une liaison de débit 100 Mb par s. (fast ethernet)
    4. Donner les deux routes que pourrait suivre une requête issue du bureau numéro 2 jusqu’au prestataire si on utilise le protocole OSPF. Donner le coût de chaque route.

    Bac 2024 Amerique du Nord J2 exercice 3

    Cet exercice porte sur la programmation objet, les structures de données, les réseaux et l’architecture matérielle.

    poo adresses ip blockchain

    On considère un réseau local constitué des trois machines de Alice, Bob et Charlie dont les adresses IP sont les suivantes :

    • la machine d’Alice a pour adresse 192.168.1.1 ;
    • la machine de Bob a pour adresse 192.168.1.2.

    On rappelle que l’adresse 192.168.1.255 est l’adresse de diffusion qui sert à communiquer avec toutes les machines du réseau local et le masque de ce réseau local est 255.255.255.0. Cette adresse de diffusion est réservée et ne peut être attribuée à une machine.

    Partie A

    1. Donner une adresse IP possible pour la machine de Charlie afin qu’elle puisse communiquer avec celles d’Alice et Bob dans le réseau local. Justifier votre réponse en donnant toutes les conditions à respecter dans le choix de cette adresse IP.

    Ce réseau est utilisé pour effectuer des transactions financières en monnaie numérique nsicoin entre les trois utilisateurs. Pour cela, on crée la classe Transaction ci-dessous :

    class Transaction:
      def __init__(self, expediteur, destinataire, montant):
        self.expediteur = expediteur
        self.destinataire = destinataire
        self.montant = montant
    1. Toutes les dix minutes, les transactions réalisées pendant cet intervalle de temps sont regroupées par ordre d’apparition dans une liste Python. Dans un intervalle de dix minutes, Alice envoie dix nsicoin à Charlie puis Bob envoie cinq nsicoin à Alice. Écrire la liste Python correspondante à ces transactions.

    Pour garder une trace de toutes les transactions effectuées, on utilise une liste chaînée de blocs (ou blockchain) dont le code Python est fourni ci-dessous. Toutes les dix minutes un nouveau bloc contenant les nouvelles transactions est créé et ajouté à la blockchain.

    class Bloc:
      def __init__(self, liste_transactions, bloc_precedent):
        self.liste_transactions = liste_transactions
        self.bloc_precedent = bloc_precedent # de type Bloc
    
    class Blockchain:
      def __init__(self):
        self.tete = self.creer_bloc_0()
    
      def self.creer_bloc_0(self):
        """
        Crée le premier bloc qui distribue 100 nsicoin à tous les utilisateurs
        (un pseudo-utilisateur Genesis est utilisé comme
        expéditeur)
        """
        liste_transactions = [
          Transaction("Genesis", "Alice", 100),
          Transaction("Genesis", "Bob", 100),
          Transaction("Genesis", "Charlie", 100)
          ]
        return Bloc(liste_transactions, None) 
    1. La figure 1 représente les trois premiers blocs d’une Blockchain. Expliquer pourquoi la valeur de l’attribut bloc_precedent du bloc0 est None.
    Blockchain

    Blockchain

    1. À l’aide des classes Bloc et Blockchain, écrire le code Python permettant de créer un objet ma_blockchain de type Blockchain représenté par la figure 1.

    2. Donner le solde en nsicoin de Bob à l’issue du bloc2.

    3. On souhaite doter la classe Blockchain d’une méthode ajouter_bloc qui prend en paramètre la liste des transactions des dix dernières minutes et l’ajoute dans un nouveau bloc. Écrire le code Python de cette méthode cidessous.

    def ajouter_bloc(self, liste_transactions):
      # A compléter
    1. Lorsqu’un utilisateur ajoute un nouveau bloc à la Blockchain, il l’envoie aux autres membres. Ainsi chaque utilisateur dispose sur sa propre machine d’une copie identique de la Blockchain. Donner le nom et la valeur de l’adresse IP à utiliser pour effectuer cet envoi.
    2. On souhaite doter la classe Bloc d’une nouvelle méthode calculer_solde permettant de renvoyer le solde à l’issue de ce bloc. Recopier et compléter sur votre copie le code Python de cette méthode :
    def calculer_solde(self, utilisateur):
      if self.precedent is None: # cas de base
        solde = 0
      else:
        solde = ... # appel récursif : calcul du solde au bloc précédent
        for transaction in bloc.liste_transactions
          if ... == utilisateur:
            solde = solde - ....
          elif ... :
            ...
        return solde
    1. Écrire l’appel à la fonction calculer_solde permettant de calculer le solde actuel de Alice

    Partie B

    Dans cette partie, on va améliorer la sécurité de la blockchain. Pour cela on enrichit la classe Bloc comme indiqué ci-dessous:

    class Bloc:
      def __init__(self, liste_transactions, bloc_precedent):
        self.liste_transactions = liste_transactions
        self.bloc_precedent = bloc_precedent
        # Définition de trois nouveaux attributs
        self.hash_bloc_precedent = self.donner_hash_precedent()
        self.nonce = 0 # Fixé arbitrairement et temporairement à 0 
        # avant le minage du bloc
        self.hash = self.calculer_hash()
    
        # Définition de trois nouvelles méthodes
        def donner_hash_precedent(self):
          if self.bloc_precedent is not None:
            return self.bloc_precedent.hash
          else :
            return "0"
    
        def calculer_hash(self):
          """calcule et renvoie le hash du bloc courant"""
          # Le code python n'est pas étudié dans cet exercice
    
        def minage_bloc(self):
          """modifie le nonce d'un bloc pour que son hash commence
          par '00'"""
          # A compléter

    La fonction calculer_hash produit une chaîne de caractères appelée hash qui possède les propriétés suivantes :

    • Le hash d’un bloc dépend de toutes les données contenues dans le bloc et uniquement de ces données ;
    • Le calcul du hash d’un bloc est rapide et facile à calculer par une machine ;
    • La moindre modification dans le bloc produit un hash complètement différent ;
    • Il est impossible de déduire le bloc à partir de son hash.
    • Si deux blocs ont le même hash, c’est qu’ils sont parfaitement identiques.
    1. L’attribut nonce est de type entier. Miner un bloc signifie trouver une valeur de nonce de telle façon que l’attribut hash du bloc commence par les deux caractères “00”. Compte tenu des propriétés précédentes, la seule façon de trouver cette valeur est de procéder à une recherche exhaustive. Expliquer en quoi consiste le fait de trouver une valeur par recherche exhaustive.

    Dans la suite de l’exercice, on considère que tous les utilisateurs cherchent à miner le nouveau bloc. Le premier qui réussit, l’ajoute à la blockchain et gagne une récompense en nsicoin.

    1. En justifiant votre réponse, donner la valeur de l’attribut hash_bloc_precedent du bloc0.
    2. Sachant que le hash est écrit sur 256 bits, donner le calcul permettant d’obtenir le nombre de hash possibles.
    3. Recopier et compléter sur votre copie le code python de la méthode minage_bloc.
    def minage_bloc(self):
      """modifie le nonce d'un bloc pour que son hash commence par
      '00' en énumérant tous les entiers naturels en partant de 0."""
      self.nonce = 0
      self.hash = self.calculer_hash()
      while ... :
        self.nonce = ...
        self.hash = ...

    POO

    Bac 2022 Metropole1/ Exercice 5

    Cet exercice porte sur la Programmation Orientée Objet.

    poo

    Les participants à un jeu de LaserGame sont répartis en équipes et s’affrontent dans ce jeu de tir, revêtus d’une veste à capteurs et munis d’une arme factice émettant des infrarouges.

    Les ordinateurs embarqués dans ces vestes utilisent la programmation orientée objet pour modéliser les joueurs. La classe Joueur est définie comme suit :

    class Joueur:
      def __init__(self, pseudo, identifiant, equipe):
        """constructeur """
        self.pseudo = pseudo
        self.equipe = equipe
        self.id = identifiant
        self.nb_de_tirs_emis = 0
        self.liste_id_tirs_recus = []
        self.est_actif = True
    
      def tire(self):
        """méthode déclenchée par l'appui sur la gachette"""
        if self.est_actif == True:
          self.nb_de_tirs_emis = self.nb_de_tirs_emis + 1
    
      def est_determine(self):
        """methode qui renvoie True si le joueur réalise un
        grand nombre de tirs"""
        return self.nb_de_tirs_emis > 500
    
      def subit_un_tir(self, id_recu):
        """méthode déclenchée par les capteurs de la
        veste"""
        if self.est_actif == True:
          self.est_actif = False
          self.liste_id_tirs_recus.append(id_recu)

    Question 1

    Parmi les instructions suivantes, recopier celle qui permet de déclarer un objet joueur1, instance de la classe Joueur, correspondant à un joueur dont le pseudo est “Sniper”, dont l’identifiant est 319 et qui est intégré à l’équipe “A”:

    • Instruction 1 : joueur1 = ["Sniper", 319, "A"]
    • Instruction 2 : joueur1 = new Joueur["Sniper", 319, "A"]
    • Instruction 3 : joueur1 = Joueur("Sniper", 319, "A")
    • Instruction 4 : joueur1 = Joueur{"pseudo":"Sniper", "id":319, "equipe":"A"}

    Question 2

    La méthode subit_un_tir réalise les actions suivantes :

    Lorsqu’un joueur actif subit un tir capté par sa veste, l’identifiant du tireur est ajouté à l’attribut liste_id_tirs_recus et l’attribut est_actifprend la valeur False (le joueur est désactivé). Il doit alors revenir à son camp de base pour être de nouveau actif.

    A. Écrire la méthode redevenir_actifqui rend à nouveau le joueur actif uniquement s’il était précédemment désactivé.

    B. Écrire la méthode nb_de_tirs_recusqui renvoie le nombre de tirs reçus par un joueur en utilisant son attribut liste_id_tirs_recus.

    Question 3

    Lorsque la partie est terminée, les participants rejoignent leur camp de base respectif où un ordinateur, qui utilise la classe Base, récupère les données. La classe Base est définie par :

    • ses attributs :
      • equipe : nom de l’équipe (str). Par exemple, “A” ,
      • liste_des_id_de_l_equipe qui correspond à la liste (list) des identifiants connus des joueurs de l’équipe,
      • score : score (int) de l’équipe, dont la valeur initiale est 1000 ;
    • ses méthodes :
      • est_un_id_allie qui renvoie True si l’identifiant passé en paramètre est un identifiant d’un joueur de l’équipe, False sinon,
      • incremente_score qui fait varier l’attribut score du nombre passé en paramètre,
      • collecte_information qui récupère les statistiques d’un participant passé en paramètre (instance de la classe Joueur) pour calculer le score de l’équipe.
    def collecte_information(self,participant):
      if participant.equipe == self.equipe : # test 1
        for id in participant.liste_id_tirs_recus:
          if self.est_un_id_allie(id): # test 2
            self.incremente_score(-20)
          else:
            self.incremente_score(-10)

    A. Indiquer le numéro du test (test 1 ou test 2) qui permet de vérifier qu’en fin de partie un participant égaré n’a pas rejoint par erreur la base adverse.

    B. Décrire comment varie quantitativement le score de la base lorsqu’un joueur de cette équipe a été touché par le tir d’un coéquipier.

    On souhaite accorder à la base un bonus de 40 points pour chaque joueur particulièrement déterminé (qui réalise un grand nombre de tirs).

    Question 4:

    Recopier et compléter, en utilisant les méthodes des classes Joueur et Base, les 2 lignes de codes suivantes qu’il faut ajouter à la fin de la méthode collecte_information :

    ........ #si le participant réalise un grand nombre de tirs
     ......... #le score de la Base augmente de 40

    Graphes

    Sujet OA : 2024 Exercice 3

    sujet complet: Sujet 0A 2024

    Partie 1

    Cet exercice porte sur les graphes, les algorithmes sur les graphes, les bases de données et les requêtes SQL.

    graphes parcours récursivité

    La société CarteMap développe une application de cartographie-GPS qui permettra aux automobilistes de définir un itinéraire et d’être guidés sur cet itinéraire. Dans le cadre du développement d’un prototype, la société CarteMap décide d’utiliser une carte fictive simplifiée comportant uniquement 7 villes : A, B, C, D, E, F et G et 9 routes (toutes les routes sont considérées à double sens).

    Voici une description de cette carte :

    • A est relié à B par une route de 4 km de long ;
    • A est relié à E par une route de 4 km de long ;
    • B est relié à F par une route de 7 km de long ;
    • B est relié à G par une route de 5 km de long ;
    • C est relié à E par une route de 8 km de long ;
    • C est relié à D par une route de 4 km de long ;
    • D est relié à E par une route de 6 km de long ;
    • D est relié à F par une route de 8 km de long ;
    • F est relié à G par une route de 3 km de long.
    1. Représenter ces villes et ces routes sur sa copie en utilisant un graphe pondéré, nommé G1.
    2. Déterminer le chemin le plus court possible entre les villes A et D.
    3. Définir la matrice d’adjacence du graphe G1 (en prenant les sommets dans l’ordre alphabétique).

    Dans la suite de l’exercice, on ne tiendra plus compte de la distance entre les différentes villes et le graphe, non pondéré et représenté ci-dessous, sera utilisé :

    Graphe G2

    Graphe G2

    Chaque sommet est une ville, chaque arête est une route qui relie deux villes.

    1. Proposer une implémentation en Python du graphe G2 à l’aide d’un dictionnaire.
    2. Proposer un parcours en largeur du graphe G2 en partant de A.

    La société CarteMap décide d’implémenter la recherche des itinéraires permettant de traverser le moins de villes possible. Par exemple, dans le cas du graphe G2, pour aller de A à E, l’itinéraire A-C-E permet de traverser une seule ville (la ville C), alors que l’itinéraire A-H-G-E oblige l’automobiliste à traverser 2 villes (H et G).

    Le programme Python suivant a donc été développé (programme p1) :

    tab_itineraires=[]
    def cherche_itineraires(G, start, end, chaine=[]):
    	chaine = chaine + [start]
    	if start == end:
    		return chaine
    	for u in G[start]:
    		if u not in chaine:
    			nchemin = cherche_itineraires(G, u, end, chaine)
    			if len(nchemin) != 0:
    				tab_itineraires.append(nchemin)
    	return []
    
    def itineraires_court(G,dep,arr):
    	cherche_itineraires(G, dep, arr) 
    	tab_court = ...
    	mini = float('inf') # mini prend la valeur + infini
    	for v in tab_itineraires:
    		if len(v) <= ... : 
    			mini = ...
    	for v in tab_itineraires: 
    		if len(v) == mini:
    			tab_court.append(...) 
    	return tab_court

    La fonction itineraires_court prend en paramètre un graphe G, un sommet de départ depet un sommet d’arrivéearr. Cette fonction renvoie une liste Python contenant tous les itinéraires pour aller de depàarr` en passant par le moins de villes possible.

    Exemple (avec le graphe G2) :

    itineraires_court(G2, 'A', 'F')
    >>> [['A', 'B', 'I', 'F'], ['A', 'H', 'G', 'F'], ['A', 'H', 'I',
    'F']]

    On rappelle les points suivants :

    • la méthode append ajoute un élément à une liste Python ; par exemple, tab.append(el) permet d’ajouter l’élément el à la liste Python tab ;
    • en python, l’expression ['a'] + ['b'] vaut ['a', 'b'];
    • en python float('inf') correspond à l’infini.
    1. Expliquer pourquoi la fonction cherche_itineraires peut être qualifiée de fonction récursive.
    2. Expliquer le rôle de la fonction cherche_itineraires dans le programme p1.
    3. Compléter la fonction itineraires_court.

    Les ingénieurs sont confrontés à un problème lors du test du programme p1. Voici les résultats obtenus en testant dans la console la fonction itineraires_court deux fois de suite (sans exécuter le programme entre les deux appels à la fonction itineraires_court) :

    exécution du programme p1

    itineraires_court(G2, 'A', 'E')
    >>> [['A', 'C', 'E']]
    itineraires_court(G2, 'A', 'F')
    >>> [['A', 'C', 'E']]

    alors que dans le cas où le programme p1 est de nouveau exécuté entre les 2 appels à la fonction itineraires_court, on obtient des résultats corrects :

    exécution du programme p1

    itineraires_court(G2, 'A', 'E')
    >>> [['A', 'C', 'E']]
    exécution du programme p1
    itineraires_court(G2, 'A', 'F')
    >>> [['A', 'B', 'I', 'F'], ['A', 'H', 'G', 'F'], ['A', 'H', 'I', 'F']]
    1. Donner une explication au problème décrit ci-dessus. Vous pourrez vous appuyer sur les tests donnés précédemment.

    Partie 2

    voir sujet complet: Sujet 0A 2024

    Arbres

    Arbres, parcours BFS (extrait 2024 centres etrangers J2, Ex 3)

    arbre parcours

    Partie B

    On considère l’arborescence de fichiers de la figure suivante:

    arborescence fichiers

    arborescence fichiers

    on propose l’implémentation suivante. L’attribut fils est une variable de type list contenant tous les dossiers fils. Cette liste est vide dans le cas où le dossier est vide.

    class Dossier:
    	def __init__(self, nom, liste):
    		self.nom = nom
    		self.fils = liste # liste d'objets de la classe Dossier
    1. Écrire le code Python d’une méthode est_vide qui renvoie True lorsque le dossier est vide et False sinon.
    2. Écrire le code Python permettant d’instancier une variable var_multimedia de la classe Dossier représentant le dossier multimedia de la figure précédente. Attention : cela nécessite d’instancier tous les nœuds du sous-arbre de racine multimedia.
    3. Recopier et compléter sur votre copie le code Python de la méthode parcours suivante qui affiche les noms de tous les descendants d’un dossier en utilisant l’ordre préfixe.
    def parcours(self):
    	print(...)
    	for f in ...:
    		...
    1. Justifier que cette méthode parcours termine toujours sur une arborescence de fichiers.
    2. Proposer une modification de la méthode parcours pour que celle-ci effectue plutôt un parcours suffixe (ou postfixe).
    3. Expliquer la différence de comportement entre un appel à la méthode parcours de la classe Dossier et une exécution de la commande UNIX ls

    On considère la variable var_videos de type Dossier représentant le dossier videos de la figure précédente. On souhaite que le code Python var_videos.mkdir("documentaires") crée un dossier documentaires vide dans le dossier var_videos.

    1. Écrire le code Python de la méthode mkdir.
    2. Écrire en Python une méthode contient(self, nom_dossier) qui renvoie True si l’arborescence de racine self contient au moins un dossier de nom nom_dossier et False sinon.
    3. Avec l’implémentation de la classe Dossier de cette partie, expliquer comment il serait possible de déterminer le dossier parent d’un dossier donné dans une arborescence donnée. On attend ici l’idée principale de l’algorithme décrite en français. On ne demande pas d’implémenter cet algorithme en Python.
    4. Proposer une modification dans la méthode __init__ de la classe Dossier qui permettrait de répondre à la question précédente beaucoup plus efficacement et expliquer votre choix.

    Exercice 1 25-NSIJ2ME1:

    Cet exercice porte sur les arbres binaires et la programmation Python.

    arbre compression codage binaire dictionnaire tableaux occurences

    Le codage de Shannon-Fano est un système de codage utilisé pour la compression sans pertes de données. Il a été mis au point par Robert Fano d’après une idée de Claude Shannon.

    Partie A

    Dans cette partie, on va étudier l’utilisation des arbres de codage. Un arbre de codage est un arbre binaire où chaque feuille contient un symbole du texte que l’on souhaite coder. Le code binaire d’un symbole s’obtient alors en concaténant les 0 et les 1 sur les branches qui mènent de la racine à la feuille contenant ce symbole.

    Par exemple, pour l’arbre de codage donné en Figure 1, le symbole c est codé par le mot binaire 1101, tandis que d est codé par le mot binaire 11000. Les codes binaires des symboles ne sont donc pas tous de la même taille. Pour décoder un mot binaire, il suffit de descendre dans l’arbre, depuis la racine, selon les 0 et les 1 qu’on lit jusqu’à trouver une feuille (et donc un symbole), puis de recommencer avec la suite du mot binaire pour décoder les symboles suivants.

    Exemple d’arbre de codage

    Exemple d’arbre de codage

    1. Écrire le mot binaire qui sera utilisé pour encoder le caractère espace, représenté par le symbole dans l’arbre.

    2. Déterminer le texte codé par le mot binaire 0001110101111110011001.

    3. Citer le type de parcours de l’arbre qui permettrait d’obtenir les symboles classés par taille d’encodage croissante.

    Partie B

    Dans cette partie, on va utiliser le codage de Shannon-Fano pour encoder le texte :

    je pense, donc je suis

    Dans la méthode de Shannon-Fano, l’arbre de codage est calculé pour un texte donné par l’algorithme suivant.

    • Étape 1 : classer les symboles du texte par nombre d’occurrences croissant;
    • Étape 2 : en gardant le classement obtenu, séparer les symboles en deux sous- groupes de sorte que les totaux des nombres d’occurrences soient les plus proches possibles dans les deux sous-groupes;
    • Étape 3 : placer tous les symboles du premier groupe dans le fils gauche (côté étiqueté par 1), et ceux du second groupe dans le fils droit (côté étiqueté par 0);
    • Étape 4 : recommencer récursivement pour chacun des sous-groupes jusqu’à ce qu’ils n’aient plus qu’un seul symbole ; on a alors une feuille étiquetée par ce symbole.

    Après avoir classé les symboles par nombre d’occurrences croissant (étape 1), on obtient le tableau suivant :

    symbole i u c o d , p n j s e _
    nombre d’occurrences 1 1 1 1 1 1 1 2 2 3 4 4
    1. Justifier par le calcul que l’étape 2 mène à la situation illustrée par la Figure 2.
    Le résultat de l’étape 2

    Le résultat de l’étape 2

    En appliquant l’algorithme de Shannon-Fano, on peut obtenir l’arbre de la Figure 3.

    Arbre de codage obtenu par l’algorithme de Shannon-Fano

    Arbre de codage obtenu par l’algorithme de Shannon-Fano

    On rappelle qu’un arbre réduit à un seul nœud, c’est-à-dire réduit à une feuille, est de hauteur 0.

    1. Donner la hauteur de l’arbre de la Figure 3 et préciser dans le contexte de l’exercice ce qu’elle représente.

    On rappelle que dans le code ASCII, chaque symbole est codé sur un octet.

    1. Justifier, en comparant le codage ASCII et le codage de Shannon-Fano, que ce second codage permet d’utiliser environ deux fois moins d’octets pour le texte : je pense, donc je suis
    2. Dessiner, en vous inspirant de l’arbre de la Figure 1, un arbre de codage qui permettrait d’encoder le mot « chiffrer » en utilisant l’algorithme de Shannon-Fano.

    Partie C

    Dans cette partie, on souhaite écrire une fonction Python qui donnera le mot binaire obtenu pour coder un texte avec l’algorithme de Shannon-Fano. On commence par la fonction creer_dico_occ :

    def creer_dico_occ(texte):
    	"""renvoie un dictionnaire dont les clés sont les
    	symboles de texte et les valeurs associées leur
    	nombre d'occurences dans texte"""
    	dico = {}
    	for symbole in texte:
    		if symbole in dico:
    			dico[symbole] = ...
    		else:
    	 		dico[symbole] = ...
    	return dico
    1. Recopier et compléter les lignes 8 et 10 du code de la fonction creer_dico_occ.

    On dispose d’une fonction creer_tab_trie qui prend en paramètre un dictionnaire construit avec la fonction creer_dico_occ et qui renvoie une liste de tuples classés dans l’ordre croissant d’occurrences des symboles.

    Par exemple :

    >>> texte = 'je pense, donc je suis'
    >>> dico = creer_dico_occ(texte)
    >>> creer_tab_trie(dico)
    [('i', 1), ('u', 1), ('c', 1), ('o', 1), ('d', 1), (',', 1),
    ('p', 1), ('n', 2), ('j', 2), ('s', 3), (' ', 4), ('e', 4)]
    1. Écrire une fonction somme_occ qui prend en paramètres un tableau tab de tuples (symbole, nb_occ) et qui renvoie la somme des nombres d’occurrences des symboles du tableau. Les tuples utilisés sont de même structure que l’élément renvoyé dans l’exemple précédent.

    On suppose pour la suite qu’on dispose d’une fonction separe qui sépare un tableau trié en deux sous-tableaux de manière à ce que les sommes de ces derniers soient les plus proches possible :

    def separe(tab):
    	moitie = somme_occ(tab) // 2
    	somme = 0
    	i = 0
    	while moitie > somme:
    		somme = somme + tab[i][1]
    		i = i + 1
    	tab1 = [tab[k] for k in range(0, i)]
    	tab2 = [tab[k] for k in range(i, len(tab))]
    	return tab1, tab2
    1. Recopier et compléter les lignes 9 et 11 du code de la fonction récursive shannon qui prend en paramètres un caractère symbole et un tableau trié tab et qui renvoie l’écriture binaire associée à symbole dans le tableau tab.
    def shannon(symbole, tab):
    	"""renvoie l'écriture binaire associée à symbole
    	dans le tableau trié tab"""
    	if len(tab) == 1:
    		return ""
    	else:
    		t1, t2 = separe(tab)
    		if symbole in [elt[0] for elt in t1]:
    			return "1" + ...
    		else:
    			return "0" + ...
    1. Décrire ce qui garantit la terminaison de la fonction récursive shannon.
    2. Écrire une fonction encode_shannon qui prend en paramètre un texte de type str et renvoie un mot binaire de type str obtenu après encodage par l’algorithme de Shannon-Fano.

    On pourra utiliser les fonctions vues précédemment qui sont recensées ci- après.

    creer_dico_occ(texte)
    	renvoie un dictionnaire dont les clés sont les symboles
    	du texte et les valeurs associées leur nombre
    	d'occurrences
    creer_tab_trie(dico)
    	renvoie la liste crée à partir d'un dictionnaire
    	de couples (symbole, nb_occ)
    separe(tab)
    	renvoie le tuple composé des 2 sous-tableaux triés
    	avec des sommes d'occurences proches
    shannon(symbole, tab)
    	renvoie l'écriture binaire associée au symbole dans le
    	tableau trié tab

    epreuve pratique

    Exercices classiques pour se préparer à l'epreuve.

    Sous-sections de epreuve pratique

    algos essentiels

    Exercices A de la BNS 2024

    chaine str tableau dictionnaire python bases compteur min max

    parcours de chaine de caractères, mot à trou

    On considère des chaînes de caractères contenant uniquement des majuscules et des carac- tères * appelées mots à trous.

    Par exemple INFO*MA*IQUE, ***I***E** et *S* sont des mots à trous.

    Programmer une fonction correspond qui :

    • prend en paramètres deux chaînes de caractères mot et mot_a_trous où mot_a_trous est un mot à trous comme indiqué ci-dessus,
    • renvoie :
      • True si on peut obtenir mot en remplaçant convenablement les caractères '*' de mot_a_trous.
      • False sinon.

    Exemple :

    >>> correspond('INFORMATIQUE', 'INFO*MA*IQUE')
    True
    >>> correspond('AUTOMATIQUE', 'INFO*MA*IQUE')
    False
    >>> correspond('STOP', 'S*')
    False
    >>> correspond('AUTO', '*UT*')
    True

    max d’une liste

    Écrire la fonction maximum_tableau, prenant en paramètre un tableau non vide de nombres tab (de type list) et renvoyant le plus grand élément de ce tableau.

    Exemples :

    >>> maximum_tableau([98, 12, 104, 23, 131, 9])
    131
    >>> maximum_tableau([-27, 24, -3, 15])
    24

    Rechercher

    Programmer la fonction recherche, prenant en paramètres un tableau non vide tab (type list) d’entiers et un entier n, et qui renvoie l’indice de la dernière occurrence de l’élément cherché. Si l’élément n’est pas présent, la fonction renvoie None.

    Exemples

    >>> recherche([5, 3], 1) # renvoie None
    2
    >>> recherche([2, 4], 2)
    0
    >>> recherche([2, 3, 5, 2, 4], 2)
    3

    Tableau trié ou non

    Écrire une fonction verifie qui prend en paramètre un tableau de valeurs numériques et qui renvoie True si ce tableau est trié dans l’ordre croissant, False sinon.

    Un tableau vide est considéré comme trié.

    Exemples :

    Exemples :
    >>> verifie([0, 5, 8, 8, 9])
    True
    >>> verifie([8, 12, 4])
    False
    >>> verifie([-1, 4])
    True
    >>> verifie([])
    True
    >>> verifie([5])
    True

    Compression. Codage par différence

    Le codage par différence (delta encoding en anglais) permet de compresser un tableau d’entiers dont les valeurs sont proches les unes des autres. Le principe est de stocker la première donnée en indiquant pour chaque autre donnée sa différence avec la précédente plutôt que la donnée elle-même.

    On se retrouve alors avec un tableau de données plus petit, nécessitant moins de place en mémoire. Cette méthode se révèle efficace lorsque les valeurs consécutives sont proches.

    Programmer la fonction delta(liste) qui prend en paramètre un tableau non vide de nombres entiers et qui renvoie un tableau contenant les valeurs entières compressées à l’aide cette technique.

    Exemples :

    >>> delta([1000, 800, 802, 1000, 1003])
    [1000, -200, 2, 198, 3]
    >>> delta([42])
    [42] 

    Compteur d’espaces

    Dans cet exercice, on considère des phrases composées de mots.

    • On appelle « mot » une chaîne de caractères composée avec des caractères choisis parmi les 26 lettres minuscules ou majuscules de l’alphabet,

    • On appelle phrase une chaîne de caractères :

      • composée avec un ou plusieurs mots séparés entre eux par un seul caractère espace ' ',
      • se finissant :
        • soit par un point '.' qui est alors collé au dernier mot,
        • soit par un point d’exclamation '!' ou d’interrogation '?' qui est alors séparé du dernier mot par un seul caractère espace ' '.

    Voici deux exemples de phrases :

    • ‘Cet exercice est simple.’
    • ‘Le point d exclamation est separe !’

    Après avoir remarqué le lien entre le nombre de mots et le nombres de caractères espace dans une phrase, programmer une fonction nombre_de_mots qui prend en paramètre une phrase et renvoie le nombre de mots présents dans cette phrase.

    >>> nombre_de_mots('Cet exercice est simple.')
    4
    >>> nombre_de_mots('Le point d exclamation est séparé !')
    6
    >>> nombre_de_mots('Combien de mots y a t il dans cette phrase ?')
    10
    >>> nombre_de_mots('Fin.')
    1

    Dictionnaire. Fusion

    Écrire une fonction ajoute_dictionnaires qui prend en paramètres deux dictionnaires d1 et d2 dont les clés sont des nombres et renvoie le dictionnaire d défini de la façon suivante :

    • Les clés de d sont celles de d1 et celles de d2 réunies.
    • Si une clé est présente dans les deux dictionnaires d1 et d2, sa valeur associée dans le dictionnaire d est la somme de ses valeurs dans les dictionnaires d1 et d2.
    • Si une clé n’est présente que dans un des deux dictionnaires, sa valeur associée dans le dictionnaire d est la même que sa valeur dans le dictionnaire où elle est présente.

    Exemples :

    >>> ajoute_dictionnaires({1: 5, 2: 7}, {2: 9, 3: 11})
    {1: 5, 2: 16, 3: 11}
    >>> ajoute_dictionnaires({}, {2: 9, 3: 11})
    {2: 9, 3: 11}
    >>> ajoute_dictionnaires({1: 5, 2: 7}, {})
    {1: 5, 2: 7}

    repondeur telephonique

    Tutoriels

    Etapes du projet

    1. Créer un explorateur de dossiers/fichiers et analyser la courbe de transit: Lien
    2. Calculatrice python et synthèse des résultats à l’aide dans un tableur: Lien
    3. Traitement de données en table - Pandas Dataframe: Lien
    4. Base de données:
      • SQL et python: Lien
      • Base de données SQL et python-pandas: Lien
    5. indice similarité avec la Terre (IST): Lien
    6. Analyse graphique: Lien
    7. Utiliser scikit-learn pour predire la classe des exoplanètes: Lien

    Courbes de transit

    Etape 1: Courbe de transit

    Outil de navigation: explorateur Python

    On souhaite créer un outil de navigation qui permettra de se deplacer dans l’arborescence des dossiers et fichiers. Cela permettra de selectionner le-s fichier-s à traiter depuis la console python, sans modifier le code du programme.

    Exemple:

    On pourra au choix:

    • Utiliser, ou s’inspirer du fichier source suivant: astep_2025_v0.py
    • Programmer cette partie du programme de manière itérative (avec boucle while)
    • Programmer cette partie à l’aide d’un algorithme récursif (niveau Term NSI)

    Les fonctions python qui permettent de naviguer entre dossiers et fichiers font partie du module os.path, dont la documentation officielle est ici: doc python

    On utilisera principalement:

    • os.getcwd(): str, le dossier courant
    • os.path.abspath(): retourne le chemin absolu du dossier courant
    • os.chdir(d): change de dossier pour aller au dossier d
    • os.chdir('..'): remonte d’un niveau
    • os.listdir() ou os.listdir(d) : retourne la liste des fichiers et dossiers du dossier courant ou bien du dossier d
    • os.path.isdir(f): booléen True si f est un dossier
    • os.path.isfile(f): True si f est un fichier
    • f.endswith('.csv'): True si l’extension de f est .csv

    Ouvrir et executer le fichier avec un IDE python quelconque. Pour le tracé de graphiques, il est recommandé d’utiliser IDLE (Python GUI) de la distribution Winpython.

    Ouverture du fichier csv

    Pour chacun des fichiers de données, ouvrir une nouvelle cellule du notebook et adapter le script suivant:

    import csv
    table = []
    with open('TIC323295479-01_20240617_ASTEP-ANTARCTICA_R_measurements.csv', 'r') as file:
        reader = csv.reader(file, delimiter=',')
        for row in reader:
            try:
                line_values = []
                for val in row:
                    val = float(val)
                    line_values.append(val)
            except:
                line_values = row
            table.append(line_values)
    
    # test
    table[:3]
    """
    [['BJD', 'FLUX', 'ERRFLUX', 'AIRMASS', 'SKY'],
     [478.87701, 0.999509, 0.00222, 1.015, 218.0],
     [478.87718, 1.003059, 0.002213, 1.015, 219.0]]
    """

    Lissage de la courbe

    Les données utiles occupent les colonnes 0 (BJD) et 1 (FLUX) de la table. Les valeurs de FLUX (nuage de points en gris) étant très bruitées, il conviendra de réaliser un lissage des points (courbe rouge):

    Le programme suivant réalise une moyenne glissante (courbe rouge): pour chaque indice i, on fait une moyenne du FLUX sur une fenêtre de 100 points, centrés sur l’indice i. y[i-50:i+50]

    Compléter la fonction lissage, ainsi que le script aux points (1), (2), (3):

    import matplotlib.pyplot as plt
    from matplotlib.widgets import Cursor
    
    def moyenne(signal):
        """fonction qui calcule la moyenne 
        sur les donnees de la liste signal
        """
        s = 0
        # à completer
        return s / b
    
    
    
    def lissage(L,largeur):
        signal_filtre = L.copy()
        for i in range(largeur//2,len(L)-largeur//2):
            signal = L[...:...]
            # on fait un slice
            # signal est le petit tableau de dimension egale à largeur
            # dont on fait la moyenne glissante
            # puis on place cette valeur moyenne dans signal_filtre, au rang i
            signal_filtre[i] = moyenne(...)
        return signal_filtre
    
    x = [] # colonne 0 de la table = BJD
    y = [] # colonne 1 de la table = FLUX
    
    # (1) import des valeurs de x et y à partir du fichier en ouverture
    
    # (2) utilisation des fonction lissage
    
    plt.clf()
    axes = plt.gca()
    plt.scatter(x,y,color='silver',marker='.',label='luminosité')
    plt.grid(True,which='both')
    plt.legend(loc='best')
    plt.title('luminosité transit')
    
    # (3) tracé de la courbe de lissage
    plt.plot(...,..., color='red',label='moyenne glissante')
    plt.grid(True,which='both')
    plt.legend(loc='best')
    cursor = Cursor(axes, useblit=True, color='red', linewidth=2)
    
    plt.show()

    On peut alors utiliser les fonctions de la fenêtre graphique pour relever les coordonnées à la main des intersections des courbes:

    option 1: le transit démarre au point A et termine au point B

    option 1: le transit démarre au point A et termine au point B

    option 2: le transit démarre au milieu du segment n°2 et termine au milieu du segment n°4

    option 2: le transit démarre au milieu du segment n°2 et termine au milieu du segment n°4

    Avec l’option 2:

    planète tau (h) incertitude sur tau delta incertitude sur delta
    TOI 270-1 7.2 à definir 1-0.991 à definir

    Suite

    • Lien vers l’etape 2: Notebook python utilisé comme calculatrice.
    • retour vers la page de présentation: retour

    dataframes

    Traitement de données d’observation en astrophysique

    Importer les données et librairies utiles

    Dans une cellule d’un notebook, copier-coller les lignes suivantes:

    import numpy as np
    import pandas as pd
    # Constantes solaires 
    Rsol = 6.9598e8               # rayon solaire en m
    rhosol = 1408                 # densite solaire kg/m3
    Msol = 1.98855e30             # masses solaire en kg
    
    # Mercure, Jupiter (SI)
    V_merc = 47                   # km/s
    R_Jup = 71e6                  # m
    # Constantes terrestres
    MEarth = 5.9736e24             # masses de la terre en kg
    REarth = 6.371e6               # rayon de la terre en m
    rhoEarth = 5514.               # densité de la terre  kg/m3
      
    # Changements d'unité
    onemasinrad = np.pi/180./3600000. # 1 mas in radian     
    kparsec = 3.08567758e19           # 1 kpc en m
    parsec = 3.08567758e16            # 1 pc en m
    
    # Constantes physiques
    G = 6.67e-11                   # m3 kg−1 s−2
    UA = 149597870700              # m

    Planète TOI 270-01

    Utilisez le notebook pour placer les valeurs de delta et tau mesurées sur la courbe de transit

    Pour la planète TOI 270-01 du système TOI 270, (valeurs à vérifier sur la courbe de transit):

    # Données de l'etoile 
    R_star = Rsol * 0.37
    M_star = Msol * 0.36
    # Observables sur la courbe de transit
    delta = 0.0044 # sans unité
    tau = 4600     # s

    Rayon planete a partir de delta

    $$R_p = R_{star}\times \sqrt{delta}$$

    La racine carrée est une fonction de la librairie numpy, avec numpy.sqrt Le résultat du calcul peut nécessiter l’écriture d’un format particulier pour faciliter la lecture:

    Utilisez le notebook pour calculer le rayon de la planète observée:

    ## Calcul du rayon planétaire    
    Rp = np.sqrt(delta) * R_star
    print("Rp = {:.3e} m.".format(Rp))    
    print("Rp = {:5.3f} REarth.".format(Rp/REarth)) 
    # ---- affichage console --- #
    Rp = 1.708e+07 m.
    Rp = 2.681 REarth. 

    Vitesse exoplanète Vp

    $$V_p = \tfrac{2 \times R_{star}}{\tau}$$

    On peut vérifier que l’on obtient:

    # ---- affichage console --- #
    Vp = 1.120e+05 m/s.
    Vp = 2382.170 V_merc.

    Rayon orbite planete

    $$r = \tfrac{G \times M_star}{V_p^2}$$

    Periode revolution

    $$T = \tfrac{2\pi \times r}{V_p}$$

    Format numérique:

    Une fois que l’on obtient T, en secondes, il peut être utile de représenter cette valeur en jours, heures, min, s:

    jours = T//(3600*24)
    h = (T-jours*24*3600)//3600
    m = (T-jours*24*3600-h*3600)//60
    s = T-jours*24*3600-h*3600-m*60
    print("{:3.0f} j, {:3.0f} h, {:3.0f} min {:3.2f} s".format(jours,h,m,s))
    # ---- affichage console --- #
    2 j,  11 h,  22 min 43.12 s

    Faire ces mêmes calculs pour chaque planète observable.

    Synthèse des résultats: fichier csv

    Les fichiers csv sont interopérables: on peut les editer avec un editeur de texte, ou un tableur. On peut les importer facilement pour un traitement en langage python.

    Utiliser un tableur

    • Les courbes de transit ont permis de mesurer les valeurs de profondeur de transit $\delta$ et de durée de transit $\tau$.
    • Ces valeurs seront reportées dans un fichier csv avec les autres informations sur les planètes et leur étoile. Utiliser un tableur. Attention à bien utiliser des points comme séparateur décimal.
    tableau rempli à l'aide d'un tableur

    tableau rempli à l'aide d'un tableur

    • Exporter (ou enregistrer) en format csv.

    On peut vérifier en ouvrant le fichier csv que les données sont mises dans un format particulier (séparation à l’aide d’un point virgule…)

    fichier csv

    fichier csv

    Import dans le notebook python

    • L’import avec la librairie pandas se fait de la manière suivante: (rien de plus simple)
    df = pd.read_csv('exoplanetes.csv',sep=';')
    df

    Suite

    La suite (étape 3) va demander un apprentissage d’une nouvelle structure de données: le dataframe. Cela représente plusieurs avantages:

    • la visualisation des données en table dans un notebook python,
    • la manipulation des données (creation de nouvelles colonnes calculées, projection, selection, …) qui est similaire au travail déjà vu sur les tables (SQL). Le langage diffère, mais l’esprit est le même.
    • L’utilisation des librairies de traitement de données est facilitée (seaborn, …)

    retour vers la page de présentation

    projet Dominos

    Jeu de Dominos avec interface graphique

    La programmation du jeu de Dominos a été réalisée dans cette séance. (sans interface graphique)

    Vous allez réaliser un jeu de Dominos avec l’interface Tkinter. A partir d’un fichier existant, vous allez ajouter des fonctionnalités utiles. Vous devrez collaborer efficacement et vous partager le travail équitablement.

    exemple de jeu

    exemple de jeu

    télécharger le fichier dominos_projet.py

    Consignes

    Il est demandé:

    • de rendre un programme fonctionnel, sur la base de celui fourni au départ. Le code du programme peut être divisé en 2 fichiers, si besoin.
    • le code du programme devra être correctement commenté et lisible.
    • Sur votre cahier de laboratoire: vous expliquerez quel a été votre rôle personnel dans la séance: Les choix que vous avez fait, les explications que vous voulez ajouter.

    Il se peut que l’editeur Spyder présente des problèmes avec la librairie TKinter. Le fichier dominos_projet.py peut ne pas s’executer. Choisir alors un autre editeur.

    Travail à réaliser

    Dans la classe Partie

    étape 1

    class Partie:
    	(...)
    
        def ajouter_fin(self,D):
            """
            ajoute l'objet domino D à la fin de la chaine:
            ajoute d'abord D à self.end.suiv
            puis D à self.end
            :param D: instance de Domino
            """
    
        def RAZ(self):
            """
            Détache le premier élement du reste de la chaine:
            met d'abord self.first.suiv à None
            puis self.end prend la valeur de self.first
            """
    
        def pose_correcte(self,val):
            """
            teste si le nouveau domino à poser est compatible avec le dernier de la chaine
            comparer alors val (équivaut à val1 0..6) du domino à poser avec val2 du dernier
            domino de la partie
            :param val: int
            :return: bool, True si les valeurs sont identiques
            """
            

    Compléter les fonctions ajouter_fin, et RAZà partir des informations contenues dans le script.

    étape 2

    Dans la classe Partie: Compléter la méthode de classe pose_correcte: celle-ci devra renvoyer True si le domino posé respecte la règle du jeu, à savoir que les nombres adjacents des 2 dominos sont identiques. Sinon, la fonction retourne False.

    étape 3: testez vos fonctions de la classe Partie

    Dans le programme principal if __name__ == '__main__'::

    Après la déclaration app = Game(partie1), ajouter les lignes suivantes:

        # ajouts
        D2 = Domino(4,3)
        print(partie1.pose_correcte(4)) # verifie si la pose 2:4 => 4:3 est OK
        partie1.ajouter_fin(D2) # ajoute le nouveau Domino D2
        print(partie1) # affiche le jeu dans la console
        app.dessine() # dessine le jeu dans la fenêtre TKinter

    Si tout se passe bien, vous devriez obtenir:

    True
    2:4  => 4:3

    Dans la classe Game

    étape 1

    • Comprendre comment on joue
    class Game(Tk):
    	(...)
    
        def readtext(self):
            """
            fonction appelée lorsque l'on valide avec le bouton VALIDER
            - lecture du contenu de la textBox avec le format de données
            2,4,[E O S N]
            soit valeur1,valeur2,direction
            alors valeur1 -> self.val1 et valeur2 -> self.val2
            direction -> self.dir
            - ou bien
            2,4
            soit valeur1,valeur2
            alors seuls les attributs self.val1 et self.val2 sont modifés
            self.dir n'est pas modifiée (E au debut)
            exemples:
            ---------
            - la textBox est validée avec: 4,2,S
            alors s vaut [4,2,S\n] et on ajoute le domino 4,2 à la partie 
            dans la direction S (Sud)
    		- la textBox est validée avec: 4,2
    		alors s vaut [4,2] et on ajoute le domino 4,2 à la partie sans
    		changer de direction
            """
            # lecture de la textBox
            result = self.textBox.get("1.0", "end")
            # decoupage de la chaine de caracteres selon les virgules
            s = str(result).split(',')
    
            # AJOUTER condition avec self.partie.pose_correcte(s[1])
            # tout le reste est declenché par condition == True
            # sinon: message d'erreur sur text_affichage qui demande de corriger
            self.text_affichage.set('DOMINO joué\n {},{}'.format(s[0],s[1]))
    
            
            self.partie.ajouter_fin(# a completer (1)
    
            print(self.partie)
    
    
            if len(s) > 2:
                self.dir = # à completer (2)
            
            self.dessine()
    • Au repère à completer (1): Completer la fonction ajouter_fin avec pour paramètre le nouveau Domino à poser.

    Il faut créer un nouvelle instance de Domino avec pour attributs int(s[0]) et int(s[1]), ce qui signifie Domino(int(s[0]),int(s[1]))

    • Au repère à completer (2): self.dir prend la valeur de str(s[2][0]), c’est à dire le premier caractère de s[2].

    étape 2

    Modifier la méthode de classe readtextde la classe Game pour tenir compte de la méthode pose_correcte de Partie: si la pose est correcte, et que la méthode self.partie.pose_correcte() retourne True, alors poser le domino sur la table de jeu. Sinon, demander de jouer un autre domino.

    Suite du projet

    La suite dependra de l’objectif visé.

    Le jeu de Dominos se joue avec un ensemble de 28 dominos:

    Le jeu peut démarrer avec un certain nombre de dominos affectés au joueur, ainsi qu’une pioche avec les dominos restants.

    Une extension du jeu pourrait permettre à 2 joueurs de jouer à tour de rôle. Cette extension du projet est plus complexe, car elle demande de programmer les objets de la fenêtre TKinter.

    Pygame Snake

    Jeu du Snake avec le module Pygame

    Pygame est une librairie Python apportant la SDL (Simple Directmedia Library), une bibliothèque libre multi-plateformes permettant la gestion du multimédia dans la programmation. Utile pour la programmation de jeux avec graphiques

    Ce projet consiste à realiser (en partie) le jeu Snake. Il traite des types abstraits personnalisés.

    Le Snake est un genre de jeu vidéo dans lequel le joueur dirige un serpent qui grandit et constitue ainsi lui-même un obstacle. Ce jeu est apparu pour la première fois en 1976 (Editeur Gremlin) sous le nom de Blockade. Les consoles de jeu à l’époque possédaient un CPU de 8-bit (MOS Technology 6507 @ 1.19 MHz) et une RAM de 128 octets. Depuis, le jeu a connu de nombreux clones.

    snake retro game

    snake retro game

    Le type serpent proposera pour interface les fonctions suivantes:

    • affiche
    • tete
    • ajoute_tete
    • supprime_queue

    Une version de ce projet sur microbit est accessible ici.

    Editeur

    Le module Pygame est installé sur votre ordinateur. Utilisez un IDE python comme IDLE ou pyzo.

    Script initial

    Le script suivant donne les éléments de base du programme.

    import pygame
    
     
    pygame.init()
     
    white = (255, 255, 255)
    black = (0, 0, 0)
    red = (255, 0, 0)
     
    dis = pygame.display.set_mode((800, 600))
    clock = pygame.time.Clock()
    
    game_over = False
     
    x1 = 300
    y1 = 300
     
    x1_change = 0       
    y1_change = 0
     
     
    while not game_over:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x1_change = -10
                    y1_change = 0
                elif event.key == pygame.K_RIGHT:
                    x1_change = 10
                    y1_change = 0
                elif event.key == pygame.K_UP:
                    y1_change = -10
                    x1_change = 0
                elif event.key == pygame.K_DOWN:
                    y1_change = 10
                    x1_change = 0
     
        x1 += x1_change
        y1 += y1_change
        dis.fill(white)
        pygame.draw.rect(dis, black, [x1, y1, 10, 10])
     
        pygame.display.update()
        clock.tick(30)
     
     
    pygame.quit()
    quit()

    Copier-coller celui-ci dans la fenêtre du fichier main.py.

    Creation d’un type abstrait serpent

    Le serpent est un objet qui stocke les données d’une certaine manière, et qui propose quelques fonctions utiles pour interragir avec lui (une interface). Il s’agit donc d’un type abstrait.

    Pour représenter le serpent, comme dans le jeu snake, les coordonnées des pixels du serpent seront stockées dans une Liste [(x1,y1),(x2,y2),...].

    Interface

    Vous allez programmer chaque fonction de l’interface à partir des renseignements suivants. Ces fonctions seront placées dans le proggramme, avant la boucle principale.

    • fonction affiche
    def affiche(S):
        # affiche tous les pixels du serpent
        # a partir de leurs coordonnees dans S
        # utilise une boucle for

    L’affichage de chaque pixel du serpent necessite une boucle bornée:

    for coord in serpent:
        x = coord[0]
        y = coord[1]
        pygame.draw.rect(dis, black, [x, y, 10, 10])
    • fonction tete
    def tete(S):
       # retourne les coordonnees x, y de la tete du serpent
       # qui sont stockees dans le dernier element S[-1]
       # sous la forme d'un tuple (x,y)
    • fonction ajoute_tete Il peut être necessaire d’ajouter un pixel au serpent. Celui-ci s’ajoutera à la fin de la liste de coordonnées:
    def ajoute_tete(S, x, y):
        # ajoute un tupple (x,y) a la fin de la liste S 
    • fonction supprime_queue

    A chaque déplacement, cela ajoute un pixel à la fin de la liste. Il s’agit de la tête du serpent. Il faut alors retirer le premier pixel (serpent[0]) si l’on veut que sa longueur reste constante.

    deplacement du serpent vers le bas

    deplacement du serpent vers le bas

    def supprime_queue(S):
        # decale toutes les valeurs de la liste S vers la gauche:
        # a l'aide d'une boucle bornee sur les indices i:
        # copie toutes les valeurs S[i+1] dans S[i]
        # puis supprime le dernier element

    Dans le programme main.py

    • Définissez une variable qui stocke les coordonnées du serpent: serpent = [(400,200),(400,210), (400,220), (400,230)]

    • Dans la boucle principale:

      • recuperer les coordonnées x1 et y1 de la tête du serpent (utiliser la fonction tete)
      • modifier les valeurs de x1 et y1 en fonction de la direction du deplacement
      • Ajoutez des conditions pour que le pixel ne sorte pas de l’écran. On peut faire changer de direction lorsque le bord de l’écran est touché par le pixel: if x1 > 800 or x1 < 0: ...
      • Ajouter les coordonnées du pixel x1, y1 à la fin de la liste serpent (ajoute_tete)
      • Supprimer le premier pixel du serpent, celui placé en serpent[0] avec supprime_queue
      • Afficher le serpent une fois ses coordonnées recalculées avec la fonction affiche.

    Le jeu devrait être à present fonctionnel.

    Créer un module

    Vous pouvez maintenant améliorer la mise en forme de votre programme: Mettre les fonctions de l’interface dans un nouveau fichier.

    Dans le fichier que vous nommerez utils.py, déplacer les fonctions: tete, ajoute_tete, et supprime_queue. (Sur Trinket, il suffira d’ajouter un nouvel onglet dans l’editeur python et de nommer cet onglet: utils.py).

    Pour faire référence à ces fonctions, il faudra ajouter la ligne suivante dans le programme main.py:

    from utils import *

    Questions

    1. Expliquer: Comment le programme gère les déplacements du serpent?
    2. Cette gestion des déplacements, est-elle facilitée par l’interface du type serpent? Si oui, comment?
    3. Quelles fonctionnalités du jeu manque-t-il pour que celui-ci soit complet?
    4. Si vous deviez créer le jeu complet:
    • quelles fonctions ajouteriez vous à l’interface serpent?
    • Quelle autre structure de données envisageriez-vous?

    Correction fichier main.py

    import pygame
    from utils import *
     
    pygame.init()
     
    white = (255, 255, 255)
    black = (0, 0, 0)
    red = (255, 0, 0)
     
    dis = pygame.display.set_mode((800, 600))
     
    game_over = False
     
    x1 = 300
    y1 = 300
     
    x1_change = 0       
    y1_change = 0
     
    clock = pygame.time.Clock()
    
    serpent = [(400,200),(400,210), (400,220), (400,230)]
    
    def affiche(S):
        # affiche tous les pixels du serpent
        # a partir de leurs coordonnees dans S
        for coord in S:
          x,y = coord
          pygame.draw.rect(dis, black, [x, y, 10, 10])
    
    while not game_over:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x1_change = -10
                    y1_change = 0
                elif event.key == pygame.K_RIGHT:
                    x1_change = 10
                    y1_change = 0
                elif event.key == pygame.K_UP:
                    y1_change = -10
                    x1_change = 0
                elif event.key == pygame.K_DOWN:
                    y1_change = 10
                    x1_change = 0
        x1, y1 = serpent[-1]
        x1 += x1_change
        y1 += y1_change
        
        if x1 > 800 or x1 < 0: x1_change = -x1_change
        if y1 > 600 or y1 < 0: y1_change = - y1_change
        
        ajoute_tete(serpent,x1,y1)
        supprime_queue(serpent)
        
        dis.fill(white)
        
        affiche(serpent)
        pygame.display.update()
     
        clock.tick(30)
    
    
    pygame.quit()
    quit()

    Correction fichier utlis.py

    import pygame
    def tete(S):
        # recupere les coordonnees x, y de la tete du serpent
        return S[-1][0], S[-1][1]
    
    def ajoute_tete(S, x, y):
        # ajoute un tupple (x,y) a la fin de la liste S
        S.append((x,y))
    
    def supprime_queue(S):
        # decale toutes les valeurs de la liste S vers la gauche:
        # copie toutes les valeurs S[i+1] dans S[i]
        # puis supprime le dernier element
        for i in range(len(S)-1):
            S[i] = S[i+1]
        S.pop()

    Microbit: Petit jeu de type Snake en 2D

    Se rendre à la page du TP de term NSI et approfondir la seance.

    Liens

    Ce TP est inspiré de la page www.edureka.co

    Jeu du Morpion

    Projet 1: jeu du Morpion

    Le jeu du Morpion est un jeu de réflexion se pratiquant à deux joueurs au tour par tour et dont le but est de créer le premier un alignement sur une grille (3x3).

    Vous allez programmer le jeu du Morpion contre l’ordinateur. L’ordinateur devra repondre à chacun des coups du joueur et, si possible, remporter la partie.

    Pour traiter ce projet, il est fortement recommandé de bien maitriser l’exercice 3.1, vues dans le TD sur les tableaux.

    On donne la fonction d’affichage de la grille:

    def affiche(grille):
        for ligne in grille:
            for case in ligne:
                print(case, '|', end=' ')
            print()

    Exemple: Afficher la grille

    morpion = [
        ['X', ' ', ' '],
        ['O', 'X', ' '],
        [' ', 'O', ' ']
    ]
    
    affiche(morpion)
    
    # affiche
    X |   |   | 
    O | X |   | 
      | O |   |

    Afin d’analyser la partie, et prevoir les prochains coups à jouer, l’ordinateur utilisera les fonctions suivantes, que vous devrez programmer:

    • compteur
    • victoire
    • cherche_car

    Prévoir ensuite le prochain coup à partir des informations fournies, et créez un jeu, où l’ordinateur ne sera jamais perdant.

    Compteur du nombre de caractères identiques

    Lire et tester le programme suivant:

    Exemple: Compte le nombre de X dans une ligne, colonne ou diagonale

    # Vérifier si la ligne 0 contient trois symboles identiques
    liste_X = [0,0,0]
    liste_Y = [0,1,2]
    compteur = 0
    for i in range(len(liste_X)):
        x = liste_X[i]
        y = liste_Y[i]
        if morpion[x][y] == 'X':
            compteur +=1
    print("il y a ", compteur, "cases X dans la ligne 0")

    Dans la boucle for, l’indice i varie de 0 à 2.

    Pour i=0, x a pour valeur liste_X[0] -> 0 et y a pour valeur liste_Y[0] -> 0. Le couple x,y vaut alors 0,0.

    On utilise ces coordonnées pour relever le symbole de la case morpion[0][0]. C’est un X. On augmente alors le compteur d’une unité (on compte les X).

    On continue dans la boucle for avec les cases 0,1 puis 0,2.

    Etape 1: Créer une fonction compteur qui prend une grille, un caractère car, une liste liste_X et une liste liste_Y en paramètres. Cette fonction devra retourner le nombre de fois que ce caractère car apparait.

    Exemple: utiliser la fonction compteur

    # Etape 1
    morpion = [
        ['X', 'O', 'X'],
        ['O', 'X', ' '],
        [' ', 'O', 'O']
    ]
    
    def compteur(grille,car,liste_X,liste_Y):
    	c = 0
    	for i in range(len(liste_X)):
    			# à completer 
    			x = ...
    			y = ...
    			if grille[][]...
    				c = c + ...
    		
    	return c
    
    compteur(morpion,'X',[0,0,0],[0,1,2])
    # retourne:
    2
    premiere étape de la boucle for

    premiere étape de la boucle for

    La fonction retourne 2: à la premiere ligne, il y a bien 2 caractères ‘X’.

    Utilisez votre fonction

    Etape 2: utilisez votre fonction pour déterminer le nombre de ‘X’ dans chacune des lignes, dans chacune des colonnes, et dans chacune des diagonales (8 appels de la fonction). Placer chaque valeur dans une liste L, puis afficher celle-ci.

    # Etape 2
    L = []
    L.append(compteur(morpion,'X',[0,0,0],[0,1,2]))
    L.append(compteur(...
    ...
    print(L)

    Victoire

    Etape 3: Créer une fonction victoire, qui prend une grille de morpion en paramètre, ainsi qu’un caractère car (qui vaut X ou O), et vérifie si la condition de victoire est réalisée pour le joueur X ou O. La fonction retournera un booléen True/False.

    Exemple: Victoire des X

    # Etape 3
    morpion = [
        ['X', 'O', 'X'],
        ['O', 'X', ' '],
        [' ', 'O', 'X']
    ]
    
    def victoire(grille,car):
    	b1 = compteur(grille, car, [0,0,0],[0,1,2])
    	b2 = compteur(grille, car, [1,1,1],[0,1,2])
    	# a completer
    	b8 = compteur(grille, ...)
    	return b1 == 3 or ...
    
    victoire(morpion,'X')
    # retourne:
    True
    victoire(morpion,'O')
    # retourne:
    False

    Detection case vide [niveau Term NSI]

    Etape 4: Ecrire une fonction cherche_car(grille,car,liste_X,liste_Y) qui verifie si les cases de coordonnées (liste_X[0], liste_Y[0]), (liste_X[1], liste_Y[1]), (liste_X[2], liste_Y[2]) contiennent au moins un symbole car, et retourne les coordonnées de la première case contenant le caractère car.

    Exemple: recherche d’un espace ’ ’ dans la ligne 2

    # Etape 4
    morpion = [
        ['X', 'O', 'X'],
        ['O', 'X', ' '],
        [' ', 'O', 'O']
    ]
    
    def cherche_car(grille,car,liste_X,liste_Y):
    	for i in range(len(liste_X)):
            x = liste_X[..
            y = liste_Y[..
            if grille[..][..] == ...:
                return x,y
    
    cherche_car(morpion,' ',[2,2,2],[0,1,2])
    # retourne:
    (2,0)

    La fonction retourne (2,0), car à la case de coordonnées [2][0], il y a un symbole ' '.

    recherche d'un caractère espace ' ' dans la dernière ligne

    recherche d'un caractère espace ' ' dans la dernière ligne

    Exemple: recherche du premier espace ’ ’ dans tout la grille

    morpion = [
        ['X', 'O', 'X'],
        ['O', 'X', ' '],
        [' ', 'O', 'O']
    ]
    
    cherche_car(grille,' ',[0,0,0,1,1,1,2,2,2],
                           [0,1,2,0,1,2,0,1,2])
    (1,2)

    Lorsque l’on recherche un caractère dans TOUTE la grille, il y a 9 coordonnées à renseigner pour chacune des listes.

    Stratégie de l’ordinateur [Niveau Term NSI]

    Etape 5: créer une fonction jeu_de_defense, qui prend pour paramètre grille, et car_attaquant, qui vaudra ‘X’ ou ‘O’.

    Cette fonction va permettre de programmer le jeu complet, pour jouer contre l’ordinateur.

    Pour chacune des lignes, puis pour chacune des colonnes, et enfin chaque diagonale:

    Si la ligne contient 2 caractères ‘X’ (fonction compteur, et que la ligne contient un espace (cherche_car ne retourne pas None), alors retourner les coordonnées x,y retournées par la fonction cherche_car.

    Sinon, retourner None

    def jeu_de_defense(grille,car_attaquant):
    
        if compteur(grille,car_attaquant,
                    [0,0,0],[0,1,2]) == 2 and cherche_car(grille,' ',
                    [0,0,0],[0,1,2]) != None:
            # jouer dans une case vide de la ligne 0
            jouer_case = cherche_car(grille,' ',
                    [0,0,0],[0,1,2])
        elif compteur(grille,car_attaquant,
                    [1,1,1],[0,1,2]) == 2 and cherche_car(grille,' ',
                    [1,1,1],[0,1,2]) != None:
            # jouer dans une case vide de la ligne 1
            jouer_case = cherche_car(grille,' ',
                    [1,1,1],[0,1,2])
        elif (...)
        (...)
    
        elif compteur(grille,car_attaquant,
                    [0,1,2],[0,0,0]) == 2 and cherche_car(grille,' ',
                    [0,1,2],[0,0,0]) != None:
            # jouer dans une case vide de la colonne 0
            jouer_case = cherche_car(grille,' ',
                    [0,1,2],[0,0,0])
        (...)
    	else:
    		jouer_case = None
        return jouer_case

    Pour appeler la fonction, et bloquer l’adversaire ‘X’, faire:

    if jeu_de_defense(morpion,'X') == None:
        x,y = cherche_car(grille,' ',[0,0,0,1,1,1,2,2,2],
                                      [0,1,2,0,1,2,0,1,2])
    else: 
        x,y = jeu_de_defense(morpion,'X')

    Ainsi, si aucune des lignes, colonnes, diagonale ne correspond ne contient deux caratères ‘X’ alignés, retourner la premiers case vide trouvée dans la grille: ce sera l’emplacement où l’ordinateur ‘O’ peut jouer.

    L’ordinateur peut alors jouer:

    def jouer(grille,car,x,y):
        grille[x][y] = car
        
    jouer(morpion,'O',x,y)
    affiche(morpion)

    Pour élaborer une stratégie plus avancée de l’ordinateur, on pourra consulter la page dédiée: site tictactoe.com

    site TICTACTOEFREE.COM

    site TICTACTOEFREE.COM

    Une ouverture possible sur la suite du programme de terminale peut aussi vous amener à consulter l’algorithme du minimax: page wikipedia

    Interface joueur

    Pour cette deuxième phase du projet, vous pourrez télécharger le script python contenant toutes les fonctions nécéssaires: telecharger

    Vous allez maintenant programmer l’interface du joueur, en lui demandant les coordonnées x,y où il placera son pion 'X'. La grille de morpion devra être modifiée en fonction de son choix, à condition que la case contienne bien ’ ‘.

    # Etape 6
    Fin_de_partie = False
    while not victoire(morpion,'X') and not victoire(morpion,'O') and not Fin_de_partie:
    	affiche(morpion)
    	x = int(input("jouer à la ligne (0,1,2), 3=Fin :"))
    	y = int(..)
    	...
    • Pour jouer contre l’ORDINATEUR. (utiliser la fonction jeu_de_defense pour prevoir la case dans laquelle il devra jouer).
    • Organisez au mieux votre script. Commentez vos fonctions.
    • Prévoir et anticiper toutes les erreurs possibles de saisie du joueur, tous les defauts possibles qui peuvent survenir dans la partie (plus de O que de X, erreurs avec les coordonnées saisies, terminaison de la boucle while, …). On pourra ajouter des structures conditionnelles supplémentaires, ou bien des tests d’assertion, ou autres mécanismes. (try.. except, raise,…): Voir cours sur la mise au poin d’un programme: python avancé
    • Utiliser une structure de données Pile pour permettre un retour en arriere (le joueur efface ses coups précédents).

    Projet 2: jeu du Sudoku [Term NSI]

    Le jeu du Sudoku est une jeu de reflexion utilisant une grille (9x9).

    Le but du jeu appelé Sudoku, est de remplir la grille avec une série de chiffres tous différents, qui ne se trouvent jamais plus d’une fois sur une même ligne, dans une même colonne ou dans une même région (également appelée « bloc », « groupe », « secteur » ou « sous-grille »).

    Vous allez proposer une grille au joueur, partiellement remplie.

    A chaque tour de jeu:

    • Demander au joueur les coordonnées de jeu dans la grille, ainsi que le chiffre à placer. Le joueur ne peut joueur que dans une case contenant déjà un zero, pas une autre valeur.
    • Si le joueur choisit un chiffre et un emplacement qui génèrent un doublon, alors informez du problème rencontré.
    • Demandez lui s’il valide son choix (on modifie alors la grille), ou s’il ne veut pas valider (on laisse le zero).
    • Vérifier si la grille est gagnante.
    • Demander au joueur s’il continue la partie, ou s’il veut revenir en arrière (on remet les zeros aux emplacements modifiés, en remontant selon une PILE).
    • On recommence avec un nouveau tour de jeu.

    Vous allez programmer les fonctions qui vont vérifier, à chaque essai du joueur, si les chiffres placés (autres que 0) sont tous différents:

    • dans les différentes lignes: fonction check_lignes
    • dans les différentes colonnes: fonction check_col
    • et dans les différentes regions (blocs 3x3): check_blocs

    Vous devrez aussi programmer une fonction qui verifie si la grille est entièrement, et correctement remplie: check_victoire

    Le joueur aura la possibilité de revenir en arrière (un ou plusieurs coups), et poursuivre la partie.

    exemple de grille et solution

    exemple de grille et solution

    Il est fortement recommandé d’utiliser les fonctions de l’exercice 3.2, vues à la page des exercices sur les tableaux.

    Pour les élèves de Terminale:

    • Organisez au mieux votre script. Commentez vos fonctions.
    • Prévoir et anticiper toutes les erreurs possibles de saisie du joueur, tous les defauts possibles qui peuvent survenir dans la partie (plus de O que de X, erreurs avec les coordonnées saisies, terminaison de la boucle while, …). On pourra ajouter des structures conditionnelles supplémentaires, ou bien des tests d’assertion, ou autres mécanismes. (try.. except, raise,…): Voir cours sur la mise au poin d’un programme: python avancé
    • Utiliser une structure de données Pile pour permettre un retour en arriere (le joueur efface ses coups précédents).
    • Algorithme du minimax: page wikipedia

    arts numeriques

    Arts numériques

    Explorer le sujet

    La page suivante montre quelques possibilités de dessins réalisés avec le module turtle. Ces dessins sont plutôt dirigés vers la réalisation de fractales: l’idée est de reproduire un même motif à différentes échelles, pour obtenir une image d’ensemble. Le script utilisé peut être recursif.

    Mais ce n’est pas le seul type de réalisation possible avec un algorithme.

    Le dessin algorithmique va permettre:

    • de dessiner, répéter, ou de remplir la page avec une grande précision (pavages, angles droits, …)
    • de gérer les proportions dans l’image, dans le remplissage, la position des éléments dans la page
    • d’ajouter du désordre calculé dans le motif
    • …
    Piet Mondrian/ Composition en rouge, jaune, bleu et noir / 1926

    Piet Mondrian/ Composition en rouge, jaune, bleu et noir / 1926

    Les compositions de Piet Mondrian sont créées de façon à être parfaitement équilibrées, que chaque élément soit justifié et que ses toiles relèvent d’une harmonie parfaite entre les lignes et les couleurs

    Piet Mondrian COMPOSITION EN COULEUR A, 1917

    Piet Mondrian COMPOSITION EN COULEUR A, 1917

    Vera Molnar

    Vera Molnar

    Suggestion de projet

    La réalisation d’une ou plusieurs oeuvres artistiques à l’aide d’un algorithme devra s’accompagner d’un guide de lecture et compréhension de l’oeuvre. Montrer également quels sont les ingrédients de programmation choisis. Et discuter de l’efficacité de celui-ci, en rapport avec la complexité algorithmique.

    Liens

    • Piet Mondrian wikipedia considéré comme l’un des fondateurs de l’art abstrait. Il peint des plans rectangulaires de dimensions variables, et aux couleurs dites pures.

    • Vera Molnar wikipedia en 1967, elle co-fonde le groupe Art et Informatique à l’Institut d’Esthétique et des Sciences de l’art de Paris. C’est dans ce cadre qu’elle réalisera ses premiers travaux sur un ordinateur.

    « Son art, conduit de façon expérimentale, porte sur la forme, sa transformation, son déplacement, sa perception. Son travail s’accompagne d’une intense réflexion théorique sur les moyens de la création et les mécanismes de la vision. »

    ABR applications

    ABR: sujet 1

    Vous programmez un jeu narratif, ou le personnage peut collecter, gagner ou perdre des objets. Il possède ainsi un (très) grand sac à dos. Pour représenter ces objets, vous les numérotez (à l’aide d’une clé) d’une manière qui permettra de facilement les retrouver. Vous placerez ces clés dans un arbre binaire de recherche lorsque le personnage gagne l’objet. Et vous retirerez cette clé lorsqu’il perd l’objet.

    Vous aurez besoin ainsi de 2 structures de données:

    • l’ABR pour ranger les clés
    • un tableau pour placer les couples clé,nom_de_l_objet

    Pour organiser votre sac à dos, les clés possèderont un code commun (voir exercice de bac pages 7,8) lorsqu’il s’agit d’une même famille d’objets. Par exemple, le couteau et le glaive pourraient être codés de la manière suivante:

    • '01100001', 'couteau'
    • '01100010', 'glaive'

    Les 4 premiers caractères de la clé, 0110 codent alors les armes de contact.

    On peut imaginer d’autres rubriques, et d’autres codes, pour classer les différents objets.

    Etape 1: Créer un programme qui place les très nombreux objets du sac à dos dans un ABR.

    Etape 2: Programmez les fonctions qui permettent:

    • d’ajouter un nouvel objet
    • de retirer un objet du sac à dos
    • d’afficher la liste des objets du sac à dos, pour une famille d’objets donnée.

    ABR: sujet 2

    vue d'artiste de la bibliothèque de Babel

    vue d'artiste de la bibliothèque de Babel

    La célèbre bibliothèque infinie de Jorge Luis Borges issue de son récit La bibliothèque de Babel a été récemment modélisée par un certain Jamie Zawinski, d’après la description faite au début du récit.

    Imaginez une bibliothèque contenant un extrêmement grand nombre de livres. Cette bibliothèque est organisée de la manière suivante :

    Il y a des milliers de pièces différentes.

    Chaque pièce est repérée par une suite de trois lettres, et dans cette pièce sont rangés tous les livres dont les titres commencent par ces trois lettres.

    Chaque pièce possède deux sorties, une à droite et une à gauche.

    La sortie de gauche mène soit à une salle dont les trois lettres sont situées avant dans l’ordre alphabétique, soit nulle part.

    La sortie de droite mène soit à une salle dont les trois lettres sont situées après dans l’ordre alphabétique, soit nulle part.

    Une représentation de cette bibliothèque peut être donnée sous la forme d’un arbre binaire tel que le suivant :

    exemple de placement des données dans un ABR. Ordre alphabetique

    exemple de placement des données dans un ABR. Ordre alphabetique

    Questions:

    1. Combien de pieces différentes pourrait comporter cette bibliothèque, si celle-ci devait représenter toutes les combinaisons de clés de 3 lettres possible?
    2. Où se placerait la salle de clé KRO?

    Etape 1: Le projet pourrait consister à établir une liste de clés, dans un fichier. Chaque ligne sera constituée de la clé, ainsi que d’un mot dont les premières lettres débutent par cette clé. (une table de hashage). Il n’est pas necessaire d’être exhaustif, et d’envisager toutes les clés existantes.

    Etape 2: Vous placerez ces clés dans un arbre binaire de recherche, avec pour information à chaque noeud le couple (clé,ligne_dans_la_table)

    Etape 3: Programmez la fonction qui permet de trouver une clé dans l’ABR, puis de retrouver les informations correspondantes dans la table.

    ABR: sujet 3

    Programmer un index inversé pour les mots d’un roman.

    Lire sur gutenberg.org

    Lire sur gutenberg.org

    L’énoncé complet se trouve ici: people.montefiore.uliege.be

    Etape 1: Ouvrir les 10 premières pages du roman The Time Machine de H.G. Wells avec les outils python (fonction open). Utiliser un compteur de phrases et de mots. Chaque mot sera associé à une position dans le texte du type (numero_phrase, numero_mot_dans_la_phrase)

    Etape 2: Placer alors tous les mots dans un ABR au fur et à mesure de leur apparition. La donnée stockée dans le noeud de l’arbre sera constituée d’une paire (clé,valeur), où la clé est le mot, la valeur est la position dans le texte pour sa première occurence.

    Etape 3: Utiliser une table pour placer toutes les occurences de chaque mot. La donnée stockée dans chaque noeud servira maintenant à retrouver la position de cette information dans la table et sera constituée du couple: (mot,ligne_dans_la_table).

    Outils

    Liens

    Grand oral

    Le Grand Oral

    Découvrir l’épreuve du Grand Oral

    Présentation de l’épreuve et Foire aux Questions: http://quandjepasselebac.education.fr/faq-grand-oral/

    La durée de l’epreuve est de 20 minutes, partagés en:

    • 10 min d’exposé oral.
    • 10 min d’entretien

    Construire sa question en rapport avec la spécialité NSI

    L’élève doit proposer 2 questions au jury, qui choisira celle qui sera presentée par le candidat. Ces questions portent obligatoirement sur les 2 spécialités de terminale, en combinaison. (une spécialité par question, ou 2 specialités représentées sur l’une des 2 questions, et une ou deux spé pour la 2e question).

    Grand Oral et enseignement de spécialité NSI (MEN)

    lien vers la ressource

    Résumé:
    L’énoncé de la question est le point final d’une réflexion qui fait l’objet d’un temps de maturation. Ce travail est progressif et s’affine avec l’avancée du programme et l’appropriation des notions.

    Elle s’appuie sur des connaissances acquises lors de l’enseignement scolaire et permet de se projeter vers la poursuite des études dans l’enseignement supérieur.

    Lors de l’entretien, le jury voudra vous faire developper des points de votre presentation orale. Il y aura alors un contrôle des connaissances evoquées, en lien avec la matière. Il peut aussi y avoir un échange sur le projet d’orientation du candidat, et sur la maturation de celui-ci. Cette construction personnelle rend authentique le propos. Il permet à l’élève d’y associer ses préoccupations personnelles et sociales, ses engagements, ses réflexions sur l’avenir, etc.

    Voici une liste de thèmes dans lequel vous pourrez concevoir votre Question.
    Le document propose 45 questions, partagées sur ces thèmes. Cette liste n’est bien sûr absolument pas limitative.

    • L’histoire de l’informatique
    • Langages et programmation
    • Données structurées et structures de données
    • Algorithmique
    • Bases de données
    • Architectures matérielles, systèmes d’exploitation et réseaux
    • Interfaces Hommes-Machines (IHM)
    • Impact sociétal et éthique de l’informatique

    https://eduscol.education.fr/media/3919/download

    LeRobert.com: Grand Oral

    Lien vers la ressource

    Le document traite 3 questions. Vous comprendrez la méthodologie attendue pour en construire la réponse:

    • « Les ruches connectées vont-elle sauver les abeilles ? »
    • « Comment faire apprendre un robot ? »
    • « Comment partager des biens culturels ? »

    Les sites des editeurs

    Les éditeurs publient des pages sur l’épreuve, d’autres exemples de sujets, et des liens pour approfondir les thèmes.

    Par exemple, le site LeLivreScolaire propose dans cette page des exemples de Questions combinant Mathématiques et NSI.

    Ressources

    Vous êtes dans une phase de construction du savoir, sur un enseignement qui est nouveau (pour vous). Il est important de commencer à explorer les articles de journaux plus généralistes qui vont assurer votre base de connaissances, et approfondir votre réflexion…

    Voici les principales ressources pour explorer les articles sur les thèmes de l’informatique. Un recueil et résumé des articles les plus recents sont mis sur la page thématiques

    Le blog Binaire

    Le blog du Monde sur l’informatique avec la société informatique de France (SIF).

    https://www.lemonde.fr/blog/binaire/

    Contenu Vous y trouverez, des articles de vulgarisation, des entretiens autour de l’informatique et des questions qu’elle soulève. Vous y trouverez aussi la rubrique « Petit binaire » pour les plus jeunes, mais pas seulement…

    Autres médias

    La chronique numérique du journal la recherche:

    https://www.larecherche.fr/rubrique/chronique-num

    Chronique éthique de Jean-Gabriel Ganascia:

    https://www.larecherche.fr/rubrique/chronique-%C3%A9thique

    Le 21e Siècle

    http://www.21siecle.quebec/ : le numérique et ses implications à destination des non informaticien·nes : Internet, communication, connaissances, le citoyen et la citoyenne, la société.

    Le site de l’ONISEP

    POURQUOI ? Pour réfléchir aux métiers du numérique et aux possibles parcours d’orientation

    NSI prem

    Agenda

    Semaine du 01/09/26

    • La spécialité NSI: pdf
    • Présentation: Performance des machines pdf
    • Architecture 1: Cours, la mémoire des machines pdf
    • TP sur la numération au cours des âges Lien
    • TD1, fiche sur la numeration binaire pdf

    Semaine du 08/09/26

    • Fiche d’exercices TD1 sur la numération: pdf
    • TP1 Python, les types de base: Lien

    Semaine du 14/09/26

    • Architecture 2: Cours, Comment fonctionne un ordinateur? pdf
    • Presentation, Univ Laval, les Bus pdf, pages 20 et plus.
    • Cours sur la représentation des entiers naturels et relatifs: Lien
    • TD2, fiche sur la représentation des entiers naturels et signés: pdf
    • TP2 Python, les variables et opérations: Lien

    Semaine du 21/09/26

    • Cours sur l’architecture Von Neumann et les composants du processeur: Lien, et version pdf
    • TP3a python, les structures conditionnelles: Lien

    Semaine du 28/09/26

    • Cours et exercices sur les bases en python (pour TP2 et TP3): pdf, et corrigé
    • TP3b python, Lien

    Semaine du 14/10/26

    • TP4 Boucles for: Lien
    • Tri et recherche algorithmes de recherche et de tri, complexité algorithmique jeu du juste prix 0-100 Le Juste Prix Deviner Vous devez rentrer un nombre. jeu du juste prix 0-1000 Le Juste Prix Deviner Vous devez rentrer un nombre. data analyse regression linéaire, prediction, KNN algorithmique avancé rendu de monnaie, algorithme glouton
    • memoires, processeur, modèle Von Neumann, composants logiques, loi de Moore, assembleur
    • binaire, hexadecimal, entiers signés, nombres à virgule flotante, codage numérique des caractères des images et de l’information
    • modele OSI modele en couches, encapsulation, numeros et adresses protocoles protocoles IP, TCP, DNS, exercices TP simulation d’un réseau du reseau local au reseau internet, adressage, routage, client, serveur, DNS protocole HTTP role du navigateur, methodes GET et POST TP GET POST cookies formulaire, methode GET POST, outil reseau du dev, navigateur tuto requests application des connaissances sur le protocole HTTP, données open source, creer une app en python utilisant des requetes en temps reel
    • Cours - les bases en python résumé de cours python Editeur Turtle Turtle Tkinter les bases Tkinter les bases Tkinter demineur Tkinter demineur IHM python Cours Du séquentiel à l’événementiel, pygame, fenetre graphique, calques dictionnaires pour inventaire utilite des dictionnaires pour mon Escape Game projet Pygame projet pygame images numeriques format matriciel, module PIL, drapeaux pays
    • HTML cours HTML, navigateur, balises css les bases les bases en CSS les bases en javascript bases en javascript, console javascript, objets, methodes javascript DOM javascript dans le code de la page, DOM, variables, types, boucles, procedures, fonctions serveur Flask pages web avec server python flask, traitement du formulaire
    • projet bases en python chaines str, types simples, boucles, conditions, random exos tableaux listes python TP listes, tableaux, matrices Jeu du Morpion projet utilisant les tableaux python

    Sous-sections de NSI prem

    Sous-sections de algorithmes

    Tri et recherche

    Pourquoi écrire des algorithmes? Pour resoudre un problème, comme trier une liste par ordre croissant, un humain y parviendra avec de l’observation, de l’intuition. Il sera peut être difficile d’expliquer sa demarche. Alan Türing (1912-1954), le père de la machine de Türing, cherche à réduire cette part d’intuition en mettant en place un algorithme, qui va guider sa machine, de manière mécanique, jusqu’à la résolution. Les machines n’ont pas d’intuition….

    Algorithmes de recherche et de tri

    Deux familles d’algorithmes fortement liées:

    Algorithmes de recherche: essentiels pour les bases de données. Par exemple: de l’identifiant du client pour retrouver la fiche client. L’algorithme le plus simple est celui de la recherche séquentielle.

    Algorithmes de tri: la recherche dichotomique sur une table déjà triée va être beaucoup plus efficace que la recherche sequentielle sur une table non triée

    Les 2 méthodes de recherche

    • Cas n°1: données non triées

    Enoncé: Supposons que notre liste contienne des valeurs (des cartes) issues d’un paquet mélangé (non triées). On cherche dans cette liste la carte du 2 de pique. On part de la carte la plus à gauche, et on remonte la liste vers la droite jusqu’à trouver cette carte (ou ne rien trouver si elle n’est pas dans la liste). La fonction de recherche retournera l’indice i si celle-ci est trouvée, -1 sinon. Il s’agit d’une recherche séquentielle.

    • Cas n°2: données triées

    Enoncé: Supposons cette fois que la liste contient cartes triées dans un ordre croissant. On cherche le 2 de carreau. On commence par la valeur (carte) du milieu de la liste. Si la carte du milieu de la liste est supérieure à cette carte, on réduit la liste à sa moitié gauche, et on prend à nouveau l’indice du milieu… On procède ainsi, par elimination de la moitié gauche ou droite de la liste jusqu’à trouver la carte (ou ne pas trouver si celle-ci n’y est pas, et que l’on a reduit le paquet à une seule carte). Il s’agit d’une recherche dichotomique.

    Recherche séquentielle

    Autre exemple

    Imaginez un jeu où votre adversaire doit deviner le nombre que vous avez en tête.

    Votre adversaire connait les bornes entre lesquelles vous avez choisi votre nombre.

    A chacune de ses propositions, vous lui répondez VRAI ou FAUX, sans autre aide. S’il doit deviner un nombre entre 1 et 100, dans le PIRE des CAS, il peut proposer jusqu’à 100 nombres pour trouver la bonne valeur que vous avez en tête.

    Et si la plage de recherche fait n valeurs, le nombre d’essais peut aller jusqu’à n propositions. On dit que la complexité algorithmique pour résoudre ce problème (trouver la valeur en parcourant tous les nombres possibles), est O(n). C’est-à-dire une classe de complexité linéaire. Il existe un algorithme plus efficaces, comme celui de recherche par dichotomie, dont la complexité est O(log(n)).

    Cette différence d’efficacité entre fonctions de n (taille du paramètre d’entrée) est d’autant marquée que le nombre n est grand.

    Ce problème s’apparente à celui de la recherche séquentielle dans une table:

    T: liste d'elements
    X: element a trouver dans la liste 
    
    Fonction recherche1(X,T)->Booleen:
        i = 0
        Tant que i < len(T) et T[i] != X:
            i = i + 1
        Fin
        Si i == len(T):
            Retourner False
        Sinon:
            Retourner True
    
    > recherche1(10, [0,2, 4, 6, 8, 10])
    True
    > recherche2(9, [0,2, 4, 6, 8, 10])
    False

    -> fiche de TD à compléter

    Recherche dichotomique

    Pour l’aider, vous l’aidez à chacun de ses essais en déclarant PLUS (le nombre que vous avez en tête est plus grand), ou MOINS (plus petit).

    Une fois que le nombre a été deviné, vous lui annoncez le nombre d’essais. Ce nombre est souvent inférieur au nombre d’essais pour la recherche séquentielle.

    L’algorithme que vous utilisez peut s’écrire en langage naturel:

    fonction devine_un_nombre(borne_inf: entier, borne_sup: entier) -> c: entier
      var N: entier[borne_inf .. borne_sup] <- tirage_aleatoire(borne_inf, borne_sup)
      var c: entier <- 0 # compteur du nombre d'essais
      var p: entier[borne_inf .. borne_sup] <- -1 # valeur proposée par l'adversaire
      tant que p != N faire:
        p <- saisie("quel nombre proposes tu?")
        c <- c + 1
        si p > N alors:
          afficher("c'est moins")
        sinon si p < N alors:
          afficher("c'est plus")
        sinon:
          afficher("bravo c'est gagné")
      fin
      retourner c

    Questions:

    1. Faire plusieurs parties avec pour bornes: [0 .. 100]. Quelle est la valeur de c dans chaque cas?
    2. Quelles sont les puissances m et n de 2 qui encadrent la valeur $2^n < 100 < 2^m$?
    3. Jouer à ce même jeu, mais avec les bornes: [0 .. 1000]
    4. Comparer c avec n et m tels que $2^n < 1000 < 2^m$

    Le jeu auquel vous avez joué est celui d’une recherche dichotomique. Vous avez cherché un élément (une valeur) dans un ensemble trié (l’ensemble des entiers [0 ..100])

    COURS: recherche linéaire

    Def: La recherche dans une liste consiste à trouver un élément x dans cette liste, et retourner l’indice de x. Cet algorithme consiste à observer les valeurs de la table, l’une après l’autre, jusqu’à trouver la valeur cherchée x, ou arriver au bout de la table.

    Dans le cas d’une table non triée, seul l’algorithme de recherche linéaire est susceptible de donner un resultat.

    L’algorithme suivant retourne l’index de x, ou bien -1 si x n’est pas dans la liste.

    def recherche1(T, x)->int:
      """
      :param T: list of elements
      :param x: element
      :return: int, index of x in the list
               else -1
      """
      i = 0
      while i < len(T) and T[i] != x:
        i = i + 1
      if i == len(T):
        return -1
      else: 
        return i

    Questions

    1. Que retourne l’instruction suivante: recherche1([i for i in range(0,10,2)], 8)?
    2. Que retourne l’instruction suivante: recherche1([i for i in range(0,10,2)], 10)?

    Efficacité de la recherche linéaire

    Def: L’efficacité est mesurée par la COMPLEXITE: La complexité mesure le nombre d’opérations effectuées par la fonction. Ce nombre d’opérations dépend des valeurs des paramètres, mais aussi de la taille de ces paramètres. C’est pourquoi, il est d’usage de considérer plusieurs cas pour mesurer l’efficacité. Elle est en général exprimée comme une fonciton de n, où n est la taille de la liste passée en paramètre.

    Quelles sont les opérations que l’on comptabilise? Pour les algorithmes de recherche, ce sont les opérations de comparaisons, dans la boucle non bornée:

    while i < len(T) and T[i] != x

    Il y a 2 comparaisons par itération: celle de l’opérateur > et celle de =.

    On peut définir ce que l’on appelle le pire des cas. Pour une taille n de la liste, les éléments sont rangés de telle sorte que le nombre d’opérations effectuée est maximum. Pour la recherche linéaire, c’est lorsque l’élément x ne se trouve pas dans la liste.

    Dans ce cas, le nombre d’opérations de comparaisons est égal à $2 \times n$. Pour simplifier, on dira que ce nombre d’opérations est égal à n.

    La complexité est dite linéaire (proportionnelle à N). Le coefficient $2 \times N$ n’a pas d’importance.

    COURS: Recherche dichotomique

    Def: La recherche dichotomique est l’algorithme le plus efficace lorsque la table dans laquelle on recherche une valeur est triée. Cette recherche consiste à diviser par 2 l’ensemble de recherche. Pour cela, on définit le milieu de l’intervalle de recherche, puis on conserve:

    • T[borne_inf : milieu-1] si x < T[milieu]
    • T[milieu +1 : borne_sup] si x > T[milieu]
    comparaison du nombre d'essais. Recherche par dichotomie vs recherche sequentielle. wikipedia

    comparaison du nombre d'essais. Recherche par dichotomie vs recherche sequentielle. wikipedia

    Exemple: On recherche un mot commençant par la lettre c dans un dictionnaire contenant 26 mots. Chaque mot commence par une lettre différente. La première de chaque mot du dictionnaire est dans l’ensemble [a .. z]. Le dictionnaire est trié par ordre lexicographique.

    Il s’agit d’une liste du type ['a','b','c','d', ..'m', ..,'x','y','z'].

    Comme il s’agit d’une liste dont les indices vont de 0 à 25: Le milieu, c’est 25//2 soit 12. la lettre c a un rang inférieur à 12 (lettre m). Donc, dans une première étape de recherche, on prendra la liste entre les rangs 0 et 11 pour rechercher c.

    def recherche_dicho(T,x):
        """
        :param T: sorted list of elements
        :param x: element
        :return: int, index of x in the list
               else -1
        """
        i_min = 0
        i_max = len(T) - 1
        while (i_max >= i_min):
            mid = (i_min + i_max)//2
            if T[mid] == x:
                return mid
            elif T[mid] < x:
                i_min = mid +1
            else:
                i_max = mid -1
        return -1

    Terminaison de la fonction de recherche dichotomique

    Dans le pire des cas, l’intervalle va se réduire jusqu’à se limiter à un seul élément. Celui dont l’index est mid. Avec i_min == i_max

    Si l’élément recherché est dans la liste: Cet élément est alors la valeur recherchée x, et la fonction se termine en retournant la valeur de l’index de x dans la liste, mid.

    Si l’élément recherché n’est pas dans la liste: alors, soit i_min prend la valeur de mid+1, soit i_max prend la valeur de mid-1. On a alors i_min > i_max, qui est la condition d’arrêt de la boucle.

    Efficacité de la recherche dichotomique

    Le nombre d’opérations de comparaison, dans le pire des cas, est proportionnel à log(n). n étant égal à la taille de la liste. Et log(n) étant egal au nombre de divisions par 2 qu’il faut effectuer pour que n arrive à 1:

    100 -> 50 -> 25 -> 13 -> 7 -> 4 -> 2 -> 1 (6 à 7 divisions)

    On dit que la complexité est logarithmique.

    Algorithmes de tri

    Definition: un algorithme de tri permet d’organiser une collection d’objets selon une relation d’ordre. wikipedia.

    Nous nous intéressons ici aux méthodes de tri en place: On modifie directement le tableau à trier en permuttant des éléments, sans créer de nouveaux tableaux.

    Le tri peut être effectué avec des éléments numériques. Mais il peut aussi être effectué avec des caractères. On parle alors de tri lexicographique.

    On a vu deux algorithmes de tri: le tri par insertion, et le tri par selection. Le langage Python possède une fonction de tri native: sorted, et une méthode de tri associée aux listes: sort.

    Le tri par insertion

    Principe

    Principe: Pour cet algorithme, trier, c’est déplacer des éléments, et y insérer l’élément rangé, depuis le debut déjà trié de la liste, jusqu’à la fin. Voir le detail dans le cours de terminale NSI

    Exemple d’algorithme

    Pour chaque carte de la donne :
      Regarder à la fin de la main triée
      Mémoriser la clé de cette carte
      Tant que la nouvelle carte va avant la carte de la main triée :
        Avancer le regard d’une carte vers la gauche dans la main triée
      Fin tant que
      Insérer la nouvelle carte à gauche de la carte de la main triée qu’on vient de regarder
    Fin pour chaque

    Question: représenter la main du joueur lorsqu’il reçoit les cartes 6, puis 9 puis Valet. Il utilise l’algorithme de tri par insertion pour les classer. Il possède au debut de la partie: 8, 10, Dame, Roi, As

    Programme python

    def tri1(table):
        for i in range(1,len(table)):
            temp = table[i]
            k = i
            while k>0 and table[k-1]>temp:
                table[k]=table[k-1]
                k-=1
            table[k]=temp
        return table

    Question: quelle partie du programme python correspond à:

    Tant que la nouvelle carte va avant la carte de la main triée :
        Avancer le regard d’une carte vers la gauche dans la main triée

    Efficacité du tri par insertion

    La mesure la durée d’execution de l’algorithme pour une liste donnée s’appelle la complexité. C’est une mesure en unités de temps. La complexité depend de la taille de la liste. C’est donc une fonction de n, tel que n = len(L).

    Pour expérimenter la mesure de cette durée, aller sur pythontutor.

    Voici le script utilisé:

    from random import sample
    L = [chr(i+97) for i in range(3)]
    L = sample(L,len(L))
    
    def tri1(L):
        for i in range(1,len(L)):
            temp = L[i]
            k = i
            while k>0 and L[k-1]>temp:
                L[k] = L[k-1]
                k = k-1
            L[k] = temp
            
    tri1(L)

    Puis executer le script pour avoir la mesure du nombre de steps… Cette mesure dépend de l’argument placé dans la fonction range, utilisée pour créer la liste L. Compléter le tableau:

    liste L n nombre de steps pour trier
    L = [chr(i+97) for i in range(3)] 3 30
    L = [chr(i+97) for i in range(6)] 6 63
    L = [chr(i+97) for i in range(12)] 12 …
    L = [chr(i+97) for i in range(24)] 24 …

    Analyser alors la fonction steps=f(n)

    Question: Ce nombre, augmente t-il de manière régulière avec n? La fonction temps=f(n) est-elle linéaire?

    Le tri par selection

    Principe: On recherche le plus petit élément dans la partie non triée et on l’insère à la fin de la partie triée.

    Exemple d’algorithme

    Pour i allant de 1 à n-1 faire:
        indmin ← i
        Pour j allant de i+1 à n faire:
            Si tab[j] < tab[indmin] alors:
                indmin ← j
            Fin si
        Fin pour
        min ← tab[indmin]
        tab[indmin] ← tab[i]
        tab[i] ← min
    Fin pour

    Questions:

    1. quelle partie de l’algorithme vous fait penser à la recherche du minimum dans une liste?
    2. Comment permute-t-on les valeurs de 2 variables a et b? Faut-il utiliser une variable supplémentaire c? Expliquer. Y-a-t-il une partie du programme qui montre une permutation entre éléments de la liste?

    Programme python:

    def tri2(T):
        for i in range(len(T)-1):
            indmin = i
            for k in range(i+1, len(T)) :
                if T[k] < T[indmin] :
                    indmin=k
            if indmin != i :
                T[i], T[indmin] = T[indmin], T[i]
        return T

    Question 3. Comment est réalisée en python la permutation des 2 éléments de liste?

    SORT et SORTED

    sorted(t)

    fonction qui renvoie une liste triée à partir de la liste t. On l’utilise de la manière suivante:

    > t = [5, 0, 6, 4, 2]
    > t1 = sorted(t)
    > t1
    [0, 2, 4, 5, 6]

    t.sort()

    méthode qui modifie la liste t. On peut lui ajouter un paramètre, comme reverse = True:

    > t = [5, 0, 6, 4, 2]
    > t.sort()
    > t
    [0, 2, 4, 5, 6]
    > t.sort(reverse = True)
    > t
    [6, 5, 4, 2, 0]

    Tri à partir d’une clé

    Lorsque les éléments à trier sont aux-mêmes des sous-listes, le tri est réalisé à partir d’une clé: la clé est l’une des valeurs de la sous-liste.

    Par exemple, pour la liste suivante:

    M = [("Paulette", 93), ("Marie", 62), ("Thomas", 45), ("Jean", 50)]

    Celle-ci pourra être triée par ordre alphabetique du nom: la clé est alors la première valeur de la sous-liste:

    > t = sorted(M, key = lambda item: item[0])
    > t
    [('Jean', 50), ('Marie', 62), ('Paulette', 93), ('Thomas', 45)]

    Mais elle peut aussi être triée par age des personnes: à partir de la 2e valeur.

    > t = sorted(M, key = lambda item: item[1])
    > t
    [('Thomas', 45), ('Jean', 50), ('Marie', 62), ('Paulette', 93)]

    Efficacité

    La meilleure complexité que l’on peut attendre pour un algorithme de tri est quasi linéaire. Mais il s’agit d’algorithmes plus élaborés que ceux vus en classe.

    Ainsi, pour le tri par insertion, le nombre d’opérations f(N) dépend de la disposition des éléments, tel que:

    $$a.N < f(N) < a.N^2$$

    La complexité est linéaire dans le meilleur des cas (liste déjà triée), mais quadratique dans le pire des cas (liste triée à l’envers).

    Pour le tri par séléction, le nombre d’opérations est constant, et egal à $b.N^2$. La complexité est quadratique.

    Documents

    * fiche d'exercices

    Liens

    jeu du juste prix 0-100

    Le Juste Prix
    Vous devez rentrer un nombre.

    jeu du juste prix 0-1000

    Le Juste Prix
    Vous devez rentrer un nombre.

    data analyse

    Apprentissage automatique

    Le machine learning est l’un des domaines de l’intelligence artificielle. Il s’agit:

    • d’abord de construire un modèle à partir de données. C’est la phase d’entrainement, ou d’apprentissage.
    • Puis d’effectuer des prédictions ou prendre des décisions, sur d’autres données.

    En apprentissage automatique, on distingue les algorithmes d’apprentissage:

    • supervisés: apprentissage à partir d’exemples déjà etiquettés (classes discretes ou valeurs Y=f(X) connues)
    • non supervisées: découverte de la structure de données sans exemples étiquettés.
    • par réenforcement: système qui augmente ses performances à partir de ses interactions avec l’environnement. Le système va alors modifier les règles de son modèle au fur et à mesure de ces interactions (plutôt catégorisé comme un apprentissage supervisé).
    prediction par un modèle de machine learning avec apprentissage supervisé

    prediction par un modèle de machine learning avec apprentissage supervisé

    Analyse données par regression lineaire

    Une étude statistique permet de repérer si certains paramètres sont liés entre eux. Alors, si ces données étaient suffisamment nombreuses et précises, il est possible d’établir des lois mathematiques sur ces données. Une manière de représenter ce lien entre paramètres est, par exemple d’établir une loi de regression linéaire.

    Régression linéaire

    La régression linéaire est un algorithme qui va trouver une droite qui se rapproche le plus possible d’un ensemble de points. Les points représentent les données d’entraînement (Training Set).

    Nuage de points avec Regression Lineaire

    Nuage de points avec Regression Lineaire

    A partir de données d’entrée, les points oranges (X1,Y1), on cherche s’il existe un modèle mathématique. Par exemple:

    $$Y1 = a \times X1 + b$$

    Les écarts entre les points et la courbe du modèle devront être les plus petits possibles.

    Regression linéaire impossible

    Regression linéaire impossible

    Modèle prédictif

    Un modèle prédictif ne peut être établi qu’à partir d’une étude prealable de données.

    Pour de nouvelles données, on peut alors, grâce à un modèle, prédire le comportement futur du nouvel objet. Faire une estimation, calculer une valeur. A condition que celui-ci fasse partie de la même famille d’objets que ceux qui ont permis d’établir le modèle.

    nouvelle donnée d'absisse X1 => Y1 determiné grace au modèle (regression)

    nouvelle donnée d'absisse X1 => Y1 determiné grace au modèle (regression)

    Exemple

    Cet exemple est issu du Blog mrmint.fr.

    Supposons que vous soyez le chef de direction d’une franchise de camions ambulants (Food Trucks). Vous envisagez différentes villes pour ouvrir un nouveau point de vente. La chaîne a déjà des camions dans différentes villes et vous avez des données pour les bénéfices et les populations des villes.

    Vous devrez utiliser ces données pour vous aider à choisir la ville pour y ouvrir un nouveau point de vente.

    Ce problème est de type apprentissage supervisé modélisable par un algorithme de régression linéaire. Il est de type supervisé car pour chaque ville ayant un certain nombre de population (variable prédictive X), on a le gain effectué dans cette dernière (la variable qu’on cherche à prédire : Y).

    Notebook

    Vous utiliserez le notebook en ligne sur Jupyterlite

    Algorithme des K proches voisins Knn

    Principe

    Il s’agit d’un algorithme d’apprentissage supervisé, initialisé par des exemples connus. Pour cela, on part d’un jeu de données existant dont on connait les classes.

    L’algorithme KNN (k-nearest neightbors) permet de déterminer à quelle classe appartient un nouvel élément.

    Exemple: Les joueurs de NBA

    On cherche une correspondance entre les caractéristiques physiques d’un joueur de basket et son poste sur le terrain.

    Pour simplifier, on considerera que les postes sont au nombre de trois :

    • le joueur Centre, noté ‘C’ (position 5 sur le schéma)
    • Le joueur Ailier, noté ‘F’ (positions 3 et 4 sur le schéma)
    • Le joueur arrière ou meneur de jeu, noté ‘G’ (positions 1 et 2 sur le schéma)

    Les données sont issues de la page : nba.com

    La ligue de basket americaine contient environ 400 joueurs professionnels. La plupart de nationalité américaine. On dispose d’un extrait de ce fichier (voir dans le dossier datas), constitué de moins de 100 joueurs, classés par ordre alphabetique.

    extrait du tableau des joueurs NBA en 2020

    extrait du tableau des joueurs NBA en 2020

    Apprentissage supervisé

    Chaque joueur de basket occupe un poste particulier sur le terrain:

    poste occupé sur le terrain

    poste occupé sur le terrain

    Une étude des caractéristiques physique des joueurs montre une correlation entre le poids, la taille, et le poste du joueur. Dans un diagramme taille-poids, les joueurs se repartissent en îlots selon leur poste:

    les joueurs

    les joueurs

    Prédiction

    On peut alors prévoir le poste d’un nouveau joueur. Pour cela on observe ses k plus proches voisins, et on en déduit quel poste corresspnd à son physique, à partir de la classe majoritairement représentée.

    Le joueur semble être à la limite des classes

    Le joueur semble être à la limite des classes

    Méthode:

    • on ajoute une nouvelle colonne calculée: Pour le joueur inconnu, on calcule la distance avec chaque élément classé dans le tableau .
    • on trie le tableau selon la distance.
    • on observe la classe majoritaire pour les k premiers éléments classés de la liste triée. La valeur de k doit être représentative. On prendra la plupart du temps $k = \sqrt N$

    Travaux pratiques

    Suite

    • page 2: clustering, recommandation

    Liens

    documents utilisés pour la redaction de la page

    Approfondissement

    algorithmique avancé

    Problèmes et algorithmes

    stratégies et limitations

    Les algorithmes ne peuvent pas resoudre tous les problèmes existants, même si ces problèmes sont bien énoncés mathématiquement. Il n’existe pas non plus une infinité d’algorithmes différents. liste complète de tous les principaux algorithmes (300).

    Souvent, c’est le même algorithme qui resoud toute une famille de problèmes. Il suffit d’arranger l’énoncé, de bien identifier les variables d’entrée, d’interpréter convenablement la sortie de l’algorithme.

    Par exemple: les énoncés suivants traitent du même problème mathématique:

    • Rendu de monnaie optimal: Comment rendre 7 euros en utilisant une caisse constituée de pieces ou billets de 5, 2 et 1 euro?
    • Decoupe optimale d’une barre de fer: Comment réaliser des découpes dans une barre de 7m afin d’optimiser le benefice? Sachant que les clients vont demander des coupes de 5, 2 et 1m. Et que le benefice est plus grand lorsque l’on fait le moins de coupes possible. (voir illustration uliege.be)
    • Occupation optimale d’une salle de spectacle
    • …

    On verra que pour certains problèmes dits de décision, ou optimisation, la recherche d’une solution peut se faire en écrivant un algorithme. Mais qu’il n’est pas possible d’executer cet algorithme sur une machine en un temps raisonnable.

    Le problème du rendu de monnaie

    Le problème du rendu de monnaie est un problème d’algorithmique. Il s’énonce de la façon suivante : étant donné un système de monnaie (pièces et billets), comment rendre une somme donnée de façon optimale?

    Il existe de nombreuses façons de rendre la monnaie. Mais quelle solution le fera avec le nombre minimal de pièces et billets ?

    Par exemple, la meilleure façon de rendre 7 euros est de rendre un billet de 5 et une pièce de 2, même si d’autres façons existent (rendre 7 pièces de un euro, par exemple).

    caisse rendu monnaie

    Image by pixabay conmongt-1226108

    algorithme naif

    Une première idée, naïve serait de commencer par rendre la piece de plus grande valeur, puis sur la somme restante, la pièce la plus grande possible (de valeur inferieure ou egale), et ainsi de suite.

    S’entrainer à rendre la monnaie de manière optimale:

    Cliquer pour lancer l'animation

    Cliquer pour lancer l'animation

    Programmation Python

    Pour une somme à rendre, et un systeme de monnaie appelé caisse, contenant par exemple la liste[20, 10, 5, 1]:

    • soit la piece est inférieure à la somme à rendre: alors on soustrait la piece à la somme à rendre et on continue avec cette même caisse, et la nouvelle somme à rendre.

    • soit la piece est supérieure à la somme à rendre. on retire la piece de la caisse. Et on continue pour faire diminuer la somme à rendre.

    • Méthode utilisant une liste pour la variable rendu

    caisse = [piece4, piece3, piece2, piece1]
    rendu = []
    tant que la somme a rendre est > 0:
      si la piece de montant caisse[i] est inferieure a somme:
        somme = somme - caisse[i]
        rendu.append(caisse[i])
      sinon:
        changer de piece
    • Méthode utilisant une structure de données en dictionnaire pour la variable rendu
    caisse = [piece4, piece3, piece2, piece1]
    rendu = {piece4 : 0, piece3: 0, piece 2: 0, piece1: 0}
    tant que la somme a rendre est > 0:
      si la piece de montant caisse[i] est inferieure a somme:
        somme = somme - caisse[i]
        rendu[caisse[i]] += 1
      sinon:
        changer de piece

    Méthode par recherche exhaustive

    Quelques essais avec le script précédent montrent que le rendu n’est pas toujours optimal. Il faut envisager d’autres possibilités pour rendre la monnaie.

    Une autre méthode pourrait être d’envisager TOUTES les combinaisons. On pourrait alors imaginer que l’on commence par rendre la monnaie avec une des pieces de la caisse (pas forcément la plus haute), puis on choisit une autre piece possible (egale ou moins haute), … Jusqu’à ce que la somme à rendre soit nulle. On envisage ainsi toutes les combinaisons possibles, ce qui, avec une valeur élevée de la somme à rendre, et un grand nombre de pieces dans la caisse, va donner un très grand nombre de combinaisons. On selectionne enfin la meilleure des solutions (celle optimale).

    Par exemple, pour rendre 7 euros, voici toutes les combinaisons possibles (la solution optimale étant la première):

    • 5 + 2
    • 5 + 1 + 1
    • 2 + 2 + 2 + 1
    • 2 + 2 + 1 + 1 + 1
    • 2 + 1 + 1 + 1 + 1 + 1
    • 1 + 1 + 1 + 1 + 1 + 1 + 1

    Un programme python exprimerait le rendu sous forme de liste:

    > rendu(7,[5,2,1])
    # 6 solutions
    [[5, 2],
     [5, 1, 1],
     [2, 2, 2, 1],
     [2, 2, 1, 1, 1],
     [2, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1]]
    > rendu(14,[10,5,2,1])
    # 19 solutions
    [[10, 2, 2],
     [10, 2, 1, 1],
     [10, 1, 1, 1, 1],
     [5, 5, 2, 2],
     [5, 5, 2, 1, 1],
     [5, 5, 1, 1, 1, 1],
     [5, 2, 2, 2, 2, 1],
     [5, 2, 2, 2, 1, 1, 1],
     [5, 2, 2, 1, 1, 1, 1, 1],
     [5, 2, 1, 1, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2, 2, 2],
     [2, 2, 2, 2, 2, 2, 1, 1],
     [2, 2, 2, 2, 2, 1, 1, 1, 1],
     [2, 2, 2, 2, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
    rendu(21,[20,10,5,2,1])
    # 44 solutions
    [[20, 1],
     [10, 10, 1],
     [10, 5, 5, 1],
     [10, 5, 2, 2, 2],
     [10, 5, 2, 2, 1, 1],
     [10, 5, 2, 1, 1, 1, 1],
     [10, 5, 1, 1, 1, 1, 1, 1],
     [10, 2, 2, 2, 2, 2, 1],
     [10, 2, 2, 2, 2, 1, 1, 1],
     [10, 2, 2, 2, 1, 1, 1, 1, 1],
     [10, 2, 2, 1, 1, 1, 1, 1, 1, 1],
     [10, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 5, 5, 1],
     [5, 5, 5, 2, 2, 2],
     [5, 5, 5, 2, 2, 1, 1],
     [5, 5, 5, 2, 1, 1, 1, 1],
     [5, 5, 5, 1, 1, 1, 1, 1, 1],
     [5, 5, 2, 2, 2, 2, 2, 1],
     [5, 5, 2, 2, 2, 2, 1, 1, 1],
     [5, 5, 2, 2, 2, 1, 1, 1, 1, 1],
     [5, 5, 2, 2, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 2, 2, 2, 2, 2, 2, 2, 2],
     [5, 2, 2, 2, 2, 2, 2, 2, 1, 1],
     [5, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1],
     [5, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1],
     [5, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1],
     [2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1],
     [2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

    Questions

    1. Parfois la solution est impossible à trouver, il n’y a pas de rendu possible avec la caisse considérée: V / F
    2. La solution dépend de l’ordre des pieces dans la caisse: V / F
    3. La solution est toujours optimale en commençant par rendre la monnaie avec la plus grande piece, puis la piece moins grande, etc…: V / F
    4. Avec la 2e méthode, celle de recherche exhaustive: cette méthode permet de tester toutes les possibilités, toutes les combinaisons possibles pour le rendu de monnaie: V / F
    5. Supposons que le programme, pour la méthode 2, commence par calculer le rendu pour pour la somme 7 avec la combinaison [5,2]. Plus loin, dans le programme, il calcule une autre solution pour rendre 7, et commence avec la combinaison [1,1,1]. Doit-il aller au bout du calcul de la solution avec cette combinaison, ou bien, peut-il arrêter son calcul au milieu? Cela est-il réalisé par le programme, tel que vous l’avez écrit?

    Conclusion

    En analysant les 2 méthodes précédentes, on voit que le rendu de monnaie sera optimal pour toute somme à rendre, et pour tout type de caisse, à condition de tester toutes les combinaisons de rendu possible. Puis de selectionner la meilleure.

    Cela risque toutefois de générer un programme dont la complexité va être très divergente. Avec une quantité d’opérations à effectuer qui peut largement depasser les capacités des machines actuelles (la durée d’execution pourrait exceder la durée de vie d’un être humain): clogique.fr

    Les algorithmes de recherche exhaustive sont de complexité exponentielle. La durée d’execution (relative à la complexité) s’exprime selon une loi dependante de la taille du-des paramètre-s d’entrée. La loi exponentielle est la plus divergente:

    comparaison de la divergence de quelques fonctions

    comparaison de la divergence de quelques fonctions

    On verra qu’il existe des méthodes de programmation qui resolvent ce type de problème avec plus d’efficacité, sans pour autant donner systematiquement la solution la plus optimale.

    Liens

    • Suite du cours, programmation dynamique, classe d’algorithmes de decision: Term NSI
    • illustrations des problèmes classiques resolus par algorithme glouton/force brute: uliege.be

    Sous-sections de architecture

    architecture 1

    Cours:

    • Histoire et modèle d’architecture Von Neumann / Harvard: Lien
    • Le fonctionnement d’un processeur: Lien
    • Langage assembleur: Lien

    Séquence composée de 3 TP:

    • TP1 Composer son ordinateur à partir d’un site commercial: Lien
    • TP2: Comment fonctionne un processeur? Lien
    • TP3: Programmes plus evolués, de python à l’assembleur: Lien

    L’Histoire de l’Ordinateur

    En 1623 Wilhelm Schickard ou bien Blaise Pascal en 1642 créent des machines munies de rouages mécaniques pour faire des additions et des soustractions. Il ne s’agit pas encore d’ordinateurs, car celles-ci n’ont qu’une seule fonction.

    En 1854 le mathématicien britannique George Boole créé le calcul propositionnel. Aujourd’hui, l’algèbre de Boole trouve de nombreuses applications en informatique et dans la conception des circuits électroniques.

    Elle fut utilisée la première fois pour les circuits de commutation téléphonique par Claude Shannon.

    Alan Türing a discuté longuement avec Claude Shannon. Cela a pu influencer ses reflexions sur le rôle des machines. Il est à l’origine de la conception du traitement automatisé de l’information par une machine. John Von Neumann va proposer l’architecture d’une machine universelle sur laquelle reposent tous les ordinateurs. Leur point commun: ils sont tous capables de traiter de la même manière les calculs sur des nombres ou des propositions, exprimés en binaire.

    La premiere machine universelle

    • 1834 La première machine sur le modèle d’un ordinateur. La machine analytique (analytical engine, Charles Babbage: 1791-1871) est une machine à calculer programmable imaginée par le mathématicien anglais Charles Babbage. Il ne la réalisera jamais (sauf pour un prototype inachevé), mais il passera le reste de sa vie à la concevoir dans les moindres détails. La machine analytique reprend les différentes parties de nos ordinateurs actuels:
      • Une unité centrale
      • Une mémoire
      • Un lecteur de cartes des métiers à tisser Jacquard (l’équivalent d’un périphérique d’entrée)
      • Une imprimante (un périphérique de sortie).

    La machine fonctionne en 5 étapes:

      • reçoit les opérations demandées des cartes,
      • gère le transfert des nombres et leur mise en place dans le bon ordre,
      • exécute les opérations,
      • stocke les résultats ,
      • imprime sous la forme demandées.
      • [source - wikidia](https://fr.vikidia.org/wiki/Machine_analytique)

    C’est la première machine Türing-complète. Sauf que celle-ci ne manipule pas les données en binaire.

    Prototype (1871) non terminé de la machine analytique de Babbage, exposée au

    Prototype (1871) non terminé de la machine analytique de Babbage, exposée au

    C’est son élève, Ada Lovelace qui formalise les idées de Babbage et développe le premier algorithme de programmation de l’histoire, devenant la première informaticienne de l’humanité.

    Des machines pour chiffrer et decrypter des informations

    La période de la seconde guerre mondiale a vu emerger des machines électromecaniques plus efficaces que celles mécaniques.

    Ces machines ne sont pas Türing-complètes.

    • 1938-1943 La Bombe, un supercalculateur est utilisé pour le décryptage d’[Enigma](https://fr.wikipedia.org/wiki/Enigma_(machine), une machine utilisant un système de rotors pour produire un chiffrement mécanique. Les anglais, français et polonais travaillent sur le déchiffrage en testant des combinaisons. La Bombe a été conçue pour les attaques de force brute. Cette machine abat par jour le travail de dix mille décrypteurs. C’est le mathematicien Alan Turing qui parvient à casser le chiffre grâce à l’utilisation d’une version améliorée de cette machine.
    La Bombe - version britannique

    La Bombe - version britannique

    • 1943-1945 Les machines du projet Colossus permettent de décrypter les machines de Lorentz. Le premier, Colossus Mark 1, est opérationnel en décembre 1943: constitué de 1500 tubes à vide, il accomplissait 5000 opérations par seconde.

    Colossus Mark2. Le panneau incliné à gauche sert

    Colossus Mark2. Le panneau incliné à gauche sert

    Le chiffrement Lorenz est beaucoup moins connu que celui d’Enigma. Il était utilisé par les hauts dirigeants allemands pour communiquer entre eux alors qu’Enigma était utilisée au quotidien pour les autres types de communication.

    Colossus n’est pas une machine universelle, mais c’est bien le premier processeur électronique, numérique, et partiellement programmable de l’histoire. Cette machine montre que l’électronique peut être utilisé pour le traitement numérique à grande vitesse.

    Vers 1940 plusieurs spécialistes développent des calculateurs à programme externe, suivant le projet de machine analytique de Babbage, en y incluant des relais électriques: Zuse, Coufignal, Aiken, Stibitz… Ces machines utilisaient des cartes ou rubans perforés, et étaient donc des calculateurs à programme externe.

    Aucun n’avait eu l’idée d’une machine à programme enregistré, concept essentiel pour les machines électroniques.

    Machines électromécaniques dans la lignée conceptuelle de Babbage

    • 1938 le Z1, 1941 le Z3 (Konrad Zuse), est un ordinateur électromécanique utilisant le système binaire et lisant son programme sur une bande perforée. Le Z3 contenait plus de 2000 relais électromécaniques, pesait une Tonne et consommait plus de 4kW. Il comprend une mémoire, un dispositif de contrôle et une unité arithmétique calculant en binaire sur des nombres à virgule flottante! Les données et les instructions sont perforées sur du film de cinema, plus solide que des rubans en papier. Il était capable d’effectuer une addition en 0,8 s. Sa fréquence était de 5,3 Hertz, assez lente à cause des relais. A l’epoque, aucun appareil ne pouvait rivaliser.

    Z3: the First Functional Programm-Controlled Automatic Calculating Machine -

    Z3: the First Functional Programm-Controlled Automatic Calculating Machine -

    L’institut de recherche aéronautique allemand l’utilisait pour réaliser des analyses statistiques sur les vibrations des ailes.

    Zuse était le premier à concevoir que les fonctions de contrôle pouvaient aussi s’exprimer et être stockées sous forme numérique, donc à créer une machine programmable. Ce qui permettait de changer de programme sans avoir à modifier les connexions.

    Si Ada Lovelace, élève de Babbage, fut la première programmeuse théorique d’une machine inexistante, Zuse fut pour sa part le premier programmeur d’une machine réelle en pratique.

    Les calculateurs géants

    Les premiers ordinateurs étaient des machines électromecaniques, fabriquées à l’unité après des années de recherche et developpement. Leur taille était immense, de même que leur consommation électrique. Le temps passé à leur maintenance et réparation était important (plus de 50%). Leur programmation était très rudimentaire, et leurs pannes, fréquentes.

    On ne pouvait pas implémenter des algorithmes trop complexes. Même s’il s’agissait, formellement, de machine universelle. Ils repondaient alors à un besoin de calculer.

    Les opérations à réaliser sont entrées à la main. Les données sont lues sur une carte perforée.

    Ces machines ont d’autres defauts:

    • il n’y a pas de distinction entre la fonction mémoire et la fonction calcul.
    • pas d’unité centrale généraliste, mais une juxtaposition d’accumulateurs et d’unités spécialisées
    • la programmation se fait par cablage ou en positionnant des interrupteurs. Ces machines nécessitent que l’on change leur câblage à chaque type d’opération.
    illustration de la différence entre supercalculateurs

    illustration de la différence entre supercalculateurs

    année machine unité logique vitesse de calcul remarques
    1944 calculateur Harvard Mark 1 (IBM) 3300 relais 3 addition sur 23 chiffres par s
    1945 ENIAC 1800 tubes (technologie superieure aux relais) 5000 additions par s a servi à calculer la faisabilité de la bombe H
    1948 EDSAC lignes à retard sur mercure programme écrit en binaire
    1951 UNIVAC 5 200 tubes à vide 1 905 opérations par seconde utilisé par CBS pour prédire l’issue de l’élection présidentielle de 1952. 13 tonnes. consomme 125 kW. L’unité accueillant la mémoire à mercure fait 4,3 m × 2,4 m × 2,6 m à elle seule. Le système au complet occupe 35,5 mètres carrés.
    1962 Atlas (Manchester) Les 96 ko de mémoire, réalisée en tores de ferrite étaient étendus à l’aide des 576 ko stockés sur tambour magnétique
    1964 CDC 6600 entre 1 et 10 mégaflops (millions d’opérations par s)

    Remarque: l’ENIAC sera améliorée en 1948: elle intègre alors la notion d’instruction et de programme, ce qui correspond au modèle classique d’ordinateur à programme enregistré.
    C’est aussi le premier ordinateur binaire, ne comportant plus de pièces mécaniques. (Mauchly et Eckert).
    Il exécute son premier programme le 12 avril, et son premier programme de production le 17 avril. La simulation de Monté Carlo exécutée le 12 avril 1948 par l’ENIAC est la plus ancienne trace de programme enregistré connue à ce jour.

    Les premiers ordinateurs fabriqués en série

    • IBM 650, le premier ordinateur fabriqué en série (1955)

    Cet ordinateur n’a pas encore de transistors mais des tubes à vide.

    • IBM 7090, le premier ordinateur à transistors (1959)

    Machines universelles

    • 1945 En tirant les conclusions de réalisations électroniques secrètes menées pendant la guerre, deux documents apparaissent et definissent ce que l’on nommera ordinateur, le calculateur numérique à programme enregistré. Les motivations des deux hommes sont différentes:
      • John Von Neumann: qui cherche à developper des moyens pour les Universités pour leurs besoins de calculs mathématiques.
      • Alan Turing: qui veut réaliser une machine à traiter les informations.

    La contribution de Turing à l’avènement des ordinateurs

    Le binaire

    Contrairement à Babbage, Türing se rend compte que les opérations arithmétiques ordinaires peuvent être traduites dans le cadre de la logique booléenne, sous forme de circuits logiques (booléens). Il conçoit comme première machine un multiplicateur booléen électrique.

    Il prolonge l’idée de Gödel de coder les opérateurs, les instructions , et les fonctions (des propositions) par des nombres entiers.

    Traiter des instructions revient à calculer sur des nombres entiers, écrits en binaires.

    Les algorithmes

    Le raisonnement mathématique est une combinaison:

    • d’intuition
    • d’ingéniosité, de procédures

    L’idée de Türing est de diminuer la part d’intuition et d’augmenter celle de procédure.

    Par exemple, lorsque l’on réalise une opération de tri, on le fait d’abord de manière intuitive. Pour qu’une machine soit capable de le réaliser, il faudra en dégager une procédure.

    Machine de Türing

    C’est une machine mathématique permettant la manipulation réglée de signes. Son rôle est de transformer les symboles fournis en entrée, en symboles lisibles en sortie.

    Cette machine utilise les instructions d’un programme (une tables d’états) et repère un état d’un registre, états qui définissent les étapes de l’algorithme.

    C’est une machine conceptuelle, qui a permi de définir ce qu’est un problème calculable.

    Une machine de Tûring est conçue pour résoudre une classe de problèmes donnés: si une machine de Türing est programmée pour résoudre un opération d’addition, alors elle pourra résoudre TOUTES les opérations d’addition, quelles que soient les données en entrée.

    Une machine de Türing particulière contient donc, par avance, un programme.

    Une machine de Türing universelle est capable de résoudre TOUS les problèmes possibles de toutes les machines de Türing possibles (contient tous les programmes existants ou à venir).

    John Von Neumann fait référence de manière explicite à ce concept lorsqu’il présente l’architecture à laquelle doivent se conformer les machines universelles:

    Un ordinateur se définit comme une instance matérielle, concrète, d’une Machine de Turing Universelle

    Calculabilité

    Si un problème (proposition, fonction), que l’on peut énoncer sous forme mathématique, peut être résolu par une machine de Tûring, alors celui-ci est calculable. Il doit exister un nombre fini d’instructions pour résoudre ce problème.

    Comparer des programmes

    Il devrait être possible de comparer des programmes en construction en évaluant le nombre de pas de calcul qui serait nécessaire. Tûring fait émerger la notion de compléxité.

    Architecture Von Neumann

    Definition: Un ordinateur est un appareil programmable qui stocke son programme dans une mémoire modifiable. article wikibook sur l’architecture de base d’un ordinateur

    John Von Neumann (1945) est le concepteur de l’architecture de la machine universelle et de ses différents dispositifs:

    • processeur
    • mémoires
    • dispositifs d’entrée/sortie

    Il est à l’origine du concept de programme enregistré: le stockage des données et des instructions sous forme d’impulsions électriques à l’intérieur même de la machine qui pourra les consulter à l’instant et à la vitesse qui lui convient. En remplacement du traitement mécanique alors utilisé, ce qui necessitait une vaste manipulation de cables et de boutons à placer sur la bonne position pour specifier le nouveau problème. Charles Babbage avait déjà eut cette idée un siècle plus tôt.

    illustration de la différence entre supercalculateurs

    illustration de la différence entre supercalculateurs

    Cette architecture s’oppose à celle de Harvard (mémoires différentes pour les données et les programmes) du Mark1.

    Von Neumann est également le concepteur de l’ordinateur IAS à Princeton.

    Le stockage était alors réalisé par des tubes cathodiques, chacun de 1024 bits.

    Dans l’architecture de Von Neumann, un ordinateur est constitué de quatre parties distinctes:

    1. Le CPU: Central Processing Unit (unité centrale de traitement) appelé aussi processeur;
    2. La mémoire où sont stockés les données et les programmes. La mémoire se divise entre:
    • une mémoire volatile (RAM ou mémoire vive) qui gère les programmes et les données
    • une mémoire permanente (ROM) qui gère les programmes de base de la machine.
    1. des bus qui sont des fils conduisant des impulsions électriques et qui relient les différents composants;
    2. des entrées-sorties (E/S ou I/O input/Output) pour échanger avec l’exterieur.

    Les échanges entre la mémoire et les registres du CPU se font via les bus selon une chronologie séquencée par l’horloge et suivant la nature des échanges: données ou adresse. Cette horloge est externe au processeur.

    Un programme est une suite d’instructions codées sous forme binaire. Il précise la suite d’instructions exécutées par l’ordinateur. Ces instructions, codées en binaire peuvent être exprimées pour un humain en langage assembleur, le langage de plus bas niveau (une traduction mnémonique du binaire).

    Le processeur CPU

    L’unité de traitement est un circuit qui s’occupe de faire des calculs et de manipuler l’information provenant des entrées-sorties ou récupérée dans la mémoire. Dans les ordinateurs, l’unité de traitement porte le nom de processeur, ou encore de Central Processing Unit, abrévié en CPU. Tout processeur est conçu pour effectuer un nombre limité d’opérations bien précises, comme des calculs, des échanges de données avec la mémoire, etc.

    Les processeurs multicœurs: regroupement de plusieurs processeurs dans le même boitier. Un processeurs multicœurs, contient plusieurs cœurs, chaque cœur pouvant exécuter un programme tout seul. Chaque coeur contient un séquenceur d’instruction, des registres, une unité de calcul. Mais il manque certains circuits dédiés au processeur principal, comme les circuits de communication avec la mémoire. Les systemes d’exploitation se sont adaptés à cette nouvelle architecture. Un processus peut lancer plusieurs threads, partagés sur les différents coeurs.

    Pour calculer plus rapidement, le processeur utilise une mémoire plus rapide que la RAM: Les caches, qui sont des mémoires intermédiaires entre les registres internes du micro-processeur et la mémoires vive.

    Pour un processeur multicoeur, certains caches sont dédié à chaque “coeur”, d’autres sont partagés. wikipedia - multicoeur

    cache dédié / cache partagé

    cache dédié / cache partagé

    La puissance de la machine augmente significativement en élevant la fréquence de calcul, supérieure à celle d’un processeur monocœur. Mais cette méthode a ses limites: En effet, l’augmentation de fréquence d’un processeur cause rapidement des problèmes de surchauffe.

    Les coprocesseurs: Ce sont des processeurs qui complètent un processeur principal pour certaines fonctions wikipedia:

    • des coprocesseurs arithmétiques: assurent certains types de calculs que ne peuvent pas realiser le processeur principal (division entiere, flottante, racines carées…). Par exemple sur la Nitendo DS.
    • coprocesseurs pour le rendu 2D/3D et les coprocesseurs sonores: sur les anciennes consoles de jeux vidéo, comme La Nintendo 64, la Playstation et autres consoles de cette génération ou antérieure.
    • coprocesseurs pour l’accès aux périphériques: L’accès aux périphériques peut demander beaucoup de puissance de calculs. La Nintendo 3DS disposait d’un processeur principal de type ARM9, du coprocesseur pour les divisions, et d’un second processeur ARM7. L’ARM 7 était le seul à communiquer avec les périphériques et les entrées-sorties.

    mémoires ROM et RWM

    Les mémoires ROM stockent des programmes à exécuter et sont lues directement par le processeur. Pour les mémoires RWM ou RAM, on peut y acceder en lecture et écriture.

    Les RWM stockent les variables du programme à exécuter, des données que le programme va manipuler. Selon l’architecture de la machine, le programme peut être entièrement stocké dans la ROM, ou bien être partagé entre la ROM et la RWM.

    source:wikibooks.org

    adressage differencié ou commun pour les mémoires  - source : wikibooks

    adressage differencié ou commun pour les mémoires - source : wikibooks

    Les bus

    Les données doivent circuler entre les différentes parties d’un ordinateur, notamment entre la mémoire vive et le CPU. Le système permettant cette circulation est appelé bus. Il existe, sans entrer dans les détails, 3 grands types de bus: adresses, données, de contrôle.

    Les péripheriques

    Les périphériques sont très divers. On les classe en périphérique d’entrée, sortie, entrée-sortie.

    Toutes les entrées-sorties contiennent des registres d’interfaçage, qui permettent de faire l’intermédiaire entre le périphérique et le reste de l’ordinateur. source:wikipedia

    registres d’interfaçage - wikipedia

    registres d’interfaçage - wikipedia

    Loi de Moore

    Des années 1970 aux années 2000, la miniaturisation des circuits a suivi al Loi de Moore qui prédit un doublement du nombre de transistors par cm2 tous les 18 mois. Cette miniaturisation et l’augmentation des fréquences d’horloge (qui ont aussi doublé environ tous les 18 mois) ont permis d’augmenter la puissance des processeurs de façon exponentielle pendant près de 40 ans.

    La figure suivante montre l’évolution du nombre de transistors pour un même élement de surface: source-wikipedia

    illustration de la loi de Moore - source wikipedia

    illustration de la loi de Moore - source wikipedia

    L’image ci-dessous illustre, elle, l’evolution de la finesse de gravure

    illustration de la finesse de gravure dans le temps - source eskool.gitlab.io/

    illustration de la finesse de gravure dans le temps - source eskool.gitlab.io/

    Architecture Von Neumann vs Harvard

    La différence de ces architectures repose sur la gestion des mémoires pour les programmes et données:

    • Von Neumann: un même support (RWM) contient programme et données pour les processus en cours. Les instructions des programmes sont dupliquées dans la RAM. Elles existent alors à 2 endroits distincts de la machine: dans la mémoire de masse (persistante) du systeme, mais aussi dans la RAM. Il serait assez inefficace d’executer le programme depuis la mémoire de masse, car celle-ci est beaucoup plus lente.
    • Harvard: Données dans une mémoire de travail différente de la RAM (mémoire flash) utilisée pour les programmes. Pas de duplication du programme. Economie des supports de stockage, et economie d’énergie.

    Voir la video suivante expliquant la différence entre ces 2 architectures:

    MooC Arduino #4 - Architecture de Von-Neumann, Harvard et Microcontrôleurs

    MooC Arduino #4 - Architecture de Von-Neumann, Harvard et Microcontrôleurs

    L’architecture Harvard est utilisée pour les microcontrôleurs, pour lesquels le besoin de miniaturisation amène à intégrer tous les composants internes dans une même puce (onchip). Les microcontrôleurs embarquent une mémoire de type EEPROM (electrically erasable programmable read only memory 64-256ko), suffisement rapide d’accès pour l’utiliser directement, et sans avoir besoin de charger le programme dans une nouvelle RAM.

    La machine avec architecture Harvard peut aussi gérer une mémoire de masse (persistante) comme un disque dur, ou carte flash externe. Il s’agit alors d’une extension, utile pour augmenter la capacité de la mémoire flash interne, qui est souvent réduite.

    architecture Harvard

    architecture Harvard

    Compléments sur la différence des architectures: www.arrow.com/fr-fr/research-and-events

    Les Systeme On Chip

    Un Circuit intégré, c’est un circuit électronique conventionnel qui a été mis sur une plaque de silicium de quelques $cm^2$. La consommation électrique, et l’echauffement sont beaucoup inférieurs, et la qualité bien supérieure en rapport aux premieres machines qui n’en disposaient pas. Cela a permis une diminution du coût.

    source image: extrait de la video youtube:MOOC Arduino, chaine Paul Pinault

    microcontroleur: systeme onchip

    microcontroleur: systeme onchip

    Un « système sur une puce » est un système complet embarqué sur une seule puce (“circuit intégré”), comprenant de la mémoire, un ou plusieurs microprocesseurs, des périphériques d’interface (processeur graphique GPU…), et autres composants nécessaires à la composition du SoC complet…

    Ces systèmes permettent de réduire l’encombrement, la consommation d’énergie (courants faibles), et de diminuer le coût de production (gros volumes de fabrication). L’inconvenient principal est qu’il est n’est pas possible de modifier soi-même ses composants, et de l’upgrader.

    Voir l’excellent cours sur https://eskool.gitlab.io/tnsi/soc/

    Liens et bibliographie

    architecture 2

    Cours:

    • Histoire et modèle d’architecture Von Neumann / Harvard: Lien
    • Le fonctionnement d’un processeur: Lien
    • Langage assembleur: Lien

    Séquence composée de 3 TP:

    • TP1 Composer son ordinateur à partir d’un site commercial: Lien
    • TP2: Comment fonctionne un processeur? Lien
    • TP3: Programmes plus evolués, de python à l’assembleur: Lien

    Qu’est ce qu’un ordinateur?

    Un ordinateur est une machine qui traite de l’information, stockée dans la mémoire, à l’aide du processeur. Les instructions de ces traitements sont aussi stockés dans la mémoire, sous forme de programmes.

    Il existe donc une très grande variété de machines que l’on peut appeler des ordinateurs: celles présentes dans une PC de bureau, dans un mac, dans un smartphone, un objet connecté, une voiture…

    Rappels sur l’architecture Von Neumann

    Dans l’architecture Von Neumann:

    • une machine universelle est contrôlée par un programme.
    • Les données et programmes sont écrits sur une même mémoire (en binaire). L’ordinateur enregistre les instructions des programmes qu’il exécute dans sa mémoire vive.
    • Les instructions sont executée de manière séquentielle, par un processeur.
    • Les mémoires RAM d’une part et les mémoires non volatiles d’autre part (Disques durs, mémoires flash) sont reliées au processeur (donc aux registres du processeur) par une liaison appelée Bus. En réalité, seule la RAM est directement accessible au processeur.

    Description d’un ordinateur avec microprocesseur

    En video

    Fonctionnement d'un ordinateur - Mooc Architecture

    Fonctionnement d'un ordinateur - Mooc Architecture

    à l’echelle de la carte mère

    La carte mère d’un ordinateur comprend:

    • un microprocesseur
    • de la mémoire volatile (random access memory, RAM)
    • de la mémoire de masse
    • des ports:
      • port ethernet, RJ45
      • port USB
      • ports pour carte wifi, carte son, carte graphique, …
    • des périphériques d’entrée et sortie: écran, haut-parleur, souris, clavier…

    Ces périphériques sont connectés aux 3 Bus définis plus loin et se comportent comme une mémoire. On leur affecte des adresses (différentes de celles de la RAM) et on communique avec eux en écrivant à ces adresses. Le Bus de contrôle va detecter un changement sur l’une de ces adresses et interrompre le traitement en cours.

    Certains ports vont ajouter des extensions à l’ordinateur (carte son, video, wifi). Certains vont être essentiels au fonctionnement de l’ordinateur (mémoires).

    Liaisons entre composants: les Bus

    Il existe des Bus de différentes nature pour relier les composants:

    • bus d’adresse: permet au processeur d’indiquer à la mémoire l’emplacement pour lire/écrire.
    • bus de données: transporte les données entre la mémoire et le processeur.
    • bus de contrôle: permet de coordonner le fonctionnement du processeur et de la mémoire.

    Les bus peuvent être bi-directionnels: les données transitent dans les 2 sens. Mais aussi directionnel: c’est le cas du bus d’adresse entre le processeur et la RAM, qui n’est parcouru que dans le sens processeur => RAM.

    à l’echelle des composants

    Les constituants de l’ordinateur sont composés de circuits intégrés. On trouve 2 grandes catégories de circuits intégrés:

    • les circuits combinatoires: l’état de sortie de ces circuits ne dépend que des états d’entrée.
    • les circuits séquentiels: l’état de sortie dépend des états d’entrée, mais aussi de l’état courant du circuit. Ces circuits peuvent ainsi stocker une valeur appelée état courant. Les registres sont typiquement des circuits intégrant des circuits séquentiels.

    CPU et MCU: des architectures différentes

    • Certaines machines comportent des composants séparés sur la carte mère. Le microprocesseur (CPU) est relié aux autres composants par des bus.

    • Pour d’autres machines, comportant microcontrôleur (MCU), les composants occupent une même puce (un même chip). Ces machines sont moins chères et consomment moins d’électricité.

    voir page 1 du cours sur l’architecture: lien

    Le fonctionnement du processeur

    Généralités

    Videos sur le fonctionnement du processeur

    Hervé Discours - architecture Von Neumann - illustration avec une cuisine (min 5 - 10)

    Hervé Discours - architecture Von Neumann - illustration avec une cuisine (min 5 - 10)

    Hervé Discours - architecture Von Neumann - déroulé d'un programme (min 15 - 20), archi X2, memoire cache (min 20-25)

    Hervé Discours - architecture Von Neumann - déroulé d'un programme (min 15 - 20), archi X2, memoire cache (min 20-25)

    Hervé Discours - architecture Von Neumann - langage assembleur (min 29 - 35)

    Hervé Discours - architecture Von Neumann - langage assembleur (min 29 - 35)

    Les 2 sous parties du processeur

    Architecture de Von-Neumann - processeur

    Architecture de Von-Neumann - processeur

    L’architecture d’un processeur (CPU) comporte 2 parties:

    • L’UC: C’est l’unité de commande, UC, qui traduit chacune des instructions successives du programme en opérations élémentaires. C’est cette partie du processeur qui est chargée d’obtenir les instructions successives du programme et de les executer. L’UC contient:
      • le registre Program Counter, PC
      • le registre d’instruction RI
      • une horloge.
    • La partie opérative qui comprend les outils permettent de réaliser les actions élémentaires ordonnés par l’UC. Cette unité de traitement est constituée de:
      • l’UAL (Unité Arithmétique et Logique) qui réalise les opérations arithmétiques sur des entiers.
      • des registres internes, pour stocker de manière très provisoire les retenues des calculs par exemple.

    L’UC traite une séquence d’instructions, alors que l’UAL traite une séquence de données. L’UC est chargée de la reconnaissance des instructions et de leur exécution par l’unité de traitement au rythme de l’horloge.

    Le cycle Von Neumann

    Le processeur réalise le cycle de Von Neumann:

    1. Lire une case mémoire d’adresse PC (envoyer l’adresse à la mémoire, et recevoir en retour la donnée à cette adresse).
    2. Interpréter cette donnée comme une instruction, et l’exécuter
    3. Ajouter 1 au program Counter (PC), qui stocke l’adresse de la prochaine instruction.
    4. Recommencer

    Détail d’un cycle d’execution

    Important:

    Le processeur ne manipule pas directement les données mais leurs adresses.

    Des registres servent à lire et écrire les données en mémoire. Ce sont les registres d’adresse et de données.

    Utilisation des registres en lecture: rôle de l’unité de contrôle

    • registre d’adresse: stocke l’adresse de la donnée, avant d’envoyer le signal de lecture
    • registre de données: la mémoire va chercher le contenu de l’adresse qui lui est envoyée, et retourne la donnée vers le registre de données.

    La donnée peut être interprétée comme une instruction. Celle-ci est alors décomposée en un code d’opération (OP) ainsi qu’en 2 opérandes, qui sont les adresses d’une données (A et B). OP, A et B sont stockés dans le registre d’instruction (RI).

    Execution de l’opération: rôle de l’unité de traitement

    La figure ci-contre représente un schéma classique d’UAL. Celle-ci possède deux entrées A et B sur lesquelles on présente les données à traiter. L’entrée F désigne l’opération à effectuer (vient du code OP). Source: wikipedia - Unité Arithmétique et Logique

    Enfin, l’UAL possède deux sorties, R qui est le résultat de l’opération, et D les éventuels drapeaux. (information d’erreur ou de dépassement)

    UAL - Unité Arithmétique et Logique

    UAL - Unité Arithmétique et Logique

    Utilisation en écriture

    • registre d’adresse: envoie à la mémoire l’adresse pour l’écriture
    • registre de données: envoie la donnée à la mémoire, qui va écrire celle-ci à l’adresse reçue.

    Travail pratique

    programmer en assembleur

    Liens

    assembleur

    Cours:

    • Histoire et modèle d’architecture Von Neumann / Harvard: Lien
    • Le fonctionnement d’un processeur: Lien
    • Langage assembleur: Lien

    Séquence composée de 3 TP:

    • TP1 Composer son ordinateur à partir d’un site commercial: Lien
    • TP2: Comment fonctionne un processeur? Lien
    • TP3: Programmes plus evolués, de python à l’assembleur: Lien

    Le langage assembleur

    Le langage assembleur est, en programmation informatique, le langage de plus bas niveau qui représente le langage machine sous une forme lisible par un humain. (wiki)

    L’assembleur oblige à programmer la gestion des mémoires:

    Pour échanger des données avec la mémoire, le processeur transfert l’état d’un registre dans une case mémoire (STR) ou l’état d’une case mémoire dans un registre (LDR). On rappelle que la mémoire contient à la fois les instructions et les données. Mais les calculs du processeur se font sur les registres. Il faut donc prévoir de charger les valeurs de la RAM vers les registres avant de faire une opération.

    D’ailleurs, une instruction machine est une chaine binaire composée de 2 parties:

    • un champ “code opération” qui indique au processeur le type de traitement à effectuer.
    • un champ opérande qui indique l’adresse des données.

    Le simulateur

    • Lancer le simulateur
      clic droit > ouvrir dans un nouvel onglet pour lancer le simulateur ARM

      clic droit > ouvrir dans un nouvel onglet pour lancer le simulateur ARM

    Les 3 familles d’instructions machine

    Ce sont les instructions:

    • de transfert de données
    • arithmétiques
    • de rupture de séquence

    Transfert de données

    Les opérations de transfert se font d’un registre vers un emplacement mémoire, ou l’inverse.

    Ordre Instruction Description en langage naturel
    Affectation (variable) x: 23 Place 23 dans la variable x, c’est à dire 23 dans l’emplacement RAM prévu pour x
    Affectation (registre) MOV R1, #23 Place la valeur 23 dans le registre R1
    Charger LDR R1, 78 LOAD: Place dans le registre R1 la valeur stockée à l’emplacement 78 de la RAM
    Stocker STR R1, 151 STORE: Place dans la RAM à l’emplacement 151, la valeur stockée dans le registre R1
    Stocker STR R1, x STORE: Place dans la RAM à l’emplacement prévu pour x, la valeur stockée dans le registre R1

    Exemple 1:

    Le programme suivant affecte une valeur dans un registre, puis la copie dans la RAM.

          MOV R0, #16
          STR R0, 55
          HALT

    Copier-coller le script, assembler. Régler le bouton OPTIONS sur hex

    question a: Vérifier que 16 (base 10) = 10 (base 16).

    question b: Combien de lignes fait le programme? Quelles sont les adresses dans la RAM des instructions (donner la somme colonne + ligne)?

    Dérouler le script pas à pas (appuis successifs sur STEP)

    question c: Quel est le registre utilisé? Quelle est la valeur déplacée? Quelle adresse de la RAM va contenir la valeur à stocker?

    question d: Si l’on suppose que la complexité temporelle est égale au nombre de fois qu’il faut appuyer sur le bouton STEP pour arriver à la dernière ligne du programme: Quelle est la compléxité de ce programme?

    Exemple 2: Programme mystère

    Dans un programme en assembleur, il sera plus facile de manipuler des variables que des adresses mémoires.

          LDR R0, x
          LDR R1, y
          STR R0, y
          STR R1, x
          HALT
          0
          0
          0
    x:    23
    y:    18

    Copier-coller le script, assembler.

    question a: Vérifier que 23 (base 10) = 17 (base 16), et que 18 (base 10) = 12 (base 16).

    question b: Combien de lignes fait le programme? Quelles sont les adresses dans la RAM des instructions (donner la somme colonne + ligne)? Quelles sont les adresses RAM des données?

    Dérouler le programme à vitesse réduite.

    question c: Interpréter les lignes 0 à 4 du programme (donner une explication en langage naturel). Que fait le programme mystère?

    Arithmétique

    Ce sont les opérations courantes (addition, soustraction, multiplication par 2, division par 2). Elles se font depuis un registre, vers un autre registre.

    Voici une liste non exaustive des instructions du simulateur ARM

    Les instructions de traitement suivantes concernent uniquement les registres.

    L’un de ces registres est le Program Counter, PC. Celui-ci repère l’état courant dans le programme (la ligne du script à executer).

    Ordre Instruction Description en langage naturel
    Ajouter ADD R0, R1, #16 Ajoute 16 à R1 et place le résultat dans R0
    Ajouter ADD R0, R0, R1 Ajoute R1 à R0 et place le résultat dans R0
    Soustraire SUB R0, R0, #16 Soustrait 16 à R0 et place le résultat dans R0
    Ajouter ADD R0, R1, #16 Ajoute 16 à R1 et place le résultat dans R0
    Multiplier par 2 LSL R0, R0, #1 déplace les bits de R0 d’un seul rang (#1) vers la gauche et place dans R0
    Diviser par 2 LSR R0, R0, #1 déplace les bits de R0 d’un seul rang (#1) vers la droite et place dans R0

    Exemple 3 add: programme qui ajoute 2 nombres entrés par l’utilisateur

    • INP R0,2: attend un nombre en entrée.
    • OUT Rd, nombre: affiche à l’écran. out Rd,4 affiche un nombre signé ou non(Rd,5). Rd,6 affiche en hexadécimal et Rd,7 affiche un caractère.
          INP R0,2
          INP R1,2
          ADD R2,R1,R0
          OUT R2,4
          HALT

    question a: Ce programme, permet-il d’additionner des nombres relatifs, comme par exemple: $123 + (-145)$? Quelle est alors la représentation binaire de $-145$?

    question b: Recopier sur votre cahier le script correspondant en python:

    x = int(input('entrer la valeur de x'))
    y = int(input('entrer la valeur de y'))
    x = x + y
    print(x)

    question c: Compléter le programme assembleur qui multiplie par 2 le nombre saisi par l’utilisateur (avec LSL), affiche le résultat, et le stocke dans la RAM à l’emplacement 10.

         INP R0,2
         LSL R0, R0, ...
         OUT R0, 4
         STR ..., ...

    question d: Ecrire dans votre cahier le script correspondant en python.

    Rupture de séquence

    Les ruptures de séquence utilisent des étiquettes, à définir dans le programme. Le programme va alors s’executer normalement, ligne après ligne, sauf si un branchement l’amène à une ligne, portant une etiquette.

    • HALT: arrêt du programme

    • CMP Ri, Rj: effectue la comparaison entre Ri et Rj. Attention, cette instruction ne traite pas le résultat de la comparaison! C’est le rôle de la commande suivante.

    • B ou BGT, … sont les opérations de branchement

    plus grand que: On utilise une combinaison de 2 lignes pour effectuer le test si R1 > R2 aller à la ligne label:

    CMP R1, R2
    BGT label

    plus petit que: On utilise une combinaison de 2 lignes pour effectuer le test si R1 < R2 aller à la ligne label:

    CMP R1, R2
    BLT label

    est egal à: On utilise une combinaison de 2 lignes pour effectuer le test si R1 == R2 aller à la ligne label:

    CMP R1, R2
    BEQ label

    aller systematiquement à: B label va obliger à toujours revenir à la ligne d’etiquette label

    La liste complète des instructions se trouve à la page INFO accessible depuis le bouton info du simulateur.

    Exemple 4 max: programme qui retourne le plus grand des 2 nombres saisis par l’utilisateur

    Ce programme peut être directement chargé depuis le bouton SELECT du simulateur.

    0     INP R0,2
    1     INP R1,2
    2     CMP R1,R0
    3     BGT HIGHER
    4     OUT R0,4
    5     B DONE
    HIGHER:
    6     OUT R1,4
    DONE:
    7     HALT
          // Input two numbers and output the higher

    Dans ce 2eme exemple, si R1 est supérieur à R0 (test à la ligne 2), alors le programme effectue un branchement conditionnel à la ligne 3 (BGT est le branchement pour Greater Than).

    Si R1 > R0, alors le programme passe directement de la ligne 3… à celle dont l’etiquette est HIGHER, donc à la ligne 6.

    Sinon il passe à la ligne 4 (OUT R0,4), ce qui est le cours naturel de lecture du programme, ligne après ligne. Le branchement à la ligne suivante, B DONE le renvoie à la ligne d’etiquette DONE. Ce qui evite d’executer OUT R1,4 qui est réservé au branchement HIGHER.

    Remarque: on peut choisir n’importe quelle nom pour l’etiquette que l’on met dans le programme: HIGHER, TEST, DONE, … peu importe.

    question a: qu’est ce qui est affiché si l’on saisit la valeur 18 pour R0 et 9 pour R1? Puis 10 pour R0 et 20 pour R1?

    question b: à quoi sert la ligne 6 B DONE? Que se passerait-il si cette ligne n’y était pas, et que l’on saisit la valeur 18 pour R0 et 9 pour R1?

    question c: Ecrire dans votre cahier le script correspondant en python.

    Exemple 5: boucle infinie

    Le programme s’execute de la manière suivante: ligne 0 (affectation de la valeur 16 au registre R0), puis ligne 1 (on definit une etiquette boucle), puis ligne 2 (addition R0+1), puis ligne 3, ligne 4, …

          MOV R0, #16
    boucle:
          ADD R0, R0, #1
          OUT R0,4
          B boucle
          HALT

    question a: Pourquoi le programme s’appelle-t-il boucle infinie?

    Le test conditionnel if R0 > 20: break, qui va permettre de sortir de la boucle va s’écrire en assembleur:

    CMP R0, #20
    BGT break

    L’étiquette break devra alors être placée après celle B boucle afin de pouvoir poursuivre le programme.

    question b: Ré-écrire le script précédent afin de sortir de la boucle lorsque R0 stocke une valeur supérieure à 20.

    Programmer avec des boucles

    Prog 1: Calculer 1+2+3…+n où n est entré au clavier:

    Compléter le programme en assembleur ci-dessous pour résoudre le problème puis essayer avec n = 3 en mode pas à pas.

    Exécuter avec RUN en vitesse maximale pour n = 10

    INP R0,2
    MOV R1,#0 // compteur de boucle
    MOV R2,#0 // somme 
    boucle:
    ADD ...........
    ADD ...........
    CMP ...........
    .... boucle
    OUT R2,4
    HALT

    questions prog 1.

    • Estimer le nombre d’opérations significatives effectuées pour n = 10.
    • Estimer le nombre d’opérations significatives qui seraient réalisées pour n = 100.
    • Ecrire dans votre cahier le script correspondant en python.

    Prog 2: boucle while

    Ecrire le programme assembleur équivalent:

    x = 0
    while x < 3:
          x = x + 1
    print(x)

    A la fin du programme, la variable x doit être égale à 3.

    Astuce: Le while est suivi d’une condition d’execution (x<3). Ici, en assembleur, on utilise plutôt une condition d’arrêt.

    Ainsi, l’instruction python while x<3 sera écrite à l’aide de plusieurs lignes en assembleur:

    CMP R0,#3
    BEQ sortieboucle
    ...
    B revenirwhile

    questions prog 2.

    • Quelle est la condition d’arrêt correspondante?
    • Ecrire dans votre cahier le script complet en assembleur.

    Prog 3: Pair/Impair

    Ecrire en assembleur un programme utilisant des fonctions parmi LSL, LSR, B et BNE qui affiche 1 si le nombre est pair , 0 sinon. (BNE: Branchement si Not Equal).

    n = int(input('entrer un nombre'))
    x = n//2
    x = n * 2
    if n == x:
          print(1)
    else:
          print(0)

    question prog 3.

    • Ecrire dans votre cahier le script complet en assembleur.

    Tuto: simulateur

    • Explications en video
      Explications (video) sur le simulateur ARM -

      Explications (video) sur le simulateur ARM -

    Liens

    Donnees

    Sous-sections de Donnees

    Denombrer

    Données, machines, algorithmes, langages

    Dénombrer: du comptage au calcul mécanique

    1. Ecriture des nombres: (Bordas p9)

    mots clés: le statut de nombre, base 10, 2, 16, Leibniz et le binaire

    Systeme de numération égyptien et gréco-romain (source:Bordas NSI)

    Systeme de numération égyptien et gréco-romain (source:Bordas NSI)

    Voir la page dédiée dans la partie SNT sur la numération au cours des ages: Lien

    2. Les abaques et le boulier

    Comment additionne t-on deux nombres avec un abaque?

    Un abaque est le nom donné à tout instrument mécanique plan facilitant le calcul.

    Au départ, une opération aussi simple que l’addition demande de la mémoire, d’utiliser les doigts de la main, ou des artefacs (petits cailloux ou des petits jetons en argile) : jusqu’à 3300 ans avant JC, voire plus tard selon les civilisations.

    Puis les abaques ont permi d’exploiter la numération de position en base 10 en séparant les unités des dizaines, centaines, et plus, avec des jetons en colonnes.

    La colonne la plus à droite étant celle des unités, celle à sa gauche, les dizaines, …

    Reconstitution d'un abaque romain

    Reconstitution d'un abaque romain

    La méthode est expliquée ici avec un container de billes, mais elle peut être adaptée facilement à l’usage du boulier…

    • On dispose les billes dans chaque colonne (centaine à gauche, puis dizaine et unité à gauche). Les nombres à additionner sont écrits sur 2 rangées, l’une sous l’autre.
    104 + 17 - debut

    104 + 17 - debut

    • On deplace les billes dans l’une des rangées
    104 + 17 - etape 2

    104 + 17 - etape 2

    • On rassemble les billes par 10 lorsqu’il y a un depassement dans l’une des colonnes, et on les remplace par une retenue dans la colonne plus à gauche.
    104 + 17 - etape 3

    104 + 17 - etape 3

    • On peut alors exprimer le résultat: 104 + 17 = 121

    104 + 17 - resultat

    104 + 17 - resultat

    Exercice:

    • Représenter les étapes de la soustraction de 15 à 103 à l’aide de ce même abaque.

    Le boulier

    Le boulier est un dispositif mécanique d’aide au calcul. Il est lié au système de numération décimale.

    Youtube: Les bouliers - Micmaths

    Youtube: Les bouliers - Micmaths

    Exercice:

    • Représenter les étapes de la multiplication de 6 par 4 avec un boulier à 10 unités.
    • Représenter les étapes de la division de 32 par 8 avec ce même boulier.
    • Pourquoi l’auteur de la video avance t-il que le disque mécanique est une amélioration importante par rapport aux colonnes droites de billes?
    • Quel est le problème qui survient lorsque l’on compte avec le disque numéroté?

    3. Circuits électroniques à 2 états

    Ce manuscrit exceptionnel, écrit par Leibniz à 33 ans mais non publié, fait le lien entre deux de ses travaux majeurs, paraissant a priori indépendants : son idée du calcul binaire et son idée de machine à calculer décimale. Ce manuscrit apparaît à ce jour comme la plus ancienne évocation d’un calculateur binaire.

    manuscrit sur la numération binaire - Leibnitz

    manuscrit sur la numération binaire - Leibnitz

    Cours: Représentation des entiers positifs

    Numération additive

    Pour la numération additive, la lecture d’un nombre se fait en additionnant les valeurs de chacun des chiffres-caractères.

    Exemple: la numération egyptienne

    Exemple: la numération egyptienne

    Numération de position

    La numération de position permet d’écrire un nombre avec les mêmes symboles pour les rangs 0, 1, 2, etc… Le rang zero étant le plus à droite. Le poids d’un chiffre dépend de son rang:

    $$Poids = Base^{rang}$$

    La numération de position implique d’utiliser un symbole pour le zero.

    Base

    Une base est un nombre qui permet de décomposer un nombre entier dans une numération de position:

    • Base 10:

    division euclidienne de 4 par 2

    division euclidienne de 4 par 2

    Pour convertir un nombre N décimal dans la base 2, on réalise la division par 2 de N puis des quotients de ses divisions, jusqu’à ce que le quotient arrive à 0.

    Le resultat de la conversion en base 2 est la série de valeur obtenues pour les restes. Le dernier reste obtenu est celui de poids le plus fort:

    conversion: 4

    conversion: 4

    Exemples et visuels

    Visuels:

    • principe de gestion mecanique de la retenue
    Youtube: How mechanical counters work, gears

    Youtube: How mechanical counters work, gears

    • Overflow avec un compteur mécanique
    Youtube: How mechanical counters work, overflow

    Youtube: How mechanical counters work, overflow

    Mémoires

    Les différents supports de stokage utilisés pour les ordinateurs modernes sont présentés [ici (wikipedia, mémoires informatiques)(https://fr.wikipedia.org/wiki/M%C3%A9moire_(informatique)#Mat%C3%A9riel_informatique)

    Le codage binaire (2 états) se fait à l’aide:

    • d’une piste pouvant avoir 2 polarités magnétiques (disque dur, disquette)
    • un creux ou une bosse sur un support (DVD, CD-ROM)
    • materiaux reflechissant ou non reflechissant (CD-ROM à graver)
    • condensateur chargé ou déchargé (mémoire RAM, registres)

    Les techniques de stockage mécaniques, par exemple par rubans perforés ont été largement utilisés dès le début de l’informatique, puis abandonnés au profit de supports plus pratiques et plus rapides

    entiers naturels, relatifs et decimaux

    Entiers naturels

    Un entier naturel (positif ou nul) se code en base 2 : chaque bit représente une puissance de 2, exactement comme chaque chiffre décimal représente une puissance de 10 en base 10.

    Exemple: sur 8 bits, le nombre 0000 1011 vaut :

    $$0{\times}2^7+0{\times}2^6+0{\times}2^5+0{\times}2^4+1{\times}2^3+0{\times}2^2+1{\times}2^1+1{\times}2^0 = 8+2+1 = 11$$

    Capacité de codage

    Avec $n$ bits, on peut coder $2^n$ valeurs différentes, comprises entre $0$ et $2^n - 1$ (car il faut compter la valeur 0).

    nombre de bits ($n$) nombre de valeurs codables ($2^n$) intervalle des entiers représentables
    4 16 [0 ; 15]
    8 256 [0 ; 255]
    16 65 536 [0 ; 65 535]
    32 4 294 967 296 [0 ; 4 294 967 295]

    Plus on dispose de bits, plus l’intervalle des valeurs représentables est grand, mais il reste toujours fini : il faut choisir à l’avance le nombre de bits utilisés pour coder un entier.

    Dépassement de capacité (overflow)

    Si le résultat d’un calcul dépasse la plus grande valeur codable sur le nombre de bits alloué, on parle de dépassement de capacité (ou overflow). La retenue supplémentaire ne peut pas être stockée : elle est perdue, et le résultat obtenu est alors complètement faux.

    Exemple: sur 8 bits, 1111 1111 (soit 255) additionné à 0000 0001 (soit 1) devrait donner 256. Mais 256 nécessite 9 bits pour être codé : le 9ᵉ bit est perdu et il ne reste que 0000 0000, soit… 0 !

    C’est ce type d’erreur qui est à l’origine de la destruction de la fusée Ariane 5, 37 secondes après son décollage en 1996 : une valeur de vitesse, trop grande pour le nombre de bits alloué à son codage, a provoqué un dépassement de capacité et un plantage du logiciel de guidage (ce bug, plus précisément, concerne la conversion d’un nombre à virgule flottante, notion que nous verrons plus loin dans ce cours).

    Short YouTube de L'aventure Ariane 5

    Short YouTube de L'aventure Ariane 5

    $370 Million Software Bug

    $370 Million Software Bug

    Entiers relatifs

    nombres signés

    Les entiers signés sont positifs, negatifs ou nuls. Comme il n’est pas possible d’écrire, comme nous le faisons normalement, un nombre négatif avec un signe (-) devant, il va falloir utiliser une nouvelle convention.

    La première idée est de reproduire le signe en utilisant le bit de poids fort du nombre pour le représenter. Les n – 1 bits restants donnent la valeur absolue binaire du nombre.

    Problèmes:

    • 2 représentations pour le zero
    • arithmetique plus difficile: on ne peut pas utiliser le même algorithme que pour l’addtion de 2 nombres positifs.

    Représentation en complément à 2

    C’est la représentation standard sur les ordinateurs pour exprimer les nombres entiers négatifs. Quand on parle de représentation signée ou d’entiers signés, ces derniers sont toujours exprimés à l’aide de la représentation en complément à 2.

    Définition

    Sur n bits, on exprime les nombres de l’intervalle $[–2^{(n-1)}; 2^{(n – 1)}– 1]$ selon les 2 règles suivantes:

    • Un nombre positif est représenté de façon standard par son écriture binaire.
    • un nombre négatif est représenté en ajoutant 1 à son complément à 1 (obtenu en inversant tous les bits) et en laissant tomber une éventuelle retenue finale.

    il est important d’indiquer sur combien de bits doit s’écrire le nombre car on ne rajoute pas des zéros en tête mais 1…

    Intérêt : on n’a plus à se préoccuper du signe des nombres avant d’effectuer l’opération.

    Exemple:

    Soit l’entier signé - 127 (1000 0001) que l’on additionne à 127 (0111 1111):

    Représentation des nombres décimaux

    nombres fractionnaires

    Un nombre avec virgule, exprimé en base décimale peut être représenté comme une somme de puissances de 10:

    écriture d'un nombre à virgule en base 10

    écriture d'un nombre à virgule en base 10

    • Les puissances de 10 positives pour la partie entière (à gauche de la virgule)
    • les puissances de 10 negatives pour la partie après la virgule

    En base 2, le nombre peut aussi s’écrire avec une virgule, et être lu comme une somme en puissance de 2:

    écriture du même nombre en base 2

    écriture du même nombre en base 2

    • Les puissances de 2 positives pour la partie entière (à gauche de la virgule)
    • les puissances de 2 negatives pour la partie après la virgule

    Pour représenter des nombres avec une partie fractionnaire, décomposer la partie fractionnaire en puissances inverses de 2:

    $2^{-1}$ $2^{-2}$ $2^{-3}$ $2^{-4}$ $2^{-5}$ $2^{-6}$ $2^{-7}$ $2^{-8}$
    1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256
    0,5 0,25 0,125 0,0625 0,03125 0,015625 0,0078125 0,00390625

    Lorsque l’on représente la partie décimale de 0.375, on a une valeur exacte que l’on peut coder sur 1 seul octet:

    conversion binaire de la partie décimale .0375

    conversion binaire de la partie décimale .0375

    Le problème est que la représentation d’un nombre peut être finie dans une base donnée, et être infini dans une autre:

    conversion binaire de la partie décimale .1

    conversion binaire de la partie décimale .1

    Si on n’utilise que 8 bits pour la partie décimale de 0.1, la valeur numérisée vaut alors:

    $$\tfrac{1}{16} + \tfrac{1}{32} + \tfrac{1}{256} = 0.09765625$$

    Ce qui est très éloigné de la réalité…

    Il existe une méthode systématique pour déterminer les bits de la partie fractionnaire. Voir le Bordas p18, §5.

    codage en virgule fixe

    Une première idée pourrait être d’utiliser 2 octets:

    • 1 octet pour la partie entière. Si le nombre est signé, cela veut dire que le nombre est compris, pour sa partie entière entre -128 et 127.
    • 1 octet pour la partie décimale. Cette partie est alors codée sur 256 valeurs, selon la méthode vue plus haut).

    Il y a alors 2 problèmes avec cette représentation:

    Problème 1: La partie fractionnaire va manquer de précision. Il n’y aura pas assez de chiffres significatifs lors de l’approximation. L’écart avec la valeur vraie du réel peut être trop important si on veut une précision raisonnable

    Problème 2: Certains nombres ont une représentation avec un nombre fini de chiffres après la virgule dans la base 10, mais infinie dans la base 2. (voir la cas du 0.1 vu plus haut, qui est approximé à 0.09765625).

    Ces approximations sont alors la source d’erreurs de calcul en python:

    somme de 0.1 + 0.2 en python

    somme de 0.1 + 0.2 en python

    codage en virgule flottante: norme IEE754

    Principe

    Pour un ordinateur, TOUT est discrêt: cela signifie que les nombres réels seront approchés par des nombres dits à virgule flottante.

    Ces nombres avec une partie décimale sont représentés sur ordinateur selon la norme IEEE 754.

    Ce codage revient à représenter le nombre sous la forme:

    $$+/-1,M.2^E$$

    Cette forme rappelle ainsi l’écriture en notation scientifique.

    M s’appelle la mantisse du nombre et E l’exposant. Comme la mantisse commence toujours par une partie entière égale à 1, on ne l’écrit pas et on n’exprime que la partie fractionnaire, M

    Selon la précision, dite simple ou double, le nombre M est constitué de 23 bits ou bien de 52 bits.

    precision bit de signe E M
    simple 1 8 23
    double 1 11 52

    Selon cette norme IEEE 754, en 32 bits (simple precision):

    • Le premier bit est celui du signe
    • les 8 bits suivants sont les bits de l’exposant E, exprimé en nombre relatif. Ce qui permet de coder l’exposant avec des valeurs comprises dans l’intervalle [-127; 128]
    • les bits restants sont ceux de M

    Cette méthode est-elle précise?

    En raison du nombre limité de bits de la représentation, les calculs en virgule flottante ne peuvent pas atteindre une précision infinie.

    Exemple: Soit la nombre 500 à coder en IEEE 754:

    $$500=1,953125×2^8 =(1+2^{−1} +2^{−2} +2^{−3} +2^{−4} +2^{−6} )×2^8$$

    Cela donne alors notation binaire:

    $$0~10000111~11110100000000000000000$$

    On a un bit de signe égal à 0, un exposant égal à 8 + 127 et les premiers bits de la pseudo-mantisse qui exprime 0,953125.

    Pour représenter des constantes physiques:

    • Vers l’infiniment grand, le nombre d’Avogadro vaut $6,0221.10^{23}$. Celui-ci, exprimé avec 5 chiffres significatifs, suffit à la plupart des calculs scientifiques.
    • Vers l’infiniment petit, la masse du proton est $9,1094.10^{-31}$. Avec 5 chiffres significatifs.

    Avec la norme IEE754 sur 32 bits, les exposants de 2 varient de -126 à 127. Ce qui correspond à peu près à $\pm 10^{38}$. Et le nombre de chiffres significatifs est sur 23 bits, ce qui signifie que la partie décimale est représentée avec 7 chiffres significatifs.

    La multiplication et division par 2 d’un nombre binaire

    La multiplication par 10 d’un nombre exprimé en base 10 va décaler la virgule vers la droite. Par exemple:

    $$8,314 \times 10 = 83,14$$

    De la même manière, pour un nombre binaire:

    • la multiplication par 2 décale sa virgule vers la droite
    • la division par 2 décale sa virgule vers la gauche

    Exemple avec la multiplication binaire: (nombres exprimés en binaire, sans faire référence à la norme IEE754)

    $$1010.101 + 1010.101 = 10101.01$$

    Conclusion

    Les règles de calcul en binaire seront les mêmes, que les nombres binaires soient des entiers naturels, relatifs, fractionnaires.

    Un même mot-binaire peut représenter un entier naturel, relatif, fractionnaire. Il faut donc bien distinguer un nombre de sa représentation.

    Exercices sur les nombres fractionnaires

    Norme IEEE 754

    Le nombre suivant est écrit dans la norme IEEE 754:

    $0~10000111~11110100000000000000000$$

    Repérer dans ce nombre:

    • le bit de signe
    • les bits correspondant à l’exposant
    • les bits de la mantisse

    Mantisse

    Pour les questions suivantes, utiliser le tableau des puissances négatives de 2:

    $2^{-1}$ $2^{-2}$ $2^{-3}$ $2^{-4}$ $2^{-5}$ $2^{-6}$ $2^{-7}$ $2^{-8}$
    1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256
    0,5 0,25 0,125 0,0625 0,03125 0,015625 0,0078125 0,00390625

    question a: On donne la partie fractionnaire d’un nombre binaire (la mantisse):

    $$1110~0000$$

    Donner la valeur correspondante en base décimale.

    question b: La partie fractionnaire suivante (mantisse) est une approximation de 0,1:

    $$0001~1001$$

    Vérifiez le par un calcul

    question c: Une meilleure approximation de 0,1 est donnée par le nombre fractionnaire suivant (mantisse):

    $$0001~1001~1001~1001~1001...$$

    Que constatez-vous?

    question d: Lorsque l’on réalise l’addition binaire suivante, en python, on obtient un résultat approché et incorrect. Pourquoi?

    >>> 0.1 + 0.2
    0.30000000000000004

    Multiplication et division par 2

    On utilise une représentation binaire avec une virgule flottante. A gauche de la virgule, le nombre binaire se lit d’une manière classique, comme pour les entiers naturels. A droite de la virgule, il s’agit de la partie fractionnaire en puissance négatives de 2.

    question a: Quel est la valeur en base 10 de $0.1$(binaire). Calculer $0.1$(binaire) multiplié par 2.

    question b: Quelle est la valeur binaire de $1101.1100$(binaire) divisé par 2?

    Norme IEEE 754 à 5 bits

    Pour l’exercice nous inventons une nouvelle norme: la IEEE 754 à 5 bits. Avec 5 bits, nous pouvons coder 25 nombres flottants. La precision est alors de 2 chiffres significatifs (taille en bits de la mantisse). Le format binaire est ainsi:

    Voici la liste des 16 positifs :

    Supposons que l’exposant E se calcule d’après e selon la règle suivante:

    $$E = e - 1$$

    Question: écrire les nombres binaires correspondants à ces 16 positifs.


    Rappelez vous que le nombre s'écrit sous la forme: $$+/-1,M.2^E$$

    Liens

    coder les caracteres et couleurs

    Codage des caractères

    Un texte est une chaine de caractères et de symboles (dont l’espace, virgule…). La représentation du texte dans l’ordinateur suit ce même schéma : c’est le rangement à des emplacements consécutifs de la mémoire des représentations des caractères un à un. Il existe plusieurs normes d’encodage des caractères.

    Code ASCII

    Une des première normes a été l’ASCII (American Standard Code for Information Interchange), qui est apparue aux états unis, à l’époque où les ordinateurs n’étaient pas connectés en reseau.

    table ascii pour les nombres 0-127

    table ascii pour les nombres 0-127

    Le problème de l’encodage ASCII est qu’il ne permet pas de représenter assez de caractères pour les besoins des différentes langues.

    Une autre norme, encore utilisée est l’ASCII étendu, dont les caractères sont encodés sur 8 bits.

    table ascii-Latin1 pour les nombres 128-255

    table ascii-Latin1 pour les nombres 128-255

    Il existe plusieurs tables ascii-étendu, celle présentée ici est celle Latin1, utile pour les caractères du français et autres langues d’europes de l’ouest.

    En ASCII étendu: 1 octet par caractère. On peut évaluer la taille d’un fichier: C’est le nombre N caractères, exprimé en octets.

    informations sur un fichier textuel (Word)

    informations sur un fichier textuel (Word)

    La principale limitation des jeux de caractères codés sur un octet, comme l’ascii-Latin1, est la nécessité d’utiliser plusieurs jeux de caractères codés pour couvrir plusieurs alphabets.

    Attention à la compatibilité avec les documents web:

    Les jeux de caractères en un seul octet ne sont pas compatibles avec la norme actuelle, l’utf-8 (voir plus loin).

    Le e accent aigû é sera représenté en utf-8 par 16 chiffres binaires, et son affichage en format ASCII donnera é.

    ascii ou utf8

    ascii ou utf8

    Dans un document HTML, on pourra tout de même afficher correctement ces caractères, mais il faudra:

    • soit utiliser une entité HTML, c’est à dire une combinaison de symboles connus par le navigateur comme par exemple: &eacute; pour la lettre é
    • soit choisir un encodage UNICODE ou utf-8

    Les normes suivantes vont proposer des formats qui vont:

    • être compatibles avec l’ASCII 7 bits, pour faire évoluer le web tout en restant retro-compatible avec la plus ancienne et la plus internationale des normes
    • permettre l’encodage de TOUS les caractères existants ou à venir

    Unicode

    Le répertoire Unicode se décline en utf-8, utf-16 et utf-32, qui sont de largeur variable ou fixe (pour utf32) Le code UNICODE permet de représenter tous les caractères spécifiques aux différentes langues.

    Cette gigantesque table est divisée en 17 plans (de 0 à 16) de deux octets chacun, soit 65 536 points de code par plan (65 536 x 17 = 1 114 112). Ces plans permettent de désigner facilement des groupes de caractères. Le premier plan, appelé Basic Multinlingual Plane (BMP), ou Plan Multinlingue de Base, regroupe les 65k caractères les plus courants. Les plans 1 à 16 sont appelés plans supplémentaires.

    L’inconvenient des encodages à largeur fixe (utf-32) est qu’ils vont générer des fichiers de poids important (poids compté en kilo octets). Bien plus lourd que l’encodage ASCII. Alors que bien souvent, la plupart des caractères utilisés pour un document texte sont ceux de l’alphabet ASCII, avec quelques caractères spéciaux.

    Code à largeur variable utf-8 et utf-16

    • Cet encodage utilise l’ASCII pour les caractères dont le point de code est inférieur ou égal à 127.

    • Chaque caractère dont le point de code est supérieur à 127 (0x7F) (caractère non ASCII) se code sur 2 à 4 octets.

    La longueur du nombre binaire est alors variable. Un caractère peut nécessiter 8 (ascii), 16 bits, ou plus (jusqu’à 32). Une information dans le code numérique va préciser cette longueur (correspond à un caractère spécial comme le Ã). Cela va permettre d’afficher tous les caractères. Cela génère un fichier dont le poids sera inférieur à l’utf-32.

    Pour le système d’exploitation Windows, l’encodage par defaut est l’utf-16. MacOs utilise un encodage utf-8.

    image issue de wikipedia utf8

    image issue de wikipedia utf8

    Lien wikipedia

    La séquence binaire contient alors un premier code qui indique la longueur de bits à venir. C’est comparable au système utilisé pour les masques de sous-reseau.

    0bbbbbbb 1 octet codant 1 à 7 bits

    110bbbbb 10bbbbbb 2 octets codant 8 à 11 bits

    Ainsi, le caractère é est représenté en utf-8 par la séquence binaire 11000011 10101001. Parmi les chiffres binaires, seuls ceux en gras sont codants pour la valeur numérique associée à ce caractère. Il s’agit donc de 000 1110 1001. C’est la valeur E9 en hexadécimal. (233 en décimal).

    Avec un encodage ASCII, le navigateur essaiera d’afficher 2 symboles. Celui de code binaire 1100 0011, qui correspond au Ã, le A majuscule tilde. Et celui de code binaire 1010 1001 affichera le ©, symbole copyright.

    Codage des couleurs

    Colorer avec une règle CSS

    Les valeurs de couleur peuvent être codées de manière numérique en décimal ou bien en hexadécimal. Voici 2 exemples d’expression de la couleur en CSS:

    /*vert clair*/
    color: #00a400;
    /*rouge pâle*/
    color: rgb(214, 122, 127);

    synthèse additive des couleurs

    Pour une image en couleur: À chaque pixel on associe 3 couleurs, le rouge, le vert et le bleu. On parle du canal rouge, du canal vert et du canal bleu d’un pixel (système RVB ou RGB en anglais).

    credit - photograpix.fr/blog

    credit - photograpix.fr/blog

    La valeur de l’intensité lumineuse associée à chaque canal de chaque pixel d’une image est comprise entre 0 et 255 (256 valeurs possibles). On codera donc un pixel à l’aide d’un triplet de valeur (par exemple (247,56,98) en code décimal, ou son équivalent en hexadecimal : (f7,38,62)

    Question a: Reproduire et compléter l’image du cercle chromatique, représentant la synthèse additive des couleurs. (placer les termes: Rouge, Vert, Bleu, magenta, cyan, jaune).

    Pour la suite, vous avez le choix entre 2 options:

    • Soit ouvrir le lien suivant : www.proftnj.com/RGB3.htm
    • Soit utiliser le script HTML minimum et modifier la couleur de fond dans la proprieté background-color: rgd();
    <style>
    	body {
    		background-color: rgb(247,56,98);
    	}
    </style>
    <body>
    </body>

    Question b: à l’aide du logiciel : Quelle est la couleur donnée par le triplet de valeurs: (247,56,98)?

    Question c: Combien de couleurs différentes est-il possible d’obtenir avec ce système RVB ? (combinaison de 3 couleurs, codées chacune sur 256 valeurs,…)

    Question d: Pour chacune des couleurs du tableau, indiquer le code couleur RGB décimal correspondant (voir ci-dessous).

    Question e: Précisez la particularité des teintes grises au niveau des valeurs RVB/RGB

    code couleur RGB
    blanc blanc
    bleu bleu
    vert vert
    rouge rouge
    jaune jaune
    gris gris
    noir noir

    codage d'une image

    Coder une image

    Une image: un tableau de pixels

    image pixelisée monochrome

    image pixelisée monochrome

    Comment représenter l’image de ce symbole de manière numérique? Compléter la grille de droite avec les valeurs 0 ou 1.

    L’objet mathematique correspondant est une matrice. C’est un tableau constitué de lignes et colonnes. Le caractère a sera représenté par la matrice M:

    M = [[1,0,0,0,1],
         [1,1,1,1,0],
         [..],
         [..],
         [..],
         [..]]

    M est une liste de lignes, où chaque ligne est aussi une liste.

    Construire une image numérique

    On utilise des boucles simples ou imbriquées, constituées d’une seule ou plusieurs instructions pour peindre les pixels (voir activité sur le site Algorea):

    pixels sur une ligne: boucle simple

    pixels sur une ligne: boucle simple

    faire 6 fois:
      peindre en rouge
    faire 6 fois:
      peindre en bleu
    tableau de pixels. boucles imbriquées

    tableau de pixels. boucles imbriquées

    faire 12 fois:
      faire 6 fois:
        peindre bleu
        peindre rouge
    tableau de pixels. utiliser un variant de boucle

    tableau de pixels. utiliser un variant de boucle

    pour i variant de 0 à 11:
      pour j variant de 0 à i:
        peindre bleu
      pour k variant de i+1 à 11:
        peindre en magenta

    codage de l’image dans un fichier

    Les plus petits détails de l’image sont ses pixels : des petits carrés remplis chacun avec une seule couleur. Coder les pixels de l’image revient à coder les couleurs de ses pixels. Les valeurs des couleurs des pixels sont alors mises les unes à la suite des autres, et constituent ainsi le fichier image en s’ajoutant aux métadonnées.

    P1
    6 5
    0 1 1 1 0 1
    0 0 0 0 1 1
    ...

    Grâce aux métadonnées du fichier, les informations de format (P1, P2, …) et de dimension (6 * 5), l’ordinateur va traiter cette suite de chiffres selon une matrice de valeurs:

    import des données du fichier dans un programme python. Codage des couleurs en 24 bits rgb

    import des données du fichier dans un programme python. Codage des couleurs en 24 bits rgb

    Chaque information va coder la couleur d’un pixel (un petit carré de couleur uniforme). Une fois agrandie, l’affichage ne pourra pas proposer plus d’informations que celles contenues dans le fichier source. C’est pour cette raison que l’image apparait parfois pixelisée.

    image pixelisée couleur

    image pixelisée couleur

    Le poids de cette image : pour 100 pixels sur 100 pixels (10 000 px)

    $$nombre\quad pixels \times 3 octets = 10000\times 3 = 30000 octets $$

    Ce qui correspond à

    $$\tfrac{30000}{1024} = 29ko$$

    Codage d’une image dans un tableau de données

    On a vu en travaux pratiques, que le programme qui permet l’affichage des données en tableau utilise 2 boucles bornées, imbriquées:

    # L est un tableau python 5 * 5
      for j in range(5):
        for i in range(5):
          if L[j][i] == 1 : 
            display.set_pixel(i, j, 9)

    On obtient alors une image de type Noir et Blanc, sur une matrice de diodes 5 * 5.

    Profondeur de couleur

    La représentation bitmap d’une image par une matrice de pixels ne se limite pas à des images binaires en noir (0) et blanc (1).

    En modifiant la profondeur de l’image, on peut coder plus de couleurs dans un pixel

    niveaux de gris

    (voir image plus bas).

    Par exemple, le tableau suivant représente des valeurs allant du plus foncé au plus clair:

    # fichier
    P2
    3 2
    0 50 100 150 200 255
    # matrice
    pix = [[0,50,100],[150,200,255]]

    couleur

    Le codage des couleurs utilise la synthèse additive. Voir animation sur Algorea > SNT V2 > photographie numerique > ambiance lumineuse

    # fichier
    P3
    2 3
    255 0 0 0 255 0 0 0 255 255 255 255
    255 0 0 0 255 0
    # matrice
    pix = [
    [[255,0,0],[0,255,0]],
    [[0,0,255],[255,255,255]],
    [[255,0,0],[0,255,0]]
    ]

    Saurez-vous deviner le codage des couleurs sur cette image?

    certains logiciels de design proposent de faire des essais de coloration. Ici, données en hex

    certains logiciels de design proposent de faire des essais de coloration. Ici, données en hex

    Caractéristiques des images

    Luminosité d’une image

    La luminosité d’une image représente la clarté de l’image. Pour un pixel donné, on peut établir une mesure de la luminosité de la manière suivante : Soient R, V et B les valeurs des intensités de chaque canal coloré. La luminosité L est égale à :

    $$L = R+V+B$$

    Pour calculer la luminosité moyenne d’une image, voici l’algorithme:

    s = 0
    pour chaque ligne:
      pour chaque colonne:
        p <- couleur du pixel
        s = s + (p[0] + p[1] + p[2])/3
    luminosite <- s / (ligne*colonne)

    Pour chaque pixel, on fait la moyenne de ses 3 couleurs primaires.

    On ajoute la valeur à l’accumulateur s. Puis on fait la moyenne des valeurs de s en divisant par le nombre de pixels (ligne*colonne).

    Contraste

    Les deux images présentées dans le paragraphe précédent, sur la luminosité, sont trop peu contrastées pour en apprécier le contenu.

    En effet, l’amplitude de luminosité entre les pixels clairs et les pixels foncés est trop petite. En d’autres termes, les tons sombres et les tons clairs de l’image ont des luminosités qui ont des valeurs trop proches.

    Le contraste mesure la différence de luminosité entre les tons clairs et les tons sombre.

    Exemple :

    image et contrastes

    images faible contraste

    Soient les fonctions recherche_du_max et recherche_du_min qui retournent la valeur du max ou du min dans une liste python simple.

    img est un tableau de valeurs des couleurs en niveau de gris des pixels. Par exemple:

    img = [[101,202,210,255,213,...], 
           [101,202,210,255,213,...], 
           [...]]

    Le programme va parcourir chaque ligne, c’est à dire chaque sous-liste de img.

    Si la fonction max_ligne retourne une valeur supérieure à max, c’est qu’une valeur plus grande d’intensité a été trouvée dans cette ligne. On remet à jour la valeur max de l’image avec max = max_ligne, et on passe à la ligne suivante.

    (même principe pour min_ligne)

    max = 0
    min = 255
    pour chaque ligne de img:
      max_ligne = recherche_du_max(ligne)
      min_ligne = recherche_du_min(ligne)
      si max_ligne > max: max = max_ligne
      si min_ligne < min: min = min_ligne

    Qualité des images

    La définition D d’une image est définie par un nombre de pixels selon la longueur et la largeur de l’image numérique. C’est une caractéristique propre de l’image.

    On l’exprime le plus souvent en donnant les dimensions du plan de pixels, par exemple, une image de définition :

    $$1900 \times 1700~pixels$$

    La résolution R d’une image numérique correspond à sa densité en points (pixels). On mesure la densité de pixels sur l’écran en pixels par pouce (ppi) et la densité de points sur l’image imprimée en points par pouce (dpi). Ce n’est pas une caractéristique de l’image elle-même, mais de sa restitution par un écran (ou imprimé).

    Selon le cas, on calculera la résolution selon l’un des côtés de l’image. Ou bien selon la diagonale de l’iamge.

    La résolution peut s’exprimer en pixels par pouce. On peut en déduire la résolution en pixels par cm à l’aide de la relation suivante

    entre la Définition D, la Résolution R, et le nombre de cm par pouces (2,54).

    $$R(px/cm) = \tfrac{R(px/pouce)}{2,54(cm/pouce)}$$

    En effet : 1 pouce vaut 2,54 cm. Un petit calcul montre que R = 72 ppi correspond à 28,3 pixels pour 1 cm.

    Exemple : Soit une image de définition 800x533 que l’on imprime sur du papier photo de taille 15x10 (en cm), calculez la résolution de cette image en ppp.

    Réponse : On prendra :

    Définition : D = 800px et Longueur : L = 15 cm. On cherche R : resolution

    $$R = \tfrac{D}{L}\times 2,54 = \tfrac{800}{15}\times 2,54 = 135 ppp$$

    Agrandissement et perte de qualité: lorsque le nombre de points codés dans l’image est inférieur au nombre de pixels de l’écran, il n’y a pas assez de points. L’agrandissement va déteriorer l’image, car un même point va être placé sur plusieurs pixels côte à côte. C’est ce que l’on appelle la pixelisation de l’image.

    agrandissement jusqu'à pixelisation

    agrandissement jusqu'à pixelisation

    La selection d’une partie des points de l’image montre qu’il n’y a plus assez de points avec le zoom x12. On peut afficher une image à partir de cet agrandisement, mais il y a pixelisation. (voir la partie sur la transformation d’une image)

    Transformation des images

    Poids d’une image avec/sans compression

    Image matricielle sans compression

    En format brut.

    A partir de ce qui a été vu plus haut, le poids d’une image non compressée de définition D et de profondeur de couleur C a un poids P :

    $$P = D \times C$$

    Exemple : D = 1900 pixels * 1700 pixels et C = 3 octets

    $$P = 1900 \times 1700 \times 3 = 9,7.10^6 octets = 9,7 Mo$$

    En réalité, les images sont compressées. Ce qui permet d’avoir un poids moindre pour leur stockage, leur transfert…

    Image matricielle avec compression

    La compression d’une image c’est la réduction de la quantité d’informations nécessaires pour décrire l’image. Les idées générales sont :

    • De rassembler plusieurs pixels de même couleur, et établir une couleur moyenne des pixels sur une zone donnée.
    • supprimer des informations : par exemple en diminuant le nombre de couleurs possibles. On fait une réduction de l’espace des couleurs à celles qui sont les plus fréquentes dans l’image.

    Le format PNG est un format d’image bitmap qui utilise la compression sans perte. Le facteur de compression n’est alors pas très élevé. Les données y sont réorganisées pour tenir moins de place. La compression utilise l’algorithme Deflate, basé sur le code de Huffman.

    Rappelez vous que le fichier image est constitué de caractères (base 64). C’est donc les occurences de ces caractères dans le fichier qui permet la compression avec l’agorithme Deflate.

    exemple de code de Huffman pour la compression d'un texte

    exemple de code de Huffman pour la compression d'un texte

    voir explication sur la page de hmalherbe.fr

    Le format jpg est un format compressé avec pertes. L’idée est de supprimer la différence de valeur des couleurs pour des pixels contigûs, aux couleurs proches.

    La compression réduit la taille du fichier, mais dégrade la qualité de l’image.

    La compression réduit la taille du fichier, mais dégrade la qualité de l’image.

    image issue du site adobe.com

    Traitement d’une image sans modifier sa dimension

    On utilise la matrice d’une image source. On créé une matrice d’image cible:

    f1 = open('image_source.ppm','r')
    M_source = []
    for line in f1.readlines()[3:]:
        L = line.split()
        M_source.append(L)
    M_cible = [[0] * len(M_source[0]) for i in range(M_source)]

    On parcourt ensuite chaque valeur de pixel de l’image source, on effectue un traitement sur ces valeurs, et on place chacune dans la matrice de l’image cible.

    image issue du site de frederic-junier.gitlab.io

    image issue du site de frederic-junier.gitlab.io

    Puis on construit l’image cible à partir de sa matrice.

    Transformation de la taille d’une image

    Certains logiciels permettent de reduire ou agrandir la taille d’une image (resize). Cela modifie le nombre de pixels. Cette transformation se fait en conservant les proportions de l’image (homothétie).

    La reduction consiste à choisir certains points de l’image d’origine pour les placer dans celle reduite.

    Un agrandissement simple peut se faire en reportant la valeur d’un point sur un carré de points de l’image agrandie:

    L’agrandissement peut aussi se faire en faisant une interpolation des valeurs des points (on invente les couleurs manquantes par un calcul de moyenne)

    Interpoler: introduire dans une série de valeurs, de nouvelles valeurs intermédiaires.

    Merci à zonensi.fr pour le travail sur cette partie du cours.

    Lire/écrire dans un fichier

    Les algorithmes de compression, d’agrandissement ou de reduction d’image agissent sur D (definition) ou sur C (profondeur de couleur) définis plus haut. Voyons ici la méthode pour lire et écrire dans un fichier image d’extension .ppm. Cela peut se faire à l’aide des fonctions natives de Python. Une autre option est d’utiliser la librairie PIL, comme vu en TP.

    Soit le fichier image_source.ppm, dont le contenu est donné ci-dessous (4 premiers pixels)

    P3
    1000 801
    255
    87 87 87 
    84 84 84 
    81 81 81 
    80 80 80

    On peut manipuler les pixels d’une image à l’aide des instructions natives du langage python.

    f1 = open('image_source.ppm','r')
    for line in f1.readlines()[3:]:
        L = line.split()
        print(L)

    Sortie:

    # affichage des 4 premieres lignes :
    ['87', '87', '87']
    ['84', '84', '84']
    ['81', '81', '81']
    ['80', '80', '80']

    Ce format en listes pour les valeurs des couleurs de pixels est utile pour appliquer un traitement.

    Pour recomposer la chaine de caractère à partir de la liste, il faut faire l’opération inverse de line.split(), c’est à dire:

    > ' '.join(['87', '87', '87'])
    '87 87 87'

    On peut rediriger les valeurs vers un nouveau fichier:

    f1 = open('image_source.ppm','r')
    f2 = open('image_copie.ppm','w')
    largeur = 1000
    hauteur = 801
    f.write('P3'+'\n')
    f.write(str(largeur)+' '+str(hauteur)+'\n')
    f.write('255'+'\n')
    
    for line in f1.readlines()[3:]:
        L = line.split()
        # ici: traitement sur les valeurs du pixel
        pixel = ' '.join(L)
        f2.write(pixel + '\n')

    Exercices

    Recherche du min/max

    Pour parcourir un tableau T à 2 dimensions, il faut 2 boucles imbriquées, la 1ere pour parcourir les lignes, et la 2e pour les colonnes.

    Cela donne souvent le script suivant:

    script A:

    for i in range(len(T)):
      # i est le numero de ligne
      for j in range(len(T[0])):
        # toutes les lignes ont la meme longueur que T[0]
        # j est le numero de colonne
        ... traitement sur T[i][j]

    script B:

    for line in T:
      for elem in line:
        ... traitement sur elem
    1. Lequel de ces scripts realise un parcours par indice? Lequel realise un parcours par élément.
    2. Utiliser l’un de ces scripts pour écrire une fonction min_max, qui détermine la valeur minimale et la valeur maximale parmi les données de la matrice.
    3. Ecrire une fonction moyenne qui retourne la moyenne des valeurs d’une matrice.

    Compréhension de liste

    Le script suivant construit une matrice M de zeros:

    n = 4
    m = 6
    M = # a completer (1)
    for i in range(n):
      for j in range(m):
        line.append(0)
      # a completer (2)  
    1. Compléter le script
    2. Quelle est la dimension de cette matrice? Et quelles seraient les dimension de l’image correspondante (largeur/hauteur)?
    3. Simplifier le script au niveau des lignes 5 et 6, en utilisant l’instruction [0] * n, qui est équivalent, ici, à [0,0,0,0].
    4. Ré-ecrire ce même script, en utilisant la compréhension de liste.

    Créer une image à partir d’instructions

    drapeau suisse

    drapeau suisse

    1. Ecrire le script qui permet de construire la matrice de ce drapeau suisse, en noir et blanc. La dimension sera de 700*500 pixels
    2. Ecrire le script qui construit la matrice du drapeau, mais cette fois, avec la couleur de fond rouge. Chaque élément de la matrice sera un tuple (R,V,B)

    Traitement d’une image sans modifier sa dimension

    On souhaite transformer une image source en couleur, en une image cible en niveaux de gris. On utilise pour cela la formule de calcul de la Luminence: *(r,g,b sont les intensités des couleurs primaires 0..255)

    $$L = 0.299\times r + 0.587\times g + 0.114\times b$$

    La valeur calculée pour L sera placée comme niveau de gris dans la matrice cible.

    1. Ecrire le script de la fonction luminence, qui calcule la valeur de L à partir d’un tuple (r,g,b)
    2. Placer dans la fonction un test d’assertion sur les valeurs permises pour r,g,b. Ce test, basé sur les données d’entrée, est appelé test de précondition
    3. Ecrire une fonction matrice_rgb_to_gris qui créé une matrice de niveaux de gris (valeurs de luminence) à partir d’une matrice couleur.

    Agrandissement, reduction

    On considère une image source de largeur L et de hauteur H et un entier $k > 0$ :

    Un agrandissement de coefficient k de l’image source est une image cible de dimensions $(k\times L,k \times H)$ dont le pixel de coordonnées $(x, y)$ prend la valeur du pixel en $(x//k, y//k)$ dans l’image source.

    image issue du site de frederic-junier.gitlab.io

    image issue du site de frederic-junier.gitlab.io

    1. On considère l’image 3*3 de matrice M = [[1,0,1],[0,1,0],[1,1,1]]. Quelle sera la dimension de l’image cible si le coefficient k est égal à 2?
    2. Représenter la matrice M_cible avec ses valeurs calculées à partir de celles de M
    3. La fonction changement_echelle prend 2 paramètres, M, la matrice $(L,H)$ de l’image source, et k, le coefficient. Cette fonction retourne une image calculée sur les valeurs de M, avec une dimension $(k\times L,k \times H)$. Ecrire le script de cette fonction.
    4. Cette fonction, sert-elle aussi pour réaliser une reduction de la taille de l’image source? Donner un exemple.
    5. Quel défaut aura une image agrandie selon cette méthode?
    6. Quel sera le poids de l’image reduite d’un facteur k? Exprimer en fonction du poids P de l’image source.

    Fiche d’exercices sur les images numeriques: version pdf

    Suite du cours

    TP simulation portes logiques

    TP et outils

    On utilisera:

    Prise en main du logiciel

    Représenter les 3 circuits ci-dessous avec l’editeur logic.ly

    Exemples de circtuits créés à l'aide du simulateur logic.ly

    Exemples de circtuits créés à l'aide du simulateur logic.ly

    Questions:

    1.a. Les circuits permettent-il une interaction avec l’utilisateur?

    1.b. Pour chaque circuit: Quels sont les composants utilisés?

    1.c. Pour chacun des circuits: Expliquer le comportement du circuit, pourquoi la lampe s’allume (ou pas)?

    Toute fonction logique peut se décomposer en fonctions NON, ET, OU. Les exemples suivants ont pour but de se familiariser avec ces combinaisons de portes logiques, et d’aboutir à la construction d’un ADDITIONNEUR à 2 bits.

    Simulation d’une porte logique NON

    Voici le schéma formel représentant la fonction NON, réalisée à l’aide d’une porte logique NAND (NON ET):

    schéma formel

    schéma formel

    Vous allez adapter ce schéma pour réaliser sur le circuit suivant sur le simulateur:

    realisation sur logic.ly

    realisation sur logic.ly

    Les 2 entrées de la portes NAND sont reliées au même interrupteur. L’interrupteur fournit une tension au circuit, à 2 état (Allumé / Eteint).

    Une lampe est aussi mise en entrée, sur l’interrupteur, afin de visualiser l’état d’entrée.

    2.a. Représenter la table des états pour ce dispositif. S’agit-il de la même table que celle de l’opérateur NON?

    E S
    0
    1

    La formule logique associée au schéma que vous avez réalisé est:

    $$NOT(x) = NAND(x,x)$$

    2.b. Commentez cette formule. Identifiez chacun des termes par rapport au circuit.

    Simulation d’une porte logique ET

    Voici le schéma formel représentant la fonction ET, réalisée à partir des portes logiques NOT et NAND:

    schéma formel

    schéma formel

    Réalisez le circuit correspondant sur logic.ly

    3.a. Représenter la table des états pour ce dispositif. S’agit-il de la même table que celle de l’opérateur ET?

    E1 E2 S
    0
    1
    0
    1

    La formule correspondant à cette association est:

    $$AND(x,y) = NOT(NAND(x,y))$$

    3.b. Commentez cette formule. Identifiez chacun des termes par rapport au circuit.

    Porte logique OR

    Sachant que:

    $$NOT(OR(x,y)) = AND(NOT(x),NOT(y))$$

    4.a. Construire et représenter le schéma électronique de $AND(NOT(x),NOT(y))$ à partir des portes AND et NOT.

    4.b. Ce circuit est-il équivalent à $NOT(OR(x,y))$?

    4.c. Conclure: Comment réaliser la fonction $OR(x,y)$ à partir des portes NOT et AND?

    Additionneur 1 bit

    Un additionneur 1 bit est vu comme deux fonctions booléennes s le chiffre des unités et cout la retenue de sortie dépendant de trois entrées:

    • 3 entrées : deux bits a et b et une retenue d’entrée cin

    • 2 sorties : Le bit de résultat s et une retenue de sortie cout

    5.a. Créer un circuit add1 qui implémente l’additionneur 1 bit à partir du schéma ci-dessous

    Additionneur 1 bit

    Additionneur 1 bit

    5.b. Compléter la table de vérité des fonctions s et cout

    a b cin s cout
    0 0
    0 1
    1 0
    1 1
    0 0
    0 1
    1 0
    1 1

    5.c. Expliquez en quoi le circuit suivant est bien un additionneur de 2 bits, avec retenue.

    Le TP est inspiré de mathly.fr

    Liens

    listes et tableaux en sciences

    listes et algos sciences physiques et chimie

    • Les exemples et scripts seront à realiser dans un notebook python.
    • On utilisera la fiche reponse

    Construire un tableau simple

    Pour tracer un graphique, on peut avoir besoin d’une liste de valeurs [0, 1, 2, … 100] correspondant aux nombres de points relevés.

    Cette liste peut être construite à l’aide d’une boucle bornée:

    T = []
    for i in range(100):
      T.append(i)

    On rappelle que range(100) créé une suite de valeurs que prendra le variant i, successivement, du premier au dernier.

    • Construire un tableau par compréhension Cette méthode permet de construire une nouvelle liste “à la volée”, en parcourant les éléments d’une première liste.
    T = [i for i in range(100)]

    Relever des valeurs

    Lors d’une expérimentation, il est parfois utile de relever des valeurs mesurées au cours du temps.

    Ces valeurs peuvent être stockées dans une liste, en utilisant la fonction append:

    temperature = []
    temperature.append(15)
    temperature.append(18)
    ...

    Il est possible de programmer la saisie de ces valeurs par une interface textuelle.

    • une boucle principale demande une valeur à l’expérimentateur (input)
    • la valeur saisie est ajoutée à la liste
    • tant que le caractère de fin n’est pas saisi, continuer (par ex “S”)

    à vous de jouer: Ecrire le script de ce programme, en python.

    Tracer un graphique

    Le module matplotlib permet de tracer des graphiques à partir de listes. La fonction scatter trace un nuage de points, et plot une figure:

    import matplotlib.pyplot as plt
    T = [i for i in range(10)]
    temperature = [t*1.1 for t in T]
    plt.scatter(T,temperature,label="Temperatures")
    plt.legend()
    plt.xlabel('temps(min)')
    plt.ylabel('Temperature(°C)')
    plt.show()

    Listes calculées

    Souvent, les données issues d’une acquisition sont présentées sous forme d’une table.

    Elles sont alors échangées avec le programme python grâce à un fichier de données en format csv. Il est alors possible de créer une liste de données par colonne: listes t, x, y, v

    A partir de l’exemple précédent, on peut supposer que:

    t[0] contient 0
    x[0] contient 0
    y[0] contient 0
    v[0] contient 10

    On peut alors ajouter une nouvelle colonne à ces données, c’est à dire une nouvelle liste.

    Par exemple: à partir de la définition de l’energie cinétique:

    $$Ec = \tfrac{1}{2}* m * v^2$$

    Supposons que le mobile ait une masse m = 1 kg:

    m = 1
    Ec = []
    for vitesse in v:
      Ec.append(0.5*m*v**2)

    Remarque: de nombreux types de données peuvent être parcourus avec la syntaxe for x in t: par exemple des chaines de caractères. La différence avec range(100), c’est que ce dernier créé une liste itérable de valeurs ordonnées, de 0 à 99. On dit que la valeur x est itérable.

    A vous de jouer:

    1. quelle instruction permet de créer la même liste Ec, mais cette fois, par compréhension de liste.
    2. télécharger le fichier data_parabolique.csv 3. Ajouter une nouvelle liste calculée: $Ec = \tfrac{1}{2}* m * (vx^2+vz^2)$. Prendre m = 1. Compléter pour cela le programme:
    m = 1
    Ec = []
    for i in range(len(vx)):
      # vx et vz sont les 2 composantes de v
      # et ont la même dimension
      # v^2 est calculé à partir de
      # vx**2 + vz**2
      Ec.append(
    1. Tracer le graphique Ec en fonction de x.

    Aide: Script pour lire les données d’un fichier

    fichier = open('data_parabolique.csv','r')   # ouverture du fichier de données
    lignes = fichier.readlines()     # parcours du fichier par ligne 
    
    lignes = lignes[1:]              # eliminer la premiere ligne qui contient les labels 
    x=[]
    t=[]
    
    for ligne in lignes:
        t.append(float(ligne.split(';')[0]))
        x.append(float(ligne.split(';')[1]))

    Parcours d’une liste

    Soit la liste:

    Temperature=[18.5, 19.0, 20.4, 20.2, 19.8]

    Pour calculer sur les valeurs de liste, par exemple, la somme, ou la moyenne des valeurs, il faut parcourir ces valeurs:

    s = 0
    for t in Temperature:
      s = s + t

    A vous de jouer: adapter ce script pour:

    1. calculez la moyenne des valeurs de Temperature
    2. Déterminez la valeur maximale de la liste
    3. Utilisez votre script pour déterminer la valeur maximale de la liste z dans le fichier data_parabolique.csv

    Recherche du nombre d’occurences dans une liste

    On peut représenter une molécule par sa liste d’atomes. Par exemple, la formule suivante peut être mise dans la liste:

    molecule = ['H','H','H','C','C','O','C','H','H','H']

    une molecule en formule semi-developpée

    une molecule en formule semi-developpée

    Compter le nombre d’occurences signifie que l’on peut compter le nombre d’atomes identiques, comme par exemple le nombre de 'H' ou bien le nombre de 'C'.

    n = 0
    for atome in molecule:
      # ajouter une condition sur atome
      # si atome vaut 'C' (ou 'O' ou 'H')
      # alors n = n + 1

    A vous de jouer. En vous inspirant du script précédent, vous allez écrire une fonction occurences qui prend une liste en paramètre, appelée molecule, ainsi qu’un caractère c, et compte le nombre d’occurences de c dans la liste molecule.

    Matrices

    Une liste peut elle-même contenir une liste. Une matrice est ainsi une liste de listes, dont les éléments sont tous de même type. La matrice forme une sorte de tableau rectangulaire, dont la premiere ligne correspond à la premiere liste, etc…

    Pour parcourir les valeurs d’une matrice, on aura besoin de 2 boucles imbriquées:

    # script pour afficher la matrice m
    m = [['a','b','c'],['d','e','f'],['g','h','i']]
    for ligne in m:
        for c in ligne:
            print(c,' ',end='')
        print('\n')
    
    # affiche 
    # a b c
    # d e f
    # g h i

    La première boucle bornée créé un itérable ligne qui vaut successivement:

    • ['a','b','c']
    • ['d','e','f']
    • ['g','h','i']

    La deuxième boucle (imbriquée), créé un itérable c à partir de chacune de ces sous-listes:

    • a
    • b
    • c
    • …

    Les valeurs de m sont accessibles à partir de ses indices, comme pour une matrice:

    • m[0][0] vaut a
    • m[0][1] vaut b
    • m[0][2] vaut c
    • m[1][0] vaut d …

    Exemple: traitement d’une image

    une image numérique est constituée de pixels

    une image numérique est constituée de pixels

    Une image est représentée par un triplet de valeurs (un tuple) pour chacun de ses pixels, correspondant à l’intensité (Rouge, Vert, Bleu) (0-255) de ce pixel.

    Soit l’image suivante, de dimension 3 pixels * 3 pixels:

    Cette image est représentée par la matrice de valeurs (R,V,B):

    im = [[(128,30,40), (130,32,44), (128,30,40)], 
          [(30,40,128), (44,32,130), (40,30,128)], 
          [(128,30,40), (130,32,44), (128,30,40)]]

    Exercice:
    Ecrire un programme qui calcule la valeur moyenne sur toutes les valeurs RVB de cette matrice. Cela donnera l’intensité moyenne de cette image (sa luminosité).

    Donnees en table

    Données en table - introduction

    Les tables structurent les données et permettent de réaliser facilement des opérations de recherche d’informations ou de calcul sur ces données.

    Prenons l’exemple une agence de voyage, qui propose des activités sur mesure à ses clients.

    les données sont organisées en 2 tables clients et sejours. Il y aura autant de tables que d’entités

    Les tables clients et sejours ont un identifiant unique attribué lors de leur enregistrement.

    CLIENTS

    IDC NOM AGE ACTIVITE
    27 Ritta 19 Danse
    19 Blaise 29 Cinema
    11 Dede 59 Nature
    18 Indie 58 Histoire
    12 Kelly 30 Surf
    17 Dupond 35 Surf
    28 Nono 65 Plongée

    SEJOURS

    IDS VILLE ACTIVITE
    1 Cayenne Nature
    10 Rio Danse
    11 Havane Danse
    12 Oahu Surf
    20 Durban Plongée
    65 Sydney Surf
    88 Rome Art
    90 Durban Surf

    L’agence de voyage a besoin d’un programme prenant en entrée un nom de VILLE, et affichant la table contenant la reponse à la question:

    Donner les couples (nom de client, identifiant de sejour) tel que ce sejour est dans la VILLE, et propose l’activité favorite de ce client.

    Exemple: suggestion_client(VILLE = 'Oahu')

    Sortie:

    VILLE NOM IDS
    Oahu Kelly 12
    Oahu Dupond 12

    Le but de l’activité est de comprendre les différentes étapes utiles à ce programme.

    1. Créer une table unique CHOIX_SEJOUR vide avec toutes les colonnes des 2 tables.
    2. Pour chaque ligne de CHOIX_SEJOUR, coller bout à bout les lignes de SEJOUR et de CLIENTS ayant la même ACTIVITE. Représenter cette table. Il peut y avoir plusieurs clients pour un même sejour. Dans ce cas, il doit y avoir une ligne unique pour chaque coupe sejour-client.
    3. Dans cette table CHOIX_SEJOUR, conserver uniquement les lignes correspondant à la ville Oahu.
    4. Créer une nouvelle table RESULTAT à partir de CHOIX_SEJOUR en ne conservant que les colonnes VILLE, NOM, IDS. Représenter cette table.
    5. Attribuer à chaque instruction le nom de l’opération réalisée. Choisir parmi:
    • Jointure
    • Projection
    • Selection
    • Modification de table

    COURS

    Tables - généralités

    Une table

    Une table est une liste de lignes, dont les éléments partagent les mêmes colonnes (descripteurs).

    Une ligne

    Chaque ligne est un p-uplet de valeurs (duet, triplet, …)

    Une colonne

    Dans chaque colonne, on trouve des valeurs de même type: le domaine de valeurs.

    Chaque colonne porte un nom: le descripteur de la colonne.

    Le schéma d’une table

    Le schema d’une table est sa structure. C’est l’ensemble de ses descripteurs de colonnes avec leur type. C’est ce qui décrit une table.

    Exemple: Donner le schema de la table clients

    • IDC : entier
    • NOM : caracteres
    • AGE : entier
    • ACTIVITE : caracteres

    Le contenu d’une table

    Le contenu d’une table est formé de ses lignes, qui contiennent les valeurs

    L’identifiant ID

    Parmi les colonnes, l’une d’entre-elles a un statut particulier: L’IDENTIFIANT. Celui-ci doit être unique pour chaque entité, et pour chaque ligne.

    Représenter une table

    On peut représenter une table sous forme de texte structuré: en csv, json, ou xml.

    Ces formats sont interopérables. On peut les manipuler avec de nombreuses applications. (tableurs, langages informatique).

    Table mise dans une liste python

    Pour ouvrir et lire un fichier csv en langage python, on peut utiliser le script suivant:

    import csv
    with open('voyage.csv', mode='r', encoding='utf-8') as f:
         table = list(csv.reader(f,delimiter=";"))

    On suppose qu’il n’y a qu’une table par fichier csv.

    La représentation d’une table est alors une LISTE de lignes en python.

    Ligne: La représentation d’une ligne de la table peut être, au choix:

    Pour une représentation en tuple:

    ligne1 = (27, 'Ritta', 19, 'Danse')

    Les valeurs doivent être placées, sans en omettre une.

    Voici alors un extrait de la table CLIENTS mise dans une liste de listes (3 premiere lignes):

    IDC NOM AGE ACTIVITE
    27 Ritta 19 Danse
    19 Blaise 29 Cinema
    11 Dede 59 Nature
    table = [(27, 'Ritta', 19, 'Danse'),
             (19, 'Blaise', 29, 'Cinema'),
             (11, 'Dede', 59, 'Nature'),
             ...
             ]

    Table mise dans un dictionnaire python

    Un dictionnaire est un tableau associatif. Les éléments sont rangés en couples clé:valeurs, séparés par une virgule, et mis entre accollades {}.

    Pour une représentation en dictionnaire:

    ligne1 = {'IDC' : 27, 'NOM': 'Ritta', 'AGE': 19, 'ACTIVITE: 'Danse'}

    Les descripteurs sont les clés du dictionnaire. A chaque clé est associée une valeur.

    On accède à l’une des valeurs en plaçant la clé entre les []:

    >>> print(ligne1['NOM'])
    Ritta

    La liste des clés est obtenue par la méthode de classe keys() du dictionnaire:

    >>> for c in ligne1.keys():
        ....print(c)
    IDC
    NOM
    AGE
    ACTIVITE

    Voici alors un extrait de la table CLIENTS mise dans une liste de dictionnaires (3 premiere lignes):

    table = [{'IDC' : 27, 'NOM': 'Ritta', 'AGE': 19, 'ACTIVITE: 'Danse'},
             {'IDC' : 19, 'NOM': 'Blaise', 'AGE': 29, 'ACTIVITE: 'Cinema'},
             {'IDC' : 11, 'NOM': 'Dede', 'AGE': 59, 'ACTIVITE: 'Nature'},
             ...
             ]

    Table mise dans un Dataframe

    Cette partie sera developpée en TP.

    Insertion dans une table

    On suppose que la table a été importée dans une liste de dictionnaires. Le traitement affectera TOUTES les lignes de la table.

    Calculer une moyenne

    • parcourir tous les elements de liste
    • ce sont des dictionnaires: selectionner la valeur associée à la clé
    • faire la somme et diviser par le nombre d’éléments de la liste. (le nombre de dictionnaires)
    • appel de la fonction avec le tableau
    tableau = [{'IDC' : 27, 'NOM': 'Ritta', 'AGE': 19, 'ACTIVITE: 'Danse'},
             {'IDC' : 19, 'NOM': 'Blaise', 'AGE': 29, 'ACTIVITE: 'Cinema'},
             {'IDC' : 11, 'NOM': 'Dede', 'AGE': 59, 'ACTIVITE: 'Nature'}
             ]
    
    def moyenne(L,cle):
      """calcule la moyenne des valeurs associées à clé
      params:
      L: list of dict
      cle: str, la clé commune à chaque dictionnaire, les valeurs associées 
      sont soit int soit float
      """
      s = 0
      for elem in L:
        s += elem[cle]
      return s / len(L)
    
    > moyenne(tableau,'AGE')
    35.666667

    Ajouter une valeur calculée

    On peut souhaiter ajouter la différence avec la moyenne des âges, pour chaque élément du tableau. Il faudra:

    • calculer la moyenne des âges (fonction moyenne)
    • parcourir les dictionnaires du tableau
    • lire la valeur associée à âge
    • valeur = moyenne(L,'AGE') - elem['AGE']
    • ajouter le couple 'DIFFERENCE': valeur pour chaque element du tableau
    tableau = [{'IDC' : 27, 'NOM': 'Ritta', 'AGE': 19, 'ACTIVITE: 'Danse'},
             {'IDC' : 19, 'NOM': 'Blaise', 'AGE': 29, 'ACTIVITE: 'Cinema'},
             {'IDC' : 11, 'NOM': 'Dede', 'AGE': 59, 'ACTIVITE: 'Nature'}
             ]
    
    def ajoute_moyenne(L):
      for elem in L:
        age = L['AGE']
        valeur = moyenne(L,'AGE') - elem['AGE']
        elem['DIFFERENCE'] = valeur
    
    > ajoute_moyenne(tableau)
    > print(tableau)
    [{'IDC' : 27, 'NOM': 'Ritta', 'AGE': 19, 'ACTIVITE: 'Danse', 'DIFFERENCE': -16.6667},
     {'IDC' : 19, 'NOM': 'Blaise', 'AGE': 29, 'ACTIVITE: 'Cinema' 'DIFFERENCE': -6.6667},
     {'IDC' : 11, 'NOM': 'Dede', 'AGE': 59, 'ACTIVITE: 'Nature', 'DIFFERENCE': 23.3333}
    ]

    Opérations sur les tables: selection, projection, jointure

    Ces opérations vont créer une nouvelle table.

    Selection

    Definition: Selectionner revient à extraire les lignes d’une table qui satisfont un critère. Pour réaliser une selection, on utilise une fonction test qui prend en paramètre une ligne de la table et retourne un booléen:

    Méthode utilisant une boucle bornée:

    selection = []
    for ligne in table:
      if test(ligne):
        selection.append(ligne)

    Méthode par compréhension

    [ligne for ligne in table if test(ligne)]

    Projection

    Definition: Une projection revient à ne conserver que certaines colonnes de la table. Pour réaliser une projection, on créé une nouvelle table:

    Méthode utilisant une boucle bornée et une table de listes:

    projection = []
    colonnes = [0,1] # liste de colonnes à conserver
    for ligne in table:
      nouvelle_ligne = []
      for i in colonnes:
        nouvelle_ligne.append(ligne[i])
      projection.append(nouvelle_ligne)

    Méthode utilisant une boucle bornée et une table dictionnaires:

    table = [{'id':0, 'NOM':'Jean','AGE': 65},
            {'id':1, 'NOM':'Michel','AGE': 45},
            {'id':2, 'NOM':'Manu','AGE': 40}]
    
    projection = []
    colonnes = ['id','NOM'] # liste de colonnes à conserver
    for ligne in table:
      nouvelle_ligne = {}
      for i in colonnes:
        nouvelle_ligne[i] = ligne[i]
      projection.append(nouvelle_ligne)
    >>> projection
    [{'id': 0, 'NOM': 'Jean'}, {'id': 1, 'NOM': 'Michel'}, {'id': 2, 'NOM': 'Manu'}]

    Méthode par compréhension, table de listes

    [[ligne[i] for i in [0,1]] for ligne in table]

    Méthode par compréhension, table de dictionnaires

    [{ligne[i] for i in ['id','NOM']} for ligne in table]
    # affiche
    [{0, 'Jean'}, {'Michel', 1}, {2, 'Manu'}]

    Jointure

    Definition: Une jointure est la fusion de 2 tables pour un même attribut. (commun). La jointure permet de regrouper des informations dans une même table.

    clients = [{'IDC':27, 'NOM': 'Ritta', 'AGE': 19, 'ACTIVITE': 'Danse'},
              {'IDC':19, 'NOM': 'Blaise', 'AGE': 29, 'ACTIVITE': 'Cinema'}]
    sejours = [{'IDS': 1, 'VILLE': 'Cayenne', 'ACTIVITE': 'Nature'},
               {'IDS': 10, 'VILLE': 'Rio', 'ACTIVITE': 'Danse'}]
    cle = 'ACTIVITE'
    table_jointure = []
    attribut_commun = 'ACTIVITE'
    for sejour in sejours:
        for client in clients:
            if sejour[cle] == client[cle]:
                ligne = {}
                for attribut in sejour.keys():
                    ligne [attribut] = sejour[attribut]
                for attribut in client.keys():
                    ligne [attribut] = client[attribut]
                table_jointure.append(ligne)
    >>> table_jointure
    [{'IDS': 10, 'VILLE': 'Rio', 'ACTIVITE': 'Danse', 'IDC': 27, 'NOM': 'Ritta', 'AGE': 19}]

    reseaux

    Sous-sections de reseaux

    modele OSI

    • cours sur le modèle OSI: Lien
    • cours sur les protocoles du modele OSI: Lien
    • cours sur le protocole HTTP: Lien
    • exemple de scénario montrant les failles de securité: Lien
    • TP simulation de reseau (../TP_reseau) avec Filius
    • TP sur la lecture des en-tête pour les methode GET et POST (HTTP): Lien
    • TP sur la conception de pages web avec serveur python et gestion de formulaire: Lien avec module Flask, et projet web
    • TP utilisant le module python requests: Lien

    Le modèle OSI

    Introduction:

    VIDEO: modèles OSI et TCP IP

    VIDEO: modèles OSI et TCP IP

    chaine Cookie connecté

    Les données qui circulent sur internet

    Internet manipule deux types d’information : les contenus envoyés et les adresses du destinataire et de l’émetteur. Ces deux types d’information sont regroupés dans des paquets de taille fixe, de façon uniforme et indépendante du type de données transportées : texte, images, sons, vidéos, etc.

    Principe du modèle OSI

    On peut rentrer un peu plus dans le détail du modèle OSI et en particulier de la communication TCP/IP. Le modèle OSI est une norme qui préconise comment les ordinateurs devraient communiquer entre eux avec 4 couches technologiques adjacentes, numérotées selon leur distance au support d’emission (la couche n°1). On peut rassembler les couches 5, 6 et 7 en une seule.

    Les couches forment une hiérarchie qui va de l’application (HTTP, FTP etc…) jusqu’au support physique (cable coaxial, ondes etc…).

    Ce modèle OSI (un modèle theorique) a été conçu pour cloisonner les différents processus, langages et technologies employés.

    Combien de couches?:

    Selon le degré de description, on parle plutôt du modèle TCP/IP en 4 couches.

    illustration du TCP/IP

    illustration du TCP/IP

    image issue de la chaine youtube - Cookie connecté

    Quelles applications pour quelle couche?:

    Les 2 schémas ci-contre illustrent le découpage couche-application.

    tableau issu de la page wikipedia - TLS, SSL

    SSH et SSL sont deux technologies qui permettent de chiffrer et d’authentifier les données qui passent entre deux ordinateurs. Ce sont des applications de la couche 5. Ces données sont chiffrées avant leur mise en forme pour le transport. Pour approfondir: différence entre SSH et SSL.

    Quelles sont les liens entre couches?

    Le modèle OSI ajoute deux règles plus générales entre les couches :

    • chaque couche est indépendante ;
    • chaque couche ne peut communiquer qu’avec une couche adjacente.

    Lors de l’émission d’une requête par une application, celle-ci doit traverser toutes les couches, depuis la 7 (application), puis de la 4 vers la 1; durant le trajet les données subiront des modifications et chaque couche rajoutera ce qu’elle voudra (généralement des en-têtes) pour mieux exercer sa fonction, mais pas seulement (la couche 1, de transport concerne… le transport).

    Ce mécanisme s’appelle l’encapsulation : la trame de données numériques est constituée de plusieurs parties distinctes et mises dans un ordre particulier. L’encapsulation, en informatique et spécifiquement pour les réseaux informatiques, est un procédé consistant à inclure les données d’un protocole dans un autre protocole.

    Au final, ce qui va circuler sur le réseau est une trame de couche 1, qui contient le datagramme de couche 2 (qui lui-même contiendra le segment de couche 3)

    encapsulation

    encapsulation

    Lors de la réception c’est exactement l’inverse qui se produit (désencapsulation).

    desencapsulation

    desencapsulation

    Prenons un exemple simple, vous demandez à votre navigateur de charger votre site préféré www.informatix.fr. Vous êtes reliés à un modem par un câble à paires torsadées.

    couche application

    Le navigateur demande au système d’envoyer une requête HTTP (couche 7). Dans cette couche, le logiciel lui même n’en fait pas partie. Cette couche concerne l’interface entre le logiciel est la couche de transport, et transporte l’information du protocole application utilisé (ici http par exemple, c’est à dire le protocole lié à l’affichage des pages html)

    Sortie : [requête HTTP]

    couche de transport

    La requête arrive dans TCP qui ajoute son en-tête. Le protocole TCP va mettre en forme les données à envoyer et ajouter son en-tête. Ici, les numeros d’identification sont les port source et le port destination, qui identifient les applications qui entrent en jeu dans la communication. Parmi les informations, on trouve aussi le numéro de séquence initial, ISN, appelé aussi SYN (pour dire à la machine en face combien de données elle est censée avoir reçues) et celui d’acquitement ACK (le numéro du prochain octet des données attendues). Ces numéros vont permettre d’établir une communication avec accusés de reception (pour TCP, pas UDP) et de s’assurer, en principe, de l’identité de la machine avec qui les données sont échangées (avec le numéro de séquence, nécessaire pour l’accusé de reception). L’en-tête contient aussi un checksum. Pour résumer, on appelera cette en-tête le PDU (Protocol Data Unit).

    Sortie : [en-tête PDU][requête HTTP]

    fragmentation TCP: cours sur openclassroom

    couche réseau

    Le segment TCP arrive dans IP qui ajoute aussi son en-tête (qui contient entre autres votre adresse IP (pour le routage) et celle du serveur demandé). La couche 3 indique à la couche 2 quel protocole a été utilisé (TCP, UDP…). Il y a aussi un numéro de connexions établies (IPID) sur le port en question et d’autres informations qui servent à l’eventuelle fragmentation du datagramme (les données ne peuvent pas exceder 1500 octets.
    Une autre valeur transportée est le TTL (time to live) qui evite que le paquet ne circule indefiniment sur les reseaux.

    Sortie : [en-tête IP][en-tête PDU][requête HTTP]

    modèle simplifié du datagramme

    modèle simplifié du datagramme

    couche physique

    Le paquet IP arrive dans Ethernet qui ajoute un en-tête (qui contient entre autres votre adresse MAC - pour le switch - et celle du modem) et un checksum (vérification d’erreurs CRC). La couche 2 peut alors former la trame et l’envoyer sur le réseau.

    Il va ajouter l’adresse MAC de l’emetteur et du destinataire, qu’il aura résolu grâce aux tables de routage et la table arp (côté serveur).

    Sortie : [en-tête Ethernet][en-tête IP][en tête PDU][requête HTTP][checksum Ethernet]

    en-tête

    en-tête Ethernet

    Le document complet sur la structure d’une trame: Lien. document est issu du cours en ligne du lycee de Taaone, série technologique.

    Lors du transport, chaque machine va désencapsuler les informations de la partie Ethernet et les remplacer par de nouvelles informations pour assurer le transport jusqu’à la prochaine étape.

    Seule la machine de destination va acceder au contenu.

    Liens

    protocoles

    Protocoles

    Pour rappel, un protocole est un langage. Il permet aux machines qui dialoguent ensemble de se comprendre.

    Grâce au protocole TCP, les machines dialoguent en mode connecté.

    Le mode connecté est l’établissement d’une session de communication entre deux parties qui veulent échanger des données. Cette session comporte:

    • un début
    • une fin
    • et une validation (vérification des erreurs).

    rappels sur le modèle en couches

    On a vu que l’information qui circule entre 2 machines comprend des données et des adresses.

    Les composants du reseau n’ont accès qu’à certaines de ces données et adresses, selon leur position dans le modèle en couches.

    message -> datagramme -> trame

    message -> datagramme -> trame

    source: comprendre les modèles OSI et TCP/IP - chaine Cookie connecté

    Ainsi:

    • Le switch fait partie des couches liaison (2) et physique (1). Il a accès aux bits et à l’adresse MAC. Il en a besoin pour commuter les trames vers le bon port. (même reseau).
    • Le routeur a accès aux adresses MAC et IP de la trame. Il va interconnecter des reseaux grace aux adresses IP.

    Protocoles de la couche physique

    le rôle principal de la couche 1 est d’offrir un support de transmission pour les communications. Le protocole de la couche 1 doit permettre aux machines de communiquer sans collision (l’une après l’autre pour 2 machines de la même ligne). Il existe par exemple le protocole CSMA/CD, pour organiser le droit de parole lorsque 2 machines sont directement connectées.

    Protocoles de la couche liaison

    Le protocole Ethernet: l’objectif est de permettre à des machines connectées ensemble de communiquer, ainsi que la détection des erreurs de transmission.

    Les données sont mises dans une trame, dont les premières valeurs lisibles sont l’adresse MAC du destinataire, puis de l’émetteur.

    Ainsi, lorsqu’une machine reçoit une trame, et que les premiers bits identifient son adresse MAC, alors elle conserve la trame, car celle-ci lui est destinée.

    Un autre protocole a été utilisé pour fiabiliser la transmission. Le protocole du bit alterné est utilisé au sein de la couche 2 du modèle OSI (distribution des trames Ethernet). Simple et léger, il peut toutefois être facilement mis en défaut, ce qui explique qu’il ait été remplacé par des protocoles plus performants.

    >  <figcaption>source: <a href=

    source:

    Cela necessite d’ajouter 1 bit dans l’en-tête prévu pour la couche 2, contenant déjà les adresses MAC.

    Principe du protocole du bit alterné

    la première trame envoyée par A aura pour drapeau 0, dès cette trame reçue par B, ce dernier va envoyer un accusé de réception avec le même drapeau 0. Dès que A reçoit l’accusé de réception avec le drapeau à 0, il envoie la 2e trame avec un drapeau à 1, et ainsi de suite…

    Le système de drapeau est complété avec un système d’horloge côté émetteur. Un “chronomètre” est déclenché à chaque envoi de trame, si au bout d’un certain temps, l’émetteur n’a pas reçu un acquittement correct (avec le bon drapeau), la trame précédemment envoyée par l’émetteur est considérée comme perdue et est de nouveau envoyée.

    Code de correction d’erreur CRC

    Dans la trame, on ajoute aux données de la couche 2 un code de correction des erreurs, ou CRC. C’est une valeur mathématique qui est représentative des données envoyées.

    Lors de l’envoi, A calcule le CRC (une valeur X) et le met à la fin de la trame.

    B reçoit le message et fait le même calcul que A avec la trame reçue (une valeur Y).

    B compare la valeur qu’elle a calculée (Y) avec la valeur que A avait calculée et mise à la fin de la trame (X).

    Si elles sont égales, bingo ! La trame envoyée par A est bien identique à la trame reçue par B.

    Désencapsulation

    Supposons que les machines A et B soient des routeurs:

    Une fois que la machine B a reçu la bonne trame, elle désencapsule les données pour consulter celles de couche 3, les adresses IP. Elle agit alors selon le protocole IP.

    Le protocole IP

    Le protocole IP a pour charge de mettre en contact 2 ordinateurs qui n’appartiennent pas au même réseau. (par exemple sur Internet). C’est un protocole de la couche 3 (couche reseau).

    La couche 3 a pour rôle d’interconnecter les reseaux.

    Lorsqu’un routeur reçoit un paquet d’une machine A, et qu’il doit la transmettre vers la machine B, il consulte sa table de routage pour l’envoyer par le chemin (l’interface) le plus court.

    La table contient, pour chaque machine à atteindre, l’interface vers laquelle doivent transiter les données, ainsi qu’un coefficient correspondant au coût pour cette interface. (Le coût étant égal au nombre de sauts, ou bien au résultat d’un calcul mettant en jeu le debit).

    réseau de routeurs et table de routage (MOOC de l'IMT)

    réseau de routeurs et table de routage (MOOC de l'IMT)

    Cette table de routage ne peut contenir tous les routeurs du reseau internet (estimé à probablement 1 million). Il est donc necessaire de regrouper les sous-réseaux en aires, et d’indiquer le chemin vers ces aires dans les tables de routage.

    La manière avec laquelle les tables de routages sont constituées est le resultat du protocole IP. Il existe ainsi:

    • le routage à vecteur de distance
    • le routage à état de liens

    Cette partie sera développée en Term NSI.

    sources: mooc de l’institut des mines telecom

    TTL: Le protocole prend en compte le time to live (TTL), une valeur numerique du datagramme (couche reseau), qui diminue d’une unité à chaque saut (routeur). Lorsque ce TTL arrive à zero, alors que le paquet n’est pas parvenu à destination, celui-ci est détruit. On verra que dans le protocole TCP, cette eventualité est prévue. Un compte à rebours du côté de la machine emettrice va provoquer la ré expedition du paquet lorsque ce compteur arrive à 0, et qu’aucun accusé de reception n’est parvenu.

    Le protocole TCP

    L’hôte source va créer une session de connexion avec l’hôte distant (protocole HTTP). Une fois la connexion établie, l’échange de données commence. C’est le protocole TCP qui va s’assurer que tous les paquets sont bien transmis. Cette connexion est maintenue jusqu’à ce qu’elle soit fermée. voir sur it-connect.fr

    Le protocole TCP permet d’assurer le transport des données de sorte que celles-ci arrivent complètes, sans trop occuper les lignes du reseau. C’est le protocole de la couche 4. A ce niveau de la couche de transport, l’identifiant ajouté au message est le numéro de port de l’application qui est à l’origine du message.

    La fiabilité est obtenue par un mécanisme d’acquittement des segments :

    • À l’émission d’un segment, une alarme est amorcée
    • Elle est désamorcée quand l’acquittement correspondant est reçu
    • Si elle expire, le segment est réémis
    TCP1

    TCP1

    • Chaque segment possède un numéro de séquence SEQ: c’est le numéro du premier octet envoyé. C’est grâce à ce numero que les segments peuvent être remis dans l’ordre.
    • Les acquittements sont identifiés par un marqueur ACK: c’est le numéro du prochain octet attendu par la machine.
    • Le concept même d’acquittement impose des notions de délai. Par exemple, quel est le délai au delà duquel un segment non acquitté doit être réémis (typiquement 30’ à 1min).

    TCP effectue une tâche importante: le multiplexage/demultiplexage: c’est à dire, faire transiter sur une même ligne, en série, des données qui sont à priori en parallèle, non hierachisées (une page web constituée de différents fragments, …). Ces données sont alors reconstruites, grâce au format utilisé pour leur transport. Voir le detail du modèle OSI

    TCP2

    TCP2

    TCP permet ainsi d’être un protocole fiable sans perte de paquets, qui permet à 2 machines de communiquer entre elles (et seulement 2)

    La communication serveur-client est-elle toujours synchrone?

    Cette attente de l’acquittement est pénalisante, sauf si on utilise un mécanisme de « fenêtres glissantes», comme le suggère la figure suivante:

    fenetre glissante

    laissus.developpez.com

    image issue de la page laissus.developpez.com introduction tcp/ip

    Les fragments peuvent être envoyés quasi simultanément, sans attente de l’acquittement. La couche TCP du destinataire aura toute l’information pour le replacer dans le bon ordre. À chaque paquet est associée une horloge. Si l’un des paquets n’est pas acquité dans les temps, il est réémis

    Avec ce principe, la bande passante du réseau est beaucoup mieux employée.

    Protocoles DNS, HTTP, …

    C’est un protocole de la couche Application. Le sujet a déja été traité ici

    La couche d’application définit les services Internet standard et les applications réseau à la disposition des utilisateurs: utilise les protocoles HTTP, FTP, SMTP.

    Le protocole HTTP a été traité ici

    Exercices

    adressage IP dans un reseau

    Ex 1:

    Sur la configuration IP d’une machine nommée MACH01 on peut lire :

    adresse Ipv4 : 172.16.100.201
    Masque de sous-réseau : 255.255.0.0
    Passerelle : 172.16.0.254

    Sur la configuration IP d’une machine nommée MACH02 on peut lire :

    adresse Ipv4 : 172.16.100.202
    Masque de sous-réseau : 255.255.0.0
    Passerelle : 172.16.0.254

    1. (QCM) Depuis la machine MACH02, à l’aide de quelle commande peut-on tester le dialogue entre ces deux machines ?

    Réponses :

    A- ping 172.16.100.201

    B- ping 172.16.100.202

    C- ping 172.16.100.254

    D- ping 255.255.0.0

    2. On souhaite ajouter une nouvelle machine dans ce reseau. Proposez une nouvelle adresse IP possible pour cette machine.

    3. (QCM) Quel est le composant qui a l’adresse 172.16.0.254?

    A- un ordinateur du reseau

    B- l’une des interfaces du routeur

    C- l’adresse du switch

    Ex 2: Une machine a pour adresse IP:

    $$192.168.0.1 / 24$$

    le /24 signifie que les 24 premiers bits correspondent à l’adresse reseau. Le reste des bits correspond à l’adresse machine.

    Représenter cette adresse en binaire, et identifier les bits correspondant aux 2 sous-parties, reseau et machine.

    Constitution d’un reseau

    Ex 1:

    1. La machine 192.168.0.1 veut joindre la machine 10.0.1.1 Combien de sauts seront necessaires?

    2. Les switchs ne sont pas représentés sur ce schéma. Positionnez celui du reseau 192.168.0.0

    3. Les ordinateurs du reseau 192.168.0 ne peuvent plus acceder à internet, de même que celui d’adresse 10.0.0.1. Par contre, ceux-ci peuvent encore communiquer entre eux. Quelle peut être la cause de cette panne?

    Routage

    Ex 1: Soit le reseau de routeurs A, B, C, D:

    On suppose que la transmission par une liaison prend une unité de temps. Un seul paquet peut emprunter une liaison pendant cette durée.

    A chaque unité de temps, le paquet poursuit sa route selon le parcours le plus rapide et fait 1 saut.

    Au bout de ce temps, le paquet est donc forcément stocké au niveau du routeur d’arrivée.

    • A l’instant 1, A commence l’envoi vers C d’une donnée constituée de 3 paquets P1, P2, P3.
    • A l’instant 2, D commence l’envoi vers C d’une donnée composée de 2 paquets P4 et P5
    Temps A B C D
    0 P1, P2, P3
    1 P2, P3 P1 P4, P5
    2
    …

    1. Compléter le tableau des différentes étapes d’envoi des données.

    2. Déterminer l’espace de stockage nécessaire dans le noeud B.

    Trame et datagramme

    Ex 1:

    1. Commenter le schéma précédent en expliquant l’encapsulation des données.
    2. Donner les principaux éléments qui composent un datagramme IP et décrire leur utilité.

    Ex 2: Voici le modèle simplifié de datagramme IP que nous allons utiliser dans la suite de l’exercice:

    modèle simplifié de datagramme IPv4

    modèle simplifié de datagramme IPv4

    1. Sur combien d’octets sont codés:

    • une adresse IPv4?
    • une adresse IPv6?
    • un entête IPv4 (au minimum)?

    2. En vous basant sur l’illustration du datagramme IP ci-dessus, dessinez et indiquez certaines des valeurs contenues dans un 2e datagramme qui repond à l’emetteur avec la donnée: il est midi, le TTL est fixé à 5.

    3. Représentez le datagramme IPv4 correspondant aux informations suivantes:

    • source: 10.0.1.1
    • destination: 128.192.2.2
    • TTL: 3
    • Données à envoyer: Bonjour
    • Pas d’option

    Protocole du bit alterné

    Ex 1:

    On veut envoyer la donnée 1234567890 de A vers B avec le protocole du bit alterné

    1. Que doit renvoyer B lorsqu’il reçoit:

    • donnée: 12345
    • bit de contrôle: 1 ?

    2. Que doit renvoyer A s’il reçoit un bit de contrôle à 0?

    3. Que doit-il renvoyer s’il reçoit 1 comme bit de contrôle?

    Ex 2:

    La machine A doit envoyer les 3 données suivantes: hohoho, salut, les enfants.

    Indiquer les données et les bits de contrôle qui sont transmis dans le protocole du bit alterné lorsque:

    a. toutes les données sont transmises sans problème.

    b. la 2e donnée est mal receptionnée 2 fois de suite.

    Protocole TCP

    Ex 1: (QCM)

    Quels sont les avantages de la transmission sous forme de paquets?

    A- S’assurer que les données arrivent dans leur ordre d’envoi.

    B- S’assurer que les données ne restent pas indéfiniment dans le réseau.

    C- Utiliser au mieux les liens dans le reseau.

    Ex 2: (QCM plusieurs reponses possibles)

    Que nécessite la transmission sous forme de paquets?

    A- Pouvoir stocker la donnée si un lien n’est pas libre.

    B- Une adresse source et une adresse destination associée au paquet.

    C- Un protocole de fiabilisation de la transmission.

    D- Un préfixe d’adresse.

    Liens

    Sources

    TP simulation d'un réseau

    TP simulation reseau

    Un reseau, c’est quoi? C’est un système constitué de machines reliées ensembles (machines de tout genre: ordinateur, imprimante,…). Elles ont une adresse IP.

    L’adresse IP (Internet Protocol) identifie un périphérique à l’intérieur d’un réseau. A l’intérieur de ce réseau elle est unique.

    Les outils utilisés en simulation ne fonctionnent pas tous en mode réel, à partir de votre propre ordinateur du lycée, à cause de restrictions nécessaires pour des problèmes de sécurité.

    TP Filius 1 : faire communiquer 2 ordinateurs (durée indicative: 10 min)

    Lancer le logiciel Filius.

    On réalise un premier réseau simple de 2 ordinateurs reliés par une seule ligne.

    On s’aidera de la video de présentation Filius 1 (David Roche)

    • Disposer les 2 ordinateurs comme présenté sur la video.

    • Modifier les adresses IP de ces ordinateurs pour avoir, dans l’ordre:

      • 192.168.0.1
      • 192.168.0.2

      Remarque: Souvent, dans un même reseau, les 3 premiers octets de l’adresse IP des machines sont identiques. (ici: 192.168.0). Seul le dernier octet change. Pour l’une des machines, ce sera .1, pour la suivante .2, etc…)

    • Relier ces ordinateurs

    • Installer les logiciels utiles pour faire communiquer ces machines. Pour faire cela: Démarrer la simulation:

    démarrer
    • Puis faire un double clic sur chacune des machines, et installer le logiciel ligne de commandes.
    console installation logiciel

    console d'installation de logiciels

    • tester alors les commandes suivantes depuis la machine M1:

      • ipconfig : vérifier la correspondance de l’adresse IP de la machine M1

      • ping 192.168.0.2 : pour établir et tester une connexion avec la machine M2

      • traceroute 192.168.0.2 : pour établir le trajet qui mène jusqu’à M2

      • Tester alors les commandes ping et traceroute vers une adresse de machine inexistante dans le réseau. Par exemple 192.168.0.3

    Qu.1a: comment voit-on si le chemin vers une machine du reseau existe? Quelle information lit-on dans la console?

    • modifier le réseau et mettre 3 ordinateurs reliés à un switch (un connecteur) : voir la vidéo pour explications
      • revenir en mode conception du reseau (bouton avec le marteau)
      • commencer par supprimer le cable (clic Droit sur le composant => Supprimer)
      • ajouter l’ordinateur M3. Modifier son IP en 192.168.0.3. Relier ces machines à l’aide d’un switch.
      • tester alors la commande de traceroute entre M1 et M3

    Qu.1b: Pourquoi a-t-on besoin d’un switch dans un réseau à 3 ordinateurs?

    TP Filius 2 : créer un reseau de type lycée (durée indicative: 20 min)

    On cherche maintenant à créer un système de 2 sous-réseaux locaux. Ces reseaux auront pour adresses: 198.168.0.0 et 192.168.2.0

    C’est à dire que toutes les machines du réseau 198.168.0.0 auront en commun les 3 octets 198.168.0 et toutes les machines du reseau 198.168.2.0 auront en commun les octets 198.168.2.

    • Le sous-réseau 192.168.2.0 comportera un switch et 3 ordinateurs M4, M5 et M6. Ces machines auront pour adresses IP:
      • 192.168.2.1
      • 192.168.2.2
      • 192.168.2.3

    Votre système devrait ressembler à l’image suivante:

    systeme de 2 sous-reseaux sans routeur

    systeme de 2 sous-reseaux sans routeur

    • Tester alors la commande ping depuis la machine M1 vers celle M6 du 2e sous-reseau.

    Qu.2a:: La machine M6 est-elle accessible depuis M1? Pourquoi?

    • Modifier le système en ajoutant un routeur:

      • clic droit sur le Switch2 : faire supprimer tous les cables
      • ajouter le routeur
      • paramétrer le routeur:

      clic sur le routeur

      renseigner les adresses des 2 reseaux sur l’interface du routeur:

      • 192.168.0.254 du côté du reseau 192.168.0.0 (à gauche)
      • 192.168.2.254 du côté du reseau 192.168.2.0 (à droite)
    adresses des reseaux

    adresses des reseaux

    cocher routage automatique:

    option routage automatique

    option routage automatique

    • Pour chacun des ordinateurs du sous-reseau 1, M1, M2, M3, renseigner l’adresse de l’interface reseau 1 du routeur: mettre 192.168.0.254 dans le champs passerelle. Ce sera l’adresse IP de la carte reseau du routeur, du côté du reseau 192.168.0.0 (on met 254 à la place de 0 pour l’adresse routeur).
    renseigner l

    renseigner l'adresse reseau pour chaque ordinateur

    • Même travail pour M4, M5, M6: renseigner la passerelle 192.168.2.254
    • refaire le cablage

    Qu.2b: Pourquoi le routeur de votre système informatique possède t-il 2 adresses IP?

    Qu.2c: Démarrer le système et tester alors la commande ping de M1 vers M6, puis de M6 vers M1. Que constatez-vous? Pourquoi?

    En cas de difficultés: on pourra consulter la video Filius 2 de David Roche

    TP Filius 3 : système avec routage (durée indicative: 20 min)

    On utilisera pour la suite un système informatique constitué de nombreux sous-reseaux:

    Premier contact avec le système

    Qu.3a. Représenter sur votre feuille le reseau en ne dessinant que les ordinateurs n°1 et n°15, ainsi que tous les routeurs traversé (plus court schemin entre M1 et M15).

    Qu.3b. Indiquer sur le schéma, pour chaque routeur, l’adresse passerelle que le message de M1 vers M15 va emprunter.

    Lancer la simulation

    1. Prendre connaissance de l’adresse IP de l’ordinateur n°15
    2. Depuis l’ordinateur n°1: Lancer le logiciel Ligne de commande
    3. Faire: traceroute suivi de l’adresse IP de la machine 15
    4. Repérer alors quels sont les adresses passerelles empruntées par les données entre ces 2 ordinateurs.

    Qu.3c. Quel est le nombre de sauts entre M1 et M15? Est-ce que le nombre de sauts effectués vous semble cohérent?

    Qu.3d. S’agit-il des mêmes adresses passerelles lorsque la machine M15 envoie un message à M1? Vérifiez le par une expérience.

    Table de routage

    Revenir en mode edition (marteau) : cliquer sur le routeur A Dans l’onglet général : décocher l’option : routage automatique

    Aller dans l’onglet table de routage (forwarding table):

    table de routage du routeur A

    table de routage du routeur A

    Q3e : cartes reseaux du routeur:

    • Hormis l’interface 127.0.0.1 : Combien d’interfaces différentes possède le routeur? (colonne NIC, next interface connection)
    • Quels sont les 3 réseaux auquel ce routeur est directement relié ? Donner leur adresse IP.

    Serveur web

    TP n°4: (optionnel) Créer une page web (durée indicative: 30 min)

    si vous n’avez pas le temps, passez cette étape et rendez vous directement au chapitre communication client-serveur

    En mode simulation:

    • Ajouter à l’ordinateur n°15 les logiciels:

      • explorateur de fichiers
      • editeur de fichier
      • webserveur
      • webbrowser
    • Sur l’ordinateur n°15:

      • lancer l’explorateur de fichiers
      • aller dans le dossier webserver: effacer tous les fichiers présents
      • lancer le logiciel editeur de texte
      • Saisir une ou plusieurs instructions en html, comme par exemple:
    • machine n°15:
      • cliquer sur le bouton Fichier
    • machine n°15:

      • sauvegarder ce fichier dans le dossier webserver. Choisir: Nom de fichier: index.html
      • Ouvrir le l’app webserveur et démarrer (Start)
    • test en local:

      • ouvrir le webbrowser. Dans la barre d’adresse, saisir http://localhost.

    Qu.4a.: Voyez vous votre page? Expliquer alors ce signifie l’adresse localhost.

    • Aller sur l’application webserver: Les informations affichées devraient montrer l’entête HTTP avec la requête reçue (méthode GET, …), l’entête de la reponse (HTTP/1.1 200 OK), ainsi que le script HTML téléchargé.

    Qu.4b.: Recopier l’entête sur votre feuille. S’agit-il d’informations de la couche 4 (Application), 3 (Transport), 2 (reseau), ou 1 (accès au reseau)? voir ici les rappels de cours de 1ere NSI

    • Ajouter à l’ordinateur n°1 le logiciel : Navigateur Web
    • Lancer le Navigateur web
    • Dans la barre d’adresse, completer http:// avec l’adresse IP de l’ordinateur n°15 et cliquer sur Afficher
    • Si la page ne se charge pas la première fois, fermer et rouvrir le serveur du poste 15, ainsi que le Navigateur Web côté client.

    Comme pour la connexion en localhost: Lire les informations de la fenêtre de l’application Webserver:

    Qu.4c: Quelles informations ont changé sur la fenêtre de l’application webserver?

    TP n°5: Communication client-serveur (durée indicative: 10 min)

    Quitter la simulation précédente et ouvrir le nouveau reseau filius. Télécharger et ouvrir le fichier

    Le reseau contient maintenant 2 serveurs (192.168.5.3 et 192.168.4.3).

    • Sur les ordinateurs 192.168.5.3 et 192.168.4.3, lancer le logiciel Webserveur. Laisser celui-ci ouvert.
    • Sur l’ordinateur client M1, ouvrir le navigateur. Saisir comme adresse http://192.168.5.3. Vous devriez obtenir une page web (en allemand…)
    • Sur le serveur 192.168.5.3, la fenêtre de son logiciel devrait montrer la requête reçue, et la reponse transmise.

    Qu.5a: d’où vient la page affichée par le navigateur de la machine M1? Recopiez sur votre feuille l’en-tête HTTP affichée par le logiciel serveur. (pas le contenu html de la page).

    Qu.5b: Même question, mais cette fois à partir d’une connexion sur le serveur 192.168.4.3

    TP n°6: Serveur DNS (durée indicative: 20 min)

    Quitter la précédente simulation et ouvrir le fichier avec les tables DNS

    Le reseau contient maintenant 2 serveurs (192.168.5.3 et 192.168.4.3) ainsi que 2 serveur DNS.

    Le BON serveur DNS a pour adresse 192.168.6.1

    Qu.6a En mode construction, relever l’adresse DNS renseignée pour tous les ordinateurs

    • En mode simulation : vous allez commencer par démarrer chacun des serveurs.

    Vérifier que la table pour la resolution par le serveur DNS 192.168.6.1 est remplie comme indiqué ci-dessous. (sinon, complétez la).

    IP adresse symbolique
    192.168.4.3 estiennedorves.fr
    192.168.5.3 autreserveur.com

    configuration DNS

    configuration DNS

    Puis, à partir de l’une des machines du reseau, comme par exemple M1, vous allez vous connecter à chacun de ces serveurs, à partir de leur adresse symbolique.

    navigation avec adresse symbolique

    navigation avec adresse symbolique

    Qu.6b: Expliquer quel est le principe du protocole DNS.

    Le protocole DNS est vulnérable, et peut faire l’objet d’un piratage: voir explications ici: site cloudfare.com

    Qu.6c: Quelle est la table du serveur DNS pirate ?

    Qu.6d: Comment peut-on utiliser la simulation réalisée sur Filius pour réaliser le scénario d’un piratage de DNS? Quelles sont les différentes étapes à suivre sur le logiciel Filius?

    DNS et configuration de votre poste informatique

    1. Constituer une table de correspondance entre nom de domaine et adresse ip sur le site https://www.my-ip-finder.fr et choisir l’onglet DNS lookup :
    Adresse symbolique Adresse IP v4 IP v6
    musee-orsay.fr
    olympics.com
    onisep.fr

    Recopier et compléter cette table

    2.Utiliser les commandes windows

    Voir tutoriel ici

    Copier les commandes une à une dans un fichier d’extension .bat et executer le fichier.

    On peut rediriger la sortie de chacune des commandes dans un fichier .txt

    ipconfig /all >R1.txt
    traceroute  x  >>R1.txt

    a. Avec ipconfig, retrouver l’adresse du serveur DNS utilisé b. Avec traceroute, combien de sauts sont necessaires pour joindre musee-orsay.fr?

    Protocoles des couches 3 et 2

    Protocole TCP (optionnel)

    • Côté client Faire un clic droit sur la machine M1. Choisir show data exchange

    Dérouler alors trames échangées jusqu’à arriver à celles de protocole TCP

    Qu.4f: Dans la série de trames TCP:

    • L’adresse source et celle destination, sont-elles toujours les mêmes? Ou y-a-t-il une alternance?
    • Observer le détail de la première trame (ci-dessous): vous avez accès aux informations de la couche liaison (2), reseau (3), ainsi que la couche transport (4): identifier les informations pour chacune de ces couches: les informations pour chacune de ces couches: adresses mac (couche 1), IP et TTL pour la couche 2, SEQ et ACK pour la couche 3… rappels de 1ere NSI
    • Ces informations, évoluent-elles d’une trame à l’autre?
    detail de la premiere trame

    detail de la premiere trame

    Protocole IP

    Le document suivant présente la disposition des données dans un datagramme. Ce sont les informations transmises au niveau de la couche 2 du modèle OSI. (explications sur openclassrooms.com)

    datagramme

    datagramme

    Qu.4g: Quels sont les renseignements fournis sur l’image de la question 4f (détail de la première trame) que l’on retrouve des les champs du datagramme?

    Compléments théoriques sur les adresses des machines

    On pourra consulter la video sur les adresses IP et masques de sous-reseau

    Adresse IP

    IPv4

    L’adresse IP(Internet Protocol) identifie un périphérique à l’intérieur d’un réseau. A l’intérieur de ce réseau elle est unique.

    Une adresse (IPv4) est constituée de 4 nombres binaire de 8 bits chacuns (32 bits), comme par exemple:

    $1100 0000.1010 1000. 0000 0000. 0000 0001$

    Pour rendre la lecture plus facile, les séries de 8 bits seront traduites en leur valeur décimale correspondante, comprise entre 0 et 255 (voir le cours codage des nombres).

    L’adresse binaire vue plus haut sera alors traduite en :

    $192.168.0.1$

    L’adresse possède 2 parties:

    • une partie identifie la machine

    • une autre partie identifie le reseau

    Masque de sous-reseau

    Masque de sous-reseau: c’est une serie de valeurs avec des 255 ou 0, ou autre sur le(s) dernier(s) octet(s).

    La valeur correspondante binaire début donc par une série de 1, marquant les positions relatives à l’adresse reseau dans l’adresse IP.

    Par exemple: L’adresse machine suivante est constituée d’une première partie reseau, les 24 premiers bits, puis de l’adressage machine dans le reseau (8 derniers bits):

    $1100 0000.1010 1000. 0000 0000. 0000 0001 / 24$

    Le masque de sous-reseau est alors:

    $1111 1111.1111 1111. 1111 1111. 0000 0000$

    Que l’on peut aussi écrire:

    $255.255.255.0$

    Machines appartenant à un même reseau

    Definition: Deux machines sont sur le même réseau si et seulement si, la partie réseau de leur adresse IP est identique.

    Les derniers caractères /24 correspondent au masque de sous-reseau. Ils signifient que le reseau contenant la machine a une adresse codée sur les 24 premiers bits (192.168.0). Et que les 8 derniers bits constituent l’adresse de la machine dans ce reseau (il s’agit donc du .1 final).

    IPv6

    Pour la norme IPv6, ce nombre est sur 128 bits, soit 16 octets.

    Exemple d’adresse IPv6 exprimée en hexadécimal (32 caractères): 2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b

    classes d’adresse IP

    • classe A : adresses IP comprises entre 0.0.0.0 et 127.255.255.255 masque 255.0.0.0 : on ne peut avoir qu’une toute petite partie sous-reseau mais beaucoup d’adresses machines. Un petit reseau de beaucoup de machines.

    • classe B : 128.0.0.0 à 191.255.255.255 masque sous-reseau de 2 octets : on met autant de machines que de sous reseaux.

    • classe C : masque sous-reseau de 3 octets: beaucoup de sous-reseaux et peu de machines.

    Sur un reseau, deux adresses sont deja reservés: l’adresse de broadcast (bit adresse mis à 255), ainsi que l’adresse de reseau (bit d’adresse mis à zero). La plage adressable se situe entre ces 2 valeurs.

    Adresse mac

    Une adresse MAC (Media Access Control), parfois nommée adresse physique, est un identifiant physique stocké dans une carte réseau ou une interface réseau similaire. Elle est unique au monde

    Une adresse MAC est codée en hexadécimal, sur 6 octets (cf cours sur l’hexadécimal)

    00-1E-33-1D-6A-79 est une adresse MAC

    => Ouvrir l’invite de commande windows et entrer la commande ipconfig /all. identifier l’adresse MAC de votre ordinateur.

    Suite

    Liens

    protocole HTTP

    Le protocole HTTP

    HTTP - chaine Cookie connecté

    HTTP - chaine Cookie connecté

    Des requêtes HTTP jusqu’à la page Web

    HTTP est un protocole de la couche Application selon le modèle de communication entre machines OSI (développé dans ce cours).

    C’est le protocole qui permet de récupérer des ressources telles que des documents HTML. Il est à la base de tout échange de données sur le Web. C’est un protocole de type client-serveur, ce qui signifie que les requêtes sont initiées par le destinataire (qui est généralement un navigateur web).

    Le protocole HTTP est un protocole synchrone: pour chacune des tâches, il faut attendre la réponse avant d’exploiter la ressource chargée.

    Un document complet est construit à partir de différents sous-documents qui sont récupérés, par exemple du texte, des descriptions de mise en page, des images, des vidéos, des scripts et bien plus.

    requêtes pour la construction d'une page web. Source: MDN Web Docs

    requêtes pour la construction d'une page web. Source: MDN Web Docs

    Le navigateur web assemble alors ces ressources pour présenter un document complet à l’utilisateur : c’est la page web.

    Pour obtenir ces fragments de page, le navigateur web envoie des messages qui sont appelés des requêtes et les messages renvoyés par le serveur sont appelés réponses.

    Entre une requête et la réponse se trouvent de nombreuses entités qu’on désignera de façon générique sous le terme proxies. Celles-ci exécutent différentes opérations et agissent comme passerelles ou comme caches par exemple.

    En réalité, il y a plus d’un ordinateur entre un navigateur et le serveur qui traite la requête : il y a les routeurs, les modems et bien plus. Grâce à la construction en couche du Web, ces intermédiaires sont cachés dans les couches réseau et transport. HTTP, lui, est bâti sur la couche applicative.

    Pour plus de détails, voir la page sur MDN Web Docs.

    Une page web est un document hypertexte. Cela signifie que certaines parties sont des liens hypertextes qui peuvent être activés (généralement avec un clic de souris) afin de récupérer une nouvelle page web, permettant à l’utilisateur de naviguer sur le Web.

    Encore une fois, c’est le navigateur qui traduit ces instructions en requêtes HTTP.

    Plus de détails: voir page du site IONOS

    Ce protocole HTTP contrôle la façon dont le client formule ses demandes et la façon dont le serveur y répond, et connaît différentes méthodes de requête: GET, POST, HEAD, OPTIONS, TRACE, ou autres méthodes spécifiques.

    Méthodes HTTP

    HTTP est un protocole de la couche Application pour lequel le client et le serveur communiquent grâce aux en-têtes.

    • Pour la requête, c’est dans l’en-tête que la demande est formulée.
    • Pour la reponse, le serveur ajoute un en-tête, utile pour le protocole.

    GET

    c’est la méthode HTTP qui est la plus utilisée pour demander une ressource, par exemple un fichier HTML, au serveur Web. Dans le navigateur, on fait cette demande grâce à une URL (uniform ressource locator)

    Comprendre les URL et leur structure (MDN)

    Comprendre les URL et leur structure

    Comprendre les URL et leur structure

    Si l’on saisit l’URL www.exemple.com/test.html dans la barre d’adresse du navigateur, celui-ci se connecte au serveur Web www.exemple.com et lui envoie la requête GET qui contiendra:

    • la méthode de communication client-serveur: ici GET
    • le chemin vers la ressource: /test.html
    GET /test.html 

    Le serveur renvoie alors le fichier test.html.

    Déroulé d’une requête HTTP par la méthode GET

    Des paramètres d’URL qui peuvent être ajoutés à l’URL s’appelent chaine query, ou chaine de requête.

    Une URL valide est alors construite de la manière suivante:

    # nom de domaine symbolique
    http://nom du domaine.org/chemin_vers_la_ressource?chaine query

    La requête GET contient alors des informations supplémentaires que le serveur Web doit traiter.

    Les règles de syntaxe employées:

    • La chaîne de requête est introduite par un « ? » (point d’interrogation).
    • Chaque paramètre est nommé, il se compose donc d’un nom et d’une valeur : « Nom=Valeur ».
    • Si plusieurs paramètres doivent être inclus, ils sont reliés par un « & ».

    Par exemple, sur un site de météo, Nice est saisi comme ville et 12 comme heure UTC. L’URL saisie dans le navigateur pourrait être:

    http://ma_meteo.fr/search?ville=Nice&UTC=12

    Il se produit alors plusieurs étapes avant l’affichage de la page par le navigateur:

    • (1): saisie de l’URL dans la barre d’adresse (ou activation d’un lien depuis la page web)

    le navigateur établit une connexion TCP avec le serveur du site ma_meteo.fr puis lui envoie la requête HTTP suivante:

    GET /search?ville=Nice&UTC=12
    • (2): émission de la requêtte HTTP dans un format normalisé (ex. HTTP/1.1)
    • (3): la requête est parsée [voir ci-dessous]et interprétée par le serveur
    • (4): reponse du serveur avec un en-tête HTTP ainsi que le script html de la page demandée.

    En réalité, pour des problèmes de standardisation, l’URL ne contient pas tout à fait les mêmes symboles, et l’extension de l’adresse (la chaîne Query) pourrait plutôt ressembler à: %2Fsearch%3Fville%3DNice%26UTC%3D12 (voir URL encoder.org

    Definition du terme PARSE:

    “Parser” signifie analyser et convertir un script en un format interne que l’environnement d’exécution peut interpréter. Il s’agit d’une analyse syntaxique. Un paragraphe de la page sur les variables en python est consacré à la manipulation d’une chaine de caractères, ainsi qu’à la méthode parse en Python.

    inconvenients de la méthode GET

    La méthode GET est la plus utilisée pour obtenir les ressources qui construisent la page Web dans le navigateur.

    Cette méthode présente des limites lorsque cette page doit être personnalisée:

    Avec la méthode GET, les données à envoyer au serveur sont aussi écrites dans l’URL.

    Cela présente un avantage: Les paramètres de l’URL peuvent être enregistrés avec l’adresse du site Web. (utile pour un marque page, historique de navigation, enregistrer des pages Web contenant certains paramètres de filtrage et de tri, meteo avec conservation de la localisation…).

    Le principal inconvénient de la méthode GET est l’absence de protection des données. Un deuxième inconvénient est sa capacité limitée : suivant le serveur Web et le navigateur, l’URL ne peut pas contenir plus de 2 000 caractères environ.

    La méthode POST

    Cette méthode n’écrit pas les paramètres de l’URL, mais les ajoute à l’en-tête HTTP (HTTP header)

    Revenons sur l’exemple de la page meteo. Voici un aperçu des interactions possibles entre l’utilisateur et la page. Celle-ci pourrait présenter:

    • un champs de texte à remplir (Ville)
    • un menu déroulant (heure)

    L’en-tête HTTP (HTTP header) pourrait alors avoir le contenu suivant:

    Comparatif GET POST

    GET POST
    Visibilité Visible pour l’utilisateur dans le champ d’adresse Invisible pour l’utilisateur
    Marque-page et historique de navigation Les paramètres de l’URL sont stockés en même temps que l’URL. L’URL est enregistrée sans paramètres URL.
    Cache et fichier log du serveur Les paramètres de l’URL sont stockés sans chiffrement Les paramètres de l’URL ne sont pas enregistrés automatiquement.
    Comportement lors de l’actualisation du navigateur / Bouton « précédent » Les paramètres de l’URL ne sont pas envoyés à nouveau. Le navigateur avertit que les données du formulaire doivent être renvoyées.
    Type de données Caractères ASCII uniquement. Caractères ASCII mais également données binaires.
    Longueur des données Limitée - longueur maximale de l’URL à 2 048 caractères. Illimitée.
    • GET pour les paramètres d’un site Web (filtres, tri, saisies de recherche, etc.).
    • POST pour la transmission des informations, des fichiers, et des données de l’utilisateur.

    Autres méthodes HTTP

    La méthode HEAD

    Utilisée pour interroger l’en-tête de la réponse, sans que le fichier ne vous soit envoyé immédiatement. C’est utile, par exemple, si des fichiers volumineux doivent être transférés : grâce à la requête HEAD, le client peut d’abord être informé de la taille du fichier et seulement ensuite décider s’il veut recevoir le fichier.

    OPTIONS

    Avec la méthode OPTIONS, le client peut demander quelles méthodes le serveur supporte pour le fichier en question. Ces méthodes autorisées sont contenues dans le champs d’en-tête “allow”.

    TRACE

    La méthode TRACE peut être utilisée pour tracer le chemin qu’une requête HTTP emprunte jusqu’au serveur puis jusqu’au client. Vous pouvez utiliser la commande tracert de Windows pour tracer vous-même cet itinéraire.

    tracert www.exemple.com

    HTTP header

    HTTP header Côté client

    Chaque requête HTTP formulée par le navigateur contient:

    • une premiere ligne constituée de: METHODE suivie du PATH (chemin vers la ressource) suivi de la version HTTP. Exemple: `GET /index.php HTTP/1.1
    • Puis vient le HTTP header.

    Pour le client, voici les principales informations contenues dans le http header:

    Champ d’en-tête Signification Exemple
    Accept Les types de contenu que le client peut traiter ; si le champ est vide, il s’agit de tous les types de contenu. Accept: text/html, application/xml
    Accept-Charset Quels jeux de caractères le client peut afficher. Accept-Charset: utf-8
    Cookie Cookie stocké pour ce serveur Cookie: $Version=1; Content=23
    Content-Length Longueur en octets Content-Length: 212
    Content-Type Type MIME: text/plain pour les fichiers texte, application/.. pour le reste Content-Type: application/x_222-form-urlencoded
    Date Date et heure de la demande Date: Mon, 9 March 2020 09:02:22 GMT
    Host Nom de domaine du serveur Host: exemple.fr
    Referrer URL de la ressource à partir de laquelle la demande est faite (c’est-à-dire à partir de laquelle le lien a été créé) Referrer: https://exemple.fr/index.html
    User-Agent navigateur du client Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36

    HTTP header Côté serveur

    Chaque reponse HTTP retournée par le serveur contient:

    • une premiere ligne constituée:
      • de la version HTTP
      • du code statut (200, 301, 404, …)
      • du message de statut (OK, …)
    • puis les différents champs de l’en-tête.
    • et enfin le contenu html ou autre.

    Sur l’exemple suivant, on voit par exemple, sur la 1ere ligne:

    • HTTP/1.1 est la version valide du protocole HTTP.
    • 200 OK est le code de statut. Il indique que le serveur a reçu, compris et accepté la demande.

    Le serveur renvoie cet en-tête avec la page HTML

    Le serveur renvoie cet en-tête avec la page HTML

    Explications pour les différentes lignes (les champs d’en-tête):

    • Content-Encoding et Content-Type fournissent des informations sur le type de fichier.
    • Age, Cache-Control, Expires, Vary et X-Cache font référence à la mise en cache du fichier.
    • Etag et Last-Modified sont utilisés pour le contrôle de la version du fichier livré.
    • Le terme « server » désigne le logiciel du serveur Web.
    • Content-Length est la taille du fichier en octets.

    Classes de statut HTTP

    erreur 404: page internet introuvable

    erreur 404: page internet introuvable

    • Classe 1xx, codes d’information : si le code commence par 1, le serveur indique au client que la requête actuelle est en en train de se faire. Cette classe regroupe des codes en cours de traitement et d’envoi.
    • Classe 2xx, codes de succès : un code qui commence par 2 indique que la requête a abouti. Elle a été reçue par le client, comprise et acceptée. En conséquence, les codes 2xx du serveur sont envoyés en même temps que les informations des pages Web désirées. En général, l’utilisateur ne prend en compte que la page Web qu’il a chargé.
    • Classe 3xx, codes de redirection : un code 3xx indique que la requête a été reçue par le serveur. Cependant, le client doit encore provoquer une action complémentaire. Par exemple, le code HTTP 301 signifie changement d’adresse définitif : les informations demandées par le client ne se trouvent plus à l’adresse indiquée car celle-ci a définitivement changée. Le navigateur Internet peut aussitôt rediriger l’utilisateur à la nouvelle adresse.
    • Classe 4xx, erreurs du client : le code 4xx renvoie à une erreur commise par le client. Le serveur a reçu la requête mais ne peut pas l’exécuter. La réponse 404 signifie par exemple que la page Internet est introuvable.. En général, il s’agit d’une syntaxe erronée. En général, l’utilisateur est automatiquement dirigé vers une page HTML.
    • Classe 5xx, erreurs du serveur : Le code 5xx fait référence à une erreur commise par le serveur. Ces informations indiquent que la requête en question est complètement ou provisoirement impossible. Une page d’erreur HTML est également présentée.

    HTTP: sécurité et confidentialité

    Sécurité

    La sécurité d’un protocole vise à ce que les communications ne soient pas exploitables pour quelqu’un qui intercepte le message.

    Le protocole HTTP possède une version sécurisée des échanges: il s’agit de HTTPS.

    confidentialité: HTTP, un protocole sans ETAT

    Pour une communication client-serveur: Un état est conservé entre 2 requêtes si l’utilisateur, le client, s’est identifié.

    Protocole sans état

    wiki: protocole sans état

    Un protocole sans état (en anglais stateless protocol) est un protocole de communication qui n’enregistre pas l’état d’une session de communication entre deux requêtes successives. La communication est formée de paires requête-réponse indépendantes et chaque paire requête-réponse est traitée comme une transaction indépendante, sans lien avec les requêtes précédentes ou suivantes.

    Le protocole HTTP est donc un protocole synchrone, et sans état.

    Des couches de protocoles avec et sans état:

    Dans les différentes couches de protocoles de communication: le protocole HTTP (sans état) s’appuie sur le protocole TCP, un protocole avec état, qui s’appuie à son tour sur le protocole IP, un autre protocole sans état.

    Cookies

    1. A quoi servent les cookies? voir MDN: HTTP cookies

    Les cookies permettent de conserver de l’information en passant par le procotole HTTP qui est lui “sans état”.

    Les cookies, ce sont des données qu’un serveur envoie au navigateur web de l’utilisateur. Le navigateur peut alors le stocker localement, puis le renvoyer à la prochaine requête vers le même serveur. Typiquement, cette méthode est utilisée par le serveur pour déterminer si deux requêtes proviennent du même navigateur.

    Cela permet:

    • Gestion des sessions Logins, panier d’achat, score d’un jeu, ou tout autre chose dont le serveur doit se souvenir.
      Par exemple, garder un utilisateur connecté.

    • Personnalisation Préférences utilisateur, thèmes, et autres paramètres.

    • Suivi Enregistrement et analyse du comportement utilisateur.

    2. Protection des données

    contrôle des cookies par l'utilisateur

    contrôle des cookies par l'utilisateur

    Les cookies étaient auparavant utilisés pour le stockage côté client. Mais aujourd’hui, la tendance est plutôt d’envoyér ces données avec chaque requête. Cela a pour conséquence de partager ses données pour l’internaute. Son surf n’est plus complètement anonyme.

    En application de la directive ePrivacy, les internautes doivent être informés et donner leur consentement préalablement au dépôt et à la lecture de certains traceurs

    Les cookies ont un domaine qui leur est associé. Si ce domaine est le même que la page sur laquelle vous êtes, on parle de cookie interne (first-party cookie). Si le domaine est différent, on parle de cookie tiers (third-party cookie).

    Pour plus de détails, voir la page: Quel est le cadre juridique applicable?

    HTTPS

    HTTPS : les en-têtes sont-elles chiffrées ?

    Oui, avec HTTPS, les en-têtes HTTP sont bien chiffrées — et c’est un point souvent mal compris! Ce qu’il se passe réellement:

    • HTTPS = HTTP + TLS (Transport Layer Security)
    • Le chiffrement TLS s’applique à tout le contenu HTTP, c’est-à-dire :

    ✅ Les en-têtes (headers) — Host, Cookie, Authorization, User-Agent…

    ✅ Le corps de la requête (body)

    ✅ Les en-têtes de réponse du serveur — Set-Cookie, Content-Type…

    ✅ Le corps de la réponse

    Ce qui reste visible (non chiffré) Même en HTTPS, quelques informations transitent en clair :

    Élément Visible ? Pourquoi
    Adresse IP du serveur ✅ Oui Nécessaire pour le routage réseau
    Port (443) ✅ Oui Idem
    Nom de domaine (SNI) ⚠️ Souvent oui Échangé pendant la négociation TLS pour choisir le bon certificat
    URL complète / chemin ❌ Non Chiffré
    En-têtes HTTP ❌ Non Chiffrés

    SNI (Server Name Indication) : lors de la poignée de main TLS (handshake), le client indique le nom de domaine cible. Cette information est traditionnellement en clair, bien que la technologie ECH (Encrypted Client Hello) commence à chiffrer cela aussi.

    On peut souvent deviner le domaine (via le SNI ou l’IP), mais pas la page précise visitée (l’URL complète, les cookies, les paramètres…).

    Schéma simplifié

    [Couche réseau]   IP source / IP destination  →  visible
    [Couche TLS]      Handshake TLS (certificat)  →  partiellement visible
    [Couche HTTP]     En-têtes + Corps            →  chiffré ✅

    Travaux Pratiques:

    Formulaire et protocoles de transmission

    La vulnérabilité des services d’authentification web correspond aux faiblesses des protocoles d’authentification du web.

    On traitera de ces problèmes avec le TP suivant: Lien

    le moniteur réseau

    TP inspiré de la page MDN Mozilla

    Le moniteur réseau du navigateur affiche des informations sur les requêtes effectuées (par exemple, au chargement d’une page).

    Outils de developpement sous Chrome

    Outils de developpement sous Chrome

    Répondre aux questions suivantes sur le cahier

    Faire une recherche sur un moteur de recherche pour trouver l’URL de la page d’accueil du site cité des sciences.

    1. Lorsque vous lancez un recherche sur un moteur de recherche, celui-ci utilise t-il une méthode GET ou POST? Justifiez. Quel est l’intérêt d’utiliser cette méthode?

    Aller sur la page d’accueil du site de: cité des sciences.

    2. Ouvrir le moniteur réseau du navigateur.

    3. Après avoir rechargé la page de cité des sciences, quel est le nombre de requêtes?

    4. Ce nombre évolue t-il alors que vous laissez la page ouverte, sans aucune action de votre part?

    5. Est-ce que toutes les requêtes sont de type GET?

    6. Cliquer sur la première ressource téléchargée, accueil/. Vous obtenez alors le détail de la ressource.

    • Quelle est la différence entre les informations transmises par le Headers et celles transmises par le Reponse (ou Response)?
    • Pour l’onglet Headers: S’agit-il du HTTP header émis par le client ou bien celui serveur? Justifier.
    • Reconnaitre et interpréter certains champs de l’en-tête.

    7. Aller sur l’onglet Cookies pour cette première ressource. Que remarquez vous?

    • Y-a-t-il des ressources qui ont un code statut différent de 200? Quels sont-ils et que signifient-ils?
    • Quel est le nom de domaine qui revient le plus souvent pour ces requêtes, dont le statut est différent de 200?
    • Pour l’une de ces ressources, on observe en détail l’extension de l’URL que l’on appelle Query String (chaine Query). Celle-ci est écrite en Base 64. Elle est constituée de la série de caractères suivante:
    c2l0ZUNvZGU9ZGFjcGJybDR0byZ2aXNpdG9yQ29kZT1mMnBvbGJucXRhNTU5b3YwJnN0YXJ0T2ZWaXNpdD1mYWxzZSZzY3JpcHRWZXJzaW9uPTIwMTkwMTE1Jm5vbmNlPThGRjcyMTVBRjMyOUM4MEEmZXZlbnRUeXBlPWFjdGl2aXR5JnRpbWU9MTYzNTc3NDY4NDMzNyZhY3RpdmU9ZmFsc2UmbnVtYmVyQ2xpY2tzPTAmdGFiQ291bnQ9MA==

    Utiliser un décodeur en base 64, comme par exemple base64.guru et afficher le texte decodé.

    8. De quoi peut-il s’agir?

    Pour l’outil de developpement du navigateur, on pourra s’aider de la page MDN Web Docs: Détails des requêtes réseau

    Liens

    …Dans le cas du protocole HTTP, les fichiers cookies sont transmis en texte clair dans les en-têtes des requêtes HTTP, ce qui signifie qu’ils ne sont pas chiffrés. Un acteur malveillant (reseau wifi public) peut alors facilement intercepter le trafic entre vous et le site Internet sur lequel vous vous trouvez, et en extraire les cookies…

    • Peut-on utiliser cette technique pour bypasser le proxy du lycée? video youtube de 2015 => Non à cause des hebergements mutualisés, et de l’identification par l’en-tête host, necessaire pour la phase de présentation (https)

    TP GET POST cookies

    Vous repondrez aux question sur le document: reseau_tp_form.odt

    Formulaire de données - 1ere NSI

    But de la séance

    Ce TP a pour but d’illustrer ce qui arrive quand un utilisateur soumet un formulaire: où les données vont-elles et comment les gère-t-on une fois à destination? Nous examinerons aussi quelques problèmes de sécurité associés à l’envoi des données d’un formulaire.

    img de MDN Sending_and_retrieving_form_data

    img de MDN Sending_and_retrieving_form_data

    Le formulaire en ligne

    Il est conseillé d’utiliser le navigateur MOZILLA pour la clarté des renseignements fournis par les outils réseau.

    On utilisera le formulaire à la page http://resaonline.la-bo.xyz.

    formulaire de connexion

    formulaire de connexion

    Le bandeau de navigation permet de selectionner la méthode d’envoi des données:

    • méthode GET
    • méthode POST
    • authentification par cookie

    Vous allez utiliser chacune des 3 méthodes. La procédure sera la même dans les 3 cas:

    • Ouvrir la fenêtre d’outils de développement du navigateur. Choisir l’outil réseau
    • Remplir et envoyer le formulaire
    • Une fois parvenu à la page “espace personnel”, vous allez explorer les éléments de la requête.

    Dans la fenêtre de dev tools, l’outil réseau montre les différentes requêtes et ressources demandées. Dans cette liste, selectionner la page web (resaonline.la-bo.xyz). On peut alors procéder à l’analyse de l’URL. Cliquer sur le curseur devant GET.

    inspecteur reseau sur Mozilla

    inspecteur reseau sur Mozilla

    L’URL permet de router notre requête vers le serveur correspondant au site web sur le réseau.

    Un site Web est identifié selon une combinaison unique de:

    • son Adresse IP
    • un Numéro de port
    • le Host header (equivalent au nom de domaine)

    Méthode GET

    1. Dans la barre d’URL du navigateur. Recopier l’URL de la page demandée. Repérer les 3 sous parties: (se documenter: openclassroom, ou bien wikipedia)

      • le nom de domaine
      • le chemin
      • les paramètres query
    2. la connexion vers le site, se fait-elle selon le protocole http ou bien https? Comment le voit-on? Peut-on modifier le protocole directement dans la barre d’adresse, en ecrivant http:// ou bien https:// avant le nom de domaine resaonline.la-bo.xyz

    3. Dans la fenêtre réseau du dev tools: Repérer les informations du header (en-tête) pour cette requête (client):

      • méthode (vous devez lire en principe: GET)
      • la version HTTP (1.1? autre?)
      • L’identité du site Web serveur: voir plus haut (IP, Host header)
      • le chemin vers la ressource sur le serveur (path)
      • les paramètres query (Query String Parameters), s’il y en a.
    4. Repérer les informations de la reponse à cette requête

      • code de statut (200 OK?)
      • Referrer: URL de la ressource à partir de laquelle la demande est faite (c’est-à-dire à partir de laquelle le lien a été créé)
      • Content-Type: informations sur le contenu du document chargé (txt, html, js, css, …?)
      • User-Agent: navigateur client
    5. Recharger la page: le navigateur propose t-il de soumettre à nouveau le contenu du formulaire? Les informations du formulaire sont-elles toujours présentes dans la carte d’identité?

    6. Dans l’historique du navigateur: le lien consulté contient-il les Query String Parameters?

    7. Ecrire directement, dans la barre d’adresse une requête vers ce serveur en choisissant vous-même vos Query Parameters. Le serveur repond-il à votre requête?

    Méthode POST

    Répondre aux même questions (qu 1 à 6 de la méthode GET).

    1. Dans les outils réseau du navigateur, chercher l’onglet cookie, et lire le contenu. Faire une copie d’écran dans votre document réponse. Comment les informations du formulaire sont-elles écrites dans le cookie? Sous une forme structurée?
    exemple de capture d'écran de l'outil d'exploration du cookie

    exemple de capture d'écran de l'outil d'exploration du cookie

    1. Recharger la page: le navigateur propose t-il de soumettre à nouveau le contenu du formulaire? Les informations du formulaire sont-elles toujours présentes dans la carte d’identité?

    2. Dans un autre onglet du navigateur: saisir l’adresse http://resaonline.la-bo.xyz/getcookie. Les informations du formulaire sont-elles toujours présentes dans la carte d’identité?

    3. Saisir maintenant cette adresse dans un AUTRE navigateur. Les informations du formulaire sont-elles toujours présentes dans la carte d’identité?

    4. Rechercher le cookie grace aux options du navigateur. (Voir tuto sur cette page. Quels autres cookies ont été déposés lors de votre session (aujourd’hui)? Comment peut-on se debarrasser de ces cookies?

    1. Conclure: Les traces numériques laissées sur mon ordinateur peuvent-elles contenir des informations sur mon identité numérique?

    Sécurité sur le Web

    Video: transfert encryptage ssl

    Code Rock & Apprendre

    Code Rock & Apprendre

    Questions

    1. Quel est le scénario mettant en jeu un cyberpirate proposé dans cette vidéo?

    2. Est-ce que cela change quelque chose, de naviguer en http ou bien en https?

    3. parmi les éléments suivants, quels sont ceux qui sont cryptés lors d’une communication en https: (lire les discussions sur https://www.ssl.com/faqs/what-is-https/ ou bien https://stackoverflow.com/questions)

      • Domain name
      • Request URL (which web page was requested by the client)
      • Website content
      • Query parameters
      • Headers
      • Cookies
    4. Si votre échange avec le serveur est en https. Est-ce une bonne idée d’échanger des informations personnelles par la méthode GET si le site internet ne propose que la méthode GET? Pourquoi?

    5. Conclure: Quels conseils peut-on donner à un utilisateur qui navigue et fait des achats sur le net?

    Liens

    tuto requests

    Module request

    Le module requests de python permet de recuperer les données d’une requete HTTP dans un format exploitable (dict,list).

    La communication avec le serveur demande d’utiliser une clé, que vous devrez générer en créant un compte. (API key).

    Données météo open source

    L’exemple suivant traite de l’exploitation d’une requete sur le site OpenWeatherMap. Le compte gratuit permet de realiser quelques requetes, en nombre raisonnable, et sera suffisant pour developper un petit projet NSI.

    Voici le script minimal

    import requests,json,sys
    
    APPID ='-- a remplacer par votre cle API et placer entre les guillemets--'
    #location = 'London,GB'
    location = 'Nice,FR'
    
    #Download the JSON data from OpenWeatherMap.org's API.
    
    url = f'https://api.openweathermap.org/data/2.5/weather?q={location}&appid={APPID}'
    response = requests.get(url)
    response.raise_for_status()
    
    #Uncomment to see the raw JSON text:
    #print(response.text)
    
    #Load JSON data into a Python variable.
    weatherData = json.loads(response.text)
    
    #Print weather descriptions
    
    w = weatherData
    print(f'Current weather in {location}')
    print(w['weather'][0]['main'],'-',w['weather'][0]['description'])
    print()

    Prolongement: Pour obtenir les prévisions sur plusieurs jours, utiliser la requete:

    url=f'https://api.openweathermap.org/data/2.5/forecast?q={location}&cnt=3&appid={APPID}'

    Le traitement va alors différer, car la météo des différents jours sera placée dans la clé list du dictionnaire weatherData.

    En-tête HTTP

    Avec l’architecture reseau d’un lycée, le logiciel proxy va filtrer les requêtes, et empêcher de lancer celles-ci depuis un script python. Cela peut constituer une faille de sécurité.

    L’en-tête HTTP va comporter une signature du client, et le proxy va distinguer un navigateur d’un IDE python.

    On peut vouloir modifier l’en-tête HTTP pour imiter le comportement d’un navigateur.

    Paramètre Valeur par défaut (requests) Valeur “Navigateur” (à imiter)
    User-Agent python-requests/x.x Mozilla/5.0 … Chrome/…
    Accept */* text/html, …
    Accept-Language (Absent) fr-FR, fr;q=0.9
    Signature TLS Bibliothèque Python Moteur Blink/WebKit (Chrome/Firefox)

    Voici adaptation du script que l’on peut alors utiliser depuis le lycée.

    Contenu masqué…

    Sous-sections de IHM python

    Cours - les bases en python

    Version pdf du document: Lien

    Les grands principes du langage

    Comme tout langage, python utilise des instructions. Ce sont :

    • les affectations, opérations
    • les definitions de fonctions
    • l’appel de fonctions
    • les instructions conditionnelles
    • les boucles

    Les types de base en python

    Créer et affecter une valeur

    Def: Une variable est un espace mémoire auquel on donne un nom. Une variable a un type, et stocke une valeur. L’affectation se fait avec le symbole =

    Variable et type

    Def: Un type définit l’ensemble des valeurs possibles pour les données, les relations entre ces données, et les opérations que l’on peut réaliser.

    Pour déterminer le type d’une variable, on utilise la fonciton type:

    > x = 5
    > type(x)
    int

    Les types de base sont:

    • nombres entiers: int
    • nombres à virgule flottante: float
    • chaine de caracteres: str
    • les variables logiques booléens: bool (True ou False)
    • le type rien: None

    Les nombres entiers et décimaux

    Un entier: C’est un nombre qui n’a pas de point décimal.

    Pour les décimaux (les flottants), ceux-ci ont pour rôle d’approcher les nombre réels, mais il est impossible de les représenter EXACTEMENT. Le séparateur est un point plutôt qu’une virgule.

    Attention, il est impossible de comparer des flottants entre eux. On préfèrera alors eviter de les utiliser pour des tests logiques d’egalité (==).

    a = 0.1
    b = 0.2
    a + b == 0.3
    # False
    abs(0.1 + 0.2 - 0.3) < 0.000001
    # True

    Pour les puissance de 10 (notation scientifique): On peut utiliser la notation scientifique e ou E. Le nombre d’Avogadro s’écrit ainsi:

    $$6.02E23$$

    Pour transformer le type, on utilise les fonctions int, float, str:

    type de depart type d’arrivée fonction
    int str str(x)
    str int int(x)
    int float float(x)
    istr float float(x)

    Type booléen

    Ce sont les valeurs True`` et ``False. Les expressions logiques, dont l’evaluation vaut True ou False utilisent les opérateurs de comparaison (>, >=, <, <=, ==, !=), plus les suivants : and, or, not, in, not in:

    Lorsque l’on affecte une expression à une variable, celle-ci est d’abord evaluée avant que la valeur ne soit affectée:

    a = 10
    b = 20
    c = a < b and b < 100
    # c'est d'abord l'expression a < b puis True AND b < 100 qui est evaluée (True)
    # puis c stocke True

    Les expressions booléennes sont utilisées pour les structures conditionnelle (if ... elif ... else).

    Les chaînes de caractères

    Definition: C’est une séquence constituée d’un ou plusieurs caractères, entourés de guillemets simples ou doubles.

    Remarque: ne pas confondre le nom d’une variable avec la chaine de caractères:print('a') ≠ print(a)…

    a = 10
    print(a)
    # affiche 10
    print('a')
    # affiche .a

    On peut réaliser des concatenations sur les chaines avec les opérateurs +, *.

    On peut aussi réaliser les opérations de comparaison >, <, ==, !=sur les chaines. Et aussi le test d’appartenance in, not in. Ces opérations retournent un booléen.

    • comparaison d’ordre: A < B vaut True, Ab < A vaut False.
    • d’égalité: HA == ha vaut False
    • ou in jour vaut True
    • ou not in jour vaut False

    Boucles

    Boucle non bornée

    Definition: ** Une boucle non bornée permet de répéter un élément de code un nombre à priori inconnu de fois.

    • Pour la boucle non bornée, on définit un variant de boucle au départ, i qui vaut zero. Puis on augmente i d’une unité à chaque itération, jusqu’à ce que sa valeur atteigne 9. Puis la condition i < 10 n’est plus réalisée et le script poursuit après la boucle.

    On écrit l’instruction: while <condition>:

    Le bloc de code est indenté sous cette première ligne:

    while <condition>:
      instruction 1
      instruction 2
    instruction suivante # suite du programme

    Exemple:

    r = 4
    while r > 0:
      r = r - 3
    print('à la fin du programme, r vaut ' + str(r))

    Boucle bornée (non traité)

    Definition: ** Une boucle bornée permet de répéter un élément de code un nombre fixe de fois.

    On rappelle que la différence entre une boucle bornée et non bornée est la definition d’un variant de boucle. Celui-ci varie sur une étendue qui est déclarée au depart.

    La fonction range(X) établit une liste de valeurs itérables, que prend le variant i qui est déclaré dans la boucle: i vaut successivement {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, de 0 à X-1.

    Les scripts suivants sont équivalents:

    for i in range(10):
      pass
    
    i = 0
    while i < 10:
      i = i + 1
    • Pour la boucle bornée, i est le variant de boucle, qui évolue à chaque itération de 0 à 9.

    Erreurs et bugs

    Les erreurs de syntaxe

    dues au non-respect des règles d’écriture de Python (parenthèses, :, …)

    erreur de definition

    dues à l’usage d’un nom qui n’a pas encore été défini (variable ou fonction):

    >>> a = a + 1
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
    NameError: name 'a' is not defined

    erreurs de type

    print(3 + 'cm') génère l’erreur *unsupported operand type(s) for +: ‘int’ and ‘str’

    erreurs d’execution

    dues à des instructions que l’ordinateur ne sait pas exécuter, comme un division par zero.

    Erreurs de logique

    n’occasionnent en général pas de message d’erreur, mais provoquent des problèmes inatendus (boucle infinie, autre…)

    Pour prévenir des erreurs logiques, il peut être utile d’utiliser des traces dans son programme pour comprendre la cause de l’erreur. On rajoute généralement des sorties print(variable) pour les variables que l’on veut suivre lors de l’execution.

    Les fonctions

    Def: Une fonction permet d’encapsuler un bloc d’instructions et de lui donnéer un nom.

    On peut ensuite exécuter ce bloc en utilsant ce nom. On dit qu’on appelle cette fonction.

    Def: Valeur de retour: Une fonction retourne en général une valeur. Après le mot-clé return:

    def hello():
      return 'Hi'
    
    hello()
    # 'Hi'

    Une fonction peut avoir plusieurs paramètres qui permettent de transmettre des valeurs au bloc d’instructions. A l’interieur de la fonction, ces paramètres sont traités comme des variables, mais locales: Elles n’existent pas à l’exterieur du bloc. (voir plus loin)

    Lors de l’appel de la fonction, le nombre d’arguments passés doit correspondre au nombre de paramètres attendus. (sauf si pour les paramètres ayant une valeur par defaut). Il y a alors une affectation: paramètre = argument

    def carre(x):
      return x**2
    
    carre(5)
    # 25

    Portée des variables

    Lorsqu’une fonction utilise des variables, celles-ci sont normalement propres à la fonction et ne sont pas accessibles à l’extérieur de celle-ci. On dit qu’il s’agit de variables locales, par opposition aux variables globales, du programme principal.

    Exemple: si on définit une variable a avant la définition de la fonction, celle-ci sera différente du a de la fonction somme:

    a = 10
    def somme(a, b):
        s = a + b
        return s
    >>> somme(1,0)
    1

    Python permet d’affecter à l’intérieur d’une fonction, une variable globale. Pour cela, il faut déclarer la variable comme étant globale au début de la fonction:

    a = 10
    def somme(b):
        global a
        s = a + b
        return s
    >>> somme(0)
    10

    Modifier une variable globale depuis une fonction s’appelle un effet de bord. C’est considéré comme une mauvaise pratique, mais parfois indispensable.

    Modules

    Une fonction peut être placée dans un autre fichier. On a alors:

    • un fichier principal (le programme main)
    • un ou plusieurs fichiers annexes (modules)

    **Def:**Un module apporte des fonctions et des variables et permet une extension du langage.

    Le programme principal doit alors faire référence aux modules. L’une des manières est la suivante:

    import module
    from module import *
    import module as alias

    Exemples:

    import du module appel d’une fonction du module
    import math math.sin(x)
    from math import sin sin(x)
    from math import * sin(x)
    import numpy as np np.arrange(3, 15, 2)

    Comment choisir la bonne méthode?

    • Il est recommandé de ne charger que les fonctions utiles du module, avec: from module import fonction1, fonction2
    • Si on importe le module entier, on préfera import module pour utiliser la fonction avec la notation pointée module.fonction.
    • Pour executer l’un des modules depuis le shell python, on peut écrire:
    >>> from programme import *

    Exemple: supposons que le programme suivant soit dans le fichier test.py

    # contenu du fichier test.py
    a = 10
    def somme(b):
        s = a + 10
        return s

    On execute le programme dans le shell:

    >>> from test import *
    >>> a
    10
    >>> somme(0)
    20

    Exercices

    Exercices

    Questions à reponses courtes

    a. Quels sont les 2 types numeriques en Python ?

    b. True et False: Quel est leur type?

    c. Comment fait-on l’affectation multiple de la valeur 3 à la variable a et 55 à la variable b?

    d. Former la chaine “Ring the Bell” à partir de a = "Ring", b = "the"et c = "Bell".

    e. Que donne l’expression: 26 // 4 ?

    f. Que donne l’expression: 26 % 4 ?

    g. Que donne l’expression: ``“4” + “4”` ?

    h. Que donne l’expression: str("4") + 4 ?

    i. Que donne l’expression `“Sup” * 3 ?

    j. Traduire en Python le calcul: $(1,2.10^{-3})**2$

    k. Quelle erreur est renvoyée par: "4" + 4?

    l. L’instruction suivante: a = a + 1 génère une erreur de type NameError. Pourquoi?

    Calcul avec des propositions

    a. Que donne l’expresion suivante: 10 > 9 and 3 < 4?

    b. Que donne l’expresion suivante: 10 > 9 and 5 < 4?

    c. Que donne l’expresion suivante: 10 > 9 or 3 < 4?

    d. Que donne l’expresion suivante: True or False?

    e. Que donne l’expresion suivante: True and not False?

    Variables et opérations

    script 1

    age = 0
    annee = 2001
    age = age + 17
    annee = annee + age

    a. Que vaut année à la fin du script?

    b. Que vaut age à la fin du script?

    script 2

    age = input('Quel est ton age?')
    nom = nput('Quel est ton nom?')
    message = "ton nom est " + nom + ", et tu as  " + age + " ans"

    a. L’utilisateur du programme repond 21 puis Francois. Qu’est ce qui est affiché à l’écran?

    On ajoute la ligne suivante au programme:

    annee_de_naissance = 2023 - age

    b. Cela génère une erreur de type. Pourquoi? Comment corriger ce problème?

    Instruction conditionnelle

    1. Ecrire l’instruction conditionnelle qui affiche la phrase “il va faire très froid / froid / bon / chaud / très chaud” selon la valeur de la variable t (la température). Vous choisirez les seuils entre chaque niveau de température.
    2. Ecrire une fonction meteo qui retourne “froid / froid / bon / chaud / très chaud” selon le paramètre t. Et écrire le programme qui appelle la fonction pour afficher “il va faire …”.

    Boucle non bornée

    Multiplication

    Compléter le script suivant qui réalise la multiplication de a par b, en n’utilisant que l’opérateur +:

    a = 3
    b = 8
    produit = 0
    while  b > ...   : 
        produit = produit + a
        b = b - ...

    Division

    Ecrire un script qui réalise la division de a par b, en n’utilisant que l’opérateur -.

    Autres exercices

    addition de chaines de caractères

    Dans le Bourgeois Gentilhomme, Molière (acte 2 scene 4): le Maitre de Philosophie dit:

    On les peut mettre premièrement comme vous avez dit : « Belle Marquise, vos beaux yeux me font mourir d’amour ». Ou bien : « D’amour mourir me font, belle Marquise, vos beaux yeux ». Ou bien : « Vos yeux beaux d’amour me font, belle Marquise, mourir ». Ou bien : « Mourir vos beaux yeux, belle Marquise, d’amour me font ». Ou bien : « Me font vos yeux beaux mourir, belle Marquise, d’amour ».

    La leçon d'orthographe.

    La leçon d'orthographe.

    a. Définir plusieurs variables contenant les morceaux de la phrase “Belle Marquise, …”, de telle sorte que l’on puisse afficher avec la fonction print et l’opérateur + des chaines de caractères, les différentes variantes énoncées. (On ignore la distinction entre majuscule et minuscule).

    b. Ecrire l’opération sur ces variables qui donne chacune des phrases.

    Version pdf du document: Lien

    Editeur Turtle

    Nous allons voir 3 options pour réaliser les scripts python turtle. La syntaxe diffère légèrement selon si vous utilisez la calculatrice TI83 CE Premium Python, la tablette Android, ou bien un interpreteur en ligne.

    Les 3 programmes proposés permettent de réaliser cette première figure.

    TI83 CE Premium Python

    • La calculatrice doit être à jour. Il faudra ajouter le module CE_turtle pour pouvoir utiliser le module python turtle. Voir notice d’installation
    • Dans l’App Python: démarrer un nouveau script. Ecrire et rédiger la première ligne: from turtle import *. Quitter le shell et revenir dans l’editeur de programme pour poursuivre l’edition. Voir Notice turtle pour la TI83

    Le script de démarrage sur la TI83:

    from turtle import *
    t = Turtle()
    t.clear()
    for i in range(4):
        t.forward(100)
        t.left(90)
    t.done()

    Astuces:

    • On appuie alors sur la touche Annul pour quitter la fenêtre graphique.
    • On peut augmenter la vitesse de la tortue: t.speed(0)

    Tablette Android Pydroid3

    • Installer l’App Pydroid3 (version gratuite)
    • Utiliser la notice suivante pour réaliser votre premier script et prendre connaissance de l’environnement

    Le script de démarrage sur la tablette android est le suivant:

    from turtle import *
    t = Turtle()
    t.clear()
    t.shape("turtle")
    for i in range(4):
        t.forward(100)
        t.left(90)
    exitonclick()

    Notebook en ligne: Basthon

    • Aller sur la page Basthon * Il vous faudra choisir: Notebook à la page d’accueil

    Le script de démarrage sur la tablette android est le suivant:

    from turtle import *
    reset()
    for i in range(4):
        forward(100)
        left(90)
    done()

    Tkinter les bases

    Tkinter les bases

    • télécharger le dossier zip: tuto_tkinter.zip * le placer dans vos Documents
    • Extraire tout
    • Ouvrir le fichier main.py avec un IDE Python de la suite Winpython

    Import des modules

    Le module tkinter apporte l’environnement graphique.

    Le module PIL permet la gestion des images.

    Démarrer votre fichier par:

    from tkinter import *
    from PIL import Image, ImageTk

    Créer une fenêtre Tkinter

    La fenêtre est un objet de la classe Tk. Pour l’exemple qui suit, on lui donne le nom de fen1.

    On créé un objet fenêtre à partir de l’instruction: fen1 = Tk()

    La dernière ligne permet d’afficher la fenêtre à l’écran. Il faudra auparavent ajouter les objets esclaves.

    if __name__ == '__main__':
        fen1 = Tk()
        # ajouter des objets esclaves à la fenêtre
        # puis finir par:
        fen1.mainloop()

    Objets esclaves

    Ces objets sont à ajouter à fen1, une fois celle-ci créé. Donc après fen1 = Tk()

    Canvas

    C’est la partie de la fenêtre dans laquelle on dessine.

    On commence par créer un objet canvas appelé ici can1: c’est l’instruction can1 = Canvas(fen1, ...arguments...). Les arguments vont permettre de choisir par exemple la largeur en pixel du canvas (width) et sa hauteur (height).

    Puis on positionne can1 avec la méthode pack. Sans cette deuxième ligne can1.pack(side=LEFT, padx=5, pady=5), l’objet esclave est créé mais non attaché à la fenêtre (et donc n’apparait pas).

    if __name__ == '__main__':
        ...
        can1 = Canvas(fen1, bg='dark grey', height=400, width=600)
        can1.pack(side=LEFT, padx=5, pady=5)

    des boutons

    Les boutons vont permettre d’appeler des fonctions lorsque l’on clique dessus.

    Par exemple, le bouton 1, bou1 va appeler une fonction de fen1 héritée lors de sa création à partir de la classe Tk. C’est la fonction quit.

    Et le bouton 1, bou2, va appeler la fonction replay qu’il vous faudra programmer. Que voudrez vous qu’il se passe lorsque l’on clique sur ce bouton…? Effacer le canvas, dessiner une grille,…?

    if __name__ == '__main__':
        ...
        # un bouton
        bou1 = Button(fen1, text='Quitter', command=fen1.quit)
        bou1.pack(side=BOTTOM)
        # un autre bouton
        bou2 = Button(fen1, text='(Re)Jouer', command=replay)
        bou2.pack()

    Remarques: en python, il est possible de mettre en argument d’une fonction une autre fonction. C’est ce qui est réalisé ici, avec les fonctions fen1.quit et replay. On appelle ces fonctions sans mettre de parenthèses: on écrit replay et non replay().

    Etiquette: Label

    On peut écrire un texte dont le contenu sera evolutif, comme un panneau d’affichage dont le contenu est variable:

    if __name__ == '__main__':
        ...
        text_affichage = StringVar()
        txt1 = Label(fen1, textvariable=text_affichage, justify=LEFT, font='TkFixedFont')
        txt1.pack()
        text_affichage.set("Cliquer sur \n le bouton \n pour demarrer")

    Plus tard, dans le programme, il suffira d’écrire text_affichage.set("nouveau \n message") pour afficher un nouveau message, à la même place.

    textBox

    Equivalent de input mais pour l’environnement tkinter. Il faudra definir le champs de saisie (objet Text), et le bouton pour validation:

    if __name__ == '__main__':
        ...
        # Une textBox
        textBox = Text(fen1, height=1, width=15)
        textBox.pack()
        # Bouton pour valider la saisie
        bou3 = Button(fen1, text='Valider', command=readtext)
        bou3.pack()

    Il faudra alors programmer la fonction de rappel readtext:

    def readtext():
        result=textBox.get("1.0","end")
        text_affichage.set(result)

    Image dans le canvas

    Plusieurs étapes sont necessaires pour:

    • ouvrir une image du dossier
    • redimensionner l’image
    • créer un objet image à partir du module tkinter: image_bomb
    • dessiner l’image dans le canvas à la position 100 * 100
    if __name__ == '__main__':
        ...
        # une image de dimension 50 pixels * 50 pixels 
        image = Image.open("images/bomb.png")
        image = image.resize((50, 50), Image.ANTIALIAS)
        image_bomb = ImageTk.PhotoImage(image)
        bomb = can1.create_image(100, 100, anchor="nw", image=image_bomb)

    Plus loin dans le programme, il suffira d’écrire bomb = can1.create_image(200, 200, anchor="nw", image=image_bomb) pour dessiner l’image à la position 200 * 200 par exemple.

    Dessiner dans le canvas

    Dessiner un carré
    On utilise la méthode: .create_rectangle(X0, Y0, X1, Y1)
    X, Y sont les coordonnées du coin supérieur gauche du carré.
    Il peut y avoir des paramètres optionnels.

    Exemple: pour dessiner un carré de côté r dans le canvas:

    can1.create_rectangle(X, Y, X + r, Y + r, outline='black', fill=couleur)

    Dessiner un cercle:
    On utilise la méthode: .create_oval(x-r, y-r, x+r, y+r)

    Dessiner une ligne:
    On utilise la méthode: .create_line(x0, y0, x1, y1)

    Exemple: le jeu du pendu

    Exemple: le jeu du pendu

    Evenements

    Gestion d’un clic de souris dans le canvas

    Pour ajouter un écouteur de clic dans le canvas, il faut ajouter dans le bloc principal (après avoir créé l’objet fen1 et can1:

    if __name__ == '__main__':
      ...
      can1.bind('<Button-1>', clic)
      ...

    Ici, la fonction qui sera appelée lorsque l’on clique avec le bouton gauche de la souris dans le canvas est la fonctionclic qu’il faudra programmer.

    Lors de l’appel de cette fonction, il ne faut pas ajouter d’agument ni de parenthèses.

    On peut par exemple vouloir afficher les coordonnées de la souris lors du clic:

    def clic(event):
        """ Gestion de l'événement clic gauche sur la zone graphique """
        # MODE JEU
        # (X,Y) : position du pointeur de la souris
        X = event.x
        Y = event.y
        text_affichage.set("{}, {}".format(X,Y))

    Remarque: la fonction de rappel clic a un paramètre obligatoire, event lors de sa création.

    Cliquer sur une image

    Pour ajouter un ecouteur de clic sur une image, on procède d’une manière presque identique:

    Après avoir placé l’image dans le canvas, on lui associe une fonction de rappel:

    if __name__ == '__main__':
        ...
        # Pierre
        image = Image.open("images/pierre.png")
        image = image.resize((image.size[0] // 2, image.size[1] // 2), Image.ANTIALIAS)
        photo_pierre = ImageTk.PhotoImage(image)
    
        pierre = can1.create_image(0, 0, anchor="nw", image=photo_pierre)
        can1.tag_bind(pierre, "<ButtonRelease>", play_pierre)
        ...

    Ici, la fonction de rappel sera play_pierre. Le clic sur cette image pourra peut-être afficher un message:

    def play_pierre(event):
        texte = "Joueur joue: \n PIERRE"
        text_affichage.set(texte)

    Gestion des touches du clavier

    De nombreux jeux utilisent les touches du clavier pour commandes. L’écoute du clavier se fait avec fen1.bind("<Key>", nom_de_la_fonction_de_rappel):

    if __name__ == '__main__':
        ...
        fen1.bind("<Key>", clavier)
        ...

    On peut alors programmer une fonction de rappel clavier qui affiche le caractère appuyé:

    def clavier(event):
        t = event.keysym
        text_affichage.set("Touche pressée : {}".format(t))

    Exemples

    Exemple 1: dessiner une grille

    Souvent, le jeu utilise un quadrillage sur tout le canvas.

    On peut programmer une fonction carre qui dessine un carré de côté r, puis appeler cette fonction lors du dessin initial, dans une autre fonction.

    def carre(r, X, Y, couleur):
        """
        dessine le contour d'une case colorée
        """
        can1.create_rectangle(X, Y, X + r, Y + r, outline='black', fill=couleur)

    La fonction qui dessine le fond quadrillé utilisera 2 boucles bornées imbriquées. Si chaque carré a pour côté H: L’idée est d’utiliser les dimensions du canvas pour avoir un nombre entier de carrés de côtés H:

        for j in range(int(can1['height']) // H):
            for i in range(int(can1['width']) // H):
                carre(H,...

    famille de jeux: le morpion, puissance 4, echecs, demineur

    Exemple 2: dessiner selon le texte saisi

    On pourrait dessiner avec un ordre: la fonction de rappel readtext pourrait évaluer les caractères saisis, et, s’il s’agit de:

    • tete: dessiner la tête du personnage
    • corps: dessiner le corps
    • bras: dessiner ses bras
    • jambes: dessiner ses jambes

    famille de jeux: jeu de devinette, jeu de rôle, jeu du pendu

    Exemple 3: ajouter une image lors d’un clic

    Avec la fonction clic, on peut créer une nouvelle image dans le canvas avec:

    def clic(event):
        """ Gestion de l'événement clic gauche sur la zone graphique """
        # MODE JEU
        # (X,Y) : position du pointeur de la souris
        X = event.x
        Y = event.y
        bomb = can1.create_image(X, Y, anchor="nw", image=image_bomb)

    Le mieux, serait d’aligner l’image sur la grille de fond lorsque l’on clique dans l’une des cases du quadrillage.

    Si les carrés ont pour côté H: Il faudra que X et Y soient multiples de H.

    Utiliser la division entière:

    X = (X // H) * H

    et Y = (Y // H) * H

    famille de jeux: demineur, puissance 4, morpion

    Tkinter demineur

    Canvas et Tkinter

    Principe

    Le module Tkinter permet de dessiner dans la fenêtre en ajoutant un objet Canvas. Les fonctions de dessin permettent de tracer des figures, afficher une image… Les éléments sont repérés par leur coordonnées (x,y). Le point (0,0) se situant en haut à gauche.

    On verra dans une autre seance que le canvas peut aussi relever la position de la souris lors d’un clic. Et que l’on peut ainsi programmer des jeux.

    But de la séance

    Vous allez poursuivre votre appentissage des algorithmes sur les listes, en positionnant les images bombes sur une grille du canvas.

    Contenu du projet

    Le projet suivant (fichier zip)

    • canvas.py: le fichier principal qui contient les fonctions de dessin. Ce sera ce fichier qui faudra executer pour afficher la fenêtre graphique.

    • utils.py: C’est le fichier qui contient les fonctions de calcul des positions des bombes. Au depart, ce fichier ne contient que la fonction position_bombes. Cette fonction génère une liste de listes adaptée à la grille $L*h$:

      • chaque sous-liste positionne les bombes d’une même ligne (L cases)
      • il y a autant de sous-listes que le nombre de cases en hauteur (h lignes)
      • une valeur 1 dans la sous-liste positionne une bombe.
      • une valeur 0 signifie case vide

    Vous devrez modifier le contenu de la fonction position_bombes pour réaliser les grilles proposées.

    Pour executer le programme, ouvrir canvas.py avec un IDE python, et Executer le module (F5: Run module)

    Que génère la fonction position_bombes?

    Pour tester la fonction, vous pouvez executer le module utils.py, puis appeler dans le shell la fonction avec des arguments choisis.

    Ouvrir le ficher utils.py avec votre IDE python. Puis Executer le module. Dans le shell, faire:

    >>> help(position_bombes)
    # retourne les informations sur la fonction
    # Pour sortir de la fenêtre de l’aide, appuyer sur la touche q
    >>> position_bombes(6,6)
    # retourne la liste Bombes générée par la fonction

    Les grilles à réaliser

    Il vous faudra modifier la fonction position_bombes pour realiser chacune de ces grilles.

    def position_bombes(L,h):
        """
        grille pleine
        :param L: nombre de cases horizontales
        :param h: nombre de cases verticales
        :return Bombes: matrice de dimension L*h
        retourne une liste de binaires avec la position des bombes
        exemple:
        --------
        >>> position_bombes(
    
        """
    grille 1

    grille 1

    def position_bombes(L,h):
        """
        ligne horizontale de bombes
        :param L: nombre de cases horizontales
        :param h: nombre de cases verticales
        :return Bombes: matrice de dimension L*h
        retourne une liste de binaires avec la position des bombes
        exemple:
        --------
        >>> position_bombes(
        
        """
    grille 2

    grille 2

    def position_bombes(L,h):
        """
        Premiere ligne verticale
        :param L: nombre de cases horizontales
        :param h: nombre de cases verticales
        :return Bombes: matrice de dimension L*h
        retourne une liste de binaires avec la position des bombes
        exemple:
        --------
        >>> position_bombes(
        
        """
    grille 3

    grille 3

    def position_bombes(L,h):
        """
        diagonale vers le bas a droite
        :param L: nombre de cases horizontales
        :param h: nombre de cases verticales
        :return Bombes: matrice de dimension L*h
        retourne une liste de binaires avec la position des bombes
        exemple:
        --------
        >>> position_bombes(
        
        """
    grille 4

    grille 4

    def position_bombes(L,h):
        """
        position aléatoire de bombes
        :param L: nombre de cases horizontales
        :param h: nombre de cases verticales
        :return Bombes: matrice de dimension L*h
        retourne une liste de binaires avec la position des bombes
        exemple:
        --------
        >>> position_bombes(
        
        """

    grille 5

    grille 5

    Aide: on pourra utiliser la fonction randint(0,1) du module random

    Spécifier la fonction et programmer des tests

    Prototypage

    Dans chaque cas, compléter le prototypage de la fonction pour:

    • spécifier ce qu’elle doit faire (début du prototypage)
    • préciser ce qui est attendu lorsqu’elle est executée avec certaines valeurs choisies pour arguments (fin du prototypage). Ajouter par exemple (compléter):
    >>> position_bombes(...,...)
    [[...,...,...,...],[...,...,...,...]]

    Programmer un test automatique

    Le doctest est un module qui recherche dans le prototypage de la fonction ce qui pourrait s’apparenter à des tests sur la fonction.

    Comme par exemple:

    >>> position_bombes(2,2)
    [[0, 0], [0, 0]]

    Pour réaliser des tests sur la fonction, on ajoutera alors à la suite du script les lignes suivantes:

    if __name__ == "__main__":
        import doctest
        doctest.testmod()

    Et pour réaliser les tests automatiques, il faudra executer le fichier utils.py: Depuis le shell, faire:

    >>> python utils.py

    Remarque: la sortie de la fonction doit suivre le guide de style python, sinon des erreurs peuvent être générées (absence d’espaces,…). Il s’agit de PEP8 sur https://python.org.

    IHM python Cours

    Interface Homme-Machine en Python avec Pygame

    Durée : 1 heure
    Objectif : Comprendre les bases des interfaces graphiques et du paradigme événementiel pour préparer la création d’un jeu type escape game/RPG


    Introduction aux Interfaces Homme-Machine (lecture 10 min)

    Qu’est-ce qu’une Interface Homme-Machine (IHM) ?

    Une Interface Homme-Machine est le moyen de communication entre un utilisateur et un programme informatique. C’est tout ce qui permet à l’utilisateur d’interagir avec le logiciel et de recevoir des informations en retour.

    Exemples du quotidien :

    • Les applications sur smartphone (boutons, gestes tactiles)
    • Les sites web (menus, formulaires, boutons)
    • Les jeux vidéo (interfaces de jeu, menus)
    • Les logiciels de bureautique (barres d’outils, fenêtres)

    Les deux grands types d’interfaces

    CLI - Command Line Interface (Interface en ligne de commande)

    • L’utilisateur tape des commandes textuelles
    • Le programme répond avec du texte
    • Exemple : le terminal, les programmes Python simples avec input()
    # Exemple CLI classique
    nom = input("Quel est votre nom ? ")
    print(f"Bonjour {nom} !")

    Avantages : Simple à programmer, précis, rapide pour les utilisateurs expérimentés
    Inconvénients : Peu intuitif, courbe d’apprentissage élevée

    GUI - Graphical User Interface (Interface graphique)

    • L’utilisateur interagit avec des éléments visuels (boutons, images, icônes)
    • Le programme répond visuellement
    • Exemple : les jeux vidéo, les applications modernes

    Avantages : Intuitif, accessible, visuellement attractif
    Inconvénients : Plus complexe à programmer


    Le paradigme événementiel (lecture 15 min)

    Du séquentiel à l’événementiel

    Programmation séquentielle (ce que vous connaissez)

    Le programme s’exécute ligne par ligne, de haut en bas, de manière prévisible.

    # Exemple séquentiel
    print("Début du programme")
    x = 5
    y = 10
    resultat = x + y
    print(f"Résultat : {resultat}")
    print("Fin du programme")

    Le programme se termine après la dernière ligne.

    Programmation événementielle (nouveau paradigme)

    Le programme reste en attente et réagit aux actions de l’utilisateur.

    # Pseudo-code événementiel
    while programme_actif:
        evenement = attendre_action_utilisateur()
        
        if evenement == "clic_souris":
            traiter_clic()
        elif evenement == "touche_clavier":
            traiter_touche()
        elif evenement == "fermeture_fenetre":
            programme_actif = False

    Le programme ne se termine que lorsque l’utilisateur décide de le fermer.

    Les événements

    Un événement est une action effectuée par l’utilisateur (ou par le système) que le programme peut détecter et traiter.

    Types d’événements courants :

    • MOUSEBUTTONDOWN : L’utilisateur clique avec la souris
    • MOUSEBUTTONUP : L’utilisateur relâche le bouton de la souris
    • MOUSEMOTION : L’utilisateur déplace la souris
    • KEYDOWN : L’utilisateur appuie sur une touche du clavier
    • KEYUP : L’utilisateur relâche une touche
    • QUIT : L’utilisateur ferme la fenêtre

    Schéma de la boucle événementielle

    ┌─────────────────────────────────┐
    │   Initialisation du programme   │
    └────────────┬────────────────────┘
                 │
                 ▼
    ┌────────────────────────────────┐
    │    BOUCLE PRINCIPALE (infinie) │◄───┐
    ├────────────────────────────────┤    │
    │  1. Récupérer les événements   │    │
    │  2. Traiter chaque événement   │    │
    │  3. Mettre à jour la logique   │    │
    │  4. Dessiner à l'écran         │    │
    │  5. Rafraîchir l'affichage     │────┘
    └────────────┬───────────────────┘
                 │
                 ▼ (si événement QUIT)
    ┌────────────────────────────────┐
    │      Fermeture propre          │
    └────────────────────────────────┘

    Introduction à Pygame (lecture 20 min)

    Pourquoi Pygame ?

    Pygame est une bibliothèque Python spécialement conçue pour créer des jeux 2D et des applications graphiques interactives.

    Avantages :

    • Facile à apprendre pour les débutants
    • Gestion simplifiée des graphismes, sons et événements
    • Grande communauté et nombreux tutoriels
    • Idéal pour des jeux 2D, prototypes et projets éducatifs

    Installation :

    pip install pygame

    Structure minimale d’un programme Pygame

    Voici le squelette de base que vous utiliserez pour tous vos projets Pygame :

    import pygame
    
    # ============================================
    # INITIALISATION
    # ============================================
    pygame.init()
    
    # Création de la fenêtre
    LARGEUR = 600
    HAUTEUR = 600
    screen = pygame.display.set_mode((LARGEUR, HAUTEUR))
    pygame.display.set_caption("Mon premier programme Pygame")
    
    # Horloge pour contrôler les FPS (images par seconde)
    clock = pygame.time.Clock()
    
    # Variable de contrôle de la boucle
    running = True
    
    # ============================================
    # BOUCLE PRINCIPALE
    # ============================================
    while running:
        # 1. GESTION DES ÉVÉNEMENTS
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
        
        # 2. LOGIQUE DU JEU: 
        # (mise à jour des positions, calculs, etc.)
        
        # 3. AFFICHAGE: 
        screen.fill((0, 0, 0))  # Efface l'écran avec du noir
        
        # Dessiner vos éléments ici
        
        pygame.display.flip()  # Met à jour l'affichage
        
        # 4. CONTRÔLE DU FRAMERATE
        clock.tick(60)  # 60 images par seconde
    
    # ============================================
    # FERMETURE PROPRE
    # ============================================
    pygame.quit()

    Explication détaillée des éléments clés

    Initialisation de Pygame

    pygame.init()

    Cette ligne initialise tous les modules de Pygame. Elle doit toujours être appelée au début.

    Création de la fenêtre

    screen = pygame.display.set_mode((LARGEUR, HAUTEUR))

    Crée une fenêtre de dimensions LARGEUR × HAUTEUR pixels. L’objet screen représente la surface d’affichage principale.

    exemple: pygame.display.set_mode((600, 600))

    exemple: pygame.display.set_mode((600, 600))

    L’horloge

    clock = pygame.time.Clock()
    # ... plus tard dans la boucle
    clock.tick(60)

    L’horloge contrôle la vitesse du jeu. clock.tick(60) limite le programme à 60 images par seconde (FPS), rendant le jeu fluide et cohérent sur différentes machines.

    La boucle de jeu

    while running:

    C’est le cœur du programme. Tant que running est True, le programme continue. Cette boucle s’exécute environ 60 fois par seconde.

    Gestion des événements

    import pygame
    
    (...)
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    pygame.event.get() récupère tous les événements qui se sont produits depuis la dernière itération. On parcourt cette liste et on réagit selon le type d’événement.

    D’autres evenements utiles:

    # retourne True si le bouton souris est appuyé
    event.type == pygame.MOUSEBUTTONDOWN
    # True si le bouton est relaché
    event.type == pygame.MOUSEBUTTONUP

    Remplissage de l’écran

    screen.fill((0, 0, 0))

    Efface l’écran en le remplissant d’une couleur. Les couleurs en Pygame sont des tuples RGB : (Rouge, Vert, Bleu) avec des valeurs de 0 à 255.

    Exemples :

    • (0, 0, 0) = noir
    • (255, 255, 255) = blanc
    • (255, 0, 0) = rouge
    • (0, 255, 0) = vert
    • (0, 0, 255) = bleu

    Rafraîchissement de l’affichage

    pygame.display.flip()

    Met à jour tout l’écran avec ce qui a été dessiné. Sans cette ligne, rien ne s’affichera !

    Exemple complet n°1: Fenêtre avec changement de couleur au clic

    import pygame
    import random
    
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption("Changer la couleur au clic")
    clock = pygame.time.Clock()
    
    # Couleur de fond initiale
    couleur_fond = (50, 50, 100)
    running = True
    
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            # Détecter un clic de souris
            if event.type == pygame.MOUSEBUTTONDOWN:
                # Changer la couleur aléatoirement
                couleur_fond = (random.randint(0, 255),
                               random.randint(0, 255),
                               random.randint(0, 255))
        
        # Remplir l'écran avec la couleur actuelle
        screen.fill(couleur_fond)
        
        pygame.display.flip()
        clock.tick(60)
    
    pygame.quit()

    Exercice mental : Que se passe-t-il si vous cliquez plusieurs fois?


    Éléments pour votre projet (lecture 10 min)

    Pour créer votre escape game/RPG, vous aurez besoin de maîtriser ces éléments :

    Afficher une image de fond

    # Chargement d'une image
    image_fond = pygame.image.load("fond_salle.png")
    
    # Dans la boucle, affichage de l'image
    screen.blit(image_fond, (0, 0))  # (0, 0) = position en haut à gauche

    Note importante : Le système de coordonnées dans Pygame :

    (0, 0) ──────► X (largeur)
      │
      │
      │
      ▼
      Y (hauteur)

    Le point (0, 0) est en haut à gauche de l’écran !

    Afficher une image à une certaine position

    • placer une figure rectangle

    La fonction pygame.draw.rect(screen, color, (x, y, width, height)) dessine un rectangle. (x, y, width, height) est un tuple Python.

    x et y sont les coordonnées du coin supérieur gauche. width et height sont la largeur et la hauteur du rectangle:

    RED = (255,0,0)
    # Dessiner
    pygame.draw.rect(screen, RED, (170, 140, 60, 120))

    Exemple complet n°2

    import pygame
     
    RED = (255, 0, 0)
    pygame.init()
    h,w = 400,400
    screen = pygame.display.set_mode((w, h))
    stop = False
    
    while not stop:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                stop = True
    
        pygame.draw.rect(screen, RED, (170, 140, 60, 120))
        pygame.display.flip()
     
    pygame.quit()
    • placer une image rectangle (porte)

    Pour cet exemple, télécharger les images:

    # Chargement image
    door = pygame.image.load("door1.png")
    # Dessiner
    screen.blit(door, (170, 140))

    Exemple complet n°3

    import pygame
    
    pygame.init()
    h,w = 400,400
    screen = pygame.display.set_mode((w, h))
    # Chargement image
    door = pygame.image.load("door1.png")
    # Dessiner
    screen.blit(door, (170, 140))
    stop = False
    
    while not stop:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                stop = True
    
        pygame.display.flip()
     
    pygame.quit()
    quit()

    Détecter un clic sur une zone précise

    cliquer:

    # Dans la boucle d'événements
    if event.type == pygame.MOUSEBUTTONDOWN:
        x, y = event.pos  # Position du clic
        
        # Vérifier si le clic est dans une zone rectangulaire
        # Zone de l'objet : x entre 100 et 200, y entre 150 et 250
        if 100 <= x <= 200 and 150 <= y <= 250:
            print("Vous avez cliqué sur l'objet !")

    relacher:

    # Dans la boucle d'événements
    if event.type == pygame.MOUSEBUTTONUP:
        x, y = event.pos  # Position du clic
        
        # Vérifier si le clic est dans une zone rectangulaire
        # Zone de l'objet : x entre 100 et 200, y entre 150 et 250
        if 100 <= x <= 200 and 150 <= y <= 250:
            print("Vous avez relaché le bouton !")

    Exemple complet n°4

    import pygame
     
    RED = (255, 0, 0)
    BLUE =(0,0,255)
    pygame.init()
    h,w = 400,400
    screen = pygame.display.set_mode((w, h))
    pygame.draw.rect(screen, RED, (170, 140, 60, 120))
    stop = False
    
    while not stop:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                stop = True
            if event.type == pygame.MOUSEBUTTONDOWN:
                x, y = event.pos
                if 170 <= x <= 230 and 140 <= y <= 260:
                    print("Vous avez cliqué sur l'objet !")
            if event.type == pygame.MOUSEBUTTONUP:
                x, y = event.pos
                if 170 <= x <= 230 and 140 <= y <= 260:
                    print("Vous avez relaché le bouton !")      
        pygame.display.flip()
     
    pygame.quit()

    Exercice 1: Créer un programme complet qui permet de changer la couleur de la porte lorsque l’on clique sur celle-ci (et que l’on maintient appuyé), mais qui remet la première couleur lorsque l’on relâche le bouton:

    Exercice 2: Créer un programme qui permet de changer la couleur de la porte lorsque l’on clique sur celle-ci. Il faudra à nouveau cliquer sur la porte pour retrouver la couleur d’origine.

    Detecter un clic sur un objet

    Méthode : Utilisez pygame.Rect pour créer un calque rectangle:

    # Définir un rectangle pour l'objet
    objet_rect = pygame.Rect(100, 150, 100, 100)  # x, y, largeur, hauteur
    
    # Dans la boucle d'événements
    if event.type == pygame.MOUSEBUTTONDOWN:
        if objet_rect.collidepoint(event.pos):
            print("Objet cliqué !")
    • Utiliser ce calque sur une image Il faut appliquer le calque sur l’image, qui aura les mêmes dimensions que celle-ci:
    # charger l'image
    door = pygame.image.load("datas/images/door1.png")
    # creation d'une surface rectangle 
    # que l'on nomme rect
    # de meme dimension que l'image door
    rect = door.get_rect()
    # Position de rect dans la fenetre graphique (centré)
    rect.center = w//2, h//2
    # Dessiner l'objet à la même position que le calque
    screen.blit(door, rect)

    Ce calque est alors cliquable:

    if event.type == pygame.MOUSEBUTTONDOWN:
    	if rect.collidepoint(event.pos):
    		print("l'objet a ete cliqué")

    Exemple complet n°5:

    import pygame
    
    pygame.init()
    door = pygame.image.load("datas/images/door1.png")
    
    h,w = 400,400
    screen = pygame.display.set_mode((w, h))
    rect = door.get_rect()
    rect.center = w//2, h//2
    stop = False
    while not stop:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                stop = True
             
            elif event.type == pygame.MOUSEBUTTONDOWN:
                    if rect.collidepoint(event.pos):
                        print('on tape à la porte')
                
        screen.fill(0) # On efface tout l'écran
        screen.blit(door, rect)
        pygame.display.flip()
     
    pygame.quit()

    Exercice 1: On dispose de 2 images d’une même porte, aux contours différents. Créer un programme complet qui permet de changer l’image de la porte lorsque l’on clique sur celle-ci (et que l’on maintient appuyé), mais qui remet la première image lorsque l’on relâche le bouton:

    Exercice 2: Créer un programme qui permet de changer l’image de la porte lorsque l’on clique sur celle-ci. Il faudra à nouveau cliquer sur la porte pour retrouver l’image d’origine.

    Afficher du texte

    • Première étape: utiliser le module font. On créé un objet pygame.font, pour lequel on choisit une police de caractères (par defaut, laisser None) et une taille pour cette police:
    my_font = pygame.font.SysFont('Comic Sans MS', 30)
    • il faut créer une surface sur laquelle on écrit, à l’aide de la fonction render:
    render(text, antialias, color, background=None) -> Surface

    Exemple:

    couleur = (255, 255, 255)
    texte = "Hello World"
    texte_surface = my_font.render(texte, True, couleur)

    L’anticrénelage ou anti-aliasing, ou lissage des obliques ou encore lissage de police, est une méthode permettant d’éviter le crénelage.

    • Troisième étape: Afficher et positionner la surface avec la fonction blit:
    screen.blit(texte_surface, (0,0))  # Position du texte 
    								   # en haut à gauche

    au final:

    screen.fill(255,255,255)
    font = pygame.font.Font(None, 36)  # None = police par défaut, 36 = taille
    texte = "Bienvenue dans la salle mystérieuse"
    texte_surface = font.render(texte, True, (0,0,0))  # True = antialiasing
    screen.blit(texte_surface, (50, 500))  # Position du texte

    Exemple complet n°6:

    import pygame
    
    pygame.init()
    h,w = 400,400
    screen = pygame.display.set_mode((w, h))
    screen.fill(255,255,255)
    font = pygame.font.Font(None, 36) 
    texte = "Bienvenue dans la salle mystérieuse"
    texte_surface = font.render(texte, True, (0,0,0)) 
    screen.blit(texte_surface, (50, 500)) 
    stop = False
    
    while not stop:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                stop = True
                
        pygame.display.flip()
     
    pygame.quit()

    Remarques:

    • Chaque fois que le texte change, il faudra créer une nouvelle surface à placer sur l’ancienne.
    • Pour changer de ligne, on ne pourra pas utiliser le symbole “\n”. Il faudra créer une nouvelle surface pour chaque ligne, et la positionner de manière correcte.

    Exercice: Ecrire un programme qui affiche les 2 lignes comme ci-dessus.

    Detecter l’appui sur une touche du clavier

    Pour detecter l’appui sur la touche "h" du clavier, on utilisera la séquence d’instruction suivantes:

            if event.type == pygame.KEYDOWN:
                if pygame.key.name(event.key) == "h": 
                    print('HELP')

    (à placer dans la zone de gestion des évènements)


    3. Testez progressivement

    • D’abord : affichez juste la fenêtre et l’image de fond
    • Ensuite : ajoutez la détection de clic sur une zone
    • Puis : ajoutez l’affichage de texte
    • Enfin : ajoutez les boutons et la logique du jeu

    4. Utilisez des commentaires et des constantes

    # Constantes
    LARGEUR = 800
    HAUTEUR = 600
    COULEUR_FOND = (0, 0, 0)
    FPS = 60
    
    # États du jeu
    ETAT_DEBUT = 0
    ETAT_JEU = 1
    ETAT_VICTOIRE = 2

    Structure de base pour votre TP

    import pygame
    
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    clock = pygame.time.Clock()
    
    # Chargement des ressources
    fond = pygame.image.load("salle.png")
    font = pygame.font.Font(None, 28)
    
    # Définition des objets interactifs
    objets = [
        # À compléter
    ]
    
    # Variables de jeu
    message_actuel = "Explorez la salle..."
    inventaire = []
    
    running = True
    while running:
        # Gestion des événements
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            if event.type == pygame.MOUSEBUTTONDOWN:
                # Vérifier les clics sur les objets
                # Vérifier les clics sur les boutons
                pass
        
        # Affichage
        screen.blit(fond, (0, 0))
        
        # Afficher les boutons
        
        # Afficher le message
        texte = font.render(message_actuel, True, (255, 255, 255))
        screen.blit(texte, (50, 550))
        
        pygame.display.flip()
        clock.tick(60)
    
    pygame.quit()
    quit()

    Récapitulatif des concepts clés

    ✅ IHM : Moyen de communication entre l’utilisateur et le programme
    ✅ Paradigme événementiel : Le programme attend et réagit aux actions
    ✅ Boucle de jeu : Cœur du programme, s’exécute en continu
    ✅ Événements : Actions détectables (clics, touches, etc.)
    ✅ Pygame : Bibliothèque pour créer des jeux 2D en Python
    ✅ Structure : Init → Boucle (événements → logique → affichage) → Quit


    Ressources utiles


    Suite

    • Le TP Escape Game: Lien
    • Les dictionnaires python et leur application pour le projet Escape Game: Lien

    dictionnaires pour inventaire

    Les dictionnaires Python pour gérer un escape game

    Durée : 1 heure
    Prérequis : Connaître les listes Python
    Objectif : Découvrir les dictionnaires et comprendre pourquoi ils sont essentiels pour gérer les objets et états d’un jeu


    1. Rappel : Les listes, ce que vous connaissez déjà (10 min)

    Structure des listes

    Une liste est une collection ordonnée d’éléments, accessibles par leur position (index).

    # Liste de prénoms
    prenoms = ["Alice", "Bob", "Charlie"]
    
    # Accès par index (position)
    print(prenoms[0])  # Affiche : Alice
    print(prenoms[1])  # Affiche : Bob
    print(prenoms[2])  # Affiche : Charlie

    Utiliser les listes pour un jeu : première tentative

    Imaginons qu’on veuille gérer un objet de notre escape game avec une liste :

    # Un objet "clé" représenté par une liste
    cle = ["clé dorée", 150, 200, False, "Une petite clé qui brille"]
    #      [0] nom      [1] x  [2] y  [3] ramassée  [4] description
    
    # Accès aux informations
    print(cle[0])  # nom
    print(cle[1])  # position x
    print(cle[3])  # est-elle ramassée ?

    Le problème avec les listes

    ❌ Difficile à lire : Que représente cle[3] ? Il faut se souvenir de l’ordre
    ❌ Difficile à maintenir : Si on ajoute une propriété, tous les indices changent
    ❌ Erreurs faciles : Confondre l’ordre des éléments
    ❌ Code cryptique : if objet[3] == False: ne dit rien sur ce qu’on vérifie

    Exercice mental : Si on a 10 objets différents avec des propriétés différentes, comment s’en sortir avec des listes ?


    2. Introduction aux dictionnaires (15 min)

    Qu’est-ce qu’un dictionnaire ?

    Un dictionnaire est une collection d’éléments accessibles par leur nom (clé) plutôt que par leur position.

    Analogie : Un dictionnaire papier

    • Dans un dictionnaire français, on cherche un mot (la clé) pour obtenir sa définition (la valeur)
    • On ne dit pas “donne-moi le 1547ème mot”, mais “donne-moi la définition de ’escape'”

    Syntaxe de base

    # Création d'un dictionnaire
    personne = {
        "nom": "Alice",
        "age": 25,
        "ville": "Paris"
    }
    
    # Accès par clé (beaucoup plus clair !)
    print(personne["nom"])    # Affiche : Alice
    print(personne["age"])    # Affiche : 25
    print(personne["ville"])  # Affiche : Paris

    Structure :

    dictionnaire = {
        "clé1": valeur1,
        "clé2": valeur2,
        "clé3": valeur3
    }
    • Les clés sont généralement des chaînes de caractères (entre guillemets)
    • Les valeurs peuvent être de n’importe quel type : nombres, chaînes, booléens, listes, ou même d’autres dictionnaires !

    Comparaison liste vs dictionnaire

    # AVEC UNE LISTE (difficile à lire)
    cle_liste = ["clé dorée", 150, 200, False, "Une petite clé qui brille"]
    nom = cle_liste[0]
    est_ramassee = cle_liste[3]
    
    # AVEC UN DICTIONNAIRE (clair et explicite)
    cle_dict = {
        "nom": "clé dorée",
        "x": 150,
        "y": 200,
        "ramassee": False,
        "description": "Une petite clé qui brille"
    }
    nom = cle_dict["nom"]
    est_ramassee = cle_dict["ramassee"]

    Quelle version préférez-vous lire ?

    Opérations de base sur les dictionnaires

    Accéder à une valeur

    joueur = {"nom": "Alice", "vie": 100, "niveau": 1}
    
    print(joueur["nom"])      # Alice
    print(joueur["vie"])      # 100

    Modifier une valeur

    joueur["vie"] = 80        # La vie passe à 80
    joueur["niveau"] = 2      # Le niveau passe à 2

    Ajouter une nouvelle paire clé-valeur

    joueur["score"] = 1500    # Ajoute une nouvelle clé "score"

    Vérifier si une clé existe

    if "vie" in joueur:
        print("Le joueur a des points de vie")
    
    if "magie" in joueur:
        print("Le joueur a de la magie")
    else:
        print("Pas de magie")  # Ceci sera affiché

    Supprimer une paire clé-valeur

    del joueur["score"]       # Supprime la clé "score"

    Obtenir une valeur avec une valeur par défaut

    # Si la clé n'existe pas, retourne une valeur par défaut
    magie = joueur.get("magie", 0)  # Retourne 0 si "magie" n'existe pas

    3. Les dictionnaires pour l’escape game (20 min)

    3.1. Représenter un objet du jeu

    Au lieu d’utiliser des listes compliquées, utilisons des dictionnaires pour chaque objet :

    porte = {
        "nom": "porte",
        "x": 300,
        "y": 200,
        "largeur": 150,
        "hauteur": 300,
        "verrouille": True,
        "description": "Une lourde porte en bois",
        "message_verrouille": "La porte est fermée à clé",
        "message_ouvert": "Vous ouvrez la porte et sortez. Victoire !"
    }
    
    cle = {
        "nom": "clé",
        "x": 100,
        "y": 400,
        "largeur": 30,
        "hauteur": 15,
        "ramassee": False,
        "description": "Une petite clé dorée",
        "dans_inventaire": False
    }
    
    tableau = {
        "nom": "tableau",
        "x": 450,
        "y": 150,
        "largeur": 200,
        "hauteur": 150,
        "examine": False,
        "description": "Un tableau représentant un paysage",
        "description_detaillee": "En examinant de plus près, vous voyez un code : 1234"
    }

    Avantages : ✅ Chaque objet peut avoir des propriétés différentes
    ✅ Le code est auto-documenté (on comprend ce que fait objet["verrouille"])
    ✅ Facile d’ajouter de nouvelles propriétés
    ✅ Pas de confusion sur l’ordre des éléments

    3.2. Gérer une collection d’objets

    On peut mettre tous les objets dans une liste :

    objets = [
        {
            "nom": "porte",
            "x": 300,
            "y": 200,
            "largeur": 150,
            "hauteur": 300,
            "verrouille": True,
            "description": "Une lourde porte en bois"
        },
        {
            "nom": "clé",
            "x": 100,
            "y": 400,
            "largeur": 30,
            "hauteur": 15,
            "ramassee": False,
            "description": "Une petite clé dorée"
        },
        {
            "nom": "coffre",
            "x": 550,
            "y": 350,
            "largeur": 100,
            "hauteur": 80,
            "ouvert": False,
            "description": "Un vieux coffre poussiéreux"
        }
    ]

    3.3. Parcourir et utiliser les objets

    # Afficher tous les objets
    for objet in objets:
        print(f"Objet : {objet['nom']} à la position ({objet['x']}, {objet['y']})")
    
    # Trouver un objet par son nom
    def trouver_objet(nom_objet):
        for objet in objets:
            if objet["nom"] == nom_objet:
                return objet
        return None
    
    # Utilisation
    porte = trouver_objet("porte")
    if porte["verrouille"]:
        print("La porte est verrouillée")

    3.4. Détecter un clic sur un objet

    def verifier_clic_objet(x_souris, y_souris):
        """Vérifie si le clic touche un objet"""
        for objet in objets:
            # Vérifier si le clic est dans les limites de l'objet
            if (objet["x"] <= x_souris <= objet["x"] + objet["largeur"] and
                objet["y"] <= y_souris <= objet["y"] + objet["hauteur"]):
                return objet
        return None
    
    # Dans la boucle d'événements
    if event.type == pygame.MOUSEBUTTONDOWN:
        x, y = event.pos
        objet_clique = verifier_clic_objet(x, y)
        
        if objet_clique:
            print(f"Vous avez cliqué sur : {objet_clique['nom']}")
            print(objet_clique["description"])

    3.5. Gérer l’inventaire

    # L'inventaire est une liste de dictionnaires
    inventaire = []
    
    def ramasser_objet(objet):
        """Ajoute un objet à l'inventaire"""
        if not objet.get("ramassee", False):
            objet["ramassee"] = True
            inventaire.append(objet)
            return f"Vous ramassez : {objet['nom']}"
        else:
            return "Cet objet a déjà été ramassé"
    
    def afficher_inventaire():
        """Affiche le contenu de l'inventaire"""
        if len(inventaire) == 0:
            print("Votre inventaire est vide")
        else:
            print("Inventaire :")
            for objet in inventaire:
                print(f"  - {objet['nom']}")
    
    def objet_dans_inventaire(nom_objet):
        """Vérifie si un objet est dans l'inventaire"""
        for objet in inventaire:
            if objet["nom"] == nom_objet:
                return True
        return False

    3.6. Gérer les interactions entre objets

    def utiliser_cle_sur_porte():
        """Tente d'ouvrir la porte avec la clé"""
        porte = trouver_objet("porte")
        
        if objet_dans_inventaire("clé"):
            if porte["verrouille"]:
                porte["verrouille"] = False
                return "Vous utilisez la clé. La porte s'ouvre !"
            else:
                return "La porte est déjà ouverte"
        else:
            return "Vous n'avez pas de clé"
    
    def examiner_objet(objet):
        """Examine un objet en détail"""
        if objet["nom"] == "tableau" and not objet.get("examine", False):
            objet["examine"] = True
            return objet.get("description_detaillee", objet["description"])
        else:
            return objet["description"]

    4. Exemple complet : Mini escape game avec dictionnaires (10 min)

    Voici un exemple fonctionnel simplifié qui montre comment tout s’assemble :

    import pygame
    
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    clock = pygame.time.Clock()
    font = pygame.font.Font(None, 28)
    
    # Définition des objets avec des dictionnaires
    objets = [
        {
            "nom": "clé",
            "x": 100,
            "y": 400,
            "largeur": 40,
            "hauteur": 20,
            "couleur": (255, 215, 0),  # Doré
            "ramassee": False,
            "description": "Une clé dorée"
        },
        {
            "nom": "porte",
            "x": 650,
            "y": 200,
            "largeur": 100,
            "hauteur": 200,
            "couleur": (139, 69, 19),  # Marron
            "verrouille": True,
            "description": "Une porte en bois"
        }
    ]
    
    # État du jeu
    inventaire = []
    message = "Trouvez la clé et ouvrez la porte !"
    victoire = False
    
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            if event.type == pygame.MOUSEBUTTONDOWN and not victoire:
                x_souris, y_souris = event.pos
                
                # Vérifier les clics sur les objets
                for objet in objets:
                    if (objet["x"] <= x_souris <= objet["x"] + objet["largeur"] and
                        objet["y"] <= y_souris <= objet["y"] + objet["hauteur"]):
                        
                        # Clic sur la clé
                        if objet["nom"] == "clé" and not objet["ramassee"]:
                            objet["ramassee"] = True
                            inventaire.append(objet)
                            message = "Vous ramassez la clé !"
                        
                        # Clic sur la porte
                        elif objet["nom"] == "porte":
                            # Vérifier si on a la clé
                            a_la_cle = any(obj["nom"] == "clé" for obj in inventaire)
                            
                            if a_la_cle and objet["verrouille"]:
                                objet["verrouille"] = False
                                message = "Vous ouvrez la porte ! VICTOIRE !"
                                victoire = True
                            elif objet["verrouille"]:
                                message = "La porte est verrouillée. Il faut une clé."
                            else:
                                message = "La porte est déjà ouverte !"
        
        # Affichage
        screen.fill((50, 50, 50))  # Fond gris
        
        # Dessiner les objets
        for objet in objets:
            # Ne pas dessiner la clé si elle est ramassée
            if objet["nom"] == "clé" and objet["ramassee"]:
                continue
            
            pygame.draw.rect(screen, objet["couleur"], 
                            (objet["x"], objet["y"], objet["largeur"], objet["hauteur"]))
        
        # Afficher le message
        texte = font.render(message, True, (255, 255, 255))
        screen.blit(texte, (50, 550))
        
        # Afficher l'inventaire
        inv_text = "Inventaire : " + ", ".join([obj["nom"] for obj in inventaire])
        if len(inventaire) == 0:
            inv_text = "Inventaire : vide"
        inv_surface = font.render(inv_text, True, (200, 200, 200))
        screen.blit(inv_surface, (50, 20))
        
        pygame.display.flip()
        clock.tick(60)
    
    pygame.quit()

    Ce que fait ce programme :

    1. Définit une clé et une porte comme dictionnaires
    2. Permet de cliquer sur la clé pour la ramasser
    3. La clé disparaît et va dans l’inventaire
    4. On peut cliquer sur la porte pour tenter de l’ouvrir
    5. La porte s’ouvre seulement si on a la clé

    5. Dictionnaires avancés pour le jeu (10 min)

    5.1. Dictionnaires imbriqués

    On peut mettre des dictionnaires dans des dictionnaires :

    objet_complexe = {
        "nom": "coffre",
        "position": {
            "x": 100,
            "y": 200
        },
        "dimensions": {
            "largeur": 80,
            "hauteur": 60
        },
        "contenu": {
            "or": 50,
            "gemmes": 3,
            "objet_special": "amulette"
        },
        "ouvert": False
    }
    
    # Accès aux valeurs imbriquées
    print(objet_complexe["position"]["x"])  # 100
    print(objet_complexe["contenu"]["or"])   # 50

    5.2. État global du jeu

    Un dictionnaire peut représenter l’état complet du jeu :

    etat_jeu = {
        "niveau_actuel": 1,
        "temps_ecoule": 0,
        "enigmes_resolues": ["enigme1", "enigme3"],
        "inventaire": [],
        "score": 1500,
        "indices_trouves": {
            "code_coffre": True,
            "message_secret": False
        },
        "pieces_visitees": ["salon", "cuisine"],
        "drapeaux": {
            "porte_ouverte": False,
            "alarme_declenchee": False,
            "a_parle_au_gardien": True
        }
    }
    
    # Vérifications faciles
    if "code_coffre" in etat_jeu["indices_trouves"]:
        print("Vous connaissez le code du coffre")
    
    if etat_jeu["drapeaux"]["a_parle_au_gardien"]:
        print("Le gardien vous a donné un indice")

    5.3. Actions et interactions

    On peut même stocker des fonctions ou des messages dans les dictionnaires :

    objets_interactifs = [
        {
            "nom": "levier",
            "x": 300,
            "y": 250,
            "actif": False,
            "description_initial": "Un levier rouillé",
            "description_active": "Le levier a été activé. Un passage secret s'ouvre.",
            "action": "ouvrir_passage"
        },
        {
            "nom": "livre",
            "x": 150,
            "y": 180,
            "lu": False,
            "description": "Un vieux grimoire",
            "texte": "Les pages révèlent : 'Le code est 4-2-7-9'",
            "action": "donner_indice"
        }
    ]
    
    def interagir_avec_objet(objet):
        """Gère l'interaction avec un objet selon son type d'action"""
        if objet["action"] == "ouvrir_passage":
            objet["actif"] = True
            return objet["description_active"]
        
        elif objet["action"] == "donner_indice":
            if not objet["lu"]:
                objet["lu"] = True
                return objet["texte"]
            else:
                return "Vous avez déjà lu ce livre"
        
        return objet["description"]

    5.4. Système de quêtes

    quetes = [
        {
            "id": "trouver_cle",
            "titre": "Trouver la clé",
            "description": "Cherchez la clé pour ouvrir la porte",
            "terminee": False,
            "objectifs": {
                "cle_trouvee": False
            }
        },
        {
            "id": "resoudre_enigme",
            "titre": "Résoudre l'énigme du tableau",
            "description": "Déchiffrez le message caché dans le tableau",
            "terminee": False,
            "objectifs": {
                "tableau_examine": False,
                "code_trouve": False
            }
        }
    ]
    
    def verifier_quetes():
        """Vérifie si les quêtes sont terminées"""
        for quete in quetes:
            if not quete["terminee"]:
                # Vérifier si tous les objectifs sont remplis
                tous_objectifs = all(quete["objectifs"].values())
                if tous_objectifs:
                    quete["terminee"] = True
                    return f"Quête terminée : {quete['titre']}"
        return None

    6. Comparaison finale et bonnes pratiques (5 min)

    Pourquoi les dictionnaires sont parfaits pour les jeux

    Critère Listes Dictionnaires
    Lisibilité ❌ objet[3] ✅ objet["verrouille"]
    Flexibilité ❌ Ordre fixe ✅ Propriétés variables
    Maintenance ❌ Changer l’ordre casse tout ✅ Ajouter/retirer facilement
    Clarté du code ❌ Besoin de commentaires ✅ Auto-documenté
    Gestion d’objets complexes ❌ Très difficile ✅ Naturel

    Bonnes pratiques avec les dictionnaires

    ✅ Utilisez des noms de clés descriptifs

    # Bien
    joueur = {"points_de_vie": 100, "niveau": 5}
    
    # Moins bien
    joueur = {"pv": 100, "niv": 5}

    ✅ Soyez cohérents dans la structure

    # Tous les objets ont les mêmes clés de base
    objet1 = {"nom": "...", "x": 0, "y": 0, "description": "..."}
    objet2 = {"nom": "...", "x": 0, "y": 0, "description": "..."}

    ✅ Utilisez .get() pour éviter les erreurs

    # Risqué - erreur si la clé n'existe pas
    vie = joueur["vie"]
    
    # Sûr - retourne 100 par défaut
    vie = joueur.get("vie", 100)

    ✅ Documentez la structure de vos dictionnaires

    # Structure d'un objet du jeu :
    # {
    #     "nom": str,           # Nom de l'objet
    #     "x": int,             # Position X
    #     "y": int,             # Position Y
    #     "ramassable": bool,   # Peut-on le ramasser ?
    #     "description": str    # Description affichée
    # }

    Quand utiliser listes vs dictionnaires ?

    Utilisez une liste quand :

    • L’ordre est important
    • Vous avez une série d’éléments similaires et simples
    • Exemple : scores = [100, 95, 87, 82]

    Utilisez un dictionnaire quand :

    • Vous avez des propriétés nommées
    • Vous voulez accéder aux données par leur signification
    • Vous gérez des objets complexes
    • Exemple : joueur = {"nom": "Alice", "score": 100, "niveau": 3}

    Récapitulatif

    🎯 Les dictionnaires permettent d’accéder aux données par nom (clé) plutôt que par position

    🎯 Syntaxe : {"clé": valeur, "clé2": valeur2}

    🎯 Parfaits pour : Représenter des objets de jeu avec de multiples propriétés

    🎯 Avantages : Code lisible, flexible, maintenable, auto-documenté

    🎯 Pour votre escape game :

    • Chaque objet est un dictionnaire
    • L’inventaire est une liste de dictionnaires
    • L’état du jeu est un dictionnaire
    • Les quêtes sont des dictionnaires dans une liste

    Exercices pratiques

    Exercice 1 : Créer vos objets

    Créez 3 dictionnaires représentant des objets pour votre escape game. Chaque objet doit avoir au minimum : nom, position (x, y), dimensions, et une description.

    Exercice 2 : Fonction de recherche

    Écrivez une fonction trouver_objet_par_nom(nom, liste_objets) qui cherche un objet dans une liste de dictionnaires et le retourne.

    Exercice 3 : Système d’inventaire

    Créez un système d’inventaire avec les fonctions :

    • ajouter_a_inventaire(objet)
    • retirer_de_inventaire(nom_objet)
    • afficher_inventaire()

    Exercice 4 : Interaction complexe

    Créez une fonction qui vérifie si le joueur peut ouvrir un coffre :

    • Le coffre doit être fermé
    • Le joueur doit avoir la clé dans son inventaire
    • Si oui, le coffre s’ouvre et donne son contenu

    Pour aller plus loin dans votre projet

    Maintenant que vous connaissez les dictionnaires, vous pouvez :

    1. Créer un fichier JSON pour stocker vos objets (JSON est basé sur les dictionnaires)
    2. Gérer plusieurs salles avec un dictionnaire de salles
    3. Créer un système de sauvegarde en enregistrant l’état du jeu
    4. Ajouter des dialogues avec des personnages (PNJ)
    5. Implémenter des énigmes complexes avec plusieurs étapes

    Bon courage pour votre escape game ! 🗝️🚪

    projet Pygame

    Prérequis:

    • Cours sur l’IHM: Lien

    Escape Game en langage python-pygame

    Script initial

    Un Escape Game est un jeu vidéo où il est question de s’échapper d’une pièce dans laquelle un joueur est enfermé. Pour cela, il fallait découvrir des éléments cachés dans le décor afin de trouver une clé qui permettrait au joueur de s’échapper de la pièce.

    Vous allez créer votre jeu à l’aide du module Pygame, en langage python.

    Voici un exemple de ce qu’il est possile de réaliser:

    Les images qui servent à l’exemple sont à télécharger depuis le dossier source.

    Nous partirons du script initial suivant:

    # Script mini pour le jeu
    import pygame
    
    # ============================================
    # INITIALISATION
    # ============================================
    pygame.init()
    
    # ==== Création de la fenêtre 
    # ==== et chargement des ressources: ZONE 1
    LARGEUR = 700
    HAUTEUR = 400
    # --- image fond
    screen = pygame.display.set_mode((LARGEUR, HAUTEUR))
    pygame.display.set_caption("Escape Game")
    fond = pygame.image.load("salon.png").convert()
    screen.blit(fond, (0,0))
    # --- objets interactifs (porte, ...)
    door1 = pygame.image.load("door3.png").convert_alpha()
    rect1 = door1.get_rect()
    rect1.center = LARGEUR//2+10, (HAUTEUR-100)//2
    screen.blit(door1,rect1)
    # --- texte
    font = pygame.font.Font(None, 36)  
    texte = "Bienvenue dans la salle mystérieuse"
    texte_surface = font.render(texte, True, (255,255,255))  
    screen.blit(texte_surface, (0, 300))
    
    # ==== Variables de contrôle de la boucle et du jeu: ZONE 2
    running = True
    
    # ============================================
    # BOUCLE PRINCIPALE
    # ============================================
    while running:
        # GESTION DES ÉVÉNEMENTS: ZONE 3
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if pygame.key.name(event.key) == "h": 
                    print('HELP')
            elif event.type == pygame.MOUSEBUTTONDOWN:
                    if rect1.collidepoint(event.pos):
                        print("Vous essayez d'ouvrir la porte")
        
        # LOGIQUE DU JEU: ZONE 4
        # (mise à jour des variables du jeu, calculs, etc.)
        
        # AFFICHAGE: ZONE 5
        
        
        # Met à jour l'affichage
        pygame.display.flip()  
        
    
    # ============================================
    # FERMETURE PROPRE
    # ============================================
    pygame.quit()

    Ajouter d’autres objets

    Vous pouvez aussi laisser cours à votre imagination, et dessiner vos propres images.

    Par exemple, si vous voulez ajouter une clé, voici l’image en format png (transparence du fond):

    Ajouter alors les instructions pour créer une surface et reduire sa taille (ZONE 1)

    cle = pygame.image.load("datas/images/cle.png")
    cle = pygame.transform.scale(cle, (60,27))

    Pour créer un calque sur l’objet:

    rect2 = cle.get_rect()
    rect2.center = 80,115

    Pour afficher l’image:

    screen.blit(cle,rect2)

    Conseils pour votre projet de TP

    Architecture recommandée pour votre escape game

    Votre jeu devrait comporter ces éléments :

    1. Image de fond : Un décor de salle (chambre, bureau, etc.)
    2. Objets interactifs : Zones cliquables sur l’image (porte, livres, tableau, bouton de la télévision, etc.)
    3. Zone de texte : Affichage des descriptions et dialogues en bas de l’écran
    4. Touches de commande ou clic sur un objet : Actions possibles (examiner, utiliser, inventaire, obtenir de l’aide, etc.)
    5. Système d’état : Gérer ce qui a été fait ou trouvé: utiliser un dictionnaire pour chacun des objets (voir plus bas). Et modifier, lorsque l’on clique sur l’objet, les variables d’état de l’objet. Par exemple: cle["ramasse"] = True, ou cle["visible"] = False (voir plus bas)

    Conseils de programmation

    Organisez votre code avec des fonctions

    def afficher_fond():
        screen.fill((0,0,0))
        screen.blit(fond, (0, 0))
    
    def afficher_texte(message):
        texte = font.render(message, True, (255, 255, 255))
        screen.blit(texte, (0, 300))

    Utilisez des dictionnaires pour vos objets.

    Vous limiterez ainsi l’emploi de trop nombreuses variables:

    porte = {
            "nom": "porte",
            "image": door1,
            "x": 650,
            "y": 150,
            "largeur": 100,
            "hauteur": 200,
            "rect": rect1,
            "visible": True,
            "verrouille": True,
            "description": "Une porte en bois"
            }
    cle =   {
            "nom": "clé",
            "image": cle,
            "x": rect3.center[0],
            "y": rect3.center[1],
            "largeur": 60,
            "hauteur": 27,
            "rect": rect3,
            "visible": False,
            "ramasse": False,
            "description": "Une clé dorée"
            }
    ...

    Définir un scénario à l’aide de diagrammes

    Dans les zones 1 et 2, placer les variables utiles au jeu. Placer les différents textes à afficher.

    Dans la zone 3, prevoir les interactions avec les différents objets, ainsi que la modification des variables:

    Prévoir diagramme par objet ou par touche appuyée

    Prévoir diagramme par objet ou par touche appuyée

    Dans la zone 5, prévoir l’affichage du texte, ou le nouveau placement des objets/images.

    Si vous utilisez un dictionnaire vous pouvez remplacer les variables L, P, M par exemple par lampe["actionner"] = True/False, porte["verouille"] = True/False, et miroir["regarder"] = True/False. Ce qui presente l’avantage d’être plus clair.

    Questions à se poser avant de commencer le TP

    1. Quel est le scénario de mon escape game ?
    2. Quels objets ou quelles zones de l’image seront cliquables ?
    3. Quelles actions le joueur pourra-t-il faire ?
    4. Comment savoir si le joueur a gagné ?
    5. De quelles images ai-je besoin ?

    Bon courage pour votre projet ! 🎮

    Ressources utiles


    images numeriques

    • creation d’images numeriques version 1: Lien
    • creation d’images numeriques version 2: Lien
    • traitement d’une image: detourage, filtre, incrustation: Lien
    • tuto pour detourer une image avec Gimp: Lien

    Créer des images numeriques - Partie 1

    Les images numériques matricielles sont des tableaux de pixels. On peut concevoir images de synthèse à partir d’instructions en python (ou autre langage). Des librairies comme PIL permettent de manipuler les pixels comme les données d’une table.

    Dans cette seance, nous allons:

    • créer des images de synthèse
    • modifier des images existantes.

    formats de données

    Le portable pixmap file format (PPM), le portable graymap file format (PGM) et le portable bitmap file format (PBM) sont des formats de fichier graphique utilisés pour les échanges. Ils correspondent respectivement à des images en noir et blanc (ppm), en niveaux de gris (pgm), et en couleur (pbm).

    Les fichiers bruts comportent alors l’indication du format sur leur première ligne avec l’information : P1 pour le format ppm, P2 pour le pgm et enfin P3 pour le pbm.

    Couleurs : RVB

    Il existe plusieurs modes de codage informatique des couleurs, le plus utilisé pour le maniement des images est l’espace colorimétrique Rouge, Vert, Bleu (RVB ou RVG: Red Green Blue) par synthèse additive.

    Une image RVB est composée de la somme des trois rayonnements lumineux Rouge, Vert, Bleu dont les faisceaux sont superposés. A l’intensité maximale ils produisent une lumière blanche 255, 255, 255 en codage décimal, ou FF FF FF en hexadecimal.

    profondeur de couleur

    • norme HD: la profondeur en haute definition est de 1 octet par canal coloré R, V ou B

    • norme 4K : UHD = 10 bits par canal coloré

    Gimp: colorimètre

    A vous de jouer: vous allez mesurer l’intensité des couleurs sur l’image suivante

    clic droit: telecharger

    clic droit: telecharger

    Télécharger l’image.

    Adopter tout de suite les BONNES PRATIQUES:

    • Créer un nouveau dossier pour y mettre tous les fichiers sources et les images.

    A l’aide du logiciel Gimp, ouvrir l’image du carré rouge et relever les valeurs RVB du colorimètre.

    Synthèse d’images

    Rectangle rouge

    Vous allez créer une image (rectangle rouge) à partir d’un programme python.

    Utiliser un IDE python pour les exercices suivants: Pyzo ou Spyder.

    Adopter tout de suite les BONNES PRATIQUES:

    • pour chaque exercice, vous allez créer un NOUVEAU fichier python.
    • Donner un nom explicite au fichier, par exemple rouge.py pour le premier exercice
    • Définir les variables globales largeur et hauteur:
    largeur=600
    hauteur=420
    • Créer un nouveau fichier texte avec les instructions:
    f=open('red_square.ppm','w') 
    
    ############ entête du fichier ##################
    f.write('P3'+'\n') # P1 était le code pour un pbm format ascii
    			  # P3 correspond au ppm format ascii
    f.write(str(largeur)+' '+str(hauteur)+'\n')
    # valeur max pour l'intensité des couleurs :
    f.write('255'+'\n')
    ############### fin de l'entête ##################
    • Definir une fonction pour remplir le fichier avec les valeurs codant la couleur:
    #########  declaration de la fonction ############
    def rectangle(couleur,h,l) :
    	""" 
    	@param couleur: str
    	couleur est un triplet d'entiers, code RGB
    	@example: dessiner un rectangle entierement noir
    	>>> rectangle('0 0 0',largeur,hauteur)
    	"""
    	for i in range(h*l) :
    			f.write(couleur+'\n')
    • Puis appel de la fonction et fermeture du fichier:
    rectangle('255 0 0',largeur,hauteur)
    f.close()
    • Ajouter la librairie PIL.

    Ce qui donne le script complet suivant:

    from PIL import Image
    largeur=600
    hauteur=420
    
    #f=open('red_square','w') 
    f=open('red_square.ppm','w') 
    
    ############ entête du fichier ##################
    f.write('P3'+'\n') # P1 était le code pour un pbm format ascii
    			  # P3 correspond au ppm format ascii
    f.write(str(largeur)+' '+str(hauteur)+'\n')
    # valeur max pour l'intensité des couleurs :
    f.write('255'+'\n')
    ############### fin de l'entête ##################
    
    #########  declaration de la fonction ############
    def rectangle(couleur,h,l) :
    	""" 
    	@param couleur: str
    	couleur est un triplet d'entiers, code RGB
    	@example: dessiner un rectangle entierement noir
    	>>> rectangle('0 0 0',largeur,hauteur)
    	"""
    	for i in range(h*l) :
    			f.write(couleur+'\n')
    ######## appel fonction ############################			
    rectangle('255 0 0',largeur,hauteur)
    ########### fermeture fichier ######################
    f.close()

    Executer le programme avec les commandes de l’IDE python, puis…

    • Ouvrir le fichier avec un editeur de texte (notepad++) et observer les données.
    • Ouvrir le fichier avec un logiciel de dessin (GIMP)

    Drapeaux de pays

    Adopter tout de suite les BONNES PRATIQUES:

    • pour chaque nouveau défi, vous allez créer un NOUVEAU fichier python.
    • Donner un nom explicite au fichier, par exemple allemagne.py pour le premier défi, belgique.py pour le 2e…

    Adapter maintenant le script du rectangle rouge pour editer en python les drapeau suivants.

    Attention à BIEN faire correspondre le nombre de valeurs codantes pour la couleur des pixels. Si le nombre ne correspond par exactement à la dimension $largeur \times hauteur$ définie dans l’en-tête du fichier, vous risquez d’avoir une image sombre (erreur à l’affichage)

    drapeau allemand. 3 appels de la fonction rectangle('255 0 0',largeur,hauteur//3)

    drapeau allemand. 3 appels de la fonction rectangle('255 0 0',largeur,hauteur//3)

    Attention à bien modifier le nom du fichier généré. Le nommer par exemple drapeau_all.ppm

    drapeau belge. Utiliser une boucle bornée pour créer le drapeau ligne par ligne.

    drapeau belge. Utiliser une boucle bornée pour créer le drapeau ligne par ligne.

    motifs périodiques

    • pour chaque nouveau défi, vous allez créer un NOUVEAU fichier python.
    • Donner un nom explicite au fichier, par exemple pixart1.py pour le premier défi, pixart2.py pour le 2e…

    Dans chaque nouveau fichier, vous allez écrire le script qui va créer les images suivantes, à partir des matrices de valeurs binaires, mat. Dans cette matrice, vous placerez les valeurs en liste (une liste par ligne), et placerez ces lignes dans la matrice mat. Une valeur 0 pourra coder par exemple le bleu, et la valeur 1 le rouge (l’image ne contient que 2 couleurs).

    • pixart1.ppm
    from PIL import Image
    largeur=12
    hauteur=12
    
    f=open('pixart1.ppm','w') 
    
    ############ entête du fichier ##################
    f.write('P3'+'\n') 
    f.write(str(largeur)+' '+str(hauteur)+'\n')
    # valeur max pour l'intensité des couleurs :
    f.write('255'+'\n')
    ############### creation matrice ################
    mat = []
    for i in range(hauteur):
        ligne = []
        for j in range(largeur):
            ligne.append(0)
            ligne.append(...
        mat.append(...
    #########  declaration de la fonction ############
    def creation_image(M,h,l) :
        """ 
        @variable couleur: str
        couleur est un triplet d'entiers, code RGB
        @example: dessiner un pixel entierement noir
        >>> couleur = '0 0 0'
        """
        for i in range(h) :
            for j in range(l):
                if M[i][j] == 1:
                    couleur = '255 0 0'
                else:
                    couleur = '0 0 255'
                f.write(couleur+'\n')
    ######## appel fonction ############################	
    creation_image(mat,largeur,hauteur)		
    ########### fermeture fichier ######################
    f.close()
    • pixart2.ppm

    Pour chacune de ces images, vous complèterez le script de la fiche de cours.

    Lecture puis traitement des pixels de l’image - Partie 2

    Lire les pixels de l’image

    Dans cette activité, nous allons utiliser la fonction de lecture des couleurs des pixels d’une image. Puis transformer cette image par effet mirroir. Les chatons devront regarder à DROITE après transformation.

    Image de chatons à télécharger

    Image de chatons à télécharger

    La fonction getpixel du module PIL.Image. Cette fonction prend en paramètres les coordonnées du pixel à lire, sous forme d’un tuple (x,y). Exemple:

    >>> imageSource.getpixel((x,y))
    # retourne un tuple constitué des couleurs (R, V, B) du pixel de coordonnée (x,y)

    Voici le programme minimal pour ouvrir l’image et déterminer ses dimensions:

    from PIL import Image
    
    
    imageSource=Image.open("chats.bmp")
    largeur,hauteur=imageSource.size

    Pour lire les couleurs de TOUS les pixels, et appliquer une transformation, on va placer les valeurs dans une matrice, dans un certain ordre:

    mat = [[0]*largeur for i in range(hauteur)]
    for i in range(hauteur):
        for j in range(largeur):
            p = imageSource.getpixel((j,i))
            # j correspond à x 
            # et i <=> y
            mat[i][j]=p

    Puis placer les valeurs de la matrice dans un fichier .ppm, comme vu dans les activités précédentes:

    ####### ecriture du fichier pour la nouvelle image
    f=open('pixart2.ppm','w') 
    
    f.write('P3'+'\n') 
    f.write(str(largeur)+' '+str(hauteur)+'\n')
    # valeur max pour l'intensité des couleurs :
    f.write('255'+'\n')
    #########  declaration de la fonction ############
    def creation_image(M) :
        """ 
        @param couleur: str
        couleur est un triplet d'entiers, code RGB
        @example: dessiner un rectangle entierement noir
        >>> rectangle('0 0 0',largeur,hauteur)
        """
        h = len(M)
        l = len(M[0])
        for i in range(h) :
            for j in range(l):
                couleur = M[i][j] # tuple
                pixel = str(couleur[0]) + ' ' + str(couleur[1]) + ' ' + str(couleur[2])
                f.write(pixel+'\n')
    ######## appel fonction ############################	
    creation_image(mat)
    ########### fermeture fichier ######################
    f.close()

    Comment doit-on placer les pixels dans la matrice pour que les chats regardent de l’autre côté ? Modifier le programme ci-dessus afin d’obtenir cette nouvelle image, avec des petits chats qui regardent à DROITE.

    Pix-Art

    Avec l’image d’origine suivante:

    Marylin Monroe

    Marylin Monroe

    Apporter les modifications necessaires pour filtrer les couleurs par zone, de manière selective. On pourra obtenir une nouvelle oeuvre inspirée de l’image suivante:

    Marylin Monroe type Pop-art

    Marylin Monroe type Pop-art

    Aide: La condition suivante permet de selectionner les pixels de la partie gauche de l’image, et qui ont une composante Rouge supérieure à 100:

    if (j<largeur//2 and p[0] > 100) :
    	# traitement sur p

    Ce qui va donner:

    mat = [[0]*largeur for i in range(hauteur)]
    for i in range(hauteur):
        for j in range(largeur):
            p = imageSource.getpixel((j,i))
    		if (j<largeur//2 and p[0] > 100) :
    			# traitement sur p
            mat[i][j]=p

    Sur une idée venue de la visite de la collection de Luigi e Peppino Agrati, Naples.

    Extrait de l'oeuvre de Andy Warhol (1967). Marilyn.

    Extrait de l'oeuvre de Andy Warhol (1967). Marilyn.

    Ce TP est une variante de celui proposé à l’adresse suivante.

    Projet - construire une image à partir de calques

    voir l’énoncé ici

    Sous-sections de IHM web

    HTML

    Les langages web

    Une conception similaire à l’edition d’un document Word

    On utilise des logiciels d’edition, comme Word, Writer, ou Page, pour créer des documents qui seront le plus souvent imprimés (ou mis dans un format pdf).

    L’edition va consister à placer du contenu, le structurer, le mettre en forme. Et pour réaliser ceci, la bonne pratique, c’est justement de séparer ces 3 moments, tout en utilisant le même logiciel.

    video - youtube

    video - youtube

    Avec les langages web, HTML et CSS, on edite le document pour le web avec cette même pratique: en séparant les moments (et donc le code) prévus pour ajouter la structure, et ceux prévus pour gérer le style du document.

    Des langages interprétés: rôle du navigateur

    HTML : HyperTextMarkup Langage; CSS : Cascading StyleSheets; Javascript sont des langages interprétés par le navigateur, côté client. Ces 3 langages, en combinaison, vont permettre de créer des sites internet.

    Pour que les pages soient accessibles à tout le monde, sur le web[^2], ces pages doivent être hébergés sur un serveur. Lorsque le navigateur client envoie une requête au serveur, celui-ci lui renvoie les fichiers HTML, CSS et JS. Les instructions sont alors interprétées par le navigateur et permettent l’affichage des pages.

    Ces langages sont en constante évolution. Ce sont des langages open sources[^5] et de nombreux contributeurs en proposent des améliorations.

    Il existe plusieurs logiciels navigateurs (Mozilla, Chrome, Safari,…). Et pourtant, malgré cette diversité et ces évolutions du langage, ceux-ci vont interpréter ces fichiers et afficher les pages (presque) de la même manière car ils se réferent tous aux mêmes recommandations, celles du w3c[^4].

    Une petite différence peut exister pour le rendu d’une même page, mais avec plusieurs navigateurs différents. Cela est du aux propriétés par défaut utilisées par le navigateur pour l’affichage des différents éléments html de la page. Ces propriétés peuvent être déclarées (CSS) afin d’avoir un rendu toujours identique.

    Rappels de SNT sur le Web

    des tâches différentes

    Les langages web se partagent les tâches : Une bonne pratique dans le développement d’un site internet (côté front-end, ce qui est executé sur la machine du client) consiste à utiliser:

    • HTML pour le contenu , et la structure (avec un contenu correctement balisé, sémantique, accessible)
    • CSS pour la mise en forme et le design de la page, les propriétés relatives à chaque élément de Style (balise html).
    • et JavaScript pour gérer les interactions (qui peuvent éventuellement amener à modifier le contenu via les méthodes du DOM[^1]).

    C’est un langage de description qui gère le contenu (le texte et les images), en ajoutant des éléments de structure, comme par exemple:

    • mettre le texte dans un paragraphe
    • mettre du texte en relief
    • insérer un hyperlien sur le texte
    • mettre un titre à la page, au paragraphe
    • …
    Lire la video depuis 20' => 1min40'

    Lire la video depuis 20' => 1min40'

    Le langage HTML est un langage constitué de balises, comme par exemple : <title>le titre de ma page</title> qui permet d’afficher le titre de la page dans l’onglet du navigateur.

    Les éléments mis dans le programme à l’aide de ces balises vont permettre d’ajouter et structurer le contenu de la page : des titres de différents niveaux, du texte, des images, des médias (sons, videos),mais surtout, des hyperliens :

    • entre les pages du sites
    • vers les pages de sites externes

    Le web est justement basé sur l’utilisation de ces hyperliens, qui permettent de naviguer de pages en pages, sur internet.

    Le HTML et la page Web

    le squelette du document

    Cette partie du script est le contenu minimum à mettre dans vos pages HTML:

    <!DOCTYPE html>
    
    <html>
        <head>
            
            <!-- encodage des caractères -->
            <meta charset="UTF-8">
            <!-- Titre -->
            <title>Titre de la page web</title>
            <!-- Lien vers la feuille de style -->
            <link rel="stylesheet" type="text/css" href="style.css">
        </head>
    
        <body>
            <!-- corps de la page -->
    
        </body>
    </html>

    Le doctype indique au navigateur la version HTML utilisée par la page (ici HTML5).

    L’élément racine <html> : C’est lui qui va recueillir les deux principaux éléments de la hiérarchie : <head> et <body>.

    À ce niveau, le code HTML est alors divisé en deux parties.

    On peut lui associer l’attribut langue, précisant la langue utilisée dans le document :

    <html lang="fr">

    L’en-tête (élément <head>) donne l’encodage des caractères (ici UTF-8).

    Préciser l’encodage des caractères est primordial pour exploiter la bonne page de code et ne pas se retrouver avec les caractères spéciaux ou accentués. Le choix de l’UTF-8 est désormais préconisé par le W3C pour tous les protocoles échangeant du texte sur internet (dont HTML).

    On peut aussi y ajouter des éléments <link> et <script> :

    • link : permet de mettre en relation la page avec d’autres documents externes: <link rel="stylesheet" type="text/css" href="style.css">
    • <script> permet d’ajouter des scripts (JavaScript) qui vont s’éxécuter côté client dans le navigateur dès leur chargement.

    Si vous avez un script qui est très gros mais indépendant, il est préférable de le placer tout à la fin, afin de ne pas retarder le navigateur dans sa construction de l’arbre du DOM et de l’affichage de la page.

    Les balises principale

    Les balises sont les instructions en langage HTML des éléments structurants de la page web.

    Les balises se distinguent entre celles qui n’ont pas d’attribut obligatoire, et celles qui en ont. Un attribut va ajouter des fonctionnalités à l’élément HTML, et modifier son allure ou son fonctionnement.

    Balises sans attribut

    Les principales balises structurantes sont:

    • h1, h2, h3, … h6
    • div
    • p
    • span
    • strong
    • …

    Elles s’utilisent de la manière suivante:

    <h1>Texte</h1>
    <p>Texte</p>

    Il existe aussi des balises qui doivent être combinées, comme celles de listes:

    • ul (parent) => li (enfants) pour une liste à puces
    • ol (parent) => li (enfants) pour une liste ordonnée (numérotée)
    <ul>
      <li>Premier</li>
      <li>Deuxieme</li>
    </ul>
    
    <ol>
      <li>Premier</li>
      <li>Deuxieme</li>
    </ol>

    Résultat:

    • Premier
    • Deuxieme
    1. Premier
    2. Deuxieme

    balises avec attribut obligatoire

    Les attributs seront obligatoires pour certaines balises selon leur fonction. Certains attributs sont facultatifs et vont juste enrichir leur comportement.

    lien

    href est un attribut obligatoire.

    <a href="lien_vers_la_ressource.html">texte cliquable</a>

    image

    Il s’agit d’une balise orpheline.

    src est un attribut obligatoire.

    <img src="lien_vers_la_ressource.jpg">

    alt est un attribut facultatif, que l’on ajoute pour afficher un texte lorsque l’adresse de l’image est erronée, ou que celle-ci ne s’affiche pas.

    <img src="lien_vers_la_ressource.jpg" alt="texte alternatif">

    Remarque sur les adresses (href et src)

    L’adresse placée pour l’attribut href ou bien src peut être relative/absolue, locale/externe.

    Absolue

    Une adresse est absolue lorsque le chemin de celle-ci commence par /. Par exemple, pour un lien interne: /docs/2nde/chimie/images/photo1.jpeg

    Et pour un lien externe: http://nom_du_domaine.xyz/docs/2nde/chimie/images/photo1.jpeg

    Relative

    L’adresse est relative lorsqu’il n’y a pas /. Ce lien ne peut être qu’interne: src = "chimie/images/photo1.jpeg"

    Imbrication et filiation des balises

    La premiere page de l’histoire du Web

    Voir l’article sur Lumni.fr

    Cette page ne présentait pas de mise en forme particulière. Le code ne contenait pas de balises fermantes. Les pages n’étaient pas hierarchisées.

    Arbre du DOM

    Si vous débutez complètement en HTML, consultez les ressources de SNT:

    Une introduction à la redaction d’un document en HTML: Document Web, contenu et structure

    L’imbrication des balises traduit le lien (la filiation) entre les éléments.

    On représente la structure d’un document html à l’aide d’un arbre. On parle d’arbre DOM (Document Object Model) du document.

    Exemple d'arbre du DOM

    Exemple d'arbre du DOM

    Pour cet exemple: Le nœud article est le père des noeuds h1, p, img et p. Les nœuds h1, p, img et p sont les fils du nœud article.

    Quand faut-il recourir à des balises parentes?

    Supposons que l’on ait besoin de structurer la page comme sur l’image suivante:

    page avec sections

    page avec sectionnements

    Les éléments containers s’ils sont de type paragraphes, sections, header, nav, article, … vont se placer naturellement l’un sous l’autre. Il n’y a pas besoin d’imbriquer les balises.

    Par contre, s’il faut disposer côte à côte 2 éléments containers, pour faire 2 colonnes, il faudra les disposer à l’interieur d’un autre élément parent. Puis modifier leur disposition naturelle (paramètre display).

    Pour cet exemple, au niveau de l’élément au fond blanc, il faudra:

    • un container parent, par exemple un élément div
    • (colonne gauche): un container fils de div qui contiendra lui-même les éléments fils ‘section, article, article`
    • (colonne droite): un élément fils de div qui sera l’élément aside

    Voir aussi: cours HTML de SNT

    Un outil de vérification de la syntaxe

    Pour vérifier que votre page Web est conforme aux spécifications HTML5, rendez-vous sur le site du W3C (World Wide Web Consortium) : http://validator.w3.org

    Pour une page Web locale (pas encore publiée sur le Web) :

    Validate by File Upload → Check

    S’il y a des erreurs, elles vous seront indiquées, avec des explications (en anglais, of course).

    Conseil : vérifier et corriger systématiquement vos pages Web avec cet outil.C’est contraignant au début, mais cela vous fera prendre rapidement de bonnes habitudes.

    L’essentiel à retenir

    Le Web

    Le web fonctionne avec : le protocole HTTP (HyperText Transfert Protocol), les URL (Uniform Resource Locator) et le langage de description HTML (HyperText Markup Language).

    Le W3C
    Le World Wide Web Consortium, abrégé par le sigle W3C, est un organisme de standardisation à but non lucratif, fondé en octobre 1994 chargé de promouvoir la compatibilité des technologies du World Wide Web telles que HTML, CSS, JS… Le W3C permet la normalisation de la présentation de l’information.

    Le HTML

    HTML (HyperText Markup Langage) permet de structurer le contenu de la page web. C’est un langage interprété par le navigateur (client).

    C’est un langage constitué de balises. La plupart du temps, le contenu se met entre les balises ouvrantes / fermantes. Mais il existe des balises orphelines qui n’ont pas de fermeture (img, br).

    Le squelette du document est constitué du doctype (première ligne), puis des éléments html, head, et body.

    La manière avec laquelle les balises sont imbriquées correspond à une filiation entre les éléments (parent-fille). Ainsi, html est la balise parente de toutes les autres. html est aussi le parent direct de head et body.

    Le contenu de la page sera mis entre les balises de body.

    Le CSS

    Le langage CSS (Cascading Style Sheets) est le langage de mise en forme d’une page web. C’est un langage interprété par le navigateur. Le lien vers la feuille de style est souvent insérée dans l’en-tête de la page web:

    <link href="style.css" rel="stylesheets">

    Le Javascript

    Langage utilisé pour les scripts cöté client. Permet de gérer l’interactivité d’une page web, son aspect dynamique. L’aspect étant reservé aux langages HTML et CSS.

    Le lien vers le fichier contenant le script javascript est souvent insérée dans la page web:

    <script src="script.js">

    Tâches synchrones et asynchrones

    Deux opérations sont synchrones lorsque la seconde attend que la première ait fini son travail pour démarrer. Par exemple, le protocole HTTP (lors du chargement et rechargement d’une page web), mais aussi l’interprétation des langages HTML et CSS par le navigateur.

    Des opérations sont asynchrones en informatique lorsqu’elles sont indépendantes. Souvent, le navigateur interprète les scripts javascript de manière asynchrone, ce qui ne créé pas de blocage lors de la construction de la page.

    Toujours côté client, la technologie AJAX permet le transfert de données en arrière plan, sans avoir à recharger la page web.

    Scripts côté serveur

    Les scripts côté serveur nécessitent une communication avec le serveur de manière synchrone ou asynchrone. Ils serviront par exemple à collecter des données, à générer le code HTML de la page, à communiquer avec une base de données. Les langages les plus utilisées sont PHP, Python, Javascript …

    Liens

    css les bases

    Bases en css

    les fondamentaux du css: cascade et héritage: MDN

    Les sigles « CSS » sont l’abréviation de « Cascading StyleSheets » ou « feuilles de styles en cascade » en français.

    Le CSS vient résoudre un problème bien différent du HTML : en effet, le HTML sert à définir les différents éléments d’une page, à leur donner du sens. Le CSS, lui, va servir à mettre en forme les différents contenus définis par le HTML en leur appliquant des styles.

    Si votre navigateur affiche par défaut les contenus textuels que vous avez déclaré comme des titres en HTML en grand et en gras et à l’inverse les paragraphes en plus petit c’est justement parce que chaque navigateur possède sa propre feuille de styles. En fournissant nos styles CSS pour les différents contenus de notre page, nous allons donc pouvoir définir l’apparence de ceux-ci puisque les styles que nous allons fournir vont être considérés comme prioritaires par rapport à ceux du navigateur. C’est le principe du style en cascade (CSS)

    Une déclaration en CSS

    Une règle typique est composée de trois parties :

    • un sélecteur,
    • une propriété,
    • une valeur
    selecteur { propriete: valeur; }

    La valeur de la propriété se met après le séparateur :.

    Ces règles deviennent des déclarations lorsque celles-ci comprennent plusieurs couples propriété-valeur :Les règles sont alors séparées par un point-virgule ;, dans la même accolade:

    selecteur {
      propriete 1: valeur;
      propriete 2: valeur;
    }

    Le selecteur fait référence à un ou plusieurs éléments du document.

    indexer les parties du document

    Classes et identifiants L’un des attributs des éléments HTML peut servir à indexer cet élément :

    • de manière unique : l’attribut id="valeur" : une seule valeur d’attribut id peut être utilisée dans tout le document HTML. L’attribut id sert, comme son nom l’indique, à identifier un élément HTML en particulier dans une page pour ensuite pouvoir le cibler précisément (pour lui appliquer des styles CSS, ou bien créer un lien vers cet élément).
    • avec un attribut de classe : class="valeur" : ici, plusieurs éléments peuvent avoir la même classe. On pourra alors séléctionner (en css et en javascript) tous les éléments possédant cette classe, avec une seule instruction.

    Remarque: Plusieurs classes peuvent être associées à un élément HTML en les séparant par un espace : <h1 class="titre lexique">

    Selecteurs

    Pour pouvoir appliquer un style à un contenu, il va déjà falloir le cibler, c’est-à-dire trouver un moyen d’indiquer qu’on souhaite appliquer tel style à un contenu en particulier.

    Pour cela, nous allons utiliser des sélecteurs.

    selecteur effet
    h1 Le nom d’une balise. Toutes les balises de ce nom contenues dans le document seront concernées.
    h1,h2,h3 Plusieurs sélecteurs séparés par des virgules.Toutes les balises énumérées sont concernées.
    #logo Le caractère # indique un identifiant. La balise avec cet ID est concernée.Exemple img id=“logo” src="…"/.
    .bidule Le point introduit une classe. Toutes les balises comportant un attribut class de ce nom sont concernées.Exemple : p class=“bidule”
    tab img Plusieurs sélecteurs séparés par un espace : inclusion. Les balises img incluses dans un tableau sont concernées. Il peut exister des niveaux intermédiaires : ici il y aura probablement au moins des balises tr et td.

    Règles principales

    Principe

    Le CSS permet d’ajouter des propriétés aux éléments (html) de la page. Par exemple, pour realiser la ligne suivante, avec une partie du texte en gras, et une partie en caractères normaux, non gras:

    Acteur: Daniel Crog

    On peut, soit utiliser une balise inline <strong> placée avant le texte (propriété font-weight: bold), soit une balise inline générique, et placer une instruction CSS. Ces 2 choix vont donner le même résultat:

    <!-- choix n°1-->
    <strong>Acteur:</strong> Daniel Crog
    <!-- choix n°2-->
    <span style="font-weight: bold">Acteur:</span> Daniel Crog

    Règles appliquées aux textes

    Tutoriel complet: developer.mozilla.org

    Quelques propriétés CSS relatives aux textes

    paramètre valeurs possibles effet
    color blue, yellow, red, … colorie le texte selon le nom anglais de la couleur
    color rgb(0..255, 0..255, 0..255) selon le code RGB sur un octet chacun
    color #0..F0..F0..F selon le code RGB exprimé en hexadecimal, sans separateur
    background-color idem color couleur de fond
    font-family arial, courier new… choix de la police de caractères
    font italic 12 px sans-serif informations complémentaires pour la police
    text-align center, left, right, justify alignement du texte
    font-weight bold mettre en gras

    Règles appliquées aux boites

    Tutoriel complet: developer.mozilla.org

    En CSS, tout élément est inclus dans une boîte

    paramètre valeurs possibles effet
    border solid, dashed, none bordure en trait plein, pointillé, sans bordure
    margin 1px marge exterieur, dimension en pixels
    padding 1px marge intérieure

    Rappel sur la propriété display

    • Les balises s’affichant en “block” (bloc) : elles prennent toute la largeur disponible et s’affichent avec un saut de ligne avant et après. On peut les dimensionner avec les propriétés width et height. Elles n’accèptent pas vertical-align
    • Les balises s’affichant en “inline” (dans la ligne) : elles prennent uniquement la largeur utile pour leur contenu, sans ajouter de saut de ligne. Elles acceptent vertical-align, mais pas width et height.

    Approfondir

    héritage

    Lien alsacreation

    L’héritage des CSS est fondé sur le modèle Parent-Enfant(s) : chaque élément Enfant reçoit en héritage tous les styles de son élément Parent. Par exemple, la balise <html> est parent de <body>, et <table> est parent de <tr> qui lui-même est parent de <td>. Cet héritage est très pratique et permet d’éviter beaucoup de répétitions inutiles.

    Précision : l’élément enfant héritera de toutes les propriétés de l’élément parent uniquement si ces propriétés s’héritent, car l’héritage ne fonctionne pas non plus sur toutes les propriétés css (margin, padding et autres propriétés de bloc).

    Pour appliquer une propriété de style “par défaut” à un document, un auteur peut l’appliquer à la racine de l’arbre du document.

    Par exemple ici, tous les descendants de l’élément BODY auront la valeur de couleur ‘black’, la propriété ‘color’ étant héritée :

    BODY { color: black; }

    Les valeurs de pourcentage spécifiées ne sont pas héritées, celles calculées le sont.

    Par exemple, cette feuille de style :

    BODY { font-size: 10pt }
    H1 { font-size: 120% }

    et cet extrait d’un document :

    <BODY>
      <H1>Un <EM>grand</EM> titre</H1>
    </BODY>

    Ici, la propriété ‘font-size’ de l’élément H1 aura une valeur calculée de ‘12pt’ (120% de la valeur de son parent). Et, comme la valeur de la propriété ‘font-size’ est héritée, la valeur calculée pour l’élément EM sera aussi ‘12pt’.

    Selection, compléments

    selecteur effet
    td > img Plusieurs sélecteurs séparés par un caractère supérieur : inclusion directe.Les balises img directement incluses dans une cellule de tableau sont concernées. Il ne doit pas exister de niveaux intermédiaires.
    td + img Plusieurs sélecteurs séparés par un signe + : vient après.Désigne les balises img venant après une balise p.
    p ~ img Plusieurs sélecteurs séparés par un signe ~ : une balise qui suit une autre (directement ou pas)
    :hover Le caractère : (deux points) introduit une pseudo-classe. La pseudo-classe désigne un élément lorsqu’il se trouve dans une certaine situation : ici lorsqu’il est survolé par la souris.Voir la liste complète des pseudo-class.
    img[width] Désigne les balises img comportant un attribut width quelle que soit la valeur de ce dernier. On teste donc seulement la présence de l’attribut.
    p[lang = “fr” ] Ici on limite la portée aux balises p qui comportent l’attribut lang avec la valeur “fr”.p lang=“fr”

    Exemple: mise en couleur de fond gris pour une cellule sur 2 du tableau

    tbody > tr:nth-child(odd) > td {
      background-color: lightGrey;
    }

    CSS avancé

    les bases en javascript

    • cours 1 sur les fondamentaux en js: Lien
    • cours 2 sur la structure du langage: Lien
    • TP 1 - decouverte du js: Lien
    • TP 2 - TP hack: Lien
    • TP 3 - calculatrice : Lien v1 ou Lien v2
    • TP 4 - Animation sur tracé SVG: Lien, correction

    Les Fondamentaux de JavaScript

    Introduction

    Ce cours présente les concepts de base de JavaScript en les comparant avec Python, que vous connaissez déjà. JavaScript est le langage de programmation du web : il permet de rendre les pages interactives.

    Principales différences avec Python :

    • JavaScript s’exécute dans le navigateur (côté client)
    • La syntaxe utilise des accolades {} au lieu de l’indentation
    • Il existe plusieurs façons de déclarer des variables
    • JavaScript manipule directement les éléments HTML (le DOM)

    Présentation de la console javascript

    Javascript est une implémentation dans le navigateur du langage Ecmascript.

    Javascript est un langage interprété … par le navigateur, donc côté client. Pour le vérifier, on peut utiliser la console javascript du navigateur pour tester quelques instructions, et interagir avec la page web en cours.

    Sur Chrome, cette console se trouve en ouvrant les outils de développement :

    console javascript Chrome

    la console javascript dans le navigateur Chrome

    Choisir alors l’onglet : Console et commencer à taper les instructions, une à une, après l’invite >, comme sur l’image suivante :

    E/S

    entrée / sortie

    Pour afficher le résultat d’une opération dans la console (équivalent au print en python), on utilise l’instruction console.log(operation).

    L’option filter de la console devra être sur Default

    Les Variables : let, const et var

    En Python (rappel)

    En Python, on déclare une variable simplement :

    # Une variable simple
    age = 15
    nom = "Alice"
    
    # On peut la modifier
    age = 16

    En JavaScript : trois mots-clés

    JavaScript propose trois façons de déclarer une variable :

    let age = 15;        // Variable qui PEUT changer
    const nom = "Alice"; // Constante qui NE PEUT PAS changer
    var ancien = 10;     // Ancienne syntaxe (à éviter)
    

    Le typage est dynamique, comme en python: il n’est pas besoin de préciser le type.

    Règle d’utilisation

    Mot-clé Usage Peut changer ? Recommandation
    const Valeur fixe [X] Non À utiliser par défaut
    let Valeur variable [V] Oui Quand la valeur change
    var Ancienne syntaxe [V] Oui À éviter (obsolète)

    Exemples concrets

    // Utiliser const par défaut
    const pi = 3.14159;           // Ne changera jamais
    const nom = "Alice";          // Ne changera jamais
    const bouton = document.getElementById('monBouton'); // Ne changera jamais
    
    // Utiliser let quand ça change
    let compteur = 0;             // Va augmenter
    let temperature = 20;         // Peut varier
    let score = 0;                // Va évoluer
    
    // Erreur : on ne peut pas modifier une const
    const age = 15;
    age = 16;  // ERREUR : Assignment to constant variable
    
    // Correct : on peut modifier un let
    let age = 15;
    age = 16;  // OK
    

    Remarque : A moins que vous soyez sûr que la valeur puisse être modifiée, déclarez vos variables avec const, puis changez en let seulement si le compilateur vous indique une erreur.

    Quelques différences Python ↔ JavaScript

    Python JavaScript
    age = 15 let age = 15;
    PI = 3.14 (convention) const PI = 3.14; (imposé)
    Pas de point-virgule Point-virgule ; recommandé
    print(age) console.log(age)

    Le DOM : Document Object Model

    Qu’est-ce que le DOM ?

    Le DOM est la représentation en mémoire de votre page HTML. JavaScript peut :

    • Lire les éléments HTML
    • Les modifier
    • Créer de nouveaux éléments
    • Réagir aux actions de l’utilisateur

    Analogie avec Python :

    # En Python, vous manipulez des fichiers
    fichier = open('data.txt', 'r')
    contenu = fichier.read()
    fichier.close()
    
    # En JavaScript, vous manipulez des éléments HTML
    element = document.getElementById('monId')
    contenu = element.textContent

    Récupérer un élément : getElementById()

    HTML de départ

    Placer un attribut id aux balises que l’on veut indexer.

    <h1 id="titre">Bienvenue</h1>
    <p id="description">Ceci est un paragraphe</p>
    <button id="monBouton">Cliquez-moi</button>

    JavaScript

    <script>
    // Récupérer les éléments
    const titre = document.getElementById('titre');
    const description = document.getElementById('description');
    const bouton = document.getElementById('monBouton');
    
    console.log(titre); // Affiche: <h1 id="titre">Bienvenue</h1>
    </script>

    A faire vous-même (1): Placer les 2 parties du script ci-dessus dans une même page (page.html). Ouvrir avec un navigateur.

    Remarque importante : L’ID doit être exactement le même (sensible à la casse)

    // Correct
    const element = document.getElementById('monBouton');
    console.log(element); // Affiche <button id="monBouton">Cliquez-moi</button>
    
    // Erreur : mauvaise casse, ou ID inexistant
    const element = document.getElementById('MonBouton');
    console.log(element); // Affiche: null
    

    Attributs vs Propriétés

    Comprendre la différence

    Un élément HTML possède :

    • Des attributs (définis dans le HTML)
    • Des propriétés (accessibles en JavaScript)

    Exemple HTML

    <input type="text" id="champNom" value="Alice">

    Les attributs (dans le HTML)

    • type="text"
    • id="champNom"
    • value="Alice"

    Les propriétés (en JavaScript)

    const champ = document.getElementById('champNom');
    
    // Propriétés disponibles :
    champ.type        // "text"
    champ.id          // "champNom"
    champ.value       // "Alice" (peut être modifié par l'utilisateur)
    champ.textContent // ""
    champ.style       // Objet avec toutes les propriétés CSS
    

    La notation pointée

    En JavaScript, on accède aux propriétés avec un point (comme en Python) :

    # Python: notation pointée pour objet.attribut ou objet.methode()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    // JavaScript : notation pointée pour les éléments HTML
    const element = document.getElementById('titre');
    
    // Lire une propriété
    console.log(element.textContent);  // "Bienvenue"
    console.log(element.id);           // "titre"
    
    // Modifier une propriété
    element.textContent = "Nouveau titre";
    element.style.color = "red";

    Propriétés courantes

    textContent : Le texte à l’intérieur

    <p id="message">Bonjour tout le monde</p>

    A faire vous-même (2): Placer dans votre page.html le paragraphe Bonjour tout le monde. Ouvrir la console Web et placer l’une après l’autre chacune des instructions javascript ci-dessous.

    const message = document.getElementById('message');
    
    // Lire le texte
    console.log(message.textContent); // "Bonjour tout le monde"
    
    // Modifier le texte
    message.textContent = "Nouveau message";
    // Le HTML devient : <p id="message">Nouveau message</p>
    

    value : La valeur d’un champ de saisie

    <input type="text" id="nom" value="Alice">
    <input type="range" id="age" min="0" max="100" value="25">
    <script>
    const champNom = document.getElementById('nom');
    const curseurAge = document.getElementById('age');
    </script>

    A faire vous-même (3): Tester cet exemple: Placer le script dans votre page.html. Puis écrire chacune de ces instructions dans la console:

    // Lire les valeurs
    console.log(champNom.value);   // "Alice"
    console.log(curseurAge.value); // "25"
    
    // Modifier les valeurs
    champNom.value = "Bob";
    curseurAge.value = 30;

    style : Modifier le CSS

    <h1 id="titre">Le Javascript c'est simple</h1>

    A faire vous-même (4): Tester cet exemple: Placer le script dans votre page.html. Puis écrire chacune de ces instructions dans la console:

    const element = document.getElementById('titre');
    
    // Modifier le style
    element.style.color = "blue";
    element.style.fontSize = "24px";
    element.style.backgroundColor = "yellow";
    
    // Note: les propriétés CSS avec tirets deviennent camelCase
    // CSS: background-color → JavaScript: backgroundColor
    // CSS: font-size → JavaScript: fontSize
    

    Tableau récapitulatif

    Propriété Type d’élément Usage
    textContent Tous Lire/modifier le texte
    value Input, textarea, select Lire/modifier la valeur saisie
    style Tous Modifier le CSS
    id Tous Lire/modifier l’ID
    className Tous Lire/modifier les classes CSS

    Comparaison complète Python ↔ JavaScript

    Variables

    Concept Python JavaScript
    Déclarer une variable x = 10 let x = 10;
    Constante PI = 3.14 (convention) const PI = 3.14;
    Chaîne de caractères "texte" ou 'texte' "texte" ou 'texte'
    Concaténation "Hello " + nom "Hello " + nom
    Affichage console print(x) console.log(x);

    Types de données

    Type Python JavaScript
    Entier age = 15 let age = 15;
    Décimal prix = 19.99 let prix = 19.99;
    Texte nom = "Alice" let nom = "Alice";
    Booléen actif = True let actif = true;
    Rien/Null None null

    Attention : True/False en Python → true/false en JavaScript (minuscules !)

    Opérateurs

    Opération Python JavaScript
    Addition x + 1 x + 1
    Incrémentation x += 1 x++ ou x += 1
    Égalité x == 5 x === 5
    Différent x != 5 x !== 5
    Et logique and &&
    Ou logique or `
    Négation not !

    [!] Important : En JavaScript, préférez toujours === et !== (égalité stricte)


    Fonctions

    Déclaration

    # Python
    def dire_bonjour(nom):
        print(f"Bonjour {nom}")
    
    dire_bonjour("Alice")
    // JavaScript - Syntaxe classique
    function direBonjour(nom) {
        console.log("Bonjour " + nom);
    }
    
    direBonjour("Alice");
    
    // JavaScript - Fonction fléchée (moderne)
    const direBonjour = (nom) => {
        console.log("Bonjour " + nom);
    };
    
    direBonjour("Alice");

    Fonctions sans paramètres

    # Python
    def afficher_message():
        print("Message affiché")
    // JavaScript
    function afficherMessage() {
        console.log("Message affiché");
    }
    
    // Ou avec fonction fléchée
    const afficherMessage = () => {
        console.log("Message affiché");
    };

    Retour de valeur

    # Python
    def additionner(a, b):
        return a + b
    
    resultat = additionner(5, 3)  # 8
    // JavaScript
    function additionner(a, b) {
        return a + b;
    }
    
    const resultat = additionner(5, 3); // 8
    

    Exemple complet : Compteur

    Version Python (pour comparaison)

    compteur = 0
    
    def incrementer():
        global compteur
        compteur += 1
        print(f"Compteur: {compteur}")
    
    incrementer()  # Affiche: Compteur: 1
    incrementer()  # Affiche: Compteur: 2

    Version JavaScript (interaction avec HTML)

    <button id="bouton">Cliquer</button>
    <p>Compteur: <span id="affichage">0</span></p>
    // Récupération des éléments
    const bouton = document.getElementById('bouton');
    const affichage = document.getElementById('affichage');
    
    // Variable compteur
    let compteur = 0;
    
    // Fonction d'incrémentation
    function incrementer() {
        compteur++;
        affichage.textContent = compteur;
    }
    
    // Associer la fonction au clic
    bouton.addEventListener('click', incrementer);

    Explication ligne par ligne :

    1. const bouton = ... : Récupère l’élément bouton (ne changera jamais)
    2. const affichage = ... : Récupère l’élément d’affichage (ne changera jamais)
    3. let compteur = 0 : Variable qui va changer (on utilise let)
    4. function incrementer() : Déclare la fonction
    5. compteur++ : Ajoute 1 au compteur (équivalent à compteur += 1)
    6. affichage.textContent = compteur : Met à jour le texte affiché
    7. addEventListener('click', incrementer) : “Quand on clique, exécute la fonction”

    Exercices d’application

    Exercice 1 : Variables

    Complétez le code suivant :

    // 1. Déclarez une constante PI valant 3.14159
    
    // 2. Déclarez une variable score initialisée à 0
    
    // 3. Augmentez le score de 10
    
    // 4. Affichez le score dans la console
    

    Exercice 2 : Manipulation du DOM

    Étant donné le HTML suivant :

    <h1 id="titre">Titre initial</h1>
    <p id="texte">Paragraphe initial</p>

    Écrivez le JavaScript pour :

    1. Récupérer le titre
    2. Changer son texte en “Nouveau titre”
    3. Récupérer le paragraphe
    4. Changer son texte en “Nouveau paragraphe”

    Exercice 3 : Formulaire interactif

    HTML fourni :

    <input type="text" id="prenom" placeholder="Votre prénom">
    <button id="valider">Valider</button>
    <p>Bonjour <span id="affichage">...</span></p>

    Écrivez le JavaScript pour afficher le prénom saisi quand on clique sur “Valider”.


    Erreurs courantes à éviter

    Erreur 1 : Oublier const ou let

    // Mauvais (crée une variable globale implicite)
    compteur = 0;
    
    // Bon
    let compteur = 0;

    Erreur 2 : Utiliser const pour une valeur qui change

    // Erreur
    const score = 0;
    score = 10; // TypeError: Assignment to constant variable
    
    // Correct
    let score = 0;
    score = 10;

    Erreur 3 : Confondre textContent et value

    // Pour un <p>, <h1>, <div>, etc.
    element.textContent = "texte"; // 
    
    // Pour un <input>, <textarea>
    element.value = "texte"; // 
    

    Aide-mémoire

    // ============================================
    // VARIABLES
    // ============================================
    const PI = 3.14;           // Constante (ne change pas)
    let compteur = 0;          // Variable (peut changer)
    
    // ============================================
    // RÉCUPÉRER UN ÉLÉMENT
    // ============================================
    const element = document.getElementById('monId');
    
    // ============================================
    // LIRE DES PROPRIÉTÉS
    // ============================================
    element.textContent        // Le texte affiché
    element.value             // La valeur d'un input
    element.id                // L'identifiant
    element.style.color       // La couleur CSS
    
    // ============================================
    // MODIFIER DES PROPRIÉTÉS
    // ============================================
    element.textContent = "Nouveau texte";
    element.value = "Nouvelle valeur";
    element.style.color = "red";
    
    // ============================================
    // FONCTION
    // ============================================
    function maFonction() {
        // Code ici
    }
    
    // ============================================
    // ÉVÉNEMENT
    // ============================================
    bouton.addEventListener('click', maFonction);
    
    // ============================================
    // OPÉRATEURS COURANTS
    // ============================================
    compteur++                // Ajoute 1
    compteur += 5             // Ajoute 5
    x === y                   // Égalité stricte
    x !== y                   // Différence stricte
    
    // ============================================
    // CONSOLE
    // ============================================
    console.log(variable);    // Affiche dans la console
    

    Pour aller plus loin

    const par défaut

    // BONNE PRATIQUE : const pour les références
    const bouton = document.getElementById('btn');
    const affichage = document.getElementById('resultat');
    
    // Ces éléments ne changeront jamais, même si leur contenu change
    bouton.textContent = "Nouveau texte";  // OK !
    affichage.textContent = "Score: 10";   // OK !
    
    // On ne peut pas réassigner à un autre élément
    bouton = document.getElementById('autre'); // ERREUR
    

    Prochaines notions à découvrir: PAGE 2 sur allophysique

    • Les conditions (if, else)
    • Les boucles (for, while)
    • Les tableaux (array)
    • Les objets
    • Les événements avancés
    • La manipulation du CSS
    • Les timers et animations

    Ressources recommandées


    Solutions
    // Exercice 1
    const PI = 3.14159;
    let score = 0;
    score += 10;
    console.log(score);
    
    // Exercice 2
    const titre = document.getElementById('titre');
    titre.textContent = "Nouveau titre";
    
    const texte = document.getElementById('texte');
    texte.textContent = "Nouveau paragraphe";
    
    // Exercice 3
    const champPrenom = document.getElementById('prenom');
    const boutonValider = document.getElementById('valider');
    const affichage = document.getElementById('affichage');
    
    function afficherPrenom() {
        const prenom = champPrenom.value;
        affichage.textContent = prenom;
    }
    
    boutonValider.addEventListener('click', afficherPrenom);

    javascript DOM

    • cours 1 sur les fondamentaux en js: Lien
    • cours 2 sur la structure du langage: Lien
    • TP 1 - decouverte du js: Lien
    • TP 2 - TP hack: Lien
    • TP 3 - calculatrice : Lien v1 ou Lien v2
    • TP 4 - Animation sur tracé SVG: Lien, correction

    Javascript : compléments

    javascript dans une page web

    Javascript, c’est aussi le langage de script des pages web : on peut aussi :

    • Mettre son code javascript entre les balises <script> et </script> d’une page HTML. Cette page est construite au fur et à mesure du parcours par l’interpreteur. La partie javascript sera interprétée APRES l’affichage de la page par le navigateur si cet élement script est mis à la fin du document HTML.

    • Mettre son code dans un fichier externe : Il faudra d’abord lier le fichier javascript à celui HTML : <script src="monfichierJavascript.js"></script>

    Principe : le rôle du navigateur et son moteur javascript

    interpreteur js

    l'interpreteur javascript

    • Browser : navigateur. C’est est un logiciel conçu pour consulter et afficher le World Wide Web. Techniquement, c’est au minimum un client http ou https (qui sont des protocoles de communication, définis lors du dernier cours)
    • Web console : Permet de coder, d’interpréter et d’exécuter du code Javascript directement sur le Browser
    • Js Engine : Est intégré dans les Browser. Chaque Browser a son propre interpréteur Javascript qui interprète le code et exécute les scripts associés aux pages Web

    En EcmaScript, on passe la majeure partie de son temps à interagir avec des API fournis par l’environnement d’exécution. En ActionScript c’est Flash (objet flash), en JavaScript dans le navigateur c’est le Document Object Model (objet document).

    Structurer son code

    La javascript utilise certains symboles pour structurer :

    • à chaque ligne on met un point-virgule pour séparer les instructions
    • les accolades { et } séparent les blocs de code
    • Commenter son code : // en debut de ligne ou bien /* texte entre les 2 separateurs */
    //Commentaire sur une ligne 
    /*Commentaire sur 
    Plusieurs ligne */

    Les indentations, comme en python ne sont pas obligatoires pour structurer le code, mais fortement conseillées pour permettre une meilleure lisibilité.

    Les 3 Data types de bases

    Les 3 types simples

    Pour déclarer une variable, on utilise le mot clé : let (ou bien var, mais qui n’est plus préconisé par le w3c)

    Par exemple : let a = 10 ; let b = “toto“ ; Le typage des variables se fait alors de manière dynamique, comme en python.

    • Number : Représente à la fois les entiers et les nombres flottants.
    • String : Représente du texte ou des caractères
    • Boolean : Seulement 2 valeurs : - vrai (true) – faux (false)

    Pour connaître le type d’une variable, on utilise la fonction typeof(variable)

    conversions de types

    a. Convertir en nombre entier : parseInt(‘valeur’) b. Convertir en nombre flottant : parseFloat() c. Tester si la valeur est NaN (not a number) : isNaN() d. Convertir en chaine de caractère : string(variable) avec un ‘S’ majuscule.

    Les tableaux: type Array

    Les tableaux, array, sont des collections d’objets, mis et ordonnés dans une variable unique. On accède à chaque élément du tableau avec son rang. Cette structure de données est assez proche de la liste que l’on a vu en python.

    Déclarer un tableau vide : 2 manières :

    let tab = new Array() ;

    let tab = [] ;

    initialiser un tableau :

    Pour déclarer et affecter directement des éléments, on fait :

    let fruits = ["Apple","Orange", "Pear"]

    accéder à un élément du tableau :

    (on peut tester ces exemples avec la console)

    console.log( fruits[0]) ; // "Apple"
    console.log( fruit[1]) ;  //...
    console.log( fruit[2]) ;  // ..
    

    méthodes associées aux tableaux :

    dimension du tableau (nombre d’éléments)

    tab.length ; // affiche 3
    

    retirer un élément de la fin du tableau

    On utilise l’instruction array.pop()

    tab.pop() ;
    console.log(tab) ; // affiche ["Apple ", "Orange "]
    

    ajouter un élément à la fin

    On utilise l’instruction array.push(nouvel_element)

    tab.push("Plum ") ;
    console.log(tab) ; // affiche ["Apple", "Orange ", "Plum "]
    

    Les objets: Type Object

    Un objet est un ensemble de propriétés et une propriété est une association entre un nom (aussi appelé clé) et une valeur. C’est l’équivalent des dictionnaires python.

    On peut définir une propriété en lui affectant une valeur. Ainsi, si on crée un objet maVoiture et qu’on lui donne les propriétés fabricant, modèle, et année :

    let maVoiture = new Object();
    maVoiture.fabricant = "Ford";
    maVoiture.modele = "Mustang";
    maVoiture.annee = 1969;

    On peut aussi définir ou accéder à des propriétés JavaScript en utilisant une notation avec les crochets:

    let maVoiture = new Object();
    maVoiture["fabricant"] = "Ford";
    maVoiture["modèle"] = "Mustang";
    maVoiture["année"] = 1969;

    L’exemple précédent peut également s’écrire avec la syntaxe littérale pour initialiser les objets:

    let maVoiture = {
      make: "Ford",
      model: "Mustang",
      year: 1969,
    };

    Opérations

    opérateurs de base

    On retrouve les opérateurs déjà vus en langage python :

    • Opérateurs de base : +, -, *, / ainsi que l’opérateur % modulo (reste de la division)
    • **est l’opérateur exposant : 2**8 correspond à 2^8 (à la puissance 8)
    • Le symbole d’affectation est le =. Par exemple : let a = 10 ; // instruction qui declare et affecte 10 à la variable a

    Question 1 : Alice a 1 frère et 3 sœurs pour 8 bonbons. Elle voudrait partager les bonbons équitablement. Utiliser des variables pour trouver une solution à son problème.

    Question 2 : Coder un programme qui permet de savoir l’âge d’Alice (28 ans) en secondes. Réaliser les calculs avec des variables aux noms bien explicites pour les heures, jours, années. Si vous pouvez, utilisez des noms en langue anglaise pour les variables.

    Les opérateurs logiques

    est égal ==, est supérieur ou égal >=, inferieur ou égal <=, et &&, ou ||, non !. On peut aussi utiliser and, or, not pour ces 3 derniers opérateurs.

    Fonctions

    function .. return

    Une fonction se définit avec le mot clé function selon la structure : function nom_de_la_fonction(parametre1, parametre2, …) { bloc de code return valeur_à_retourner ; }

    Par exemple, pour programmer une fonction nommée f qui retourne le résultat du calcul :

    $$f : n \mapsto 3n+3$$
    function f(n) { <br>    return 3*n+3 ; <br>}
    f(2) // affiche 9
    

    procédure

    On peut réaliser une fonction qui ne calcule rien, une procédure :

    Exemple : pour afficher 5 petits chats dans la console :

    function drawCats (howManyTimes) {
    	     for (let i = 0 ; i < howManyTimes; i++) {
    	     	console.log(i + ” =^.^=”);
    	     	}
    	     }
    drawCats(5);
    // affiche
    =^.^=
    =^.^=
    =^.^=
    =^.^=
    =^.^=

    La boucle bornée for est expliquée dans le chapitre suivant…

    Contrôler le flux du programme

    Conditions : if .. else .. :

    if (condition) {
    bloc1 ;
           } else {
        bloc2 ;
           }

    Exemple : le programme suivant compare la somme de 2 entiers avec 4 et renvoie below ou over, selon le resultat :

    let a = 1,b = 2 ;
    if (a+b<4){
    result="below";
           } else {
    result="over";
          }

    Boucles bornées

    Boucle for :

    for (let variable; condition à realiser pour boucler; augmenter la variable) {
        bloc de code à realiser ;
    }

    Par exemple, pour afficher toutes les valeurs de 0 à 10 dans la console, on fait :

    for (let i =0; i<=10; i++){
        console.log(i);
    }

    Parcourir les éléments d’un tableau ou d’un objet: 2 manières

    • En utilisant la méthode fruits.lenght :
    for (let i =0; i<=fruits.length; i++){
    	console.log(fruits[i]);}
    // affiche
    Apple
    Orange
    Plum
    • En utilisant for...of:
    const object1 = {
      a: "somestring",
      b: 42,
      c: false,
    };
    
    console.log(Object.keys(object1));
    // Expected output: Array ["a", "b", "c"]
    for (const i of Object.keys(object1) ) {console.log(i,object1[i])};
    // Affiche:
    > "a" "somestring"
    > "b" 42
    > "c" false

    Boucles non bornées : while :

    syntaxe :

    while (condition à realiser pour boucler) {
        bloc de code
    }

    Par exemple, pour afficher les entiers de 0 à 2 :

    let i = 0 ;
    while (i<3) {
        console.log(i) ;
        i ++ ;
    }

    La grande différence avec une boucle bornée, c’est que l’instruction qui modifie la variable i est DANS le bloc de code. Si celle-ci est mal écrite, la boucle risque d’être exécutée indéfiniment (à éviter bien sûr).

    Liens

    • parcours for pour les éléments d’un objet: MDN mozilla

    • Concepts avancés et Jeu d’arcade en javascript (hors programme): Page 3

    serveur Flask

    • TP python-Flask pas à pas: Lien
    • projet utilisant python-Flask: Lien

    Flask

    Flask est une bibliothèque python fournissant les outils pour faire fonctionner un serveur web.

    Fonctionnement de Flask

    Fonctionnement de Flask

    L’architecture Modèle-Vue-Contrôleur est composée de trois entités distinctes, chacune ayant son propre rôle:

    • Le contrôleur: gère le fonctionnement du site Web. Le programme est écrit en python.
    • Les vues: cette partie se concentre sur l’affichage, et a pour rôle d’assembler le code HTML issu du template. Dans une vue, on peut mettre en oeuvre des algorithmes écrits en python. La vue va partager des variables avec les templates.
    • Les templates: c’est le modèle de la page HTML qui sera utilisée par la vue pour générer la page HTML envoyée au client. Cette page peut être personnalisée selon les variables partagées avec la vue. C’est grâce à certaines parties écrites en langage JINJA2, dans le corps du script du template que la substitution des éléments HTML sera réalisée. Un peu comme un texte à trous.

    lien vers explications

    Structure du projet

    Créez dans vos Documents un dossier serveur_form.

    Créez les sous-dossiers templates, static, et images, comme sur l’arborescence suivante:

    Documents/serveur_form
    /
    |- main.py
    |- templates/ 
        |- form.html
        |- result.html

    fichier serveur

    à faire

    • Ouvrir un editeur Python (Spyder par exemple)
    • créez un fichier Python “main.py” (ce fichier devra être sauvegardé dans le répertoire “serveur_form” précédemment créé). Saisissez le code suivant dans le fichier “main.py”
    from flask import Flask, render_template
    
    app = Flask(__name__)
    
    @app.route('/')
    def form():
      return "<p>Tout fonctionne parfaitement</p>"
    
    app.run(debug=True)

    Ce fichier main.py contient les vues (les pages), et lance le contrôleur lorsqu’il est executé.

    • Executer le programme ci-dessus

    • ouvrez votre navigateur web et tapez dans la barre d’adresse “localhost:5000”

    Vous devriez voir la phrase “Tout fonctionne parfaitement” s’afficher dans votre navigateur.

    Explications

    notre serveur et notre client se trouvent sur la même machine, avec le “localhost”, on indique au navigateur que le serveur web se trouve sur le même ordinateur que lui (on parle de machine locale). La barre d’adresse doit être renseignée avec l’adresse du serveur web: http://127.0.0.1:5000 ou bien http://localhost:5000

    En exécutant le programme Python ci-dessus, le framework Flask a lancé un serveur web. Ce serveur web attend des requêtes HTTP sur le port 5000. En ouvrant un navigateur web et en tapant “localhost:5000”, nous faisons une requête HTTP.

    Cette requête demande au serveur de lui retourner la ressource située à la racine du site Web. Le serveur web fourni avec Flask répond à cette requête HTTP en envoyant une page web (une vue) contenant uniquement <p>Tout fonctionne parfaitement</p>. C’est ce qui est retourné par la fonction index et le groupe de lignes:

    @app.route('/')
    def form():
      return "<p>Tout fonctionne parfaitement</p>"

    Dans la console de l’IDE python, nous voyons ainsi les requêtes et les éventuelles erreurs. C’est un bon moyen de visualiser les requêtes vers le serveur.

    Par exemple lorsque vous avez ouvert le navigateur à l’adresse 127.0.0.1:5000/ vous avez eu une ligne qui est apparu dans la console :

    127.0.0.1 - - [27/Feb/2025] "GET / HTTP/1.1" 200 -

    Voir le chapitre sur les protocoles HTTP pour plus d’explications.

    Ajouter la page de formulaire

    Dans le dossier templates, vous allez créer la page de formulaire form.html

    <!doctype html>
    <html lang="fr">
        <head>
            <meta charset="utf-8">
            <title>Le formulaire</title>
        </head>
        <body>
            <form action="http://localhost:5000/result" method="post">
                    <label>Nom</label> : <input type="text" name="nom" />
                    <label>Prénom</label> : <input type="text" name="prenom" />
                    <input type="submit" value="Envoyer" />
            </form>
        </body>
    </html>

    Celui-ci contiendra les éléments input de type text et nommés nom et prenom, ainsi qu’un bouton pour envoyer les données du formulaire.

    Le formulaire utilisera la méthode POST pour envoyer les données. Celles-ci vont parvenir à la page result.

    La page result.html

    Saisir le script HTML (notepad ++) suivant dans le fichier result.html du dossier templates:

    <!doctype html>
    <html lang="fr">
        <head>
            <meta charset="utf-8">
            <title>Résultat</title>
        </head>
        <body>
            <p>Bonjour {{prenom}} {{nom}}, j'espère que vous allez bien.</p>
        </body>
    </html>

    Cette requête POST sera envoyée à l’URL http://localhost:5000/result (voir l’attribut “action”). Les données saisies dans le formulaire seront envoyées au serveur par l’intermédiaire de cette requête.

    En réponse à la requête POST, le serveur renvoie une page HTML créée à partir du template resultat.html et des paramètres nom et prenom.

    Vous remarquerez que cette page contient des éléments d’un autre langage: {{prenom}} {{nom}}. Il s’agit d’instructions en Jinja2, un langage serveur comme PHP. Ce langage est executé côté serveur et il génère des bouts de script HTML AVANT que la page ne soit retournée au client.

    Ici, ce seront les contenus de variables qui remplacent {{prenom}} {{nom}} dans le script HTML.

    Fichier main.py

    Modifiez le fichier main.py comme suit :

    from flask import Flask, render_template, request
    
    app = Flask(__name__)
    
    @app.route('/')
    def form():
      return render_template('form.html')
    
    @app.route('/result',methods = ['POST'])
    def result():
      result = request.form
      n = result['nom']
      p = result['prenom']
      return render_template("result.html", nom=n, prenom=p)
    
    app.run(debug=True)

    Observez comment la fonction result va ouvrir la page result.html tout en passant les variables nom et prenom, par la méthode POST.

    Observez également la ligne précédent la definition de la fonction result: celle-ci contient un décorateur, @app.route('/result'... sur l’objet app de la librairie flask qui précise le chemin vers le fichier à ouvrir: /result.html

    moniteur reseau

    méthode POST

    Ouvrir le moniteur reseau. Utiliser la page de formulaire, envoyer les donées. Dans le moniteur, cliquer sur l’onglet header.

    • Observer l’URL de la requête client. Celle-ci comporte-t-elle des paramètres query?
    • Observer le champ formulaire: contient-il l’information des données transmises?
    moniteur reseau (Chrome)

    Exemple de moniteur reseau (Chrome)

    méthode GET

    On peut modifier la méthode HTTP utilisée (POST) par la méthode GET. Cela modifie le traitement des données (python)

    voir explications ici

    Modifier le projet de la manière suivante:

    • Dans “form.html”, la méthode POST sera remplacée par la méthode GET
    • Dans le fichier “main.py” remplacer POST par GET, et utiliser request.args à la place de request.form:
    @app.route('/result',methods = ['GET'])
    def result():
      result = request.args
      n = result['nom']
      p = result['prenom']
      return render_template("result.html", nom=n, prenom=p)

    Ouvrir le moniteur reseau et recommencer l’opération (transmettre les données par le formulaire):

    • Observer l’URL de la requête client. Celle-ci comporte-t-elle des paramètres query?
    • Observer le champ Query String parameters: contient-il l’information des données transmises?

    Prolongements possibles

    Ajouter des pages statiques

    Vous pouvez ajouter des pages dans le dossier templates.

    Pour des pages statiques, le script contiendra les instructions en HTML que vous connaissez. Les pages peuvent être liées par des liens. Exprimez les liens à partir de la racine / du site.

    Exemple: <a href="/">Lien</a> dirigera vers la page d’accueil du site.

    Il faudra ajouter une vue vers chacune des nouvelles pages depuis le fichier main.py. Par exemple, supposons que vous avez créé une page test.html dans le dossier templates. Ajouter alors les lignes suivantes dans le fichier main.py:

    @app.route("/test")
    def test():
        return render_template("test.html")

    La page est alors accessible depuis l’adresse http://localhost:5000/test, ou bien http://127.0.0.1:5000/test

    Traitement des valeurs du formulaire

    C’est au niveau des lignes suivantes que l’on récupère les informations du formulaire:

      n = result['nom']
      p = result['prenom']

    Il est possible des diriger vers un page différente selon la valeur des informations. On peut imaginer que l’administrateur du site va ouvrir une page différente:

      if n = 'admin':
        return render_template("admin.html")
      else:
        return render_template("result.html", nom=n, prenom=p)

    Ajouter une feuille de style

    Pour la séance de TP, il est recommandé d’ajouter les instructions CSS directement dans le fichier HTML, avec les balises <script> (plus facile). Mais dans une démarche de projet, on peut mettre le code css dans un fichier externe.

    • Créer un nouveau dossier, appelé static à la racine du dossier du projet. L’arborescence ressemble alors à:
    Documents/serveur_form
    /
    |- main.py
    |- templates/ 
        |- form.html
        |- result.html
    |- static/
        |- style.css
    • Dans le dossier static à la racine du projet: ajouter votre feuille de style avec le nom style.css.
    • Dans le debut du fichier main.py, ajouter l’import de url_for avec:
    from flask import url_for
    • Dans le fichier form.html, entre les balises <head> et </head>, ajouter:
    <link rel="stylesheet" type="text/css" href="{{url_for('static', filename='style.css')}}">

    Publiez votre site sur internet

    Publiez votre projet en ligne, sur Pythonanywhere.com

    • modifier la dernière ligne, app.run(debug=True) du fichier main.py par:
    if __name__ == '__main__':
        app.run()

    Projets

    Liens

    Sous-sections de TP

    projet bases en python

    Rire aléatoire

    La fonction random de la bibliothèque random produit un nombre aleatoire entre 0 et 1.

    > from random import random
    > random()
    
    0.8324575544825609

    On peut egalement demander un entier aleatoire entre 0 et 100 avec la fonction int:

    > int(100*random())
    
    62
    1. Ecrire un programme qui affiche de manière aléatoire la chaine de phonèmes “Ke”, “KeKe”, “KeKeKe” ou “KeKeKeKe”, …, avec “Ke” répété un nombre aléatoire de fois, entre 1 et 10.
    2. On veut maintenant que le programme affiche un texte aléatoire pouvant aussi comporter des séquences de “Ki”, “Di”, “Bi” comme par exemple: “KeKiDiBiBi”. La séquence devra avoir une longueur inférieure ou egale à 10 phonèmes et pourra comporter des repetitions.
    3. Programmer une fonction texte_aleatoire qui prend en paramètres les 4 phonèmes son1, ‘son2’, son3, son4. La fonction retourne un texte aleatoire de 10 sons maximum. Lors de l’appel de cette fonction avec texte_aleatoire("Ke","Ki","Di","Bi"), cette fonction pourrait retourner par exemple : “KeKiDiBiBi”

    Calendrier

    1. Ecrire un programme qui indique si une année a est bissextile. Une année est bissextile si elle est divisible par 4.

    2. Compléter le programme pour calculer le nombre de jours du mois m. m étant un entier compris entre 1 et 12. De janvier à juillet, les mois impairs ont 31 jours, les autres 30. Sauf le mois de fevrier a 29 ou 28 selon que l’année est bissextile ou non. Pour les autres mois, du mois d’aout à décembre c’est l’inverse (31 jours pour les m pairs).

    3. Ecrire une fonction jour_semaine qui détermine le jour de la semaine à une date donnée. On représente les jours par les nombres 0 = lundi, 1 = mardi, … 6 = dimanche.

    def jour_semaine(jour,mois,annee,jour0):
      """retourne le jour de la semaine à une 
      date donnée. jour0 est le code du premier
      jour de l'année"""

    4. Vérifier que le 14 juillet 2022 tombe un jeudi.

    Fonction sin

    1. Ecrire un programme qui utilise une boucle pour afficher les valeurs de la fonction sin pour x entre 0 et π
    On découpera l’intervale [0; π] de façon à afficher 15 valeurs de sin(x).
    Pour utiliser la fonction sin, il faudra l’importer avec la librairie math:

    Exemple d’import de la fonction sin et de la constante PI en console:

    > from math import sin,pi
    > sin(pi/2)
    
    1.0

    Exemple de valeurs obtenue pour sin(x), où x est dans [0; π]

    0.0
    0.20791169081775931
    0.40673664307580015
    0.5877852522924731
    0.7431448254773941
    0.8660254037844386
    0.9510565162951535
    0.9945218953682733
    0.9945218953682734
    0.9510565162951536
    0.8660254037844388
    0.7431448254773945
    0.5877852522924732
    0.40673664307580004
    0.2079116908177593
    5.66553889764798e-16

    2. Pour afficher le graphe de la fonction sin, on peut remplacer chaque valeur calculée précédement par une barre horizontale de longueur proportionnelle à sa valeur.
    On pourra par exemple multiplier le résultat de sin(x) par 30, et utiliser la fonction int pour transformer le nombre en entier, afin d’afficher un nombre de barres entre 0 et 30: int(30 * sin(x))
    Utiliser le programme pour afficher un graphique qui aura l’allure suivante:

    =====
    ===========
    ================
    =====================
    ========================
    ===========================
    ============================
    ============================
    ===========================
    ========================
    =====================
    ================
    ===========
    =====

    3. (difficile) Modifier le programme pour afficher maintenant la courbe entière de sin sur une période entière, c’est à dire pour x compris dans l’intervale [0, 2π]

                                  ======
                                  ============
                                  =================
                                  ======================
                                  =========================
                                  ============================
                                  =============================
                                  =============================
                                  ============================
                                  =========================
                                  ======================
                                  =================
                                  ============
                                  ======
                                  
                            ======
                      ============
                 =================
            ======================
         =========================
      ============================
     =============================
     =============================
      ============================
         =========================
            ======================
                 =================
                      ============
                            ======

    Jeu de hasard

    1. Ecrire un programme qui, étant donné un nombre entre 2 et 12, affiche toutes les combinaisons possibles permettant d’obtenir ce nombre avec 2 dés.

    Par exemple, pour obtenir 7, il pourrait afficher:

    '1 ET 6 , 2 ET 5 , 3 ET 4 , 4 ET 3 , 5 ET 2 , 6 ET 1 , '

    Aide: Pour faire une boucle bornée, avec un variant qui va de 1 à 6, on peut faire:

    for i in range(1,7):
      ...

    2. Etendre ce programme pour afficher, pour chaque nombre entre 2 et 12, toutes les combinaisons possibles permettant d’obtenir ce nombre avec les 2 dés.

    Par exemple:

    Pour obtenir 2, on peut faire 1 ET 1 , 
    Pour obtenir 3, on peut faire 1 ET 2 , 2 ET 1 , 
    Pour obtenir 4, on peut faire 1 ET 3 , 2 ET 2 , 3 ET 1 , 
    Pour obtenir 5, on peut faire 1 ET 4 , 2 ET 3 , 3 ET 2 , 4 ET 1 , 
    Pour obtenir 6, on peut faire 1 ET 5 , 2 ET 4 , 3 ET 3 , 4 ET 2 , 5 ET 1 , 
    Pour obtenir 7, on peut faire 1 ET 6 , 2 ET 5 , 3 ET 4 , 4 ET 3 , 5 ET 2 , 6 ET 1 , 
    Pour obtenir 8, on peut faire 2 ET 6 , 3 ET 5 , 4 ET 4 , 5 ET 3 , 6 ET 2 , 
    Pour obtenir 9, on peut faire 3 ET 6 , 4 ET 5 , 5 ET 4 , 6 ET 3 , 
    Pour obtenir 10, on peut faire 4 ET 6 , 5 ET 5 , 6 ET 4 , 
    Pour obtenir 11, on peut faire 5 ET 6 , 6 ET 5 , 
    Pour obtenir 12, on peut faire 6 ET 6 ,

    3. Modifier le programme pour faire la même chose avec 3 dés.

    exos tableaux listes python

    Partie 1 : Tableaux 1D - Accès par indice

    Exercice 1.1 : Gestion d’un inventaire de jeu vidéo

    Vous développez un jeu de rôle où le personnage possède un inventaire de 10 emplacements. Chaque emplacement contient un objet représenté par une chaîne de caractères.

    inventaire = ["épée", "potion", "bouclier", "vide", "clé", "vide", "arc", "carte", "vide", "torche"]

    Exemple 1 : Accéder à un élément

    # Pour afficher l'objet à l'indice 2
    print(inventaire[2])  # Affiche : bouclier

    Exemple 2 : Modifier un élément

    # Pour remplacer l'objet à l'indice 3
    inventaire[3] = "diamant"
    print(inventaire[3])  # Affiche : diamant

    Exemple 3 : Échanger deux éléments

    # Pour échanger les éléments aux indices 1 et 5
    temp = inventaire[1]
    inventaire[1] = inventaire[5]
    inventaire[5] = temp

    Questions :

    1. Affichez l’objet situé à l’emplacement 4 de l’inventaire.
    2. Le joueur ramasse un “parchemin”. Remplacez le premier emplacement “vide” par “parchemin”.
    3. Le joueur utilise sa potion (indice 1). Remplacez-la par “vide”.
    4. Échangez les objets aux emplacements 0 et 6 (épée et arc).
    5. Créer une fonction echange qui prend une liste L ainsi que 2 indices i et j pour paramètres, et qui modifie la liste L en permutant les objets aux rangs i et j. Cette fonction n’aura pas de valeur de retour.
    6. Ecrire l’instruction qui échange les objets aux emplacements 0 et 6, mais cette fois-ci, en utilisant la fonction echange.

    Exercice 1.2 : Thermomètre intelligent

    Un thermomètre enregistre les températures de chaque heure de la journée (24 valeurs).

    temperatures = [12, 11, 10, 10, 9, 9, 11, 14, 17, 20, 23, 25, 27, 28, 27, 25, 22, 19, 17, 15, 14, 13, 13, 12]

    Exemple : Calculer un écart

    # Pour calculer l'écart entre deux températures
    ecart = temperatures[10] - temperatures[3]
    print("L'écart est de", ecart, "degrés")

    Exemple : Augmenter une valeur

    # Pour augmenter de 3 degrés la température à l'indice 5
    temperatures[5] = temperatures[5] + 3
    # ou plus court :
    temperatures[5] += 3

    Questions :

    1. Affichez la température à 14h (indice 14).
    2. Une erreur de capteur s’est produite à 8h. Modifiez la valeur à l’indice 8 pour la remplacer par 16.
    3. Pourrait-on utiliser la fonction echange? Si oui, écrire l’instruction correspondante.
    4. Calculez l’écart entre la température maximale (indice 13) et minimale (indice 5).
    5. Augmentez de 2 degrés la température de minuit (indice 0).

    Partie 2 : Tableaux 1D - Parcours par élément et par indice

    Exercice 2.1 : Analyse d’une partie de Scrabble

    Un joueur de Scrabble possède les lettres suivantes dans son chevalet :

    chevalet = ['A', 'E', 'R', 'T', 'I', 'N', 'S']

    Exemple 1: Parcours par élément

    # Afficher chaque lettre
    for lettre in chevalet:
        print(lettre)

    Exemple 2: Compter des éléments

    # Compter les 'E' dans le chevalet
    compteur = 0
    for lettre in chevalet:
        if lettre == 'E':
            compteur += 1
    print("Il y a", compteur, "lettre E")

    Exemple 3: Vérifier une condition

    # Vérifier si le chevalet contient un 'A'
    if 'A' in chevalet:
        print("Il y a un A !")
    else:
        print("Pas de A")

    Questions avec parcours par élément :

    1. Affichez toutes les lettres du chevalet, une par ligne, en utilisant une boucle for lettre in chevalet.
    2. Comptez combien de voyelles (A, E, I, O, U, Y) se trouvent dans le chevalet.
    3. Affichez “BINGO!” si le chevalet contient au moins une lettre ‘S’, sinon affichez “Pas de S”.
    4. Ecrire une fonction compte qui prend une liste L ainsi qu’une lettre V en paramètre, et qui retourne le nombre de fois où cette lettre est présente dans la liste.
    5. Ecrire l’instruction qui appelle cette fonction pour déterminer le nombre de E dans le chevalet ['A', 'E', 'R', 'T', 'I', 'N', 'S']

    Exercice 2.2: Parcours par indice

    Exemple 1: afficher l’indice et l’élément

    # Afficher chaque lettre avec sa position
    for i in range(len(chevalet)):
        print("Position", i, ":", chevalet[i])

    Exemple 2: Modifier en parcourant

    # Remplacer tous les 'A' par des '*'
    for i in range(len(chevalet)):
        if chevalet[i] == 'A':
            chevalet[i] = '*'

    Exemple 3: Créer un nouveau tableau

    # Créer un tableau avec uniquement les voyelles
    voyelles_trouvees = []
    for i in range(len(chevalet)):
        if chevalet[i] in ['A', 'E', 'I', 'O', 'U', 'Y']:
            voyelles_trouvees.append(chevalet[i])
    print(voyelles_trouvees)

    Questions avec parcours par indice :

    1. Affichez chaque lettre avec sa position : “Position 0 : A”, “Position 1 : E”, etc.
    2. Remplacez toutes les voyelles par des ‘*’ en parcourant le tableau par indice.
    3. Créez un nouveau tableau contenant uniquement les consonnes en utilisant les indices.

    Partie 3 : Tableaux 2D - Parcours par élément et par indice

    Exercice 3.1 : Grille de Morpion

    Parcours par élément

    Une grille de morpion est représentée par un tableau 2D de 3×3 :

    morpion = [
        ['X', 'O', 'X'],
        ['O', 'X', ' '],
        [' ', ' ', 'O']
    ]

    Exemple 1: afficher les éléments

    for ligne in morpion:
        for case in ligne:
            print(case, end=' ')
        print()  # retour à la ligne
    # Affiche toutes les valeurs ligne par ligne:
    X | O | X | 
    O | X |   | 
      |   | O |

    Exemple 2: Compter les éléments

    # Compter les 'X'
    compteur = 0
    for ligne in morpion:
        for case in ligne:
            if case == 'X':
                compteur += 1
    print("Nombre de X :", compteur)

    Questions:

    1. Affichez tous les ‘X’ de la grille, ligne par ligne en utilisant deux boucles for.
    2. Comptez le nombre de cases vides (contenant ’ ‘).
    3. Déterminez qui a le plus de coups joués (X ou O).

    parcours par indice :

    Exemple 1: Parcours par indice (tableau 2D)

    # Afficher la grille avec les indices
    for i in range(len(morpion)):
        for j in range(len(morpion[i])):
            print(morpion[i][j], end=' ')
        print()

    Exemple 2: Accéder à un élément précis

    # Afficher et modifier un élément
    print("Case [0][1] :", morpion[0][1])  # Affiche 'O'
    morpion[0][1] = 'X'  # Modifier la case

    Exemple 3: Vérifier une ligne

    # Vérifier si la ligne 0 contient trois symboles identiques
    ligne = morpion[0]
    if ligne[0] == ligne[1] == ligne[2] and ligne[0] != ' ':
        print("La ligne 0 est gagnante !")

    Questions:

    1. Le joueur O joue en position [1][2] (ligne 1, colonne 2). Ecrire l’instruction qui modifie la grille.
    2. Quelles sont les coordonnées morpion[i][j] pour chacune des cases? Dessinez sur votre cahier une matrice pour placer les coordonnées [i][j]dans chaque case..
    3. Ecrire les instructions qui verifient si la première ligne contient trois symboles identiques (condition de victoire).
    4. Ecrire une fonction ligne_X qui prend pour paramètre une matrice M comme la grille de morpion (3*3). M contient dans chaque case 'X', 'O', ou ''. Cette fonction retournera True si l’une des lignes est remplie avec trois 'X'.

    Exercice 3.2 : Grille de Sudoku (9×9)

    Voici une grille de Sudoku partiellement remplie :

    sudoku = [
        [5, 3, 0, 0, 7, 0, 0, 0, 0],
        [6, 0, 0, 1, 9, 5, 0, 0, 0],
        [0, 9, 8, 0, 0, 0, 0, 6, 0],
        [8, 0, 0, 0, 6, 0, 0, 0, 3],
        [4, 0, 0, 8, 0, 3, 0, 0, 1],
        [7, 0, 0, 0, 2, 0, 0, 0, 6],
        [0, 6, 0, 0, 0, 0, 2, 8, 0],
        [0, 0, 0, 4, 1, 9, 0, 0, 5],
        [0, 0, 0, 0, 8, 0, 0, 7, 9]
    ]

    Les cases vides sont représentées par 0.

    Exemple : Compter les cases vides

    # Compter les 0 dans toute la grille
    compteur = 0
    for i in range(len(sudoku)):
        for j in range(len(sudoku[i])):
            if sudoku[i][j] == 0:
                compteur += 1
    print("Nombre de cases vides :", compteur)

    Exemple : Afficher une ligne

    # Afficher la ligne 0
    for j in range(len(sudoku[0])):
        print(sudoku[0][j], end=' ')
    print()

    Exemple : Afficher une colonne

    # Afficher la colonne 2
    for i in range(len(sudoku)):
        print(sudoku[i][2], end=' ')
    print()

    Exemple : Modifier une case

    # Remplacer le 0 en position [0][2] par 4
    sudoku[0][2] = 4
    print("Nouvelle valeur :", sudoku[0][2])

    Exemple : Extraire un bloc 3×3

    # Extraire le bloc en haut à gauche (lignes 0-2, colonnes 0-2)
    bloc = []
    for i in range(0, 3):  # lignes 0, 1, 2
        ligne_bloc = []
        for j in range(0, 3):  # colonnes 0, 1, 2
            ligne_bloc.append(sudoku[i][j])
        bloc.append(ligne_bloc)
    print(bloc)

    Exemple : Vérifier les doublons dans une ligne

    # Vérifier si la ligne 1 contient des doublons (sans compter les 0)
    ligne = sudoku[1]
    nombres = []
    for valeur in ligne:
        if valeur != 0:
            if valeur in nombres:
                print("Doublon détecté !")
            else:
                nombres.append(valeur)

    Questions avec parcours par indice :

    1. Comptez le nombre de cases vides (valeur 0) dans toute la grille.
    2. Affichez tous les chiffres de la première ligne (ligne d’indice 0).
    3. Affichez tous les chiffres de la cinquième colonne (colonne d’indice 4).
    4. Remplacez le 0 en position [0][2] par le chiffre 4.
    5. Ecrire une fonction doublons, qui prend en paramètre une grille de sudoku G, ainsi qu’un numero de ligne i, et qui retourne un booléen True/False. selon si la ligne i contient des doublons. (sans compter les 0).
    6. Appeler la fonction doublons pour vérifier si la première ligne contient des doublons.
    7. Créez une fonction bloc qui extrait l’un des 9 blocs 3×3, n’importe où dans la grille. (par exemple, le bloc en haut à gauche : lignes 0-2, colonnes 0-2), à partir des indices i,j de départ (coin supérieur gauche du bloc).

    Conseils généraux

    • Testez votre code progressivement : ne cherchez pas à tout résoudre d’un coup.
    • Utilisez des fonctions pour organiser votre code et le rendre réutilisable.
    • Affichez des résultats intermédiaires avec print() pour vérifier votre logique.
    • N’oubliez pas : les indices commencent à 0 en Python !

    COURS python sur les tableaux

    Suite en projet:

    Liste des projets

    Jeu du Morpion

    Projet 1: jeu du Morpion

    Le jeu du Morpion est un jeu de réflexion se pratiquant à deux joueurs au tour par tour et dont le but est de créer le premier un alignement sur une grille (3x3).

    Vous allez programmer le jeu du Morpion contre l’ordinateur. L’ordinateur devra repondre à chacun des coups du joueur et, si possible, remporter la partie.

    Pour traiter ce projet, il est fortement recommandé de bien maitriser l’exercice 3.1, vues dans le TD sur les tableaux.

    On donne la fonction d’affichage de la grille:

    def affiche(grille):
        for ligne in grille:
            for case in ligne:
                print(case, '|', end=' ')
            print()

    Exemple: Afficher la grille

    morpion = [
        ['X', ' ', ' '],
        ['O', 'X', ' '],
        [' ', 'O', ' ']
    ]
    
    affiche(morpion)
    
    # affiche
    X |   |   | 
    O | X |   | 
      | O |   |

    Afin d’analyser la partie, et prevoir les prochains coups à jouer, l’ordinateur utilisera les fonctions suivantes, que vous devrez programmer:

    • compteur
    • victoire
    • cherche_car

    Prévoir ensuite le prochain coup à partir des informations fournies, et créez un jeu, où l’ordinateur ne sera jamais perdant.

    Compteur du nombre de caractères identiques

    Lire et tester le programme suivant:

    Exemple: Compte le nombre de X dans une ligne, colonne ou diagonale

    # Vérifier si la ligne 0 contient trois symboles identiques
    liste_X = [0,0,0]
    liste_Y = [0,1,2]
    compteur = 0
    for i in range(len(liste_X)):
        x = liste_X[i]
        y = liste_Y[i]
        if morpion[x][y] == 'X':
            compteur +=1
    print("il y a ", compteur, "cases X dans la ligne 0")

    Dans la boucle for, l’indice i varie de 0 à 2.

    Pour i=0, x a pour valeur liste_X[0] -> 0 et y a pour valeur liste_Y[0] -> 0. Le couple x,y vaut alors 0,0.

    On utilise ces coordonnées pour relever le symbole de la case morpion[0][0]. C’est un X. On augmente alors le compteur d’une unité (on compte les X).

    On continue dans la boucle for avec les cases 0,1 puis 0,2.

    Etape 1: Créer une fonction compteur qui prend une grille, un caractère car, une liste liste_X et une liste liste_Y en paramètres. Cette fonction devra retourner le nombre de fois que ce caractère car apparait.

    Exemple: utiliser la fonction compteur

    # Etape 1
    morpion = [
        ['X', 'O', 'X'],
        ['O', 'X', ' '],
        [' ', 'O', 'O']
    ]
    
    def compteur(grille,car,liste_X,liste_Y):
    	c = 0
    	for i in range(len(liste_X)):
    			# à completer 
    			x = ...
    			y = ...
    			if grille[][]...
    				c = c + ...
    		
    	return c
    
    compteur(morpion,'X',[0,0,0],[0,1,2])
    # retourne:
    2
    premiere étape de la boucle for

    premiere étape de la boucle for

    La fonction retourne 2: à la premiere ligne, il y a bien 2 caractères ‘X’.

    Utilisez votre fonction

    Etape 2: utilisez votre fonction pour déterminer le nombre de ‘X’ dans chacune des lignes, dans chacune des colonnes, et dans chacune des diagonales (8 appels de la fonction). Placer chaque valeur dans une liste L, puis afficher celle-ci.

    # Etape 2
    L = []
    L.append(compteur(morpion,'X',[0,0,0],[0,1,2]))
    L.append(compteur(...
    ...
    print(L)

    Victoire

    Etape 3: Créer une fonction victoire, qui prend une grille de morpion en paramètre, ainsi qu’un caractère car (qui vaut X ou O), et vérifie si la condition de victoire est réalisée pour le joueur X ou O. La fonction retournera un booléen True/False.

    Exemple: Victoire des X

    # Etape 3
    morpion = [
        ['X', 'O', 'X'],
        ['O', 'X', ' '],
        [' ', 'O', 'X']
    ]
    
    def victoire(grille,car):
    	b1 = compteur(grille, car, [0,0,0],[0,1,2])
    	b2 = compteur(grille, car, [1,1,1],[0,1,2])
    	# a completer
    	b8 = compteur(grille, ...)
    	return b1 == 3 or ...
    
    victoire(morpion,'X')
    # retourne:
    True
    victoire(morpion,'O')
    # retourne:
    False

    Interface joueurs

    Etape 4: Vous allez maintenant programmer l’interface joueurs, en demandant alternativement, à chacun d’entre eux les coordonnées x,y pour placer son pion: ‘X’ puis ‘O’, puis ‘X’, puis ‘O’, …

    # Etape 4
    Fin_de_partie = False
    while not victoire(morpion,'X') and not victoire(morpion,'O') and not Fin_de_partie:
        afficher(morpion)
        print('Joueur X:')
        x = int(input("jouer à la ligne (0,1,2), 3=Fin: "))
        y = int(..)
        ...

    Puis…

    • Si le joueur ‘X’ n’est pas vainqueur, demander à l’adversaire où il veut jouer.
    • Le joueur ‘O’ est-il gagnant?
    • Afficher la grille modifiée après ce tour de jeu
    • Recommencer s’il n’y a pas de vainqueur.

    Phase 2: Comment jouer contre l’ordinateur?

    Dans cette phase du projet, nous allons remplacer les choix du joueur ‘O’ par ceux de l’ordinateur. Ce sera lui qui essaiera de vous bloquer lorsque vous avez deux pions ‘X’ alignés, et que vous risquez de gagner à la partie suivante.

    Nous aurons besoin de 2 nouvelles fonctions:

    • cherche_car: fonction qui recherche la première case vide dans un ensemble de cases du morpion, et retourne les coordonnées x,y de cette case
    • jeu_de_defense: qui retourne les coordonnées x,y de la case qui doit bloquer le joueur (si celui-ci a une ligne avec deux ‘X’ et peut gagner au prochain tour)

    Detection case vide

    Etape 1: Ecrire une fonction cherche_car(grille,car,liste_X,liste_Y) qui verifie si les cases de coordonnées (liste_X[0], liste_Y[0]), (liste_X[1], liste_Y[1]), (liste_X[2], liste_Y[2]) contiennent au moins un symbole car, et retourne les coordonnées de la première case contenant le caractère car.

    Exemple: recherche d’un espace ’ ’ dans la ligne 2

    # Etape 1
    morpion = [
        ['X', 'O', 'X'],
        ['O', 'X', ' '],
        [' ', 'O', 'O']
    ]
    
    def cherche_car(grille,car,liste_X,liste_Y):
        for i in range(len(liste_X)):
            x = liste_X[..
            y = liste_Y[..
            if grille[..][..] == ...:
                return x,y
    
    cherche_car(morpion,' ',[2,2,2],[0,1,2])
    # retourne:
    (2,0)

    La fonction retourne (2,0), car à la case de coordonnées [2][0], il y a un symbole ' '.

    recherche d'un caractère espace ' ' dans la dernière ligne

    recherche d'un caractère espace ' ' dans la dernière ligne

    Exemple: recherche du premier espace ’ ’ dans tout la grille

    morpion = [
        ['X', 'O', 'X'],
        ['O', 'X', ' '],
        [' ', 'O', 'O']
    ]
    
    cherche_car(grille,' ',[0,0,0,1,1,1,2,2,2],
                           [0,1,2,0,1,2,0,1,2])
    (1,2)

    Lorsque l’on recherche un caractère dans TOUTE la grille, il y a 9 coordonnées à renseigner pour chacune des listes.

    Etape 2: créer une fonction jeu_de_defense, qui prend pour paramètre grille, et car_attaquant, qui vaudra ‘X’ ou ‘O’.

    Cette fonction va permettre de programmer le jeu complet, pour jouer contre l’ordinateur.

    Pour chacune des lignes, puis pour chacune des colonnes, et enfin chaque diagonale:

    Si la ligne contient 2 caractères ‘X’ (fonction compteur, et que la ligne contient un espace (cherche_car ne retourne pas None), alors retourner les coordonnées x,y retournées par la fonction cherche_car.

    Sinon, retourner None

    def jeu_de_defense(grille,car_attaquant):
    
        if compteur(grille,car_attaquant,
                    [0,0,0],[0,1,2]) == 2 and cherche_car(grille,' ',
                    [0,0,0],[0,1,2]) != None:
            # jouer dans une case vide de la ligne 0
            jouer_case = cherche_car(grille,' ',
                    [0,0,0],[0,1,2])
        elif compteur(grille,car_attaquant,
                    [1,1,1],[0,1,2]) == 2 and cherche_car(grille,' ',
                    [1,1,1],[0,1,2]) != None:
            # jouer dans une case vide de la ligne 1
            jouer_case = cherche_car(grille,' ',
                    [1,1,1],[0,1,2])
        elif (...)
        (...)
    
        elif compteur(grille,car_attaquant,
                    [0,1,2],[0,0,0]) == 2 and cherche_car(grille,' ',
                    [0,1,2],[0,0,0]) != None:
            # jouer dans une case vide de la colonne 0
            jouer_case = cherche_car(grille,' ',
                    [0,1,2],[0,0,0])
        (...)
    	else:
    		jouer_case = None
        return jouer_case

    Pour appeler la fonction, et bloquer l’adversaire ‘X’, faire:

    if jeu_de_defense(morpion,'X') == None:
        x,y = cherche_car(grille,' ',[0,0,0,1,1,1,2,2,2],
                                      [0,1,2,0,1,2,0,1,2])
    else: 
        x,y = jeu_de_defense(morpion,'X')

    Ainsi, si aucune des lignes, colonnes, diagonale ne correspond ne contient deux caratères ‘X’ alignés, retourner la premiers case vide trouvée dans la grille: ce sera l’emplacement où l’ordinateur ‘O’ peut jouer.

    L’ordinateur peut alors jouer:

    def jouer(grille,car,x,y):
        grille[x][y] = car
    
    jouer(morpion,'O',x,y)
    affiche(morpion)

    Jouer contre l’ordinateur

    Pour cette dernière phase du projet, vous pourrez télécharger le script python contenant toutes les fonctions nécéssaires: telecharger

    Pour élaborer une stratégie plus avancée de l’ordinateur, on pourra consulter la page dédiée: site tictactoe.com

    site TICTACTOEFREE.COM

    site TICTACTOEFREE.COM

    • pour jouer contre l’ORDINATEUR. (utiliser la fonction jeu_de_defense pour prevoir la case dans laquelle il devra jouer).
    • Organisez au mieux votre script. Commentez vos fonctions.

    Pour les élèves de Terminale:

    • Prévoir et anticiper toutes les erreurs possibles de saisie du joueur, tous les defauts possibles qui peuvent survenir dans la partie (plus de O que de X, erreurs avec les coordonnées saisies, terminaison de la boucle while, …). On pourra ajouter des structures conditionnelles supplémentaires, ou bien des tests d’assertion, ou autres mécanismes. (try.. except, raise,…): Voir cours sur la mise au poin d’un programme: python avancé
    • Utiliser une structure de données Pile pour permettre un retour en arriere (le joueur efface ses coups précédents).

    SNT

    Agenda

    Semaine de la rentrée: 01/09/2026

    • Présentation de la matière: pdf
    • TD en classe: Informatique et données (Calculer, automatiser, prédire,…) Lien
    • Exercices. Temps d’execution et performance d’une machine: pdf

    Semaine du 08/09/26

    • TP1 enquête de police: Lien
    • Cours sur la collecte des données: Lien

    Semaine du 15/09/26

    • Cours sur la collecte des données: Lien
    • Document à remplir: pdf

    Semaine du 21/09/26 et du 05/10/26

    • Realiser un questionnaire d’enquête: pdf
    • Cours sur le modèle économique: Lien
    • Exercices bilans sur la collecte des DCP: pdf

    Semaine du 12/10/26

    • Cours sur le RGPD: pdf
    • Représentation des données en table, traitement, protection des données personnelles et enquêtes
    • Projet de fin de séquence: créer une campagne de sensibilisation (affiche + post type Instagram/TikTok fictif) sur un enjeu réel : cyberharcèlement, désinformation, addiction au scroll, ou effet de bulle de filtre. Justifier le choix (ciblage, algorithme de recommandation, mécanismes d’engagement) en s’appuyant sur ce qui a été vu en cours. Variante plus technique : concevoir le cahier des charges d’un “réseau social idéal pour lycéens” en explicitant les paramètres de confidentialité et leurs compromis. reseaux sociaux identité numérique, modélisation des liens d’amitié, aspects economiques et sociaux
    • Projet de fin de séquence: créer un mini-site HTML/CSS de 3-4 pages sur un sujet de son choix, avec navigation, liens hypertexte, structuration correcte (balises sémantiques). une “enquête” sur un site réel (certificat HTTPS, mentions légales, cookies) restituée sous forme de fiche d’analyse. le web definition du web, navigation entre pages, moteur de recherche, URL modele client serveur modele client serveur et URL, securite et confidentialite HTML langage HTML, balises introduction à CSS declaration css, selecteur, propriete, valeur, heritage, arbre du DOM
    • Projet de fin de chapitre: Réaliser un traceroute/ping vers plusieurs sites (France, Europe, autre continent), relèver les adresses IP et temps de latence, puis produire un schéma annoté expliquant le trajet des paquets (routeurs, protocole TCP/IP, adressage). généralités usage d’internet, les formes de communication reseau local et reseau internet machines et architecture reseau, liaisons entre machines, adresses MAC et adresses IP circulation des données protocoles, routage, modele client serveur, DNS, http et https, VPN TP simulation d’un réseau TP Filius, reseau a 2 machines et plus, adresses IP
    • Projet de fin de chapitre: conception d’un objet simple (arrosage automatique, alarme, feu tricolore) avec algorithme, capteurs et actionneurs identifiés. IOT robot, machine et ordinateur, chaine d’information et d’energie, objet connecté Programme informatique programmer un robot, algorithme et langage informatique Python Turtle dessiner en donnant des ordres
    • Projet de fin de chapitre: comparer les tailles de fichier selon la résolution et le format (JPEG vs PNG), et documenter la perte de qualité liée à la compression. stéganographie (retrouver le message caché dans une image) créer une affiche démontant une image retouchée/deepfake avec analyse technique (pixels, métadonnées). Photographie numérique appareil photographique numerique, codage, pixel, prise de vue Enjeux ethiques et societaux de l’image droit a l’image, propriete, fausses informations EXIF et données colorimetriques TP coloration, outil de prelevement de couleurs, code RGB des couleurs, et donnees EXIF, obtenue a partir d’una app en ligne TP pixel art TP python, tableaux, codage d’une image numerique, microbit
    • Projet de fin de chapitre: Organisation d’un rallye géolocalisé dans l’établissement. GPS services geolocalisation sur un smartphone, reglages, confidentialité, calcul d’itineraires geolocaliser methode d’echolocation, trilateralisation introduction aux graphes et internet modelisation d’une carte numerique par un graphe fonction de conversion TI83 utiliser les fonctions python pour convertir les unités des repères d’angle, version TI83 fonction de conversion android utiliser les fonctions python pour convertir les unités des repères d’angle, version tablette android

    Sous-sections de SNT

    Donnees structurees

    Projet de fin de chapitre: Enquêter sur les données de sondage: Lien

    Sous-sections de Donnees structurees

    codage des nombres

    modelisation

    Civilisations anciennes

    Le document suivant donne un aperçu des périodes d’existence d’anciennes civilisations.

    L’apparition des grandes civilisations commence alors que le néolithique prend fin. C’est l’usage de la metallurgie qui aura pour conséquence de structurer davantage la société, avec l’usage d’armes en métal par des soldats spécialisés. La protection des richesses accumulées par les producteurs est confiée à des guerriers professionnels. La société se hiérarchise: timeline

    IREM Lille

    Carte perforée. IREM Lille

    La naissance de l’écriture… et du nombre

    Dans les temps préhistoriques, les hommes ont eu besoin de recourir à une numération. Ils ont naturellement utilisé des artefacs pour compter (des objets, des os…). L’écriture n’existait pas.

    Le plus vieux vestige montrant cette activité date de 35 000 ans. Il s’agit d’un os qui a été utilisé comme baton de comptage.

    baton de comptage

    Le bâton d’Ishango (à gauche), exposé à l’Institut royal des sciences naturelles de Belgique

    (source: PourlaScience.fr)

    Que comptaient-ils exactement avec ce baton? Les proies tuées, le nombre d’individus de leur clan, …, il nous est impossible de le savoir.

    Pour certains peuple primitifs, la numération se limitait d’ailleurs à 3 : un, deux, trois, beaucoup…

    Au néolithique, la société devient sédentaire et se structure davantage. Alors l’homme éprouve un besoin plus urgent de dénombrer, et de calculer.

    A partir du VII millénaire avant JC : des vestiges de jetons en pierre montrent l’activité de compter. D’autres objets de comptage ont été utilisés, comme des petits jetons en argile (calculis) que l’on mettait dans une bourse:

    Il s’agissait d’une sphère d’argile creuse dans laquelle on insérait des calculis et sur laquelle on marquait le contenu et qu’on signait avec un sceau-cylindre.

    Bulle-enveloppe et ses jetons de comptabilité (Institute museum Chicago)

    Bulle-enveloppe et ses jetons de comptabilité (Institute museum Chicago)

    Comment ça se passe en pratique, le dénombrement ?

    Au quotidien, les hommes ont d’abord utilisé leurs doigts ou leur phalanges pour compter. Selon la méthode employée, ils ont alors compté en base 10 (10 doigts de la main), ou en base 20 (en incluant les doigts de pied), en base 12 (en utilisant les phalanges), ou en base 60.

    systeme de numération duodecimal (base 12)

    systeme de numération duodecimal (base 12)

    source: wikipedia, systeme duodecimal

    Et l’écriture des chiffres ?

    Au IV millénaire avant JC : On trouve les plus anciennes traces de chiffres écrits (Mésopotamiens1 et Egyptiens), gravés sur des supports en argile.

    Les symboles que l’on peut observer sur la photographie suivante sont des formes de clous ou des barres verticales |, des chevrons <.

    tablette en argile. 3000 ajc

    tablette en argile. 3000 ajc. Mésopotamie

    Les symboles des unités sont employés pour les chiffres de 1 à 9:

    Ceux des dizaines: de 10 à 50 (1 à 5 dizaines):

    Comment ces chiffres constituent-ils des nombres ?

    Les systèmes de numération antiques variaient d’une aire culturelle à l’autre :

    Pour chacun des systèmes de numération, la valeur d’un nombre est égale à la somme des symboles qui le composent. Ce sont des numérations dites additives.

    Base 10: Les Egyptiens2, pour écrire le chiffre 7, répétaient le symbole de l’unité | sept fois par exemple ( ||||||| ). lorsque ces symboles devaient être répétés dix fois, on remplaçait ces 10 symboles unitaires par un nouveau symbole correspondant à la dizaine.

    Il s’agit d’une numération en base 10 (numération décimale), mais différente de la notre: Un autre symbole correspond à la dizaine de dizaine, etc.

    tableau a remplir

    symboles utilisés par les egyptiens, de 1 à 1 million

    Base 60: Pour les Babylonniens3 cependant, cette numération ne permettait de compter que jusqu’à 59. Ils ont alors utilisé les mêmes chiffres pour dénombrer les soixantaines:

    $$71 = 1 \times 60 + 11 \times 1$$

    Ce qui s’écrira en notation babylonienne:

    $$| ~ >|$$
    equivalence base 60 vers decimale

    Equivalence entre la base 60 sumérienne et notre base décimale

    Toutes les civilisations n’ont pas adopté la numération décimale, ni les mêmes symboles pour compter :

    • Les Sumériens au proche-orient comptaient en base 60 (numération sexagésimale).
    • La base 12 (système duodécimal) était connue et utilisée par certaines populations (Moyen-Orient, Roumanie, Égypte, etc.)
    • En Eurasie, les peuples indo-européens utilisaient un système décimal mais avec des symboles alphabétiques, notamment par les signes I, V, X, L, C, D et M, appelés chiffres romains: voir article et exemples4
    symboles romains

    symboles romains

    Comment est apparu le ZERO ?

    Les Sumériens ont progressivement remplacé les petits objets en argile représentant les nombres par l’écriture sur des tablettes en argiles. Ils gravaient dessus avec un calame en roseau. Le comptage matériel est alors devenu un comptage conceptuel. Ainsi sont nés les plus vieux chiffres connus de l’histoire, et surtout, l’invention du ZERO.

    Sans l’écriture du zero, il peut y avoir une confusion dans la lecture. Le nombre suivant, écrit en notation babylonienne :

    $$| > |$$

    Celui-ci peut ainsi signifier:

    $$1 \times 60 + 11 \times 1 = 71$$

    mais aussi, selon la position supposée de l’espacement:

    $$11 \times 60 + 1 \times 1 = 661$$

    ou encore:

    $$11 \times 3600 + 0 \times 60 + 1 \times 1 = 39 601$$

    L’invention du ZERO implique que l’écriture du nombre va suivre la règle de la position des symboles : les dizaines sont écrites avec un symbole mis à la position des dizaines, les unités sont écrites avec un symbole mis à la position des unités. Et lorsque le nombre par exemple ne comporte pas de dizaine, on met un ZERO à la position du chiffre des dizaines.

    C’est la position du chiffre qui permet de savoir si celui-ci représente unité, dizaine ou centaine. C’est ce que l’on appelle la numération de POSITION.

    Ce signe signifiant RIEN, et appelé le ZERO sera décisif pour l’apparition de la science du calcul, l’arithmétique.

    Sans l’écriture du ZERO, l’usage des nombres ne permet pas de réaliser facilement des opérations. On ne peut pas facilement reporter des retenues depuis les unités vers les dizaines par exemple (base 10). Le zero va faciliter les opérations arithmétiques.

    Fondamentalement, ce sont les savants indiens qui vont faire évoluer le zéro vers le sens que nous lui reconnaissons aujourd’hui, à savoir d’un nombre entier non naturel, pair, ni premier, ni positif, ni négatif.

    video Futura Sciences

    video Futura Sciences : Les découvertes du zero

    Epoque médievale

    Le savoir circule à travers le monde de l’Extrême-Orient à l’Egypte, de la Méditerranée à l’lslande.

    Au IXe siècle, les Arabes emprunteront aux Indiens le zéro, le mot sunya devenant sifr. Ce ne sera finalement qu’au XIIe siècle que cette écriture arrivera en Occident, issue des « Ghubâr », les arabes occidentaux.

    Questions

    Numération Babylonienne3

    1. En vous aidant du documents suivant, traduire les inscriptions de la tablette sumérienne : compter le nombre d’animaux de chacune des espèces.
      tablette Babylonienne
    2. Combien de symboles différents utilisent les sumériens pour écrire les chiffres ?
    3. Ces symboles, sont-ils différents pour les unités, les soixantaines, et les soixantaines de soixantaines ?
    4. Comment les mésopotamiens (et Sumeriens) écrivaient-ils le nombre 1637 ?
    5. Expliquer en quoi on peut considérer que les sumériens utilisaient une numération de position ?

    Numération Egyptienne2

    C’est une numération de type additif.

    Les Égyptiens de l’Antiquité utilisaient des hiéroglyphes pour écrire leurs nombres. Ce système de hiéroglyphes est assez proche de notre système de numération décimale : chaque symbole possède une valeur (1,10,100,1 000…) et peut être écrit jusqu’à neuf fois.

    1. En étudiant les trois exemples donnés ci-dessous, retrouver la valeur des sept hiéroglyphes utilisés. (voir images)
    2. Comment les egyptiens écrivaient-ils le nombre 1637 ?
    3. Comparer les numérations Babylonienne et Egyptienne : laquelle des deux est une numération de position ? Justifiez.
    4. Les egyptiens, avaient-il une manière de représenter les fractions de 1 (par exemple 1/2)? Expliquer.

    exemple de numeration egyptienne

    exemples, numeration egyptienne

    tableau a remplir

    tableau a remplir

    Numération Maya5

    La numération maya est une numération de base vingt pratiquée dans la civilisation mésoaméricaine maya.

    Pour écrire les petits nombres, par exemple la durée d’une lunaison (c’est-à-dire les entiers 29 ou 30) ou les petits déplacements (dans l’almanach divinatoire de 260 jours), les Mayas disposaient d’une numération de type additif utilisant trois signes pour 1, 5 et 20 ; dans cette écriture : ‘20,9’ s’interprète 20 + 9. On trouve ainsi le nombre 62 écrit à l’aide de 3 signes « 20 » complétés de 2 points … (wikipedia).

    L’écriture d’un nombre se fait par empilement de chiffres. Chaque étage correspond à un poids 20 fois supérieur au poids de l’étage inférieur, à l’exception du passage du 2e au 3e étage où la multiplication n’est que de 18. Ainsi la valeur de l’étage le plus bas est multipliée par 1, du second étage par 20, du troisième étage par 20 × 18 = 360

    LeMonde Histoire

    LeMonde Histoire

    1. Les Mayas, utilisaient-ils l’écriture pour représenter les nombres? Si oui, sur quel support écrivaient-ils?
    2. S’agit-il d’une numération de position?
    3. Commenter le document ci-dessus et expliquer cette numération.

    Numération Romaine4

    1. Quels sont les symboles romains utilisés pour compter jusqu’à 2000?
    2. En quelle année, exprimée en chiffres romains, Jésus est-il né ?
    3. La numération romaine, peut-elle être considérée comme une numération de position?
    4. Comment les romains écrivaient-ils le nombre 1637 ?

    Numération Chinoise6

    1. S’agit-il d’une numération de position?
    2. Quels sont les symboles utilisés?
    3. Enoncer les principes d’une numération en base 10.
    4. Comment les chinois écrivent-ils le nombre 1637 (dans l’écriture dite normale? Y-a-t-il des similitudes avec l’écriture Japonnaise?
    5. Est-ce que cette numération facilite les opérations entre les nombres? Comment? Expliquer en utilisant le principe du boulier

    Voir exemples sur le monde-du-boulier.com

    Numération Indo-arabe7

    1. S’agit-il d’une numération de position?
    2. Quels sont les symboles utilisés? Comparer ceux utilisés par les indiens (Gurmukhi), les arabes (occidental/oriental), les européens.
    3. Enoncer les principes d’une numération en base 10.
    4. Comment les indiens écrivent-ils le nombre 1637 (dans l’écriture dite (Gurmukhi)?
    5. Est-ce que cette numération facilite les opérations entre les nombres? Comment? Expliquer en utilisant le principe du boulier

    Voir exemples sur le monde-du-boulier.com

    Numération binaire

    1. Quelle est la valeur de la base de la numération binaire?
    2. Sans effectuer de calcul, dire si le nombre binaire 10011001 est pair ou impair.
    3. Quelle est la valeur la plus élevée que l’on peut écrire avec 8 symboles, en notation binaire?
    4. Comment écrit-on le nombre 1637 en binaire?
    5. Citer un ou des avantages de la notation binaire.
    6. Le binaire est aussi utilisé pour écrire des lettres et des caractères. Comment?
    7. Additionnez 1010 (binaire) + 1101 (binaire), réponse en binaire. Expliquez la procédure.

    Numération Hexadécimale

    1. Quelle est la valeur de la base de la numération hexadécimale?
    2. L’écriture #F4 représente t-elle un nombre héxadecimal? Si oui, quelle est sa valeur?
    3. Quelle est la valeur la plus élevée que l’on peut écrire avec 2 symboles, en notation hexadécimale?
    4. Comment écrit-on le nombre 1637 en hexadecimal?
    5. Citer un ou des avantages de la notation hexadécimale.
    6. L’hexadécimal est aussi utilisé pour écrire des lettres et des caractères. Comment?
    7. Comment convertir rapidement 1100 1001 (binaire) en héxadecimal?

    Le système bibinaire

    Le chanteur et mathématicien Boby Lapointe, surtout connu pour ses talents d’auteur, de compositeur et d’acteur, a inventé un système de numération qu’il voulait universel et proche du langage des ordinateurs. Ce système, qualifié de bibinaire, s’appuie sur l’écriture binaire des nombres et présente deux aspects, un langage écrit qui repose sur des symboles associés aux nombres, et un langage oral.

    Soit un nombre N. Par exemple : N = 347, donc N = 101011011 (binaire).

    Dans le système bibinaire, on décompose l’écriture binaire en quartets (groupements de quatre bits) en partant de la droite et en ajoutant à gauche, si besoin est, les zéros complémentaires pour former un nombre entier de quartets.

    Ici, N = (0001 0101 1011).

    On considère que chaque quartet est composé de deux duets (00, 01, 10 ou 11). A chaque duet est associé une consone ou une voyelle, selon que ce duet est en tête ou en queue du quartet :

    Duet Correspondance duet de tête Correspondance en duet de queue
    00 H O
    01 B A
    10 K E
    11 D I

    Ainsi, le quartet 0111 se lit BI, car 01 est en tête et correspond à B et 11 est en queue et correspond à I. Le nombre N = 347 après écriture binaire, se lit HABAKI.

    1. Combien de quartes différents peut-on écrire en numération binaire ?
    2. Quelle est la base réellement utilisée dans le système bibinaire ?
    3. Quels nombres décimaux correspondent aux mots : HEKAKA, BOKEKE, KEBOBO et KEBAHI ?
    4. Comment sont traduits les nombres 52326 et 11847 dans le langage bibinaire?

    Notes


    1. Mésopotamiens : La civilisation babylonienne est héritière de Sumer, et elle s’est épanouie en Mésopotamie du Sud du début du IIe millénaire av. J.-C. jusqu’au début de notre ère. Elle est marquée par l’affirmation progressive, de la cité de Babylone, capitale de l’État qui connait son apogée à partir du VIe siècle av. J.-C. Cette cité prospère étend son influence du nord-est de la Syrie, au nord de l’Irak actuel, ainsi que les plaines plus au sud. Les milliers de tablettes cunéiformes découvertes sur les différents sites de Babylonie (Babylone, Ur, Uruk, Nippur, Sippar, etc.) ont permis de dresser le tableau d’une civilisation urbaine reposant sur une agriculture irriguée potentiellement très productive. https://fr.wikipedia.org/wiki/Babylone ↩︎

    2. Numération egyptienne, lien wikipedia ↩︎ ↩︎

    3. Numération babylonienne, lien wikipedia ↩︎ ↩︎

    4. Numération Romaine: lien wikipedia ↩︎ ↩︎

    5. Numération Maya: lien wikipedia ↩︎

    6. Numération Chinoise: Lien wikipedia ↩︎

    7. Numération indienne lien wikipedia et Numération Indo-arabe: Lien wikipedia ↩︎

    memoire des machines

    culture numer

    Numérisation - video du site du CEA

    introduction à l'architecture de l'ordinateur

    introduction à l'architecture de l'ordinateur

    Les machines ne comprennent que les chiffres ! Et pas n’importe lesquels : 0 et 1 sont ses préférés… Pourtant, une machine comme celle qui vous sert à afficher cette page n’est pas (seulement) une calculatrice:

    Comment peut-on travailler avec du texte ou des images sur une machine, qui ne manipule que du binaire?

    Mémoire d’une machine

    Une machine manipule des données numériques BINAIRES. Ce sont des nombres constitués de chiffres ne pouvant prendre que 2 valeurs, 0 ou 1 : des bits.

    Le stockage des bits s’est fait autrefois sur support papier (avec/sans trou):

    carte perforée IBM - source wikipedia

    carte perforée IBM - source wikipedia

    source - courstechinfo.be/Techno/Historique2.html

    source - courstechinfo.be/Techno/Historique2.html

    Une machine comme l’IBM 1401 lisait les cartes (a) pour en recopier le code sur une bande magnétique (b). Un gros calculateur lisait cette bande (c), exécutait les jobs (d) puis transcrivait les résultats sur une autre bande (e) postposant ainsi l’impression des résultats (impression off-line) faite ensuite par un ordinateur plus léger (f).

    On devine en quoi les machines ont grandement evolué: aujourd’hui, le processeur gère tout seul l’accès aux données et aux programmes. Il n’y a plus besoin d’un personnel humain…

    Mais alors, comment représenter et organiser les données sur un support (mémoire) pour qu’elles soient accessibles (lecture/ecriture) par le processeur ?

    Aujourd’hui, le support mémoire est constitué de milliards de transistors, possédant 2 niveaux de tension : 5V ou 0V.

    C’est donc le transistor qui permet la représentation d’un bit de donnée, en ajustant la tension électrique au niveau haut ou au niveau bas.

    Le transistor: un composant électronique à 2 états

    Le transistor: un composant électronique à 2 états

    Un transistor est un morceau de conducteur, dont la conductivité est contrôlée par sa troisième broche/borne. - Source: Fonctionnement d’un ordinateur/Les transistors et portes logiques

    Loi de Moore

    voir la presentation:

    Le nombre de transistors sur une puce électronique devrait être doublé tous les 2 ans, pour le même prix de fabrication. Les transistors deviennent donc de plus en plus petits.

    La figure suivante montre l’évolution du nombre de transistors pour un même élement de surface:

    illustration de la loi de Moore - source wikipedia

    illustration de la loi de Moore - source wikipedia

    Lien page wikipedia

    Cette miniaturisation a un effet sur d’autres caracteristiques. Voir l’article ci-dessous.

    evolution des caracteristiques des machines - source wikibooks

    evolution des caracteristiques des machines - source wikibooks

    Lien page wikibooks

    Coder et manipuler de plus grandes valeurs

    Les transistors sont gravés sur circuits intégrés, ce qui a permi d’atteindre des fortes densités par unité de surface. La finesse de gravure est actuellement de 10 nm environ (Intel).

    Le transistor: un composant électronique à 2 états

    Le transistor: un composant électronique à 2 états

    Une machine va traiter des informations qui vont être à l’origine très diverses, plus ou moins structurées, mais toujours en binaire :

    Ce sont des nombres, des caractères, des mots, des images, des sons, des bruits, la température, la quantité d’argent qu’on a dans notre porte-monnaie, notre âge, des dates, etc.

    La quantité de mémoire, même importante, n’est pas infinie dans une machine. C’est pourquoi on doit reserver un certain nombre de bit à chaque donnée, et ce nombre doit être ajusté au mieux.

    Pour coder une information qui peut prendre plus de 2 valeurs, il faudra utiliser plusieurs bits. Ceux-ci sont souvent rassemblés par 8, formant un mot-octet. Celui-ci peut prendre 256 valeurs.

    Stocker de manière durable: Disque dur

    Les mémoires se partagent en 2 familles: Les mémoires volatiles, comme la RAM: les données stockées vont s’éffacer lorsque l’on coupe l’alimentation de la machine. Et les mémoire persistantes, pour lesquelles les données ne s’effacent pas lors de la mise hors tension.

    Le disque dur est du 2e type. Il utilise des pistes magnétiques sur un plateau pour écrire et lire avec une tête magnétique.

    disque dur - Wikipedia

    disque dur - Wikipedia

    Actuellement, les disques durs vendus dans le commerce contiennent 1 à plusieurs To (teraoctets: 1015 octets)

    Numériser des données - les standards internationaux

    Dès l’invention de l’informatique, les ordinateurs ont pu manipuler des textes composés de caractères, que ce soit pour la saisie des commandes sur un clavier ou pour l’impression des résultats sur le papier. Il a donc fallu adopter une convention commune qui soit utilisée par tous les ordinateurs. Ainsi, est né en 1961 le code ASCII (American Standard Code for Information Interchange) qui associe une valeur numérique à chaque caractère de l’alphabet : 65 pour A, 66 pour B…

    table ascii, source: lookuptable.com

    table ascii, source: lookuptable.com

    Avec la taille des mémoires, et les performances des machines qui ont progressé, il a été possible de coder des données de plus en plus complexes. Il a fallu trouver un moyen de structurer ces données, c’est à dire de les mettre en forme et en lien dans un format approprié.

    Sources et compléménts

    numeration binaire

    modelisation

    Codage des nombres

    Ce cours comprend une page d’exercices avec des flash cards : Lien vers la page d’exercices

    Explication en vidéo

    introduction au langage binaire

    introduction au langage binaire

    Définition de la numeration binaire

    La numeration binaire est une numeration de position, en base 2.

    Numération en base 2 :

    • On utilise 2 symboles 0 et 1
    • Le mot-nombre comprend, depuis la droite vers la gauche : les unités, les paires, les paires de paires…

    Numeration de position : on utilise les mêmes chiffres pour représenter les unités, les paires, etc…

    Comparaison avec la numération décimale

    La numération décimale est aussi une numération de position. On retrouve donc des similitudes avec le binaire:

    decimale binaire
    base 10 2
    chiffres utilisés 0,1,2,3,4,5,6,7,8,9 0, 1
    poids du chiffre le plus à droite 1 (unité) 1 (unité)
    poids du chiffre à gauche des unités 10 (dizaines) 2 (paire)
    poids du chiffre encore plus à gauche 100 (dizaine de dizaine) 4 (paire de paire)

    Résumé :

    ascii ou utf8

    Chaque caractère dont le point de code est supérieur à 127 (0x7F) (caractère non ASCII) se code sur 2 à 4 octets:

    • Codage des caractères Unicode sur plusieurs octets.

    0bbbbbbb 1 octet codant 1 à 7 bits

    110bbbbb 10bbbbbb 2 octets codant 8 à 11 bits

    Exercices et flash card

    Lien vers la page d’exercices

    Format des donnees

    culture numer D1 Format des données : Lien
    culture numer D2 Collecte des données personnelles : Lien
    culture numer D3 RGPD Lien et videos, recherche documentaire Lien
    modelisation D4 Traitement des données en table Lien
    competences TP1 Enquete de police Lien
    modelisation TP2 Pommes Lien
    modelisation TP3 Traitement de données data.gouv Lien
    competences TP4 Formulaire d’enquête, conception du formulaire pdf et traitement Lien

    Introduction

    En informatique, tout est donné, depuis les 0 et les 1 qui décrivent l’état des transistors dans un circuit électronique, jusqu’à une vidéo, en passant par les photos, les adresses, un relevé de température ou l’âge d’une personne. Les données sont souvent rassemblées pour caractériser un objet comme l’adresse d’une personne (composée du numéro de rue, du nom de la rue, du code postal, de la ville et du pays par exemple). Lorsque les données sont ainsi rassemblées pour décrire quelque chose avec plusieurs informations, on parle de données structurées (voir plus loin).

    activité sur le traitement des données

    activité sur le traitement des données

    1. A partir de l’image projetée, choisir une méthode pour placer les informations dans un même tableau. Quelles seront les étiquettes de colonne?
    2. Lorsque l’on place ses données sur une page internet, les champs du formulaire demandent un format particulier pour les données. Etes vous capables de retrouver rapidement l’information suivante: quel évènement a pour plaignant Me Dubois? => besoin de ranger les informations dans une table pour effectuer la recherche avec une clé (étiquette de colonne)
    3. Ouvrir la page de l’activité. Recopier le tableau et le compléter avec 3 étiquettes post-it ou plus. (consigne précise: Votre mission est d’extraire les informations importantes et de les organiser dans le tableau fourni ci-dessous.)

    Type de variable, cellule d’un tableur

    Selon la mise en forme, le format associé est soit du texte (entre guillemets, soit un nombre (virgule pour décimal), mais cela peut être aussi une date (15/09/2023), une heure (8:30) ou une coordonnée GPS exprimée en degré minute d’arc seconde (45°30’45’’).

    Dans un fichier .xls, ou csv, les données sont structurées. Dans une même colonne, les données sont dans le même format (sont du même type)

    Présentation des données

    Un fichier Excel regroupe une ou plusieurs table(s) Dans une table, les données sont mises dans des colonnes, où elles ont le meme type. Chaque donnée est dans une cellule, référencée par ses coordonnées.

    Chaque TABLE représente une COLLECTION. C’est à dire un ensemble d’objets (des lignes) qui partagent les mêmes DESCRIPTEURS. Les valeurs de ces objets ont un certain type. Chaque colonne contient des valeurs du même type.

    Chaque ligne contient une information.

    Open datas et données structurées

    video du site cookie-connecté

    video du site cookie-connecté

    L’open data (ou données ouvertes) est l’ouverture via le Web de données collectées par des organismes publics (ou entreprises), et dont la diffusion est considerée comme d’interêt général.

    Quelques exemples:

    • horaires transports publics
    • état des lignes (métro, autobus…)
    • prévisions météorologiques
    • prix des carburants
    • …

    Il y a des conditions à respecter pour la mise à disposision de ces données. Une donnée doit être de nature:

    • ouverte
    • primaire
    • libre de droit

    Organisation des données

    • Une collection de données peut être ordonnée sous forme de liste, ou d’une table.

    La façon de structurer les données influe fortement sur les opérations de traitement : il est par exemple bien plus efficace de rechercher une donnée dans une collection toujours ordonnée, mais y insérer une information est plus coûteux.

    • Donnée : représentation d’une information au sein d’un système informatique.

    • Métadonnée : donnée servant à définir ou décrire une autre donnée, pour permettre sa manipulation.

    • Une base de données regroupe plusieurs collections de données reliées entre elles.

    • Descripteur : mot ou un groupe de mots choisi pour caractériser les informations contenues dans un document et pour faciliter les recherches.

    • Une collection regroupe des objets partageant les mêmes descripteurs (par exemple, la collection des contacts d’un carnet d’adresses). La structure de table permet de présenter une collection : les objets en ligne, les descripteurs en colonne et les données à l’intersection. Les données sont alors dites structurées.

    • Une information est issu du croisement de plusieurs données. On donne un nouveau sens à ces données.

    Format des données

    L’OPen Datas exige que les données doivent être au format EXPLOITABLE, et non proprietaire.

    Souvent, on va trouver les format csv, json et XML pour les fichiers.

    csv:

    nom, prenom, age
    Dupont, François, 17
    Darcis, Pauline, 16

    json:

    {
    	{
    		"nom": "Dupont",
    		"prenom": "François",
    		"age": 17
    	}
    	{
    		"nom": "Darcis",
    		"prenom": "Pauline",
    		"age": 16		
    	}
    }

    XML

    <membre>
    	<nom>Dupont</nom>
    	<prenom>Francois</prenom>

    Plateforme ouverte des données publiques françaises

    Plateforme ouverte des données publiques françaises

    Le Répertoire National des Élus (RNE) a pour finalité le suivi des titulaires d’un mandat électoral. Il est renseigné et tenu à jour par les préfectures et hauts commissariats et par les services du ministère de l’intérieur, notamment sur la base des éléments fournis par les élus lors de la phase d’enregistrement des candidatures.

    Données du RNE pour les conseillers municipaux - extrait en csv

    Données du RNE pour les conseillers municipaux - extrait en csv

    Les données du RNE sont structurées par mandat. Neuf fichiers sont publiés ici :

    1. les conseillers municipaux ;

    1. les conseillers communautaires ;
    2. les conseillers départementaux ;
    3. les conseillers régionaux ;
    4. les membres des assemblées des collectivités à statut particulier ;
    5. les représentants au Parlement européen ;
    6. les sénateurs ;
    7. les députés ;
    8. les maires.

    En bas de page, vous pourrez observer les réutilisations de ces documents:

    exemples de réutilisation des données ouvertes sur les elus municipaux

    exemples de réutilisation des données ouvertes sur les elus municipaux

    On voit ici comment des données numériques sont transformées en informations.

    Ouvrir les données jugées d’intérêt public, c’est encourager leur réutilisation par tout un chacun. Cela permet d’encourager la transparence démocratique, de bénéficier de services au quotidien ou de prendre des décisions plus éclairées.

    Lien vers le TP

    Traitement des données en table

    culture numer D1 Format des données : Lien
    culture numer D2 Collecte des données personnelles : Lien
    modelisation D3 Données en table Lien
    culture numer D4 RGPD Lien et videos, recherche documentaire Lien
    competences TP1 Enquete de police Lien
    modelisation TP2 Pommes Lien
    modelisation TP3 Traitement de données data.gouv Lien
    competences TP4 Formulaire d’enquête, conception du formulaire pdf et traitement Lien

    Activité 1: Trouver une information

    Lea, une jeune mère de famille a accepté l’enregistrement de ses données de géolocalisation par le service Google.

    Elle se renseigne sur les données enregistrées et obtient le tableau suivant pour les jours 15/09 et 16/09:

    1. Quelle est la référence de la case contenant la valeur 08:45 ? …

    2. Quelle est la valeur de la case E4 ? …

    Compléter la formule de calcul de la distance parcourue le 15/09:

    = E4 + …

    1. Compléter la formule utilisant la fonction somme pour calculer la distance totale parcourue pendant ces 2 jours:

    = SOMME(E4 : …

    1. D’après les données de ce tableau:
    • Quelle a été la journée de Lea le Dimanche 15/09?

    • Où est le lieu de travail de Léa?

    Activité 2: Données en plusieurs tables

    L’agence de voyage Globe Trotteur enregistre les données de ses clients sous la forme de plusieurs tables: CLIENTS, VOYAGES et VOLS:

    1. Quel est l’identifiant de Julien Dumas dans le fichier CLIENTS?
    2. Quelles étaient les destinations de Francoise Dargent au cours du mois d’octobre 2024?
    3. Combien de miles cela lui-a-t-il rapporté dans son programme de fidélité?

    Chaque traitement sur la base de données s’exprime de la manière suivante:

    • Rechercher dans la colonne … de la table … la valeur … et retourner la valeur de la colonne … ou bien:
    • Filtrer les lignes de la table … en conservant celles où la colonne … vaut …
    • Dans la table … faire la somme des valeurs de la colonne … On peut aussi réaliser une combinaison de ces 3 opérations: par exemple, faire la somme sur les colonnes d’un tableau filtré.
    1. Pour chacune des 3 premières questions, énoncer le traitement qui est réalisé.
    2. Trouver une information à laquelle la base de données peut répondre. Formuler la question, comme vu dans les questions 1. à 3.

    Cours

    Recherche et tri

    Le traitement sur des données structurées peut consister à:

    • rechercher une donnée (critère)
    • filtrer sur les données selon un critère

    La formule exprime alors une idée du type: sur le tableau de données T, je cherche la valeur couleur correspondant à la fréquence 4,19

    Calculer

    Pour copier une donnée dans une nouvelle cellule, on peut faire une copie par référence en indiquant sa coordonnées, après le signe =

    Le traitement peut aussi consister à réaliser des calculs:

    = somme(E4:E11)
    = E4 + E5 + E6

    On peut aussi combiner les méthodes: somme et filtre:

    =SOMME.SI(C3:C18;”David";E3:E18)

    Cette formule calcule uniquement la somme des valeurs de la plage C2:C5, dans laquelle les cellules correspondantes de la plage B2:B5 contiennent le mot « Jean ».

    Base de données à plusieurs tables

    Pour représenter les données, on peut utiliser un simple fichier texte. Pour séparer ces données, le plus courant est d’utiliser un séparateur par virgule (comma en anglais) : comma separated values (csv). Ce format convient bien pour des petites collections de données. Pour de plus grosses quantités, on utilisera des ensembles de tables, reliées entre elles par des règles et constituants des « bases de données » (database). Pour une base de données à plusieurs tables, on utilise des clefs d’indexation permettant d’identifier rapidement chaque ensemble de données (comme un numéro d’article ou un numéro de client)

    Exemple: voici un ensemble de données. Placer celles-ci comme nouvelles entrées dans les tableaux proposés.

    Dupond Kevin, 21 ans, habite à Nice, voyage à Berlin le 06/12/24, son code client est le 756A Pour son voyage à Berlin, la compagnie était Lufthansa, le vol était LF 231, à 7h01 et son numéro de siege le 31D. Le passager voyageait seul et avait un bagage en soute de poids 14,6 kg, dont la reference bagage était 1234.

    source: www.cours.jlrichter.fr

    Donnees personnelles

    culture numer D1 Format des données : Lien
    culture numer D2 Collecte des données personnelles : Lien
    culture numer D3 RGPD Lien et videos, recherche documentaire Lien
    modelisation D4 Traitement des données en table Lien
    competences TP1 Enquete de police Lien
    modelisation TP2 Pommes Lien
    modelisation TP3 Traitement de données data.gouv Lien
    competences TP4 Formulaire d’enquête, conception du formulaire pdf et traitement Lien

    Données à caractère personnel

    culture numer

    Une donnée à caractère personnel est une information sur une personne.

    Parmi les données suivantes, certaines peuvent être classées comme relevant de:

    • l’identité numérique
    • identité administrative
    • indirectement nominative (qui donne l’identite de la personne, une fois effectué un recoupement d’informations)

    Ce sont:

    • Le nom, le prenom, l’adresse
    • un pseudo, un mot de passe
    • une adresse IP
    • des lieux visités et géolocalisés
    • un panier d’achat
    • des clés de recherche sur internet
    • numero de carte bancaire
    • numero NIR (securité sociale)
    • données associées à son compte de reseau social (publications, like)
    • Données exposée par d’autres mais nous identifiant dans un reseau social
    • ordonance médicale, clichés radiographiques, …
    • L’enregistrement de la voix de clients ou salariés par un dispositif informatique
    • images de personnes physiques captées par un système de vidéosurveillance
    • les conversations (par le microphone)
    • le patrimoine d’un propriétaire
    • …

    Même des données supposées anonymes peuvent nous identifier car il existe souvent une clé de correspondance qui peut nous identifier.

    VIDEO Cash Investigation, le mythe de l'anonymisation

    VIDEO Cash Investigation, le mythe de l'anonymisation

    Mais alors, à qui servent ces données?

    VIDEO Qui collecte nos données personnelles? - Le Tatoo (0-3min) puis Comment limiter la collecte de nos DCP (6min->fin)

    VIDEO Qui collecte nos données personnelles? - Le Tatoo (0-3min) puis Comment limiter la collecte de nos DCP (6min->fin)

    Identité numérique

    L’identité est construite à partir de données à caractère personnel.

    • L’exercice du droit d’une personne passe par la justification de l’identité administrative de la personne (nom, prenom, date de naissance, etc…).
    Infographie du RGPD - site de la CNIL

    Infographie du RGPD - site de la CNIL

    • Identité sur le net: Sur internet, la majorité des utilisateurs ne communiquent pas leur identité administrative. Ils donnent un pseudo, un mot de passe, un email. Le site associe souvent leur adresse IP à ces données. Ce qui constitue aussi une identité numérique.

    Comment sont collectées nos données personnelles

    (voir activité p 16 du livre SNT)

    Les données nous concernant peuvent être cédées de manière:

    • volontaires, directement: à partir d’un formulaire à remplir
    • involontaires, indirectement: dans les metadonnées des photos de ma galerie, à partir du gps de mon telephone, de mon activité sur le net, de mes amis sur le net, de mon profil social sur les reseaux, …

    Pour utiliser les services du net, on doit en contrepartie donner son accord pour partager certaines de nos données.

    Lorsque l’on installe une application, un logiciel, un driver pour un objet connecté, on est souvent obligé d’accepter le contrat sur les Conditions Générales d’Utilisation (CGU).

    De même, pour accéder à la plupart des sites d’information, on est obligé d’accepter en grande partie les cookies du site, qui vont enregistrer et partager certaines de nos données.

    Les données nous concernant peuvent aussi être cédées de manière:

    • héritée: c’est lorsque ce sont d’autres personnes qui parlent de nous, ou publient des photos de nous, sur le net. (voir le chapitre sur les réseaux sociaux)

    Pour résumer:

    extrait d'une affiche sur le site de la CNIL

    extrait d'une affiche sur le site de la CNIL

    Traces numériques et marketing ciblé

    Après 1978, c’est la valeur commerciale des données personnelles qui va commencer à aiguiser l’appetit d’opérateurs économiques: l’émergence d’une économie fondée sur la connaissance du client. Ce qui va intensifier la collecte de données à caractère personnel et amener à un marketing ciblé.

    C’est la convergence technologique et la traçabilité qui permet d’intensifier cette collecte indirecte de nos données: des cartes à puces, cartes de fidélité client, videosurveillance, données de connexion aux réseaux numériques, moyens de paiement (cartes bancaires ou autre types de paiement numériques). On est passé d’une problématique de fichier à une problématique de traces numériques.

    Comment peut-on limiter nos traces numériques?

    • Tous les cookies ne se valent pas : cookies « nécessaires » ≠ cookies « publicité / partage à des tiers ».
    • Cliquer sur « Tout accepter » maximise la collecte de vos DCP ; paramétrer réduit votre exposition.
    • Les CGU renseignent sur les données collectées et sur qui les reçoit : les consulter (même en diagonale) est un outil de choix.
    • Réduire sa collecte de DCP est possible par 2 leviers : le paramétrage des cookies ET le choix d’un service moins coûteux en données.

    Traitement des données

    Definition

    il s’agit de toute opération effectuée de manière automatisée appliqué à des données à caractère personnel.

    Par recoupement de plusieurs informations (publications, enregistrement par des dispositifs matériels, camera ou autre…), un algorithme peut déduire des informations sur ma personnalité, quelles sont mes préférences en terme de:

    • religion
    • sexualité
    • politique

    Un ordinateur, ou bien une personne qui a accès à certaines données indirectes qui me concernent, peut retrouver mon identité.

    extrait de l'Ep2 S04, recherche dans la base de données d'une boutique de location de films

    extrait de l'Ep2 S04, recherche dans la base de données d'une boutique de location de films

    Enjeux pour l’usager

    Aujourd’hui, l’aspiration des individus, en termes de protection de leur vie privée est de pouvoir utiliser les services technologiques d’internet, de s’exposer personnellement (reseaux sociaux), tout en cédant une partie acceptable de leurs données personnelles. Cette part cédée doit rester raisonnable et être négociée par contrat avec les opérateurs économiques.

    A quoi (à qui) sert cette collecte des données?

    Imaginez un stade de football. Les panneaux publicitaires autour de la pelouse n’appartiennent pas au club qui joue le match : ils sont vendus par une agence intermédiaire à des annonceurs, qui paient pour être vus par les spectateurs présents et par ceux qui suivent le match à la télévision. Le club ne vend pas un morceau de terrain : il vend l’attention de son public.

    Une page de site de presse fonctionne sur le même principe. L’espace publicitaire affiché n’appartient pas au site lui-même : il est vendu par une régie publicitaire à des annonceurs. Mais il existe une différence essentielle.

    Au stade, tous les spectateurs voient le même panneau publicitaire au même moment. Sur le web, chaque lecteur peut voir une publicité différente, choisie spécifiquement pour lui à partir de son profil.

    Une expérience similaire a été constatée pour l’Euro 2020: en Allemagne ou en France, les bandeaux publicitaires qui encadrent le terrain ne vont pas vous vendre la même chose.

    numerama - Au foot tout le monde ne voit pas les memes pubs au bord du terrain

    numerama - Au foot tout le monde ne voit pas les memes pubs au bord du terrain

    La société distributrice des panneaux d’affichage, Adi.tv s’est spécialisée dans le traitement des images, avant leur diffusion. Ces technologies numériques sont utilisées aujourd’hui pour la plupart des grands evenements sportifs, pour améliorer l’experience des telespectateurs, ou pour leur proposer des publicités plus ciblées.

    Vox - How the NFL's magic yellow line works (start 1:55

    Vox - How the NFL's magic yellow line works (start 1:55

    Un triangle à quatre acteurs:

    Quand un internaute consulte un site de presse gratuit, trois-quatre acteurs interviennent, même si un seul est visible.

    • L’éditeur: Le site de presse. Produit le contenu, mais a besoin de revenus pour exister sans faire payer le lecteur.
    • La régie publicitaire: Intermédiaire qui vend les espaces publicitaires du site à des annonceurs, souvent via une plateforme automatisée.
    • Les entreprises de l’adtech: plateformes technologiques. C’est l’ensemble des technologies, des logiciels et des algorithmes utilisés pour concevoir, cibler, diffuser et mesurer ces publicités de manière automatisée.
    • Les partenaires: Annonceurs, courtiers de données : ceux qui achètent l’accès à l’attention et aux données du lecteur.

    l’éditeur ne vend pas seulement un espace sur sa page, il vend surtout l’accès à un lecteur profilé — et plus ce profil est précis, plus il se vend cher.

    • Le service est « gratuit » pour le lecteur, mais pas sans contrepartie : le financement du site repose en partie sur la vente de l’accès à son profil.
    • Le cookie n’est pas qu’un outil technique de confort (retenir un panier, une connexion) : il peut être la clé qui relie la navigation à ce marché publicitaire.
    • Paramétrer ses cookies plutôt que tout accepter limite concrètement le nombre de partenaires qui reçoivent des informations sur le lecteur — un des deux leviers vus dans ce cours pour réduire la collecte de DCP.

    Le RGPD (Réglement Général pour la Protection de Données)

    Définition

    C’est un document qui donne un cadre légal à l’utilisation des données dans l’UE et contraint les organismes publics ou privés à certaines obligations.

    Ce texte vise à définir des équilibres: protection des individus d’une part, utilisation des données à des fins commerciales ou pour des missions d’intérêt public, d’autre part.

    Le RGPD n’interdit PAS l’utilisation commerciale des données.

    Mais il fournit un cadre, auquel les entreprises privées, comme les administrations publiques doivent se conformer.

    Obligations de conformité vis à vis du RGPD

    Pour les entreprises et administrations, susceptible de TRAITER des données à caractère personnel:

    • devoir de tenir un registre des activités de traitement (finalités, délai de conservation et de suppression automatique, réalisation d’atude d’impact…)
    • obligation d’assurer une collecte lisible et transparente des données
    • protéger les données. Assure leur sécurité et leur confidentialité
    • définir un paramètre: Rester minimal dans la quantité de données et le type de données collectées
    • interdiction de collecter certaines catégories particulières de données (origines raciale ou ethnique, opinions politiques, convictions religieuses, appartenance syndicale)
    • interdiction de collecter le numero NIR (securité sociale) car celui-ci contient un certain nombre de caractéristiques qui aident au chainage des données
    • interdiction de collecter des données génétiques, biométriques, concerant la santé, la vie et l’orientation sexuelle.

    Droit des personnes vis à vis du RGPD

    Tout individu doit:

    • pouvoir être questionné pour demander son consentement préalable à la collecte et l’utilisation de ses données.
    • être informé sur la finalité du traitement qui sera effectué
    • dans le cas d’une collecte indirecte: être informé de la source de cette collecte, et droit de recours auprès de la CNIL
    • avoir droit d’accès, de rectification et de portabilité des données (c’est à dire, droit à obtenir ses données collectées dans un format structuré, lisible)
    • avoir droit d’effacement
    • avoir droit d’opposition au traitement des données à visée commerciale et de profilage
    • avoir des droits concernant les cookies, exploitant ses traces de navigation. Côté client, ces cookies sont stokées dans le navigateur web. L’individu doit donner son consentement sur leur utilisation, à partir d’une information claire et complète
    • avoir droit au deferencement: demander la suppression de liens vers des informations portant atteinte à la vie privée.

    Remarques:

    • Il existe également un tracking côté serveur. Le client n’est alors pas en mesure d’effacer ses traces numériques, qui sont partagées le plus souvent avec des entreprises tierces (revente des données). Dans la chaine de partage des données, tout le monde est alors responsable du traitement qui sera effectué sur ces données.
    • De nombreux exemples montrent des manquements à ces règles sur la protection des données et leurs conséquences: L’affaire Facebook pendant l’élection américaine, qui a vu gagner le président Trump en est un tristement célèbre, même si cela ne concernait pas le territoire d’influence de la CNIL et de son équivalent européen. Au niveau fançais: les affaires Foncia, Acadomia…

    La CNIL

    Definition

    Commission Nationale pour l’informatique et les libertés. La CNIL est la premiere autorité administrative instaurée en France (1978) à la faveur de l’adoption de la loi “informatique et libertés”.

    Les actions de la CNIL

    La CNIL exerce un pouvoir de contrôle et de sanctions pour la protection des données. Elle est indépendante et ne reçoit d’instruction d’aucune autorité publique.

    Tout citoyen peut s’adresser à la CNIL pour la saisir d’une plainte.

    La CNIL réalise des:

    • controles d’audit, qui sont programmés, sur des organismes privés comme publics.
    • contrôles de contentieux à partir de plaintes, de dénonciations anonyme ou de tout autre moyen qui lui aurait permi de prendre connaissance d’un manquement au RGPD.

    La CNIL fait en sorte que l’usage qui est fait des données personnelles ne porte pas atteinte à la liberté des individus.

    Sanctions prises

    Lors d’un manquement avéré, la CNIL peut:

    • faire suspendre les flux de données adressés à un destinataire
    • prendre des sanctions pécunières
    • prendre des sanctions d’image: publication sur le site de la CNIL et dans le Journal Officiel. Les répercussions peuvent être importantes (risque réputationnel)

    Le RGPD (Le règlement général sur la protection des données)

    mai 2018

    C’est un document qui donne un cadre légal à l’utilisation des données dans l’UE et contraint les organismes publics ou privés à certaines obligations. C’est un texte plus général que celui sur la loi informatique et libertés.

    Le RGPD - affiche de la CNIL

    Le RGPD - affiche de la CNIL

    Il s’agit d’un texte long (plusieurs centaines de pages), fruit de la concertation de 28 états membres de l’Europe. Ce texte est complexe à dechiffrer. Un des rôles de la CNIL est de produire des documents et textes Extraits:

    • La collecte de données doit servir l’objectif prévu. Ne collecter que celles nécessaires.
    • Les personnes doivent être clairement informés de l’utilisation qui sera faite de leurs données. Ce traitement n’est pas forcement informatisé. Mais tout traitement de données rentre dans le cadre du RGPD.
    • permettre aux personnes d’exercer leurs droits sur ces données.
    • Sécuriser ces données.

    Violation de données et incidents de sécurité

    Malgré toutes les mesures de sécurité mises en oeuvre, les violations et incidents peuvent survenir. En vertu du RGPD, les entreprises et administrations sont tenues d’informer l’autorité de contrôle (CNIL), ainsi que les individus concernés par le vol de données personnelles.

    Ainsi, en 2024, les données de santé de 33 millions de français stockées pour le tiers payant (Aimerys) ont été hackées par des malfaiteurs. Elles ont pu être reversées dans le dark web, et contribuer à créer de fausses identités.

    Mais, encore plus préoccupant, ce sont les données rendues publiques par les internautes, sur des sites internet, reseaux et applications sur leur smartphone qui sont les plus faciles à dérober.

    Les reseaux sociaux et les clouds gratuits exploitent grandement ces données, qu’ils collectent massivement.

    paramétrer son smartphone pour éviter la fuite de ses données

    paramétrer son smartphone pour éviter la fuite de ses données

    Il est essentiel de connaitre les risques et d’adopter une attitude modérée lorsque l’on utilise ces outils.

    Vie privée et traces numériques, persistance sur le net

    Comme vos données sont personnelles, elles vous concernent et vous devez en avoir la maitrise.

    Conserver des secrets sur sa vie privée est relativement difficile lorsque l’on s’expose sur internet.

    Le format numérique des données va faciliter leur échange, leur multiplication, … et leur persistance sur le web.

    Il est souhaitable d’avoir un compte privé sur les réseaux sociaux, et de diffuser le moins d’informations possibles. Mais les algorithmes utilisés par les réseaux sociaux vont chercher à déduire des informations à partir d’indices:

    Votre activité sur les reseaux sociaux

    Les personnes que vous suivez, les pages que vous likez, … sont autant d’informations pour établir votre profil par recoupement d’information.

    Données de Géolocalisation

    Il s’agit d’un exemple de données personnelles indirectement nominatives. Celles-ci contribuent aussi à fournir une information sur la personne (habitude, travail, consultation de médecin)…

    Données personnelles, Google vous suit à la trace - FranceTV info

    Données personnelles, Google vous suit à la trace - FranceTV info

    Il existe cependant quelques gestes et attitudes qui peuvent limiter nos traces numériques, ainsi que la confidentialité des données que l’on échange.

    Questions-reponses

    une entreprise peut-elle être tenue responsable du vol des données de ses clients?

    une entreprise peut-elle être tenue responsable du vol des données de ses clients?

    Q/R issu du site europe-consommateurs.eu Lorsque vous acceptez la collecte, transfert, sauvegarde, utilisation de vos données par un professionnel:

    Doit-on vous informer de l’utilisation qui est faite de vos données ?

    Oui. Vous avez le droit de savoir si vos données sont collectées, transférées, sauvegardées, modifiées…

    Vous devez également être informé, entre autres, :

    • de l’identité du responsable de la collecte de vos données.
    • des finalités de cette collecte.
    • des destinataires de vos données.
    • de la durée de conservation de vos données.
    • de votre droit d’introduire une réclamation auprès d’une autorité de contrôle.

    Les entreprises américaines comme Uber ou Amazon, …, doivent-elles se conformer au RGPD?

    Oui car le RGPD est un texte de loi qui protège les citoyens européens (pour leurs données personnelles), même ci ceux-ci utilisent des services proposés par des entreprises hors UE, dès lors qu’elles ciblent des usagers européens.

    Comment protéger mes données lors d’un achat en ligne ?

    Assurez-vous que vous payez votre commande sur un site utilisant une connexion sécurisée. L’adresse du site doit commencer par « https:// » et un cadenas fermé doit apparaitre.

    Pour éviter le piratage de vos données bancaires, vous pouvez privilégier l’utilisation d’une carte bancaire à usage unique.

    Un site marchand européen a-t-il le droit de garder mes coordonnées bancaires pour faciliter mes futurs achats ?

    Oui mais seulement si vous y avez consenti expressément en cochant une case. Accepter simplement les conditions générales de vente ou passer par une case pré-cochée ne suffit pas.

    Vous pouvez à tout moment contacter le professionnel afin de demander la suppression de vos données bancaires.

    Comment protéger mes données sur les réseaux sociaux ?

    Pour protéger votre vie privée, paramétrez l’accès à vos photos et à votre profil. Vérifiez régulièrement le paramétrage de confidentialité de votre compte.

    Evitez de répondre aux questions de géolocalisation si cela n’est pas indispensable. Surtout, ne répondez pas aux messages adressés par des individus que vous ne connaissez pas.

    Laissez également le strict minimum concernant vos coordonnées et évitez d’y détailler votre vie privée, pour rester à l’abri de personnes malintentionnées.

    Un réseau social basé en Europe refuse de me donner accès à mes données personnelles. Vers qui dois-je me retourner ?

    Si vous résidez en France, vous pouvez adresser une plainte à la Commission Nationale Informatique et Libertés (CNIL) en cas de violation de vos droits. La CNIL se chargera d’en informer l’autorité chef de file. Il s’agit de l’autorité nationale de protection des données personnelles du pays dans lequel le professionnel/le réseau social est établi.

    Je n’utilise plus mon compte sur un réseau social, mes données sont-elles supprimées ?

    Non pas automatiquement. Ce n’est pas parce que vous ne vous êtes pas connecté à votre compte sur un réseau social depuis plusieurs années qu’il a supprimé vos données personnelles et ne les exploite plus. Renseignez-vous bien quant au devenir du compte que vous n’utilisez plus sur un réseau social.

    Les autorités de protection des données personnelles dans l’Union européenne recommandent aux différents réseaux sociaux de supprimer les comptes restés inactifs pendant une certaine période mais ces recommandations ne sont pas toujours respectées.

    Veillez donc à supprimer votre compte.

    Mon enfant de 14 ans peut-il s’inscrire seul et confier ses données à un réseau social ou un jeu en ligne ?

    Pas sans votre consentement car la majorité numérique en France est à 15 ans. En Europe, le RGPD a laissé le soin à chaque pays de fixer sa « majorité numérique » qui doit être entre 13 et 16 ans.

    Peut-on m’imposer de recevoir des publicités pour valider ma participation à un jeu concours ?

    Non. Aucune jeu concours ne peut conditionner votre participation au fait que vous acceptiez de recevoir une prospection commerciale, ou de communiquer vos coordonnées à des partenaires de l’organisateur du jeu. Vous devez pouvoir participer au jeu concours de manière libre. De la même manière, l’organisateur du jeu ne peut prévoir de vous accorder des chances supplémentaires au tirage au sort du jeu concours à condition que vous acceptiez de recevoir une prospection commerciale.

    Les informations recueillies ne peuvent être utilisées que dans le cadre du jeu et de la remise du lot en cas de gain, sauf si vous avez consenti à recevoir de la prospection.

    Le site Internet du restaurant-livreur de pizza, sur lequel vous avez renseigné des données personnelles est victime de hacking. Est-ce grave ? Doit-il informer ses clients ? Est-il responsable de l’usage qui sera fait de ces données ?

    Vous pouvez contactez la CNIL et cybermalveillance.gouv.fr, même si en principe l’entreprise doit effectuer la démarche. Demandez à l’entreprise des informations détaillées sur l’incident : date et contexte exact, origine de l’attaque, quelles données le hacker a-t-il exactement dérobées (identité, coordonnées, informations financières, numéro de sécurité sociale…) ? Quels documents a-t-il récupérés (copie de la carte d’identité, des fiches de salaires, justificatifs bancaires….) ? Est-ce que l’entreprise victime a bien fait une déclaration à la CNIL ? Réagissez à temps, afin d’anticiper une potentielle usurpation d’identité via les données volées !

    Compléments et activités

    Autres sites academiques

    TP Enquete police

    Enoncé du TP

    Un pieton a été renversé par une voiture dans la nuit du 02 septembre 2022.

    Vous enquêtez sur cet accident. Vous diposez d’une base de données comprenant:

    • des témoignages
    • un fichier d’immatriculation des vehicules
    • un fichier des personnes enregistrées au cours d’autres enquêtes réalisées par la police: les données de personnes fichées, ou bien temoins, soupçonnées, ou déjà condamnées.
    • un fichier avec références pour les données biométriques.

    Tous ces fichiers sont mis dans le même classeur à télécharger ici

    extrait du classeur

    extrait du classeur

    Tuto Excel

    Rechercher une information

    Vous recherchez un procès verbal qui contient le mot voiture, ou accident, ou encore pieton.

    Le fichier peut être long à lire, alors utilisez les fonctions de recherche du logiciel:

    1. Cliquer sur le repère de la colonne
    2. Dans les fonctions du logiciel, choisir Rechercher et remplacer > Rechercher (on peut s’aider du menu Aide). Placer alors votre mot-clé voiture dans les paramètres de recherche
    3. Sélectionner une à une toute les lignes qui contiennent voiture en appuyant sur Suivant

    Placer des informations dans une feuille Excel

    Au cours de l’enquête, vous aurez besoin de mémoriser des informations, et de les placer dans un tableau. Utiliser une nouvelle page du fichier en appuyant sur + en bas de page.

    Puis remplir vos informations dans la feuille:

    Travail (à rendre sur feuille)

    A. Questions sur l’enquête

    1. Quels renseignements relevez-vous dans la page témoignages du fichier?
    2. Comment utilisez-vous les renseignements donnés par les différentes pages du fichier pour identifier le-s suspect-s? Préciser le lien existant entre chaque page du fichier?
    3. Quels sont les suspects identifiés? (remplir un tableau sur Excel et le montrer au professeur).
    4. Quel est alors le PRINCIPAL suspect? Pourquoi?
    5. L’enquête à partir de ces fichiers va-t-elle, à coup sûr, permettre de désigner le coupable? Expliquez

    B. Prolongement: questions sur la protection des données personnelles

    A partir des liens proposées ci-dessous, ou bien d’autres issus d’une recherche personnelle, repondez de manière argumentée à au moins une des questions suivantes:

    1. Quelles personnes sont renseignées dans le fichier de la police? Des criminels, des personnes ayant eu affaire avec la justice, les victimes, ou bien tout citoyen français?
    2. La CNIL va s’opposer à l’existance d’un fichier du type de celui appelé proprietaire dans le classeur. Pourquoi?

    Liens

    Sources

    L’activité est inspiré d’un document de la page SNT du site monlyceenumerique.fr

    TP Pommes

    Format des données

    Les données structurées sont stockées dans des fichiers contenant des caractères. Ces fichiers peuvent être utilisés par plusieurs logiciels (interopérabilité), à condition que les données y soient mises dans un le bon format.

    Nous allons voir ici l’un de ces formats: Le csv, ou comma separated values.

    Voici un exemple de données en format csv. Il s’agit d’informations sur les vendeurs de fruits d’une compagnie, sur le territoire français.

    ;;;;;
    ;;;;;
    Région;Commercial;Produit;Unités;;
    Est;Maurice;Pommes;6380;;
    Ouest;Alain;Raisins;5619;;
    Nord;Ariane;Poires;4565;;
    Sud;Marie;Bananes;5323;;
    Est;Claude;Pommes;4394;;
    Ouest;Noël;Raisins;7195;;
    Nord;Jérôme;Poires;5231;;
    Sud;Sébastien;Bananes;2427;;
    Est;Maurice;Bananes;4213;;
    Ouest;Alain;Poires;3239;;
    Nord;Ariane;Raisins;6420;;
    Sud;Marie;Pommes;1310;;
    Est;Claude;Bananes;6274;;
    Ouest;Noël;Poires;4894;;
    Nord;Jérome;Raisins;7580;;

    Copiez ces données et collez les dans un fichier à l’aide de Notepad (du menu Programmes > accessoires de l’ordinateur).

    Sauvegardez le fichier dans votre dossier documents en le nommant: fruits.txt, ou bien "fruits.csv"

    Question a: A partir de vos connaissances, ou bien après une petite recherche sur le net quelle différence y-a-t-il entre un fichier à l’extension .txt et un fichier .csv? Les données y-sont-elles mises dans un format special (structuré) pour l’un de ces 2 types de fichiers?

    Présenter les données à l’aide d’un tableur

    Démarrer le logiciel Excel (un tableur de la suite bureautique microsoft).

    Une fois le logiciel Excel démarré, ouvrir le fichier fruits.txt

    A l’ouverture, il vous sera demandé de préciser le séparateur des données (, ou bien ;), puis l’encodage et les caractères.

    Selon la version du logiciel Excel, la boite de dialogue peut différer:

    le format n'a pas été correctement renseigné

    le format n'a pas été correctement renseigné

    Le paramètre semicolon (point virgule) précise le caractère séparateur.

    le format a été correctement renseigné

    le format a été correctement renseigné

    Dans une version plus recente, la boite de dialogue peut ressembler à celle-ci:

    à gauche, les caractères accentués ne sont pas gérés. à droite, en utf-8, les caractères accentués sont pris en charge.

    à gauche, les caractères accentués ne sont pas gérés. à droite, en utf-8, les caractères accentués sont pris en charge.

    Pour l’encodage des données, choisir utf-8. Cela permetra d’afficher aussi les caractères accentués.

    Le logiciel Excel sert à PRESENTER les données. C’est à dire à reconstruire le tableau. Le visuel peut être important pour lire les informations contenues.

    Vous devriez obtenir un tableau (lignes, colonnes, cellules, texte, couleurs) comme celui présenté ci-dessous:

    exemple de présentation structurée des données en tableau

    exemple de présentation structurée des données en tableau

    Question b: Comment le logiciel a-t-il analysé le contenu du fichier pour obtenir cet affichage, en lignes et en colonnes?

    Maintenant que la présentation est satisfaisante:

    ajoutez l’information suivante, en renseigant certaines valeurs dans le tableau:

    le commercial Sébastien a vendu 9814 Pommes dans la région Sud

    Question c: Quelles sont les réferences (coordonnées) des cases dans laquelle vous avez renseigné Sébastien, Pommes, région Sud, 9814? Justifier.

    Rechercher et Filtrer

    Rechercher

    Souvent, les tables contiennent de très nombreuses lignes, et ne peuvent pas toutes être présentées à l’écran. Il faut alors utiliser la fonction de recherche (bouton LOUPE à droite).

    Utiliser le bouton pour rechercher le nom Alain. Cliquer sur Suivant.

    Question d: Quelles sont les réferences des cases qui sont sélectionnés lorsque l’on clique plusieurs fois sur Suivant?

    Filtrer par critère simple

    Le fichier, lorsqu’il est importé depuis le bandeau Données, s’ouvre dans un classeur avec filtres.

    à gauche: ouverture du classeur AVEC filtres. à droite, ouverture SANS filtres

    à gauche: ouverture du classeur AVEC filtres. à droite, ouverture SANS filtres

    Si la feuille de calcul ne présente pas de filtres en tête de colonnes:

    • Commencer par selectionner toutes les colonnes A, B, C, D, E dans laquelles se trouvent les données du tableau.
    • Dans le bandeau Données, choisir Filtrer (entonoir).

    Il apparait alors des listes de choix au dessus des descripteurs du tableau. Pour filtrer selon l’un des descripteurs, cliquer sur l’une de ces listes de choix:

    • Sur le filtre appliqué à la première colonne (étiquette: Région), choisir Est.
    menu permettant la sélection par Région

    menu permettant la sélection par Région

    Filtrer selon un 2e critère

    • Sur le filtre appliqué à la troisième colonne (étiquette: Produits), choisir Pommes.

    Vous devriez obtenir un tableau ressemblant à celui-ci, mais avec plus de lignes:

    exemple de tableau filtré par Région ET par Produit (n'affiche que la 1ere ligne)

    exemple de tableau filtré par Région ET par Produit (n'affiche que la 1ere ligne)

    Question e: Combien de lignes sont affichées dans ce tableau filtré? Qu’ont-elles en commun?

    Les fonctions de calcul

    Somme de toutes les valeurs de la colonne Unités

    Pour revenir au tableau initial, rappuyer sur Filtre dans le bandeau d’Excel.

    Cela retire tous les filtres.

    Fonction somme

    Vous allez maintenant programmer une fonction de calcul sur le tableau: La fonction SOMME.

    Voici un lien vers le tuto de microsoft office.

    • cliquer dans la cellule juste sous la dernière valeur de la colonne Unités.
    • Ecrire debut de la formule: = SOMME(
    • puis faire une sélection étendue de toutes les valeurs de la colonne.
    • Valider avec la touche Entrer

    Question f: Quel est le resultat du calcul? Si le resultat est égal à zero, veuillez modifier le format comme expliqué en bas de page (Compléments), puis recommencer.

    Question g: Cliquer dans la case. Recopier la formule du calcul généré par le logiciel.

    Somme conditionnelle: SOMME.SI

    La fonction SOMME.SI permet de sélectionner certaines cellules d’une selection étendue.

    On va s’aider du concepteur de formule: Cliquer dans la cellule dans laquelle vous souhaitez rentrer la formule, sous le tableau, puis:

    • écrire = SOMME.SI(
    somme conditionnelle

    somme conditionnelle

    • cliquer sur le bouton fx de la barre de saisie.
    • Aidez vous des champs suivants pour remplir les plages pour cette formule:
    • Plage: faire une selection étendue des valeurs de la colonne Produits
    • Critères: écrire “Pommes”, ou bien cliquer sur le mot “Pommes” dans l’une des cellules du tableau (la C24 dans cet exemple.
    • Somme_plage: selectionner toutes les valeurs numériques de la colonne Unités:

    concepteur de formule pour SOMME.SI

    concepteur de formule pour SOMME.SI

    On a alors le nombre de Pommes vendues dans toute la France.

    Question h: Quel est le résultat? Recopier aussi la formule qui a été générée.

    Conclusion

    Un logiciel tableur (Excel, Calc, Number) permet de présenter les données à l’utilisateur en tableau, mais apporte aussi des fonctions de traitement. Ce sont les mêmes fonctions que l’on peut programmer avec un langage de traitement sur une Base de Données (SQL).

    Question i: Quelles sont les fonctions de traitement que vous avez utilisées lors de ce TP? Donner leur nom.

    Quel est le meilleur commercial?

    Dans cette entreprise, les pretendants au titre de meilleur commercial sont Maurice, Jérome et Sébastien.

    Question j: Utilisez la somme conditionnelle pour calculer le nombre de fruits total vendu par chacun des ces 3 commerciaux. Placez les résultats dans un nouveau tableau, sur la même page. Recopier ce tableau sur votre feuille. Décidez enfin: Qui remporte le titre de meilleur commercial?

    Compléments

    Format numérique

    Lors de l’import des données, le format des cellules est parfois incompatible avec les fonctions de calcul.

    Il faut alors définir une plage de valeurs numériques.

    Sélectionner toutes les valeurs numériques du tableau.

    Dans le bandeau Données, choisir: Convertir. Et faire suivant, plusieurs fois, sans changer les options proposées. Les cellules sont maintenant en format NOMBRE.

    reseaux sociaux

    Projet de fin de séquence:
    • créer une campagne de sensibilisation (affiche + post type Instagram/TikTok fictif) sur un enjeu réel : cyberharcèlement, désinformation, addiction au scroll, ou effet de bulle de filtre. Justifier le choix (ciblage, algorithme de recommandation, mécanismes d'engagement) en s'appuyant sur ce qui a été vu en cours.
    • Variante plus technique : concevoir le cahier des charges d'un "réseau social idéal pour lycéens" en explicitant les paramètres de confidentialité et leurs compromis.
    • identité numérique, modélisation des liens d’amitié, aspects economiques et sociaux

    Sous-sections de reseaux sociaux

    reseaux sociaux

    Black Mirror - Chute Libre S03EP01 commenté

    Black Mirror - Chute Libre S03EP01 commenté

    “La Mythocritique transhumanisme dans NoseDive (S3E1 - Black Mirror)”. Intervention proposée dans le cadre du 11ème Colloque International “Beyond Humanism”, à l’Université Catholique de Lille, le 12 juillet 2019.

    Definition d’un reseau social

    Ca sert à…

    Les reseaux sociaux sont des applications qui servent à créer des « communautés ». Il permettent aux usagers d’utiliser un compte public ou privé. Il permet de communiquer de manière instantanée, et se substituent peu à peu aux autres formes de communications par voie électronique (mails…).

    L’emergence des reseaux sociaux vient de l’apparition des premiers smartphones, qui ont permis de nouveaux services grâce au partage de photo, video, medias…

    Les applications de type RS ont des fonctionnalités étendues qui sont en convergence (utilisation de hashtag, post de texte, img, video, reactions de type LIKE, interopérabilité…)

    Les réseaux sociaux combinent trois fonctions fondamentales :

    • support de l’identité numérique ;
    • moyen de sociabilité sur la base de critères d’affinité ;
    • média réticulaire de communication interpersonnelle et/ou intergroupe.
    • moyen de se distraire

    Au démarrage: il faut créer un compte, le paramétrer. Il est conseillé de limiter la portée des données personnelles publiques lors de ce paramétrage. Par exemple, bloquer la lecture de votre liste d’amis, ne pas rendre votre mail et numero de telephone accessible à tous.

    L’activité sur le réseau social va aussi construire une identité numérique. Il est recommandé d’avoir une certaine hygienne sociale avec son activité sur les reseaux.

    identité numérique

    L’identité numérique est de son côté le lien entre une personne et ses informations virtuelles, pouvant être trouvées par le biais d’une simple recherche sur Internet. Cette identité est multiple: la personnalité que vous construisez est différente selon le reseau social utilisé et la manière avec laquelle vous l’utilisez.

    Toute activité sur le Web implique la création de traces. Certaines sont volontaires, d’autres involontaires. Elles sont collectées, partagées entre applications et stockées dans des bases de données. Leur addition construit l’identité numérique de chacun.

    Une conséquence de l’usage d’un ou plusieurs RS est la constitution d’une veritable identité numérique pour la personne, puisque chaque reaction/publication, surf, se fait avec sa propre identité.

    e-reputation

    La e-reputation est due à l’identité numérique que l’on se construit, mais aussi par ce qu’en disent les autres.

    La e-réputation a tendance à définir, aux yeux des autres, ce que vous êtes, selon la manière dont on parlera de vous, positivement ou négativement. Cette notoriété Internet peut pencher d’un côté comme de l’autre, en tout cas elle sera très représentative de la manière dont on vous percevra, qui que vous soyez.

    Les sites de vente en ligne permettent aux usagers d’être egalement vendeurs. La reputation du vendeur (et de l’acheteur) se construit au fil de ses transactions, grâce aux notes obtenues.

    Viralité: Avec les reseaux sociaux, la propagation d’une information, surtout si elle est sensationnelle, se fait très facilement, à une très grande echelle. Cette propagation explosive vient de la manière avec laquelle les usagers sont en relation. C’est ce mécanisme qui agrave les problèmes de cyberharcelement.

    Modelisation d’un reseau social

    Documents issus des pages:

    Pour comprendre comment se propagent les informations, on a cherché un moyen de représenter visuellement l’organisation du réseau social. D’où l’utilisation des graphes.

    Dans un réseau du genre de « Facebook », où l’amitié est une relation symétrique, on va donc représenter chaque personne par une bulle (les sommets du graphe) et chaque relation par un lien entre deux bulles (les arêtes du graphes).

    Utiliser une représentation visuelle: le graphe

    Graphe non orienté

    A faire soi-même :

    1. Construire le graphe de relations amicales (type Facebook) du petit groupe suivant :
    • Ashley est amie avec Benoit, Dido et Ela
    • Benoit est ami avec tout le monde
    • Cédric est ami avec Benoit et Ela
    • Dido est ami avec Ashley et Benoit
    • Ela est amie avec Ashley, Benoit et Cédric
    1. Déterminer quelle est la personne la plus influente dans ce réseau
    2. Quel chemin va emprunter une publication, systématique re-publiée, pour parvenir de Denis à Camel?

    Corrections : 3 visualisations de la même situation

    Seule la 3e visualisation montre clairement que Benoit est l’élément central de ce graphe. On verra plus loin que la seule représentation visuelle ne permet pas toujours de faire des mesures sur le graphe. Il faudra la plupart du temps utiliser un algorithme.

    Graphe orienté

    Dans un réseau social comme « X, ex-Twitter », il s’agit de s’abonner à quelqu’un pour suivre ses publications. La relation est à sens unique, si vous suivez quelqu’un cette personne ne vous suit pas forcement.

    La flèche traduit alors une relation. Cela peut être, au choix:

    • suit …
    • est suivi par…

    De tels graphes permettent ainsi aux sites de réseaux sociaux de vous proposer de nouveaux contacts, lieux ou autres en fonction de vos envies et de vos connaissances.

    Exemple:

    1. D’après le diagramme précédent, quelle visite pourrait-on conseiller à Bob ?
    2. Supposons que Bill et Alice visitent la tour Eiffel en même temps, et que leurs données de géolocalisation sont partagées avec l’application de reseau social. Que pourrait faire l’appli?

    Mesures sur un graphe

    Pour le graphe non orienté suivant, comportant une centaine de sommets, on établit 2 représentations:

    a gauche: graphe non organisé, a droite: organisé

    a gauche: graphe non organisé, a droite: organisé

    Le graphe de droite est organisé en plaçant tous les sommets sur une couronne.

    Le graphe de gauche montre que certains sommets sont plus connectés que d’autres. A droite, ces mêmes sommets sont répartis régulièrement sur la couronne.

    1. Repérer ces sommets particuliers sur chacun des 2 graphes
    2. Quel est la signification de ces connexions plus nombreuses pour certains sommets?

    On donne 2 représentations d’un nouveau reseau:

    1. Que fait apparaître cette organisation des sommets?
    2. Quelle peut être la conséquence de ces regroupements sur les réseaux sociaux, et dans un contexte élargi : à la vie offline?

    Definitions

    La distance entre deux sommets d’un graphe est le nombre minimum d’arêtes pour aller du sommet à un autre. La distance entre a et f est 2.

    L’écartement d’un sommet est la distance maximale existant entre ce sommet et les autres sommets du graphe. Pour le sommet a, la plus grande distance avec un autre sommet est 2. L’écartement est donc de 2.

    Le centre d’un graphe est le sommet d’écartement minimal (le centre n’est pas nécessairement unique). Ci-contre, tous les sommets ont un écartement de 2, sauf d qui a un écartement de 1. Le centre est donc d.

    Le rayon d’un graphe G est l’écartement d’un centre du graphe. Ici d est le centre et d a un écartement de 1. Donc le rayon est de 1

    Le diamètre d’un graphe est la distance maximale entre deux sommets du graphe. Ici le diamètre est de 2.

    Le degré d’un sommet est le nombre de sommets qui lui sont connectés. Il s’agit du nombre d’amis.

    Le rayon et les centres du graphe vont permettre d’identifier les presonnes les plus influentes du reseau.

    A vous de jouer. Pour simplifier, imaginons un réseau social ne possédant que 7 abonnés :

    1. Déterminez-le (ou les) centre(s) du graphe ci-contre.
    2. En déduire le rayon du graphe.
    3. Déterminer le diamètre du graphe.
    4. Représenter les relations d’amitié dans un tableau
    L M N O P Q R
    M
    N
    O
    P
    Q
    R

    Ce tableau, permet-il de repondre plus facilement aux 3 premieres questions?

    Experience de Milgram

    Milgram envoie soixante lettres à des recrues de la ville d’Omaha dans le Nebraska. Il leur demande de faire suivre cette lettre à un agent de change, vivant à une adresse fournie, dans la ville de Sharon dans le Massachusetts. Les participants pouvaient seulement passer les lettres, de main à main, à des connaissances personnelles qu’ils pensaient être capables d’atteindre l’objectif.

    Remarque: Une des difficultés dans la conduite de ces études tient à la supposition que les gens dans la chaîne sont compétents pour découvrir le lien entre les deux personnes servant de terminaux. Ceci est plus evident avec des communautés, dans lequel le chemin entre usagers va exister et être relativement court. Mais il n’est pas certain que le monde lui-même soit un petit monde

    Le cas des influenceurs

    Voir le paragraphe plus haut les mesures sur un graphe, et la recherche de centres.

    Paradoxe des communautés

    Quels éléments permettent aux algorithmes des réseaux sociaux de produire des clusters?

    Véracité contre viralité, désinformation

    Petits mondes

    Sur le document suivant, on voit que les groupes à centre d’intérêt spécifique, ou communautaires peuvent avoir des liens fragiles entre-eux.

    En 2015 à Bombey, en Inde, le gouvernement a interdit la consommation de viande. La situation a fait polemique dans le pays et notamment sur Twitter, où le hashtag #BeefBara été largement repris.

    Sur le document suivant, on a colorié en vert et en rouge les tweets pour et contre l’interdiction de la consommation de viande. On constate un lien étroit entre les opinions et l’appartenance à une communauté. extrait du livre Delagrave SNT p135.

    Les reseaux sociaux conduisent fréquemment à rester dans un “petit monde” où l’on est en relation avant tout avec des personnes qui nous ressemblent et pensent comme nous, au risque d’un certain repli sur soi.

    Aspects économiques et controverses

    Victimes des algorithmes. L’usager d’un reseau social est soumis, voire manipulé par les algorithmes de celui-ci.

    Mais quels sont ces algorithmes au final? Et comment parviennent-ils à nous fournir un contenu personnalisé?…

    Les reseaux sociaux parlent pour nous

    La collecte de données personnelles est le ciment du modèle économique des réseaux sociaux. Au regard de ce que l’on vient d’apprendre, cela fonctionne comme un cercle vicieux :

    • Plus l’on interagit sur les plateformes numériques, plus elles enregistrent nos données personnelles.
    • Plus elles enregistrent nos données personnelles, plus elles personnalisent nos flux d’informations, en usant d’objets techniques liés à l’économie de l’attention.
    • Plus nos flux d’informations sont personnalisés, confortables et rassurants, au détriment de ce qui se passe en dehors de ces chambres d’écho (bulle d’informations), plus nous passons de temps sur les plateformes numériques.

    … et plus nous interagissons et produisons de données personnelles. Algorithmables, mémorisables, monétisables, profilables par les plateformes numériques.

    Et cela déborde de la sphère économique pour empiéter dans la sphère psychologique…

    C’est tellement vrai qu’aujourd’hui d’anciens responsables de Facebook dénoncent des pratiques qu’ils ont contribué à mettre en place. Diffusion de la vidéo “D’anciens responsables de Facebook alertent quant aux dangers des réseaux sociaux”.

    Une journaliste parisienne inscrite sur un fameux site de rencontre a décidé de réclamer ses données personnelles auprès du site. Pour 1’équivalent d’une fréquentation de 4 années, el1e a reçu pas moins de 800 pages résumant les différents aspects de sa vie privée : ses « likes » sur Facebook, ses photos postées sur Instagram, ses diplômes universitaires, mais aussi ies dates, lieux et contenus de ses conversations… Que pourrait-il se passer dans le cas oit ces informations seraient divulguées ou revendues à une autre entreprise ?

    Témoignage : elle réclame ses données et reçoit". " 800 pages ! D’après Libération

    Addiction

    Les reseaux sociaux peuvent repondre à un besoin de reconnaissance. Cela peut entrainer un comportement addictif dans leur usage, en multipliant les parutions ou autres activités (partage, like).

    C’est à partir de ce constat que Beomseok Yang, réalisateur sud-coréen, a décidé de produire un court-métrage montrant l’addiction aux réseaux sociaux. Notamment chez les jeunes.

    La vidéo, intitulée “Social Network”, nous permet de suivre la journée d’un jeune homme en mettant en avant toutes les interactions sociales qu’il a au cours de cette journée.

    Beomseok Yang: SOCIAL NETWORK

    Beomseok Yang: SOCIAL NETWORK

    Are You Living an Insta Lie? Social Media Vs. Reality

    Are You Living an Insta Lie? Social Media Vs. Reality

    Les reseaux sociaux mettent en place des fonctionnalités addictives pour vous faire passer plus de temps sur leur plateforme. Il est prouvé que passer plus de 30 min par jour sur ces reseaux sociaux augmente l’anxiété et le sentiment de solitude.

    De plus, l’utilisation d’appli tierces (jeux, quizz) constitue une menace pour nos données confidentielles, et renforcent le marketing ciblé dont on oeut faire l’objet.

    Comprendre l’algorithme de recommandation

    L’algorithme de Facebook, c’est comme au restaurant ! site academique ac-nantes > Ressource

    Pour comprendre ce qui apparaît sur notre Newsfeed au moment où l’on se connecte à Facebook, on peut comparer l’algorithme du réseau social aux mécanismes qui nous permettent de choisir un menu au restaurant.

    NOTA : ressource élaborée d’après l’article publié sur le site Le blog du modérateur, par Thomas Coëffé, le 27 octobre 2017.

    Cyberviolence

    Def:

    • la cyberviolence, c’est l’acte agressif et intentionnel perpétré par un individu ou un groupe d’individus au moyen de formes électroniques de communication.

    • le cyberharcelement consiste en des agissements malveillants répétés, dans un cadre public ou restreint, qui peuvent prendre différentes formes : intimidations, insultes, menaces, rumeurs, publication de photos ou vidéos compromettantes, etc.

    Avec Ies spécificités du numérique, on ajoute un impact plus conséquent aux violences. En effet, les contenus offensants peuvent se répandre très rapidement grâce aux reseaux qui accelerent et grandissent l’échelle des échanges. D’autre part, le caractere anonyme des echanges favorise le sentiment d’impunité. Une certaine distance s’installe et diminue la capacité d’empathie ou la conscience de ses actes. Dans certains cas, il rend aussi difficile l’identification de l’auteur. Enfin, les cyberviolences n’ont pas de limite temporelle: elles laissent toujours une trace. Une fois diffusée sur la toile, on ne peux plus maitriser son cheminement.
    d’après un document de SNT Nathan p76

    Droit pénal

    Le fait de harceler une personne par des propos ou comportements répétés avantpour objet ou pour effet une dégradation de ses conditions de vie se traduisant par une altération de sa santé physique ou mentale est puni d’un an d’emprisonnement lorsque ces faits ont causé une incapacité totale de travai[ inférieure ou égale à huit jours. Ou et de 15 000 € d’amende si cela n’a entraîné aucune incapacité de travait.
    Article 222-33-2-2 du code penal

    Typologie des Cyberviolences

    Typologie des Cyberviolences

    Droit à l’oubli

    grâce à l’arrêt de la Cour de justice de l’Union européeenne du 13 mai 2014, il est possible de réclamer le “droit à l’oubli”. Pour l’appliquer, il faut demander au site d’origine de supprimer les information outrageuese et au moteur de recherche de ne plus les référencer.

    Liens

    Amazing mind reader reveals his 'gift' - video - le mentaliste

    Amazing mind reader reveals his 'gift' - video - le mentaliste

    Le web

    Projet de fin de séquence:
    • créer un mini-site HTML/CSS de 3-4 pages sur un sujet de son choix, avec navigation, liens hypertexte, structuration correcte (balises sémantiques).
    • une "enquête" sur un site réel (certificat HTTPS, mentions légales, cookies) restituée sous forme de fiche d'analyse.

    Sous-sections de Le web

    le web

    • Cours le web et les moteurs de recherche: Lien
    • Cours modèle client-serveur, URL: Lien
    • Cours langage HTML: Lien
    • Compléments sur CSS: Lien
    • Travaux pratiques dans la partie Compétences numeriques > publier du site

    le Web et les moteurs de recherche

    Le world wide web, ou toile en français, est un service construit sur l’infrastructure du reseau internet pour mettre à la disposition des utilisateurs des documents repartis au niveau mondial.

    Lors de sa navigation, l’usager d’internet va suivre des liens qui connectent les pages entre-elles (ce que l’on appelle surfer sur le Web).

    Historique du 3w

    Le “World Wide Web”, plus communément appelé “Web” a été développé au CERN (Conseil Européen pour la Recherche Nucléaire) par le Britannique Sir Timothy John Berners-Lee et le Belge Robert Cailliau au début des années 90. À cette époque les principaux centres de recherche mondiaux étaient déjà connectés les uns aux autres, mais pour faciliter les échanges d’information Tim Berners-Lee met au point le système hypertexte. Le système hypertexte permet, à partir d’un document, de consulter d’autres documents en cliquant sur des mots clés. Ces mots “cliquables” sont appelés hyperliens et sont souvent soulignés et en bleu. Ces hyperliens sont plutôt connus aujourd’hui sous le simple terme de “liens”.

    Cette première page est d’ailleurs encore en consultation sur le lien suivant : http://info.cern.ch/hypertext/WWW/TheProject.html

    Normalisation de la présentation de l’information (w3c)

    Le bon fonctionnement du www nécessite le respect de normes et de formats de fichiers et de protocoles entre serveurs et clients.

    Le World Wide Web Consortium, abrégé par le sigle W3C, est un organisme de standardisation à but non lucratif, fondé en octobre 1994 chargé de promouvoir la compatibilité des technologies du World Wide Web telles que HTML, CSS, JS, …

    W3C: un organisme qui définit les standarts du web

    Le web fonctionne avec : le protocole HTTP (HyperText Transfert Protocol), les URL (Uniform Resource Locator) et le langage de description HTML (HyperText Markup Language).

    La lecture et l’usage des hyperliens d’une page html nécessite d’utiliser un navigateur.

    Adresse d’une page web: URL

    Uniform Ressource Locator: où est la page?

    Une URL (Uniform Resource Locator) est l’adresse d’une page web. Voir la page le web: modele client-serveur

    On peut entrer dans une page directement en saisissant son URL.

    On peut alors se demander: Comment est tissée la toile du web? C’est à dire, comment sont reliées ces pages les unes aux autres…

    Tout d’abord, il y a les liens hypertext. Ces liens permettent la navigation de page en page, et c’est comme cela que l’on peut utiliser le Web.

    Ensuite, il y a l’entrée par un moteur de recherche.

    Trouver une page: moteurs de recherche

    Principe

    Avant l’usage généralisé des moteurs de recherche, les sites étaient référencés par dans des annuaires web: répertoire web, annuaire Internet ou répertoire Internet est un site web proposant une liste classée de sites Web.

    Le classement se fait typiquement dans une arborescence de catégories, censée couvrir tout ou partie des centres d’intérêt des visiteurs.

    Aujourd’hui, ils ont perdu de l’interêt face à la facilité d’utilisation des moteurs de recherche, et ne sont plus utilisés que dans des cas particuliers voir article

    dernière page de l'annuaire Yahoo avant sa fermeture en 2014

    dernière page de l'annuaire Yahoo avant sa fermeture en 2014

    Un moteur de recherche: Logiciel qui dispose d’une indexation des pages internet. Son fonctionnement repose sur plusieurs étapes, qui sont executées en continu:

    • La collecte automatique d’informations, par des robots d’exploration (Crawlers), qui parcourent le reseau hypertexte du web.
    • Le référencement: un traitement qui consiste à analyser des pages pour y detecter des mots clés utilisés fréquemment par les internautes. L’indexation, est la manière dont le moteur de recherche organise ces informations. Il va créer une table de mise en correspondance mot-clé <=> URL de la page.

    L’internaute va utiliser l’interface du moteur de recherche pour faire une recherche par mots-clés:

    • Traitement de la requête: Les mots clés sont comparés avec ceux référencés et le moteur de recherche construit une liste ordonnée, un classement établi grâce à un calcul selon un algorithme. C’est un classement par degré de pertinence.
    • Le moteur de recherche va retourner une liste ordonnée de liens en rapport avec les mots clés proposés par l’internaute.

    L’utilisateur va alors cliquer sur le lien de son choix parmi les propositions du moteur de recherche. Et se retrouver sur la page proposée, sans avoir à connaitre et mémoriser son URL.

    fonctionnement d'un moteur de recherche

    fonctionnement d'un moteur de recherche

    Mooc SNT: internet et le web: 3'00 et plus (moteurs de recherche)

    moteurs de recherche : fonctionement

    video: Mooc SNT internet et le Web + moteur recherche

    Les moteurs de recherche – Mediaprovence (juin 2019) https://www.youtube.com/watch?v=Y8l4hKNQOEY

    moteurs de recherche : fonctionnement

    video: Fonctionnement du moteur de recherche – FenetresurWordpress

    Activité 1 - simuler un moteur de recherche

    Créer un index à partir de mots clés, relevés dans les différents textes de Raymond Queneau: Exercices de style.

    Activité inspirée du document sur : imo.universite-paris-saclay.fr

    Activité 2 - recherche documentaire

    a) Comment fait un moteur de recherche pour trouver des milliards de pages du Web ?

    b) Comment fait le moteur de recherche pour faire un classement entre ces pages ? Qu’est-ce que le SEO (Search engine optimisation)

    c) Quand vous avez cinq à six mille ordinateurs qui travaillent pour vous, il est certain que plusieurs tomberont en panne chaque jour. Comment un moteur de recherche fait-il pour ne jamais s’arrêter ?

    d) Pour fabriquer un index, il faut lire toutes les pages qu’il index sur le Web. Le moteur de recherche n’a pas fini de les lire que certaines pages ont déjà changé et qu’il lui faudrait les relire. Et découvrir de nouvelles pages… Comment se tenir au courant des « nouveautés » du Web ?

    e) On fait des fautes d’orthographe. Comment un moteur de recherche peut-il répondre aux questions quand les textes et les questions contiennent des fautes ?

    f) Moteur de recherche et IA générative : Les moteurs de recherche évoluent et proposent maintenant de nouvelles expériences. Quelle est la différence entre un moteur de recherche, comme Google, et une application de génération de texte à base d’IA comme Chat GPT ?

    Questions inspirées du document sur : imo.universite-paris-saclay.fr

    Moteur de recherche et IA générative

     target=

    Les surprises à venir des moteurs de recherche - FRANCE 24

    Les firmes OpenAI, Google ou encore Perplexity vont modifier notre manière de rechercher sur Internet.

    ChatGPT, conçu par le groupe OpenAI, est un Logiciel de Traitement automatique du langage naturel. Il repose sur un modèle d’apprentissage automatique et une architecture de réseau neuronal.

    OpenAI a dû former le modèle à travers une quantité importante de données pour que le système puisse interagir de manière naturelle avec un interlocuteur humain. (lecture de livres, de blogs, etc…). Depuis, il procède à une optimisation de l’apprentissage via une couche supplémentaire de formation utilisant la RLHF ou Reinforcement Learning from Human Feedback.

    ChatGPT va servir à générer des textes de niveau humain, des traductions, mais aussi d’autres contenus : images, videos, constructions à partir modèles physiques (sequences et repliement des proteines !). Il peut servir à analyser et reconnaître des formes (medecine, reconnaissance faciale…)

    L’interface du logiciel est très différente de celle d’un moteur de recherche: Avec ChatGPT Search, on a l’impression de participer à une véritable conversation, en ajoutant des informations à sa requête initiale. ChatGPT comprend et se souvient du contexte. Une fois la requête lancée, il rassemble les informations provenant de différentes sources pour fournir des réponses approfondies, et générer un texte ou un média.

    Ces logiciels génératifs de texte ou image peuvent aussi répondre à une recherche sur le net, mais ils se distinguent des moteurs de recherche:

    Chatbot versus moteur de recherche: ChatGPT Search vs Google Search

    Le type de reponse de ChatGPT va être davantage construite, comme une synthèse. Par exemple, ChatGPT Search peut comparer des produits côte à côte, en soulignant les avantages et les inconvénients ou même en établissant un tableau comparatif simple pour vous aider à choisir.

    En revanche, Google Search traite chaque question séparément, de sorte qu’il ne relie pas les réponses de la même manière et n’est pas prévu pour maintenir une conversation. On l’utilise plus pour obtenir des informations rapides, des informations visuelles ou des options de réservation et d’achat.

    Inconvénients des Chatbot et moteurs génératifs basés sur IA:

    • Gourmand en ressources énergétiques, puissance de calcul et mémoire significatifs
    • Temps de calcul long, rendant difficile le traitement en temps réel
    • Absence de mise à jour en temps réel (n’a pas accès à Internet en temps réel)
    • peut produire des réponses biaisées ou limitées.
    • Pose des questions éthiques et juridiques, notamment en ce qui concerne l’utilisation de données protégées par le droit d’auteur et la confidentialité des informations.

    sécurité et confidentialité

    Moteurs de recherche et problème de confidentialité

    Un moteur de recherche, c’est une entreprise, qui doit faire des profits. Ses revenus viennent des annonceurs (sites commerçants) qui sont mis en avant par des publicités ciblées. C’est un mode de référencement payant, par opposition à celui naturel, réalisé à partir des contenus redactionnels (SEO).

    Les moteurs de recherche mettent en avant une expérience plus personnalisée de l’internaute. Et ils ont besoin pour cela de récupérer vos données.

    moteurs de recherche : fonctionement

    video: Les moteurs de recherche – Mediaprovence (juin 2019)

    Limiter ses traces numériques: solutions

    Ce que le moteur de recherche appelle des données échangées (entre services de la même entreprise), sont vos données personnelles. Votre identité, vos contacts, la durée des appels, date, titres de vidéos, musiques consultées, historique des coord GPS, adresse IP, données des capteurs de l’appareil, requete lors des recherches, historique de navigation…

    Pour limiter ses traces sur le Web, et reduire cette collecte de données qui vous concernent, vous pouvez:

    • dans le navigateur Mozilla : effacer les traces : bouton bibliothèqe, Historique, marques pages et plus encore > Historique > Effacer l’historique recent (cocher au choix : historique, historique des formulaires et des recherches, cookies et câche) ET Données > préférence des sites
    • paramétrer le navigateur : menu > Options > Vie privée et sécurité (Il y a plusieurs niveaux de sécurité). Dans Identifiants et mots de passe > afficher les mots de passe. Dans cookies et données > recherche la présence d’un cookie de connexion au site du lycée…
    • et Vie privée : blocage de contenus : toujours, afin de bloquer les contenus tiers qui peuvent ralentir la navigation ou distraire.

    Impacts sur les pratiques humaines

    • Aspects positifs: liberté d’information, d’opinion

      • Le web permet à chacun de publier des informations sans contrôle préalable par une autorité. Cette revolution democratique amène la présence de fausses nouvelles (fake news) et le besoin de verification. Libération (désintox) et Le Monde (le blog des decodeurs) possèdent des espaces dédiés à la pratique, dédiant des journalistes à cette seule tâche.
      • Wikipedia est un exemple d’encyclopedie libre et participative, où des centaines d’internautes publient et relisent et effectuent des milliers de changement par heure.
    • aspects négatifs:

      • Le web et le droit d’auteur: besoin de protection grâce à des licences (creatice commun)
      • Les traces laissées de manière voulue ou non lors de sa navigation
      • la surveillance des individus sur le web
    bigdataiswatchingyou

    D’où l’importance d’un cadre juridique permettant de protéger les usagers, préoccupation à laquelle répond le règlement général sur la protection des données (RGPD).

    • Cout environnemental
      • Selon Google, toute requête sur son moteur de recherche consomme autant d’énergie qu’une ampoule de 60 watts qu’on allume pendant 17 secondes. Soit, en moyenne, une émission de 0,7 gramme de CO2.
      • 1 mail simple émet 4 g CO2. 1 mail avec pièce jointe émet 35 gCO2, soit près de 10 fois plus !
      • Pour une requête sur ChatGpt : Une courte conversation (quelques interactions) avec le dernier modèle de ChatGPT émet environ 270g d’équivalent CO2 (eqCO2), soit près d’une tonne de CO2 par an pour dix échanges par jour.

    Exercices

    Construire une URL (Uniform Ressource Locator)

    Pour accéder aux documents d’un serveur, il faut saisir une URL (une adresse) dans un navigateur.

    Un ordinateur serveur héberge des dossiers et des fichiers. Le chemin vers un document est mis après l’adresse du nom de domaine dans l’URL.

    Par exemple, pour atteindre fichier1.css, il faut saisir l’adresse :

    http://nom_du_domaine.fr/dossier2/fichier1.css

    exercice inspiré de la page web du site pixees.fr/informatiquelycee

    exercice inspiré de la page web du site pixees.fr/informatiquelycee

    • Quelle est l’URL à saisir pour atteindre fichier4.js ?
    • Quelle est l’URL à saisir pour atteindre fichier6.html ?

    Autres exercices

    fiche d’exercices: lien vers le pdf

    Liens

    modele client serveur

    Le Web et les documents hypertexte

    Le web est un de ces services qui consiste à pouvoir naviguer sur des pages web reliées entre elles par des liens hypertextes.

    • Une brève introduction:
    mooc SNT: Internet et le Web

    mooc SNT: Internet et le Web

    • le rôle du navigateur: présenter et rendre les pages interactives
    histoire du web - Delagrave

    histoire du web - Delagrave

    Il existe plusieurs logiciels navigateurs (Mozilla, Chrome, Safari,…). Et pourtant, malgré cette diversité et ces évolutions du langage, ceux-ci vont interpréter ces fichiers et afficher les pages (presque) de la même manière car ils se réferent tous aux mêmes recommandations, qui sont les normes dictées par le w3c.

    Une petite différence peut exister pour le rendu d’une même page, mais avec plusieurs navigateurs différents. Cela est du aux propriétés par défaut utilisées par le navigateur pour l’affichage des différents éléments html de la page.

    Bilan: Le Web fonctionne avec des documents qui sont interconnectés par des hyperliens. Le web necessite d’utiliser un logiciel appelé navigateur qui sert à présenter les pages, surfer, mais aussi remplir des formulaires, interagir avec la page.

    Cette navigation sur le web est possible grâce à la relation client-serveur du navigateur avec le serveur qui heberge la page. Ce serveur possède une adresse sur le net que l’on traduit de manière symbolique grace à l’URL. Cette relation necessite d’utiliser des protocole de communication, comme http.

    Adresse d’une page web: URL

    Uniform Ressource Locator: où est la page?

    Une URL (Uniform Resource Locator) est l’adresse d’une page web. Elle est composée de 3 parties:

    • http:// ou https:// qui correspond au protocole de communication client-serveur développé pour le web.
    • Un nom de domaine, souvent une marque, une entreprise, une association, …
    • un chemin qui pointe vers une ressource ou page précise.
    • la ressource

    Par exemple, la page html que vous consultez, fait partie du domaine allophysique.com et se trouve à l’emplacement /docs/snt_2nde/pages/page4/web/index.html:

    https://allophysique.com/docs/snt_2nde/pages/page4/web/index.html

    Cette URL est construite en 3 parties distinctes:

    nom de domaine / chemin / ressource

    nom de domaine / chemin / ressource

    Le modèle client-serveur

    Activité d’introduction: Le Web nous traque

    Do Not Track explore les différentes manières dont le Web moderne enregistre et traque nos activités, nos publications et nos identités.

    Debut de la vídeo: je sais que où vous habitez et que vous avez une belle journée je sais que vous utilisez un PC... Comment fait le site pour savoir ceci ? Quelles informations ai-je envoyé (sans le vouloir) pour charger la page?

    Client -> Serveur

    Un système informatique fonctionne sur le modèle client-serveur : L’ordinateur client a besoin d’établir des connexions avec un ordinateur serveur pour une grande partie des services dont il a besoin (consulter une base de données, communiquer, ouvrir des pages internet, charger des vidéos…).

    Une fois la connexion établie, l’ordinateur serveur lui répond en lui renvoyant les données necessaires.

    modele client serveur

    modele client serveur

    mode client-serveur. Un serveur peut repondre aux requetes de multiples clients

    mode client-serveur. Un serveur peut repondre aux requetes de multiples clients

    Le serveur lui repond en renvoyant un (des) fichier(s) qui constituent des fragments de page (en HTML, js, css, png, …). Ces fragments complètent la page, son contenu, son style, ses éléments interactifs, ou apportent des ressources (images, videos…). C’est le navigateur qui interprète ces fichiers (ces fragments de page) et assure l’affichage de la page.

    Mais alors ici, le serveur connaissait des informations sur le client. Pourquoi?

    Le protocole HTTP

    Usage du navigateur

    Le navigateur est le logiciel qui permet d’utiliser le Web. Il se connecte au serveur à l’adresse définie par l’URL.

    Il envoie une requete pour demander la ressource à l’aide du protocole HTTP.

    HTTP : HyperText Transfert Protocol, permet au navigateur de demander une page sur le reseau et au serveur de la transmettre.

    Dans le protocole HTTP, une méthode est une commande spécifiant un type de requête, c’est-à-dire qu’elle demande au serveur d’effectuer une action. En général l’action concerne une ressource identifiée par l’URL qui suit le nom de la méthode. (definitions issues de https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol)

    Le navigateur utilise souvent la méthode GET lors de l’envoi d’une requete:

    outil reseau du navigateur

    observation de la requete GET à l'aide de l'outil reseau du navigateur

    Contenu: données et metadonnées

    Dans le fichier de reponse, il y a 2 parties :

    • Une partie concerne l’en-tête : des métadonnées sur le document • L’autre partie est constituée des données à afficher (balises HTML)

    Du côté client, il y a aussi des métadonnées. C’est ici que l’on retrouve :

    • Information de la methode GET
    • url demandée (non de domaine de serveur
    • Accept (text/html, fr…)
    • Site depuis lequel la demande est effectuée

    MAIS AUSSI, des informations partagées (et qui ne devraient pas l’être) qui devraient faciliter la session avec le site demandé : les cookies.

    Champ d’en-tête Signification Exemple
    Accept Les types de contenu que le client peut traiter ; si le champ est vide, il s’agit de tous les types de contenu. Accept: text/html, application/xml
    Accept-Charset Quels jeux de caractères le client peut afficher. Accept-Charset: utf-8
    Cookie Cookie stocké pour ce serveur Cookie: $Version=1; Content=23
    Content-Length Longueur en octets Content-Length: 212
    Content-Type Type MIME: text/plain pour les fichiers texte, application/.. pour le reste Content-Type: application/x_222-form-urlencoded
    Date Date et heure de la demande Date: Mon, 9 March 2020 09:02:22 GMT
    Host Nom de domaine du serveur Host: exemple.fr
    Referrer URL de la ressource à partir de laquelle la demande est faite (c’est-à-dire à partir de laquelle le lien a été créé) Referrer: https://exemple.fr/index.html
    User-Agent navigateur du client Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36

    reseau P2P

    C’est un mode d’organisation sur internet où toutes les machines se comportent alternativement comme clients ou serveurs.

    mode P2P. Chaque machine joue alternativement le rôle de client et de serveur

    mode P2P. Chaque machine joue alternativement le rôle de client et de serveur

    Ce mode a pu être utilisé pour partager illégalement des fichiers en infraction avec le droit d’auteur. La repartition des documents sur de multiples machines a compliqué les poursuites judiciaires.

    Ce mode P2P connait un regain d’interet avec les Blockchains qui consistent à repliquer sur de nombreuses machines les preuves chifrées et vérifiables d’un ensembles d’informations enregistrées. (monnaies virtuelles)

    sécurité et confidentialité

    Ce que le moteur de recherche appelle des données échangées (entre services de la même entreprise), sont vos données personnelles. Votre identité, vos contacts, la durée desappels, date, titres de vidéos, musiques consultées, historique des coord GPS, adresse IP, données des capteurs de l’appareil, requete lors des recherches, historique de navigation…

    Pour limiter ses traces sur le Web, et reduire cette collecte de données qui vous concernent, vous pouvez:

    • dans le navigateur Mozilla : effacer les traces : bouton bibliothèqe, Historique, marques pages et plus encore > Historique > Effacer l’historique recent (cocher au choix : historique, historique des formulaires et des recherches, cookies et câche) ET Données > préférence des sites
    • paramétrer le navigateur : menu > Options > Vie privée et sécurité (Il y a plusieurs niveaux de sécurité). Dans Identifiants et mots de passe > afficher les mots de passe. Dans cookies et données > recherche la présence d’un cookie de connexion au site du lycée…
    • et Vie privée : blocage de contenus : toujours, afin de bloquer les contenus tiers qui peuvent ralentir la navigation ou distraire.

    Liens

    HTML

    video - evolution des pages web 1990-2019

    video - evolution des pages web 1990-2019

    Document Web: HTML

    Contenu et Structure

    Le contenu des documents Web est rédigé en langage HTML (acronyme de Hypertext Markup Language). HTML est un langage interprété (par le navigateur). C’est un langage de description qui gère le contenu (le texte et les images), en ajoutant des éléments de structure, comme par exemple:

    • mettre le texte dans un paragraphe
    • mettre du texte en relief
    • insérer un hyperlien sur le texte
    • mettre un titre à la page, au paragraphe
    • …
    Lire la video depuis 20' => 1min40'

    Lire la video depuis 20' => 1min40'

    Cette combinaison de contenu et de structure a été vue avec la création d’un document sous LibreOffice Writer. Ces documents ne peuvent toutefois pas servir à la navigation sur internet. Leur poids est trop important, et le code de la page n’est pas normalisé. On utilise pour la redaction de ces pages une combinaison de langages (html, css, js) qui seront rédigés de manière normalisée (recommandations du w3c), et interprétés de la même manière ou presque par tous les logiciels navigateurs.

    Les éléments en HTML

    Balises

    Les élements sont décrits par des balises, comme par exemple, l’élément paragraphe p, est déclaré à l’aide d’une balise <p>. Toute balise ouverte doit être refermée, ici avec </p>. Et le contenu (souvent textuel), est mis entre ces deux balises:

    exemple d'une balise paragraphe

    exemple d'une balise paragraphe

    Ces balises s’utilisent comme des parenthèses et peuvent être imbriquées. Une mauvaise imbrication de balises constitue une erreur.

    Par exemple: Une imbrication correcte:

    <body>
        <div>  
          <h1>Wanted!</h1>
        </div>
    </body>

    Une imbrication non correcte:

    <body>
        <div>  
          <h1>Wanted!</h1>
        
    </body>
    </div>

    Les balises principale

    Les balises sont les instructions en langage HTML des éléments structurants de la page web.

    Les balises se distinguent entre celles qui n’ont pas d’attribut obligatoire, et celles qui en ont. Un attribut va ajouter des fonctionnalités à l’élément HTML, et modifier son allure ou son fonctionnement.

    Voir l’exercice 1

    Balises sans attribut

    Les principales balises structurantes sont:

    • h1, h2, h3, … h6
    • div
    • p
    • span
    • …

    Elles s’utilisent de la manière suivante:

    <h1>Texte</h1>
    <p>Texte</p>

    Il existe aussi des balises qui doivent être combinées, comme celles de listes:

    • ul (parent) => li (enfants) pour une liste à puces
    • ol (parent) => li (enfants) pour une liste ordonnée (numérotée)

    exemple:

    <ul>
    <li>ligne1</li>
    <li>ligne2</li>
    </ul>

    balises avec attribut obligatoire

    image

    Il s’agit d’une balise orpheline.

    <img src="lien_vers_la_ressource.jpg">

    lien

    Voir l’exercice 1

    <a href="lien_vers_la_ressource.html">texte cliquable</a>

    On peut ajouter des attributs à une balise. Cela permet de modifier son comportement. Par exemple, la balise de lien a prend un argument obligatoire qui est href, et qui pointe vers la ressource. Lorsque l’on clique sur le contenu (ce qui est affiché par la balise), on est dirigé vers cette ressource.

    Exemple: En reprenant l’exemple initial, on souhaite maintenant créer un lien hypertexte sur l’un des mots affichés. On inclue la balise suivante dans le paragraphe:

    Restauration Le lien Restauration Et cela va rediriger sur la page de wikipedia: restauration française de 1814, lorsque l’on clique sur Restauration

    rendu navigateur html avec lien

    exemple de liens dans un paragraphe

    Structure du document

    La premiere page de l’histoire du Web

    Voir l’article sur Lumni.fr

    Cette page ne présentait pas de mise en forme particulière. Le code ne contenait pas de balises fermantes. Les pages n’étaient pas hierarchisées.

    Mise en boîte

    Avec la norme actuelle du HTML, les pages présentent un structure qui propose un parcours de lecture, un design. L’idée est de capter l’attention du lecteur le plus longtemps possible, de transmettre une information dans un certain ordre.

    Et pour mettre en forme des éléments à différentes positions, il faut insérer les éléments HTML dans des “boîtes”.

    D’où l’usage de balises dite “container”, qui vont permettre ces structures en lignes et colonnes, comme div, section, article, …

    La boite principale sera l’élément body, qui contiendra toutes les autres.

    Une représentation en arbre

    Observons 2 exemples.

    Dans le premier, les éléments de la page se mettent l’un sous l’autre. Ici, les balises ne présentent pas de hierarchie entre elles. Elles sont toutes au même niveau.

    Dans ce deuxieme exemple: l’élément h1 est au même niveau de hierarchie que l’ensemble suivant, constitué de 2 colonnes. Tout cet ensemble sera mis dans un container div.

    Les 2 colonnes contiennent pour la premiere, les éléments h2 et p, et pour la deuxieme, une image.

    Chacune de ces 2 colonnes devront être mises dans un élément parent, un autre container div par exemple. Cela va amener la descrition suivante:

    Le schéma suivant montre la position de ces boîtes dans la fenêtre:

    L’image en forme d’arbre, montre la hierarchie (généalogie) entre ces éléments.

    Exercice

    Voir l’exercice 2

    Dans l’exemple qui suit, on peut lire dans le script html que la balise html contient celles head et body. html est donc une balise parente de head et body. On peut représenter ces liens de parentée avec le diagramme suivant:

    Script complet:

    <html>
      
      <head>
        <link rel="stylesheet" href="style.css">
      </head>
      
      <body>
      
        <div>  
          <h1>Wanted!</h1>
          <h3>Have you seen this robot?</h3>
          <img src="robot.png">
          <p>Description: Height: 30cm, Colour: purple and orange, Arms: 4</p>
          <p>If you have any information, please contact 6207 332 2310</p>
        </div>
        
      </body>
      
    </html>

    Exercice: A l’aide du script complet, poursuivre le diagramme représentant la hierarchie entre ces balises.

    Lien vers la suite du TP

    introduction à CSS

    Bases en css

    les fondamentaux du css: cascade et héritage: MDN

    Les sigles « CSS » sont l’abréviation de « Cascading StyleSheets » ou « feuilles de styles en cascade » en français.

    Le CSS vient résoudre un problème bien différent du HTML : en effet, le HTML sert à définir le contenu et la structure d’une page, à leur donner du sens.

    Le CSS, lui, va servir à mettre en forme les différents contenus définis par le HTML en leur appliquant des styles.

    Si votre navigateur affiche par défaut les contenus textuels que vous avez déclaré comme des titres en HTML en grand et en gras et à l’inverse les paragraphes en plus petit c’est justement parce que chaque navigateur possède sa propre feuille de styles. En fournissant nos styles CSS pour les différents contenus de notre page, nous allons donc pouvoir définir l’apparence de ceux-ci puisque les styles que nous allons fournir vont être considérés comme prioritaires par rapport à ceux du navigateur. C’est le principe du style en cascade (CSS)

    Une déclaration CSS

    Une déclaration typique est composée de trois parties :

    • un sélecteur,
    • une propriété,
    • une valeur
    selecteur { propriete: valeur; }

    La valeur de la propriété se met après le séparateur :.

    Ces règles deviennent des déclarations lorsque celles-ci comprennent plusieurs couples propriété-valeur :Les règles sont alors séparées par un point-virgule ;, dans la même accolade:

    selecteur {
      propriete 1: valeur;
      propriete 2: valeur;
    }

    Exemple:

    règles CSS associées à tous les éléments p de la page: caractères mis en gras (font-weight: bold) et entourés d'une bordure rouge (border: 2px solid red)

    règles CSS associées à tous les éléments p de la page: caractères mis en gras (font-weight: bold) et entourés d'une bordure rouge (border: 2px solid red)

    Le selecteur fait référence à un ou plusieurs éléments du document.

    Selecteurs

    Pour pouvoir appliquer un style à un contenu, il va déjà falloir le cibler, c’est-à-dire trouver un moyen d’indiquer qu’on souhaite appliquer tel style à un contenu en particulier.

    En classe de SNT, le sélecteur, c’est l’élement HTML que l’on veut cibler.

    Où met-on les déclarations CSS?

    On cherche à créer le style suivant:

    Il y a 3 possibilités pour écrire les règles CSS:

    • Soit directement dans la balise, avec l’attribut style. Exemple:
    <div style="border:solid;">
     <p style ="color:#26b72b;>Le texte suivant sera affiché en VERT, qui est codée en hexadécimal avec #26b72b.</p></div>

    Dans ce cas, seule la règle propriete:valeur; est écrite, pas le sélecteur.

    • Soit directement dans la page HTML, entre les balises style:

    L’élément <style> peut être inclus dans l’élément <head> ou dans l’élément <body> du document et les styles seront appliqués. Toutefois, il est recommandé de placer les styles dans l’élément <head> afin de clairement séparer la présentation du contenu autant que possible.

    Exemple:

    <head>
      <style>
        p {
            color: #26b72b;
            border: solid 2px;
          }
      </style>
    </head>
    
    <body>
      <p>Le texte suivant sera affiché en VERT, qui est codée en hexadécimal avec #26b72b.</p>
    </body>
    • La méthode idéale consiste toutefois à utiliser des feuilles de style dans des fichiers externes et de les appliquer au document grâce à des éléments <link>:
    <head>
      <link rel="stylesheet" href="style.css">
    </head>
    <body>
      <p>Le texte suivant sera affiché en VERT, qui est codée en hexadécimal avec #26b72b.</p>
    </body>

    C’est dans le fichier style.css que l’on mettra alors les déclarations css.

    Le choix de la position du CSS est déterminé par l’ampleur du projet à définir, doit-on par exemple appliquer ces déclarations à toute la page, aux autres pages du site, …

    introduction au CSS, video de la chaine Alphorm

    introduction au CSS, video de la chaine Alphorm

    Héritage

    Comme vu dans le cours sur HTML, les éléments ont une hierarchie selon l’imbrication de leurs balises.

    Par exemple, avec l’extrait de page HTML suivant:

    <section>
      <h1>Titre de la section</h1>
      <div>  
        <p>Paragraphe 1</p>
        <img src="photo.jpg">
      </div>
      <div>
        <p>Paragraphe 2</p>
      </div >
     </section>

    On a l’arbre du DOM:

    arbre du DOM d'après l'extrait HTML

    arbre du DOM d'après l'extrait HTML

    Les éléments enfants héritent les règles CSS de leur parent, à condition que ces règles leurs soient applicables.

    Pour selectionner un élément particulier, il faudra le selectionner à partir de sa classe, un attribut qu’il faut rajouter à la balise de l’élément.

    Ceci oblige à co-construire le fichier HTML et le fichier CSS, ce qui peut être parfois un vrai casse-tête…

    Youtube - Mon probleme avec le CSS

    Youtube - Mon probleme avec le CSS

    Avec un attribut classe, le selecteur CSS fait reference à la valeur de classe. Le sélecteur utilise une notation avec un point devant la valeur de classe.

    Exemple:

    balise HTML déclaration CSS
    <p class="paragraphe_stylé">Mon paragraphe</p> .paragraphe_stylé {font-family: arial; }
    • Dans le code HTML, la balise p que l’on veut styliser a l’attribut class. Et la valeur paragraphe_stylé pour valeur de la classe. Ce nom est librement choisi par le programmeur.
    • Dans le code CSS, le sélecteur est alors .paragraphe_stylé, avec un point devant le nom. La règle ne concerne alors QUE ce paragraphe. Si la déclaration avait été : p {font-family: arial; }, cela aurait concerné TOUT les paragraphes p de la page.

    Règles principales

    Règles appliquées aux textes

    Tutoriel complet: developer.mozilla.org

    Quelques propriétés CSS relatives aux textes

    paramètre valeurs possibles effet
    color blue, yellow, red, … colorie le texte selon le nom anglais de la couleur
    color rgb(0..255, 0..255, 0..255) selon le code RGB sur un octet chacun
    color #0..F0..F0..F selon le code RGB exprimé en hexadecimal, sans separateur
    background-color idem color couleur de fond
    font-family arial, courier new… choix de la police de caractères
    font italic 12 pt sans-serif informations complémentaires pour la police
    text-align center, left, right, justify alignement du texte
    font-weight bold mettre en gras

    Règles relatives aux listes

    Voici un exemple de page qui liste les différentes missions de la NASA:

    <head>
      <style>
    
      </style>
    </head>
    
    <body>
      <h2>NASA Notable Missions</h2>
      <ul>
        <li>Apollo</li>
        <li>Hubble</li>
        <li>Chandra</li>
      </ul>
    </body>

    NASA Notable Missions

    • Apollo
    • Hubble
    • Chandra

    On peut ajouter une déclaration CSS dans le début du fichier. Par exemple pour enlever les marqueurs de liste de la manière suivante:

    <head>
      <style>
        li {list-style: none;}
      </style>
    </head>

    NASA Notable Missions

    • Apollo
    • Hubble
    • Chandra

    Résumé

    paramètre exemples de valeurs possibles effet
    list-style square puces carres puces carres
    list-style none pas de puces pas de puces

    Liens

    internet

    Projet de fin de chapitre: Réaliser un traceroute/ping vers plusieurs sites (France, Europe, autre continent), relèver les adresses IP et temps de latence, puis produire un schéma annoté expliquant le trajet des paquets (routeurs, protocole TCP/IP, adressage).

    Sous-sections de internet

    généralités

    • culture numer généralités sur l’usage d’internet: Lien
    • culture numer réseau local et reseau internet: Lien
    • culture numer circulation des données, protocoles: Lien
    • culture numer le cloud: Lien
    • competences TP simulation d’un reseau d’ordinateurs: Lien

    tour d’horizon de l’usage d’internet

    culture numer

    A quoi vous sert votre équipement informatique ?

    Avant l’accès généralisé à l’internet, le particulier s’équipait d’un ordinateur pour faire du traitement de texte et des jeux.

    Maintenant, c’est l’accès à internet qui est recherché, pour :

    • avoir accès à des informations distantes
    • s’informer, ou rechercher de l’information
    • apprendre, se former
    • communiquer entre personnes
    • divertissements interactifs (jeux, musique, vidéo à la carte)
    • commerce électronique (auquel participent même les institutions financières, mais aussi des services de braderie en ligne, entre particuliers, de consommateur à consommateur
    • commande d’un taxi ou d’un repas, avec suivi en temps réel du délai d’attente
    • autres services : téléformation, télémedecine, …
    https://fr.surveymonkey.com/r/T8GSRTW

    https://fr.surveymonkey.com/r/T8GSRTW

    Quel est votre terminal ?

    On entend par terminal, l’appareil que vous utilisez pour utiliser les services fournis par internet. Progressivement, l’ordinateur a reculé et a été remplacé par les smartphones, tablettes, assistant vocal ou montre connectées pour la plupart de ces services.

    equipement numerique

    equipement le plus utilisé pour se connecter à internet en 2019

    une utilisation nomade

    Il y a une convergence des usages que l’on fait avec un ordinateur et un smartphone. Sauf qu’avec le smartphone, le reseau sans fil est un moyen d’avoir un bureau mobile.

    Mais c’est aussi d’autres services : taxis connectés, des applications mobiles comme celles par exemple de parcmètres (bornes qui lisent les cartes de credit en effectuant un contrôle immédiat, ou qui rapportent l’expiration), les distributeurs de boisson connectés avec état des stocks, compteurs d’electricité…

    Pour le client, la possibilité de lire un code barre et de mettre en relation avec une base de données. (les autres magasins, la composition, le meilleur point de vente…)

    La géolocalisation offre de nombreuses possibilités, comme le conseil des restaurants à proximité. Les possibilités sont infinies.

    Mais les activités principales liées à l’utilisation d’un smartphone restent la consultation de page à l’aide d’un navigateur, et l’utilisation de messageries ou des réseaux sociaux :

    usage numerique en 2019

    Proportion de la population qui utilise leur téléphone mobile pour ...

    La communication par internet

    Des formes de communication interpersonnelles : (entre 2 personnes ou plus)

    • Le mail a été la première manière de s’envoyer des messages, et reste aujourd’hui la forme la plus utilisée dans le milieu professionnel.
    • Il y a eu au démarrage un fort engouement des adolescents pour la messagerie instantanée (inspiré du programme talk de Unix); les chat rooms, salles de conversation autorisant un groupe de personnes à taper des messages visibles par tous. (sorte de bavardage). Les formes de communication ne s’y limitent d’ailleurs pas au texte, mais il y a des photos ou de courtes vidéos qui peuvent aussi y être partagées.
    • Les forums de discussion : où la communication ne fonctionne pas en temps réel, mais permet de poster un message que tous les membres peuvent lire
    • les applications de messagerie instantanée, avec la possible création de groupes
    • les applications de réseaux sociaux, qui diffèrent des forums par une communication plus immédiate et éphemère, mais aussi des messageries instantanée par la possibilité de naviguer sur le net, se focaliser sur certains types de médias (photo, video), de s’abonner à certains comptes, …
    • le peer to peer : communication entre systèmes homologues (pairs) : différents du modèle client-serveur. Les utilisateurs forment un groupe indéfini. L’échange se fait sur pied d’egalité et les rôles client-serveur ne sont pas assignés de façon fixe. Chaque utilisateur maintient sa propre base de données ainsi qu’une liste des autres personnes dans le voisinage participant au système. Jeux en réseau, courrier électronique sont d’autres exemples de peer to peer.
    • téléphonie, visiophonie, radio via internet.

    Statistique: Classement des réseaux sociaux et messageries instantanées ayant le plus fort taux de pénétration en France en 2018 | Statista
    Trouver plus de statistiques sur

    La recherche d’informations sur le net

    La recherche d’information passe le plus souvent par:

    • un moteur de recherche généraliste
    • un moteur de recherche spécialisé
    • un assistant LLM

    Voir chapitre sur les moteur de recherche.

    Les informations qui circulent sur internet

    Aspects societaux, politiques et moraux

    Sur des reseaux avec des sujets aux thematiques techniques, les échanges entre personnes ne génèrent pas de problemes.

    Par contre, lorsque les sujets touchent à des domaines plus sensibles : religion, politique ou sexualité, les esprits s’enflamment et les messages peuvent devenir choquants, ou blessants.

    Il y a 2 courants de pensée :

    • ceux qui prônent la tolérance
    • ceux qui pensent que certains messages doivent être censurés

    D’ailleurs, les lois diffèrent ou s’opposent selon les pays.

    Des personnes ont poursuivi en justice les opérateurs, les tenant pour reponsables du contenu qui circule sur les reseaux. Mais cela s’apparenterait alors à une censure et porter atteinte à la liberté d’expression.

    Une autre source de désaccord, liée à l’utilisation du contenu des messages sur les réseaux sociaux, ou des traces de navigation concerne :

    • le droit respectif des employés et des employeurs
    • des universités et leurs étudiants
    • les gouvernements et leurs citoyens. Par exemple, le FBI avait mis en place un systeme d’espionnage des messages chez plusieurs fournisseurs d’accès afin de collecter des données interessantes. Le 4e amendement de la constitution americaine a mis fin à ce projet.
    • les entreprises et leurs visiteurs : les cookies, qui leur permettent de suivre leur activité et renseignent ceux qui y ont accès à certaines informations confidentielles comme les intérêts des visiteurs pour certains produits, leur mail, leur mot de passe, ou leur numéro de téléphone mobile.

    * La CNIL :

    • Restez informé : Les droits pour maîtriser vos données personnelles ! <figure
      restez informé : la CNIL
    s
    * paramétrer
    maitrisez l'accès à vos données : la CNIL
    maitriser ses données

    fausses informations

    Les reseaux permettent d’envoyer des messages anonymes. On peut ainsi dénoncer quelqu’un sans risquer de represailles. Mais, heureusement, dans une societé democratique, une accusation ne fait pas preuve et toute personne a le droit d’être confronté à son accusateur.

    Internet permet la diffusion d’informations de manière virale :

    • Cela peut contribuer à un reveil de l’opinion publique :

      • voir l’enchainement des évenements pendant les elections en Espagne : 11 mars 2004, l’attentat de la gare de Madrid. Le gouvernement du président Aznar manipule l’information pour laisser croire que la responsabilité de cet attentat incombe à l’ETA, un parti politique clandestin. Mais rapidement, une chaine de messages (twitter ou autres reseaux sociaux) entre citoyens met au jour ce que l’on pourrait apparenter à un mensonge d’état. Aznar perd alors dans la foulée les élections legislatives qui se tiennent 2 jours plus tard. https://www.monde-diplomatique.fr/2004/04/RAMONET/10895
      • voir soulèvement du 15 mai 2011 en espagne : parti politique d’initiatives populaires (les indignados)
    • Ou la manipulation de l’opinion publique avec des nouvelles fausses (elections de Donald Trump aux états-unis en 2016).

    Important : Toujours vérifier une information. Quelle est sa source ? Quelle est la qualité du média ou de la personne qui la diffuse ?

    Le Décodex du journal en ligne Le Monde Le site Lumni

    Des problèmes de sécurité

    L’internet c’est aussi aussi des problemes de securité, avec de nombreuses données non chiffrées, ce qui ouvre la possibilté à de nombreux méfaits :

    • recevoir du courrier electronique non sollicité (spam). Notre adresse est revendue à des sociétés qui s’adonnent au marketing sauvage.
    • recevoir des macros avec virus en pièces jointes
    • le vol d’identité

    securité

    Sur internet, il y a autant de personnes mal intentionnées que dans la vraie vie

    Mais le chiffrement est couteux pour les fournisseurs d’équipement et de logiciels.

    Un autre problème de sécurité vient d’une technique que l’on appelle le phishing : le pirate se fait passer pour un organisme bancaire, un assureur, un opérateur de téléphonie… La technique est souvent celle-ci :

    Vous recevez un mail de cet organisme, vous demandant de cliquer sur un lien qui devrait vous rediriger vers le site de cet organisme.

    Seulement, lorsque vous cliquez, vous pouvez constater que le nom de domaine n’est pas rigoureusement identique à celui de l’organisme original. Ainsi, l’URL https://twiter.com (le faux site, dont le nom de domaine est twiter) n’est pas identique à https://twitter.com (le vrai site, de nom de domaine twitter).

    phishing

    un exemple de phishing

    phishing

    detail du lien

    Ensuite, on vous demande:

    • vos identifiants de connexion,
    • ou coordonnées bancaires, numéro de carte de crédit ou autre, que vous choisissez intentionnellement (et malheureusement) de donner, sans vous méfier.

    Il existe heureusement des recours, au cas où cette mésaventure vous arrive, mais cela vous aura porté préjudice. Le mieux est de toujours adopter une posture de doute lorsqu’un tel mail vous parvient…

    La diffusion libre d’ouvrages artistiques

    L’utilisation d’un service de téléchargement ou de streaming illégal entraine la violation des droits d’auteur avec la transmission de musique et video numerique.

    L’objet étant numérique, cela ne constitue pas à proprement parler d’un vol lorsque l’on s’en procure une copie. On peut d’ailleurs en réaliser un nombre illimité de copies numériques. Un fichier musical, une vidéo, une image ou un livre numérique constituent des biens non rivaux. Mais l’existance de droits d’auteurs empêche normalement la libre diffusion de l’oeuvre, et les personnes qui pratiquent cet échange enfreignent la loi.

    Le coût énergétique de l’utilisation d’internet

    Un article interessant du CNRS montre que l’usage de services dits dématérialisés n’est pas sans conséquences au niveau de la consommation énergétique.

    Etre présent sur le web

    Faut-il créer son site web ou être présent sur les reseaux sociaux?

    Les deux:

    La bonne pratique est de créer du contenu sur votre site ou page web et ensuite de le diffuser sur les réseaux sociaux. En effet, la communication sur les réseaux sociaux est éphémère. Si votre tweet ou votre post n’est pas vu au moment de sa publication, ce contenu sera perdu tandis que le contenu sur votre site internet restera et contribuera au bon référencement naturel de celui-ci.

    Aspects techniques : fonctionnement d’internet

    Voir la page fonctionnement d’internet, prococoles

    Liens

    Approfondir

    reseau local et reseau internet

    Comment fonctionne internet - Youtube

    Comment fonctionne internet - Youtube

    Faire communiquer des ordinateurs

    Une première idée naïve : tout usage du numérique met des machines en connexion, et qui échangent des données.

    communication avec 2 ordinateurs

    communication avec 2 ordinateurs

    Ce modèle simpliste de réseau va devenir irréalisable lorsque celui-ci contiendra de nombreux ordinateurs :

    • grand nombre de connexions (et de liaisons physiques) au départ de chaque ordinateur
    • grand nombre de ports utilisés

    Internet ne constitue pas un graphe complet, c’est à dire un reseau dans lequel chaque machine est directement connectée à une autre.

    Il faudra d’autres éléments pour connecter les ordinateurs entre eux.

    Reseau d’ordinateurs

    Qu’est ce qu’un système informatique ?

    Un système informatique fonctionne sur le modèle client-serveur :

    Les parcs informatiques des écoles, universités, et entreprises ont leur activité qui dépend d’informations partagées sur leur réseau. (gestion des salles, ressources, identité des étudiants, des clients, les stocks, la comptabilité, les états financiers,…). En conséquence, une panne informatique ne leur permettrait plus de fonctionner. C’est pour cette raison que les ordinateurs doivent être connectés, que ces informations doivent être distribuées; que l’information doit être accessible, même si l’un des ordinateurs est en panne.

    Un système informatique est alors constitué :

    • d’une ou plusieurs base(s) de données
    • d’ordinateurs serveurs qui stockent les bases de données
    • d’ordinateurs clients : des ordinateurs plus simples, et qui doivent avoir accès aux ressouces.
    LAN

    local area network (LAN)

    des services diversifiés

    Un réseau d’ordinateurs peut aussi servir à fournir des services de communication :

    • courrier électronique
    • outils de collaboration (redaction à plusieurs)
    • visioconférence
    • la conclusion d’affaires par voie électronique, commandes en temps réel
    • logiciel partagé

    C’est l’utilisation d’un serveur partagé dans le réseau qui permet d’acceder à ces services.

    Certains de ces services peuvent aussi être fournis par un serveur sur un réseau externe, accessible depuis internet. C’est ce que l’on appelle le cloud : la livraison de ressources et de services à la demande par internet.1

    Un réseau d’ordinateur peut aussi servir à partager du matériel (une imprimante), ou une connexion internet (le routeur). (voir note en bas de page sur la configuration d’un reseau local2)

    Le commutateur (switch) et le routeur

    Les appareils ne sont pas forcément connectés directement, mais peuvent l’être au moyen d’un switch. (concentre les liaisons et possède une table de routage avec les adresses mac des ordinateurs reliés).

    les switchs (commutateurs) peuvent lire les adresses matérielles des paquets entrants afin de les transmettre à la destination appropriée.

    Les réseaux sont alors reliés entre eux par un routeur

    réseau d

    réseaux d'ordinateurs

    Sur cette image, plusieurs sous-reseaux sont reliés par des routeurs. Par contre, l’appareil qui interconnecte les machines dans un même sous-reseau est un switch.

    le routeur est l’appareil disposant plusieurs adresses IP, une adresse par interface (voir plus loin). Il fait office de passerelle entre les périphériques sur un réseau local (LAN) et Internet. Dans un réseau de réseaux, cette machine doit posséder plusieurs interfaces (plusieurs cartes réseau), chacune reliée à un réseau. Son rôle va être d’aiguiller les paquets reçus entre les différents réseaux.

    Un routeur possède plusieurs interfaces

    Un routeur possède plusieurs interfaces

    Différences entre reseau local et reseau internet

    Reseau local: Systeme réparti3

    Un système réparti permet de partager des ressources, données et logiciels.

    Avec un réseau local d’ordinateurs, qui peut constituer un système réparti, l’utilisateur se trouve devant la réalité des machines et leurs caractéristiques diverses, la varieté des équipements, et de leur système d’exploitation; pour executer un programme sur une machine distante, l’usager doit ouvrir une session. La maitenance d’un reseau local demande une bonne connaissance de tous ces matériels.

    Et si l’un des ordinateurs tombe en panne, les autres ordinateurs risquent de s’en apercevoir (base de donnée inaccessible, etc…).

    Définition: Un système réparti est un système qui vous empêche de travailler quand une machine dont vous n’avez jamais entendu parler tombe en panne.

    Des exemples de systèmes répartis: un centre de documentation, bibliothèque, reseau de lycée, contrôle et organisation d’activité en temps réél,…

    Pour approfondir : (Wikihow) comment configurer son réseau local ? 2

    Reseau internet: un système distribué4

    Lorsque l’on utilise internet, on ne voit plus cette variété d’équipement.

    le système distribué est un ensemble d’ordinateurs indépendants, présenté à l’utilisateur comme un système unique cohérent. Souvent une couche logicielle intermédiaire appelée middleware située au dessus du système d’exploitation est responsable de son implémentation.

    Un exemple est le web dans lequel toute information apparait comme un document. C’est donc un logiciel élaboré au dessus du réseau, qui nous fait oublier la variété des supports utilisés pour transmettre les données (Serveur, Adsl, Box, wifi, bluetooth…).

    Définitions

    Un système distribué: C’est un ensemble d’ordinateurs indépendants qui apparaît à un utilisateur comme un système unique et cohérent

    Internet n’est pas un réseau d’ordinateurs. C’est un réseau de réseaux.

    Le web, c’est un système distribué opérant au-dessus d’internet.

    Caractéristiques physiques : canal de transmission:

    1. reseau local

    Deux critères permettent de les caractériser : la technologie de transmission utilisée, et leur taille.

    Dans un reseau local, les supports de transmission des données peuvent être :

    • cable ethernet
    • wifi (ondes EM)
    • bluetooth (ondes EM à courte portée)

    2. reseau internet

    Une fois sorties du reseau local, les transmissions peuvent se faire par:

    • fibre optique (Adsl)
    • ligne de type telephonique (Adsl)
    • reseau de telephonie mobile (4G, 5G)

    Remarque: L’utilisation d’internet demande un abonnement à un FAI.

    Adressage des machines.

    adressage dans un reseau local: MAC

    une adresse MAC (Media Access Control), appelée également adresse Ethernet, est l’adresse physique d’une interface (carte réseau, wifi, …). Chaque adresse MAC est normalement unique au monde et fournie par le fabricant de l’interface.

    Cette adresse est constituée de 6 octets, soit 12 caractères hexadécimaux, comme par exemple:

    $$01:b8:43:c4:85:a3$$

    Un ordinateur qui reçoit un message par l’une de ses interface, va lire si l’adresse MAC est bien la sienne. Sinon, c’est que le message ne lui est pas destiné: il détruit alors le message.

    Dans un reseau local où les machines sont interconnectées via un switch: Pour envoyer la trame vers la bonne machine, le switch se sert de l’adresse MAC destination contenue dans l’en-tête de la trame. Il contient en fait une table qui fait l’association entre un port du switch (une prise RJ45 femelle) et une adresse MAC. Cette table est appelée la table CAM.

    adressage IP

    une adresse IP est un identifiant numérique unique attribué à chaque appareil (appareils mobiles, ordinateurs, routeurs, imprimantes, consoles de jeux, etc.) connecté à un réseau TCP / IP comme Internet. Plus précisemment, c’est l’identifiant de la carte reseau, reelle ou virtuelle. Chaque dispositif peut se connecter grâce à cette adresse IP à d’autres périphériques et partager des informations. Il s’agit du Protocole Internet (IP).

    Question: Est-il possible de connaître l’emplacement de mon ordinateur (smartphone, …) en connaissant son adresse IP?

    En principe, non, pas exactement, car mon dispositif possède une adresse IP privée… Il existe 2 types d’adresses IP:

    • Adresse IP privée: 2 machines peuvent avoir la même adresse privée à condition qu’elles soient sur 2 reseaux privés distincts. Pour une machine dotée d’une adresse privée qui doit accéder à internet, une traduction de son adresse privée en adresse publique est nécessaire. C’est le mécanisme NAT (Network Adress Translation) qui assure cette fonction. Ce mécanisme de traduction d’adresse réseau se fait par la passerelle, qui se situe à l’interface entre les réseaux privés et les réseaux publics. Elle est aussi nommée routeur (gateway). Une passerelle possède au moins 2 interfaces reseau.

    • adresse IP publique: adresse attribuée aux machines connectées sur Internet. Ce sont les FAI qui sont autorisés à affecter des adresses publiques. Ces adresses sont uniques au niveau mondial. L’essor constant d’internet au niveau mondial fait que l’on migre progressivement de la norme IPv4 vers IPv6. Ce sont deux protocoles réseau de la couche 3 du modèle OSI (Open Systems Interconnection).

    IPv4

    Ces adresses IP constituées de 4 nombres sont les plus répandues à l’heure actuelle, on les appelle IPv4.

    Un exemple d’adresse IPV4: (exprimée par 4 nombres decimaux 0-255)

    $$192.168.0.10$$

    Bien que codés sur 32 bits (4 octets), leur nombre se révèle assez limité : il n’y a en effet “que”

    $$256×256×256×256$$

    possibilités d’IP, soit

    $$256^4=4\phantom*294\phantom*967\phantom*296$$

    (plus de 4 milliards). Ce nombre a l’air grand, mais on finira prochainement par l’atteindre avec la multiplication des ordinateurs et des serveurs reliés à Internet. C’est pourquoi ces IP ont vocation à être remplacées par un nouveau système : IPv6 (8 groupes de 2 octets)

    IPv6

    Ce sont des adresses IP codées sur 128 bits, soit 16 octets, ou 32 caractères hexadecimaux.

    La nouvelle forme d’IP, que l’on va rencontrer de plus en plus, a la forme suivante : (exemple)

    $$1703:01b8:43c4:85a3:0000:0000:a213:bba7$$

    Leur nombre est d’environ 10^29 fois plus important que pour les adresses IPv4.

    DNS, IP et URL

    Lorsque l’on demande un service sur internet, on ne saisit pas http://adresse IP mais http://URL de la page depuis la barre du navigateur. Il y a alors plusieurs étapes avant d’obtenir une ressource du serveur:

    1. Le navigateur demande l’adresse IP correspondant au domaine mentionné dans l’URL. Il demande ce service à un serveur DNS.
    DNS

    le DNS: un enorme repertoire contenant les adr IP

    1. Le navigateur se présente alors au serveur, qu’il arrive à joindre grace à son adresse IP.
    2. Une fois la connection établie, le navigateur envoie sa requête, qui est souvent la demande d’une page internet.
    3. Le serveur lui repond en lui envoyant la ressource demandée.
    protocole HTTP

    modèle client-serveur

    En pratique, la ressource n’est pas envoyée en entier par le serveur, mais par petits morceaux. Cela rend l’utilisation d’internet plus efficace. (voir aussi le cours sur le modele OSI et le protocole TCP )

    le protocole IP: c’est lui qui permet de se connecter à un autre ordinateur. Il gère l’adressage.

    le protocole TCP: permet d’envoyer les paquets d’un ordinateur vers un autre ordinateur. Il gère le routage et l’interconnexion des différents réseaux.

    Liens


    1. Le cloud : désigne le stockage et l’accès aux données par l’intermédiaire d’internet plutôt que via le disque dur d’un ordinateur. Mais aussi des services rendus par des logiciels hébergés côté serveur. ↩︎

    2. configurer son réseau local (Wikihow) : https://fr.wikihow.com/configurer-un-réseau-local ↩︎ ↩︎

    3. Systèmes répartis: Ce sont des systèmes pour lesquels les ordinateurs mis en reseau ont un couplage fort. Des exemples de systèmes répartis: un centre de documentation, bibliothèque, reseau de lycée, contrôle et organisation d’activité en temps réél,… ↩︎

    4. Système distribué: Les ordinateurs du reseau ont un couplage faible, et communiquent par echange de messages de manière asynchrone. La difficulté de mise en oeuvre d’un algorithme sur un système distribué, est que l’on n’a pas connaissance de l’état global du système (routage sur internet). ↩︎

    circulation des données

    Video SNT: les protocoles

    Video SNT: Internet, TCP-IP un protocole universel ?

    Video SNT: Internet, TCP-IP un protocole universel ?

    Constitution du reseau internet

    Réseau local

    • Dans un réseau local, les ordinateurs sont interconnectés par un switch et peuvent communiquer entre eux par l’intermédiaire d’un routeur. C’est aussi le routeur qui fait passerelle vers internet.
    reseau internet

    reseau local et internet

    réseau internet

    • Internet est un réseau de réseaux qui interconnecte toutes les machines à l’échelle mondiale. En pratique, ce sont les routeurs des réseaux qui sont interconnectés. Lorsqu’un routeur reçoit une requête d’une des machines de son réseau, adressée à une machine qui n’appartient pas à son réseau, il se réfère à une table de routage d’internet pour expedier la requête. Il envoie alors la requête à un autre routeur.

    Routeur et routage

    Le routeur: c’est une machine qui a pour rôle de communiquer avec d’autres machines.

    Les routeurs s’occupent du routage sur internet, c’est à dire du meilleur choix de route selon les renseignements dans leur table de routage. Le but est de faire circuler les données, sans que celles-ci occupent trop longtemps le reseau, par les voies les plus rapides.

    Chaque routeur est identifié par une adresse IP. Il possède une table de routage qui lui permet de choisir la bonne liaison entre les 2 machines qui veulent communiquer.

    Cette table de routage identifie les ordinateurs de manière unique par leur adresse IP : Un code binaire à 32 bits (norme IPv4) ou 128 bits (norme IPv6).

    Dans l’exemple ci-dessous, les données qui circulent du client vers le serveur vont probablement emprunter des chemins différents : certains passeront par les reseaux d’accès E, A, B et D, alors que d’autres emprunteront les reseaux E, A, C et D. Les routeurs par lesquels passent ces données seront aussi différents dans un même réseau d’accès. Le calcul de l’itinéraire est réalisé de manière dynamique, par les routeurs eux-même, en fonction du trafic.

    Le trajet possible entre les 2 machines n’est pas unique :

    reseau internet

    des reseaux interconnectés

    source: interstices.info

    Les données peuvent circuler en sous plusieurs formes et à travers différents canaux, ce qui modifie leur vitesse et leur débit :

    • Fibre optique : 100 Mo/s
    • Adsl : 5Mo/s
    • 4G: 10 Mo/s
    • Wifi : 10 Mo/s
    • Bluetooth : 0,5 Mo/s

    Comment utiliser le reseau Internet?

    Pour naviguer sur internet, votre machine va communiquer avec d’autres serveurs. Cette communication met en jeu plusieurs protocoles, dont les principaux sont DNS, HTTP, IP et TCP.

    Client – serveur

    la description du reseau sous-entend un mode de fonctionnement client-serveur

    • Client : demande une ressource
    • Serveur : heberge et fournit la ressource

    Il existe plusieurs niveaux de description des echanges entre client et serveur ce qui amène à utiliser un modèle en couches (TCP/IP).

    Dans chaque couche de ce modèle, des algorithmes sont mis en œuvre et chaque couche s’occupe d’une partie de la transmission.

    Par exemple, au niveau du client, le navigateur s’occupe de la resolution DNS puis de l’établissement du contact avec le serveur (HTTP)

    Les autres couches vont s’occuper du routage et de sa fiabilisation.

    Algorithme : une suite ordonnée et non ambigüe de commandes ou instructions. C’est une séquence d’ordres

    la resolution DNS

    C’est l’une des étapes du protocole TCP/IP. Au cours de celle-ci, l’ordinateur client qui cherche à se connecter à un ordinateur serveur. Il va demander au serveur DNS de lui convertir l’adresse symbolique (URL) en une adresse IP, celle du serveur à joindre. Puis, une fois qu’il connaît l’adresse ip, il envoie une requête HTTP à l’ip correspondante afin que le serveur lui retourne la page.

    Il y a une correspondance entre l’adresse symbolique et l’adresse IP. Lorsque l’on demande à notre machine de joindre celle d’adresse symbolique musee-orsay.fr, il y a un protocole qui se charge de renseigner l’adresse IP correspondante, afin que les machines puissent communiquer entre elles. C’est le protocole de résolution DNS.

    Cette résolution DNS est réalisée :

    1. D’abord grâce au fichier host.txt de notre machine
    2. Puis, si l’adresse n’est pas dans le fichier, par le serveur DNS

    Le protocole HTTP

    Ce protocole HTTP est initié par le client, le navigateur (Mozilla, Chrome, …). Une fois la connexion établie, vous allez pouvoir charger la page Web depuis l’ordinateur serveur.

    adresse IP et adresses symboliques

    Les adresses IP identifient les machines par un numero (sur 32 bits pour l’IPV4, et 128 bits pour l’IPV6) et leur permet de communiquer entre elles. Le problème est que le format de cette adresse n’est pas très intelligible pour un humain. C’est pour cela que les sites et les programmes hébergés sur les serveurs possèdent aussi une adresse symbolique (nom d’hôte).

    Par exemple, l’adresse IP 207.142.131.245 est celle de Wikilivres.com (son nom d’hôte correspondant).

    Les tables de correspondance : nom d’hôte <=> adresse IP sont tenues par des serveurs appelés DNS (domain name system). C’est à ce serveur DNS que votre routeur se réfère lorsque vous saisissez une adresse symbolique (une URL) dans la barre de navigation de votre navigateur.

    Une fois la résolution DNS réalisée, les machines entrent en contact grâce à leurs adresses IP. Ce sont des étapes du protocole IP.

    Comment sont transmises les informations numériques ?

    Le protocole TCP
    Internet manipule deux types d’information : les contenus envoyés et les adresses du destinataire et de l’émetteur. Ces deux types d’information sont regroupés dans des paquets de taille fixe, de façon uniforme et indépendante du type de données transportées : texte, images, sons, vidéos, etc.

    Ces données sont rassemblées dans des trames de 1500 octets. La plupart du temps, les données à envoyer sont de taille supérieure à 1500 octets, et il faut plusieurs trames.

    trame

    decoupage de l'information numérique en plusieurs datagrammes

    C’est le protocole TCP qui gère ce découpage, et rajoute des informations pour pouvoir renvoyer les paquets perdus en chemin (grâce à un accusé de reception), et remettre les paquets dans le bon ordre. Un code de vérification est également ajouté au paquet, pour vérifier s’il est conforme à l’original, et non corrompu en chemin.

    TP: comprendre le protocole TCP en jouant :

    reseau internet

    reseau local et chemin entre routeurs : interstice.info

    > Vous devez perturber le transport des paquets afin d’empêcher la reconstitution du message. Au fur et à mesure que vous passez les niveaux, l’ordinateur trouve de nouvelles stratégies pour y parvenir. Vous pouvez : retarder les paquets, les corrompre, ou les détruire.

    Problème de libre accès au réseau internet et cybersécurité

    Utilité des noms de domaine

    Une bonne pratique est de lire les noms de domaines dans la barre d’adresse afin de s’assurer que l’on navigue vers le BON site. Une des attaques les plus classiques sur le net est le Phishing

    On pourra consulter la video suivante:

    phishing et noms de domaine - arsen.co

    phishing et noms de domaine - arsen.co

    https est la version securisée pour l’echange de données sur internet. Lorsque vous demandez à charger une page sur internet (on dit que vous demandez une ressource), les etapes sont les suivantes :

    • Resolution DNS
    • Contact avec le serveur grace à l’adresse IP et le nom de domaine du site internet
    • Echange des clés de chiffrement
    • Le client demande la page web
    • Le serveur lui retourne la page
    • Le client envoie des données
    • Le serveur traite les données
    • …

    En italique : les echanges chiffrés.

    Risque (faible): si le flux de données est capturé: il est possible de connaitre le nom de domaine consulté, mais pas le contenu ni l’adresse de la page consultée sur le site.

    Censure sur internet

    Blocage DNS

    Le blocage DNS consiste à empêcher la résolution d’un nom de domaine en adresse ip. On peut vérifier depuis la France si certains sites sont inaccéssibles pour un pays qui pratique la censure d’internet. Sur le site experte.com

    page du site experte.com

    page du site experte.com

    Fonctionnement du site: envoi de l’URL sur l’un de ses serveurs hebergés dans les pays considérés. Test avec des pays pour lesquels l’internet est libre, afin de s’assurer que le domaine fonctionne bien.

    page du site experte.com

    page du site experte.com

    exemple de blocages

    exemple de blocages

    Ce blocage est facilement contournable en utilisant un serveur DNS alternatif.

    Blocage par adresse IP

    Dans le cas d’un blocage ip, c’est directement l’adresse ip du site web qui est bloquée par le FAI, ou bien par un logiciel installé sur un noeud de routage (Proxy).

    Dans de nombreux pays, les FAI sont contraints par leur gouvernement d’effectuer régulièrement un filtrage et une censure d’Internet. Ce type de blocage n’est pas sans poser de problème puisque si plusieurs sites sont hébergés sur la même adresse ip, comme dans le cas d’un hébergement mutualisé, l’ensemble des sites se retrouvent inaccessibles.

    Néanmoins, dans le cas d’un tel blocage, il existe des solutions, comme d’avoir recours à un tunnel chiffré, tel qu’un VPN.

    Utiliser un VPN

    Le VPN assure un tunnel pour acheminer les données, chiffrées dès que la connexion est établie. La procédure est la suivante:

    • Connection au serveur VPN
    • Resolution DNS pour le site demandé
    • Contact avec le serveur..
    • Echange des clés
    • ;;;

    En italique : les echanges chiffrés.

    La connexion au VPN ajoute une securité supplémentaire, avec un 2e chiffrement, et l’effacement du nom de domaine consulté.

    TP simulation d'un réseau

    TP simulation reseau

    Un reseau, c’est quoi? C’est un système constitué de machines reliées ensembles (machines de tout genre: ordinateur, imprimante,…). Elles ont une adresse IP.

    L’adresse IP (Internet Protocol) identifie un périphérique à l’intérieur d’un réseau. A l’intérieur de ce réseau elle est unique.

    Les outils utilisés en simulation ne fonctionnent pas tous en mode réel, à partir de votre propre ordinateur du lycée, à cause de restrictions nécessaires pour des problèmes de sécurité.

    TP Filius 1 : faire communiquer 2 ordinateurs (durée indicative: 10 min)

    Lancer le logiciel Filius.

    On réalise un premier réseau simple de 2 ordinateurs reliés par une seule ligne.

    On s’aidera de la video de présentation Filius 1 (David Roche)

    • Disposer les 2 ordinateurs comme présenté sur la video.

    • Modifier les adresses IP de ces ordinateurs pour avoir, dans l’ordre:

      • 192.168.0.1
      • 192.168.0.2

      Remarque: Souvent, dans un même reseau, les 3 premiers octets de l’adresse IP des machines sont identiques. (ici: 192.168.0). Seul le dernier octet change. Pour l’une des machines, ce sera .1, pour la suivante .2, etc…)

    • Relier ces ordinateurs

    • Installer les logiciels utiles pour faire communiquer ces machines. Pour faire cela: Démarrer la simulation:

    démarrer
    • Puis faire un double clic sur chacune des machines, et installer le logiciel ligne de commandes.
    console installation logiciel

    console d'installation de logiciels

    • tester alors les commandes suivantes depuis la machine M1:

      • ipconfig : vérifier la correspondance de l’adresse IP de la machine M1

      • ping 192.168.0.2 : pour établir et tester une connexion avec la machine M2

      • traceroute 192.168.0.2 : pour établir le trajet qui mène jusqu’à M2

      • Tester alors les commandes ping et traceroute vers une adresse de machine inexistante dans le réseau. Par exemple 192.168.0.3

    Qu.1a: comment voit-on si le chemin vers une machine du reseau existe? Quelle information lit-on dans la console?

    • modifier le réseau et mettre 3 ordinateurs reliés à un switch (un connecteur) : voir la vidéo pour explications
      • revenir en mode conception du reseau (bouton avec le marteau)
      • commencer par supprimer le cable (clic Droit sur le composant => Supprimer)
      • ajouter l’ordinateur M3. Modifier son IP en 192.168.0.3. Relier ces machines à l’aide d’un switch.
      • tester alors la commande de traceroute entre M1 et M3

    Qu.1b: Pourquoi a-t-on besoin d’un switch dans un réseau à 3 ordinateurs?

    TP Filius 2 : créer un reseau de type lycée (durée indicative: 20 min)

    On cherche maintenant à créer un système de 2 sous-réseaux locaux. Ces reseaux auront pour adresses: 198.168.0.0 et 192.168.2.0

    C’est à dire que toutes les machines du réseau 198.168.0.0 auront en commun les 3 octets 198.168.0 et toutes les machines du reseau 198.168.2.0 auront en commun les octets 198.168.2.

    • Le sous-réseau 192.168.2.0 comportera un switch et 3 ordinateurs M4, M5 et M6. Ces machines auront pour adresses IP:
      • 192.168.2.1
      • 192.168.2.2
      • 192.168.2.3

    Votre système devrait ressembler à l’image suivante:

    systeme de 2 sous-reseaux sans routeur

    systeme de 2 sous-reseaux sans routeur

    • Tester alors la commande ping depuis la machine M1 vers celle M6 du 2e sous-reseau.

    Qu.2a:: La machine M6 est-elle accessible depuis M1? Pourquoi?

    • Modifier le système en ajoutant un routeur:

      • clic droit sur le Switch2 : faire supprimer tous les cables
      • ajouter le routeur
      • paramétrer le routeur:

      clic sur le routeur

      renseigner les adresses des 2 reseaux sur l’interface du routeur:

      • 192.168.0.254 du côté du reseau 192.168.0.0 (à gauche)
      • 192.168.2.254 du côté du reseau 192.168.2.0 (à droite)
    adresses des reseaux

    adresses des reseaux

    cocher routage automatique:

    option routage automatique

    option routage automatique

    • Pour chacun des ordinateurs du sous-reseau 1, M1, M2, M3, renseigner l’adresse de l’interface reseau 1 du routeur: mettre 192.168.0.254 dans le champs passerelle. Ce sera l’adresse IP de la carte reseau du routeur, du côté du reseau 192.168.0.0 (on met 254 à la place de 0 pour l’adresse routeur).
    renseigner l

    renseigner l'adresse reseau pour chaque ordinateur

    • Même travail pour M4, M5, M6: renseigner la passerelle 192.168.2.254
    • refaire le cablage

    Qu.2b: Pourquoi le routeur de votre système informatique possède t-il 2 adresses IP?

    Qu.2c: Démarrer le système et tester alors la commande ping de M1 vers M6, puis de M6 vers M1. Que constatez-vous? Pourquoi?

    En cas de difficultés: on pourra consulter la video Filius 2 de David Roche

    TP Filius 3 : système avec routage (durée indicative: 20 min)

    On utilisera pour la suite un système informatique constitué de nombreux sous-reseaux:

    Premier contact avec le système

    Qu.3a. Représenter sur votre feuille le reseau en ne dessinant que les ordinateurs n°1 et n°15, ainsi que tous les routeurs traversé (plus court schemin entre M1 et M15).

    Qu.3b. Indiquer sur le schéma, pour chaque routeur, l’adresse passerelle que le message de M1 vers M15 va emprunter.

    Lancer la simulation

    1. Prendre connaissance de l’adresse IP de l’ordinateur n°15
    2. Depuis l’ordinateur n°1: Lancer le logiciel Ligne de commande
    3. Faire: traceroute suivi de l’adresse IP de la machine 15
    4. Repérer alors quels sont les adresses passerelles empruntées par les données entre ces 2 ordinateurs.

    Qu.3c. Quel est le nombre de sauts entre M1 et M15? Est-ce que le nombre de sauts effectués vous semble cohérent?

    Qu.3d. S’agit-il des mêmes adresses passerelles lorsque la machine M15 envoie un message à M1? Vérifiez le par une expérience.

    Table de routage

    Revenir en mode edition (marteau) : cliquer sur le routeur A Dans l’onglet général : décocher l’option : routage automatique

    Aller dans l’onglet table de routage (forwarding table):

    table de routage du routeur A

    table de routage du routeur A

    Q3e : cartes reseaux du routeur:

    • Hormis l’interface 127.0.0.1 : Combien d’interfaces différentes possède le routeur? (colonne NIC, next interface connection)
    • Quels sont les 3 réseaux auquel ce routeur est directement relié ? Donner leur adresse IP.

    Compléments théoriques sur les adresses des machines

    On pourra consulter la video sur les adresses IP et masques de sous-reseau

    Adresse IP

    IPv4

    L’adresse IP(Internet Protocol) identifie un périphérique à l’intérieur d’un réseau. A l’intérieur de ce réseau elle est unique.

    Une adresse (IPv4) est constituée de 4 nombres binaire de 8 bits chacuns (32 bits), comme par exemple:

    $1100 0000.1010 1000. 0000 0000. 0000 0001$

    Pour rendre la lecture plus facile, les séries de 8 bits seront traduites en leur valeur décimale correspondante, comprise entre 0 et 255 (voir le cours codage des nombres).

    L’adresse binaire vue plus haut sera alors traduite en :

    $192.168.0.1$

    L’adresse possède 2 parties:

    • une partie identifie la machine

    • une autre partie identifie le reseau

    Masque de sous-reseau

    Masque de sous-reseau: c’est une serie de valeurs avec des 255 ou 0, ou autre sur le(s) dernier(s) octet(s).

    La valeur correspondante binaire début donc par une série de 1, marquant les positions relatives à l’adresse reseau dans l’adresse IP.

    Par exemple: L’adresse machine suivante est constituée d’une première partie reseau, les 24 premiers bits, puis de l’adressage machine dans le reseau (8 derniers bits):

    $1100 0000.1010 1000. 0000 0000. 0000 0001 / 24$

    Le masque de sous-reseau est alors:

    $1111 1111.1111 1111. 1111 1111. 0000 0000$

    Que l’on peut aussi écrire:

    $255.255.255.0$

    Machines appartenant à un même reseau

    Definition: Deux machines sont sur le même réseau si et seulement si, la partie réseau de leur adresse IP est identique.

    Les derniers caractères /24 correspondent au masque de sous-reseau. Ils signifient que le reseau contenant la machine a une adresse codée sur les 24 premiers bits (192.168.0). Et que les 8 derniers bits constituent l’adresse de la machine dans ce reseau (il s’agit donc du .1 final).

    IPv6

    Pour la norme IPv6, ce nombre est sur 128 bits, soit 16 octets.

    Exemple d’adresse IPv6 exprimée en hexadécimal (32 caractères): 2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b

    classes d’adresse IP

    • classe A : adresses IP comprises entre 0.0.0.0 et 127.255.255.255 masque 255.0.0.0 : on ne peut avoir qu’une toute petite partie sous-reseau mais beaucoup d’adresses machines. Un petit reseau de beaucoup de machines.

    • classe B : 128.0.0.0 à 191.255.255.255 masque sous-reseau de 2 octets : on met autant de machines que de sous reseaux.

    • classe C : masque sous-reseau de 3 octets: beaucoup de sous-reseaux et peu de machines.

    Sur un reseau, deux adresses sont deja reservés: l’adresse de broadcast (bit adresse mis à 255), ainsi que l’adresse de reseau (bit d’adresse mis à zero). La plage adressable se situe entre ces 2 valeurs.

    Adresse mac

    Une adresse MAC (Media Access Control), parfois nommée adresse physique, est un identifiant physique stocké dans une carte réseau ou une interface réseau similaire. Elle est unique au monde

    Une adresse MAC est codée en hexadécimal, sur 6 octets (cf cours sur l’hexadécimal)

    00-1E-33-1D-6A-79 est une adresse MAC

    => Ouvrir l’invite de commande windows et entrer la commande ipconfig /all. identifier l’adresse MAC de votre ordinateur.

    Suite

    Liens

    informatique embarquée

    Projet de fin de chapitre: conception d'un objet simple (arrosage automatique, alarme, feu tricolore) avec algorithme, capteurs et actionneurs identifiés.

    Sous-sections de informatique embarquée

    Robot ou ordinateur

    Atlas (2013), robot androïde de Boston Dynamics. Wikipedia.

    Atlas (2013), robot androïde de Boston Dynamics. Wikipedia.

    Le terme robot est issu des langues slaves et formé à partir du radical rabot, rabota (работа en russe) qui signifie travail, corvée que l’on retrouve dans le mot Rab (раб), esclave en russe. wiki.

    Les robots sont utilisés pour des tâches qu’ils remplissent mieux que les humains. Il peut s’agir d’un travail répétitif, d’une tâche de haute précision, ou d’une activité dans un milieu hostile.

    Dans l’antiquité: Le mythe de Pygmalion racontait déjà comment la statue Galatée devint vivante et s’affranchit de son créateur afin de partir à la conquête du monde des hommes.

    A la Renaissance, Le premier exemple d’un robot de forme humaine fut donné par Léonard de Vinci en 1495. Ses notes à ce sujet recelaient des croquis montrant un cavalier muni d’une armure qui avait la possibilité de se lever, bouger ses membres.

    La litterature de science fiction du XIXe et XXe regorge d’exemples, mettant en scène des robots. Une oeuvre majeure est celle de Isaac Asimov: Les Robots (1950), dans laquelle il énonce les 3 lois de la robotique. Ces trois lois forment un principe d’organisation, qui donne un cadre aux différentes nouvelles.

    Les premieres machines autonomes, capables d’interagir avec l’homme apparaissent dans les années 1980.

    Computer History Museum, San José, CA

    Computer History Museum, San José, CA

    Les robots ne sont pas de simples automates: ils ont la capacité de s’adapter à leur environnement dans leurs déplacements et leurs actions. Ils analysent leur environnement pour réagir par le biais de capteurs et de programmes. Ils peuvent réagir à des situations imprévues (piece defectueuse, obstacle).

    Diversité des robots actuels. Wikipedia.

    Diversité des robots actuels. Wikipedia.

    Definition: Un robot est une machine possédant un processeur, une mémoire, des interfaces d’entrée et de sortie, et qui capable d’exécuter des programmes. C’est aussi la définition d’un ordinateur. La différence se situe avec la nature des capteurs et actionneurs que possède le robot, ce qui lui donne une action autonome, en temps réel et remplace souvent une activité humaine.

    On distingue parmi les extensions de la machine-robot, celles qui sont commandées (ACTIONNEURS) de celles qui numérisent une grandeur physique (CAPTEURS)

    C’est alors un programme, écrit en langage informatique, qui va traiter les données et commander la machine-robot, lui donnant un comportement autonome, en temps réel.

    Son comportement peut aussi être commandé par une autre machine, dans un système informatique disttribué.

    Description d’un système automatisé

    Le système automatisé comprend les sous-parties du robot, les interfaces, les machines utiles pour le traitement, les sources d’énergie.

    Par exemple: caméra, moteur, relais électrodynamique, batterie, lampes, roues, antenne radio, écran, ordinateur serveur, client, commutateur, …

    Premier exemple: robots agricoles

    Comment le robot s’inscrit-il dans un système informatique complet?

    • il utilise la reconnaissance de formes et de couleurs
    • analyse, déclenche une action en rapport avec cette mesure
    • Utilise une source d’énergie adaptée, qui les rend autonome
    • communique sur le reseau (internet)
    • echange avec un logiciel (IHM)
    Exemple 1

    Exemple 1

    Exemple 2

    Exemple 2

    Exemple 3

    Exemple 3

    voitures autonomes

    En test à San Francisco actuellement, les taxis autonomes.

    Jaguar électriques I-PACE Waymo One: taxi autonome

    Jaguar électriques I-PACE Waymo One: taxi autonome

    On peut représenter les sous-parties de ce système informatique avec les chaines d’information et d’énergie.

    Chaine d’information et chaine d’énergie

    Chaine d'information et chaine d'énergie, structure des systèmes

    Chaine d'information et chaine d'énergie, structure des systèmes

    Chaine d’information

    La chaine d’informations permet de transmettre entre différentes parties et traiter les données au niveau d’une machine.

    Décrire la chaine d’information revient à placer les verbes ACQUERIR, TRAITER LES DONNEES, COMMUNIQUER dans un diagramme d’activité:

    Camera -> ACQUERIR (images) -> TRAITER LES DONNEES (microcontroleur) -> COMMUNIQUER (antenne radio, interface de communication) -> stockage et traitement (serveur) ou bien : Camera -> ACQUERIR (images) -> TRAITER LES DONNEES (microcontroleur) -> COMMUNIQUER -> actionneur

    Chaine d’énergie

    La chaine d’énergie montre l’utilisation des différents capteurs et actionneurs, et la nature du travail (mécanique, électrique, lumineux) qui est mis en jeu.

    Décrire la chaine d’information revient à placer les verbes ALIMENTER, DISTRIBUER, CONVERTIR TRANSMETTRE dans un diagramme d’activité:

    Les robots et microcontrôleurs doivent souvent avoir une alimentation autonome, qui doit durer le plus longtemps possible. Il faut alors optimiser leur consommation électrique.

    Bilan: robot ou objet connecté

    La diversité de machines, et leur interaction, montre que le robot fait partie d’une plus grande famille d’objets, dont l’enjeu dépasse aujourd’hui le simple fait d’agir de manière autonome. Ce sont aussi et surtout des objets connectés, en reseau.

    On parlera plus d’objets connectés que de robots.

    Informatique et internet des objets

    Video du mooc SNT sur IOT

    Video du mooc SNT sur IOT

    A partir de la video: citer un ou des capteurs, actionneurs, un exemple de programme. Qu’est-ce qu’un objet connecté?

    Constitution d’un objet connecté

    Un objet connecté a une fonction: il est prévu pour réaliser certaines tâches en rapport avec la mission qu’il doit accomplir.

    Un objet connecté est muni de:

    • Capteur: transformation d’une mesure physique en un signal électrique.
    • Actionneur: transformation d’un signal electrique en un moyen physique
    • Processeur: pour un traitement local des données, plus ou moins complexe
    • Source d’énergie: adaptée à la fonction
    • Moyen de communication: du codage à la transmission des données selon des protocoles standards ou dédiés.

    Enfin, l’objet peut disposer également d’une IHM (interface homme-machine), souvent par l’intermédiaire d’une application.

    Définition d’un objet connecté

    Définitions d’un objet connecté et de l’Internet des Objets (IdO), ou Internet of Things (IOT):

    Un objet connecté dispose de tout ou partie des caractéristiques d’un robot, mais surtout, fait partie d’un système informatique à plusieurs machines, reliées au réseau internet.

    Les fonctions sont alors reparties sur l’ensemble de ces machines, et il peut arriver que le programme ne soit pas dans l’objet lui-même, mais dans une autre machine du système (le client, le serveur…)

    Enfin, grâce à la connexion internet, la communication peut se faire entre appareils eux-mêmes, ou entre appareils et le Cloud.

    • Les objets connectés sont donc des objets physiques connectés ayant leur propre identité numérique et capables de communiquer les uns avec les autres.

    Un objet connecté a deux rôles principaux:

    • La collecte de données issues de son univers (surveillance)
    • Un seuil d’ action: selon les données recueillies et communiquées. Ainsi, par exemple, déclencher l’arrosage du gazon lorsque la chaleur externe est trop élevée.

    Etude de quelques exemples d’objets connectés du quotidien: SNT, Lycee Lafayette Brioude

    Retrouver tous les constituants de l’objet connecté à partir de l’un des exemples proposés.

    Exemple 3

    Exemple 3

    A quoi servent-ils?

    Un objet connecté a une fonction: il est prévu pour réaliser certaines tâches en rapport avec la mission qu’il doit accomplir.

    les objets connectés proposent un certain degré de commodité dans notre quotidien. Grâce à cet objet, nous pouvons gagner beaucoup de temps et parfois d’énergie. L’idO est employé dans différents domaines d’activité.

    Vous les trouvez partout, de la machine à café aux jouets pour enfants: TOUT est susceptible de se transformer en IOT!

    La collecte des données en temps réel offre beaucoup de potentiel:

    • l’automatisation à partir de ces données
    • une gestion à distance
    • un historique qui peut être analysé

    Par ailleurs, l’Internet des objets vise à relever différents challenges majeurs actuels et futurs. page eurotechconseil.com:

    • Les smart-cities: pilotent le flux de circulation ou les illuminations en temps réel en fonction de l’heure de la journée. Une telle avancée technologique permet de régler certains des problèmes de saturation des centres-villes et de la pollution par la lumière, et de réduire les émissions de CO2.
    • transports publics: plusieurs capteurs existent pour diffuser des informations précieuses ainsi que pour réguler la circulation et renseigner les passagers en temps réel.
    • Dans les secteurs industriel et agricoles, l’idO augmente la productivité: surveillance des cultures et analyse du sol, arrosage intelligent, suivi distant de cheptel.
    • Aquaculture: station météo sous-marine avec surveillance de la qualité des eaux, détection de la pollution ou de contamination.
    • Domotique: thermostat intelligent, électroménager connecté, alarme connectée, pilotage de l’éclairage, des stores…
    • Santé: paire de lunette connectée pour une personne en situation d’handicap, peut fournir des informations sur les lieux alentour, bracelet connecté pour les personnes sourdes (envoi d’une impulsion selon l’activité ou les messages perçus), mesure du rythme cardiaque
    • Loisirs: balises GPS de géolocalisation de randonneurs, drones pour filmer defense: drones de combat

    Il peut donc exister autant d’objets connectés qu’il existe d’activités humaines.

    Un objet connecté dans le reseau internet

    modèle Client-serveur

    La communication entre un objet connecté et sa plateforme est du type client-serveur.

    Comme toute machine sur internet, un objet est identifié par son adresse IP. Dans son réseau, le canal de communication privilégié sera le Wi-Fi, le Bluetooth, la puce RFID…

    Le programme et les données: souvent, le programme n’est pas dans l’objet, mais dans le serveur prévu. L’utilisation du serveur necessite souvent de renseigner des informations personnelles lorsque l’on utilise un service connecté. Cela peut poser un problème sur la protection et l’usage de ces données.

    Les IOT sont-ils particulièrement vulnérables?

    On a vu que la communication entre Client et Serveur sur internet doit être authentifiée, que les données doivent circuler sans être modifiées (intégrité), et de manière confidentielle. Ce sont les protocoles HTTP(S), IP et TCP qui assurent le transport de cette manière. Le problème est que ces objets connectés disposent de moins d’énergie qu’un ordinateur, et d’une faible bande passante. Ces protocoles sont donc adaptés pour les IOT, mais avec moins de sécurité.

    Les IOT sont vulnérables, les failles de sécurité concernent:

    • la force des mots de passe employés pour se connecter à l’objet, voire l’absence de mots de passe (bluetooth, wifi direct): authentification pas assez securisée.
    • le wifi vulnérable, ce qui permet
      • de couper l’accès au réseau pour l’IOT (probleme s’il s’agit d’une caméra de surveillance)
      • de s’introduire dans le réseau, d’intercepter les données
    • l’IOT peut conserver le nom des utilisateurs. Recueillir ces noms d’utilisateurs peut être utilisé pour un attaque par phishing
    • l’absence de mise à jour du logiciel de l’IOT. Des failles de vulnérabilité permettent à un pirate de découvrir des ports ouverts et de prendre le contrôle de l’objet.
    • La sécurité de la plateforme, du logiciel côté serveur avec sa base de données peut poser des problèmes de confidentialité des données.

    Quels sont les moyens de sécuriser les IOT ?

    Des normes de sécurité rigoureuses préconisent:

    • l’authentification et les autorisation doivent être robustes
    • le chiffrement des données entre l’IOT et la plateforme
    • garantir l’intégrité des données (verification avec une fonction de hachage par exemple)
    • des mises à jours régulières des logiciels, avec des correctifs réguliers de la part du constructeur
    • une surveillance en temps réel pour détecter toute activité suspecte

    Problème de confidentialité des données

    De manière générale, les objets connectés font peser des risques en matière de vie privée avec la collecte des données. La Chine a ainsi développé un système de crédit social basé sur une surveillance généralisée de sa population (caméra et capteurs). Leur comportement est noté et les incivilités sont punies par l’abaissement de la note sociale des individus. Ceux-ci ne peuvent plus par exemple acheter un billet de train s’ils ont commis une incivilité dans les transports.

    Variété des modes de communication

    La plupart des IOT sont connectés sur internet via la wifi.

    Certains objets, comme les cartes à puce ont une architecture et un moyen de communication différents. Ce sont des cartes en plastique d’au moins 1mm d’epaisseur.

    image issue de wikipedia

    image issue de wikipedia

    La carte à puce contient un circuit intégré avec, selon le modèle:

    • de la mémoire flash
    • de la mémoire non volatile
    • un microprocesseur (pour les cartes à microcontrôleur)

    Elles sont souvent utilisées comme moyen d’identification.

    RFID: Radio Frequency Identification: c’est une méthode permettant de mémoriser et récupérer des données à distance. Le système est activé par un transfert d’énergie électromagnétique entre une étiquette radio et un émetteur RFID. L’étiquette radio composée d’une puce électronique et d’une antenne reçoit le signal radio émis par le lecteur lui aussi équipé d’une technologie RFID. Les composants permettent à la fois de lire et de répondre aux signaux.

    fonctionnement du RFID

    fonctionnement du RFID

    L’antenne reçoit un signal électrique alternatif, émis à distance par le terminal. La puce convertit ce signal en tension continue (alimente la puce) et alternatif (horloge pour synchroniser les echanges).

    On trouve cette technologie dans les puces pour animaux, clés de voiture, badges d’entrée, badge pour transport en commun… voir article sur RFID et NFC

    Le programme et les données: souvent, le programme n’est pas dans l’objet, mais dans le serveur prévu. L’utilisation du serveur necessite souvent de renseigner des informations personnelles lorsque l’on utilise un service connecté. Cela peut poser un problème sur la protection et l’usage de ces données.

    Une obsolescence programmée

    la durée de vie de ces objets peut être écourtée indépendamment de l’usure physique de l’objet. En effet, le fonctionnement des objets connectés dépend aussi de services proposés par le fabriquant, qui peut cesser avec son activité. Ce fut le cas du lapin connecté Nabaztag lancé en 2005, qui a cessé en 2011 avec l’arrêt des serveurs de la société.

    Le robot supérieur aux humains?

    Ces videos virales sur Youtube. Vrai ou Faux Robot?

    Exemple avec cette vidéo montrant un robot qui fait un superbe point contre le Polonais Pavel Sirucek

    Exemple avec cette vidéo montrant un robot qui fait un superbe point contre le Polonais Pavel Sirucek

    les vidéos de robotique virales nous conduisent à la prudence et à une analyse plus critique de ce que nous voyons.

    Liens

    A quoi sert un programme informatique

    Sojourner (de la sonde Mars Pathfinder est le premier rover géologue envoyé sur Mars. Il a ouvert la voie aux autres Spirit, Opportunity (2003), Curiosity (2011), Perseverence (2021) et Zuhrong (2021).

    le robot explorateur Pathfinder (1997) en plein travail

    le robot explorateur Pathfinder (1997) en plein travail

    Ce premier rover, muni d’un moteur (chenilles), d’une batterie solaire et une autre au Lithium, disposait d’une camera, une station meteo, et d’un spectromètre à RX pour analyser les échantillons minéraux. Il possedait egalement une antenne, dirigée vers la Terre pour ses communications.

    Les programmes qui le contrôlaient devaient lui permettre d’evoluer de manière plus ou moins autonome sur la surface de Mars, et de réaliser diverses mesures physiques, tout en veillant à sa propre sécurité et autonomie (batteries).

    Que fait un programme informatique?

    Ce qui fait fonctionner un appareil numérique, c’est un programme: C’est donc grâce à un programme que l’on fait fonctionner un ordinateur, une console de jeux, une machine à laver, le poste de pilotage d’un avion, un guichet automatique bancaire…

    des machines utilisant un programme informatique

    des machines utilisant un programme informatique

    Mais c’est aussi grâce à un programme que ces machines peuvent fournir un service: un logiciel de bureautique, un jeu, le lavage du linge, le pilotage automatique, ou le retrait d’argent de son compte….

    Aujourd’hui, le smartphone est l’objet qui nous permet d’executer de nombreux programmes, en permanence.

    applications et smartphone

    applications et smartphone

    On confond parfois programme informatique et logiciel, ou application. Un logiciel peut comporter plusieurs programmes.

    Quelques repères historiques

    • En 1842, la comtesse Ada Lovelace crée des diagrammes pour la machine analytique de Charles Babbage. Ces diagrammes sont considérés aujourd’hui comme étant les premiers programmes informatiques au monde
    • 1936: Première formulation de ce qu’est un programme par Alan Turing.
    • 1940: Les premiers ordinateurs. Les programmes informatiques étaient alors conçus par des analystes, rédigés par des programmeurs et saisis par des opératrices sur des bandes type cartes en carton perforé.
    • Le premier système d’exploitation a été développé en 1954.
    • 1970: début de la programmation structurée. Depuis, la variété et mise à jour des langages n’a cessé de rendre plus accéssible la programmation.
    Compléter la frise

    Compléter la frise

    Algorithme

    Un algorithme traduit le cahier des charges d’un programme en un langage naturel et non ambigü, où les instructions sont séquencées.

    Quelques exemples

    Origami

    • Cahier des charges: Réaliser une grue (l’animal) par 10 pliages succéssifs d’une feuille de papier.
    • Algorithme:
    extrait de la séquence de pliage

    extrait de la séquence de pliage

    L’algorithme du pliage de l’origami présente une structure linéaire. On peut visualiser celui-ci à l’aide d’un algorigramme

    Code PIN

    • Cahier des charges: Demander à l’utilisateur du smartphone de saisir son code PIN, et s’il echoue 3 fois, lui demander son code PUK
    • Algorithme: L’un des deux algorithmes correspond bien au cahier des charges
    # algorithme 1
    Répéter 3 fois:
      demander code PIN
    Si code PIN incorrect
      demander code PUK
    Sinon
      passer

    Ce premier algorithme montre une structure alternative: on commence par tester la condition ; si elle est vraie, l’action 2 est exécutée, sinon, c’est l’action 3.

    # algorithme 2
    demander code PIN
    nbessai = 1
    Tant que code PIN incorrect et nbessai < 3:
      demander code PIN
      nbessai = nbessai + 1
    Si code PIN incorrect:
      demander code PUK

    Dans ce 2e algorithme:

    • on utilise une variable appelée nbessai. Sa valeur est d’abord mise à 1, puis évolue au fur et à mesure que le programme avance.
    • on utilise une structure qui amène une répétition. (une structure itérative): Tant que <condition> …qui répète le bloc tant que la condition est VRAIE.

    Questions:

    1. Pour l’algorithme 1, compléter l’algorigramme.
    2. Trouver lequel des 2 algorithmes correspond bien au cahier des charges.
    3. Pour les 2 algorithmes: Expliquer ce que fait le programme si l’utilisateur entre 2 fois un code PIN erroné, puis entre le bon (au 3e essai).
    4. Pour l’algorithme 2: expliquer ce que fait le programme lorsque l’on entre 3 code PIN erronés.

    Les ingrédients d’un algorithme

    Les instructions relatives aux ingrédients d’un algorithme seront données en langage naturel, mais à la manière du langage Python.

    Données: Variables et opérations

    Une variable stocke une valeur et peut être utilisée pour des opérations.

    (voir introduction à la programmation)

    • Exemples Le signe = permet d’affecter une valeur à une variable:
    nom de la variable affectation d’une valeur type de variable
    nbessai nbessai = 1 nombre entier
    message message = "bonjour" texte
    text1 texte1 = “je suis " texte
    text2 texte2 = “le prof” texte

    Lors de l’affectation, python va choisir un type pour cette variable, ce qui va permettre certaines opérations.

    • Opérations sur les variables de type textes:
    >>> text1 = "je suis "
    >>> text2 = "le prof"
    >>> text = text1 + text2
    >>> afficher(text)
    je suis le prof
    • Opérations sur les variables de type nombres entiers:
    >>> nbessai = 1
    >>> nbessai = nbessai + 1
    >>> afficher(nbessai)
    2

    Interface: Entrées/Sorties

    Un algorithme doit fournir une interface qui permet d’interagir avec l’utilisateur. Il doit pouvoir lire et entrer des données.

    Ce sont les instructions: afficher et entrer qui réalisent ceci.

    afficher("un message")
    afficher(une_variable)
    
    x = entrer("position")

    Contrôler le programme: Structures conditionnelles

    Cette structure permet d’effectuer une séquence d’opérations selon la valeur d’une condition.

    Une condition est une expression logique (on dit également booléenne), dont la valeur est vrai ou faux.

    Si ( <expression_logique> ) alors 
      <bloc_alors>
    Sinon 
      <bloc_sinon>
    • Exemple: le physionomiste d’une discothèque

      • Programme 1: Vous pouvez entrer si vous avez plus de 18 ans
    >>> si age >= 18 alors:
          dire("vous pouvez entrer")
        sinon : 
          dire("repasser une prochaine fois")
    • Vous pouvez entrer si vous avez plus de 18 ans, ET si vous ne portez pas des baskets
    >>> si age >= 18 ET non porte_des_baskets alors:
          dire("vous pouvez entrer")
        sinon : 
          dire("repasser une prochaine fois")

    Contrôler le programme: Boucles

    • Les structures répétitives permettent d’exécuter plusieurs fois un bloc d’opérations, en faisant varier automatiquement une variable de boucle.
    Pour <identificateur_variable> de <valeur_début> a <valeur_fin> faire
     <bloc_opérations> 
    • Les structures répétitives permettent d’exécuter plusieurs fois un bloc d’opérations, tant qu’une condition (de continuation) est satisfaite.
    Tantque ( <condition> ) faire
     <bloc_opérations> 

    Structure: Fonctions et Procedures

    Les fonctions permettent de rendre le script plus efficace, plus facile à lire et à vérifier. Un bonne pratique est de faire régulierement du remaniement de son code : C’est à dire ré-écrire les parties du programme qui fonctionnent et les mettre dans une fonction. Cela evite aussi les répétitions. On remplace alors le code par un appel à une fonction.

    La programmation se fait en deux temps: On commence par programmer la fonction

    fonction carre(x)
      y = x * x
      return y

    Puis on appelle cette fonction:

    a = 10
    carre(10)

    Le programme retourne dans ce cas la valeur 100.

    Langages informatiques

    Les instructions qu’un ordinateur devra exécuter doivent pouvoir être exprimées de manière précise et non ambiguë.

    Définitions

    Un programme informatique

    C’est un ensemble d’opérations destinées à être exécutées par un ordinateur.

    Un programme source est un code écrit par un informaticien dans un langage de programmation. Il peut être compilé vers une forme binaire ou directement interprété. Au final, les instructions seront traduites en binaire, afin qu’elles soient exécutées par un microprocesseur.

    Un langage de programmation

    C’est une notation utilisée pour exprimer des algorithmes et écrire des programmes.

    Un algorithme

    Un algorithme est un procédé pour obtenir un résultat par une succession de calculs, décrits sous forme de termes simples dans une langue naturelle. C’est une suite finie et non ambigüe d’instructions, permettant de resoudre certains problèmes.

    Un bug

    Un bug est un défaut de construction dans un programme. Les instructions que l’appareil informatique exécute ne correspondent pas à ce qui est attendu, ce qui provoque des dysfonctionnements et des pannes.

    Exercices

    Ex 1: code PIN et code PUK

    Le programme suivant, est-il celui utilisé pour le deverouillage d’un smartphone? Pour repondre à la question:

    • dessiner l’algorigramme correspondant.
    • Expliquer ce que fait le programme lorsque l’utilisateur se trompe 3 fois de suite de code PIN, puis parvient enfin à rentrer le bon (au 4e essai).
    # algorithme 3
    demander code PIN
    Tant que code PIN incorrect:
      demander code PIN
    demander code PUK

    Ex 2: Application pour la course à pied

    • Cahier des charges: Une application de course à pieds sur spartphone propose à l’utilisateur de rentrer les distances parcourues chaque jour. Lorsque l’utilisateur a atteint son objectif, fixé à 42 km, le décompte s’arrête. L’ecran affiche alors: Félicitations
    • Algorithme:
    total = 0
    Tant que total ...    :
      distance = entrer("Saisir la distance : "))
      ...
    Afficher("Félicitations")

    Remarque: l’instruction distance = entrer("Saisir la distance : ")) va afficher Saisir la distance :, puis stocker celle-ci dans la variable distance.

    • Compléter l’algorithme.
    • Expliquer ce que fait le programme lorsque l’utilisateur entre successivement: 10, 12, 10, 15.

    Ex 3: Diamètre d’ouverture de l’appareil photographique

    • Cahier des charges: Pour l’appareil photo numérique: Mesurer le flux lumineux. Si celui-ci est supérieur à 100 Lux, diminuer le diamètre d’ouverture. S’il est infèrieur ou égal à 100 Lux, ouvrir davantage.

    • Algorithme:

    Répeter indefiniment:
      Mesurer la lumière et stocker dans L
      Si L ...  :
        ...
      Sinon:
        ...

    A vous de jouer: Compléter l’algorithme.

    Remarque: on peut utiliser les fonctions diminuer et augmenter pour agir sur l’ouverture de l’appareil photo.

    Exercices supplementaires

    Ex 1

    On donne le script d’un programme en langage naturel, ainsi que sa traduction en Python. Déterminer, à la fin du programme, les valeurs stockées dans les variables a, b et c.

    • Programme 1 en langage naturel
    a = 10
    b = 5
    c = 1
    si ( a == b )
     c = 2 * c
    sinon
     a = a + 1
     b = b div 2
    • Programme 1 en langage Python
    a = 10
    b = 5
    c = 1
    if ( a == b ):
     c = 2 * c
    else:
     a = a + 1
     b = b / 2 

    Ex 2

    On donne le script d’un programme en langage naturel, ainsi que sa traduction en Python. Déterminer, à la fin du programme, la valeur stockée dans la variable a.

    • Programme 2 en langage naturel
    a = 10
    Tantque ( a different de 0 ) faire
     afficher ( 2 * a )
     a = a - 1 
    • Programme 2 en langage Python
    a = 10
    while ( a != 0 ):
     print 2*a
     a = a - 1 

    Ex 3

    On donne le script d’un programme en langage naturel, ainsi que sa traduction en Python. Déterminer, à la fin du programme, la valeur stockée dans la variable a.

    • Programme 3 en langage naturel
    pour i de 1 a n faire
     a = 3 * i
     Afficher ( a )
    • Programme 3 en langage Python
    for i in range(1,n+1):
     a = 3 * i
     print a

    range(a,b) permet de parcourir les valeurs a, a+1, …, b-1 (b non compris)

    Exercices issus du site Algorea

    Boucle simple

    Plots

    Ecrire un programme utilisant une boucle for, permettant au robot de deposer un plot sur chaque repère.

    parcours initial

    parcours initial

    Fonctions disponibles : tournerGauche(), tournerDroite(), avancer(), deposerPlot(), surCaseMarquee(), plotDevant().

    Mots-clés autorisés : for.

    Caisses

    Programmez le robot pour qu’il pousse les caisses sur les cases marquées.

    parcours carré

    parcours carré

    Fonctions disponibles : tournerGauche(), tournerDroite(), avancer(), pousserCaisse().

    Mots-clés autorisés : for.

    Boucle et test conditionnel

    Compléter le programme suivant pour qu’il permette au robot de déposer tous les plots sur les repères. Le programme doit fonctionner quel que soit le terrain (1, 2, ou 3) proposé:

    terrain 1

    terrain 1

    terrain 2

    terrain 2

    terrain 3

    terrain 3

    from robot import *
    for i in range(9):
        if surCaseMarquee():
            deposerPlot()
            ...
        else:
            ...

    Fonctions disponibles : tournerGauche(), tournerDroite(), avancer(), deposerPlot(), surCaseMarquee(), plotDevant().

    Mots-clés autorisés : if, else, for.

    Boucle conditionnelle: while

    Programmer le robot pour qu’il ramasse sa bille et la pose sur le trou le plus éloigné. Cette fois, on n’utilisera pas le mot-clé for car on ne connait pas à l’avance le nombre de cases à parcourir.

    On utilisera plutôt le mot-clé while suivi de la condition à réaliser pour executer les instructions.

    Ce sujet contient deux tests, avec une position différente pour le trou. Votre programme doit fonctionner pour les deux.

    test 1

    test 1

    test 2

    test 2

    Fonctions disponibles : droite(), ramasser(), deposer(), surTrou()

    Mots-clés autorisés : while, not

    Boucle for, boucle conditionnelle while

    Même exercice que precedemment, mais cette fois, ce sont les 2 parcours suivants qui doivent être réalisés par le même programme:

    test 1

    test 1

    test 2

    test 2

    Fonctions disponibles : droite(), gauche(), bas(), ramasser(), deposer(), surTrou(), surObjet()

    Mots-clés autorisés : for, while, not

    Utiliser des variables

    Pour la première situation, le robot consomme 1 segment de sa batterie chaque fois qu’il pose un plot. Il doit s’arrêter de travailler lorsque sa batterie ne contient plus qu’un seul segment. Comment peut-il tenir le compte du nombre de segments utilisés, et donc, du niveau de sa batterie?

    batterie du robot

    batterie du robot

    Fonctions disponibles : tournerGauche(), tournerDroite(), avancer(), deposerPlot(), surCaseMarquee(), plotDevant().

    Mots-clés et symboles autorisés : for, while, not, =, +, -, >, <

    Liens et ressources

    • Programme informatique: wikipedia
    • exercice sur algorithme issu du Bordas 3.0 SNT (code PIN)
    • exercice sur algorithme issu du Delagrave SNT (course à pieds)
    des exemples de figures mathématiques

    des exemples de figures mathématiques

    TP Python Turtle

    Le module Turtle de Python permet de dessiner à l’écran des formes, à l’aide d’instructions qui tracent des formes géométriques.

    Nous nous limiterons aux fonctions:

    • up() : lève le crayon
    • down() : baisse le crayon
    • forward(n) : avance de n
    • left(n) : tourne vers la gauche de n degrés
    • right(n) : tourne vers la droite de n degrés
    • circle(n) : dessine un cercle de rayon n
    • write(’texte’) : écrit le texte
    • color(’couleur’) : définit la couleur du trait
    • fillcolor(‘couleur’) : definit la couleur du remplissage

    Premiers tracés

    L’interface Scratch + Python de Vittascience

    • Aller sur le site Vittascience.com Le site propose un éditeur Scratch en ligne (avec des blocs de code).

    Les blocs de code sont accessibles à partir des menus, par genre:

    • Affichage
    • Turtle
    • Logique
    • Boucles
    • Variables
    • Fonctions …

    Pour commencer: dessiner un triangle simple

    Assembler les blocs

    A partir du menu Turtle, en utilisant les blocs, vous allez:

    bloc avancer du menu Turtle

    bloc avancer du menu Turtle

    avancer de 50
    tourner a gauche d'un angle de 120°
    avancer de 50

    Vous voyez sur l’écran de droite le script Python équivalent, qui se construit au fur et à mesure:

    import turtle
    
    turtle.forward(50)
    turtle.left(120)
    turtle.forward(50)

    Appuyer sur Executer: La forme dessinée n’est pas un triangle fermé.

    Défi 1: ajouter les blocs manquants pour dessiner complètement le triangle.

    • Recopiez le script python correspondant dans votre cahier.

    Répéter avec une boucle

    Si vous observez votre script, vous remarquez qu’il est constitué de 3 répétitions:

    Vous allez réaliser la même chose, mais en réduisant AU MAXIMUM le nombre de lignes.

    • Conserver uniquement les 2 premiers blocs, AVANCER et TOURNER. Supprimer les autres
    • Dans le menu Boucles, prendre le bloc répéter … fois et insérer dans ce bloc les 2 instructions de dessin. Modifier le paramètre 3.
    • EXECUTER le programme
    • Recopiez le script python correspondant dans votre cahier.

    Créer une spirale de triangles

    Défi 2: Vous allez créer une figure originale en modifiant juste les paramètres dans votre script:

    • Répéter 25 fois
    • Faites tourner chaque fois votre Tortue d’un angle de 125° et non 120°

    Vous voyez ici l’interêt d’utiliser une boucle pour répéter plusieurs fois les même instructions…

    Créer ses propres fonctions

    Une fonction permet de mémoriser des blocs de code afin de les organiser et les réutiliser plusieurs fois.

    • Remettre les arguments qui dessinent un triangle simple (3 fois, 120°)
    • Dans le menu Fonctions, prendre le premier bloc Définir. Modifier le nom, et renommer cette fonction avec triangle.
    • Mettre alors la boucle entière dans cette fonction. EXECUTER… il ne se passe rien.
    • Revenir dans le menu Fonctions et:
      • aller chercher le bloc de code appelé triangle.
      • Ajouter ce bloc dans la programme, à la suite
      • et EXECUTER… voilà qui devrait afficher le triangle. Vous venez de programmer votre propre fonction, puis vous l’avez appelé avec son nom, triangle().
    • Recopiez le script python correspondant dans votre cahier.

    Réutiliser une fonction

    Voici un extrait de la suite du script qui vous permettra de créer une figurre plus complexe:

    Défi 3: Vous allez déplacer votre Tortue à différentes positions de l’image, afin de dessiner la forme suivante:

    Remarque: Vous aurez besoin pour cela de réutiliser votre fonction triangle.

    Une fois le défi réalisé, recopiez le script dans votre cahier.

    Défi 4: Réaliser maintenant l’une des figures ci-dessous:

    figure 1: triangles alignés

    figure 1: triangles alignés

    figure 2: triangles tournants

    figure 2: triangles tournants

    images numeriques

    Projet de fin de chapitre:
    • comparer les tailles de fichier selon la résolution et le format (JPEG vs PNG), et documenter la perte de qualité liée à la compression.
    • stéganographie (retrouver le message caché dans une image)
    • créer une affiche démontant une image retouchée/deepfake avec analyse technique (pixels, métadonnées).

    Sous-sections de images numeriques

    Photographie numérique

    • culture numer Photographie numerique: Lien
    • culture numer Enjeux ethiques et societaux: Lien
    • competences TP detourer une image avec Gimp: Lien
    • competences TP données EXIF et données colorimetriques: Lien
    • modelisation TP pixel art avec microbit: Lien
    • modelisation Coder une image numerique avec un langage de programmation ou dans un fichier de données: Lien
    • modelisation metadonnées EXIF, programme python pour interagir avec les metadonnées: Lien

    Astrophotographie avec un smartphone?

    culture numer
    Jupyter au smartphone

    Jupyter au smartphone

    En disposant un smartphone sur un téléscope, on approche rapidement les limites de la qualité de l’appareil photo: sa capacité à capter les détails: les contours, les petits objets, le manque de contraste et de lumière.

    On peut deviner que ce qui caractérise une image numérique, c’est:

    • sa définition
    • sa profondeur de couleurs
    • son poids (en Mo)

    Ces caractéristiques vont dépendre de la chaine d’acquisition de l’image, dont l’appareil photographique fait partie.

    L’appareil photographique numérique

    Présentation

    Video: Fonctionnement d un appareil photo numérique

    Video: Fonctionnement d un appareil photo numérique

    Composants principaux

    On retrouve dans un appareil photographique numérique, ou pour la partie photographie d’un smartphone ou d’une tablette, les constituants suivant :

    • L’objectif photographique : c’est un système optique, amovible ou non, convergent et composé généralement de plusieurs lentilles.

    objectif AP

    objectif d appareil photo

    objectif sur un smartphone

    objectif photographique smartphone

    • La cellule d’exposition : c’est un composant électronique qui permet de mesurer la lumière renvoyée par le sujet et de régler l’ouverture du diaphragme, le temps d’ouverture de l’obturateur, et le déclenchement du flash. Cela permettra d’obtenir une exposition correcte.

    • L’obturateur est une piece qui s’ouvre et se ferme pour laisser passer la lumiere pendant un temps appelé temps d’obturation, choisi par le logiciel.

    • Le diaphragme : c’est une piece dont le diamètre (l’ouverture) est réglable. Ceci permet de limiter la quantité de lumière qui rentre dans l’appareil photographique.

    • un filtre de Bayer (RVB), sans qui la photo serait en N&B

    filtre de bayer

    filtre de bayer et photosite

    Ce filtre de bayer est en réalité constitué de 3 filtres. La lumière issue de l’objectif traverse la grille de filtres colorés avant d’éclairer la grille de photosites.

    • un capteur, constitué de photosites, répartis sur une grille. Ce capteur se trouve à l’endroit où la lumière est focalisée (nette). Les photosites transforment l’intensité lumineuse en signal électrique.

    Cette grille de photosites correspond à la pellicule photosensible des appareils photo argentiques. Sauf qu’avec un appareil photo numérique, l’image est construite en données …numériques, qui correspondent aux pixels.

    Sur l’image suivante, on voit que la grille contient des carrés constitués de 2 cellules sensibles au vert, 1 cellule au bleu et 1 cellule au rouge. Il y a donc 2 fois plus de cellules vertes que de cellules rouge ou bleu.

    photosites

    plan de photosites

    • Une carte mémoire (SDcard), pour y enregistrer les images.
    • un ordinateur interne capable de traiter des programmes.

    Le plus petit détail d’une image: le PIXEL

    L’image est construite en données numériques qui correspondent aux pixels.

    C’est le grain de coloration d’une image, l’atome de l’image numérique.

    La Definition d’une image correspond au nombre de pixels de l’image, exprimé en largeur * hauteur (par exemple 800 * 600).

    Codage

    Pour une image en noir et blanc: le codage numerique sera de 1 bit par pixel.

    Pour une image couleur: Un des algorithmes possibles consiste à créer un pixel à partir de 4 photosites : un bleu, un rouge et deux verts. Un pixel sera alors composé de 3 couleurs : rouge, vert, bleu (RVB).

    Restitution

    Sur un écran numérique, un pixel est constitué de 3 diodes luminescentes, presque au contact, et qui vont restituer la couleur en un point. Ces 3 diodes constituent le pixel.

    Lorsque l’on agrandit l’image, celle-ci parrait nette si la définition de l’image numérique est supérieure à celle de l’écran.

    pixels sur un smartphone

    detail des pixels d'un iphone

    De manière générale, c’est la densité de pixels qui va donner le détail de l’image. Elle est exprimée en pixels/cm ou pixels/pouces. C’est la résolution d’un écran.

    faible et forte densité

    faible/forte densité de pixels, image de formettic.be

    image issue de la page formettic.be

    réglages lors de la prise de photographie

    Les réglages de l’appareil photographique se font la plupart du temps de manière automatique.

    Mise au point: La mise au point est l’opération qui consiste, pour un photographe, à régler la netteté de l’image qu’il veut obtenir.

    Algorithmes de prise de vue

    l’appareil photographique est capable de mesurer la quantité de lumière, et de régler seul:

    • le diapragme : c’est la taille de cette ouverture qui détermine la quantité de lumière arrivant sur le capteur.
    • la vitesse d’obturation : correspond à l’intervalle de temps durant laquelle l’obturateur de l’appareil photo laisse entrer la lumière. Plus cette vitesse est lente et plus l’appareil photo capte la lumière. L’ image sera alors plus lumineuse. Ce réglage influe aussi sur la profondeur de champs, et la netteté des images pour des sujets en mouvement (mode sport).

    Algorithme d’aide à la mise au point

    Parfois, la mise au point automatique n’est pas possible. Certains appareils photographiques proposent une option d’aide appelée le Focus Peaking (l’intensification de la mise au point). C’est utile lorsque le sujet manque de lumière, ou que l’on utilise un objectif manuel.

     En rouge, le focus peaking qui indique la zone de mise au point

    En rouge, le focus peaking qui indique la zone de mise au point

    Voici un exemple d’algorithme utilisé:

    pour chaque pixel:
      si le contraste avec un pixel voisin est fort alors:
        colorier le pixel en rouge

    Algorithmes de correction

    Correction du flou: Une image floue est une image dont la valeur radiométrique de chaque pixel a été altérée localement par les valeurs des pixels au voisinage. Ce problème est du au temps d’exposition qui est trop long.

    Les algorithmes de correction de flou on beaucoup progressé avec la cartographie mobile. En effet, il n’était pas possible de ralentir le vehicule lors des prises de vues (circulation routière de jour), ni d’utiliser de flash puissant pour éclairer les façades (nuit).

     véhicules terrestres decartographie mobile

    véhicules terrestres decartographie mobile

    L’algorithme utilisé va alors calculer le mouvement des pixels pour reconstruire l’image nette.

    résultat du traitement par algorithme

    résultat du traitement par algorithme

    algorithme de correction des couleurs L’intensité de la couleur est mesurée par la saturation. Les applications de traitement d’image permettent la correction de la saturation grâce à des filtres, qui seront appliqués à tous les pixels de l’image.

    Qu’est ce qu’une photographie numérique ?

    Une photographie numérique, comme tout autre objet numérique, c’est un fichier de données numériques, c’est à dire des valeurs codées en binaire.

    Une partie des données correspond à des métadonnées, c’est à dire des données périphériques. L’autre partie contient les données relatives à l’image: pour chaque pixel, le fichier contient les données des intensités RVB.

    On pourra consulter la page sur les

    Enjeux ethiques et societaux de l'image

    L’intégration des appareils photo dans les smartphones a multiplié les usages d’une photographie:

    La photographie n’est plus seulement utilisée pour conserver les souvenirs mais permet à tout instant de partager un moment ou de servir d’aide-mémoire.

    Cela engendre des problèmes de stockage mais également de droits. En effet, à l’heure où des millions de photos sont mises en ligne sur les réseaux sociaux, des espaces communautaires comme Flickr, Instagram et où la duplication est instantanée, la protection des données et le respect des droits d’auteur représentent un enjeu majeur.

    Le support de l’image comme témoignage ou éléments de preuve est remise en cause en raison de la facilité avec laquelle on peut effectuer des retouches sans qu’on les détecte.

    culture numer

    Droit à l’image des personnes photographiées

    Contexte

    “Ni l’auteur, ni le propriétaire d’un portrait, ni tout autre possesseur ou détenteur d’un portrait n’a le droit de le reproduire ou de le communiquer au public sans l’assentiment de la personne représentée ou celui de ses ayants droit pendant vingt ans à partir de son décès”.

    Selon ce principe, l’autorisation de la personne photographiée doit être demandée.

    Le droit à l’image ne s’applique pas à une personne photographiée de dos ou dans une foule.

    Personnalité publique

    Cependant, pour les personnages publics et les personnes privées qui accèdent temporairement à la vie publique, cette autorisation est considérée comme implicite, pour autant que les images relatives à la vie publique des personnes concernées soient publiées dans un contexte de couverture d’événements relevant de l’actualité. Ces photos ne peuvent en aucun cas être dénigrantes ou diffamatoires et elles doivent avoir un rapport avec la fonction ou le métier exercé par la personne photographiée.

    Diffamation

    En tout état de cause, le respect de la vie intime et de la dignité de la personne humaine primera toujours sur la liberté d’expression.

    Droit d’auteur

    Propriété intellectuelle

    Une œuvre est protégée automatiquement, du simple fait de sa création et sans qu’il soit nécessaire de procéder à aucun enregistrement, dépôt, paiement de taxe, ou autre formalité.

    Toutes les productions du domaine littéraire, scientifique et artistique, quel qu’en soit le mode ou la forme d’expression, telles que notamment les livres, brochures et autres écrits, les conférences, les compositions musicales avec ou sans paroles, les œuvres chorégraphiques, dramatiques, audiovisuelles, multimedia, les dessins, peintures, sculptures, les plans d’architecte, les photos, les œuvres de l’art appliqué, les bases de données, les programmes d’ordinateur, sites internet… exprimées dans une forme originale.

    Pour être protégée, l’œuvre doit donc :

    • être originale Cette condition n’est pas formellement définie par la loi. On considère généralement qu’une œuvre est originale lorsqu’elle représente l’expression de l’effort intellectuel de l’auteur qui l’a réalisée et/ou lorsqu’elle porte l’empreinte personnelle de celui-ci.
    • être mise en forme La création doit avoir atteint une certaine « concrétisation », sans nécessairement que l’œuvre soit achevée. Les idées, les concepts ne sont pas protégeables.

    Reproduction d’une oeuvre

    Les œuvres exposées sur la voie publique ne font pas partie du domaine public. S’il s’agit d’une œuvre originale protégée par le droit d’auteur, imaginons des sculptures de Folon exposées au parc royal, l’autorisation de l’auteur sera toujours nécessaire pour publier des photos des œuvres exposées.

    images sur le Net

    Très souvent, les images disponibles sur internet, qu’il s’agisse de photos ou d’images graphiques, ne sont pas libres d’utilisation. En aucun cas, le fait qu’une photo soit disponible dans une banque d’image ne signifie que la personne représentée a donné son accord à la reproduction ou la communication au public de son image ! Une autorisation expresse est toujours nécessaire.

    Il en va de même pour les logos, dessins, images graphiques disponibles dans ces banques d’image. Non seulement, le nom de l’auteur est rarement mentionné, mais, généralement, il n’a pas donné son accord pour la diffusion et l’utilisation de ses créations.

    En reprenant des photos ou des images protégées par le droit d’auteur, vous vous rendez coupable d’un acte de contrefaçon puni civilement et pénalement. La plus grande prudence s’impose donc.

    Licence Creative Commons

    Détourner d’images

    Une pratique virale

    L’image numérique peut être facilement modifiée, transformée, et devenir un objet complètement artificiel.

    la nécessité d’illustrer un contenu sur le web est devenu tellement indispensable qu’il est préférable d’utiliser une image «passe-partout» voire inappropriée plutôt que rien du tout!

    *Une seule image, et des milliers d’interprétations possibles.* L'article suivant

    une image source, impersonnelle

    une image source, impersonnelle

    Quelques exemples

    Des images numériques crées par superposition de calques.

    Source : okeit.net

    Source : okeit.net

    Source : awkward.com

    Source : awkward.com

    Cette « vague de riz » est une sculpture japonaise exposée dans un magasin d’alimentation à Tokyo.

    Vérifier l’authenticité d’une image ou d’une information numérique

    Les vrais sites d’information

    Le Décodex

    Reseaux sociaux

    Pourquoi utiliser Decodex?

    Google images

    Une photo ou une vidéo n’est jamais une preuve en soi. Pour vérifier la nature d’une photo, on peut effectuer une recherche sur Google photo, non pas par mots-clés, mais par images (uploader ou coller l’URL). On peut aussi faire un clic droit sur l’image et choisir (Google lens).

    TP données EXIF et données colorimetriques

    Partie 1 : synthèse additive des couleurs

    Pour une image en couleur: À chaque pixel on associe 3 couleurs, le rouge, le vert et le bleu. On parle du canal rouge, du canal vert et du canal bleu d’un pixel (système RVB ou RGB en anglais).

    La valeur de l’intensité lumineuse associée à chaque canal de chaque pixel d’une image est comprise entre 0 et 255 (256 valeurs possibles). On codera donc un pixel à l’aide d’un triplet de valeur (par exemple (247,56,98) en code décimal, ou son équivalent en hexadecimal : (f7,38,62)

    Ouvrir le lien suivant : www.proftnj.com/RGB3.htm Question a: à l’aide du logiciel : Quelle est la couleur donnée par ce triplet de valeurs ? (247,56,98)

    Question b: Combien de couleurs différentes est-il possible d’obtenir avec ce système RVB ? (combinaison de 3 couleurs, codées chacune sur 256 valeurs,…)

    Question c: Pour chacune des couleurs du tableau, indiquer le code couleur RGB décimal correspondant:

    code couleur RGB
    blanc blanc
    bleu bleu
    vert vert
    rouge rouge
    jaune jaune
    gris gris
    noir noir

    Astuce: On pourra verifier l’exactitude de la reponse avec l’outil de prélèvement de couleur (logiciel Paint). Suivre le tuto suivant: https://www.pcastuces.com/pratique/astuces/5453.htm

    Partie 2: Les données EXIF

    Certaines informations, contenues dans le fichier image, donnent des informations sur les conditions de la prise de vue, le type d’appareil utilisé, la géolocalisation, les dimensions de l’image… Ces données suivent un format précis du standard EXIF.

    Utilisez un logiciel en ligne de lecture des données EXIF, comme par exemple : onlineexifviewer.com/

    • Télécharger l’image suivante sur votre disque dur
    • Select image depuis le logiciel en ligne

    cliquer sur l'image pour telecharger

    cliquer sur l'image pour telecharger

    Le logiciel met ces données EXIF sous une forme lisible par un être humain :

    Question d compléter les informations contenues dans le fichier de cette photographie :

    information donnée EXIF
    L’appareil photo utilisé
    La lentille de l’objectif
    Les coordonnées GPS du lieu où la photo a été prise
    La date de la prise de vue
    Le nombre de pixels
    Poids de la photo en ko Mo

    Question e: Quel est l’endroit où la photo a été prise (pays, region, commune) : utiliser le lien proposé vers openstreetmap par exemple.

    Partie 3: Vrai ou Fausse photo?

    Le paragraphe suivant explique qu’il est possible de faire une recherche par image, et, peut-être, de retrouver la source.

    Question f: L’image suivante est-elle une vraie image?

    TP pixel art

    Pixel art

    Codage d’une image numérique

    Une image numérique est constituée de pixels juxtaposés dont on règle l’intensité lumineuse. L’image suivante montre le caractère a obtenu en remplissant judicieusement la grille de pixels de 5 pixels * 6 pixels. C’est en prenant un recul suffisant que l’image retrouve sa finesse, et que les pixels se mélangent pour former la lettre a.

    Ici, l’image est en noir et blanc. Les pixels ont une intensité que l’on pourrait représenter par 0 ou 1. Les pixels d’intensité lumineuse égale à 0 sont noirs. Ceux à 1 sont blancs.

    détails du caractère a

    détails du caractère a

    On pourrait représenter chaque ligne de cette image par une liste de valeurs 0 ou 1 :

    ligne1 = [1, 0, 0, 0, 1]

    L’image entière serait alors une liste de listes (une liste contenant les listes de chaque ligne). On donne ci-contre un extrait :

    image = [[1, 0, 0, 0, 1], [1, 1, 1, 1, 0], … [1, 0, 0, 0, 0] ]

    ou bien, sur plusieurs lignes:

    image = [[1, 0, 0, 0, 1],
             [1, 1, 1, 1, 0],
              . . .  
             [1, 0, 0, 0, 0] ]

    à vous de jouer: Compléter la liste contenant l’image du bateau.

    L’écran LED de la carte microbit

    La carte microbit est un microcontrôleur que l’on peut programmer en Python. Cette carte dispose de capteurs intégrés (temperature, luminosité, champ magnétique), peut communiquer par ondes radio.

    Et surtout, elle dispose d’un écran de diodes électroluminescentes (DEL), que l’on peut allumer en fonctions des coordonnées x, y de ces diodes.

    coordonnée pour chacune des DEL x,y

    coordonnée pour chacune des DEL x,y

    La grille de DEL de la carte microbit est constituée d’un plan de 5 * 5 LED. L’intensité lumineuse est ajustable avec une valeur entre 0 à 9. La valeur 0 correspondant à la LED éteinte, 9, allumée au maximum. Il y a donc 10 niveaux d’éclairement, pour chaque pixel.

    # instruction pour allumer une DEL en x,y
    display.set_pixel(x,y, 9)
    # instruction pour éteindre une DEL en x,y
    display.set_pixel(x,y, 0)

    Le simulateur de carte microbit

    Programmer l’affichage d’une image

    Imaginons que nous ayons à créer une structure de données qui contienne l’image d’un bateau.

    deux mâts dessiné avec un tableau de DEL 5 x 5

    deux mâts dessiné avec un tableau de DEL 5 x 5

    On propose le programme suivant en langage Python:

    Pour lancer le simulateur, appuyer sur le bouton

    Pour revenir au script, appuyer à nouveau sur

    Le programme de la carte microbit contient en général une boucle qui est répétée indéfiniment: while True à la ligne 12.

    Dans le bloc qui est répété:

    • la boucle bornée for à la ligne 12 créé une variable j, qui prend successivement les valeurs 0, 1, 2, 3 et 4. Ces valeurs correspondent aux coordonnées x des DEL à allumer.
    • à la ligne 13: la structure conditionnnelle if teste si l’élément de la liste x = j et y = 0 est égal à 1:
      • s’il est égal à 1: on allume la DEL en (x,y) = (j,0)
      • sinon, on laisse éteint

    Ce programme ne sert donc qu’à allumer les DEL de la première ligne, celle de rang 0.

    Afficher l’image entière

    Pour afficher l’image entière, il faudra aussi parcourir les lignes 1, 2, 3 et 4 de la liste.

    On pourrait adapter le script en ajoutant dans le bloc while True:

      for j in range(5):
        if L[1][j] == 1:
          display.set_pixel(j,1, 9)
      
      for j in range(5):
        if L[2][j] == 1:
          display.set_pixel(j,2, 9)
    
      for j in range(5):
        if L[3][j] == 1:
          display.set_pixel(j,3, 9)
      . . .

    à vous de jouer: compléter le script précédent, directement dans la fenêtre d’édition, afin d’afficher l’image entière.

    Amélioration du script

    Comme vous l’imaginez, il sera possible d’eviter toutes ces répétitions grâce à l’ajout d’une nouvelle boucle for. La structure devrait ressembler à ceci:

    while True:
      for j in range(5):
        for i in range(5):
          if L[j][i] ... : 
            display.set_pixel( . . . )

    Modifier le script pour utiliser une deuxième boucle for i in range(5) comme dans l’exemple donné ci-dessus.

    Utiliser la grille ci-dessous pour créer votre propre logo, avec une grille de 5 * 5 DEL. Programmer ensuite son affichage sur la carte microbit.

    grille à compléter

    grille à compléter

    localisation

    Projet de fin de chapitre: Organisation d'un rallye géolocalisé dans l'établissement.

    Sous-sections de localisation

    • culture numer Introduction a la sequence sur la geolocalisation: Lien
    • modelisation Methode d’echolocation et trilateralisation: Lien
    • modelisation Modelisation par un graphe: Lien
    • competences TP itineraire d’une croisiere: Lien
    • competences TP geoportail: Lien
    • modelisation Analyse d’une trame NMEA en langage python: Lien

    App utilisant la geolocalisation sur smartphone

    culture numer

    Sur Iphone: Réglages > Confidentialité > Services de localisation.

    On peut paramétrer les permissions pour chacune des app de son smartphone.

    Lorsque l’on choisit une app, celle-ci précise à quoi serviront les données de localisation (celles de la trame NMEA

    • Booking, Expedia: “pour trouver des hébergements et hôtels près de chez vous”
    • Facebook, Instagram: “pour aider à indiquer votre présence dans un lieu, pour être notifié des évènements locaux, pour personnaliser du contenu”
    • météo: “quand des épisodes de pluie ou de neige commencent”
    • …

    Par défaut, de nombreuses applications sont susceptibles de traquer vos données de géolocalisation, afin d’étbalir au mieux votre profil. Voir la video ci-dessous: Un espion dans ma poche?

    Envoyé special, Francetvinfo.fr

    Envoyé special, Francetvinfo.fr

    Voici un exemple de la promesse faite à l’utilisateur: l’incrustation des recommandations en réalité augmentée…

    realité augmentée. fiction ou réalité?

    realité augmentée. fiction ou réalité?

    Les cartes numériques

    Les services de cartographie numérique, comme geoportail ou openstreetmap mettent à disposition des images géoréférencées, avec plusieurs profondeur de zoom disponibles. A ces cartes sont ajoutés des repères avec des lieux d’intérêt.

    Comment gère t-on la profondeur de zoom? Pour une même zone géographique, le service stocke des tuiles: ce sont les images assemblées, géoréférencées autour du point central, proposées à certaines échelles. Seules certaines échelles sont disponibles:

    *Les pyramides des caches d’images du Géoportail pour le WMTS comportent 21 niveaux de zoom.*

    *Les pyramides des caches d’images du Géoportail pour le WMTS comportent 21 niveaux de zoom.*

    images issue de geoservices.ign.fr

    Une carte est donc constituée:

    • d’un fond de carte constitué avec des tuiles: il s’agit d’images figurant un fragments de la carte, qui, rassemblées à la façon d’un puzzle, forment le fond de carte.
    • des calques, qui ajoutent certaines informations pour enrichir la carte (altimétrie, cadastre,…). Ils ont une transparence.
    • de POI: points of interest d’un repère de coordonnées, dont la norme est Dgrés décimaux (DD).

    Les calques servent à regrouper des objets, par ordre d’empilement.

    détails sur geoservices.ign.fr

    détails sur geoservices.ign.fr

    Dans ce dernier exemple, chaque tuile est une image matricielle: elle peut être agrandie mais sans détails supplémentaires jusqu’au chargement d’une nouvelle tuile. Alors que les quadrillages sont toujours aussi nets: ce sont des images vectorielles ajoutées.

    image issue de: geoservices.ign.fr

    Voir l’activité compléte ici: Lien vers pdf

    Géoportail

    Les cartes de Géoportail Elles permettent de zoomer, et ainsi de modifier dynamiquement l’echelle, mais aussi de mesurer une surface, créer un itinéraire, … voir ici

    Openstreetmap

    Les fichiers d’itinéraires sont un autre exemple de données standardisées afin de pouvoir être échangées entre applis de cartes numériques: c’est le format .GPX

    Carte et image numérique

    Activité sur la structure des cartes numériques

    Travaux pratiques

    Calcul d’initéraire

    L’ensemble des itinéraires peut être représenté à l’aide d’un graphe pondéré. Les noeuds sont des intersections, souvent des villes, croisements, points d’interêt. Les arêtes sont les routes. Le calcul d’itinéraire se fait à l’aide d’algorithmes prenant de nombreux paramétres en compte. L’itinéraire est alors une liste de coordonnées de noeuds dans ce graphe.

    Exemple naïf:

    fonction recherche_itineraire(depart, arrivee, graphe):
      ville_courante <- depart
      itineraire.ajouter(ville_courante)
      tant que ville_courante != arrivee:
        ville_courante <- ville_voisine_plus_proche(ville_courante, graphe)
        itineraire.ajouter(ville_courante)
      retourner itineraire
    graphe

    graphe

    Questions:

    1. Quel itineraire est retourné par l’appel de la fonction avec les paramètres suivants: recherche_itineraire("Montpellier", "Lyon", graphe) ?
      Montpellier => Lyon

      Montpellier => Lyon

      2. Quel autre itineraire est retourné par l’appel de la fonction avec les paramètres suivants: recherche_itineraire("Lyon", "Montpellier", graphe) ?
      Lyon => Montpellier

      Lyon => Montpellier

      3. Cet algorithme donne t-il à coup sûr le chemin le plus court? Pourquoi?

    L’algorithme de Dijkstra

    On a vu que l’algorithme précédent n’est pas efficace pour trouver le meilleur itineraire. Celui-ci n’assure pas non plus de trouver un itinéraire, car il n’y a pas de retour en arrière possible.

    L’algorithme le plus efficace pour la recherche de l’itinéraire le plus court est l’algorithme de Dijkstra (voir ici pour une description plus formelle).

    L’idée de cet algorithme est de procéder comme pour un parcours de graphe en largeur. On tient à jour une liste de sommets adjacents, qu’il faudra visiter dans l’ordre. Pour un noeud N visité dans la liste, on ajoute les sommets adjacents à N en fin de liste. Puis on progresse dans la liste.

    Mais ici:

    • Le graphe est pondéré (les arêtes ont un poids qui correspond à la distance)
    • La liste contient pour chaque sommet visité: le noeud et sa distance cumulée au sommet de départ.
    • la liste des sommets à visiter est remise à jour, triée par ordre croissant de distance cumulée.

    Une présentation en vidéo de cet algorithme:

    video - Lelivrescolaire.fr

    video - Lelivrescolaire.fr

    Documents et liens

    • Livre Delagrave, activité 5 page 89 Cartographie numérique pour débutant: blog
    • HTTP request make your own map: geoservices.ign.fr

    Suite du cours

    principe de la geolocalisation

    • culture numer Introduction a la sequence sur la geolocalisation: Lien
    • modelisation Methode d’echolocation et trilateralisation: Lien
    • modelisation Modelisation par un graphe: Lien
    • competences TP itineraire d’une croisiere: Lien
    • competences TP geoportail: Lien

    Géolocaliser

    modelisation

    Prérequis: La lumière, transport d’une information par modulation cours de PC 2nde

    Traquer un telephone portable

    Dans la série Person Of Interest, le personnage principal, Finch, utilise une entité numérique, la machine pour effectuer une surveillance globale de la population, qu’il a lui même mise en place pour les États-Unis. La série soulève de nombreuses questions quant au respect de la vie privée.

    voir extrait du film S2E3 13'

    voir extrait du film S2E3 13'

    Questions:

    • Cet extrait, vous parait-il réaliste?
    • Dans ce passage du film, quel dispositif détermine la position de Sophia? (le film evoque une antenne, mais c’est plus probablement le mobile de Sophia)
    • Quel dispositif partage cette position?

    Mesurer le temps pour determiner une distance

    Les systèmes américains GPS et européens Galiléo permettent la géolocalisation par satellite d’un recepteur.

    La géolocalisation est le calcul de la position sur Terre.

    Le récepteur va recevoir en continu 2 types d’informations de la part de chacun des satellites:

    • la position du satellite
    • l’heure d’envoi du signal depuis le satellite t0

    Le recepteur va utiliser ces informations pour réaliser un calcul de positionnement. D’abord en calculant sa distance au satellite: Il utilise les temps t0 d’emission du signal et t1, celui de reception:

    Le signal se deplaçant à la vitesse de la lumière, c = 300 000 km/s.

    Cette durée, t1 - t0 est calculée à partir des temps t1 et t0, mesurés par deux horloges différentes, et qu’il faudra synchroniser au mieux.

    Exercice: Calculer la distance satellite-recepteur si le temps de transit t1-t0 est egal à 70ms.

    L’horloge du récepteur nécessite d’être régulièrement synchronisée avec celle des satellites émetteurs. C’est grâce à un algorithme calculant sur les écarts de positionnement, que l’horloge du récepteur se met à l’heure des émetteurs. Cela nécessite de capter les signaux d’au moins 4 satellites GPS.

    Principe de la trilatération

    1964 : Le premier système de positionnement par satellites est développé par les États-Unis, à usage uniquement militaire

    1995 : ouverture mondiale au reseau GPS, le Global Positioning System

    GNSS est l’appellation du groupement de systèmes de positionnements par satellites qui envoie des données de localisation et d’horaire depuis leur orbite. Le système GNSS comprend le célèbre système de positionnement GPS (Global Positioning System), le système de positionnement russe GLONASS, le système de positionnement chinois BeiDou mais aussi le nouveau système de positionnement européen Galileo.

    En équipant chaque satellite d’un émetteur radio, il est possible de réceptionner les signaux provenant d’appareils reconnus et d’estimer les délais de synchronisation.

    Orbites de la constellation de satellites du système GPS - wikipedia

    Orbites de la constellation de satellites du système GPS - wikipedia

    image issue de la page GNNS-wikipedia

    Pour déterminer la position précise du recepteur sur Terre, il faut utiliser le resultat du calcul de la distance à 4 satellites, et déterminer le point d’intersection de 4 sphères (video explicative).

    KEZAKO: Comment fonctionne un GPS?

    KEZAKO: Comment fonctionne un GPS?

    Pour optimiser le système, les satellites de navigation circulent sur une orbite moyenne à une altitude d’environ 20000 kilomètres. Compte tenu de cette donnée et de la nécessité que le récepteur puisse en permanence avoir quatre satellites visibles au-dessus de l’horizon, un système de navigation (GPS, Galileo, Beidou, Glonass) doit comporter environ 25 satellites de navigation opérationnels pour fournir une position, quelle que soit la position de l’utilisateur à la surface de la Terre. GNNS-wikipedia

    Observer les orbites de différents systèmes de satellites sur l’animation suivante: wikipedia

    Coordonnées terrestres

    La géolocalisation est un procédé qui permet de repérer une personne, un objet, un lieu sur une carte (le plus souvent numérique) à l’aide de ses coordonnées géographiques qui sont :

    • Sa latitude (en degrés)
    • Sa longitude (en degrés)
    • Son altitude par rapport au niveau moyen de la mer (en mètres)

    Le format numérique de la longitude est différent de celui de la latitude avec un chiffre significatif supplémentaire. Ceci s’explique par la valeur de l’angle qui ne dépasse pas 90° pour une latitude et qui peut atteindre 180° pour une longitude.

    Les coordonnées géographiques sont traditionnellement exprimées dans le système sexagésimal, parfois noté DMS : degrés minutes secondes. De nos jours, les notations équivalentes en degrés minutes décimales (DM) ou degrés décimaux (DD) sont également utilisées :

    • DMS : Degré : Minute : Seconde (49°30’00”) ;
    • DM : Degré : Minute (49°30,0’) ;
    • DD : Degré décimal (49,5000°), généralement avec quatre décimales
    norme exemple
    Degrés DD 48.225833
    Degrés, minutes DM 48°13,54998'
    Degrés, minutes, secondes 48°13'32.9988''
    Video sur les conversions DD<->DMS

    Video sur les conversions DD<->DMS

    Trame NMEA

    Protocole NMEA 0183 : (National Marine Electronics Association): protocole utilisé par les récepteurs GPS pour fournir la localisation sous une forme de trame normalisée facilement décodable. Ces données sont mises dans un format standard :

    Sur cette trame:

    • Quel est le caractère de début de la trame?
    • Quel est le séparateur entre les données?
    • Que signifient les lettres N, E, M?
    • Comment convertit-on 4836.5375 en 48°36’32.25’’? Aide: il s’agit d’une conversion DD vers DMS.

    Positionner

    Voici une trame affichée sur votre smartphone (utilisation de l’appli nmeaGPS):

    $GPGGA,093642.126,4342.1254,N,00103.2814,O,1,04,3.2,200.2,M,,,,0000*0E$

    • Déterminer l’heure de réception de la trame. On précisera les heures, les minutes et les secondes.
    • Déterminer les coordonnées géographiques envoyées par la trame NMEA (DM)
    • Convertir ces données en format DD.
    • Positionner le point sur la carte

    Liens

    Suite du cours

    graphes

    • culture numer Introduction a la sequence sur la geolocalisation: Lien
    • modelisation Methode d’echolocation et trilateralisation: Lien
    • modelisation Modelisation par un graphe: Lien
    • competences TP itineraire d’une croisiere: Lien
    • competences TP geoportail: Lien

    Les graphes et internet

    modelisation

    Les graphes sont utilisés en mathématiques appliquées pour simplifier la compréhension de tous types de réseaux.

    Ce sont des représentations visuelles permettant de relier des objets entre eux.

    Cette théorie regroupe un ensemble de théorèmes et d’algorithmes visant à résoudre divers problèmes liés aux réseaux.

    Relier des noeuds avec des arêtes

    Soit un reseau constitué de 6 machines, que l’on symbolisera par 6 ronds A, B ,C ,D, E et F.

    sommets

    sommets d'un graphe

    Sur une feuille, relier ses sommets ( pour que le graphe soit “connexe”). Imaginez plusieurs types de figures.

    Selon le reseau dessiné entre ces machines, plusieurs scénarios peuvent être envisagés. Il peut y avoir une coupure de l’une des liaisons, ce qui risque d’isoler une partie du reseau, et entrainer des problèmes de fiabilité.

    On peut aussi considérer le coût que représente le cablage des machines, qui augmente avec le nombre d’arêtes et leur longueur…

    Questions:

    1. Quels sont les avantages et inconvénients de chacun des graphes constuits sur le cahier (complets, en étoile, circulaires en particulier) en termes de fiabilité du reseau, et de coût?

    2. Quel graphe montre la connexion la plus solide entre ces différentes machines?

    3. Avec un graphe complet ( tous les sommets reliés à toutes les arêtes):

    • exprimer le nombre d’arêtes en fonction du nombre de sommets
    • calculer ainsi le nombre d’arêtes d’un graphe complet de 10, puis 20 sommets à l’aide d’un tableau .
    • calculer le nombre de connections qu’il faudrait pour relier directement chacun des 3 milliards d’internautes(chiffrede2015) )

    Definitions et remarques:

    • Un graphe est un ensemble d’arêtes et de sommets. Ces sommets peuvent constituer des noeuds s’ils sont reliés à d’autres sommets par une arête.
    • Deux sommets sont voisins s’ils sont reliés par une arête.
    • Le degré d’un sommet dans un graphe est son nombre de voisins.
    • Un graphe est dit connexe s’il est en un seul morceau.
    • Un graphe complet est un graphe simple dont tous les sommets sont adjacents deux à deux.
    • Un chemin entre 2 sommets d’un graphe est le parcours qui relie ces 2 sommets. On peut présenter le parcours en énonçant les sommets traversés, ou bien les arêtes empruntées.
    • La longueur du chemin est égale au nombre d’arêtes empruntées.
    • il est illusoire d’imaginer que toutes les machines sur internet sont reliées 2 à 2 selon un graphe complet.
    • Les données echangées doivent donc transiter selon un chemin avec de nombreux sauts, de routeur en routeur.

    Enoncé du premier problème sur les graphes

    Le problème des sept ponts de Königsberg est connu pour être à l’origine de la topologie et de la théorie des graphes. Résolu par Leonhard Euler en 1735, ce problème mathématique se présente de la façon suivante :

    il y a une île appelée le Kneiphof, entourée d’un fleuve qui se partage en 2 bras. Les bras de ce fleuve sont garnis de 7 ponts

    les ponts de Konigsberg

    les ponts de Konigsberg

    Le problème consiste à déterminer s’il existe ou non une promenade dans les rues de Königsberg permettant, à partir d’un point de départ au choix, de passer une et une seule fois par chaque pont, et de revenir à son point de départ.

    Il est possible de vérifier, de manière intuitive, que la promenade demandée n’existe pas. Ce sont au moins deux ponts, bien choisis, qu’il faudrait ajouter ou retirer pour permettre la promenade avec retour initialement cherchée.

    Questions:

    • Que modélisent les noeuds du graphe?
    • Que modélisent les arêtes du graphe?
    • Vérifier que cette promenade n’existe pas.
    • Modifier le plan des ponts (avec un nombre minimum de ponts ajoutés) pour rendre cette balade possible.
    • Que remarque t-on alors sur la parité du nombre d’arêtes pour chacun des noeuds?

    Modélisation

    Euler propose une modélisation qui consiste à désigner chacune des berges par une lettre majuscule, les ponts par une lettre minuscule et à étudier l’existence de listes d’une taille donnée de lettres majuscules. Par exemple, sur la figure précédente, la liste CABD peut correspondre à un parcours de la berge C à la berge A par le pont e, puis de A vers B par le pont a, puis de B vers D par f.

    L’impossibilité de passer deux fois par le même pont se traduit par l’impossibilité qu’une liste comporte plus de fois la séquence XY ou Y X qu’il n’existe de ponts entre les berges X et Y.

    Pour Euler, une solution est une liste comportant exactement une lettre de plus qu’il n’y a de ponts, et répondant aux contraintes précédentes.

    Testez le vous-même:

    • Repérer les berges par des noms de sommet (A, B, C, D). Et représenter les parcours possibles comme une liste de sommets atteints, en n’empruntant qu’une seule fois chaque pont.
    • Constater alors que la liste-solution n’existe pas.

    Euler propose ensuite une règle pour répondre au problème général de promenades sur des ponts :

    Un parcours eulérien est possible si, et seulement si, deux régions au plus ont un nombre impair de ponts y conduisant. Si deux régions ont un nombre impair de ponts y conduisant, le parcours commencera par l’une de ces deux régions.

    Utilité des graphes

    Implémentation

    Les algorithmes développés par les mathématiciens discrets se prêtent bien à l’implémentation informatique, dans la mesure où le graphe est un objet discret aisément représentable de façon matricielle ou par listes chaînées par exemple:

    • Les réseaux routiers : les villes sont alors considérées comme des sommets, et les routes comme des arêtes ou des arcs.
    • Le web : les pages sont considérées comme les sommets, et les liens hypertextes sont les arêtes.
    • Les réseaux sociaux : les individus sont les sommets, et leurs connexions sont les arêtes.
    • Les bases de données, dans le modèle entité-relation, peuvent être représentées par un graphe orienté.

    Résolution de problèmes

    La théorie des graphes a donné naissance à une multitude de théorèmes et d’algorithmes. Chacun d’entre eux a pour objectif de résoudre un problème pratique.

    Théorème pour la résolution du problème d’Euler: un graphe connexe admet un parcours eulérien si et seulement si ses sommets sont tous de degré pair sauf éventuellement deux d’entre eux.

    Si le graphe modélise un réseau urbain (les sommets représentant les sites et les arêtes les liens de communication): par exemple, un plan de métro:

    • quel est le nombre minimal de changements entre deux stations données ?
    • quelles sont les stations que l’on peut rejoindre à partir d’une station donnée, avec un changement au plus ?

    La recherche en mathématiques

    La théorie des graphes a connu un essor important et a permis de modéliser de nombreux problèmes:

    • Le problème hamiltonien, qui peut paraître proche du problème eulérien. Il s’énonce ainsi : Existe-t-il un chemin ou un circuit passant par tous les sommets d’un graphe une et une seule fois ? Ce problème n’a pas de solution générale aujourd’hui.
    • Le théorème des 4 couleurs : Énoncé en 1852 par Francis Guthrie, ce problème a été résolu à la fin du vingtième siècle. Dans sa première forme, il s’énonçait ainsi : peut- on colorier avec quatre couleurs une carte géographique de telle façon que deux régions limitrophes aient une couleur différente? Voir resolution ici: villemin.gerard.free.fr

    Quels problèmes peuvent resoudre les graphes pour Internet

    La modélisation en graphe du reseau internet peut répondre aux questions:

    • tous les noeuds du graphe sont-ils accessibles? deux sites donnés peuvent-ils communiquer ?
    • Quels sont les chemins possibles pour relier 2 noeuds A et B?
    • Si l’un des chemins est rompu, existe t-il un autre chemin?
    • Quel est le plus court chemin pour relier 2 noeuds A et B?

    Toutes ces questions peuvent être résolues grâce à un algorithme de parcours de ce graphe, dont un exemple sur cette page, avec le parcours en largeur.

    fonction de conversion TI83

    Aller sur la page Vittascience.com mode Texas Instruments

    Situation - problème

    La randonnée du Col des Fourches jusqu’au fort de Pelousette est décrite ici. Il s’agit d’un itinéraire dans les alpes du Sud, près du col de la Bonette.

    Le but de la séance est de placer des marqueurs sur la carte IGN, afin de matérialiser l’itinéraire, comme sur l’image suivante:

    PROGRAMME 1 : conversion DM => DD

    DM et DD sont des formats de repères d’angles:

    • DM: signifie Degrès Minutes
    • DD: signifie Degrès Décimal

    Sur l’interface Scratch de Vittascience:

    … puis:

    Choisir le bloc demander à l’utilisateur “Entrer un nombre“

    Le programme devrait ressembler à ceci :
    Entre les guillemets : modifier le texte : Entrer les degres :
    Compléter le programme pour qu’il demande aussi les minutes et qu’il stocke la valeur dans la nouvelle variable minutes :

    Opération math

    Enfin, vous allez créer une nouvelle variable DD. Et lui affecter le résultat de l’opération degres + minutes / 60 :

    Menu Math : choisir le premier bloc (opération +) :

    Modifier et combiner 2 blocs comme celui-ci pour écrire l’opération degres + minutes / 60

    Afficher le résultat

    Il ne reste plus qu’à afficher le résultat avec la fonction écrire dans la console du menu E/S.

    Le script complet est donné ci-dessous :

    Il ne vous reste plus qu’à télécharger

    Utiliser le programme TI-CONNECT pour le transfert de fichier.

    Transfert sur calculatrice TI83

    Brancher la caclulatrice. Dans le logiciel TI-CONNECT, appuyer sur le bouton de transfert ordinateur => calculatrice

    IDE Python

    Avec le bouton prgm de la calculatrice, choisir 2: Python App

    Choisir le programme PYTHON01 avec le curseur.

    Les boutons du menu en bas de l’ecran sont accessibles avec chacune des touches situées au dessous.

    Par exemple, touche fx pour Exécuter.

    Utiliser alors le programme depuis la fenêtre du shell:


    Utilisez alors votre programme pour définir les coordonnées DD du départ de la randonnée:


    latitude longitude
    Départ 44°20,01612' 6°52,1109'

    Remarque: il vous faudra executer une 2e fois le programme pour le calcul de la longitude. Aller dans le menu Script puis executer à nouveau le programme.

    PROGRAMME 2: Créer une fonction conversion

    Une meilleure approche du langage python consiste à créer une fonction, puis appeler celle-ci depuis le Shell pour afficher le résultat.

    Aller sur Editer

    Le script est alors le suivant:

    degres = float(input('Entrer les degres :'))
    minutes = float(input('Entrer les minutes :'))
    DD = degres + minutes / 60
    print("L'angle en notation DD est :")
    print(str(DD))

    script affiché dans l'éditeur de la TI83

    script affiché dans l'éditeur de la TI83

    Aller sur la première ligne et insérer la définition de la fonction:

    • Menu Fns…: onglet Fonc: choisir 1: def fonction()
    • ajouter le nom de la fonction en passant en clavier alphanumérique (bouton 2nde puis alpha): def conversion():
    • ajouter des paramètres entre les parenthèses, que vous nommerez degres et minutes
    • adaptez alors le script: supprimez toutes les lignes sauf celle du calcul de DD, rectifier les indentations dans le bloc de la fonction.
    • ajouter l’instruction return DD à partir du menu Fns…: onglet Fonc: choisir 2: Return
    • Exécuter le programme

    Le Shell python

    Dans la fenêtre du Shell, il ne se passe rien. C’est normal, vous allez appeler la fonction avec des arguments placés:

    • avec le bouton var: choisir conversion (OK)
    • le Shell affiche le nom de la fonction.
    • Il faut completer avec les arguments

    Voilà, vous pourrez utiliser maintenant la fonction conversion pour transformer n’importe quelle valeur du format DM vers le format DD.

    Voici celles du départ et de l’arrivée de la randonnée:

    latitude longitude
    Départ 44°20,01612' 6°52,1109'
    Arrivée 44°20,04108' 6°51,91188'

    Positionner des marqueurs sur une carte

    Vous allez placer 2 marqueurs sur une carte, correspondant au départ et à l’arrivée de la randonnée.

    Rendez vous sur le portail Geoportail

    • Dans le menu outil, choisir Annoter la carte:
    • Dans les outils de creation, choisir le marqueur: Placer des points.
    • Renseigner alors les coordonnées dans la barre de recherche à partir des résultats calculés en format DD (voir plus haut)
    • Il vous reste alors à cliquer sur le cercle-cible pour placer les 2 points départ et arrivée sur la carte.
    • On pourra placer d’autres points de l’itinéraire avec la même méthode…
    latitude longitude
    étape 1 20,43636' 6°51,54288'
    étape 2 44°20,49468' 6°51,99768'
    étape 3 44°20,10228' 6°52,15908'
    étape 4 44°19,81248' 6°52,28124'
    étape 5 44°19,83708' 6°52,27248'

    fonction de conversion android

    Situation - problème

    La randonnée du Col des Fourches jusqu’au fort de Pelousette est décrite ici. Il s’agit d’un itinéraire dans les alpes du Sud, près du col de la Bonette.

    Le but de la séance est de placer des marqueurs sur la carte IGN, afin de matérialiser l’itinéraire, comme sur l’image suivante:

    PROGRAMME 1 : conversion DM => DD

    DM et DD sont des formats de repères d’angles:

    • DM: signifie Degrès Minutes
    • DD: signifie Degrès Décimal

    L’editeur de programme

    Pour créer un nouveau programme: Menu Fichier: New

    • Saisir alors le script python:
    degres = float(input('Entrer les degres :'))
    minutes = float(input('Entrer les minutes :'))
    DD = degres + minutes / 60
    print("l'angle en notation DD est :")
    print(DD)
    • Sauvegarder le programme:
      • Menu Fichier: Save as
    • Internal storage
    • Créer un nouveau dossier appelé python: New Folder puis saisir python
    • Nommer le fichier: localisation.py
    • Executer alors le programme avec le bouton jaune en bas de l’écran
    • Renseigner les valeurs de degrés et minutes pour convertir en DD:


    Utilisez alors votre programme pour définir les coordonnées DD du départ de la randonnée:


    latitude longitude
    Départ 44°20,01612' 6°52,1109'

    Remarque: il vous faudra executer une 2e fois le programme pour le calcul de la longitude

    Programme 2 : Créer une fonction conversion

    Une meilleure approche du langage python consiste à créer une fonction, puis appeler celle-ci depuis le Shell pour afficher le résultat.

    Modifier le programme pour créer une fonction conversion

    Revenir dans l’editeur et modifier le programme pour créer une fonction:

    La fonction conversion a alors 2 paramètres, degres et minutes qui devront être renseignés lors de l’appel de la fonction. Cela se fera depuis le Shell python.

    Le Terminal

    • Depuis le menu principal, à gauche, choisir Terminal
    • Utiliser alors les instructions UNIX:
    $ ls
    $ cd python
    $ python

    explications…

    instruction UNIX commentaire
    ls affiche le contenu du dossier courant
    cd python changer de dossier et aller dans le dossier python
    python lancer le shell python

    Le Shell python

    Les instructions python seront alors saisies après les chevrons >>> Chaque ligne saisie sera alors exécutée.

    Saisir:

    >>> from localisation import *
    >>> conversion(40,23)

    Voilà, vous pourrez utiliser maintenant la fonction conversion pour transformer n’importe quelle valeur du format DM vers le format DD.

    Voici celles du départ et de l’arrivée de la randonnée:

    latitude longitude
    Départ 44°20,01612' 6°52,1109'
    Arrivée 44°20,04108' 6°51,91188'

    Positionner des marqueurs sur une carte

    Vous allez placer 2 marqueurs sur une carte, correspondant au départ et à l’arrivée de la randonnée.

    Rendez vous sur le portail Geoportail

    • Dans le menu outil, choisir Annoter la carte:
    • Dans les outils de creation, choisir le marqueur: Placer des points.
    • Renseigner alors les coordonnées dans la barre de recherche à partir des résultats calculés en format DD (voir plus haut)
    • Il vous reste alors à cliquer sur le cercle-cible pour placer les 2 points départ et arrivée sur la carte.
    • On pourra placer d’autres points de l’itinéraire avec la même méthode…
    latitude longitude
    étape 1 20,43636' 6°51,54288'
    étape 2 44°20,49468' 6°51,99768'
    étape 3 44°20,10228' 6°52,15908'
    étape 4 44°19,81248' 6°52,28124'
    étape 5 44°19,83708' 6°52,27248'

    competences numeriques

    • recherche RGPD recherche documentaire, travail collaboratif, framapad histoire informatique et reseaux recherche documentaire, LibreOffice Writer Mettre en forme RGPD suite du travail de recherche documentaire sur le RGPD, mise en forme avec Writer guide style mise en forme d’un document, guide de style, libreOffice, structure Utiliser Writer traitement de texte, logiciel libre, contenu, structure et styles, proprietes des elements Writer et Word elements, proprietes, styles, similitudes dans l’utilisation des logiciels de traitement de texte moteurs de recherche experimenter avec un moteur de recherche
    • classif vivant balises HTML, structurer le document Les plastiques balises HTML, structurer le document La démocratie athenienne balises HTML, structurer le document La bataille de Marignan langages web, html css, structure et mise en forme du document web mon film prefere v1 appliquer ses connaissances pour construire une page web de zero, version SNT mon film prefere v2 appliquer ses connaissances pour construire une page web de zero, version NSI_1 questionnaire creer un questionnaire en ligne à destination des parents d’eleves dans une ecole elementaire. Framasoft
    • tableau de notes tableau de notes, formule de calcul, etendre une selection nobels selectionner, ordonner, somme avec condition analyse graphique importer un fichier de reponses en format csv, analyse et representations graphiques
    • detourer une image tuto Gimp, edition et modification d’image numerique
    • somme et moyenne sur Excel Tableur Excel Construire une formule de calcul de moyenne Fonction somme Pour programmer la fonction SOMME sur les valeurs d’une colonne du tableau Voici un lien vers le tuto de microsoft office. cliquer dans la cellule juste sous la dernière valeur de la colonne. Ecrire debut de la formule (bien commencer la ligne par le signe =): = SOMME( puis faire une sélection étendue de toutes les valeurs de la colonne. (voir image ci-dessous) Valider avec la touche Entrer Compter le nombre de cellules Pour compter le nombre de valeurs dans le tableau, utiliser la fonction NOMBRE tracé d’un histogramme Tracé d’un histogramme avec Excel Un histogramme donne une représentation d’un tableau avec des effectifs, de manière très visuelle. Cela facilité grandement l’interprétation. Dans une feuille du tableur Excel: Placer dans une première ligne les etiquettes des colonnes (par exemple, renseigner le nom des matières) Placer juste au dessous les effectifs correspondant (par exemple, la matière préférée) Selectionner ensuite l’emplacement des données (ne pas prendre la première colonne, qui constitue le titre). recherche de correlations Recherche de corrélations Principe La recherche de correlations entre valeur d’un tableau consiste à identifier des colonnes qui semblent être interdépendantes. On doit commencer par rassembler les données dans une même table, où les réponses d’une même personne sont rassemblées dans une même ligne. matchs OM Nice stats sur l’ensemble des matchs Nice Marseille en Ligue 1, Excel data.gouv maires de France data.gouv Le site data.gouv.fr est la plateforme des données publiques françaises. Nous allons consulter les données du Répertoire National des Élus (RNE). Celui-ci a pour finalité le suivi des titulaires d’un mandat électoral. Il est renseigné et tenu à jour par les préfectures et les services du ministère de l’intérieur. Rendez vous à la page de consultation du RNE. tableur sur calcu TI83 Utilisation de la base de données Ouvrir la base de données Aller sur la page Exoplanet.eu Pour consulter la base de données de toutes les planetes observées, cliquer sur Tous les catalogues. accès à la base de données
    • Notebook: variables en python: Lien vers Capytale, ou telechargement Notebook: fonctions en python: Lien vers Capytale, ou bien, si l’ENT ne fonctionne pas: telechargement, et version pdf utiliser des fonctions pour calculer sans peine les caracteristiques des planetes du systeme solaire: Notebook et fiche reponse: pdf de scratch à python programmer une fonction python avec des blocs scratch puis recopier le programme python généré

    Sous-sections de competences numeriques

    rediger

    Sous-sections de rediger

    recherche RGPD

    TP - Travail collaboratif sur la protection des données

    Document reponse:

    Le framapad est un document avec editeur en ligne de la societé de logiciels libre Framasoft.

    • Commencer par entrer votre prénom pour vous identifier lors de votre travail d’edition.
    • Rédiger votre réponse: pour une seule ou plusieurs des questions posées. Préciser le numero de la question.
    • Une fois tous les changements terminés, marquez votre version avec une étoile pour la sauvegarder en ligne et la retrouver dans l’historique.
    • Enregistrer le document au format .text dans vos documents. Vous pourrez l’éditer de façon plus complète dans LibreOffice Writer dans une prochaine séance.

    Recherche Documentaire: Questions

    1. Quelles données relèvent de l’identité numérique, l’identité administrative, ou de l’indirectement nominatif?
    2. Qu’est ce que le RGPD
    3. Qu’est ce que la CNIL?
    4. Qui a pour devoir de se mettre en conformité vis à vis du RGPD?
    5. Une entreprise, pour être en conformité avec le traitement de données de ses clients, doit-elle adresser une demande auprès de la CNIL? Que doit-elle faire?
    6. Le RGPD interdit-il l’utilisation à des fins commerciales des données?
    7. Quelle est la différence entre une donnée, et une information sur une personne?
    8. A partir de quelles données personnelles peut-on trouver des renseignements sur la santé et l’hygiène de vie d’une personne? Peut-on l’utiliser pour prendre des décisions sur son embauche, ou bien pour calculer le prix de sa cotisation mutuelle santé?
    9. Un restaurant qui livre des pizzas: quelles données va-t-il avoir besoin de collecter sur ses clients? Ces données peuvent-elles être considérées comme sensibles? Si la base de données du restaurant est piratée, celui-ci est-il responsable au regard de la loi?
    10. Que pensez-vous d’une entreprise qui utilise les données biométriques de ses employés pour contrôler leur identité et accès à leur poste de travail le matin (voir le film de science fiction Bienvenue à Gattaca)
    11. Lorsque je surfe sur le web, à la recherche d’un article à acheter: Le prix de l’article proposé par les commerçants va-t-il evoluer au fur et à mesure de mes activités sur le web? Y-a-t-il des traces de ma navigation? Qu’est-ce qu’un tracker?
    12. Suis-je en droit de demander à l’entreprise Google qu’elle me fournisse toutes mes traces numériques qui me concernent? Quelles seront ces traces numériques?

    Données à caractère personnel

    Parmi les données suivantes, certaines peuvent être classées comme relevant de:

    • l’identité numérique
    • identité administrative
    • indirectement nominative (qui donne l’identite de la personne, une fois effectué un recoupement d’informations)

    Ce sont:

    • Le nom, le prenom, l’adresse
    • un pseudo, un mot de passe
    • une adresse IP
    • des lieux visités et géolocalisés
    • un panier d’achat
    • des clés de recherche su internet
    • numero de carte bancaire
    • numero NIR (securité sociale)
    • données associées à son compte de reseau social (publications, like)
    • Données exposée par d’autres mais nous identifiant dans un reseau social
    • ordonance médicale, clichés radiographiques, …
    • L’enregistrement de la voix de clients ou salariés par un dispositif informatique
    • images de personnes physiques captées par un système de vidéosurveillance
    • le patrimoine d’un propriétaire
    • …

    Même des données supposées anonymes peuvent nous identifier car il existe souvent une clé de correspondance qui peut nous identifier.

    Traitement des données

    Definition

    il s’agit de toute opération effectuée de manière automatisée appliqué à des données à caractère personnel.

    Enjeux pour l’usager

    Aujourd’hui, l’aspiration des individus, en termes de protection de leur vie privée est de pouvoir utiliser les services technologiques d’internet, de s’exposer personnellement (reseaux sociaux), tout en cédant une partie acceptable de leurs données personnelles. Cette part cédée doit rester raisonnable et être négociée par contrat avec les opérateurs économiques.

    Le RGPD (Réglement Général pour la Protection de Données)

    Définition

    C’est un document qui donne un cadre légal à l’utilisation des données dans l’UE et contraint les organismes publics ou privés à certaines obligations.

    Ce texte vise à définir des équilibres: protection des individus d’une part, utilisation des données à des fins commerciales ou pour des missions d’intérêt public, d’autre part.

    Le RGPD n’interdit PAS l’utilisation commerciale des données.

    Mais il fournit un cadre, auquel les entreprises privées, comme les administrations publiques doivent se conformer.

    Obligations de conformité vis à vis du RGPD

    Pour les entreprises et administrations, susceptible de TRAITER des données à caractère personnel:

    • devoir de tenir un registre des activités de traitement (finalités, délai de conservation et de suppression automatique, réalisation d’atude d’impact…)
    • obligation d’assurer une collecte lisible et transparente des données
    • protéger les données. Assure leur sécurité et leur confidentialité
    • définir un paramètre: Rester minimal dans la quantité de données et le type de données collectées
    • interdiction de collecter certaines catégories particulières de données (origines raciale ou ethnique, opinions politiques, convictions religieuses, appartenance syndicale)
    • interdiction de collecter le numero NIR (securité sociale) car celui-ci contient un certain nombre de caractéristiques qui aident au chainage des données
    • interdiction de collecter des données génétiques, biométriques, concerant la santé, la vie et l’orientation sexuelle.

    Droit des personnes vis à vis du RGPD

    Tout individu doit:

    • pouvoir être questionné pour demander son consentement préalable à la collecte et l’utilisation de ses données.
    • être informé sur la finalité du traitement qui sera effectué
    • dans le cas d’une collecte indirecte: être informé de la source de cette collecte, et droit de recours auprès de la CNIL
    • avoir droit d’accès, de rectification et de portabilité des données (c’est à dire, droit à obtenir ses données collectées dans un format structuré, lisible)
    • avoir droit d’effacement
    • avoir droit d’opposition au traitement des données à visée commerciale et de profilage
    • avoir des droits concernant les cookies, exploitant ses traces de navigation. Côté client, ces cookies sont stokées dans le navigateur web. L’individu doit donner son consentement sur leur utilisation, à partir d’une information claire et complète
    • avoir droit au deferencement: demander la suppression de liens vers des informations portant atteinte à la vie privée.

    Remarques:

    • Il existe également un tracking côté serveur. Le client n’est alors pas en mesure d’effacer ses traces numériques, qui sont partagées le plus souvent avec des entreprises tierces (revente des données). Dans la chaine de partage des données, tout le monde est alors responsable du traitement qui sera effectué sur ces données.
    • De nombreux exemples montrent des manquements à ces règles sur la protection des données et leurs conséquences: L’affaire Facebook pendant l’élection américaine, qui a vu gagner le président Trump en est un tristement célèbre, même si cela ne concernait pas le territoire d’influence de la CNIL et de son équivalent européen. Au niveau fançais: les affaires Foncia, Acadomia…

    La CNIL

    Definition

    Commission Nationale pour l’informatique et les libertés. La CNIL est la premiere autorité administrative instaurée en France (1978) à la faveur de l’adoption de la loi “informatique et libertés”.

    Les actions de la CNIL

    La CNIL exerce un pouvoir de contrôle et de sanctions pour la protection des données. Elle est indépendante et ne reçoit d’instruction d’aucune autorité publique.

    Tout citoyen peut s’adresser à la CNIL pour la saisir d’une plainte.

    La CNIL réalise des

    • controles d’audit, qui sont programmés, sur des organismes privés comme publics.
    • contrôles de contentieux à partir de plaintes, de dénonciations anonyme ou de tout autre moyen qui lui aurait permi de prendre connaissance d’un manquement au RGPD

    Sanctions prises

    Lors d’un manquement avéré, la CNIL peut:

    • faire suspendre les flux de données adressés à un destinataire
    • prendre des sanctions pécunières
    • prendre des sanctions d’image: publication sur le site de la CNIL et dans le Journal Officiel. Les répercussions peuvent être importantes (risque réputationnel)

    Liens

    • cours de Seconde SNT sur la protection des données, illustré de quelques videos et autres liens
    • Ouvrage: La protection des données personnelles, le RGPD et la nouvelle loi française, Guillaume Desgens-Pasanau, ed. LexisNexis

    histoire informatique et reseaux

    Partie 1: Histoire de l’informatique et des reseaux

    Dans ce TP nous allons créer une petite chronologie de l’informatique à l’aide du traitement de textes LibreOffice Writer.

    En utilisant l’article Wikipédia sur la chronologie de l’informatique, ainsi que la page sur l’architecture des ordinateurs site allophysique:

    créer un document texte qui rassemble 3 à 6 dates par période de l’histoire de l’informatique et d’internet. Faites un choix pertinent pour chacune des dates et descriptions. Choisir ce qui selon vous, résume le mieux chaque période.

    Consignes

    • Le document ne doit pas excéder DEUX pages A4.

    • Vous utiliserez des styles pour le mettre en forme:

      • Titre principal pour le titre du document: «Chronologie de l’informatique»
      • Titre 1 pour chacune des phases de l’histoire de l’informatique:
        • «L’époque des pionniers»
        • «Les débuts de la micro-informatique»
        • «L’ère d’Internet et du World Wide Web»
        • «L’ère de la mobilité et des données partagées»
      • Les dates et leur description sont écrites sous forme d’une liste non-ordonnée avec le Style de paragraphe par défaut.
      • Sauvegarder votre fichier sous le titre histoire_informatique_reseaux dans le dossier Documents/Devoirs/tixidor/

    Remarque: Vous pouvez coller du texte issu d’une page en supprimant sa mise en forme grâce au collage spécial <CTRL+MAJ+V>(ou bien clic droit: coller sans Formatage)

    Il est nécessaire de séparer l’écriture du contenu du document (Partie 1) de celui de sa mise en forme (Partie 2).

    Partie 2: mise en forme du document

    Pour être lisible, un texte doit comporter une certaine hiérarchie.

    Définir les éléments, structurer le document

    Utiliser des niveaux de titres pour structurer votre document (Titre1, Titre2, Titre3…).

    Le document initial

    Le document initial

    • Choisir Titre 1 pour le titre principal
    • Choisir Titre 2 pour chacune des phases de l’histoire de l’informatique: Les prémices de l’informatique, …
    • Choisir le Style Titre 3 pour les dates relatives aux machines et leurs systèmes d’exploitation.
    Le document devrait maintenant ressembler à ceci

    Le document devrait maintenant ressembler à ceci

    • Créer ensuite DEUX nouveaux Styles enfants de Titre 3, comme sur l’image ci-dessous.
      • L’un des ces nouveaux Style servira à mettre en relief les Algorithmes
      • L’autre pour les reseaux et les programmes relatifs à ces reseaux.

    Seule la propriété couleurs des Styles enfants diffèrent de Titre 3. Les autres propriétés sont héritées.

    • Ajouter une numérotation aux chapitres (phases de l’histoire)

    Créer un épigraphe pour chaque phase de l’histoire

    L’épigraphe est une courte citation placée au début d’un ouvrage ou d’un chapitre, et qui permet d’en indiquer l’esprit, de résumer son contenu.

    Personnaliser le style

    Vous allez personnaliser les Styles utilisés dans votre document. Vous modifierez les propriétés des différents éléments. Un exemple de document stylisé est donné ci-dessous:

    personnalisation des propriétés couleur, alignement, police, ...

    personnalisation des propriétés couleur, alignement, police, ...

    Styliser le document de manière personnelle

    Voici un modèle utilisé pour un mémoire (document long), pour sciences politiques Lille:

    Exemple de document - rediger un mémoire - sciencespo-lille.eu

    Exemple de document - rediger un mémoire - sciencespo-lille.eu

    Les manières de mettre en forme un document sont très variés, les choix de design sont personnels. Dans tous les cas, il sera nécessaire de modifier les propriétés des Styles en modifiant leurs valeurs.

    Utiliser les tutoriels ci-dessous.

    Modifier le style d’un élément ou en créer un nouveau

    Méthode 1:

    Depuis la fenêtre des Styles (à droite), sélectionner l’un des élements, comme par exemple Style de paragraphe par défaut. Choisir dans le menu: Nouveau ou Modifier

    • Nouveau: cela créé un nouvel objet fils de celui sélectionné, qui s’ajoute à la liste des Styles

    • Modifier: cela ouvre la fenêtre de modification du Style, que l’on peut aussi atteindre depuis la barre de menu du haut (Styles > choisir Editer le Style). La nouvelle fenêtre contient alors toutes les propriétés modifiables pour ce Style, classées par onglet.

    Méthode 2:

    Sélectionner dans la page l’un des éléments dont vous souhaitez modifier le style. Modifier avec les boutons de la barre d’icones (en haut), ou bien celle des proriétés de style (à droite).

    barre d'icones

    barre d'icones

    Puis cliquer sur le bouton Mettre à jour le Style sélectionné.

    Ce bouton se trouve près du menu des styles de la barre d'icones

    Ce bouton se trouve près du menu des styles de la barre d'icones

    Modifier l’une des propriétés de Titre 1

    Si vous souhaitez modifier la couleur des Titre 1

    Dans la partie Style (fenêtre à droite), dérouler le sous menu Titre

    • Choisir Titre 1 , puis Modifier. Cela ouvre la fenêtre d’Edition.

    Le but est alors de retrouver la bonne Propriété.

    • Choisir l’onglet Effets de caractère. Puis la propriété Couleur de Police, dont vous pouvez modifier la valeur.

    Aide en video

    On s’aidera des tutoriels pour LibreOffice Writer à l’adresse suivante: Youtube - LibreOffice Writer 1/11 : Mettre en forme le style principal

    Mettre en forme RGPD

    Document texte

    Le logiciel Writer de traitement de texte

    Writer est l’un des logiciels de la suite bureautique LibreOffice.

    Cette suite bureautique est libre et gratuite, elle est dérivée du projet OpenOffice.org, créée et gérée par The Document Foundation.

    LibreOffice est notamment soutenue par la Fondation pour le logiciel libre et rassemble une grande partie de l’ancienne communauté d’OpenOffice.org.

    En France, LibreOffice est intégré au socle interministériel de logiciels libres de l’État. L’interface utilisateur est disponible en 114 langues.

    Dans un logiciel de traitement de texte, on fait simultanément les 2 actions suivantes:

    • on insère du contenu dans une page
    • on formate le contenu.

    Que signifie: Formater le contenu?

    Mettre en forme un document textuel demande de connaitre le nom et la nature des objets et des fonctions utilisés:

    • feuille de Style
    • Objets paragraphes, Titre 1, Titre 2, …, listes.

    Tous ces objets sont accessibles dans le bandeau de droite Vous allez identifier ou ajouter ces différents éléments éléments au document:

    Les paragraphes

    Le titre

    Le sous-titre

    Les chapitres (HEADER) de niveau 1, niveau 2, etc

    Les listes

    L’en-tête et le pied de page

    La bibliographie

    Le sommaire

    Travail demandé

    • Copier le contenu du Framapad. Coller en faisant collage special afin d’éliminer toutes les mises en forme.
    • Reconstruire les paragraphes
    • Utiliser les niveaux de titres pour structurer votre document (Titre1, Titre2, Titre3…).
    • Numéroter les sous-titres (Menu Outils> Numérotation des chapitres).
    • Insérer une image
    • Ajouter une bibliographie ou une sitographie

    Utilisation basique de Writer

    Un tutoriel sur l’utilisation avancée de Writer:

    Youtube - LibreOffice Writer 1/11 : Mettre en forme le style principal

    Youtube - LibreOffice Writer 1/11 : Mettre en forme le style principal

    Identifier les titres de niveau 1, 2, …

    Titre de niveau 1: Positionner le curseur sur la ligne que vous voulez identifier comme un titre de niveau 1

    Dans la partie Style (fenêtre à droite), dérouler le sous menu Titre

    Et faire un double-clic sur Titre 1. L’élément devient alors un Titre 1, et prend le style associé, c’est à dire les propriétés suivantes, visible dans la barre d’outils (en haut):

    • police: Liberation Serif
    • taille: 24 pt
    • decoration: bold

    Par defaut, un élément du document est de type Paragraphe.

    Ajouter une numérotation

    Si vous souhaitez ajouter un numéro aux éléments de type Titre 4:

    Ouvrir le menu Outils de la barre des menus et choisir numérotation des chapitres:

    Dans la fenêtre, choisir l’onglet numérotation et paramétrer pour démarrer une numérotation 1,2,3 pour les titres de niveau 4:

    Voir pour plus de détails les explications ici: pdf de lyceedupaysdesoule.fr

    Ajouter une sitographie

    Vous allez ajouter 3 à 6 liens qui ont été utiles pour la rédaction du contenu.

    Une référence bibliographique doit indiquer toutes les informations indispensables à l’identification d’un document ou d’un texte, et ce, qu’il soit accessible en version papier ou en ligne. Le format de la référence varie légèrement selon le document. Essayez de vous y conformer.

    Référencer une page web

    • Auteur identifié

    Nom, P. Titre de la page. Nom du site. Consulté le Date sur URL

    Exemple:
    -------
    Leterme, C. (2020, janvier 31). Tout savoir sur la publication d’un article scientifique. Scribbr. Consulté le 15 mars 2023 sur https://www.scribbr.fr/article-scientifique/publication-article-scientifique/
    • Sans auteur, sans date
    Exemple: 
    -------
    Tarte aux pommes. (s. d.). Marmiton. https://www.marmiton.org/recettes/recette_tarte-aux-pommes_18588.aspx

    Référencer une publication

    • Un article d’encyclopédie ou d’une revue en ligne:

    Nom, P. (Année). Titre de l’article. Dans Titre de l’encyclopédie. URL

    Exemple:
    -------
    Ramade, F. (2022). Écotoxicologie. Dans Encyclopædia Universalis. http://www.universalisedu.com.srvext.uco.fr/encyclopedie/ecotoxicologie/
    • Auteur non identifié:

    Si l’auteur n’est pas identifié car il s’agit d’une institution ou d’un organisme, son nom remplace celui de l’auteur.

    Exemple:
    -------
    Ademe. (2021). Rapport de diagnostic-Actualisation de l’étude d’évaluation des services vélos. https://librairie.ademe.fr/mobilite-et-transport/4934-diagnostic-d-evaluation-des-services-velos.html
    • Un texte réglementaire en ligne:

    Titre de l’arrêté. (Année). JORF No, Jour mois, 2021. Texte no. Http

    (à lire) Recommandations utiles pour des documents longs

    • Insérer des sauts de pages avant les titres de niveau 1 (Menu Style de paragraphe: Titre1)
    • Utiliser peu de polices, une pour les titres et une pour le texte. Utiliser des polices de qualité bien lisibles par exemple: Times new Roman(serif pour le texte), Arial(sans serif pour les titres).
    • Utiliser les images avec parcimonie et numéroter et légender les figures(clic droit sur l’image: Insérer une légende). Pensez à citer la source, et respecter les droits d’auteur sur l’image.
    • Numéroter les pages(Dans le pied de page, Insertion> Champ > Numéro de page).
    • Faire une page de garde non numérotée avec le style de page Première Page.
    • Insérer en deuxième page la table des matières générée automatiquement à partir des titres(MenuInsertion > Table des matières).
    • Pour la bibliographie, l’insertion de notes de bas de page ou de fin peut suffire(Menu Insertion > Note de bas de page/ de fin).

    S’il vous reste du temps

    TP suivant: les moteurs de recherche: Lien

    guide style

    Pour être lisible, un texte doit comporter une certaine hierarchie. Cela amène de la clarté, mais, aussi, cela sera utile si l’on veut intégrer une table des matières ou un sommaire.

    Il est nécessaire de séparer le travail de la forme du document de celui du contenu. Et de bien connaitre les différents éléments du document.

    Guide de style pour le mémoire

    Les règles à suivre

    • Utiliser les niveaux de titres pour structurer votre document (Titre1, Titre2, Titre3…).
    • Numéroter les titres et sous-titres(Menu Outils> Numérotation des chapitres).
    • Insérer des sauts de pages avant les titres de niveau 1 (Menu Style de paragraphe: Titre1)
    • Utiliser peu de polices, une pour les titres et une pour le texte. Utiliser des polices de qualité bien lisibles par exemple: Times new Roman(serif pour le texte), Arial(sans serif pour les titres).
    • Utiliser les images avec parcimonie et numéroter et légender les figures(clic droit sur l’image: Insérer une légende). Pensez à citer la source, et respecter les droits d’auteur sur l’image.
    • Numéroter les pages(Dans le pied de page, Insertion> Champ > Numéro de page).
    • Faire une page de garde non numérotée avec le style de page Première Page.
    • Insérer en deuxième page la table des matières générée automatiquement à partir des titres(MenuInsertion > Table des matières).
    • Pour la bibliographie, l’insertion de notes de bas de page ou de fin peut suffire(Menu Insertion > Note de bas de page/ de fin).
    • Pensez à exporter votre document au format pdf pour le partager.

    TP1 - Evaluer la forme d’un mémoire

    Le modèle

    A vous de jouer: Repérez ces différents éléments dans le document suivant:

    Vademecum - rediger un mémoire - sciencespo-lille.eu

    Vademecum - rediger un mémoire - sciencespo-lille.eu

    Evaluation

    Ouvrir ensuite les rapports de stage d’observation et de pratique accompagnée de Julie et Marion. Ces deux documents, respectent-ils TOUTES les règles du guides de style présentés plus haut?

    TP2 - Mettre en forme un document

    On s’aidera du tutoriel pour LibreOffice Writer à l’adresse suivante:

    Youtube - LibreOffice Writer 1/11 : Mettre en forme le style principal

    Youtube - LibreOffice Writer 1/11 : Mettre en forme le style principal

    Vous pouvez aussi consulter le cours de PPPE1: utilisation basique de Writer.

    Document .odt > LibreOffice Writer

    Le document suivant ne présente aucune mise en forme pour son contenu.

    Téléchargez ce document et modifiez le pour le présenter avec un Style inspiré du mémoire - sciencespo-lille.eu:

    • Créer des éléments particuliers dans le texte: ajouter un Titre, un Sous-titre, des Chapitres de niveau 1, 2…
    • Modifier les Styles
    • Ajouter une ou plusieurs images
    • Ajouter un sommaire, un épigraphe
    • Ajouter un en-tête, un pied de page

    Remarque: Si on a malencontreusement stylé du texte par le menu du haut, utiliser le raccourci CTRL+M pour «Effacer le formatage direct» (ou par le menu Format)

    Les éléments du document

    Voici la liste des éléments mentionnés dans le guide de style. On retrouve la plupart de ces éléments comme des objets communs aux logiciels de traitement de texte (Word, Writer).

    • Le titre
    • Le sous-titre
    • Les chapitres (HEADER) de niveau 1, niveau 2, etc
    • Les paragraphes
    • Les listes
    • L’en-tête et le pied de page
    • L’épigraphe

    L’épigraphe est une courte citation placée au début d’un ouvrage ou d’un chapitre, et qui permet d’en indiquer l’esprit. La table des matières correspond à une liste complète des parties et des sous-parties d’un document.

    • La table des matières La table des matières (table of contents en anglais) est placée à la fin de l’ouvrage. Elle détaille l’ensemble des divisions d’un document.

    • Le sommaire Le sommaire est généralement plus succinct et ne reprend pas forcément toutes les sous-parties. Le sommaire propose un résumé des parties à venir dans le document et se situe ainsi au début de celui-ci.

    Réutiliser ses Styles personnalisés

    A l’ouverture d’un nouveau document, les Styles sont remis à ceux d’origine. Pour retrouver ceux que vous avez déjà définis, il faut charger les Styles à partir de votre ancien document: Voir ici les explications .

    Correcteur orthographique

    Le logiciel Writer comprend un correcteur grammatical et d’orthographe. On peut aussi en ajouter un (par ex. l’extension Grammalecte. Utilisez le, il vous permettra d’améliorer grandement la qualité de votre compte-rendu(fautes d’orthographe, formes grammaticales, insertion d’espaces insécables…).

    Liens

    Utiliser Writer

    Cette fiche montre les similitudes de conception d’un document:

    1. Textuel avec LibreOffice Writer
    2. Pour le Web, en langage HTML

    Un document réponse est à télécharger et compléter:

    Document à compléter

    Document à compléter

    Partie 1: Formater le texte d’un document avec Writer

    Mettre en forme un document textuel demande une certaine maitrise du logiciel, mais surtout, connaitre le nom des objets et des fonctions utilisés:

    • feuille de Style
    • Objets paragraphes, Titre 1, Titre 2, …, listes.

    Ainsi que le nom des propriétés de ces objets:

    • Police, taille de la police, couleur
    • indentation, surlignage, encadré
    • …

    Remarque: Le logiciel appelle ces éléments et objets des Styles. Nous préférons conserver les termes objets ou éléments pour désigner les paragraphes, Titre 1, …, comme il est d’usage en HTML (voir partie 2).

    Choisir une feuille de style à l’ouverture

    A l’ouverture du logiciel Writer, vous pouvez choisir parmi plusieurs styles prédéfinis. Mais que se passe-t-il si vous avez besoin d’un style différent tel qu’un style poème qui n’est pas dans la fenêtre Styles et formatage?

    Avec Writer, vous pouvez créer les styles correspondant à vos besoins …openoffice.org > Créer des styles personnalisés

    Une fois votre document ouvert, vous pouvez toujours changer de feuille de style. Pour afficher les styles sous Libre Office : Choisissez dans la barre des menus (en haut): Styles > Charger les styles.

    Modifier le style d’un élément ou en créer un nouveau

    Méthode 1:

    Depuis la fenêtre des Styles (à droite), sélectionner l’un des élements, comme par exemple Style de paragraphe par défaut. Choisir dans le menu: Nouveau ou Modifier

    • Nouveau: cela créé un nouvel objet fils de celui sélectionné, qui s’ajoute à la liste des Styles

    • Modifier: cela ouvre la fenêtre de modification du Style, que l’on peut aussi atteindre depuis la barre de menu du haut (Styles > choisir Editer le Style). La nouvelle fenêtre contient alors toutes les propriétés modifiables pour ce Style, classées par onglet.

    Méthode 2:

    Sélectionner dans la page l’un des éléments dont vous souhaitez modifier le style. Modifier avec les boutons de la barre d’icones (en haut).

    Puis cliquer sur le bouton Mettre à jour le Style sélectionné.

    Ce bouton se trouve près du menu des styles de la barre d'icones

    Ce bouton se trouve près du menu des styles de la barre d'icones

    Modifier l’une des propriétés de Titre 1

    Si vous souhaitez modifier la couleur des Titre 1

    Dans la partie Style (fenêtre à droite), dérouler le sous menu Titre

    • Choisir Titre 1 , puis Modifier. Cela ouvre la fenêtre d’Edition.

    Le but est alors de retrouver la bonne Propriété.

    • Choisir l’onglet Effets de caractère. Puis la propriété Couleur de Police, dont vous pouvez modifier la valeur.

    Créer un élément pour insérer des scripts

    Les scripts sont des programmes informatiques. Leur format suit des règles précises, et ceux-ci ne doivent pas être reformatés par le logiciel Writer. Leur indentation doit être conservée, la casse (minuscule / majuscule) aussi.

    Cela peut nécéssiter la création d’un nouvel élément dans Writer. Cela permettra d’avoir un format personnalisé, comme une nouvelle police de caractères. Souvent, celle utilisée pour les scripts est Courier New, en gras.

    On peut aussi faire un collage du script avec la coloration syntaxique highlight). Le logiciel en ligne highlight.hohli.com permet de faire cela. Coller le script dans la fenêtre, choisir le langage, et copier le texte mis en couleur avant de la coller dans Writer. Puis utiliser le nouveau Style personnalisé pour le formater (script).

    Ajouter une numérotation

    Si vous souhaitez ajouter un numéro aux éléments de type Titre 4:

    Ouvrir le menu Outils de la barre des menus et choisir numérotation des chapitres:

    Dans la fenêtre, choisir l’onglet numérotation et paramétrer pour démarrer une numérotation 1,2,3 pour les titres de niveau 4:

    Voir pour plus de détails les explications ici: pdf de lyceedupaysdesoule.fr

    Liens

    Writer et Word

    Ce TP montre les similitudes de conception d’un document:

    1. Textuel avec Word/LibreOffice Writer
    2. Pour le Web, en langage HTML

    Formater le texte d’un document

    Mettre en forme un document textuel demande une certaine maitrise du logiciel, mais surtout, connaitre le nom des objets et des fonctions utilisés:

    • feuille de Style
    • Objets paragraphes, Titre 1, Titre 2, …, listes.

    Ainsi que le nom des propriétés de ces objets:

    • Police, taille de la police, couleur
    • indentation, surlignage, encadré
    • …

    Remarque: Le logiciel appelle ces éléments et objets des Styles. Nous préférons conserver les termes objets ou éléments pour désigner les paragraphes, Titre 1, …, comme il est d’usage en HTML (voir partie 2).

    Microsoft Word

    A vous de jouer: Télecharger et ouvrir le document textuel sur les plastiques . Copiez l’ensemble du texte (CTRL + a, CTRL + c) et collez-le dans un nouveau document Word CTRL + V)

    En vous inspirant de la video suivante, mettre en forme le document en suivant la méthode proposée.

    video - youtube - separation contenu, structure, forme

    video - youtube - separation contenu, structure, forme

    Ci-dessous, certains travaux d’élèves sont proposés en exemple:

    Pour modifier plus grandement la structure, il faut utiliser des sections.

    L’editeur de texte Word permet aussi de placer une partie du contenu sur plusieurs colonnes. Le logiciel place alors des sections dans le document, comme expliqué dans le tuto suivant: tuto unilim.fr.

    Libre Office Writer

    Modifier le style d’un élément ou en créer un nouveau

    Méthode 1:

    Depuis la fenêtre des Styles (à droite), sélectionner l’un des élements, comme par exemple Style de paragraphe par défaut. Choisir dans le menu: Nouveau ou Modifier

    • Nouveau: cela créé un nouvel objet fils de celui sélectionné, qui s’ajoute à la liste des Styles

    • Modifier: cela ouvre la fenêtre de modification du Style, que l’on peut aussi atteindre depuis la barre de menu du haut (Styles > choisir Editer le Style). La nouvelle fenêtre contient alors toutes les propriétés modifiables pour ce Style, classées par onglet.

    Méthode 2:

    Sélectionner dans la page l’un des éléments dont vous souhaitez modifier le style. Modifier avec les boutons de la barre d’icones (en haut).

    Puis cliquer sur le bouton Mettre à jour le Style sélectionné.

    Ce bouton se trouve près du menu des styles de la barre d'icones

    Ce bouton se trouve près du menu des styles de la barre d'icones

    Modifier l’une des propriétés de Titre 1

    Si vous souhaitez modifier la couleur des Titre 1

    Dans la partie Style (fenêtre à droite), dérouler le sous menu Titre

    • Choisir Titre 1 , puis Modifier. Cela ouvre la fenêtre d’Edition.

    Le but est alors de retrouver la bonne Propriété.

    • Choisir l’onglet Effets de caractère. Puis la propriété Couleur de Police, dont vous pouvez modifier la valeur.

    Créer un élément pour insérer des scripts

    Les scripts sont des programmes informatiques. Leur format suit des règles précises, et ceux-ci ne doivent pas être reformatés par le logiciel Writer. Leur indentation doit être conservée, la casse (minuscule / majuscule) aussi.

    Cela peut nécéssiter la création d’un nouvel élément dans Writer. Cela permettra d’avoir un format personnalisé, comme une nouvelle police de caractères. Souvent, celle utilisée pour les scripts est Courier New, en gras.

    On peut aussi faire un collage du script avec la coloration syntaxique highlight). Le logiciel en ligne highlight.hohli.com permet de faire cela. Coller le script dans la fenêtre, choisir le langage, et copier le texte mis en couleur avant de la coller dans Writer. Puis utiliser le nouveau Style personnalisé pour le formater (script).

    Ajouter une numérotation

    Si vous souhaitez ajouter un numéro aux éléments de type Titre 4:

    Ouvrir le menu Outils de la barre des menus et choisir numérotation des chapitres:

    Dans la fenêtre, choisir l’onglet numérotation et paramétrer pour démarrer une numérotation 1,2,3 pour les titres de niveau 4:

    Voir pour plus de détails les explications ici: pdf de lyceedupaysdesoule.fr

    Liens

    moteurs de recherche

    Moteurs de recherche

    Expérience

    Faites une recherche avec le seul mot clé Harry

    Quels sont les principales informations des documents proposés par le moteur recherche? Classer ces propositions avec un score décroissant

    • des pages qui ne concernent que le prince Harry, sa biographie, …
    • des pages qui concernent le prince Harry et sa famille
    • des pages qui concernent l’actualité autour du prince Harry
    • des pages qui concernent Harry et son épouse Meghan
    • des pages qui concernent d’autres personnes que le prince Harry de Sussex (Harry Potter par exemple)

    Faites une autre recherche, mais cette fois avec la combinaison de mots clés Harry -"Meghan"

    Ne pas mettre d’espace entre le - et le texte entre guillemets.

    Refaire le classement. Que remarquez-vous?

    Comment fonctionne un moteur de recherche?

    Le TP suivant est adapté de la page: paris-université

    On utilisera la liste suivante pour les textes de Raymond Queneau.

    publier

    Sous-sections de publier

    classif vivant

    TP HTML/CSS n°2 - La classification du vivant

    Rappels : Balises et règles CSS

    Tableau récapitulatif des balises HTML

    Balise Utilisation Syntaxe
    <h1> Titre principal <h1>Mon titre</h1>
    <h2> Titre de section <h2>Ma section</h2>
    <h3> Sous-titre <h3>Mon sous-titre</h3>
    <p> Paragraphe <p>Mon texte...</p>
    <a> Lien hypertexte <a href="URL">Texte du lien</a>
    <img> Image <img src="nom_image.jpg">
    <figure> Container pour image <figure>...</figure>
    <figcaption> Légende d’image <figcaption>Texte</figcaption>
    <div> Container / bloc <div>...</div>
    <blockquote> Citation <blockquote>...</blockquote>
    <strong> groupe de mots en gras <strong>...</strong>

    Principales règles CSS utiles

    Propriété Effet Exemple
    color Couleur du texte color: blue;
    background-color Couleur de fond background-color: lightgreen;
    font-size Taille du texte font-size: 20px;
    font-family Police de caractères font-family: Arial, sans-serif;
    text-align Alignement du texte text-align: center;
    width Largeur width: 80%;
    margin Marges externes margin: 20px;
    padding Marges internes padding: 10px;
    border Bordure border: 2px solid black;
    display: flex; Placer côte à côte display: flex;

    Structure de base d’un document HTML

    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<title>Titre de la page</title>
    </head>
    <style>
    	/* Vos règles CSS ici */
    </style>
    <body>
    	<main>
    	<!-- Votre contenu ici -->
    	</main>
    
    
    </body>
    </html>

    Consignes du TP

    Vous allez créer une page web sur la classification du vivant en utilisant vos connaissances en HTML et CSS.

    Étape 1 : Créer le fichier

    1. Ouvrez Notepad++
    2. Copiez le texte de contenu ci-dessous
    3. Enregistrez le fichier sous le nom classification.html dans vos Documents

    Étape 2 : Structurer le document

    En vous aidant du tableau récapitulatif :

    • Ajoutez la structure de base du document HTML (doctype, html, head, body, main)
    • Identifiez et ajoutez les balises appropriées pour :
      • Le titre principal
      • Les titres de sections
      • Les paragraphes
      • Le lien en fin de document

    Étape 3 : Ajouter une image

    • Téléchargez l’image fournie (arbre phylogénétique)
    • Placez-la dans le même dossier que votre fichier HTML
    • Insérez l’image dans le document avec une légende appropriée
    • Utilisez un container <div style="display:flex;"> pour placer l’image à droite du paragraphe concernant “Les arbres phylogénétiques”

    Étape 4 : Styliser la page

    Créez des règles CSS pour :

    • Donner un style particulier au titre principal (police, couleur, taille, centrage)
    • Définir une largeur et une couleur de fond pour le <main>
    • Adapter les dimensions de l’image et de son paragraphe associé
    • Personnaliser l’apparence des légendes d’images
    • Ajouter des bordures et marges si nécessaire

    Objectif visuel : Obtenir une page lisible, structurée et esthétique.


    Texte de contenu à structurer

    La classification du vivant
    Qu'est-ce que la classification du vivant ?
    
    La classification du vivant est une science qui a pour objet de regrouper les êtres vivants par catégories. Le système actuel repose sur la notion d'évolution et de parenté entre les espèces. On classe ensemble les êtres vivants qui partagent un ancêtre commun récent. Cette approche s'appelle la classification phylogénétique.
    
    Les critères de classification
    
    Pour classer les êtres vivants, les scientifiques comparent leurs caractères, c'est-à-dire leurs caractéristiques observables : présence d'un squelette interne, de plumes, de poils, d'écailles, type de reproduction, etc. Plus deux êtres vivants partagent de caractères en commun, plus ils sont proches sur le plan de l'évolution. Ces caractères partagés sont appelés caractères dérivés et ils témoignent d'une origine commune.
    
    Les arbres phylogénétiques
    
    Les relations de parenté entre les espèces sont représentées sous forme d'arbres phylogénétiques, aussi appelés arbres du vivant. Chaque branche de l'arbre représente un groupe d'êtres vivants partageant des caractères communs. Les nœuds de l'arbre correspondent aux ancêtres communs hypothétiques. Plus on remonte dans l'arbre, plus on retrouve des ancêtres communs à de nombreux groupes d'organismes.
    
    L'importance de la classification
    
    La classification du vivant permet aux scientifiques du monde entier de parler le même langage lorsqu'ils étudient la biodiversité. Elle aide à comprendre l'histoire évolutive de la vie sur Terre et à identifier les relations entre les différentes formes de vie. Cette connaissance est essentielle pour la conservation des espèces et pour mieux comprendre comment la vie s'est diversifiée au cours des temps géologiques.
    
    Sitographie
    Article adapté de la page Classification phylogénétique du vivant consultée le 15 janvier 2024 sur Wikipédia : https://fr.wikipedia.org/wiki/Classification_phylog%C3%A9n%C3%A9tique_du_vivant

    Image à télécharger

    Pour ce TP, vous utiliserez une image d’arbre phylogénétique simplifié.

    Recherche de l’image :

    • Rendez-vous sur Wikimedia Commons ou Wikipedia
    • Recherchez “arbre phylogénétique” ou “phylogenetic tree”
    • Choisissez une image libre de droits
    • Téléchargez-la et enregistrez-la sous le nom arbre.jpg dans le même dossier que votre fichier HTML

    Critères de réussite

    ✓ Le document HTML est valide et s’affiche correctement dans le navigateur
    ✓ Toutes les balises de structure sont présentes (h1, h2, p)
    ✓ Le lien est fonctionnel
    ✓ L’image est visible avec sa légende
    ✓ L’image est placée à droite d’un paragraphe
    ✓ Des règles CSS personnalisées sont appliquées
    ✓ La mise en page est cohérente et agréable visuellement

    Bonus : Ajoutez une couleur de fond différente pour les titres h2, ou créez une bordure autour des images.


    Bon courage !

    Les plastiques

    Découverte du langage HTML

    docx, odt, txt et html: différents documents textuels

    Les fichiers aux extensions docx et odt permettent d’écrire et présenter du texte. La structure du document se fait à l’aide de boutons d’options proposés par le logiciel. Le rendu visuel de la page est présenté par le logiciel au fur et à mesure de sa construction.

    Pour la creation d’une page web, c’est différent. On utilise un editeur HTML, comme notepad++.

    Dans l’editeur, pour structurer le contenu textuel, il n’y a pas de boutons pour choisir les propriétés des éléments. Il faut ajouter DANS LE DOCUMENT des métadonnées. Cela se fait d’une manière très speciale avec le html, à l’aide de BALISES. C’est ce que nous allons voir ici.

    Pour afficher la page, il faudra retrouver la page à l’aide de l’explorateur, sur votre disque dur, et l’ouvrir avec un 2e outil, le navigateur.

    Le HTML : Document pour le Web

    Un document pour le Web est constitué d’un ou plusieurs fichiers de type texte. Le fichier aura pour extension .html. Un fichier .html doit être ouvert avec un navigateur.

    La manière avec laquelle vous allez construire ce document suit les même étapes que la rédaction d’un document textuel. Mais ici, les instructions de mise en page seront ajoutées au contenu, dans le même fichier.

    Le langage HTML s’occupe de la structure du document, grâce à des balises qui intègrent le contenu.

    Format de document

    A vous de jouer: Télecharger et ouvrir le document textuel sur les plastiques . Copiez l’ensemble du texte (CTRL + a, CTRL + c)

    Dans un editeur de texte: Rechercher parmi les logiciels installés: Bloc notes, Notepad, ou mieux, Notepad++ (ajoute la coloration syntaxique): coller le texte. Sauvegarder dans vos Documents avec le nom plastiques.html

    Ouvrir à l’aide d’un navigateur: Double clic sur le document depuis l’explorateur windows, ou bien, depuis le menu fichier du navigateur: Ouvrir.. et rechercher le document.

    Problèmes:

    • On obtient alors un document qui n’a aucune structure
    • De plus, avec certains navigateurs, certains caractères ne sont pas reconnus et cela peut donner le rendu suivant:
    fichier texte non formaté ouvert avec un navigateur

    fichier texte non formaté ouvert avec un navigateur

    On va résoudre certains de ces problèmes en déclarant le format d’encodage des caractères. Cette information est très importante pour le navigateur.

    Au début du document html: Ajouter avec l’editeur les lignes suivantes:

    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<title>page principale</title>
    </head>
    <body>
    <section>
    Le plastique, une « antiquité » !
    Plusieurs siècles av. J.C, les hommes utilisaient déjà ...
    • Ajouter aussi les lignes suivantes en FIN de document:
    </section>
    </body>
    </html>

    Navigateur:

    • Recharger la page (CTRL + r). Que remarquez vous?
    • Dans le fichier html. Remplacer <meta charset="utf-8"> par <meta charset="us-ascii">. Recharger la page. Que remarquez vous? Lequel des 2 encodages, us-ascii ou utf-8 est le plus adapté pour présenter les caractères.
    • Sélectionner le bon encodage pour la suite de votre travail.

    Définir des éléments dans la page

    Pour créer un paragraphe, le contenu devra être inséré entre une balise de début <p> et une balise de fin </p>.

    Les autres balises principales sont:

    • Titre 1: <h1> ... </h1>
    • Titre 2: <h2> ... </h2>
    • Titre 3: <h3> ... </h3>
    • Bloc de citation: <blockquote> ... </blockquote>
    • liens: <a> ... </a>

    Où les ... signifient le contenu.

    Balises HTML: modifier la structure du document à l’aide des balises HTML:

    ajouter la balise h1 pour le titre principal

    ajouter les balises h2 pour les titres des chapitres

    ajouter les balises p pour les paragraphes

    ajouter les balises a pour les liens: Le lien se trouve en fin de document dans cet exemple.

    Il s’agit du texte: Article issu de la page histoire du plastique de cabriolice.com https://www.carbiolice.com/blog/lhistoire-du-plastique-en-15-dates-cle/

    • Identifier l’URL de redirection (l’adresse du lien): https:/ ... dates-cle/
    • Identifier la cible du lien (le mot sur lequel vous devez cliquer): histoire du plastique
    • Remplacer le texte non formaté par le mélange de texte et de balises suivant:

    Article issu de la page <a href="https://www.carbiolice.com/blog/lhistoire-du-plastique-en-15-dates-cle/">histoire du plastique</a> de cabriolice.com

    Questions: Dans les instructions de la balise <a>:

    • où se place la cible du lien?
    • où se place l’adresse du lien?

    5. Ajouter un autre lien

    Placer après cette dernière ligne un autre lien, vers la page de wikipedia sur les matières plastiques par exemple.

    Navigateur: Recharger la page (CTRL + r). Que remarquez vous? Les liens sont-ils actifs lorsque l’on clique dessus?

    Ajouter une image

    L’ajout d’image diffère de la procédure d’un logiciel d’edition de texte comme Word ou Writer. Ici, on n’insère pas l’image elle-même, mais on indique son adresse sur le net. La syntaxe est la suivante:

    <img src="https://adresse_sur_le_net.jpg">

    On choisira une image libre d’être diffusée, comme par exemple celle sur le site wikipedia d’adresse:

    https://upload.wikimedia.org/wikipedia/commons/8/80/Compounding.png

    Faites référence à l’auteur de l’image si vous l’identifiez, ou bien la page dont est issue l’image, à l’aide d’un élément html qui suivra l’image. On peut utiliser une balise <figcaption> ... légende ... </figcaption>.

    production de granulés de polymères - image de la page *Matières plastiques* (wikipedia)

    production de granulés de polymères - image de la page *Matières plastiques* (wikipedia)

    Modifier les styles des éléments

    Les instructions de style se mettent entre les balises <style>. Ces balises seront placées après la fermeture </head> et avant l’ouverture du contenu <body>

    </head>
    
    <style>
      instructions de style en langage css
    </style>
    
    <body>
    .. contenu ..

    Les instructions de style, en langage CSS, vont déclarer:

    • l’élément HTML auquel on fait référence (un selecteur p, h1, …)
    • la propriété que l’on veut styliser
    • la valeur que l’on veut mettre pour cette propriété

    Suivre le tutoriel à la page developper.mozilla sur le CSS niveau débutant.

    Vous pouvez tester les effets de certaines de ces instructions en les plaçant entre les balises <style> de votre document. Par exemple:

    <style>
    h1 {
      font-size: 60px;
      text-align: center;
    }
    
    p {
      font-size: 16px;
      line-height: 2;
      letter-spacing: 1px;
    }
    </style>

    Ajouter une deuxième page

    Votre site web va être constitué de 2 pages, sur le recyclage des plastiques. Le contenu textuel se trouve dans ce fichier: recyclage_plastiques.txt

    Le texte est extrait de la ressource: rapport du sénat sur le traitement des plastiques

    • Créer une 2e page HTML à partir de ce contenu
    • Créer un lien depuis la page 1 vers la page 2, puis de la page 2 vers la page 1.

    Cette fois-ci, vous allez créer des liens internes (entre documents d’un même site internet). Vous allez utiliser des adresses relatives entre les pages. Deux possibilités:

    • Supposons que page1.html et page2.html sont dans le même dossier: Pour créer un lien de la page 1 vers la page 2, la balise lien s’écrira: <a href="page2.html">Lien vers la page 2</a>
    • Si les page1.html et page2.html ne sont pas dans le même dossier, il faudra utiliser le chemin relatif: <a href="chemin/page2.html">Lien vers la page 2</a>

    Chemin relatif: explication ici

    La démocratie athenienne

    Rédiger un document pour le Web

    Le HTML : Structurer le document

    Le HTML s’occupe de la structure du document, grâce à des balises qui intègrent le contenu.

    Formats de document

    Démocratie athénienne
    Les origines de la démocratie athénienne
    
    Au vie siècle av. J.-C., les cités du monde grec sont confrontées à une grave crise politique. Pour répondre à cette crise, de nombreuses cités modifient radicalement leur organisation politique. À Athènes, un ensemble de réformes amorce un processus débouchant au ve siècle av. J.-C. sur l'apparition d'un régime politique inédit : une sorte de démocratie pour les hommes libres mais avec la continuation de l'esclavage.
    
    La démocratie athénienne
    
    La démocratie athénienne désigne le régime politique de démocratie directe mis en place progressivement dans la cité d'Athènes durant l'Antiquité et réputée pour être l'ancêtre des démocraties modernes. Le terme démocratie vient des mots grecs δῆμος / dêmos («le peuple») et κράτος / krátos («la puissance, le pouvoir»). Il s'agit donc d'un régime où les décisions sont prises par le peuple.
    
    La cité
    
    Athènes est fondée formellement vers 750 av. J.-C. par synœcisme de plusieurs agglomérations partiellement préservées de l'invasion des Doriens.
    
    Le site est choisi pour la forteresse naturelle que représente l'Acropole ; les habitants peuvent résister aux hordes de pillards qui menacent la région, augmentant avec les années sa fortification. À partir de 510 av. J.-C., cette fonction défensive est abandonnée, le lieu étant consacré aux cultes et notamment celui d'Athéna, déesse protectrice d'Athènes. Des remparts encerclent à partir de 478 av. J.-C. la ville et son port, le Pirée.
    
    Quelques gymnases et écoles de philosophie s'excentrent pour que leurs élèves profitent de la tranquillité et soient totalement isolés pendant les deux années de leur éphébie.
    
    L'agora devient le centre social et politique de la cité avec l'installation des institutions démocratiques sur cette place. En été de nombreux débats houleux ou amicaux se tiennent à l'ombre du portique sud et de la Stoa Poikilè, on discute politique et philosophie. Des joutes oratoires d'un autre genre se déroulent sur la Pnyx, colline sur laquelle sont votées toutes les lois athéniennes. La cité est donc le cœur de la démocratie.
    Sitographie
    Article issu de la page (consultée le 01 dec 2023) Démocratie Athénienne sur wikipedia.org: https://fr.wikipedia.org/wiki/D%C3%A9mocratie_ath%C3%A9nienne

    Le contenu doit être mis dans un document avec l’extension .html.

    A vous de jouer: Copiez l’ensemble du texte. Dans un editeur de texte: Rechercher parmi les logiciels installés: Notepad++: coller le texte. Sauvegarder dans vos Documents avec le nom athenes.html

    Ouvrir à l’aide d’un navigateur: Double clic sur le document depuis l’explorateur windows, ou bien, depuis le menu fichier du navigateur: Ouvrir.. et rechercher le document.

    Problèmes:

    • On obtient alors un document qui n’a aucune structure
    • De plus, avec certains navigateurs, certains caractères ne sont pas reconnus et cela peut donner le rendu suivant:
    fichier texte non formaté ouvert avec un navigateur

    fichier texte non formaté ouvert avec un navigateur

    On va résoudre certains de ces problèmes en déclarant le format d’encodage des caractères. Cette information est très importante pour le navigateur.

    Au début du document html: Ajouter avec l’editeur les lignes suivantes:

    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<title>page principale</title>
    </head>
    <body>
    <main>
    Démocratie athénienne
    Les origines de la démocratie athénienne
    
    Au vie siècle av. J.-C., ...
    • Ajouter aussi les lignes suivantes en FIN de document:
    </main>
    </body>
    </html>

    Navigateur: Recharger la page (CTRL + r). Que remarquez vous?

    Définir des éléments dans la page

    Pour créer un paragraphe, le contenu devra être inséré entre une balise de début <p> et une balise de fin </p>.

    Les autres balises principales sont:

    • Titre 1: <h1> ... </h1>
    • Titre 2: <h2> ... </h2>
    • Titre 3: <h3> ... </h3>
    • Bloc de citation: <blockquote> ... </blockquote>
    • liens: <a> ... </a>

    Où les ... signifient le contenu.

    Balises HTML: modifier la structure du document à l’aide des balises HTML:

    ajouter la balise h1 pour le titre principal

    ajouter les balises h2 pour les titres des chapitres

    ajouter les balises p pour les paragraphes

    ajouter les balises a pour les liens: Le lien se trouve en fin de document dans cet exemple.

    Il s’agit du texte: Article issu de la page (consultée le 01 dec 2023) Démocratie Athénienne sur wikipedia.org: https://fr.wikipedia.org/wiki/D%C3%A9mocratie_ath%C3%A9nienne

    • Identifier l’URL de redirection (l’adresse du lien): https:/ ... dates-cle/
    • Identifier la cible du lien (le mot sur lequel vous devez cliquer): Démocratie Athénienne sur wikipedia.org
    • Remplacer ce texte par le script suivant:
    Article issu de la page (consultée le 01 dec 2023) <a href="https://fr.wikipedia.org/wiki/D%C3%A9mocratie_ath%C3%A9nienne">Démocratie Athénienne sur wikipedia.org</a>

    A savoir: Dans les instructions de la balise <a>:

    • la balise <a> possède un attribut href, à l’intérieur même de la balise: <a href="">
    • l’URL se place entre les guillemets devant l’attribut href
    • la cible du lien (le texte à cliquer) se place entre la balise ouvrante <a> et fermante </a>

    Navigateur: Recharger la page (CTRL + r). Que remarquez vous? Le lien est-ils actif lorsque l’on clique dessus?

    Ajouter une image

    L’ajout d’image diffère de la procédure d’un logiciel d’edition de texte comme Word ou Writer. Ici, on n’insère pas l’image elle-même, mais on indique son adresse sur le net. La syntaxe est la suivante:

    <img src="chemin vers l'image">

    On choisira une image libre d’être diffusée, comme par exemple celle sur le site wikipedia ci-dessous:

    Cliquer sur l'image pour télécharger

    Cliquer sur l'image pour télécharger

    Cliquer sur l’image pour l’afficher seule dans une page.

    Faire alors clic droit: enregister sous…

    enregistrer l’image dans le même dossier que votre fichier athenes.html

    Mettre alors l’image sous le paragraphe qui fait référence au Pnyx avec l’ensemble d’instructions:

    <figure>
    <img src="pnyx.jpg">
    <figcaption>Un texte sous l'image</figcaption>
    </figure>

    Faites référence à l’auteur…

    … si vous l’identifiez, ou bien la page dont est issue l’image, à l’aide d’un élément html qui suivra l’image. On peut modifier le texte de la balise figcaption.

    <figcaption>Plate-forme de la Pnyx d'où parle l'orateur public. En arrière-plan, l'Acropole. (wikipedia)</figcaption>

    Modifier la structure du document

    Pour placer l’image à droite du pragraphe, on va utiliser un container (div) qui va englober les 2 éléments à placer côte à côte:

    Placer la balise <div style="display:flex;"> avant le paragraphe:

    <div style="display:flex">
    <p class="gauche">L'agora devient le centre social ...
    le cœur de la démocratie.</p>

    Et fermer la balise </div> après l’objet figure:

    <figcaption>Plate-forme de la Pnyx ... (wikipedia)</figcaption>
    </figure>
    </div>

    Modifier les styles des éléments

    Les instructions de style vont modifier les paramètres par défaut du navigateur pour les éléments HTML. L’idée est d’obtenir le rendu suivant pour votre page:

    Commencer par copier et coller ces nouvelles règles de style fin de document, juste avant la balise de fermeture </html>, les lignes suivantes:

    <style>
    .titre{font-family: Papyrus, Herculanum, Party LET, Curlz MT, Harrington, fantasy;color: blue;font-size: 40px;text-align: center;}
    main {width: 80%;margin: 50px;background-color: hsla(0,70%,50%,0.3);padding: 0 20px 20px 20px;border: 5px solid black;}
    .gauche{width:50%;}
    figure{width:30%;}
    img{width:100%;}
    figcaption{font-size: 0.8em;font-style: italic;}
    a:visited{color: #0000ff;}
    </style>

    Modifier ensuite le style du titre principal ainsi que la position de l’image avec les manipulations suivantes:

    • Ajouter l’attribut de classe au titre h1 en modifiant sa balise. Remplacer <h1 par <h1 class="titre">
    • Ajouter l’attribut de classe au paragraphe qui traite de la partie sur le Pnyx. Ce paragraphe devrait alors se placer à gauche de l’image. Remplacer <p> par <p class="gauche">, seulement pour ce paragraphe.

    La bataille de Marignan

    Encodage des caracteres et header en html

    Dans un fichier, les données sont écrites en binaire. Même les caractères sont exprimés sous forme numérique. Il existe plusieurs tables de correspondance lettre - chiffre. La plus ancienne est celle appelée ASCII. Mais la plus utile sera celle utf-8.

    Pour approfondir: page https://sebsauvage.net/comprendre/ascii/

    Code ASCII

    Le code ASCII définit la correspondance entre symboles et nombres jusqu’au nombre 127. Les caractères sont représentés par une série de 7 chiffres, en binaire. Les mots ont alors une longueur multiple de 7 chiffres binaires, puisque chaque lettre a une longueur fixe.

    Cette longueur de 7 bits est suffisante pour repésenter de manière unique chaque caractère latin. Le problème de l’encodage ASCII est qu’il ne permet pas de représenter assez de caractères pour les besoins des différentes langues. Le e accent aigû é sera ainsi représenté par 16 chiffres binaires, et son affichage en format ASCII donnera é.

    Dans un document HTML, on pourra tout de même afficher correctement ces caractères, mais il faudra utiliser une entité HTML, c’est à dire une combinaison de symboles connus par le navigateur comme par exemple: &eacute; pour la lettre é. Ou, mieux, utiliser l’encodage utf-8.

    Unicode

    Le répertoire Unicode se décline en utf-8, utf-16 et utf-32, qui sont de largeur variable ou fixe (pour utf32) Le code UNICODE permet de représenter tous les caractères spécifiques aux différentes langues.

    L’inconvenient des encodages à largeur fixe (utf-32) est qu’ils vont générer des fichiers de poids important (poids compté en kilo octets). Bien plus lourd que l’encodage ASCII. Alors que bien souvent, la plupart des caractères utilisés pour un document texte sont ceux de l’alphabet ASCII, avec quelques caractères spéciaux.

    Code à largeur variable utf-8 et utf-16

    • Cet encodage utilise l’ASCII pour les caractères dont le point de code est inférieur ou égal à 127.

    • Chaque caractère dont le point de code est supérieur à 127 (0x7F) (caractère non ASCII) se code sur 2 à 4 octets.

    La longueur du nombre binaire est alors variable. Un caractère peut nécessiter 8 bits (ascii), 16 bits, ou plus(jusqu’à 32 bits). Une information dans le code numérique va préciser cette longueur (correspond à un caractère spécial comme le Ã). Cela va permettre d’afficher tous les caractères. Cela génère un fichier dont le poids sera inférieur à l’utf-32.

    Pour le système d’exploitation Windows, l’encodage par defaut est l’utf-16. MacOs utilise un encodage utf-8.

    Activité: Définir le bon encodage en HTML

    Utiliser le logiciel Notepad++ ou tout autre éditeur de script. Créer un nouveau fichier et commencer par l’entête suivant:

    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="ISO-8859-1">
    	<title>page principale</title>
    </head>

    La balise <meta charset="ISO-8859-1"> va donner l’information au navigateur que l’encodage des caractères se fait en ASCII.

    Ajouter alors les lignes suivantes:

    <body>
    <section>
    <h3>La bataille de Marignan, une date restée gravée</h3>
    
    <p>La bataille de Marignan (Marignano en Italie, aujourd’hui Melegnano, ville à 16 km au sud-est de Milan) eut lieu les 13 et 14 septembre 1515 et opposa le roi de France François Ier et ses alliés vénitiens aux mercenaires suisses qui défendaient le duché de Milan.</p>
    
    <p>Il s'agit de la première victoire du jeune roi François Ier, acquise dès la première année de son règne. Celle-ci fit environ 16 000 morts en seize heures de combat.</p>
    
    <p>François Ier, né sous le nom de François d’Angoulême le 12 septembre 1494 à Cognac et mort le 31 mars 1547 à Rambouillet, est un <a href="https://fr.wikipedia.org/wiki/Liste_des_monarques_de_France">roi de France</a> ayant régné du 25 janvier 1515, jour de son sacre, à sa mort en 1547. Fils de <a href="https://fr.wikipedia.org/wiki/Charles_d%27Orl%C3%A9ans_(1459-1496)" title="Charles d'Orléans (1459-1496)">Charles d'Orléans</a> et de <a href="https://fr.wikipedia.org/wiki/Louise_de_Savoie">Louise de Savoie</a>, il appartient à la branche de Valois-Angoulême de la dynastie capétienne.</p>
    </section>
    </body>
    </html>

    Le contenu de la page se trouve entre les balise <body> et </body>. La balise <section> va créer un container et sera utile pour segmenter le document.

    Question a: Sauvegarder le document avec le nom: marignan.html Puis ouvrir le document avec le navigateur. Que constatez-vous? Pourquoi?

    Ajouter maintenant une DEUXIEME section avec la partie suivante: (à placer avant la balise de fermeture </body>:

    <section>
    <h3>La bataille de Marignan, une date rest&eacute;e grav&eacute;e</h3>
    
    <p>La bataille de Marignan (Marignano en Italie, aujourd&rsquo;hui Melegnano, ville &agrave; 16 km au sud-est de Milan) eut lieu les 13 et 14 septembre 1515 et opposa le roi de France Fran&ccedil;ois Ier et ses alli&eacute;s v&eacute;nitiens aux mercenaires suisses qui d&eacute;fendaient le duch&eacute; de Milan.</p>
    
    <p>Il s&#39;agit de la premi&egrave;re victoire du jeune roi Fran&ccedil;ois Ier, acquise d&egrave;s la premi&egrave;re ann&eacute;e de son r&egrave;gne. Celle-ci&nbsp; fit environ 16 000 morts en seize heures de combat.</p>
    
    <p>Fran&ccedil;ois&nbsp;Ier, n&eacute; sous le nom de&nbsp;Fran&ccedil;ois d&rsquo;Angoul&ecirc;me&nbsp;le 12 septembre 1494 &agrave;&nbsp;Cognac et mort le 31 mars 1547 &agrave; Rambouillet, est un&nbsp;<a href="https://fr.wikipedia.org/wiki/Liste_des_monarques_de_France" title="Liste des monarques de France">roi de France</a>&nbsp;ayant r&eacute;gn&eacute; du 25 janvier 1515, jour de son sacre, &agrave; sa mort en&nbsp;1547. Fils de&nbsp;<a href="https://fr.wikipedia.org/wiki/Charles_d%27Orl%C3%A9ans_(1459-1496)">Charles d&#39;Orl&eacute;ans</a>&nbsp;et de&nbsp;<a href="https://fr.wikipedia.org/wiki/Louise_de_Savoie">Louise de Savoie</a>, il appartient &agrave; la branche de&nbsp;Valois-Angoul&ecirc;me de la dynastie cap&eacute;tienne.</p>
    </section>

    Question b: Recharger le document dans le navigateur. Que constatez-vous? Pourquoi?

    Vous allez maintenant modifier l’information sur l’encodage en remplaçant la balise <meta charset="ISO-8859-1"> par balise <meta charset="utf-8">. Revenir sur la première version du texte (celui avec les accents é, à, …).

    Question c: Recharger le document dans le navigateur. Que constatez-vous? Pourquoi?

    introduction au CSS

    Vous avez découvert le langage HTML (Hypertext Markup Langage) dans le TP précédent. Celui-ci gère la structure ET le contenu du document. La mise en forme dépend alors de votre navigateur, à partir des règles de mise en page standart qu’il va appliquer.

    Mais pour maitriser et personnaliser cette mise en forme, il faut utiliser un langage prévu pour gérer les styles. C’est le langage CSS (Cascading Style Sheet).

    Les instructions de style se mettent entre les balises <style>. Ces balises seront placées après la fermeture </head> et avant l’ouverture du contenu <body>

    </head>
    
    <style>
      instructions de style en langage css
    </style>
    
    <body>
    .. contenu ..

    Les instructions de style, en langage CSS, vont déclarer:

    • l’élément HTML auquel on fait référence (un selecteur p, h1, …)
    • la propriété que l’on veut styliser
    • la valeur que l’on veut mettre pour cette propriété

    Vous pouvez consulter le tuto à l’adresse suivante: MDN Mozilla: le CSS

    Question d:: Ecrire une règle CSS complète en identifiant: le sélecteur, la propriété, la valeur.

    Police, coloration, alignement

    Les principales règles de style pour le texte sont color, font-size, text-align, ainsi que font-family.

    Vous pouvez tester les effets de certaines de ces instructions en les plaçant entre les balises <style> de votre document. Par exemple:

    <style>
    h3 {
      color: blue;
      font-size: 60px;
      text-align: center;
    }
    
    p {
      font-size: 16px;
      line-height: 2;
      letter-spacing: 1px;
    }
    </style>

    Pour approfondir, suivre le tutoriel à la page developper.mozilla sur le CSS niveau débutant.

    Hierarchie des éléments html, bordures

    Dans le document marignan.html, les éléments HTML ont une certaine hierarchie: Les balises <h3> et <p> sont à l’intérieur de la balise <section>. Si on veut encadrer le contenu, il faudra appliquer les règles à l’élément section:

    section {
    	...
    }

    Les règles peuvent permettre de

    • fixer la largeur
    • mettre une marge entre les éléments
    • mettre une couleur de fond
    • dessiner une bordure

    Suivre maintenant le tutoriel developper.mozilla pour voir un exemple d’application de ces règles.

    travaux pratiques: écrire les règles de style CSS qui vont permettre d’obtenir la mise en forme suivante:

    Question e: faire un tableau avec 3 colonnes: nom de la propriété, effet de style, exemple de valeur. Mettre dans ce tableau au moins 3 propriétés prévues pour styliser le texte, et 3 propriétés pour styliser le container de ce texte.

    Positionnement des éléments

    Les éléments section se placent naturellement l’un sous l’autre. Ce qui donne, pour la page avec 2 éléments section:

    Pour modifier cette mise en page, et mettre les 2 éléments côte à côte, il faut appliquer la règle de positionnement à l’élément PARENT des 2 éléments section. Ici, cet élément parent, c’est body.

    La règle à appliquer, c’est:

    display: flex;

    Ajouter cette règle CSS pour obtenir la disposition suivante:

    Question f:: Ecrire la règle complète que vous avez utilisée.

    Approfondir: developper.mozilla

    Agencer les éléments

    Vous savez maintenant positionner les éléments dans le flux vertical, horizontal, mettre une image dans un container sans que celle-ci déborde, et utiliser des règles CSS pour personnaliser les styles. Vous pouvez peut-être, s’il vous reste du temps, revenir sur le TP précédent et personnaliser l’affichage de votre page…

    mon film prefere v1

    Créer une page web sur votre film préféré

    Le but de cet exercice est de réaliser une page HTML de présentation de votre film préféré. Cette page sera simple. On pourra piocher les informations de votre film sur des bases de données en ligne de films telles que IMDb, AlloCiné, Wikipédia…

    L’objectif est de réaliser une page qui pourrait présenter les informations comme ceci:

    Mise en place de l’environnement de travail de notre site web

    Dans un premier temps :

    • dans votre répertoire personnel: créez un dossier appelé web, ou utlisez votre précédent dossier (celui contenant vos autres pages web, réalisées lors des précédentes séances).

    Attention, on prendra soin de ne pas mettre d’espaces et d’accents dans notre arborescence de fichiers et dossiers.

    • Dans le dossier web, créez un nouveau dossier, que vous appelerez pages
    • Dans le dossier pages, créez un nouveau fichier à l’aide de l’editeur Notepad++. Copiez-collez les lignes suivantes:
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<title>page principale</title>
    </head>
    <style>
    	/* placer ici vos déclarations CSS*/
    </style>
    <body>
    <!-- le contenu de votre page web. 
    Ceci est un commentaire et peut être effacé.
    -->
    </body>
    </html>
    • Sauvegardez le en l’appelant page1.html

    • Dans le dossier pages, créer un nouveau dossier que vous appelerez images. Placez dans ce dossier les images du film que vous souhaitez afficher dans votre page.

    • Ouvrir le fichier à l’aide d’un navigateur (Mozilla, Edge, …). Rafraichir la page à chaque modification.

    Contenu du fichier

    Rappelez-vous: le contenu de votre document se place entre les balises <body> et </body>. A chaque modification, vous devrez Enregistrer votre document pour que ces modifications soient prises en compte.

    Le document contiendra les éléments suivants:

    Ce document a été réalisé par VOTRE NOM ET PRENOM

    TITRE DU FILM

    Informations générales:

    • Année de Sortie
    • Réalisateur
    • Acteurs Principaux
    • Genre

    Résumé

    Bande-Annonce du Film

    Sources des informations et médias

    Méthode:

    • Ces éléments peuvent être des titres (h1), des sous-titres (h2), … Voir le TP de découverte du HTML.

    • On pourra aussi mettre en évidence, avec la balise <strong>, les différents items de la partie Informations générales.

    • Les éléments de liste peuvent être placés les uns sous les autres, organisés (liste à puce) à l’aide du système d’instructions suivant: (balises ul et li)

    <ul>
        <li>Année de sortie: </li>
        <li>Réalisateur: </h1>
        <li>...</li>
    </ul>
    • Modifiez le texte Ce document a été réalisé par VOTRE NOM ET PRENOM et TITRE DU FILM

    Enregistrez votre travail puis faire F5 dans votre navigateur pour rafraîchir la page. Admirez votre premier travail.

    Compléter les informations

    Des paragraphes

    À l’aide des sites web du début de page, renseignez les différentes informations de la page.

    Méthode: Utilisez les balises <p> ... </p> pour placer des informations dans un paragraphe (par exemple pour le résumé)

    Créer des liens hypertextes

    On l’a vu précédemment, les liens hypertextes sont la base du Web. Voyons comment réaliser ces liens avec du HTML. Un lien permet simplement de se déplacer vers une autre page HTML.

    <a> désigne une ancre, c’est-à-dire un lien vers une cible de destination. Cette balise entoure généralement un mot (une image, un paragraphe, un titre, …) qui devient le texte ‘support du lien’ hypertexte.

    La syntaxe est :

    <a href="adresse_du_lien_hypertexte">support_du_lien</a>

    Dans la partie Sources des informations et médias, ajouter le ou les site·s où vous avez pris vos informations et l’affiche en créant un lien vers le ou les site·s en question.

    Ajouter une image

    (1) Depuis un site web, télécharger le fichier image du film en faisant un clic-droit dessus Enregistrer l’image sous… Enregistrez ce fichier dans le dossier images crée précédemment.

    (2) Nommez cette image affiche.jpg, ou affiche.png ou encore affiche.webp selon le format initial du fichier image.

    Pour ajouter une image dans une page HTML, il faut utiliser la balise

    <img src="image/affiche.png"/>

    chemin vers l’image est le chemin à fournir à partir du fichier HTML:

    • si le fichier affiche.png est enregistré dans le dossier pages, à côté de page1.html, on met la ligne de code suivante : <img src="affiche.png"/>
    • Si l’image se trouve dans le dossier images, et qu’elle s’appelle affiche.png, le chemin est images/affiche.png

    (3) Ajoutez l’affiche à votre page web en ajoutant la balise HTML adéquate.

    Si votre affiche est trop grande, on peut demander au navigateur de réduire sa largeur en pixels (propriété CSS width:300px;)

    (4) Ajouter une déclaration CSS pour les éléments img de la manière suivante:

    • Entre les balise <style> ... </style> du debut du document, ajouter la déclaration:
    img {width: 300px;}

    Lien vers une bande d’annonces

    Nous allons ajouter une image, qui, lorsqu’elle est cliquée, envoie vers la page de la bande d’anonce.

    (1) Rechercher le lien vers la bande d’annonce (Youtube)

    (2) Télécharger l’image ci-dessous, player.png, ou bien concevoir votre propre image à partir de celle-ci

    (3) Placer l’image dans une balise lien <a>

    Le code ressemble à cela :

    <a href="lien_vers_la_video"><img src="lien_vers_image"></a>

    Règles css

    Et si je veux mettre un peu de couleurs ? Le style d’un document est apporté par le langage CSS

    Ok, le rendu précédent n’est pas très fun, c’est le rendu par défaut des différentes balises ; on va donc ajouter des instructions de styles à notre page afin de la personnaliser à notre goût.

    Voici un exemple: copiez le code ci-dessous. Placez le à la fermeture de la balise </head> et avant l’ouverture par la balise <body>

    <style>
    body {	background-color: pink;	}
    
    h1 { color: blue; }
    
    h2 { font-variant: small-caps;
    		color: green;
    		}
    </style>

    Vous devriez obtenir quelque chose approchant…

    Vous pouvez ausi definir des containers et deplacer certains éléments comme vu dans la TP1, la démocratie athénienne ou bien celui-ci: TP1 bis la bataille de Marignan

    Pour aller plus loin…

    Vous avez terminé et c’est validé par votre enseignant ? Vous pouvez :

    • améliorer le style à l’aide de nouvelles règles CSS
    • rajouter des pages à votre site (autre film, 2e volet du film…)

    Vous trouverez de nombreuses références sur les styles sur Internet mais le plus simple sera d’utiliser cette page, ou bien celui-ci très complet: MDN Mozilla

    mon film prefere v2

    Créer une page web sur votre film préféré

    Le but de cet exercice est de réaliser une page HTML de présentation de votre film préféré. Cette page sera simple. On pourra piocher les informations de votre film sur des bases de données en ligne de films telles que IMDb, AlloCiné, Wikipédia…

    L’objectif est de réaliser une page qui pourrait présenter les informations comme ceci:

    Mise en place de l’environnement de travail de notre site web

    Dans un premier temps :

    • dans votre répertoire personnel: créez un dossier appelé web, ou utlisez votre précédent dossier (celui contenant vos autres pages web, réalisées lors des précédentes séances).

    Attention, on prendra soin de ne pas mettre d’espaces et d’accents dans notre arborescence de fichiers et dossiers.

    • Dans le dossier web, créez un nouveau dossier, que vous appelerez pages
    • Dans le dossier pages, créez un nouveau fichier à l’aide de l’editeur Notepad++. Copiez-collez les lignes suivantes:
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8">
    	<title>page principale</title>
    </head>
    <style>
    	/* placer ici vos déclarations CSS*/
    </style>
    <body>
    <!-- le contenu de votre page web. 
    Ceci est un commentaire et peut être effacé.
    -->
    </body>
    </html>
    • Sauvegardez le en l’appelant page1.html

    • Dans le dossier pages, créer un nouveau dossier que vous appelerez images. Placez dans ce dossier les images du film que vous souhaitez afficher dans votre page.

    • Ouvrir le fichier à l’aide d’un navigateur (Mozilla, Edge, …). Rafraichir la page à chaque modification.

    Contenu du fichier

    Rappelez-vous: le contenu de votre document se place entre les balises <body> et </body>. A chaque modification, vous devrez Enregistrer votre document pour que ces modifications soient prises en compte.

    Le document contiendra les éléments suivants:

    Ce document a été réalisé par VOTRE NOM ET PRENOM

    TITRE DU FILM

    Informations générales:

    • Année de Sortie
    • Réalisateur
    • Acteurs Principaux
    • Genre

    Résumé

    Bande-Annonce du Film

    Sources des informations et médias

    Méthode:

    • Ces éléments peuvent être des titres (h1), des sous-titres (h2), … Voir le TP de découverte du HTML.

    • On pourra aussi mettre en évidence, avec la balise <strong>, les différents items de la partie Informations générales.

    • Les éléments de liste peuvent être placés les uns sous les autres, organisés (liste à puce) à l’aide du système d’instructions suivant: (balises ul et li)

    <ul>
        <li>Année de sortie: </li>
        <li>Réalisateur: </h1>
        <li>...</li>
    </ul>
    • Modifiez le texte Ce document a été réalisé par VOTRE NOM ET PRENOM et TITRE DU FILM

    Enregistrez votre travail puis faire F5 dans votre navigateur pour rafraîchir la page. Admirez votre premier travail.

    Compléter les informations

    Des paragraphes

    À l’aide des sites web du début de page, renseignez les différentes informations de la page.

    Méthode: Utilisez les balises <p> ... </p> pour placer des informations dans un paragraphe (par exemple pour le résumé)

    Créer des liens hypertextes

    On l’a vu précédemment, les liens hypertextes sont la base du Web. Voyons comment réaliser ces liens avec du HTML. Un lien permet simplement de se déplacer vers une autre page HTML.

    <a> désigne une ancre, c’est-à-dire un lien vers une cible de destination. Cette balise entoure généralement un mot (une image, un paragraphe, un titre, …) qui devient le texte ‘support du lien’ hypertexte.

    La syntaxe est :

    <a href="adresse_du_lien_hypertexte">support_du_lien</a>

    Dans la partie Sources des informations et médias, ajouter le ou les site·s où vous avez pris vos informations et l’affiche en créant un lien vers le ou les site·s en question.

    Ajouter une image

    (1) Depuis un site web, télécharger le fichier image du film en faisant un clic-droit dessus Enregistrer l’image sous… Enregistrez ce fichier dans le dossier images crée précédemment.

    (2) Nommez cette image affiche.jpg, ou affiche.png ou encore affiche.webp selon le format initial du fichier image.

    Pour ajouter une image dans une page HTML, il faut utiliser la balise

    <img src="image/affiche.png"/>

    chemin vers l’image est le chemin à fournir à partir du fichier HTML:

    • si le fichier affiche.png est enregistré dans le dossier pages, à côté de page1.html, on met la ligne de code suivante : <img src="affiche.png"/>
    • Si l’image se trouve dans le dossier images, et qu’elle s’appelle affiche.png, le chemin est images/affiche.png

    (3) Ajoutez l’affiche à votre page web en ajoutant la balise HTML adéquate.

    Si votre affiche est trop grande, on peut demander au navigateur de réduire sa largeur en pixels (propriété CSS width:300px;)

    (4) Ajouter une déclaration CSS pour les éléments img de la manière suivante:

    • Entre les balise <style> ... </style> du debut du document, ajouter la déclaration:
    img {width: 300px;}

    Lien vers une bande d’annonces

    Nous allons ajouter une image, qui, lorsqu’elle est cliquée, envoie vers la page de la bande d’anonce.

    (1) Rechercher le lien vers la bande d’annonce (Youtube)

    (2) Télécharger l’image ci-dessous, player.png, ou bien concevoir votre propre image à partir de celle-ci

    (3) Placer l’image dans une balise lien <a>

    Le code ressemble à cela :

    <a href="lien_vers_la_video"><img src="lien_vers_image"></a>

    Règles css

    Et si je veux mettre un peu de couleurs ? Le style d’un document est apporté par le langage CSS

    Ok, le rendu précédent n’est pas très fun, c’est le rendu par défaut des différentes balises ; on va donc ajouter des instructions de styles à notre page afin de la personnaliser à notre goût.

    Voici un exemple: copiez le code ci-dessous. Placez le à la fermeture de la balise </head> et avant l’ouverture par la balise <body>

    <style>
    body {	background-color: pink;	}
    
    h1 { color: blue; }
    
    h2 { font-variant: small-caps;
    		color: green;
    		}
    </style>

    Vous devriez obtenir quelque chose approchant…

    Vous pouvez ausi definir des containers et deplacer certains éléments comme vu dans la TP1, la démocratie athénienne ou bien celui-ci: TP1 bis la bataille de Marignan

    Pour aller plus loin…

    Associez votre page à celles déjà réalisées (TP1, TP2), afin de créer un site Web complet.

    • Organisez votre code et vos fichiers et sous-dossiers du projet.
    • Essayez autant que possible d’avoir une présentation homogène pour toutes les pages de votre site.
    • Utiliser une feuille de style pour rassembler toutes les déclarations CSS du site.
    • Ajouter une page pour personnaliser encore plus votre site (vous aimez les voyages, la lecture, la peinture, les jeux videos…), partagez vos goûts ou vos connaissances.

    Vous trouverez de nombreuses références sur les styles sur Internet mais le plus simple sera d’utiliser cette page, ou bien celui-ci très complet: MDN Mozilla

    questionnaire

    Formulaires

    La réalisation d’une enquête de terrain consiste à interroger les usagers au moyen d’un questionnaire.

    But et règlementation

    Lors de la confection du questionnaire, posez-vous au minimum les questions suivantes:

    • quel est le but du questionnaire?
    • quel est le public visé?
    • la collecte des informations personnelles est-elle anonyme?
    • si celle-ci n’est pas anonyme, que prevoyez-vous en regard du RGPD?
    • la collecte des informations, est-elle simple?

    Questionnaire à destination des parents

    Nous prendrons comme exemple le Questionnaire suivant, dont le but est d’établir un profil de la famille et des enfants scolarisés dans une école élémentaire. Ce questionnaire est adressé aux parents:

    • Combien d’enfants avez vous?
    • L’enfant scolarisé dans notre école, s’agit-il d’une fille/d’un garçon?
    • Bénéficie t-il (elle) d’un dispositif particulier (PAP, PAI, …)?
    • Fréquente t-il (elle) l’accueil périscolaire du matin?

    Vous allez adapter ce questionnaire pour le publier en ligne.

    Ce questionnaire est anonyme; la plupart des questions sont de type Question à Choix Multiple, n’autorisant qu’une seule réponse.

    Ce type de questions est à privilégier pour en faciliter l’analyse.

    Framaforms

    Les données relatives aux élèves ou à leurs parents sont des données sensibles qu’il faut protéger. Même si cela peut paraitre tentant d’utiliser les outils de formulaires américains tels que Microsoft et Google, il faut les éviter d’après la CNIL, car non respectueuses du RGPD en raison du «privacy shield» américain.

    Dans ce TP, vous allez devoir créer un compte sur framaforms, une association française qui respecte le RGPD qui s’engage à ne pas vendre vos données ni celles de vos utilisateurs.

    Un tutoriel pour comprendre: docs.framasoft.org

    Conception du formulaire

    Une fois le compte créé, aller dans l’editeur et commencer à concevoir le formulaire.

    • Mettre un titre et un commentaire à partir des informations suivantes:

    Titre du formulaire: Questionnaire à destination des parents

    Description: Madame, Monsieur, chers parents, Dans le cadre de l’auto-évaluation de notre école, nous vous proposons une enquête afin d’établir un profil et de répondre à vos besoins.

    Votre participation à l’enquête est essentielle. Elle est libre et anonyme. Il vous suffit d’indiquer ce que vous pensez des propositions qui suivent.

    Nous vous remercions à l’avance de votre participation.

    L’équipe pédagogique

    • Accès public aux résultats: Choisir Non.
    • En bas de page: Cliquer sur Enregistrer

    • Ajouter votre première liste à puces: haut de page: Formulaire

    • Dans l’onglet Options, modifier les valeurs des boutons.
    • Pour être plus lisible, le champs de réponses peut être placé sur la même ligne que la question.
    • La question suivante pose un problème pour l’analyse des résultats: Votre enfant bénéficie-t-il d’un dispositif?. Le choix Non n’apparait pas.
      • Il faudra d’abord placer une 1ere question: Votre enfant bénéficie-t-il d’un dispositif d’accompagnement?: OUI / NON
      • Puis la question demandant le type de dispositif: (PAI, PAP, UPE2A, ULIS)?
      • Enfin, il faudra lier ces 2 questions: la 2e question ne sera proposée qu’à condition que la réponse précédente est OUI. Cela demande d’ajouter un champ conditionnel
    • La reponse OUI à la première question entraine l’affichage de la 2e:
    choix de la question 1

    choix de la question 1

    choix de la question 2

    choix de la question 2

    • Les questions suivantes sont regroupées dans un même tableau. Pour chaque tableau, on les regoupe dans le même paragraphe du formulaire.

      Choisir: groupe de champs

      Choisir: groupe de champs

    • Puis ajouter les questions dans ce groupe de champs.

    • Vous pouvez alors partager ce formulaire grâce à son adresse. Voir le bouton partager depuis le tableau de bord.

    Liens

    • Questionnaires préparatoires à l’évaluation d’école (documents nationaux) disponibles ci-dessous et sur l’ENT : ac-Lille
    • Concevoir un questionnaire pour une etude de marché: bpifrance-creation.fr
    • Le RGPD appliqué aux enquêtes: guide
    • Exemple de formulaire réalisé à partir des consignes: exemple

    utiliser un tableur

    • selectionner, ordonner, somme avec condition
    • importer un fichier de reponses en format csv, analyse et representations graphiques

    Sous-sections de utiliser un tableur

    tableau de notes

    Tableau de notes

    Tableurs

    Les tableurs sont des logiciels de présentation et de traitement de données.

    les suites Microsoft Office et LibreOffice proposent les mêmes logiciels, mais les formats de fichiers différent.

    Logiciel LibreOffice Extension Microsoft Extension
    Traitement de textes Writer odt Word docx
    Tableur Calc ods Excel xlsx
    Présentations Impress odp PowerPoint pptx

    Les fonctionnalités de ces logiciels sont identiques. Pour les tableurs, la page est un tableau de cellules, repérées par leurs coordonnées (A1, A2, …). La mise en forme du tableau demande une certaine maitrise des différents curseurs.

    Les curseurs pour manipuler les cellules

    Il existe 3 sortes de curseur dans la page: “main”, “croix blanche”, “croix noire”. C’est en faisant glisser celui-ci dans la cellule que l’on peut passer d’un curseur à l’autre.

    Main: déplacer une cellule

    • Ouvrir le logiciel Excel (document vierge). Ecrire Le nom de l’école.
    • Choisir alors le curseur “main” et déplacer la cellule dans A1.

    Croix blanche: sélection étendue

    La croix blanche permet de selectionner plusieurs cellules, ou de selectionner une plage de cellule (utile pour les formules de calcul)

    • Glisser le curseur au centre de la cellule. Lorsque l’on obtient une croix blanche, cliquer-glisser sur plusieurs colonnes pour faire une sélection étendue.

    On peut alors fusionner les cellules: clic droit > format de cellule

    • Cocher la case “fusionner (merge)”. Puis aligner le texte au centre.

    • Compléter alors le tableau selon l’image suivante:

    Croix noire: reproduire une mise en forme

    • Ecrire pour nom du premier élève: Elève 1.
    • Glisser le curseur dans le coin inférieur droit de la cellule pour obtenir une croix noire.
    • cliquer-glisser le long de la colonne, sur 3 lignes.

    Le tableur adapte alors le contenu. Ici, en numérotant les élèves.

    Formules de calcul

    Le traitement des données peut se faire à l’aide de fonctions ou bien de formules mathématiques.

    Avant de commencer, compléter le tableau avec les notes des élèves.

    Fonctions

    Le nom des fonctions peut différer selon les logiciels tableurs utilisés. Il peut être prudent d’utiliser le concepteur de formule (bouton fx).

    Une fois que vous avez saisi = ainsi que les premières lettres de la fonction, le concepteur de formule va vous proposer un choix parmi les fonctions existantes.

    Pour calculer la moyenne de la classe obtenues pour les élèves au devoir 1:

    • dans une cellule de la colonne B (devoir 1), commencer par écrire =
    • Puis la fonction MOYENNE(
    • Ecrire le paramètre entre parenthèses: il faut placer les coordonnées de la plage de valeurs. Avec l’outil de sélection étendue (croix blanche), sélectionner toutes les cellules des devoir 1: B6:B8. Fermer la parenthèse.
    • Modifier le format de cellule pour afficher une valeur arrondie (1 ou 2 chiffres après la virgule): clic droit > Format de cellule

    On devrait obtenir maintenant le tableau suivant:

    • Reproduire la mise en forme dans les cellules voisines: croix noire dans la cellule B9 puis cliquer-glisser jusqu’à devoir 4.

    C’est là l’une des fonctions magiques du logiciel. Observez les paramètres de chacune des fonctions reproduites. Pour le devoir 2, vous devriez voir =MOYENNE(C6:C8). Le logiciel a adapté la mise en forme, dans la nouvelle colonne, à partir de celle adjacente!

    Ecrire une formule

    • La formule non coefficientée, pour l’élève 1 s’écrira:
    $$= (B6/B5+C6/C5+D6/D5+E6/E5) * 20 / 4$$

    Il s’agit de la somme de ses notes, divisée par la somme de la ligne “note sur:” , Le tout, multiplié par 20.

    Pour calculer la moyenne de l’élève 1, après ses 4 devoirs: Dans quelle cellule va t-on placer la formule?

    Saisir cette formule dans la cellule la plus adaptée. Puis modifier le format de cellule pour arrondir à 2 chiffres après la virgule.

    On souhaite reproduire la mise en forme afin de calculer la moyenne pour les autres élèves. Comment va-t-on s’y prendre?

    • Reproduire la mise en forme du calcul de moyenne pour chaque élève. Les résultats vous paraissent-ils cohérents? D’où cela peut-il provenir?

    Nous allons corriger ce problème dans le paragraphe suivant…

    Références relatives ou absolues

    Le problème précédent vient de la manière avec laquelle nous avons écrit les coordonnées de cellules. Le calcul doit être reproduit pour chaque élève, mais avec des coordonnées pour les valeurs note sur: qui doivent rester fixes. Pour cela, à la place d’écrire $= (B6/B5+C6/C5...$ dans la formule de calcul pour l’élève 1, nous allons écrire: = (B6/B$5+C6/C$5...

    Cela ne change rien au calcul de la moyenne de l’élève 1. Par contre, si vous faites une reproduction de la mise en forme pour les autres élèves, leur moyenne est cette fois-ci correctement calculée: La copie de la formule ne modifie pas la reference de cellule de la ligne 5.

    Finir le tableau

    Il vous reste maintenant:

    • à tenir compte des coefficients pour chaque matière. Cela va vous obliger à modifier la formule de calcul de moyenne par élève:

    = (B6/B$5*B$4+C6/C$5*C$4+D6/..*..+E6/..*..) * 20 / (B$4+C$4+D$4+E$4)

    • à ajouter le calcul de la moyenne de la classe pour le trimestre (semestre).

    Complément sur les références absolues

    Les références absolues sont notées avec des $.

    Il est possible de bloquer:

    • La colonne. Exemple: $B6.
    • La ligne. Exemple: B$6.
    • Les deux. Exemple: $B$6.

    Une vidéo pour mieux comprendre: https://www.youtube.com/watch?v=6fMizCr1hpA

    nobels

    Statistiques et prix Nobel

    Le prix Nobel est une récompense de portée internationale. Remis pour la première fois en 1901, les prix sont décernés chaque année à des personnes « ayant apporté le plus grand bénéfice à l’humanité », par leurs inventions, découvertes et améliorations dans différents domaines de la connaissance, par l’œuvre littéraire la plus impressionnante, ou par leur travail en faveur de la paix, suivant ainsi les derniers vœux d’Alfred Nobel, inventeur de la dynamite.

    L’année 2023 a vu une féminisation des lauréats au prix Nobel. Mais depuis sa création, le nombre de femmes primées est-il comparable aux hommes? Faisons le bilan.

    Prix Nobel : une féminisation à tout petit pas - TV5 Monde

    Prix Nobel : une féminisation à tout petit pas - TV5 Monde

    Narges Mohammadi, Claudia Goldin, Anne L’Huillier, Katalin Karikó. Quatre noms de femmes s’ajoutent en 2023 à la liste des “Nobélisé-es”. Un seul en 2024, Han Kang, prix nobel de littérature.

    Fichier de données

    Selon la version Excel installée:

    méthode 1: avec Excel jusqu’à la version 16 (2019), ou bien LibreOffice Calc:

    • Fichier: Importer le fichier de données nobels.csv.

    méthode 2: Excel version plus récente

    • Données: Obtenir des données, puis choisir “à partir d’un fichier”, “fichier text ou csv”, choisir le fichier nobels.csv.

    Dans les 2 cas (méthode 1 ou 2): Bien sélectionner:

    • séparateur par point virgule
    • Origine du fichier: unicode utf-8 afin de bien gérer les caractères avec accents.

    Puis Enregistrer le fichier au format xls (ou xlsx) dans le même répertoire. Maintenant que nous sommes sur un fichier en format tableur, nous pouvons utiliser les fonctionnalités avancées de ce type de logiciel.

    Rechercher et remplacer: (facultatif)

    Commencer par franciser le fichier en utilisant les noms des descripteurs et des prix en français (Physics -> Physique…). Pour cela utiliser la fonction Rechercher et Remplacer(Menu Edition> Rechercher et Remplacer)

    Filtrage des données

    • Selectionner toutes les colonnes du tableau
    • Cliquer sur l’icône en forme d’entonnoir dans le menu du haut. Vous pouvez maintenant cliquer sur les petites flèches à côté des noms des descripteurs pour filtrer les données (ne sélectionner que certaines valeurs), les trier par ordre croissant, ou décroissant.

    Vous obtenez alors une VUE à partir de votre TABLE. C’est à dire un extrait de la table.

    Qu 2a. Quand a été décerné le premier prix Nobel de Littérature? Et d’économie? Combien de lauréats ont reçu un prix Nobel cette année?

    Qu 2b. Combien de femmes ont reçu un prix Nobel? Et d’hommes?

    Qu 2c. Quelle est la discipline dans laquelle les femmes sont les plus représentées? Le moins représentées?

    Qu 2d. Bilan: Quelle est la différence entre FILTRER et TRIER des données? Expliquer le rôle de chacune de ces fonctions en utilisant l’exemple de la Qu 2a. Rechercher le nom des instructions correspondante en langage SQL sur une base de données: Lien 1: order by, Lien 2: where

    Nouveau tableau statistique

    Nous allons maintenant créer un nouveau tableau pour rassembler des statistiques sur le genre des prix Nobel.

    • Rappelez-vous que les formules commencent toujours par un signe =.

    • Pour référencer une cellule on utilise son adresse sous la forme ColonneLigne. Exemple: D2 pour la cellule de la colonne D, ligne 2.

    • On peut référencer une plage de cellule.

      Exemple: D2:D10 pour les cellules D2 à D10 de la feuille.

    Dans une partie libre de la feuille, créer le tableau suivant:

    Nombre de femmes prix nobel Chimie

    Dans la cellule Chimie -> femme, écrire = puis NB.SI.ENS(

    La fonction NB.SI.ENS applique des critères aux cellules de plusieurs plages et compte le nombre de fois où tous les critères sont remplis.

    $$=NB.SI.ENS(plage~critères1; critères1; plage~critères2; critères2…)$$

    Un tutoriel sur la page support.microsoft.com

    Ainsi, pour savoir combien de “femme”-s ont obtenu le prix Nobel de Chimie, il y aura 2 couples plage critère <-> critère:

    • La première plage critère: sélection de la catégorie. B2:B1000
    • Le premier critère: “Chimie” (ou “Chemistry” si le document est resté en anglais)
    • La deuxième plage critère: C2:C1000
    • Le deuxième critère: “femme” (ou “female” si le document est resté en anglais)
    • Exemple: Pour dénombrer le nombre de femmes qui ont reçu le prix nobel de Chimie:
    $$=NB.SI.ENS(B2:B1000;"female";C2:C1000;"Chemistry")$$

    Compléter le tableau

    Pour chacune des cases des colonnes femme et homme, saisir les formules qui donnent les nombre de femmes et d’hommes pour chaque catégorie de prix Nobel. Utiliser la fonction =NB.SI.ENS()

    Totaux

    Dans les colonnes totaux (dernière colonne et dernière ligne), appliquer la fonction SOMME pour ajouter les valeurs sur une même ligne, ou sur une même colonne. support microsoft

    Il est aussi possible d’utiliser une formule utilisant des opérateurs mathématiques (+, -, /, *) sur les cellules: = A1 + A2 par exemple, pour additionner les valeurs des cellules A1 et A2.

    Qu 3a. Compléter les valeurs du tableau dans la feuille de reponse.

    Qu 3b. Calculer dans une cellule de la feuille Excel, la proportion de femmes parmi les nobélisés (pourcentage). Donner le résultat, ainsi que la formule utilisée.

    Graphique

    Sélectionner les données calculées du nouveau tableau de statistiques pour créer un histogramme résumant les données.

    On peut s’aider du tutoriel suivant pour l’affichage d’un histogramme.

    Excel - 1 Basique - Cours Graphique

    Excel - 1 Basique - Cours Graphique

    exemple d'histogramme réalisé sur des valeurs fictives

    exemple d'histogramme réalisé sur des valeurs fictives

    Base de données

    1. Telecharger la base de données sous format SQL: nobels.sql.

    2. Ouvrir dans un nouvel onglet le gestionnaire de bases de données sqliteonline.com.

    3. Depuis le menu du logiciel, faire (+) dans le coin gauche et import. Importer alors le fichier SQL.

    4. Tester alors dans l’editeur les commandes SQL correspondant aux requêtes que vous avez réalisées depuis le tableur.

    Voir cours SQL en ligne.

    analyse graphique

    Partie 1: Traitement de données avec un tableur

    Lors de la seance précédente, vous avez réalisé un questionnaire en ligne. L’interface de framaforms permet de visualiser les réponses, et d’établir des statistiques.

    Mais, les réponses étant accessibles dans un format standard, le fichier de données peut également être ouvert avec un logiciel tableur.

    Soumission et import des résultats du questionnaire

    A l’aide du lien de partage sur votre tableau de bord sur framaforms.org, répondez à votre questionnaire. Répéter l’opération au moins 2 fois. Puis, depuis votre tableau de bord, choisissez le téléchargement en format csv.

    Choisir virgule (,) comme séparateur.

    Dans Composants d’export inclus, choisir les informations à importer. Ne pas choisir celles relatives à l’identité des parents questionnés (formulaire anonyme).

    Télécharger votre fichier.

    Question a: Quelle est l’extension du fichier? Avec quel logiciel (editeur texte) peut on ouvrir et visualiser les données? Donner au moins 2 exemples à partir des logiciels installés sur votre ordinateur.

    Question b: Comment sont organisées les données dans le fichier? Décrire le format des données.

    Pour la suite de la séance, nous allons prendre le fichier suivant, resultats.csv pour analyse.

    Vous allez réaliser un premier travail de mise en forme des données avant leur représentation graphique.

    Mise en forme des données sous Excel

    • Télécharger le ficher, resultats.csv, et l’ouvrir avec Excel (ou bien LibreOffice Calc) comme vu dans le TP sur le format des données.

    • Enregistrer le fichier au format xls dans le même répertoire. Attention, Sans cette manipulation, csv -> xls, vous risquez de perdre vos travaux sur ce fichier.

    Maintenant que nous sommes sur un fichier tableur d’extension xls, nous pouvons utiliser les fonctionnalités avancées de ce type de logiciel.

    Question c: Combien de réponses au formulaire sont présentées dans le tableau?

    Question d: Combien de questions comporte le formulaire?

    Utiliser la fonction nb.si

    Pour compter le nombre de “Oui” dans une colonne, utiliser la fonction NB.SI

    • Pour compter le nombre d’élèves qui fréquentent la cantine: Ecrire sous la colonne Cantine:
    $$=NB.SI(plagedonnees;"Oui")$$
    selection de la plage de données (en pointillés bleus) après avoir écrit =NB.SI(

    selection de la plage de données (en pointillés bleus) après avoir écrit =NB.SI(

    Un tutoriel sur la page support.microsoft.com

    • Plage données correspond alors à C1:C50 si la colonne C est celle de cantine (Et que le tableau contient 50 lignes)
    • On peut aussi, de la même manière, compter le nombre de “Non”.

    Question e: Quelle formule Excel donne le nombre de “Oui” pour la colonne cantine? Quelle formule donne le nombre de “Non”?

    Utiliser la fonction nb.si.ens

    La fonction NB.SI.ENS applique les critères aux cellules de plusieurs plages et compte le nombre de fois où tous les critères sont remplis.

    $$NB.SI.ENS(plage~critères1; critères1; plage~critères2; critères2…)$$

    Un tutoriel sur la page support.microsoft.com

    Ainsi, pour savoir combien d’élèves de “CP” déjeunent à la cantine, il y aura 2 couples plage critère <-> critère:

    • La première plage critère: sélection de la classe. B1:B50 si la colonne B correspond à la classe. Et que 50 lignes sont renseignées.
    • Le premier critère: “CP”
    • La deuxième plage critère: C1:C50
    • Le deuxième critère: “Oui”

    Question f: Quelle est alors la formule utilisée dans la cellule du tableur?

    Partie 2: Etude statistique

    Tableau statistique à 2 entrées

    Cette deuxième partie demande une nouvelle présentation des données.

    Vous allez créer 2 nouvelles tables à partir des résultats bruts:

    • Une table donnant les effectifs cantine, suivi périscolaire:
    • Une table donnant une information sur la qualité d’accueil

    Les valeurs sont indicatives. Celles affichées dans chacune de vos tables doivent être calculées à partir du fichier .csv fourni, à l’aide des formules nb.si et nb.si.ens vues dans la partie 1.

    Completer la fiche reponse: tableau

    Graphiques, histogrammes

    Il est conseillé de suivre le tutoriel suivant pour l’affichage des graphiques.

    Excel - 1 Basique - Cours Graphique

    Excel - 1 Basique - Cours Graphique

    Obtenir les graphiques suivants (les valeurs ont été modifiées pour le tracé et ne correspondent pas au tableau fourni):

    graphique 1

    graphique 1

    graphique 2

    graphique 2

    Lequel de ces graphiques répond à la question:

    • A. Quelle est la distribution de reponses des élèves de CP à propos de la qualité de la cantine?
    • B. Quelle distribution en age ou classe des élèves repond favorablement à la question sur la qualité de la cantine?

    Etablir un diagnostic à propos de cette enquête. (max 5 lignes)

    Sous-sections de dessiner

    Selectionner une forme, retirer le fond avec Gimp

    image à telecharger

    image à telecharger

    selectionner l'outil BAGUETTE MAGIQUE et cliquer dans la zone blanche de l'image

    selectionner l'outil BAGUETTE MAGIQUE et cliquer dans la zone blanche de l'image

    Choisir: SELECTION: inverser la selection

    Choisir: SELECTION: inverser la selection

    Calque: Masque: Ajouter un masque de calque

    Calque: Masque: Ajouter un masque de calque

    Choisir: SELECTION

    Choisir: SELECTION

    Vous obtenez alors un calque détouré

    Vous obtenez alors un calque détouré

    analyser

    • Tableur Excel Construire une formule de calcul de moyenne Fonction somme Pour programmer la fonction SOMME sur les valeurs d’une colonne du tableau Voici un lien vers le tuto de microsoft office. cliquer dans la cellule juste sous la dernière valeur de la colonne. Ecrire debut de la formule (bien commencer la ligne par le signe =): = SOMME( puis faire une sélection étendue de toutes les valeurs de la colonne. (voir image ci-dessous) Valider avec la touche Entrer Compter le nombre de cellules Pour compter le nombre de valeurs dans le tableau, utiliser la fonction NOMBRE
    • Tracé d’un histogramme avec Excel Un histogramme donne une représentation d’un tableau avec des effectifs, de manière très visuelle. Cela facilité grandement l’interprétation. Dans une feuille du tableur Excel: Placer dans une première ligne les etiquettes des colonnes (par exemple, renseigner le nom des matières) Placer juste au dessous les effectifs correspondant (par exemple, la matière préférée) Selectionner ensuite l’emplacement des données (ne pas prendre la première colonne, qui constitue le titre).
    • Recherche de corrélations Principe La recherche de correlations entre valeur d’un tableau consiste à identifier des colonnes qui semblent être interdépendantes. On doit commencer par rassembler les données dans une même table, où les réponses d’une même personne sont rassemblées dans une même ligne.
    • stats sur l’ensemble des matchs Nice Marseille en Ligue 1, Excel
    • data.gouv Le site data.gouv.fr est la plateforme des données publiques françaises. Nous allons consulter les données du Répertoire National des Élus (RNE). Celui-ci a pour finalité le suivi des titulaires d’un mandat électoral. Il est renseigné et tenu à jour par les préfectures et les services du ministère de l’intérieur. Rendez vous à la page de consultation du RNE.
    • Utilisation de la base de données Ouvrir la base de données Aller sur la page Exoplanet.eu Pour consulter la base de données de toutes les planetes observées, cliquer sur Tous les catalogues. accès à la base de données

    Sous-sections de analyser

    somme et moyenne sur Excel

    Tableur Excel

    Construire une formule de calcul de moyenne

    Fonction somme

    Pour programmer la fonction SOMME sur les valeurs d’une colonne du tableau

    Voici un lien vers le tuto de microsoft office.

    • cliquer dans la cellule juste sous la dernière valeur de la colonne.
    • Ecrire debut de la formule (bien commencer la ligne par le signe =): = SOMME(
    • puis faire une sélection étendue de toutes les valeurs de la colonne. (voir image ci-dessous)
    • Valider avec la touche Entrer

    Compter le nombre de cellules

    Pour compter le nombre de valeurs dans le tableau, utiliser la fonction NOMBRE

    Voir ici la liste de fonctions excel possibles

    • cliquer dans une cellule vide de la colonne.
    • Ecrire debut de la formule (bien commencer la ligne par le signe =): = NOMBRE(
    • puis faire une sélection étendue de toutes les valeurs de la colonne.
    • Valider avec la touche Entrer

    Calculer la moyenne

    La moyenne des valeurs se calcule en divisant le résultat de SOMME par celui de NOMBRE.

    Supposons que la somme se trouve dans la cellule D18, et le nombre dans D19, alors il faudra calculer avec la formule:

    =D18/D19

    Placer cette formule dans une cellule libre de la feuille de calcul, si possible sous les autres valeurs

    Cette formule est DYNAMIQUE: si vous modifiez une valeur dans le tableau, tout est recalculé. Vous avez créé une tâche AUTOMATISEE.

    tracé d'un histogramme

    Tracé d’un histogramme avec Excel

    Un histogramme donne une représentation d’un tableau avec des effectifs, de manière très visuelle. Cela facilité grandement l’interprétation.

    Dans une feuille du tableur Excel:

    • Placer dans une première ligne les etiquettes des colonnes (par exemple, renseigner le nom des matières)
    • Placer juste au dessous les effectifs correspondant (par exemple, la matière préférée)

    Selectionner ensuite l’emplacement des données (ne pas prendre la première colonne, qui constitue le titre).

    Dans le menu INSERTION (1), choisir HISTOGRAMME 2D(2). Prendre le premier histogramme proposé (en haut à gauche).

    Vous devriez obtenir un diagramme de frequence en batons (un histogramme).

    recherche de correlations

    Recherche de corrélations

    Principe

    La recherche de correlations entre valeur d’un tableau consiste à identifier des colonnes qui semblent être interdépendantes.

    On doit commencer par rassembler les données dans une même table, où les réponses d’une même personne sont rassemblées dans une même ligne.

    Puis on fait des hypothèses sur ce qui pourrait montrer une interdépendance:

    • Exemple: il y a peut être un lien entre la durée du trajet scolaire, et l’avance avant le début des cours.
    • Contre exemple: il y a peu de chances de trouver une corrélation entre l’âge et la durée du trajet scolaire.

    On selectionne alors les colonnes de la table qui sont probablement corrélées. On les porte comme axes X et Y dans un graphique. Puis on place les points pour chaque élève:

    La corrélation peut montrer un regroupement de points

    source: appendre le machine learning en une semaine, G. Saint-Cirgue

    source: appendre le machine learning en une semaine, G. Saint-Cirgue

    Cela peut être aussi un alignement sur une droite, ou une courbe.

    source: appendre le machine learning en une semaine, G. Saint-Cirgue

    source: appendre le machine learning en une semaine, G. Saint-Cirgue

    En pratique

    A l’aide du logiciel Excel:

    • importer les données à partir des fonctionnalités du logiciel (faites-vous aider par le professeur).
    • (1): selectionner les 2 colonnes de données. Celles-ci doivent être côte à côte dans le tableau, sinon, déplacer les colonnes.
    • (2): menu INSERTION
    • (3): choisir graphique > nuage de points

    Analyser et conclure

    matchs OM Nice

    Matchs de Football Nice - Marseille

    Le fichier suivant rescence tous les matchs de football de Ligue 1 depuis 2002.

    Il s’agit d’un document tenu à jour sur le site L’Equipe.

    Les fichier à télecharger:

    Vous aurez besoin pour mener à bien ce travail pratique de revoir:

    Comprendre les descripteurs du tableau

    1. Noter sur la fiche reponse le nom de ces descripteurs

    2. Ecrire la plage des cellules contenant des valeurs pour chacun de ces descripteurs, sous la forme cellule depart : cellule arrivée

    Exemple : Les valeurs du descripteur Ligue sont sur la plage A2:A7221

    3. Comment peut-on savoir, en lisant le tableau, quelle est l’équipe qui joue son match à domicile?

    4. Retrouver, en parcourant le tableau, les dates des matchs Nice - Marseille (Nice reçoit à domicile) lors des saisons 2002-2003 et 2003-2004.
    Compter le nombre de victoires de Nice sur ces 2 matchs.

    5. Compter le nombre de matchs Nice-Marseille:

    • Utiliser la colonne de descripteur equipe_domicile. Utiliser une cellule à la suite du tableau, après la ligne 7221. Dans cette cellule, écrire = NB.SI.ENS(
    • Avec l’outil d’aide : compléter les champs pour faire la somme de tous les matchs tels que:
      • equipe_domicile = “Nice”
      • equipe_exterieur = “Marseille”

    Ce qui signifie que vous devrez remplir:

    • Plage_critères1: F2:F7221
    • Critères1: “Nice”
    • …

    6. Calculer le score moyen entre ces 2 équipes.
    Pour faire ceci:

    • Utiliser la colonne de descripteur score_domicile. Utiliser une cellule à la suite du tableau, après la ligne 7221. Dans cette cellule, écrire = SOMME.SI.ENS(

    • Avec l’outil d’aide : compléter les champs pour faire la somme de tous les buts marqués par Nice lorsque l’équipe reçoit Marseille. C’est à dire, lorsque:

      • critère 1: equipe_domicile = “Nice”
      • critère 2: equipe_exterieur = “Marseille”
      • somme_plage: celle de score_domicile
    • Faire de même pour les buts marqués par Marseille, en utilisant la colonne sous score_exterieur

    • Enfin: sous le score moyen de Nice: écrire une formule qui calcule le nombre moyen de buts marqués par Nice

    • Faire de même avec Marseille puis compléter le tableau des scores sur votre feuille de reponse.

    data.gouv maires de France

    data.gouv

    Le site data.gouv.fr est la plateforme des données publiques françaises.

    Nous allons consulter les données du Répertoire National des Élus (RNE). Celui-ci a pour finalité le suivi des titulaires d’un mandat électoral. Il est renseigné et tenu à jour par les préfectures et les services du ministère de l’intérieur.

    Rendez vous à la page de consultation du RNE.

    En bas de page, trouver la rubrique elus-maires-mai.csv. Cliquer sur le bouton pour telecharger le document.

    Lancer le logiciel Excel. Ouvrir un nouveau classeur, vide.

    L’ouverture du fichier va se faire à partir du bandeau Données: Chercher ensuite le bouton importer un fichier texte ou csv. Puis selectionner le fichier.

    Exemple d'import d'un fichier .csv depuis le bandeau Données

    Exemple d'import d'un fichier .csv depuis le bandeau Données

    A l’ouverture du fichier, dans la boite de dialogue, il faudra paramétrer:

    • l’encodage des caractères (page 1)
    dans la page 1, rechercher le menu sur l'encodage des caractères

    dans la page 1, rechercher le menu sur l'encodage des caractères

    menu deroulant proposant l'encodage des caractères

    menu deroulant proposant l'encodage des caractères

    • la tabulation avec pour separateur le point virgule ; (page 2)

    Le paramètre semicolon (point virgule) précise le caractère séparateur.

    le format a été correctement renseigné

    le format a été correctement renseigné

    Traitement du fichier

    Le fichier contient des informations basiques sur tous les maires des communes de France. Cela fait un très grand nombre de lignes…

    Commençons par reduire l’affichage aux seuls maires du departement 06:

    Si la feuille de calcul ne présente pas de filtres en tête de colonnes:

    • Commencer par selectionner toutes les colonnes A, B, C, D, E dans laquelles se trouvent les données du tableau.
    • Dans le bandeau Données, choisir Filtrer (entonoir).

    Il apparait alors des listes de choix au dessus des descripteurs du tableau. Pour filtrer selon l’un des descripteurs, cliquer sur l’une de ces listes de choix. Celle du Code du departement… et choisir 6

    Calculons alors le nombre de maire de sexe feminin.

    Dans le classeur, sous le tableau, utiliser l’une des cellules pour placer le calcul du nombre de maires dont le Code sexe est “F”.

    Vous allez utiliser pour cela la fonction NB.SI (voir Notice sur support.microsoft.com)

    Dans une cellule juste dessous, faire de même pour le nombre de maires de sexe “M”.

    Sélectionner ensuite ces 2 cellules et insérer un diagramme circulaire: (dans le bandeau INSERTION)

    diagramme circulaire dans le bandeau INSERTION

    diagramme circulaire dans le bandeau INSERTION

    La proportion joue clairement en faveur des maires de sexe masculin…

    un joli camembert

    un joli camembert

    Suite

    Rechercher un autre departement pour lequel la parité est mieux respectée…

    tableur sur calcu TI83

    Utilisation de la base de données

    Ouvrir la base de données

    Aller sur la page Exoplanet.eu Pour consulter la base de données de toutes les planetes observées, cliquer sur Tous les catalogues.

    accès à la base de données

    accès à la base de données

    Le tableau donne les caractéristiques connues pour ces planètes. Leur nombre est gigantesque. Vous allez utiliser les formules de filtre pour en selectionner quelques unes.

    Filtrer

    Par exemple, si l’on cherche à étudier les seules planètes telluriques, on choisira celles dont le rayon est un peu supérieur ou un peu inférieur à celui de la Terre.

    D’après le tableau comparatif des planètes du système solaire

    $$mass:mjup = 0.00315$$
    • 1/317 = 0.00315
    • mass = masse Terre
    • mjup = masse Jupiter
    • masse:mjup = masse de la Terre rapporté à celle de Jupiter

    On pourrait donc selectionner uniquement les planètes dont la masse (rapporté à celle de Jupiter) est comprise entre 0.001 et 0.004, soit:

    $$mass{:}mjup > 0.001 ~AND ~mass{:}mjup < 0.004$$

    A vous de jouer:

    1. Dans la barre de formule, vous écrirez la relation qui permettra de filtrer les planètes, et conserver celles dont les masses sont comprises entre 0.001 et 0.004 fois celle de Jupiter.
    2. Ajouter aussi un filtre sur le rayon: $$radius{:}rjup < 0.1$$
    appliquer un filtre sur la base de données

    appliquer un filtre sur la base de données

    Loi de régréssion linéaire

    Entrer les données dans un tableau

    On cherche maintenant une loi entre les grandeurs mass et radius pour ces planètes. Le modèle mathematique possible est le suivant:

    $$\rho= \tfrac{mass{:}rjup}{(radius{:}rjup)^3}$$

    Soit: la masse volumique relative à celle de Jupiter est égale à sa masse relative, divisée par son rayon relatif, à la puissance 3.

    Entrer les données dans un tableur:

    • Sur votre calculatrice Ti-83, commencer par effacer les listes: appuyer sur 2nde + pour accéder au menu mém.
    • Choisir 4:EffTtesListes
    • Appuyer sur le bouton stats puis 1:Modifier.
    • Entrer alors les données issues de la base de données: celle correspondant à mass dans L1 et celles correspondant à radius dans L2
    • Ajouter en dernière entrée la valeur 0 dans chacune des 2 colonnes (une planète de rayon 0 aura aussi une masse de 0…)
    • Quitter alors le tableur: 2nde mode ce qui correspond à quitter.
    • Dans la fenêtre de calcul, saisir: L2^3 puis touche STO → et L3 pour obtenir: $$L2^3 \rightarrow L3$$

    Si vous revenez sur la fenêtre d’edition du tableau, celui-ci devrait ressembler à ceci:

    fenêtre tableur de la Ti-83

    fenêtre tableur de la Ti-83

    Afficher le nuage de points

    • Sur votre calculatrice Ti-83, choisir les listes de valeurs: faire 2nde f(x), ce qui correspond à graph stat. Choisir 1:Graph1...Aff puis: * Aff * Type: le nuage de points * XListe : L3 * YListe : L1
    selection des séries L1 et L3 pour X et Y

    selection des séries L1 et L3 pour X et Y

    • Réglage des axes: bouton fenêtre. Choisir: * Xmin=0 * Xmax=0.001 * Ymin=0 * Ymax=0.005
    Réglage des axes

    Réglage des axes

    • Appuyer alors sur le bouton graphe pour visualiser la distribution de points.

    Régréssion linéaire

    • Appuyer sur le bouton stats, puis menu CALC
    • Choisir 4:RégLin(ax+b)
      • Xliste: L3
      • Yliste: L1
      • puis descendre et appuyer sur calculer en bas de la fenêtre

    Recopier alors le coefficient obtenu pour a. Celui-ci représente la masse volumique relative d’une planète tellurique moyenne, rapportée à celle de Jupiter (1,3g.cm-3).

    Prolongement

    On pourra faire ce même travail pour une série de planètes gazeuses. Il faudra cette fois choisir des planètes dont les masses et les rayons sont proches de ceux de Jupiter. Par exemple (vous pouvez tester d’autres combinaisons):

    mass:mjup> 0.7 and mass:mjup <1.5 AND radius:rjup>0.7

    Choisir alors les 10 premières lignes du tableau (il devrait y en avoir plus d’une centaine…). Et faire le même travail que pour les planetes telluriques:

    • effacer les listes
    • remplir les listes L1 et L2 avec les valeurs de mass et de radius.
    • Calculer les valeurs de la liste $L_3 = L_2^3$
    • tracer la courbe L1 en fonction de L3
    • Obtenir les coefficients de la regression linéaire pour cette distribution de points.

    liens

    • Les planètes telluriques et gazeuses diffèrent grandement par leur densité, comme on peut le voir sur le dossier suivant: futura-sciences

    • Exoplanète : première mesure de la densité d’une très jeune planète avec SPIRou: article du CNRS.fr

    • Modeliser, simuler: POST

    Sous-sections de programmer

    de scratch à python

    TP1: de scratch à python

    Aller sur l’interface de programmation python du site Vittascience

    Partie 1: Premier programme

    BUT:

    créer un programme qui demande à l’utilisateur son nom, et lui affiche un message de bienvenue.

    VARIABLES:

    le programme utilise les variables:

    • nom, de type texte. Contient le nom renseigné par l’utilisateur
    • debut, de type texte. Contient le mot: “Bonjour "
    • message, de type texte, contient debut + nom

    On rappelle qu’une variable, c’est un nom qui fait référence à une valeur stockée dans un espace de la mémoire. Exemple:

    Le nom de variable

    Le nom de variable

    ECRIRE LE PROGRAMME:

    Dans la fenêtre SCRATCH, on a un seul bloc de code:

    • Dans la rubrique AFFICHAGE: selectionner et glisser l’instruction: demander un texte à l’utilisateur.

    Comme cette instruction n’est pas complète, elle ne peut pas constituer un bloc de code. Il faut ajouter une affectation.

    • Dans la rubrique VARIABLE: cliquer sur Créer une variable. Nommer celle-ci nom
    • Rubrique VARIABLES: selectionner et glisser: Affecter à nom la valeur " ".
      Puis mettre l’instruction demander un texte à l’utilisateur, et coller les 2 blocs de code.
    • Rubrique VARIABLES: Créer une nouvelle variable debut. Selectionner et glisser: Affecter à debut la valeur " ".
      Ecrire "Bonjour "à la place de " ".
    • Rubrique VARIABLES: créer une nouvelle variable message.

    • Rubrique MATH: choisir le premier élément, celui qui permet une addition

    A l’aide des variables debut et nom, vous allez construire l’instruction complète: Affecter à message la valeur debut + nom

    Vous trouverez les éléments debut et nom dans la rubrique VARIABLES:

    Compléter alors l’instruction pour obtenir:

    • Mettre à la suite les blocs de code pour former le programme:
    • Mettez vous maintenant dans la peau de l’utilisateur: Executer le programme (bouton du haut >) Et repondre à la question dans le shell, sous la fenêtre d’edition.

    Sur votre cahier, recopier le script python correspondant. Et répondre aux questions:

    1. Quelle instruction en python permet de demander à l’utilisateur d’entrer une valeur ou un texte?
    2. Quelle instruction python permet d’afficher :
    • un texte?
    • le contenu d’une variable?
    1. Quelle instruction en python permet d’affecter le texte “bonjour” à la variable “debut”?

    Partie 2: programmer une fonction

    But: remplacer les entrées demander à et sortie afficher par des paramètres de fonction

    Ecrire le programme

    • Supprimer le premier bloc du programme précédent (Affecter à nom la valeur demander…)
    • Rubrique FONCTIONS: Choisir le 2e bloc, Définir nom_de_la_fonction avec l’option retour.
      • modifier le nom_de_la_fonction: mettre salutation comme nouveau nom
      • Bouton (+): ajouter le paramètre nom

    Votre fonction est vide et ne contient pas encore d’instruction.

    • Mettre le bloc du programme précédent dans la fonction:
    • Supprimer la dernière ligne afficher message.
    • Dans l’espace vide après retour : mettre la variable message pour que celle-ci s’affiche lorsque l’on appelle la fonction:
    • Executer le programme (bouton du haut >)
      En apparence, il ne se passe rien, mais vous avez quand même chargé la fonction en mémoire.
    • Dans le shell (partie inférieure de la fenêtre), après les chevrons >>>, saisir l’instruction qui va appeler votre fonction:
    >>> salutation("votre nom")

    Modifier votre nom par votre veritable nom…

    Sur votre cahier, recopier le script python correspondant. Et répondre aux questions: Dans le script python: …

    1. Quelle partie du programme associe votre nom à la variable nom?
    2. Quelle partie du programme affiche le contenu du message?
    3. Comment sont mises les instructions du bloc de code dans la fonction?
    4. Comment faut-il faire pour appeler la fonction et déclencher son execution?
    5. Quel est l’avantage d’utiliser une fonction plutôt que le script de la partie 1?

    Utiliser la calculatrice TI-83 Premium CE edition Python

    • S’il vous reste du temps, recopiez ce programme dans l’environnement python de la calculatrice. Executez le.

    technologies

    • Ti83 prise en main mettre a jour et tester les scripts python sur la calculatrice Ti83 et mise a niveau microbit mettre a jour charger les modules pour la connexion de la carte microbit avec la calculatrice TI83 Ti83 microbit prise en main tester la connexion de la carte microbit avec la calculatrice TI83 Loi de Mariotte TP utilisant la calculatrice TI83, l’extension avec la carte microbit et le dispositif de mesure de pression volume
    • informatique des objets presentation de la carte microbit capteurs integres capteurs de la carte microbit niveau a bulles microbit capteur de direction, inclinaison, jeu du snake MB grove shield groove, capteurs passifs MB LED clignotante shield groove, circuit electronique a LED MB diviseur de tension microbit CTN et pont diviseur de tension, capteur photosensible Capteur lumiere capteur integre, mesure et detection de clarté obscurité, chaine de caracteres MB sons jouer des sons avec le HP de la carte microbit mesure de c du son microcontroleur microbit avec extension ultrasons pour effectuer les mesures et traitement python portes logiques etude des portes logiques en circuit integré, branchements sur la carte microbit loi de Mariotte mesure dispositif, copie des valeurs depuis REPL et traitement python reseau radio SNT decouverte et programmation de la carte microbit, fonction radio reseau radio 1ere programmation de la carte microbit, fonction radio, niveau 1ere NSI reseau radio term sequence reseau de niveau terminale NSI Chiffrement TP chiffrement a partir d’un reseau de cartes microbits communiquant par radio, niveau term NSI

    Sous-sections de technologies

    Sous-sections de Texas instruments

    Ti83 prise en main

    Mettre à jour la calculatrice TI-83 Premium CE

    Installer TI CONNECT sur votre ordinateur

    page Produits du site

    page Produits du site

    Cliquez sur l’onglet Mises à jour et logiciels et choisir Logiciel Ti-connect

    Télécharger le logiciel Ti-Connect le plus récent

    Télécharger le logiciel Ti-Connect le plus récent

    Choisir la bonne version du logiciel et installez le logiciel TI CONNECT sur votre ordinateur: Executer le fichier téléchargé et suivre les instructions d’installation.

    Mettre à jour la calculatrice

    Revenir sur la page Produits du site.

    page Produits du site

    page Produits du site

    Cliquer sur l’onglet Mises à jour et logiciels et choisir Mise à jour de la TI-83 Premium CE

    Cliquer sur le bouton télécharger. Choisir alors le modèle de la calculatrice: Ti-83 Premium CE Edition Python.

    Choisissez le modèle de votre calculatrice

    Choisissez le modèle de votre calculatrice

    Au bas de la page, choisissez Télécharger le bundle (OS + applications):

    Télécharger le système d'exploitation le plus récent pour votre calculatrice

    Télécharger le système d'exploitation le plus récent pour votre calculatrice

    • Lancer le logiciel TI CONNECT et brancher la calculatrice sur le port USB de votre ordinateur (cable USB vers usb B fourni).
    connexion calculatrice - ordinateur

    connexion calculatrice - ordinateur

    • Cliquer sur
    1. l’explorateur de calculatrice (1),
    2. puis sur ajouter les données de l’ordinateur vers la calculatrice connectée (2).

    explorateur de calculatrice sur TI CONNECT

    explorateur de calculatrice sur TI CONNECT

    L’explorateur de votre ordinateur devrait vous permettre de retrouver le fichier TI83CEBundle-5.8.0.22.b83 (la version peut différer au moment de votre téléchargement).

    • Sélectionner le fichier.

    • Suivre les instructions d’installation.

    Testez votre premier script Python

    video Yvan Monka Ti83

    Video Yvan Monka: prise en main de la Ti83 Ed python

    Utiliser des extensions

    Modules python

    On pourra ajouter des modules pour:

    • utiliser turtle python
    • représenter des vecteurs
    • réaliser des diagrammes en barre ou en boîte à moustache.

    Lien vers la page de téléchargement des modules

    Exemple de modules au moment de la redaction

    Exemple de modules au moment de la redaction

    Pour le module CE_Turtle:

    page de téléchargement du module Turtle

    page de téléchargement du module Turtle

    • Cliquer sur le bouton télécharger. Dezziper le fichier. Installer les 2 fichiers (GRID.8xv et TURTLE.8xv) dans la calculatrice (voir plus loin)
    • Le dossier contient aussi le guide de démarrage

    Le fichier devrait alors se trouver dans votre dossier téléchargements.

    Téléverser les modules dans la calculatrice

    • Lancer le logiciel TI CONNECT et brancher la calculatrice sur le port USB de votre ordinateur (cable USB vers usb B fourni).

    connexion calculatrice - ordinateur

    connexion calculatrice - ordinateur

    Suivre la même procédure que pour la mise à jour de la calculatrice: Cliquer sur ajouter les données de l’ordinateur à la calculatrice connectée. Et ajouter le module à installer.

    Module microbit

    Depuis la page de téléchargement des modules :

    Répéter la même procédure que pour le module Turtle. Installer cette fois le module microbit.

    Dezipper les fichiers:

    Les fichiers devront cette fois être installé:

    • sur la calculatrice (les 2 fichiers .tns)
    • et sur la carte microbit (le fichier runtime.hex)

    Liens

    • Prise en main de la calculatrice et autres tips: letutosmaths
    • Prise en main du module Python sur la calculatrice TI-83 avec Ti codes
    • Chaine Youtube de Yvan Monka du site www.maths-et-tiques.fr: Lien
    • Chaine Youtube pour pour utiliser la calculatrice TI-83 Premium CE Python avec le microcontrôleur micro:bit : lien

    Ti83 et mise a niveau microbit

    Mettre à jour la calculatrice TI-83 Premium CE

    Installer TI CONNECT sur votre ordinateur

    Choisissez le modèle de votre calculatrice

    Choisissez le modèle de votre calculatrice

    Cliquez sur le bouton Suivant.

    Télécharger le logiciel Ti-Connect le plus récent

    Télécharger le logiciel Ti-Connect le plus récent

    Installez alors le logiciel TI CONNECT sur votre ordinateur: Executer le fichier téléchargé et suivre les instructions d’installation.

    Mettre à jour la calculatrice

    Sur la même page du site Texas-Instruments:

    Télécharger le système d'exploitation le plus récent pour votre calculatrice

    Télécharger le système d'exploitation le plus récent pour votre calculatrice

    • Lancer le logiciel TI CONNECT et brancher la calculatrice sur le port USB de votre ordinateur (cable USB vers usb B fourni).
    connexion calculatrice - ordinateur

    connexion calculatrice - ordinateur

    • Cliquer sur
    1. l’explorateur de calculatrice (1),
    2. puis sur ajouter les données de l’ordinateur vers la calculatrice connectée (2).

    explorateur de calculatrice sur TI CONNECT

    explorateur de calculatrice sur TI CONNECT

    L’explorateur de votre ordinateur devrait vous permettre de retrouver le fichier TI83CEBundle-5.5.2.44.b83 (la version peut différer au moment de votre téléchargement).

    • Sélectionner le fichier.

    • Suivre les instructions d’installation.

    Testez votre premier script Python

    video Yvan Monka Ti83

    Video Yvan Monka: prise en main de la Ti83 Ed python

    Utiliser des extensions

    Préparer la calculatrice pour utiliser la carte micro:bit

    TI83 et microbit

    Ti-83 Premium CE Python et micro:bit

    Télécharger les modules

    Se rendre du la page de téléchargement du site Texas Instrument: Lien

    Vous pouvez télécharger l’ensemble de ces fichiers, en un seul clic, depuis la page du site Texas instruments

    Téléchargez le dossier “modules_microbit V1.zip” ou “modules_microbit V2.zip” selon le modèle de carte dont vous disposez

    Ceux-ci devraient se trouver dans votre dossier téléchargements.

    Téléverser les modules dans la calculatrice

    • Lancer le logiciel TI CONNECT et brancher la calculatrice sur le port USB de votre ordinateur (cable USB vers usb B fourni).

    connexion calculatrice - ordinateur

    connexion calculatrice - ordinateur

    Suivre la même procédure que pour la mise à jour de la calculatrice: Cliquer sur ajouter les données de l’ordinateur à la calculatrice connectée. Et sélectionner en une seule fois tous les modules à installer:

    • MICROBIT.8xv
    • MB_GROVE.8xv
    • MB_SENSR.8xv
    • MB_RADIO.8xv
    • MB_PINS.8xv
    • MB_BUTNS.8xv
    • MB_DISP.8xv
    • …

    Liens

    • Prise en main de la calculatrice et autres tips: letutosmaths
    • Prise en main du module Python sur la calculatrice TI-83 avec Ti codes
    • Chaine Youtube de Yvan Monka du site www.maths-et-tiques.fr: Lien
    • Chaine Youtube pour pour utiliser la calculatrice TI-83 Premium CE Python avec le microcontrôleur micro:bit : lien

    Ti83 microbit prise en main

    La carte micro:bit peut être programmée à partir de la calculatrice TI-83 edition python. La programmation se fait en langage Python.

    Préparer le matériel

    Commencer par mettre à jour la calculatrice TI-83 Premium CE edition Python. Voir la fiche explicative. Téléchargez également tous les modules necessaires pour piloter la carte microbit, avec la calculatrice. Voir fiche.

    Puis changer de cable pour brancher la carte micro:bit sur l’ordinateur (cable USB: ordinateur vers micro usb B : microbit).

    Télécharger le fichier sur votre ordinateur:

    ti_runtime_1.0.0.hex ti_runtime_2.0.0.hex Puis, à l’aide de l’explorateur windows, glisser-déposer ce fichier vers la carte micro:bit.

    Premier script

    le module Python

    Ecriture du premier programme:

    • Bouton prgm : Choisir 2:Python App
    • la fenêtre du shell Python s’ouvre alors. Vous pouvez selectionner l’une des options du menu en bas de l’écran à l’aide des touches f(x), fenêtre, … Ici, vous allez choisir Nouveau.
    • Saisir le nom de votre premier programme puis valider (par exemple MBINIT puisque vous demarrez un premier script d’initiation à la carte microbit).
    • Pour importer la librairie microbit dans votre programme, aller dans le catalogue pour selectionner l’instruction from SCRIPT import *: Faire 2nde 0 qui lance le menu catalogue, puis la touche alpha et F. Selectionner la ligne from SCRIPT import *
    • ecrire le nom du module microbit à la place du mot SCRIPT

    A partir de maintenant, les autres modules relatifs à la carte micro:bit seront ensuite appelés à partir du menu « microbit » qui vient d’être rajouté dans les modules.

    Saisir le script

    A la ligne suivante de votre script, vous allez ajouter la librairie qui pilote l’affichage de la carte micro:bit:

    • menu du bas de la fenêtre Fns: Selectionner le menu Module en vous deplaçant avec les flèches.
    • Choisir 8:micro:bit puis 1:affichage, ce qui devrait ajouter la ligne from mb_disp import *
    • Dans le menu des Modules, il est apparu une nouvelle collection d’instructions: 9:affichage. Choisir cette collection puis choisir 1.clear()
    • Faire de même et choisir cette fois 2.show de cette même collection. Cela devrait afficher display.show(,delay=400,wait=True).
    • Le curseur clignote au niveau du premier paramètre que vous devrez renseigner: mettez "Image.HAPPY" à l’aide de l’editeur de texte (bouton du bas a A #). Valider les symboles avec la touche entrer. Faites Coller lorsque vous avez terminé la saisie.

    Votre programme devrait ressembler à ceci:

    Executer

    Relier alors la carte micro:bit à la calculatrice à l’aide du cable usb mini B vers micro B.

    Puis executer le script: Option Exec de la fenêtre d’edition…

    A vous de jouer: remplacer l’image HAPPY par celle Image.SAD

    Liens

    Loi de Mariotte

    Ti83 et loi de Mariotte

    dispositif TI83CE microbit capteur

    dispositif TI83CE microbit capteur

    Matériel

    • TI 83 CE edition Python
    • carte microbit
    • Capteur grove MPX5700AP capable de mesurer la pression de l’air dans une plage de 15 kPa à 700 kPa. Sensibilté 6,4 mV/kPa.

    Notice

    Les différents programmes PRESS.8xv et BOYLEMAR.8xv seront déjà installés sur la calculatrice. Celle-ci devra être préparée avec les librairies utiles selon la procédure expliquée sur la Fiche de prise en main

    Préparer le matériel

    • La carte microbit doit être équipée du shield grove.
    • Connecter la calculatrice sur la carte microbit.
    • Connecter le capteur de pression sur le shield (entrée PIN0).
    • Mettre la seringue dans la position 12mL et fermer celle-ci sur le capteur.

    Lancer le programme

    • Sur la calculatrice: Touche prgm: Choisir 2-Python App
    • Dans la liste des programmes installés: Choisir BOYLEMAR avec le curseur. Valider avec la touche entrer.
    • Touche var. Choisir la fonction mesure(). Valider avec OK (touche graphe).
    • Vous avez alors 3s pour positionner et maintenir la seringue sur le volume 2mL comme indiqué sur l’écran. Puis à nouveau 3s pour chacun des autres volumes proposés…
    • Une fois la serie de mesures réalisée, le graphique P-V est affiché à l’écran.
    • Pour prendre connaissance et traiter les données:
      • Revenir en mode calculatrice: touche on puis 2nde mode(quitter). Valider.
      • touche stats puis 1:modifier. La liste 1 est celle du volume(mL) et la liste 2 celle de la pression(kPa).
    tableau de mesures obtenu à 25°C

    tableau de mesures obtenu à 25°C

    Liens vers les documents

    Microbit

    Sous-sections de Microbit

    informatique des objets

    Prise en main de la carte micro:bit: présentation

    La carte microbit est un nano-ordinateur créé pour la promotion de la programmation dans l’éducation. Elle est très simple d’utilisation, mais peut également s’intégrer dans des applications complexes.

    capteurs integres

    Capteurs intégrés

    Description

    La carte microbit dispose de plusieurs capteurs intégrés:

    • temperature
    • acceleromètre à 3 axes
    • mesure de champs magnétique
    • luminosité

    Mesure d’horizontalité

    Principe

    On utilisera le capteur “acceleromètre”.

    Le champs de pesanteur génère une force, le poids, qui peut être mesurée par l’acceleromètre. Une des applications principale des accéléromètres est le calcul d’inclinaison. Ca permet de savoir comment est orienté votre microcontrôleur par rapport à la terre. C’est ainsi que sur un smartphone, celui-ci passe du mode portrait au mode paysage par rotation d’un quart de tour.

    C’est un composant électronique qui réalise cette mesure: une tige de silicium est chargée électriquement et la cage dans laquelle elle se trouve également, le déplacement de charges portée sur la tige est détectable et on en déduit le sens du déplacement. source

    principe d’un accéléromètre électromécanique (la partie rouge se met en mouvement par rapport au reste et le décalage est détecté grace au déplacement de charge qu’elle porte) —

    principe d’un accéléromètre électromécanique (la partie rouge se met en mouvement par rapport au reste et le décalage est détecté grace au déplacement de charge qu’elle porte) —

    Script 1

    Ce programme lit les valeurs toutes les 100 ms et affiche une flèche correspondant à la direction du mouvement sur l’écran micro:bit.

    La mesure de l’acceleration est faite dans la direction X:

    from microbit import *
    
    while True:
        acc = accelerometer.get_x()
        if acc > 0:
            display.show(Image.ARROW_E)
        else:
            display.show(Image.ARROW_W)
        sleep(100) 

    Script 2

    L’écran montre un pixel qui sera bien centré si le micro:bit est bien à l’horizontale ou qui sera décalé en direction de l’inclinaison dans le cas contraire. Le but est donc de mettre le micro:bit parfaitement à plat, de sorte qu’uniquement la LED centrale soit allumée. source

    from microbit import *
    
    x = 1
    y = 1
    
    while True:
        accX = accelerometer.get_x()
        accY = accelerometer.get_y() 
        if accX > 100 and x < 4:
            x += 1
        elif accX < -100 and x > 0:
            x -= 1
        elif accY > 100 and y < 4:
            y += 1
        elif accY < -100 and y > 0:
            y -= 1
        display.clear()
        display.set_pixel(x, y, 9)
        sleep(100)

    Utilisation de la boussole

    La boussole s’utilise avec compass mais elle doit etre calibrée avant utilisation : voir doc

    L’instruction en micropython est: compass.heading()

    Exemple:

    from microbit import *
    
    compass.calibrate()
    
    while True:
        aiguille = ((15 - compass.heading()) // 30) % 12
        display.show(Image.ALL_CLOCKS[aiguille])

    Utilisation du thermomètre

    L’instruction pour mesurer la température est: temperature(), que l’on peut afficher directement sur la carte avec display.scroll(temperature()).

    Voir aussi l’exemple avec l’affichage à LED: Lien

    Liens

    Vincent Le Mieux, www.laboiteaphysique.fr

    niveau a bulles

    Acceleromètre et niveau à bulles

    But: Programmer une série d’instructions conditionnelles et une fonction en Python.

    Editeur

    Choisir l’editeur MU en mode BBC microbit

    Afficher la direction d’inclinaison

    Le script devra démarrer par les lignes suivantes:

    from microbit import *
    
    while True:
        incli_X = accelerometer.get_x()
        incli_Y = accelerometer.get_y()

    Le programme permet de stocker dans les variables incli_X et incli_Y les valeurs mesurées par l’accéleromètre.

    Vous pouvez charger ce programme dans la carte microbit. Puis ouvrir la console de l’editeur MU (REPL), et afficher les valeurs de ces variables: (ces valeurs dependent de l’inclinaison initiale de la carte microbit)

    >>> incli_X
    228
    >>> incli_Y
    -15

    Refermez alors la console et revenir sur l’editeur de script…

    Compléter le script avec les tests qui permettront d’afficher “D”, “G”, “H”, “B” ou “-” selon si l’inclinaison est vers la Droite, Gauche, Haut, Bas, ou - neutre.

    On pourra se conformer au diagramme ci-dessous:

    diagramme de décision if ... elif ... else

    diagramme de décision if ... elif ... else

    Flasher. La lettre qui est affichée depend alors de l’inclinaison!

    sauvegarder le fichier .pydans votre classeur numérique (vos documents, dans un dossier particulier)

    Afficher une bulle

    L’inclinaison va maintenant mettre en mouvement une bulle à l’écran. (Un pixel de coordonnées x, y).

    On définit les variables x, y = 2, 2 avant la boucle principale while True.

    Boucle principale

    On remplacera ensuite chacune des instructions d’affichage display.show() par la mise à jour d’une variable direction:

    display.show("D")
    # sera remplace par
    direction = "D"

    à la fin de la boucle, on ajoutera les lignes qui vont:

    • appeler la fonction deplace avec les arguments: direction, x, y. Affecter à x, y les valeurs de retour.
    • Effacer l’écran
    • Afficher le pixel à la position x, y
        x, y = deplace(direction, x, y)
        sleep(100) # optionnel
        display.clear()
        display.set_pixel(x,y,9)

    Le corps du programme devrait alors ressembler au script suivant:

    from microbit import *
    def deplace(direction, pos_X, pos_Y):
    	# a completer
        return pos_X,pos_Y
    
    x, y = 2,2
    
    while True:
        incli_X = accelerometer.get_x()
        incli_Y = accelerometer.get_y()
        if abs(incli_X ) > abs(incli_Y):
            if incli_X > 20:
                direction = "D"
            elif incli_X < -20:
                #display.show("G")
                direction = "G"
            else:
                direction = "-"
        else:
            if incli_Y < -20:
                direction = "B"
            elif incli_Y > 20:
                direction = "H"
            else:
                direction = "-"
        x, y = deplace(direction, x, y)
        sleep(100)
        display.clear()
        display.set_pixel(x,y,9)

    Programmer une fonction avec paramètres

    La fonction sert à modifier les valeurs des paramètres pos_X et pos_Y selon celle de direction.

    • direction est une variable de type str et vaut “D”, “G”, “H”, “B” ou “-”.
    • pos_X et pos_Y sont de type int.
    • Les valeurs de retour sont pos_X et pos_Y.
    def deplace(direction, pos_X, pos_Y):
    	# a completer
    	return pos_X, pos_Y

    Il faudra donc programmer une série de conditions sur direction pour modifier les valeurs de position (augmenter ou diminuer d’une unité pos_X ou pos_Y).

    Problème de depassement: Les valeurs admises pour pos_X et pos_Y doivent être comprises en 0 et 4, sinon cela génère un Value Error lorsque l’on veut afficher le pixel à l’ecran avec display.set_pixel(x,y,9).

    Votre fonction doit aussi prendre en compte cette possibilité et ne pas retourner de valeur <0 ou >4.

    pencher la carte microbit vers la droite

    pencher la carte microbit vers la droite

    Flasher et testez votre programme. Parviendrez-vous à maintenir le pixel au centre pendant quelques secondes?

    sauvegarder le fichier .py

    Prolongement: Le SNAKE

    On peut augmenter la complexité du programme en affichant un serpent à l’écran comme dans le jeu snake. Les coordonnées des pixels du serpent sont alors stockées dans une Liste [(x1,y1),(x2,y2),...] pour permettre leur affichage:

    for coord in serpent:
    	display.set_pixel(coord[0],coord[1],9)

    A chaque déplacement, cela ajoute un pixel à la fin de la liste. Il s’agit de la tête du serpent. Il faut alors retirer le premier pixel (serpent[0]) si l’on veut que sa longueur reste constante.

    deplacement du serpent vers le bas

    deplacement du serpent vers le bas

    Dans la boucle principale, une fois que la variable directiona été mise à jour, on ajoutera les lignes suivantes pour la gestion du deplacement du serpent:

        x, y =  tete(serpent)
        if direction != "-":
            x, y = deplace(direction, x, y)
            ajoute_tete(serpent, x, y)
            supprime_queue(serpent)
        sleep(100)
        display.clear()
        affiche(serpent)

    Voir en annexe1 le corps du programme complet.

    L’objet serpent est alors une liste Python à laquelle on associes les fonctions tete, ‘ajoute_tete, supprime_queueet affiche`.

    Ces fonctions sont décrites dans les commentaires suivants:

    def tete(S):
       # retourne les coordonnees x, y de la tete du serpent
       # qui sont stockees dans le dernier element S[-1]
       # sous la forme d'un tupple (x,y)
    
    def ajoute_tete(S, x, y):
       # ajoute un tupple (x,y) a la fin de la liste S 
    
    def supprime_queue(S):
       # decale toutes les valeurs de la liste S vers la gauche:
       # a l'aide d'une boucle bornee sur les indices i:
       # copie toutes les valeurs S[i+1] dans S[i]
       # puis supprime le dernier element
    
    def affiche(S):
       # affiche tous les pixels du serpent
       # a partir de leurs coordonnees dans S

    Il restera à écrire le script de ces fonctions. Cette méthode de programmation introduit le chapitre sur les types construits en Terminale NSI: On s’intéresse d’abord à l’interface de ce nouveau type appelé serpent. Puis à son implémentation.

    • interface: Ce que réalisent les fonctions associées au type construit. Comment on les utilise.
    • implémentation: Programmation de ces fonctions.

    Annexe

    serpent = [(2,0),(2,1),(2,2)]
    
    while True:
        incli_X = accelerometer.get_x()
        incli_Y = accelerometer.get_y()
        if abs(incli_X ) > abs(incli_Y):
            if incli_X > 20:
                direction = "D"
            elif incli_X < -20:
                direction = "G"
            else:
                direction = "-"
        else:
            if incli_Y < -20:
                direction = "B"
            elif incli_Y > 20:
                direction = "H"
            else:
                direction = "-"
    
        x, y =  tete(serpent)
        if direction != "-":
            x, y = deplace(direction, x, y)
            ajoute_tete(serpent, x, y)
            supprime_queue(serpent)
        sleep(100)
        display.clear()
        affiche(serpent)

    1. boucle principale du programme snake.py ↩︎

    MB grove

    MB Grove : capteur luminosité

    Principe

    La carte microbit associée au shield grove permet d’utiliser de nombreux capteurs passifs. L’instruction à utiliser: pin0.read_analog(). Cette instruction permet la lecture d’une tension de type analogique sur l’entrée PIN0, quel que soit le composant passif.

    Matériel

    • carte microbit et shield grove
    • capteur de luminosité grove ou autre capteur passif
    • eventuellement: lampe de bureau, filtres occultants

    Script

    from microbit import *
    
    
    while True:
        
        display.show(Image.SQUARE)
        sleep(1000)
        display.clear()
        display.scroll(pin0.read_analog())

    Liens

    Voir exemples sur http://ww2.ac-poitiers.fr/sc_phys/sites/sc_phys/IMG/pdf/prise_en_main_carte_microbit_langage_python.pdf

    MB LED clignotante

    LED clignotante

    Principe

    On utilise le connecteur grove du microbit pour commander une sortie en tension. On pourra allumer, et faire clignoter une LED, branchée en série avec sa resistance de protection.

    Il faudra utiliser les connecteurs avec fils de couleur sur prise grove:

    • Jaune: tension commandée : relier au + de la LED
    • Noir: GND : relier à la resistance 1k
    • Rouge (3V fixe) et Blanc: non utilisés

    circuit avec LED et Resistance

    circuit avec LED et Resistance

    montage complet

    montage complet

    Matériel

    • carte micro:bit et shield grove
    • fil de connexion grove-connecteurs couleur (rouge noir blanc jaune)
    • pince crocodile
    • Diode electroluminescente LED
    • resistance de 1kΩ
    • multimètre

    Script

    # Jaune: tension commandée : relier au + de la LED  
    # Noir: GND : relier à la resistance 1k
    # Rouge et Blanc: non utilisés
    from microbit import *
    
    while True:
        pin0.write_digital(1) # sortie 3V
        sleep(1000)
        pin0.write_digital(0)
        sleep(1000)

    MB diviseur de tension

    luminosité LDR et diviseur de tension

    Principe

    La LDR est un composant électronique photosensible. Sa valeur de résistance diminue avec la luminosité.

    Pour constater ces variations, on utilisera la LDR dans un montage type diviseur de tension.

    Un seul des connecteurs grove de la carte micro:bit suffira pour alimenter le circuit et mesurer la tension au milieu du pont diviseur. Il faudra utiliser les connecteurs avec fils de couleur sur prise grove:

    • Rouge: Alimentation fixe 3V avec l’instruction pin0.write_digital(1)
    • Noir: GND
    • Jaune: pour la mesure de tension avec l’instruction pin0.read_analog()

    circuit avec LDR et Resistance

    circuit avec LDR et Resistance

    montage à réaliser

    montage à réaliser

    Matériel

    • carte micro:bit et shield grove
    • fil de connexion grove-connecteurs couleur (rouge noir blanc jaune)
    • pince crocodile
    • Photoresistance type VT900 serie (light dependant resistor LDR)
    • resistance de 10kΩ
    • lampe de bureau (allumée/éteinte)
    • filtres occultants
    • multimètre

    Script

    # pin0 rouge : alim fixe 3V
    # pin0 jaune : lecture tension
    # pin0 noir : GND
    from microbit import *
    
    pin0.write_digital(1) # sortie 3V
    while True:
        display.scroll(pin0.read_analog())

    Capteur lumiere

    Capteur de luminosité

    Le projet

    Le projet consiste à créer un motif lumineux sur la grille de DEL de la carte micro:bit. La nature du motif et l’intensité des DEL dépendra de la lumière ambiante: l’affichage sera plus lumineux si l’environnement est sombre.

    clair- obscur

    clair- obscur

    Prise en main du capteur

    Pour ce projet, le panneau de DEL peut être utilisé en capteur de luminosité basique en inversant la polarisation des DEL.

    Celles-ci sont alors utilisées comme capteur de lumière.

    Le capteur de lumière de la micro:bit mesure la lumière dans une gamme allant de 0 (très sombre) à 255 (très lumineuse).

    La mesure du niveau de luminosité passe par la commande ci-dessous.

    from microbit import *
    display.read_light_level()

    On peut stocker cette valeur dans une variable, par exemple:

    from microbit import *
    lumi = display.read_light_level()

    Il est possible d’afficher la valeur mesurée. En respectant une pause entre 2 valeurs mesurées cela donne:

    from microbit import *
    
    while True:
        lumi = display.read_light_level()
        display.scroll(lumi)
        sleep(100)

    Version 1 du projet: Seuil de lumière

    Ajouter des branchements sur la variable lumi dans le programme pour actionner un smiley qui depend de la mesure (clarté/obscurité).

    • Il faudra prévoir un seuil de luminosité pour basculer d’un smiley à un autre smiley.

    • Et mettre l’ensemble dans une boucle while True:, comme par exemple:

    # script 1
    from microbit import *
    
    while True:
        lumi = display.read_light_level()
        if lumi ... ...:
            ...
        else:
            ...

    La surface de DEL alterne alors entre mesure d’intensité et affichage. D’où le clignottement.

    Question a: Programmez la premiere version de ce projet, appelée *script 1. Recopier le script sur votre feuille.

    Version 2 du projet: afficher une forme personnalisée

    On peut fabriquer nos propres images à partir de chaine de caractère utilisant des chiffres de 0 à 9.

    Le script suivant donne un carré de plus forte intensité:

    from microbit import *
    motif = '99999:90009:90009:90009:99999:'
    img = Image(motif)
    display.show(img)

    Le script suivant donne un carré de plus faible intensité:

    from microbit import *
    motif = '11111:10001:10001:10001:11111:'
    img = Image(motif)
    display.show(img)

    Adapter le script 1 pour afficher un carré très lumineux lorsqu’il fait sombre, ou faiblement lumineux lorsqu’il fait clair. Appeler ce nouveau script: script 2

    Question b: Concevoir et tester le script 2. Recopier le script sur votre feuille.

    Version 3: Affichage d’intensité variable

    L’intensité lumineuse du motif affiché dépend de la valeur attribuée à chaque pixel:

    • ‘99999:90009:90009:90009:99999:’: motif d’intensité forte
    • ‘33333:30003:30003:30003:33333:’ motif d’intensité intermédiaire
    • ‘11111:10001:10001:10001:11111:’: motif d’intensité faible

    On peut créer une chaine de caractères en fonction d’une variable I qui varie de 0 à 9 et qui dessine un motif carré. Les 2 premieres lignes du motif sont construites à partir de:

    motif = str(I + I + I + I + I + ":" + I + "000" + I + ":")

    La valeur de I sera calculée d’après la variable lumiselon la loi:

    I = int((255 - lumi)/255*9)

    Le programme principal du script 3 (à compléter) sera alors:

    while True:
        lumi = display.read_light_level()
        I = ...
        motif = ...
        img = Image(...)
        display.show(img)

    Afficher avec le script 3 un carré dont l’intensité lumineuse varie entre 0 et 9 selon l’intensité lumineuse mesurée. Tester et mettre au point le programme.

    Question c: Recopier sur votre feuille le script 3.

    Prolongement 1: utiliser des fonctions

    Le script 3 peut être amélioré en utilisant des fonctions. Le programme principal:

    while True:
    	lumi = display.read_light_level()
    	I = intensite(lumi)
    	motif = carre(I)
    	img = Image(motif)
    	display.show(img)

    Ajouter les definitions des fonctions intensite et carre au script 3. Appeler ce nouveau script: le script 4.

    Aides:

    1. La fonction intensite retourne une valeur de 0 à 9 selon la variable lumi en argument:
    def intensite(lumi):
    	"""retourne une valeur de 0 a 9
    	9 <=> lumi = 0
    	0 <=> lumi = 255
    	Exemples:
    	>>> I = intensite(255)
    	>>> print(I)
    	0
    	>>> I = intensite(0)
    	>>> print(I)
    	9
    	"""
    	return int((255 - lumi)/255*9)
    1. La fonction carre qui prendra en paramètre la valeur I, retourne une chaine de caractères dans le bon format pour dessiner les contours d’un carré vide en son centre.
    def carre(I):
    	"""
    	>>> carre(9)
    	'99999:90009:90009:90009:99999:'
    	>>> carre(1)
    	'11111:10001:10001:10001:11111:'
    	>>> carre(5)
    	'55555:50005:50005:50005:55555:'
    	"""
    	return ... ... ...

    Question d: Programmez et testez le script 4. Recopiez le sur votre feuille.

    Prolongement 2: motif animé

    On pourra remplacer l’image fixe par une animation. Il faudra alterner avec 3 images successives, et attendre un delai de 100ms entre chaque. Utiliser pour cela la fonction sleep(100) entre chaque affichage.

    Et ajuster l’intensité lumineuse du motif affiché selon l’éclairage mesuré (voir script 4).

    Documentation

    MB sons

    Jouer un son

    Jouer des sons (qui ne sont pas des notes de musique) avec un HP branché sur pin0:

    from microbit import *
    import music
    for i in range (1,11):
      music.pitch(100*i, 2000, pin0)
      print('son de freq ', i*100, ' Hz')

    Ecrire une partition de musique, avec des notes

    Instruction : NOTE[octave][:durée]

    from microbit import *
    import music
    tune = ["C4:4", "D4:4", "E4:4", "C4:4", "C4:4", "D4:4", "E4:4", "C4:4", "E4:4", "F4:4", "G4:8", "E4:4", "F4:4", "G4:8"]
    music.play(tune)

    mesure de c du son

    TP : Mesure d’une durée de propagation d’ultra-sons

    Principe

    On cherche à mesurer la durée de propagation des ultra-sons lors de leur reflexion sur un obstacle.

    mesure de la duree de propagation des US

    Dispositif

    Pour une distance d1 entre le dispositif ultra-sons et l’écran, on relève la durée de propagation t (en micro secondes) sur la carte microbit.

    Cette mesure est déclanchée par l’appui sur le bouton a de la carte microbit.

    Script

    Commencer par uploader le script ci-dessous dans la carte microbit selon la méthode utilisant l’editeur Mu (flasher): voir page présentation microbit

    Mu editor

    Mu editor

    from microbit import *
    from machine import time_pulse_us
    import time, music, math
    
    analogiq_in = [pin1]
    
    
    def mesure_temps_A_R(broche = pin1):
        """Module Grove - Ultrasonic Ranger
        Retourne la durée d'un aller/retour des ultra_sons en microsecondes
        Paramètre : Nom de la broche utilisée
        """
        broche.write_digital(0)
        time.sleep_ms(2)
        broche.write_digital(1)
        time.sleep_ms(10)
        broche.write_digital(0)
        broche.read_digital()
        dt = time_pulse_us(broche, 1)
        return dt
    
    while True:
      if button_a.is_pressed():
        dt = mesure_temps_A_R()
        display.scroll(dt)

    Brancher le dispositif à ultra-sons

    Brancher l’emetteur-capteur à ultra-son sur la carte micro:bit. Choisir le port groove appelé PIN1 sur la carte.

    Diriger l’emetteur-capteur à ultra-sons vers un support rigide, afin que les ondes ultrasonores se reflechissent et reviennent vers le recepteur.

    Mesures

    Une fois le script téléversé :

    Lorsque l’on appuie sur le bouton A, la fonction mesure_temps_A_R permet de communiquer avec l’emetteur-capteur à ultra-son. L’affichage de la durée de propagation pour un aller-retour s’affiche sur l’écran LED du microcontrôleur, chiffre après chiffre (scroll). La durée est en µs.

    Exemple d’affichage d’une durée dt = 833µs: En positionnant l’emetteur-capteur à environ 15 cm d’un support reflechissant, on lit :

    En supposant que la célérité du son vaut 340m/s au moment de l’experience, cela donne une distance parcourue de $340 \times 833.10^{-6} = 0,28m$, double de la distance au support.

    Cela semble cohérent. Mais il faudrait discuter de la précision attendue sur les 2 derniers digits mesurés par le dispositif…

    exploitation des mesures

    • Répeter les mesures et relever la durée mise par les ultra-sons pour se reflechir sur un support rigide. Sur le cahier, consigner les données dans un tableau:
    distance parcourue (m) 0 0.25 0.5 1.0 …
    temps (s) 0 .. .. .. ..
    • Ouvrir un editeur Python, comme par exemple Pyzo, et saisir le script ci-dessous. Enregistrer le programme dans vos Documents avec une extension .py, comme par exemple: courbe.py
    • Modifier les valeurs dans les listes X et Y afin d’afficher la courbe de la distance parcourue en fonction du temps (Y = distance; X = temps).
    • Relever alors l’équation de la courbe modélisée, déterminer la célérité des ondes c, ainsi que le coefficient de correlation.
    • QUESTIONS: Dans le programme python ci-dessous, quelle partie du script correspond à:
      • l’import de librairie
      • la définition des listes X et Y
      • le traitement statistique des données
      • l’affichage du graphique
    import matplotlib.pyplot as plt
    
    import numpy as np
    from scipy.optimize import curve_fit
    from matplotlib.widgets import Cursor
    
    #--------------------------------------------------
    #création des listes de variables utilisées dans le programme
    #--------------------------------------------------
    
    X=[0,1,2,3,4,5]
    Y=[0.0,1.1,1.9,3.0,4.1,4.9]
    
    
    #--------------------------------------------------
    #partie modélisation
    #--------------------------------------------------
    #variables utilisées dans la modélisation polynomiale standard
    a=0.9
    b=0
    
    #mise en place de l'outil curve fit (scipy)
    def func(x,a,b):
        return a*x+b
    
    X = np.asarray(X) # conversion des listes en matrices 
    Y = np.asarray(Y) # pour pouvoir calculer a*X+b
    
    y = func(X,a,b)
    
    params, mcov =curve_fit(func,X,Y)
    # params = coefficients retournés par le calcul de modélisation avec R2 minimal
    # mcov = matrice de covariance, permet de quantifier la variation de chaque variable par rapport à chacune des autres
    a = params[0]; b=params[1]
    
    #--------------------------------------------------
    #partie calcul de r2 coefficient de correlation
    #--------------------------------------------------
    residuals = Y- func(X, params[0],params[1])
    ss_res = np.sum(residuals**2)
    ss_tot = np.sum((Y-np.mean(Y))**2)
    r_squared = 1 - (ss_res / ss_tot)
    print(r_squared)
    
    #-------------------------------------------------
    #             partie graphique avec quadrillage
    #-------------------------------------------------
    
    # label et config des axes
    plt.xlabel('X (s)')
    plt.ylabel('Y (m)')
    
    # Plot
    plt.plot(X,Y,'o') # nuage de points de l'acquisition
    plt.plot(X,func(X,a,b),'g',linewidth=1) # courbe modelisee
    equation = "Y = "+str(round(a,3))+" * X + "+str(round(b,3)) + ", coef correlation r2 = " + str(round(r_squared,5))
    plt.legend(["mesures","courbe modélisée"])
    plt.title(equation)
    
    # modifier les axes APRES avoir positionné les points si besoin de choisir l'echelle
    axes = plt.gca()
    cursor = Cursor(axes, useblit=True, color='red', linewidth=2)
    
    # affichage
    plt.show()

    Liens

    portes logiques

    TP Portes logiques - NSI Term

    But de la seance

    Vous allez étudier les portes logiques fournies pour la seance. Vous utiliserez une carte microcontrôleur Microbit pour disposer d’une générateur de tension à 2 sorties. Chacune de ces sorties sera branché à l’une des entrées de la porte logique. Les boutons de la carte microbit serviront à choisir le niveau de tension 0 ou 3,3V pour les entrées de la porte logique.

    Progammer la carte microbit

    La carte microbit est présentée dans cette fiche.

    Dans un premier temps, vous allez consulter la fiche du TP sur le clignottement d’une Diode Electroluminescente.

    Ce que doit réaliser le programme: On pilote les niveaux de tension PIN0 et PIN1 à l’aide des boutons a et b de la carte microbit:

    bouton niveau de tension
    a relâché PIN0 à 0V
    a appuyé PIN0 à 3,3V
    b relâché PIN1 à 0V
    b appuyé PIN1 à 3,3V

    Sur l’editeur Mu: Copier et compléter le programme suivant. Brancher la carte microbit sur un port USB de l’ordinateur (maintenir le câble au cours de la seance). Et flasher la carte (charger le programme).

    # Ecrit ton programme ici ;-)
    # Jaune: tension commandée : relier au + de la LED  
    # Noir: GND : relier à la resistance 1k
    # Rouge du PIN1 : relier à la borne +Vcc du circuit integre
    # Blanc: non utilises
    from microbit import *
    
    while True:
        if button_a.is_pressed():
          # à completer

    PIN0 et PIN1 de la carte

    Brancher les connecteurs grove sur les PIN0 et PIN1. Utiliser alors des fils electriques pour acceder aux contacts des connecteurs grove:

    • PIN0: contact noir (0V)
    • PIN0: contact jaune (0 ou 3,3V selon le programme)
    • PIN1: contact noir (0V)
    • PIN1: contact rouge (3,3V fixe)
    • PIN1: contact jaune (0 ou 3,3V selon le programme)

    carte microbit

    conneceurs grove de la carte microbit

    Relier alors les contacts noirs et jaune de chaque connecteur grove sur une ligne verticale de la plaquette d’essai (breadboard).

    connection carte microbit sur breadboard

    connection carte microbit sur breadboard

    Premiers essais

    On va maintenant utiliser la diode electroluminescente pour tester si le programme fonctionne: Brancher la diode en série avec sa resistance de protection $1k\Ohm$ aux bornes de la tension du PIN0 (entre les contacts jaune et noir).

    DEL et resistance de protection

    Branchement en serie de la DEL

    Tester si celle-ci s’allume lorsque l’on appuie sur le bouton.

    Cabler la porte logique

    Les circuits intégrés fournis pour la seance sont de différents types. Certaines possèdent des portes logiques à 2 entrées (AND, OR, NAND), alors que celle NAND ne possède qu’une entrée. Des marques de couleur ont été peintes pour les identifier plus facilement:

    code porte logique
    4081 (bleue) AND
    4071 (orange) OR
    4011 (jaune) NAND
    4069 (vert) NOT

    Chaque circuit intégré comporte plusieurs portes logiques. Pour celles à 2 entrées, on peut les repérer comme sur le schéma suivant:

    portes logiques PIN 2 entrées

    Portes logiques à 2 entrées

    Pour le circuit NOT, à une entrée, la disposition des portes logiques est comme ceci:

    portes logiques PIN 1 entrée

    Portes logiques NOT

    • Disposer le circuit integré jaune 4011 sur le breadboard

    • selectionner l’une des portes logique du composant

    • Brancher la diode avec, en serie, sa resistance de protection à la sortie de la porte logique. Fermer le circuit de la diode sur l’un des contacts noirs (0V) de PIN0 ou PIN1.

    • alimenter le circuit intégré: brancher la borne +Vcc sur le contact rouge du PIN1 (3,3V) et la borne GND (masse) sur l’un des contacts noirs (0V) de PIN0 ou PIN1.

    diode en sortie

    branchement de la diode en sortie

    • brancher les contacts commandés (jaunes) des PIN0 et PIN1 sur les entrées de la porte logique
    circuit complet à porte logique

    circuit complet

    • Actionner alors les boutons a et b de la carte microbit pour tester toutes les combinaisons possibles en entrée. Renseigner la table de vérité.
    E1 E2 S
    0 0
    0 1
    1 0
    1 1

    Prolongements

    Modifier le montage pour tester les autres portes logiques fournies.

    loi de Mariotte

    Loi de Mariotte - utilisation d’un dispositf à microcontrôleur

    Dispositif

    La seringue est branchée sur le capteur de pression, lui-même relié au port grove PIN0 de la carte microbit.

    La carte est branchée sur un port USB de l’ordinateur.

    L’écran LED de la carte microbit affichera la valeur de la tension sur PIN0.

    Grâce à sa liaison série sur le port USB, le logiciel Mu affichera les données mesurées au cours de l’acquisition sous un format: [(volume1, tension1), (volume2, tension2), ...]

    Editeur Mu

    Lancer l’editeur Mu. Choisir au demarrage le mode BBC microbit.

    Dans la fenêtre d’edition, coller le script suivant:

    from microbit import *
    
    datas = []
    v = 70
    
    while True:
    
        if button_a.is_pressed(): 
            display.clear()
            lecture = pin0.read_analog()
            v = v -10
            display.scroll(lecture)
            datas.append((v,lecture))
            print(datas)
        elif button_b.is_pressed(): 
            datas = []
            v = 70
            display.scroll("RAZ")
        else: 
            display.show(Image.SQUARE)

    Questions: à partir de la lecture du script…

    1. A quoi servent les 2 premières lignes sous l’import de la librairie microbit: datas = [], et v = 70?
    1. Que se passe t-il lorsque l’on appuie sur le bouton a de la carte microbit?
    2. Que se passe t-il lorsque l’on appuie sur le bouton b?
    3. Comment faudrait-il adapter le script pour réaliser une mesure de pression pour des volumes décroissants d’air, de 5mL en 5mL?

    Téléversement du programme

    Appuyer sur le bouton FLASHER pour téléverser le programme dans la carte microbit.

    bouton FLASHER

    bouton FLASHER

    REPL

    Pour afficher les sorties textuelles de la carte microbit (print()), il faudra ouvrir l’interface avec le bouton REPL.

    bouton REPL

    bouton REPL

    Pour démarrer le programme d’acquisition, appuyer sur le bouton de démarrage du programme au dos de la carte.

    Bouton de (re)démarrage

    Bouton de (re)démarrage

    Lors de l’appui sur le bouton a, une nouvelle mesure est enregistrée. la liste des valeurs acquises est alors affichée dans la fenêtre du logiciel.

    Lors de l’appui sur le bouton b, la liste est remise à zero (recommencer l’acquisition).

    Mesurer

    Enregistrer votre première valeur, pour un volume de 60mL:

    • appuyer sur le bouton a.

    Pour enregistrer votre 2e valeur:

    • maintenir la pression pour un volume de 50mL
    • appuyer sur le bouton a

    Vous devriez voir à l’écran la liste [(volume1, tension1), (volume2, tension2)].

    affichage de la liste de mesures dans le REPL

    affichage de la liste de mesures dans le REPL

    Verifier que les volumes enregsitrés correspondent bien aux positions du piston lors de l’acquisition, sinon recommencer (bouton b).

    Copier les valeurs

    A la fin de l’acquisition (volume de 30, ou 20 mL):

    • Selectionner les valeurs directement dans la fenêtre du REPL.
    selection dans le REPL

    selection dans le REPL

    • Clic droit: enregistrer
    selection dans le REPL

    selection dans le REPL

    Traitement des données

    Graphique volume - tension

    Se rendre sur l’application en ligne : basthon.fr

    Choisir Notebook

    Ecrire dans la cellule du notebook datas = et coller les valeurs mesurées.

    A la suite, coller le script suivant:

    import matplotlib.pyplot as plt
    
    volume = []
    tension = []
    inv_volume = []
    pression = []
    
    for mesure in datas:
        volume.append(mesure[0])
        tension.append(mesure[1])
    
    plt.xlabel("Volume mL")
    plt.ylabel("Tension")
    
    
    
    # Plot
    plt.plot(volume,tension,'o') # nuage de points de l'acquisition
    
    
    # affichage
    plt.show()

    Executer la cellule (Maj + Entrée) ou bonton triangle sur la barre de commande du logiciel.

    Quelle est l’allure de la courbe tension = f(volume)?

    Etude de l’evolution de la pression

    Dans la boucle : for mesure in datas:, ajouter les instructions qui permettront de completer la liste inv_volume. On veut mettre dans cette liste inv_volume les valeurs calculées à partir de $1 / volume$

    Comme les valeurs du volume sont mises dans mersure[0]cela donne dans le script python:

    for mesure in datas:
        volume.append(mesure[0])
        tension.append(mesure[1])
        inv_volume.append(1/mesure[0])

    Tracer alors le graphique tension = f(inv_volume). Que constatez-vous?

    Utiliser la fonction d’etalonnage

    La tension du capteur correspond à une certaine valeur de pression.

    • A l’aide d’un manomètre, mesurer la pression atmosphérique Po en hPa
    • Relever la valeur de tension donnée par le capteur à pression Uo

    La valeur de tension est exprimées en unités, un nombre compris entre 0 et 1023 (codage de la valeur en 10 bits).

    Le coefficient de conversion tension-pression est donné à 8 hPa/unite

    Pour une tension U mesurée lors de l’experience (exprimé en unités, la pression P correspondante est donnée par:

    $$P = Po + 8\times(U-Uo)$$

    Utilisez cette relation d’etalonnage pour créer une nouvelle liste pression à partir de celle tension. Par exemple, avec Po=1000hPa, et Uo=190 unités:

      pression.append(1000 + 8 * (mesure[1] - 190))

    Tracer alors le graphique pression = f(inv_volume). Que constatez-vous?

    Mise en evidence la loi de Mariotte

    La loi de Mariotte s’énonce ainsi:

    $$P \times V = Constante$$

    Cette loi est-elle en accord avec la courbe obtenue?

    Prolongement: Modelisation

    Adapter alors le script suivant pour obtenir la courbe modélisée $P = f(\tfrac{1}{V})$

    Cellule python 1: équation de la courbe modélisée

    from scipy import stats
    import numpy as np
    inv_volume_np = np.asarray(inv_volume)
    pression_np = np.asarray(pression)
    a, b, r_value, p_value, std_err = stats.linregress(inv_volume, pression)
    a, b, r_value

    Cellule python 2 créer une fonction de prédiction à partir du modèle

    def H(x,a,b):
        return a * x + b

    Cellule python 3 graphique avec courbe modélisée

    plt.clf()
    plt.plot(inv_volume_np,pression_np,'o') # nuage de points de l'acquisition
    plt.plot(inv_volume_np, H(inv_volume_np,a, b), c='r')
    plt.show()

    reseau radio SNT

    Partie 1: Gestion de l’affichage

    Une présentation générale de la carte microbit se trouve à la page suivante.

    La fiche reponse pour les questions.

    Prise en main de l’interface microbit sur Vittascience

    Ce premier travail permet de découvrir l’interface Vittascience.com pour la programmation de la carte microbit. Les questions qui suivent cette manipulation vont présenter le langage Python. Aucune connaissance du langage n’est requise pour ce premier travail.

    • Aller à la page Editeur microbit sur Vittascience.com

    • Brancher la carte microbit sur l’un des ports USB de l’ordinateur. La carte est alors visible depuis l’explorateur comme une nouvelle mémoire flash.

    Premier programme

    La page présente 2 espaces. L’edition du programme se fait dans la partie gauche (celle présentant les blocs à assembler). A droite, c’est la traduction du programme en langage Python, qui est réalisée de manière automatique.

    Le programme en langage Python est alors:

    from microbit import *
    
    while True:
      pass

    En colorant les différentes parties du script Python, on peut mettre en correspondance: les blocs et leur équivalent en langage informatique:

    Mettre un bloc de type affichage sur la carte microbit, comme illustré ci-dessous:

    Modifier l’image pour avoir l’affichage d’un smiley. Il faut modifier le paramètre du bloc et choisir une image parmi les propositions:

    Vous pouvez alors téléverser le programme dans la carte microbit et observer l’affichage. Il y a 2 options proposées:

    • Soit utiliser le bouton téléverser. Le programme se charge alors automatiquement dans la carte microbit
    • soit le bouton de téléchargement. C’est l’ordinateur qui charge alors le programme généré (l’extension est .hex). Il faudra le deplacer sur la carte microbit à l’aide de l’explorateur:

    Ajouter une instruction conditionnelle (si le bouton A est préssé, alors…)

    Observer le script Python.

    from microbit import *
    
    while True:
      if button_a.is_pressed():
        display.show(Image.HAPPY)

    Si on met à nouveau les blocs en correspondance avec les instructions du langage, cela donne:

    Qu1.: colorier le script sur la fiche de reponse.

    Les instructions en python ne sont pas alignées sur la même verticale. On dit qu’elles sont indentées lorsqu’elles présentent un décalage horizontal. Cette disposition est aussi visible sur l’algorithme écrit en langage scratch (blocs colorés).

    Qu2.: Expliquer la signification de cette indentation en Python

    Terminer maintenant le programme selon l’image suivante:

    Et téléverser dans la carte microbit. Comment réagit-elle lorsque vous appuyez sur le bouton A, le bouton B?

    Qu3.: Comment la réagit la carte lorsque l’on appuie sur les 2 boutons simultanément? Cela génère t-il un bug a l’affichage? Pourquoi?

    Modifier la structure conditionnelle en remplaçant la séquence: si … si …

    if button_a.is_pressed():
      instruction1
    if button_b.is_pressed():
      instruction2

    par la séquence: si … sinon si …

    if button_a.is_pressed():
      instruction1
    elif button_b.is_pressed():
      instruction2

    Qu4.: Cela améliore t-il le comportement de la carte lorsque l’on appuie simultanément sur les 2 boutons? Pourquoi?

    Introduction au langage Python

    Le langage python, comme tout langage informatique est un langage très structuré, qui utilise un petit nombre de mots clés, à partir desquels on construit des instructions.

    Les couleurs (programme en blocs, fenêtre de gauche) indiquent la famille d’instructions. Les instructions du langage peuvent être rassemblées selon les principales familles qui sont:

    • Affichage
    • Entrées/ Sorties
    • Logique
    • Boucles
    • Variables

    D’autres familles d’instructions concernent la programmation de Fonctions, ou l’utilisation de types construits comme les chaines de caractères et les listes, les opérations Math, ou la gestion des erreurs (Exceptions).

    Les fonctions Communication, Capteurs, Actionneurs, Robots, … concernent la manipulation d’objets technologiques et apportent des extensions du langage. Selon les besoins, il faudra parfois ajouter des extensions de cette sorte, comme ici avec la première ligne:

    from microbit import *

    Avec la programmation par blocs sur l’interface Vittascience.com, cette ligne est ajoutée dès que vous choisissez une instruction du bloc Entrées/Sorties spécifique à la carte microbit.

    Qu5.: compléter le tableau avec la description de l’instruction:

    mot clé description
    import
    display.show()
    button_a.is_pressed()
    button_b.is_pressed()

    Les instructions qui terminent par des parenthèses () sont des fonctions. Les fonctions executent une série d’instructions, qui sont rassemblées dans un seul bloc appelé fonction. Cela permet de rendre le script plus court et plus lisible. Une fonction peut être réutilisée à plusieurs endroits du programme.

    Parmi ces fonctions, certaines doivent être écrites en plaçant un argument entre les parenthèses. Cela permet de préciser leur comportement.

    **Qu6.: Dans le tableau précédent, quelle est LA fonction qui nécessite un argument? A quoi sert-il?

    Certaines instructions vont permettre des répétitions (famille des boucles), d’autres vont executer des branchements conditionnels (famille logique). Ce sont les mots clés while et if.

    Qu7.: Retrouver les familles pour chacun de ces 2 mots clés, if et while. Préciser: lequel va servir pour une instruction conditionnelle, executée une seule fois? Lequel sert à répéter un bloc de code (écrire dans la colonne execution)?

    mot clé famille execution
    if
    while

    Qu8: compléter le tableau avec la description de chacune des instructions:

    instruction description
    while True:
    if button_a.is_pressed():

    Le bloc suivant permet de personnaliser l’image affichée:

    Lorsque l’on ajoute ce bloc au programme, cela insère les 2 lignes suivantes dans le script python:

    led_image = Image('00000:00000:00000:00000:00000')
    display.show(led_image)

    L’image est alors générée par la ligne led_image = Image('00000:00000:00000:00000:00000'). L’instruction display.show(led_image) va afficher cette image sur la carte microbit.

    Remplacer les 2 images du programme précédent (smiley happy/sad). Placer vos propres dessins, réalisés à partir de la matrice.

    Pour dessiner l’image, il faut cliquer dans les cellules de la matrice(pixels). Le bloc suivant affiche un Y sur la carte microbit.

    1. Quel est le code correspondant pour le Y?
    2. Programmez la carte afin qu’elle montre l’animation suivante:
    rotation droite

    rotation droite

    1. Recopier le code python qui est généré -> Qu9.

    Partie 2 : Projets utilisant le module radio

    Envoyer un message par ondes radio La carte microbit possède une antenne radio, ce qui lui permet d’emettre et de recevoir des messages.

    communication radio en reseau

    communication radio en reseau

    Projet 1: Animation à plusieurs cartes microbit

    Utiliser le module radio de la carte microbit pour afficher un dessin glissant sur plusieurs cartes.

    Il faudra synchroniser l’animation, afin de provoquer cet effet de glissement de l’image. Par exemple, déclencher l’animation sur la carte 2 lorsque le dessin sort de la carte 1.

    Projet 2: Communication confidentielle

    Vous allez envoyer un message dans le reseau de cartes. L’une de ces cartes est une carte mystère. Celle-ci est programmée pour repondre lorsqu’elle reçoit le message “Hello”.

    Vous cherchez à découvrir ce que la carte mystère va répondre. Aussi, vous allez programmer votre carte pour qu’elle emette le mot “Hello”, et qu’elle n’affiche que les mots différents de “Hello”: c’est à dire les messages qui proviennent de la carte mystère…

    Voici le programme que vous devrez saisir:

    programme complet

    programme complet

    Dans le menu Variables, créer une nouvelle variable que vous nommerez n.

    Créez 2 autres variables que vous nommerez texte et message.

    Ajouter l’instruction Affecter à n la valeur " “.

    Saisir une valeur numerique à 2 chiffres dans ce bloc. Ce sera votre identifiant. Cette valeur doit être unique, personne ne devra avoir la même parmi les autres cartes du reseau. (L’exemple suivant sera traité avec la valeur 19).

    Ne pas choisir 19: ce nombre doit être différent pour chacune des cartes élèves de la classe.

    Ajouter l’instruction Affecter à texte la valeur " “.

    La variable n se trouve dans la liste des blocs du menu Variables

    La variable n se trouve dans la liste des blocs du menu Variables

    Ajouter la variable n dans ce bloc.

    Ajouter alors les blocs suivants pour finir la partie Au demarrage:

    Ces instructions permettent de construire la variable message par collage des 2 chaines de caractère, n et texte.

    n = '19'
    message = n
    texte = 'Hello'
    message = message + texte

    Un langage informatique utilise des variables. Ce sont des caractères ou des mots, qui n’existent pas dans le langage, et que vous choisissez pour y stocker une valeur. En langage Python, le signe ‘=’ devant une variable indique que l’on stocke la valeur de droite dans la variable ecrite à gauche:

    jour = 'lundi'

    Cette instruction signifie que l’on stocke le mot ’lundi’ dans la variable jour.

    Question a: Quelles sont les variables utilisées dans ce programme?

    Question b: Quelles chaines de caractères sont stockées dans les variables lors des 3 premieres instructions:

    n = '19'
    message = n
    texte = 'Hello'

    Question c: Quel est le contenu de la variable message apres la dernière instruction?

    message = message + texte

    Poursuivre la programmation: Dans la partie Répéter indefiniment:

    Ajouter les blocs qui permettront d’envoyer par radio la chaine message.

    Remplacer le texte par la variable message

    Remplacer le texte par la variable message

    Ajouter les blocs qui vont traiter les messages radio reçus (s’il y en a):

    • Ajouter le bloc [radio] si une chaine est reçu dans stringData alors:

    • Puis, pour obtenir la condition si dans la chaine strigData obtenir la sous-chaine…, vous allez passer par les étapes suivantes:

    choisir la variable stringData

    choisir la variable stringData

    Placer ce bloc dans l’instruction conditionnelle:

    Rechercher l’instruction suivante dans le menu Textes:

    il faudra probablement remplacer la variable proposée

    il faudra probablement remplacer la variable proposée

    Choisir la variable stringData

    Choisir la sous-chaine depuis la premiere lettre:

    Dans le menu math, trouver le selecteur de valeur numerique:

    mettre la valeur 1

    mettre la valeur 1

    Modifier le signe (mettre =) et compléter l’instruction avec la variable n:

    Téléverser et tester le programme.

    Question d: Vous devriez recevoir un message personnalisé de la carte microbit mystère. BRAVO!! Recopiez ce message.

    Question e: Le programme utilise des instructions apportées par la librairie radio, utiles pour la programmation de la carte microbit.

    Quel est le rôle des fonctions suivantes: Recopier et compléter le tableau:

    instruction description
    send
    receive

    Question f: Quel est le rôle de la variable stringData? (Que contient-elle?)

    Compléments: Configuration radio

    radio.config(channel=7): Configure la fréquence d’émission : la valeur est un numéro entre 0 et 83

    radio.config(group=0): Configure le groupe : au sein d’une même adresse, 256 groupes numérotés de 0 à 255 peuvent cohabiter`

    Programme de la carte MB mystere

    notes pour l’enseignant

    Programme de la carte eleve

    Correction à venir

    Programme de la carte enseignant

    from microbit import *
    import radio
    import utime
    """
    # chaque carte eleve recoit son propre message
    # meme apres plusieurs appuis successifs sur le btn a
    # son id est stocke dans le dict D
    """
    radio.on()
    
    radio.config(channel = 7, power = 6, length = 32, group=0)
    i = 0
    L = ['mardi', 'juillet', 'but'] # ...liste de mots mysteres a completer
    l = len(L)
    D = {}
    n_precedent = 0
    
    while True:
      stringData = radio.receive()
      if stringData:
        n = stringData[:2]
        if n_precedent != n:
          if n not in D.keys():
            D[n] = [L[i%l],3]
          message = stringData[:2]+ " " + D[n][0]
          i += 1
          radio.send(message)
          utime.sleep(0.5)
          display.clear()
          # repere pour avoir le nombre de message retournes
          display.set_pixel(i%5,(i%25)//5,9)
          n_precedent = n
        elif n_precedent == n and D[n][1]>0: 
            # gestion d'un appui prolongé
            D[n][1] -= 1
        elif n_precedent == n and D[n][1]<=0:
            D[n][1] = 3
            n_precedent = 0
            # RAZ du TTL et id precedent
            # on renvoie le mot

    Liens

    reseau radio 1ere

    Communication radio

    Une présentation générale de la carte microbit et des editeurs pour sa programmation se trouve à la page MB_init. Ce TP fait suite à celui de SNT, à la page MB radio.

    La carte microbit possède une antenne radio, ce qui lui permet d’emettre et de recevoir des messages:

    source: microbit.org

    source: microbit.org

    Prise en main de l’interface microbit sur Vittascience

    Ce premier travail permet de découvrir l’interface Vittascience.com pour la programmation de la carte microbit. Les questions qui suivent cette manipulation vont permettre d’approfondir les connaissances en langage Python. Les projets qui complètent cette séquence se basent sur la partie RESEAUX du programme (protocole HTTP, securité des transmissions)

    • Aller à la page Editeur microbit sur Vittascience.com

    • Brancher la carte microbit sur l’un des ports USB de l’ordinateur. La carte est alors visible depuis l’explorateur comme une nouvelle mémoire flash.

    Réseau privé, public

    Programmation du script initial

    Créer pas à pas le programme suivant à l’aide de l’Editeur microbit sur Vittascience.com

    communication radio en reseau

    communication radio en reseau

    Commencer par écrire les instructions de debut du programme (ne sont executées qu’une seule fois, au démarrage).

    Puis ajouter les instructions de la boucle principale: d’abord les instructions d’émission:

    Puis les instructions de reception:

    Retrouver la variable stringData dans les Variables

    Placer la variable stringData dans l’expression conditionnelle:

    Retrouver le paramètre " " dans le menu Texte

    Remplacer le paramètre 1 par le caractère “1”:

    Puis les instructions pour le comportement de la carte selon le message reçu:

    A. Téléverser et tester le programme.

    B. Compléter le code python obtenu:

    from microbit import *
    import radio
    import utime
    
    radio.on()
    radio.config(channel = 7, power = 6, length = 32, group=0)
    print('Bonjour !' + "")
    
    while ...:
      if button_a.is_pressed():
        ...
      if button_b.is_pressed():
        ...
      stringData = radio.receive()
      if stringData:
        if stringData == '1':
          display.show(...
          utime.sleep(0.015)
          display.clear()
        elif stringData == '2':
          display.show(...
          utime.sleep(0.015)
          display.clear()
    1. Quel est la signification de chacune des instructions suivantes?
    instruction description
    if stringData:
    if stringData == '1':
    1. Le programme utilise des instructions apportées par les librairies radio et utime, utiles pour la programmation de la carte microbit.
    • Quel est le rôle des fonctions suivantes: Recopier et compléter le tableau:
    instruction description
    send
    receive
    sleep
    • Quel est le rôle de la variable stringData? (Que contient-elle?)
    1. Analyse du programme: Décrire le programme avec un diagramme d’activité.

    2. Ce programme, comment devrait-il fonctionner? Quel-s problème-s voyez-vous lorsque plusieurs cartes microbits fonctionnent de concert, avec ce même programme?

    Pour communiquer à 2 cartes microbit, dans un reseau privé, vous pouvez choisir votre valeur pour radio.config(group=0), comme par exemple radio.config(group=1), … (maximum 255).

    1. Choisir le-s terme-s adapté-s parmi les mots suivants: il s’agit d’un problème de…
    • intégrité
    • authenticité
    • confidentialité

    Projet 1: Générateur de messages

    But: On améliore le dispositif pour faire une selection parmi plusieurs messages (au moins 3). Les messages peuvent être des textes brefs, ou bien des messages de reaction de type LIKE/ UNLIKE.

    discussion

    discussion

    Compléments théoriques: index modulo avec %

    Cette fois, le nombre de messages possibles est supérieur au nombre de boutons (3 messages pour 2 boutons).

    Nous allons utiliser une liste de messages. Pour acceder à un element de cette liste, nous allons utiliser un index. Exemple:

    # declaration de la liste
    L = ['mon message a envoyer', 'LIKE', 'UNLIKE']
    # acceder a l'un des elements de la liste:
    # 1er element: index 0
    print(L[0])
    # 2e element: index 1
    print(L[1])
    # 3e element: index 2
    print(L[2])
    # attention au depassement d'index de la liste
    # l'index 3 n'existe pas
    print(L[3])

    On peut utiliser un index numérique pour parcourir tous les éléments de la liste. Exemple:

    for i in range(len(L)):
      print(i,L[i])
    # affiche:
    0 mon message a envoyer
    1 LIKE
    2 UNLIKE

    Là aussi, avec un variant de boucle i qui depasse 2, cela va générer une erreur:

    for i in range(10):
      print(i,L[i])
    # affiche:
    0 mon message a envoyer
    1 LIKE
    2 UNLIKE
    # IndexError

    Pour eviter de depasser l’index maximum de la liste, utiliser l’opérateur modulo:

    for i in range(10):
      j = i % 3
      print(i,j,L[j])
    # affiche
    0 0  mon message a envoyer
    1 1  LIKE
    2 2  UNLIKE
    3 0  mon message a envoyer
    4 1  LIKE
    5 2  UNLIKE
    6 0  mon message a envoyer
    7 1  LIKE
    8 2  UNLIKE
    9 0  mon message a envoyer

    On a alors une selection periodique des éléments de liste.

    Programmation de la carte microbit

    Utiliser maintenant l’interface Python sur Vittascience.com pour réaliser les modifications.

    • Bloc “Au démarrage”: régler les cartes par binome sur le même reseau (même canal, et même group).
    • Dans le bloc: Répéter indéfiniment (while True), il faudra modifier le rôle des boutons et le comportement lorsqu’un message est reçu.
    rôle des boutons a et b

    rôle des boutons a et b

    Bouton a

    • le bouton_a sert à selectionner le message dans une liste, en passant au message suivant dans la liste. L’indice est calculé selon une règle d’arithmétique modulaire. Voici un extrait du script à utiliser:
    # a placer au "demarrage"
    L = ['message', 'like', 'unlike']
    i = 0
    ...
    # a placer dans le bloc "repeter indefiniment"
    if button_a.is_pressed():
      i = (i+1)%3
    ...
    if button_b.is_pressed():
      radio.send(L[i])
    • [En option] Ajout d’un repère visuel: On peut ajouter un repère visuel pour la selection du message. On éclaire alors la diode de la première ligne (y=0), dont la position x correspond à l’index x=i. Cela donne: display.set_pixel(i,0,9)
    if button_a.is_pressed():
      i = (i+1)%3
      display.clear()
      display.set_pixel(i,0,9)
      utime.sleep(0.2)

    Les 2 autres instructions servent à effacer l’écran display.clear(), et à placer un délai d’attente utime.sleep(0.2), necessaire pour eviter de nombreux appuis prolongés sur le bouton.

    Bouton b

    • Le bouton_b servira à envoyer le message.
    if button_b.is_pressed():
        radio.send(messages[i])
    • On pourra placer un repère visuel qui montre l’envoi du message:
    if button_b.is_pressed():
        radio.send(messages[i])
        display.show([Image.DIAMOND,Image.DIAMOND_SMALL],delay=100)
        utime.sleep(0.015)
        display.clear()

    Reception d’un message

    Lorsqu’un message est reçu:

    • if, si c’est ’like’, on affiche un smiley happy
    • elif, sinon si c’est ‘unlike’, on affiche un smiley triste
    • else, sinon, c’est un message textuel, on l’affiche avec display.scroll(stringData)

    Vous avez reussi à échanger des messages avec votre binôme? Poursuivre cette séance avec les 2 projets suivants.

    Projet 2: Auteurs authentifiés

    But: Utiliser une règle d’authentification entre 2 cartes de votre réseau privé.

    Votre reseau privé n’est pas à l’abris d’un utilisateur non invité. Vous souhaiteriez alors savoir de QUI vient le message reçu.

    L’idée est d’utiliser la chaine de caractère émise pour y placer des informations, en plus du message. Ces informations pourraient identifier la carte émettrice. Ainsi, plutôt que d’envoyer:

    "le lundi ne mange pas a la cantine"

    la carte n°1 enverra:

    "1_le lundi ne mange pas a la cantine"

    Le programme recepteur pourra afficher la chaine de caractère entière, renseignant à la fois le numéro de la carte emettrice ET le message.

    Pour lire le numéro au début du message, il faudra PARSER la chaine reçue. Parser signifie: diviser une chaîne de caractères en une liste ordonnée de sous-chaînes.

    Python offre une multitude de possibilités pour travailler avec des chaînes de caractères (strings): voir page du cours python sur les variables et string

    Rappels: Comment parser une chaine?

    Dans un notebook (Atrium > Capytale) ou bien basthon.fr/, saisir les lignes suivantes:

    • Composer le message:
    n = 1
    texte = "la feve est dans la 3e part"
    message = str(n) + "_" + texte
    print(message)
    • Parser le message avec un Slice:

    Il faudra tranformer la chaine "1_la feve est dans la 3e part" en 2 chaines: "1" et "la feve est dans la 3e part".

    message = "1_la feve est dans la 3e part"
    n = message[0]
    # selection du 1er caractere
    print(n) # affiche: 1
    message = message[2:]
    # slice du 3e caractere au dernier
    print(message) # affiche: la feve est dans la 3e part
    # on a extrait le numero au debut du message, et reduit le message
    print("la carte n°",n," vous informe que\n", message)
    • Ou mieux, parser le message avec la méthode de chaine split:
    message = "1_la feve est dans la 3e part"
    L = message.split('_')
    # L vaut ['1','la feve est dans la 3e part']
    n = L[0]
    message = L[1]

    Pour traiter un message dont l’identifiant numérique est composé de 2 chiffres: Quelle méthode vaut-il mieux privilegier?

    Programmation de la carte microbit

    Adapter le programme pour permettre une communication avec un auteur authentifié dans un reseau à plusieurs cartes.

    Vous allez mettre 2 cartes microbits ou plus dans un même réseau privé (Réglage dans l’instruction radio.config(channel = 7, power = 6, length = 32, group=0)). Choisir le même channel et le même group pour les cartes microbit du même groupe.

    Utiliser l’interface Python sur Vittascience.com.

    A partir du programme initial, apporter les modifications pour:

    1. Choisir un numero pour votre groupe privé que vous placerez dans groupe_prive. Modifiez votre message à envoyer.
    2. Ecrire une fonction parse qui prend en paramètre une chaine de caractère message, et un caractère de separation sep. Cette fonction doit retourner une liste L constituée de 2 éléments: L[0] contient le numero du groupe et L[1] le message placé après le caractère de séparation.
    3. Ajouter à votre script la fonction test_parse() qui teste le bon fonctionnement de la fonction parse:
    def test_parse():
      assert parse("1_les carrotes sont cuites","_") == ["1","les carrotes sont cuites"]
      assert parse("1_2_3","_") == ["1","2"]

    Ajouter aussi l’appel de la fonction parse_test() dans le corps de votre programme.

    1. Lorsque l’on appuie sur le bouton b: envoyer un message avec un numero d’identification à 2 chiffres. Ce numero doit être le même pour toutes les cartes microbits du même reseau privé. Le message sera mis en forme avec str(groupe_prive) + "_" + message
    2. parser et afficher tout message qui commence par le bon identifiant, pas les autres messages reçus. Il faudra utiliser une instruction conditionnelle sur le numéro de carte pour afficher (ou non) le message.

    Votre script devrait avoir les instructions suivantes:

    from microbit import *
    import radio
    import utime
    
    groupe_prive = ...
    radio.on()
    radio.config(channel = 7, power = 6, length = 32, group=groupe_prive)
    message = "message a personnaliser" # personnalisez votre message
    
    def parse(message,sep):
      """retourne une liste constituée de 2 elements
      decoupe de la chaine message autour du caractere sep
      """
      pass
    
    def test_parse():
      assert parse("1_les carrotes sont cuites","_") == ["1","les carrotes sont cuites"]
      assert parse("1_2_3","_") == ["1","2"]
    
    test_parse()
    
    while True:
      if button_b.is_pressed():
        radio.send(...
      stringData = radio.receive()
      if stringData:
        ...

    Tester le bon fonctionnement de votre programme dans un reseau contenant plusieurs cartes microbits. Décrivez le reseau (nombre de cartes microbit de chaque groupe et numeros de ces groupes).

    Projet 3: Chiffrement

    But: réaliser une communication privée dans un reseau public.

    Premier programme utilisant un notebook python

    Chiffrer / Code Cesar: Le code César réalise une permutation des caractères, selon leur rang (table ASCII), grâce à une clé de chiffrement/ déchiffrement.

    Les fonctions utiles du langage sont: ord et chr:

    >>> ord('a')
    97
    >>> chr(98)
    'b'
    >>> chr(122)
    'z'

    Pour utiliser une clé de chiffrement, il sera nécessaire d’utiliser un décalage avec un modulo(26) afin d’obtenir une lettre chiffrée dans l’alphabet a-z:

    no_lettre = ord(lettre)
    chiffre = no_lettre + cle # decalage sans modulo, depassement possible
    chiffre = (lettre + cle)%26 # decalage avec modulo 26, chiffre de 0 à 25
    chiffre = (lettre-97 + cle)%26 + 97 # decalage avec modulo 26, chiffre de 97 à (97 + 25) = 122

    Comme l’alphabet a-z va du rang 97 à 122 dans la table ascii, on choisira la 3e méthode:

    chiffre = (lettre-97 + cle)%26 + 97

    Créer une fonction de chiffrement appelée chiffre, qui retourne la lettre chiffrée selon les arguments lettre (lettre en clair) et cle (la clé de chiffrement).

    La fonction chiffre peut aussi servir à déchiffrer. Il suffira de remplacer la clé de chiffrement par son opposé: $3 => -3$.

    Assurez vous à l’aide de quelques tests, que la fonction donne de bons résultats, pour chiffrer et dechiffrer un caractère.

    Créer une fonction de chiffrement appelée chiffre_texte, qui retourne la texte chiffré. La fonction aura pour arguments: texte (texte en clair) et cle (la clé de chiffrement).

    Assurez vous à l’aide de quelques tests, que la fonction donne de bons résultats, pour chiffrer et dechiffrer un texte.

    Programmation de la carte microbit

    Vittascience.com

    Adapter le programme pour permettre une communication confidentielle entre 2 cartes microbit. Décrire le programme avec un diagramme d’état.

    Compléments

    radio.config(channel=7): Configure la fréquence d’émission : la valeur est un numéro entre 0 et 83

    radio.config(group=0): Configure le groupe : au sein d’une même adresse, 256 groupes numérotés de 0 à 255 peuvent cohabiter`

    programme de base pour faire communiquer 2 cartes microbit:

    from microbit import *
    import radio
    import utime
    
    radio.on()
    radio.config(channel = 7, power = 6, length = 32, group=0)
    print('Bonjour !' + "")
    
    while True:
      if button_a.is_pressed():
        radio.send('1')
      if button_b.is_pressed():
        radio.send('2')
      stringData = radio.receive()
      if stringData:
        if stringData == '1':
          display.show(Image.HAPPY)
          utime.sleep(0.015)
          display.clear()
        elif stringData == '2':
          display.show(Image.SAD)
          utime.sleep(0.015)
          display.clear()

    Le reseau mesh

    D’après un article du Monde (02/05/2026)

    Comment pourrait-on réaliser un reseau mesh pour la ville de Nice? Expliquer ce qu’il faudrait utiliser en terme de matériel, de noeuds du reseau, ainsi qu’en terme de logiciels, pour assurer l’intégrité et la confidentialité.

    Liens

    reseau radio term

    Séance qui comporte 3 TP:

    Communication radio

    Une présentation générale de la carte microbit et des editeurs pour sa programmation se trouve à la page MB_init. Ce TP fait suite à celui de 1ere NSI, à la page MB radio2.

    La carte microbit possède une antenne radio, ce qui lui permet d’emettre et de recevoir des messages:

    source: microbit.org

    source: microbit.org

    Prise en main de l’interface microbit sur Vittascience

    Ce premier travail permet de découvrir l’interface Vittascience.com pour la programmation de la carte microbit. Les questions qui suivent cette manipulation vont permettre d’approfondir les connaissances en langage Python. Les projets qui complètent cette séquence se basent sur la partie RESEAUX du programme (protocole HTTP, securité des transmissions)

    • Aller à la page Editeur microbit sur Vittascience.com

    • Brancher la carte microbit sur l’un des ports USB de l’ordinateur. La carte est alors visible depuis l’explorateur comme une nouvelle mémoire flash.

    Réseau social, public

    Programmation du script initial

    Copier-coller le programme suivant à l’aide de l’Editeur microbit sur Vittascience.com

    communication radio en reseau

    communication radio en reseau

    from microbit import *
    import radio
    import utime
    
    # variables globales
    ch = 7
    gpe = 0
    messages = ['lundi','LIKE','UNLIKE']
    i = 0
    img = [Image.DIAMOND,Image.DIAMOND_SMALL]
    # parametres radio
    radio.on()
    radio.config(channel = ch, power = 6, length = 32, group=gpe)
    
    while True:
      if button_a.is_pressed():
        display.clear()
        l = len(messages)
        i = (i + 1) % l
        display.set_pixel(i,0,9)
        utime.sleep(0.2)
      if button_b.is_pressed():
        radio.send(messages[i])
        display.show(img,delay=100)
        utime.sleep(0.015)
        display.clear()
        
    
      stringData = radio.receive()
      if stringData:
        if stringData == 'LIKE':
          display.show(Image.HAPPY)
          utime.sleep(0.2)
          display.clear()
        elif stringData == 'UNLIKE':
          display.show(Image.SAD)
          utime.sleep(0.2)
          display.clear()
        else:
          display.scroll(stringData)

    Téléverser et tester le programme.

    1. Quel est la signification de chacune des instructions suivantes?
    instruction description
    if stringData:
    if stringData == 'LIKE':
    1. Le programme utilise des instructions apportées par les librairies radio et utime, utiles pour la programmation de la carte microbit.
    • Quel est le rôle des fonctions suivantes: Recopier et compléter le tableau:
    instruction description
    send
    receive
    sleep
    • Quel est le rôle de la variable stringData? (Que contient-elle?)
    1. Selection de message: Expliquez le rôle des instructions suivantes:
    l = len(messages)
    i = (i + 1) % l
    1. Analyse du programme: Décrire le programme avec un diagramme d’activités (exemple à la page 4).

    2. Ce programme, comment devrait-il fonctionner? Quel-s problème-s voyez-vous lorsque plusieurs cartes microbits fonctionnent de concert, avec ce même programme?

    1. Choisir le-s terme-s adapté-s parmi les mots suivants: il s’agit d’un problème de…
    • intégrité
    • authenticité
    • confidentialité

    Programmation orientée objet

    On souhaite effacer du programme les variables globales. Les variables seront regroupées comme attributs de la classe Communication_radio. On ajoutera à cette classe les méthodes qui serviront à rendre le script plus concis.

    Voici le script que vous allez utiliser: Créer un nouveau fichier, coller ce nouveau script et complétez le pour qu’il soit fonctionnel.

    from microbit import *
    import radio
    import utime
    
    
    class Communication_radio:
      def __init__(self, # a completer)
        # a completer
      
      def message_suivant(self):
        # a completer
      
      def select_message(self):
        # a completer
      
      def img_send(self):
        # a completer
    
    
    com = Communication_radio(7,0,['lundi','LIKE','UNLIKE'])
    radio.on()
    radio.config(channel = com.channel, power = 6, length = 32, group=com.group)
       
    while True:
      if button_a.is_pressed():
        com.message_suivant()
      if button_b.is_pressed():
        radio.send(com.select_message())
        com.img_send() # affiche l'animation lors de l'envoi du message
    
      stringData = radio.receive()
      if stringData:
        if stringData == 'LIKE':
          display.show(Image.HAPPY)
          utime.sleep(0.2)
          display.clear()
        elif stringData == 'UNLIKE':
          display.show(Image.SAD)
          utime.sleep(0.2)
          display.clear()
        else:
          display.scroll(stringData)

    Question: quelles sont les différentes méthodes que vous pouvez envisager pour que la communication entre 2 cartes microbit reste confidentielle?

    Projets

    Poursuivre cette séance avec les 2 projets suivants.

    Compléments

    radio.config(channel=7): Configure la fréquence d’émission : la valeur est un numéro entre 0 et 83

    radio.config(group=0): Configure le groupe : au sein d’une même adresse, 256 groupes numérotés de 0 à 255 peuvent cohabiter`

    Liens

    Chiffrement

    Séance qui comporte 3 TP:

    Projet 2: Chiffrement

    But: réaliser une communication privée dans un reseau public.

    Premier programme utilisant un notebook python

    Chiffrer / Code Cesar: Le code César réalise une permutation des caractères, selon leur rang (table ASCII), grâce à une clé de chiffrement/ déchiffrement.

    Les fonctions utiles du langage sont: ord et chr:

    >>> ord('a')
    97
    >>> chr(98)
    'b'
    >>> chr(122)
    'z'

    Pour utiliser une clé de chiffrement, il sera nécessaire d’utiliser un décalage avec un modulo(26) afin d’obtenir une lettre chiffrée dans l’alphabet a-z:

    no_lettre = ord(lettre)
    chiffre = no_lettre + cle # decalage sans modulo, depassement possible
    chiffre = (lettre + cle)%26 # decalage avec modulo 26, chiffre de 0 à 25
    chiffre = (lettre-97 + cle)%26 + 97 # decalage avec modulo 26, chiffre de 97 à (97 + 25) = 122

    Comme l’alphabet a-z va du rang 97 à 122 dans la table ascii, on choisira la 3e méthode:

    chiffre = (lettre-97 + cle)%26 + 97

    Créer une fonction de chiffrement appelée chiffre, qui retourne la lettre chiffrée selon les arguments lettre (lettre en clair) et cle (la clé de chiffrement).

    La fonction chiffre peut aussi servir à déchiffrer. Il suffira de remplacer la clé de chiffrement par son opposé: $3 => -3$.

    Assurez vous à l’aide de quelques tests, que la fonction donne de bons résultats, pour chiffrer et dechiffrer un caractère.

    Créer une fonction de chiffrement appelée chiffre_texte, qui retourne la texte chiffré. La fonction aura pour arguments: texte (texte en clair) et cle (la clé de chiffrement).

    Assurez vous à l’aide de quelques tests, que la fonction donne de bons résultats, pour chiffrer et dechiffrer un texte.

    Programmation de la carte microbit

    Editeur Vittascience.com

    Adapter le programme pour permettre une communication confidentielle entre 2 cartes microbit. Décrire le programme avec un diagramme d’état.

    Projet 3: Compteur de likes

    Programme

    On considère le réseau social de type “X (ex Twitter)” dans lequel A, B, C, et D sont des usagers (des twittos)

    • A suit B
    • B suit C
    • C suit A et B
    • D suit B

    La structure de données sera un dictionnaire Python:

    # un exemple de dictionnaire représentant un graphe à 4 cartes
    G = {'A':['B'],'B':['C'],'C':['A','B'],'D':['B']}

    Vous allez expérimenter la chaine de messages dans ce réseau social.

    • Chaque twittos envoie, régulièrement, un message sur le reseau:

    Ce message contient pour unique contenu le mot Publi. L’émetteur du message devra s’identifier lorsqu’il fait une publi:

    # pour le twittos B
    radio.send("B_Publi")

    Lorsque A reçoit un message de B (c’est à dire le message qui commence par "B"): comme "B" est dans sa liste self.reseau['A'], A envoie un like à B. (un message “B_LIKE”`). Et affiche un smiley HAPPY:

    display.show(Image.HEART)
    utime.sleep(0.2)
    display.clear()

    Si B reçoit le message "B_LIKE". Il verifie que le premier caractère n correspond à son propre numero de carte (n == self.numero). il affiche un COEUR, puis la valeur de son compteur, incrémentée de 1.

    Démarrer le programme de manière synchrone sur chaque carte microbit du reseau. Faites une publication de manière régulière (chronométer). Expérimenter pendant 2 à 5 minutes, puis relever les valeurs des compteurs sur chaque carte.

    Les valeurs sont-elles en accord avec la structure du reseau?

    Redigez une description de votre programme, de votre experimentation, ainsi qu’un commentaire des résultats.

    Aide

    On utilisera la classe:

    class Communication_radio:
      def __init__(self, ch=7,gpe=0,messages=['LIKE','Publi'],numero='A', reseau = {'A':['B'],'B':['A']}):
        self.channel = ch
        self.group = gpe
        self.messages = messages
        self.img = [Image.DIAMOND,Image.DIAMOND_SMALL]
        self.numero = numero
        self.reseau = reseau
        self.compteur = 0
      
      def select_message(self):
        message_complet = str(self.numero) + "_" + self.messages[1]
        return message_complet
      
      def img_send(self):
        display.show(self.img,delay=100)
        utime.sleep(0.015)
        display.clear()
        
      def parse(self,stringData):
        """decoupage de stringData en une chaine n ('A, 'B', ...)
        et un texte grace a la methode split('_')
        returns:
        --------
        - etat du compteur +1 si n == self.numero ET texte == 'LIKE'
        - 'LIKE' si n est le numero d'un compte suivi ET texte == 'Publi'. Et emission radio avec radio.send('n_LIKE')
        - '', string vide, si n ne correspond a aucun des 2 cas precedents
        """
        # a completer

    Le travail demandé consiste alors à compléter la méthode de classe parse. Il est conseillé de bien comprendre la correction du Projet 1 avant de commencer: Solution du projet_authentifier_POO.py

    Après l’import des librairies, et la déclaration de la classe Communication_radio, le programme sera le suivant:

    # Attention a changer le 4e argument par la lettre attribuee a votre carte ('A', 'B', ...)
    # modifier aussi le reseau {'A':['B'],'B':['A']} si vous avez plus
    # de 4 cartes
    com = Communication_radio(7,0,['LIKE','Publi'],'B',{'A':['B'],'B':['A']})
    radio.on()
    radio.config(channel = com.channel, power = 6, length = 32, group=com.group)
       
    while True:
      if button_a.is_pressed():
        radio.send(com.select_message())
        com.img_send() # affiche l'animation lors de l'envoi du message
    
      stringData = radio.receive()
      if stringData:
        texte = com.parse(stringData)
        if texte == 'LIKE':
          display.show(Image.HAPPY)
          utime.sleep(0.4)
          display.clear()
        else:
            display.scroll(texte)
            utime.sleep(0.4)
            display.clear()  

    Correction: script

    Sous-sections de Robotique

    Robotique

    Robot maqueen

    Prise en main du robot

    logo logo

    Programmer un robot a pour but de lui faire réaliser des tâches autonomes, répétitives. Il va prendre des décisions en fonction de son environnement grâce à un algorithme.

    La programmation se fera sur l’editeur Vittascience.com

    Selon la tâche à executer, il faudra bien distinguer les instructions que le robot n’execute qu’une seule fois, et celles qu’il devra répéter indéfiniment.

    disposer les instruction dans le bon bloc de code

    disposer les instruction dans le bon bloc de code

    Défi n°1: S’arrêter au parking

    Le robot peut être prévu pour circuler selon une couleur marquée au sol.

    • les différentes fonctions d’actions des moteurs sont dans le menu Robots de la page de l’editeur Vittascience.com

    Le menu Robots propose les instructions de plusieurs robots. Le votre s’appelle Maqueen.

    • [Maqueen] Contrôler le robot avancer vitesse 50
    la valeur de vitesse est un paramètre ajustable. Mettre 50

    la valeur de vitesse est un paramètre ajustable. Mettre 50

    • [Maqueen] Arrêter le robot

    Dans le menu Entrees/Sorties, choisir le bloc attendre 1 seconde-s, et réaliser le programme suivant:

    Tester ce premier programme avec le robot maqueen. Puis démarrer un nouveau projet pour stopper le robot dans une zone noire.

    Pour ce défi:

    • Votre programme utilise une structure conditionnelle: retrouvez celle-ci dans le menu logique.

    Le robot dispose de 2 capteurs d’intensité lumineuse, sous le chassis.

    La mesure de l’état du capteur de ligne, sous le robot se fait grâce à la fonction:

    • [Maqueen] Etat du capteur ligne droit / gauche

    Cette instruction renvoie un booléen (True, False), qui sera affectée à une variable. Créez 2 nouvelles variables, G et D.

    • Affecter les instructions des capteurs de ligne à chacune de ces variables:

    On place alors ces variables dans une structure conditionnelle (si G ET D faire…):

    Si le capteur G vaut True et le capteur D vaut True: avancer

    Si le capteur G vaut True et le capteur D vaut True: avancer

    à vous de jouer: Créez un programme qui fait avancer le robot tant qu’il est sur une piste blanche. Et qui s’arrête lorsqu’il est sur son parking, noir.

    Vous avez reussi?

    • Sauvegardez le programme dans vos documents.
    • Et recopier le script sur votre cahier.

    Défi n°2: Suivi de ligne

    Le robot peut circuler en suivant une courbe peinte au sol.

    Une différence de clarté sous le robot (bord du chemin) permet de programmer un virage du robot.

    Il faudra alors placer les instructions de commande du moteur Droit et Gauche dans une sequence d’intructions conditionnelles.

    if
    ...
    elif
    ...
    else

    Pour faire pivoter le robot, il faudra contrôler différement chaque moteur (Droit / Gauche). Utiliser:

    • [Maqueen] Contrôler le moteur gauche direction … vitesse 50

    à vous de jouer: Créer un deuxième programme qui fera:

    • tourner le robot vers la droite lorsqu’il se trouve dans la situation suivante:
    blanc/noir => virage a droite

    blanc/noir => virage a droite

    • tourner vers la gauche dans la situation inverse
    • sinon: avancer tout droit lorsque les 2 capteurs mesurent la même couleur noire, ou blanche.

    Tester alors votre programme sur une piste circulaire.

    Votre robot fait le tour entierement? Vous avez relevé le premier défi!

    Travail: Recopier le script python dans un fichier .txt

    Aide: detection de la ligne noire

    Avant le défi n°3: Programmer en python

    D’autres fonctions du robot peuvent être exploitées pour réaliser d’autres tâches. Par exemple:

    • [Maqueen] Pivoter à droite
    • [Maqueen] Avancer d’une case

    Pour la suite, il sera utile de partir du programme réalisé avec les blocs (Vittascience), puis d’adapter, modifier certains paramètre à la main, directement dans le script python.

    Vous devrez vous familiariser avec les instructions en python spécifiques au robot marqueen.

    Editeur Vittascience.com. Placer l’une des commandes du robot dans le bloc “Au demarrage”. Et lire le script python généré.

    Travail: Copiez le contenu du document maqueen.py. Coller les instructions dans votre fichier .txt. Et complétez le avec les instructions python des différents blocs.

    Certaines commandes necessitent la declaration de fonctions, et occupent plusieurs lignes d’instructions.

    Défi n°3: Avancer d’une case

    Pour programmer les deplacements du robot indépendemment du marquage au sol, il sera necessaire de calibrer la longueur de ses deplacements.

    Ouvrir un nouveau projet et mettre dans le bloc “Au demarrage”, l’instruction “avancer d’une case”. La longueur parcourue correspond-elle à la dimension d’une case sur le support?

    Les paramètres doivent être ajustés dans le script python (blocs inopérants pour ajustements).

    La longueur du deplacement dépend de la durée d’attente utime.sleep_ms(int(15e-2/speed_mps*1000)) dans la fonction maqueen_moveWithSquare.

    Passer en mode programmation python. Ne plus revenir sur l’interface avec les blocs. Modifier le script python et tester avec le robot. Quelle(s) modification(s) lui permet(ent) d’avancer d’une case sur le support?

    De la même manière, il sera utile de calibrer l’angle de rotation lors de la commande de pivot à droite ou à gauche.

    Travail: Créer le programme qui permet au robot de suivre un chemin proposé, comme sur l’image plus haut. Utiliser une LISTE python comme structure de données pour placer les consignes de parcours (ex: chemin = [1,1,1,2,1,1,2,1,1,3,1]). Ce parcours doit utiliser les cases du support.

    Recopier le script dans votre fichier .txt

    Défi 4: Enregister des données

    L’enregistrement de données peut être utile pour calibrer les capteurs du robot.

    Le programme suivant peut être chargé dans l’interface Vittascience.com. Télécharger le fichier. Puis l’ouvrir depuis l’interface.

    • La fonction getUltrasonicData permet de mesurer une distance/un temps selon le paramètre data.
    • Pour écrire des données sur la carte, ce sont les fonctions:
      • log.set_labels: definition des colonnes du tableau de mesure
      • log.add pour ajouter une entrée dans le tableau

    On utilisera alors l’explorateur (windows) pour ouvrir et visualiser les données, dans un fichier d’extension .html

    from microbit import *
    import log
    import utime
    from machine import time_pulse_us
    
    """ Maqueen robot """
    
    # Ultrasonic TRIG on pin1
    # Ultrasonic ECHO on pin2
    
    def getUltrasonicData(trig, echo, data='distance', timeout_us=30000):
      trig.write_digital(0)
      utime.sleep_us(2)
      trig.write_digital(1)
      utime.sleep_us(10)
      trig.write_digital(0)
      echo.read_digital()
      duration = time_pulse_us(echo, 1, timeout_us)/1e6 # t_echo in seconds
      if duration > 0:
        if data == 'distance':
          #sound speed, round-trip/2, get in cm
          return 343 * duration/2 * 100
        elif data == 'duration':
          return duration
        else:
          raise ValueError("Data option '" + data + "' is not valid")
      else:
        return -1
    
    log.set_labels('distance', timestamp=log.MILLISECONDS)
    log.set_labels('temps', timestamp=log.MILLISECONDS)
    i = 0
    
    while True:
      if button_a.is_pressed():
        log.delete(full=True)
        i = 0
      utime.sleep(1)
      d = getUltrasonicData(pin1, pin2, 'distance')
      if d > 0:
        log.add(distance = d,temps = i)
        i = i + 1
      display.scroll(str(d), delay=150, wait=True)

    Le format des données dans le fichier de log permet un traitement comme on le ferait pour un ficher txt ou csv.

    Suggestion de projets

    • Piloter le robot à l’aide d’une telecommande: on utilisera une 2e carte microbit pour telecommande. Les données seront transmises grâce à la fonction radio
    • Conduite autonome: le robot est capable d’avancer, et de s’arrêter seul lorsqu’il detecte un obstacle.
    • Course déclenchée par un clap
    • Evolution dans un labyrinthe
    • Programme d’exploration type robot aspirateur
    • Detection de formes (la forme de l’arêne dans laquelle est le robot)

    Avec quelques extensions, les actions du robot peuvent être complexifiées (detection de couleur, ramassage d’objets, …).

    Supports de tracés pour le robot

    • Documents pdf pour le robot suiveur de ligne: Lien vers pdf
    • Exemple de courbe à imprimer en format pdf
    • Exemple de courbe en format photoshop eps

    Exemple de programmes sur Vittasciences.com

    Liens

    Posts

    • Ce mini projet sera l’occasion de mettre en oeuvre les notions vues dans le cours précédent sur : la définition d’un objet en javascript la gestion des évènements l’utilisation d’une fonction callback avec un timer Vous pourrez également suivre ce tutoriel avec la video à l’adresse : lien video Afficher des éléments en javascript Contenu du dossier du projet D’abord, créer un dossier contenant :
    • Le DOM le DOM ou Document Object Model, une interface qui fait partie du BOM (Browser Object Model) et grâce à laquelle nous allons pouvoir manipuler le contenu HTML et les styles de nos pages. Le DOM est ainsi une représentation structurée du document sous forme « d’arbre » crée automatiquement par le navigateur, à partir de sa lecture du document HTML.
    • Algorithme des k plus proches voisins notebook Le notebook présenté ici se trouve à l’adresse tix06.github.io/jupyterlite_NSI Choisir le dossier TP4_data_analyse puis le notebook algoKNN.ipynb.
    • Notebooks associés algorithme de recherche de plus proches voisins KNN: algKnn algorithme de recommandation : algorithme de recommandation.md arbres de décision : graphes_mini_prog.md Intelligence artificielle (IA) L’intelligence artificielle désigne des algorithmes plus ou moins évolués qui traitent des problèmes dont la résolution fait appel à l’intelligence humaine. Ils imitent des actions humaines.
    • Algorithmes de recommandation Lien vers le notebook en ligne : https://mybinder.org/v2/gh/tix06/notebooks_classif/master Choisir alors le fichier : algorithme de recommandation.ipynb Il s’agit d’un cas très classique d’algorithme utilisé dans le web marketing. Un client choisit et met dans ses favoris un article, ou dans son panier. Le site lui propose des articles compatibles, ou similaires. La recommandation peut être basée sur la description de ces articles. L’algorithme va alors chercher les articles qui ont le plus de points communs dans leur description; c’est à dire le plus de mots communs dans leur description.
    • Arbres de classification Lien vers le notebook en ligne : https://mybinder.org/v2/gh/tix06/notebooks_classif/master Choisir alors le fichier : graphes_mini_prog.ipynb Définition Un arbre de classification est utile pour réaliser des prévisions de manière explicite. C’est un outil utilisé pour les algorithmes de backtracking (modéliser une partie d’echecs) pour l’appentissage automatisé (machine learning) supervisé (les classes des entrées sont connue) Pour le machine learning l’arbre peut évoluer et se restructurer à partir d’informations reçues.
    • tracer un arbre à partir d’une expression NPI NPI : notation polonaise inversée En particulier : on dispose d’une expression en NPI, du type : L3 = [7,8,’-’,6,’’,10,3,’+’,’’] Et on veut créer et afficher le graphe correspondant : On utilisera le script : L3 = [7,8,’-’,6,’’,10,3,’+’,’’] D = makeTree(L3) G = nx.Graph() graphDict(D) Dont l’instruction suivante va générer le dictionnaire à partir de l’expression NPI (fonction npiTree recursive):
    • tracé de graphes avec Networkx Les scripts suivants permettent de choisir entre plusieurs types de configuration pour tracer un graphe avec Networkx, module Python. On pourra choisir de personaliser : la couleur d’un noeud l’etiquette des noeuds l’étiquette des arêtes le type de trait (plein ou en pointillés) des arêtes Déclaration du graphe import matplotlib.pyplot as plt import networkx as nx from numpy import array G = nx.Graph() # definition des noeuds G.add_node(0,label=‘A’,col=‘pink’) G.add_node(1,label=‘B’,col=‘red’) G.add_node(2,label=‘C’,col=‘white’) G.add_node(3,label=‘D’,col=‘white’) G.add_node(4,label=‘E’,col=‘white’) G.add_node(5,label=‘F’,col=‘blue’) # definition des aretes G.add_edge(0,1,weight=6,styl=‘dashed’) G.add_edge(0,2,weight=5,styl=‘solid’) G.add_edge(0,4,weight=1,styl=‘solid’) G.add_edge(4,1,weight=5,styl=‘solid’) G.add_edge(4,2,weight=1,styl=‘solid’) G.add_edge(4,3,weight=3,styl=‘solid’) G.add_edge(2,3,weight=8,styl=‘solid’) G.add_edge(4,5,weight=6,styl=‘dashed’) G.add_edge(3,5,weight=9,styl=‘solid’) Exploration de la structure de données couleur des noeuds liste = list(G.nodes(data=‘col’)) colorNodes = {} for noeud in liste: colorNodes[noeud[0]]=noeud[1] colorNodes {0: ‘pink’, 1: ‘red’, 2: ‘white’, 3: ‘white’, 4: ‘white’, 5: ‘blue’} Pour les couleurs des noeuds, le format doit être en liste (de la taille du nombre de noeuds)
    • Créer et resoudre un labyrinthe Les scripts suivants permettent de créer un labyrinthe de manière aléatoire, et d’exploiter la structure de données de ce labyrinthe. On pourra ainsi tester quelques algorithmes relatifs au parcours de ce labyrinthe. Les scripts en permettent une visualisation. Définitions des classes class Pile: def init(self): self.lst = [] def empty(self): return self.lst == [] def push(self, x): self.lst.append(x) def pop(self): if self.empty(): raise ValueError(“pile vide”) return self.lst.pop() def explorer(laby): pile = Pile() pile.push((0, laby.q - 1)) laby.tab[0][laby.q - 1].etat = False while True: i, j = pile.pop() if i == laby.p - 1 and j == 0: break if j > 0 and laby.tab[i][j].S and laby.tab[i][j-1].etat: pile.push((i, j)) pile.push((i, j-1)) laby.tab[i][j-1].etat = False elif i < laby.p-1 and laby.tab[i][j].E and laby.tab[i+1][j].etat: pile.push((i, j)) pile.push((i+1, j)) laby.tab[i+1][j].etat = False elif j < laby.q-1 and laby.tab[i][j].N and laby.tab[i][j+1].etat: pile.push((i, j)) pile.push((i, j+1)) laby.tab[i][j+1].etat = False elif i > 0 and laby.tab[i][j].W and laby.tab[i-1][j].etat: pile.push((i, j)) pile.push((i-1, j)) laby.tab[i-1][j].etat = False return pile.lst class Case: def init(self): self.N = False self.W = False self.S = False self.E = False self.etat = False class Labyrinthe: def init(self, p, q): self.p = p self.q = q self.tab = [[Case() for j in range(q)] for i in range(p)] def show(self): plt.plot([0, 0, self.p, self.p, 0], [0, self.q, self.q, 0, 0], linewidth=2) for i in range(self.p-1): for j in range(self.q): if not self.tab[i][j].E: plt.plot([i+1, i+1], [j, j+1], ‘b’) for j in range(self.q-1): for i in range(self.p): if not self.tab[i][j].N: plt.plot([i, i+1], [j+1, j+1], ‘b’) plt.axis([-1, self.p+1, -1, self.q+1]) plt.show() def solution(self): sol = explorer(self) X, Y = [], [] for (i, j) in sol: X.append(i+.5) Y.append(j+.5) X.append(self.p-.5) Y.append(.5) plt.plot(X, Y, ‘r’, linewidth=2) self.show() def creation(p, q): laby = Labyrinthe(p, q) pile = Pile() i, j = randint(p), randint(q) pile.push((i, j)) laby.tab[i][j].etat = True while not pile.empty(): i, j = pile.pop() v = [] if j < q-1 and not laby.tab[i][j+1].etat: v.append(‘N’) if i > 0 and not laby.tab[i-1][j].etat: v.append(‘W’) if j > 0 and not laby.tab[i][j-1].etat: v.append(‘S’) if i < p-1 and not laby.tab[i+1][j].etat: v.append(‘E’) if len(v) > 1: pile.push((i, j)) if len(v) > 0: c = v[randint(len(v))] if c == ‘N’: laby.tab[i][j].N = True laby.tab[i][j+1].S = True laby.tab[i][j+1].etat = True pile.push((i, j+1)) elif c == ‘W’: laby.tab[i][j].W = True laby.tab[i-1][j].E = True laby.tab[i-1][j].etat = True pile.push((i-1, j)) elif c == ‘S’: laby.tab[i][j].S = True laby.tab[i][j-1].N = True laby.tab[i][j-1].etat = True pile.push((i, j-1)) else: laby.tab[i][j].E = True laby.tab[i+1][j].W = True laby.tab[i+1][j].etat = True pile.push((i+1, j)) return laby Librairies from numpy.random import randint import matplotlib.pyplot as plt Un premier exemple laby = creation(6, 5) laby.solution()
    • Utiliser le module turtle Le script suivant présente les classes et fonctions utiles pour : tracer un labyrinthe complet parcourir le labyrinthe selon une méthode de parcours en profondeur tracer ce parcours animé avec turtle Utilisation : tab=labyrinthe(5,6) L = parcours((len(tab)-1,0),(0,len(tab[0])-1),tab) afficheTurtle(tab,L) librairies from numpy.random import randint import matplotlib.pyplot as plt import turtle classes utiles class Pile: def init(self): self.lst = [] def empty(self): return self.lst == [] def push(self, x): self.lst.append(x) def pop(self): if self.empty(): raise ValueError(“pile vide”) return self.lst.pop() """ def explorer(laby): pile = Pile() pile.push((0, laby.q - 1)) laby.tab[0][laby.q - 1].etat = False while True: i, j = pile.pop() if i == laby.p - 1 and j == 0: break if j > 0 and laby.tab[i][j].S and laby.tab[i][j-1].etat: pile.push((i, j)) pile.push((i, j-1)) laby.tab[i][j-1].etat = False elif i < laby.p-1 and laby.tab[i][j].E and laby.tab[i+1][j].etat: pile.push((i, j)) pile.push((i+1, j)) laby.tab[i+1][j].etat = False elif j < laby.q-1 and laby.tab[i][j].N and laby.tab[i][j+1].etat: pile.push((i, j)) pile.push((i, j+1)) laby.tab[i][j+1].etat = False elif i > 0 and laby.tab[i][j].W and laby.tab[i-1][j].etat: pile.push((i, j)) pile.push((i-1, j)) laby.tab[i-1][j].etat = False return pile.lst """ class Case: def init(self): self.N = False self.W = False self.S = False self.E = False self.etat = False class Labyrinthe: def init(self, p, q): self.p = p self.q = q self.tab = [[Case() for j in range(q)] for i in range(p)] def show(self): plt.plot([0, 0, self.p, self.p, 0], [0, self.q, self.q, 0, 0], linewidth=2) for i in range(self.p-1): for j in range(self.q): if not self.tab[i][j].E: plt.plot([i+1, i+1], [j, j+1], ‘b’) for j in range(self.q-1): for i in range(self.p): if not self.tab[i][j].N: plt.plot([i, i+1], [j+1, j+1], ‘b’) plt.axis([-1, self.p+1, -1, self.q+1]) plt.show() """ def solution(self): sol = explorer(self) X, Y = [], [] for (i, j) in sol: X.append(i+.5) Y.append(j+.5) X.append(self.p-.5) Y.append(.5) plt.plot(X, Y, ‘r’, linewidth=2) self.show() """ def creation(p, q): laby = Labyrinthe(p, q) pile = Pile() i, j = randint(p), randint(q) pile.push((i, j)) laby.tab[i][j].etat = True while not pile.empty(): i, j = pile.pop() v = [] if j < q-1 and not laby.tab[i][j+1].etat: v.append(‘N’) if i > 0 and not laby.tab[i-1][j].etat: v.append(‘W’) if j > 0 and not laby.tab[i][j-1].etat: v.append(‘S’) if i < p-1 and not laby.tab[i+1][j].etat: v.append(‘E’) if len(v) > 1: pile.push((i, j)) if len(v) > 0: c = v[randint(len(v))] if c == ‘N’: laby.tab[i][j].N = True laby.tab[i][j+1].S = True laby.tab[i][j+1].etat = True pile.push((i, j+1)) elif c == ‘W’: laby.tab[i][j].W = True laby.tab[i-1][j].E = True laby.tab[i-1][j].etat = True pile.push((i-1, j)) elif c == ‘S’: laby.tab[i][j].S = True laby.tab[i][j-1].N = True laby.tab[i][j-1].etat = True pile.push((i, j-1)) else: laby.tab[i][j].E = True laby.tab[i+1][j].W = True laby.tab[i+1][j].etat = True pile.push((i+1, j)) return laby autres definitions utiles def directions(laby,i,j): “““les directions possibles pour la case courante i : int numero de ligne j : numero de la colonne retourne une liste (tuple) des points cardinaux possibles "”” L = [] if laby.tab[j][i].N == True: L.append(‘N’) if laby.tab[j][i].S == True: L.append(‘S’) if laby.tab[j][i].E == True: L.append(‘E’) if laby.tab[j][i].W == True: L.append(‘W’) return tuple(L) def labyrinthe(lines,col): "”" Params : ——– lines : int : nombre de lignes du labyrinthe col : int : nombre de colonnes Returns : ——— tab2 : list : tuples de 1 à 4 éléments correspondants aux directions libres (‘N’, ‘S’, E’, ‘W’) sortie : tracé du labyrinthe Variables : ———– p : nombre de colonnes (=largeur) q : nombre de lignes (=hauteur) """ laby = creation(col, lines) tab2 = [[0]laby.p for i in range(laby.q)] for i in range(laby.q): for j in range(laby.p): tab2[i][j] = directions(laby,i,j) Labyrinthe.show(laby) return tab2 def nexto(c,direc): “““retourne les coordonnées lors du deplacement selon la position actuelle et la direction Params : ——– c : tuple (ligne,colonne) correspondant à (y,x) dans le plan cartesien direct : str : ‘N’, ‘S’, E’, ‘W’ Returns : ——— tuple : (int,int) correspondant à (ligne,colonne) "”” i,j = c[0],c[1] if direc==‘N’ : return (i+1,j) if direc==‘S’ : return (i-1,j) if direc==‘E’ : return (i,j+1) if direc==‘W’ : return (i,j-1) def visited(c,L,couleur): “““retourne la couleur du noeud de coord c et de liste de directions possibles L selon celle de ses voisins Params : ——– c : tuple : (ligne,colonne) correspondant à (y,x) dans le plan cartesien L : list : tuples de 1 à 4 éléments correspondants aux directions libres (‘N’, ‘S’, E’, ‘W’) couleur : List dimension 2 contenant des elements str ‘white’ si noeud non visité, ‘green’ si le noeud est en cours de visite, ‘red’ si tous les noeuds ont été visités autour de lui Returns : ——— couleur : str : ‘green’ si le noeud est en cours de visite, ‘red’ si tous les noeuds ont été visités autour de lui "”” i,j = c[0],c[1] coul=‘red’ for direc in L: coord = nexto(c,direc) if couleur[coord[0]][coord[1]]‘white’:coul=‘green’ #print(c,coul) return coul def parcours(start,end,tab): “““trouve la solution au labyrinthe et trace ce chemin p : Pile() utile pour la recherche du parcours pchemin : Pile() utile pour memoriser tout le chemin on insère dans le chemin toutes les arêtes empruntées : pour le chemin entre c1 et c2, on insère c1 puis c2 "”” p = Pile() pchemin = Pile() p.push(start) c = start couleur = [[‘white’]*len(tab[0]) for i in range(len(tab))] while (not p.empty()) and (not c == end): c = p.pop() pchemin.push(c) # chaque fois que l’on depile, on rempile dans pchemin L = tab[c[0]][c[1]] couleur[c[0]][c[1]]=visited(c,L,couleur) # c est retiré de la pile et coloré en green ou red for direc in L: coord = nexto(c,direc) if couleur[coord[0]][coord[1]]‘white’: # le noeud fils est coloré en blanc dans la direction D p.push(c) # on remet le noeud parent afin de reconsidérer sa couleur à chaque fois que l’on depile # et le chemin arriere CONTINU pour le tracé p.push(coord) # alors on ajoute le noeud fils dans la direction D au sommet de la pile return pchemin.lst fonctions particulières au module turtle def turtleWall(dir,i,j): “““trace les murs des directions fermées dir est un tuple contenant les directions libres "”” larg = len(tab[0]) haut = len(tab) fenX = 600 fenY = fenXhaut/larg scaleX = (fenX-20)/larg scaleY = (fenY-20)/haut x0=-fenX/2+10 y0=-fenY/2+10 if not(‘N’ in dir[i][j]) : turtle.penup() turtle.setpos(x0+jscaleX,y0+(i+1)scaleY) turtle.setheading(0) turtle.pendown() turtle.forward(scaleX) if not(‘S’ in dir[i][j]) : turtle.penup() turtle.setpos(x0+jscaleX,y0+iscaleY) turtle.setheading(0) turtle.pendown() turtle.forward(scaleX) if not(‘E’ in dir[i][j]) : turtle.penup() turtle.setpos(x0+(j+1)scaleX,y0+iscaleY) turtle.setheading(90) turtle.pendown() turtle.forward(scaleY) if not(‘W’ in dir[i][j]) : turtle.penup() turtle.setpos(x0+jscaleX,y0+iscaleY) turtle.setheading(90) turtle.pendown() turtle.forward(scaleY) def turtleLab(tab): for i in range(len(tab)): for j in range(len(tab[i])): turtleWall(tab,i,j) #plt.plot([0, 0, len(tab[0]), len(tab[0]), 0], [0, len(tab), len(tab), 0, 0], ‘blue’,linewidth=10) #plt.savefig(’laby.png’) def turtlePath(tab,L): “““tracé du parcours dans le labyrinthe à l’aide de la tortue Params: ——- tab : Liste de liste contenant des str : ‘N’,‘S’,‘W’,‘E’ = le labyrinthe L : Liste de tuples correspondant aux cases visitées sortie : ——– le dessin du parcours animé "”” larg = len(tab[0]) haut = len(tab) fenX = 600 fenY = fenXhaut/larg scaleX = (fenX-20)/larg scaleY = (fenY-20)/haut x0=-fenX/2+10 y0=-fenY/2+10 turtle.penup() turtle.pencolor(“red”) turtle.setpos(x0+scaleX/2,y0+scaleY4+scaleY/2) # depart turtle.showturtle() turtle.pendown() start = L[0] for c in L[1:]: #angle = 90*(c[0]-start[0]) # si deplacement uniquement vertical if c[0]!=start[0] : depl = scaleY # vertical angle = 90*(c[0]-start[0]) else : depl = scaleX # horizontal angle = 90 - 90*(c[1]-start[1]) if c[1]<start[1] : angle = 180 # deplacement à gauche turtle.setheading(angle) turtle.forward(depl) start = c fonction principale pour affichage de l’animation turtle def afficheTurtle(tab,L): larg = len(tab[0]) haut = len(tab) fenX = 600 fenY = fenX*haut/larg scaleX = (fenX-20)/larg scaleY = (fenY-20)/haut turtle.setup(fenX, fenY) #Largeur : 600px, Hauteur : 400px turtle.bgcolor((0.9, 0.9, 0.9)) turtle.hideturtle() turtle.penup() turtle.setpos(-fenX/2+10,-fenY/2+10) turtle.setheading(90) turtle.pendown() #turtle.speed(0) turtle.tracer(False) # tracer le Laby avant de demarrer l’animation avec la tortue turtle.pensize(2) turtle.forward(fenY-20) turtle.left(-90) turtle.forward(fenX-20) turtle.left(-90) turtle.forward(fenY-20) turtle.left(-90) turtle.forward(fenX-20) turtle.left(-90) turtleLab(tab) turtle.tracer(True) # fin du tracé du Laby turtle.speed(6) turtlePath(tab,L) # animation du parcours par la tortue #calling for the mainloop() turtle.mainloop() Programme tab=labyrinthe(5,6) L = parcours((len(tab)-1,0),(0,len(tab[0])-1),tab) afficheTurtle(tab,L)
    • Principe Un modèle prédictif ne peut être établi qu’à partir d’une étude prealable de données. Une étude statistique permet de repérer si certains paramètres sont liés entre eux. Alors, si ces données étaient suffisamment nombreuses et précises, il est possible d’établir des lois mathematiques sur ces données. Une manière de représenter ce lien entre paramètres est d’établir une loi de regression linéaire, par exemple.
    • Utilisation du module unittest avec le calcul des nombres premiers avant de démarrer cette partie, il est recommandé de consulter : le cours sur les tests unitaires Et le paragraphe sur mettre son programme sous forme de modules Définition: Un test unitaire est un test réalisé sur une portion du programme, typiquement sur une fonction. Le module unittest offre des outils de test de code, comme la classe TestCase. Le but est des vérifier que votre code génère des résultats corrects, conformes au attentes.
    • Chiffrements symétriques Vocabulaire Chiffrer: transformer les caractères d’un texte pour le rendre incompréhensible, sauf pour celui qui possède la clé de chiffrement. Déchiffrer: transformer le texte chiffré en texte clair à l’aide de la clé de chiffrement Décrypter: transformer le texte chiffré en texte clair sans posséder la clé. Cryptologie: science du secret: possède deux branches cryptographie: étude de l’art du chiffrement cryptanalyse: analyse des méthodes de chiffrement pour les casser (décrypter) à quoi sert le chiffrement? Le chiffrement a pour but de protéger nos données, nos communications, mais aussi de signer nos messages et de s’assurer que l’on communique bien avec la bonne personne:

    Sous-sections de Posts

    jeu Space Invader

    Ce mini projet sera l’occasion de mettre en oeuvre les notions vues dans le cours précédent sur :

    • la définition d’un objet en javascript
    • la gestion des évènements
    • l’utilisation d’une fonction callback avec un timer

    Vous pourrez également suivre ce tutoriel avec la video à l’adresse : lien video

    Afficher des éléments en javascript

    Contenu du dossier du projet

    D’abord, créer un dossier contenant :

    Pour les images, on pourra faire un clic droit sur les liens proposés et choisir de télécharger le fichier.

    Code minimal HTML

    Le code html minimal qui permet de positionner un vaisseau aux coordonnées : 200px horizontal et 100px vertical :

    <html>
    <head>
    	<title>My space invader</title>
    	<script src="jeu.js"></script>
    <style>
    	html,body {margin : 0px; padding: 0px; width : 100%; height: 100%}
    	body {background: url('fond.jpg'); background-size: cover; overflow: hidden;}
    </style>
    
    </head>
    <body>
    	<img id="ship" src="ship.png">
    	<script type="text/javascript">
    		let v = document.getElementById('ship');
    		v.style.width = '100px';
    		v.style.height = 'auto'; // pour conserver le ratio
    		v.style.position = "absolute";
    		// regles de positionnement
    		// demarrer par la regle de positionnement absolute pour que 
    		// l'image soit mise par rapport à l'élément precedent dans le flux
    		// de maniere absolute
    		v.style.left= '200px';
    		v.style.top='100px';
    
    	</script>
    </body>
    </html>
    vaisseau
    position du vaisseau à 200px à gauche et 100 px en bas

    Le problème est que l’on ne veut pas avoir à taper tout ces volumes de code pour positionner un vaisseau un missile ou un alien : on va alors utiliser une librairie que l’on va nous même écrire.

    On pourra effacer toutes les lignes écrites entre les balises <body> et </body>

    le constructeur de Sprites : function Sprite( )

    les propriétés liées aux attributs

    Nous allors programmer une librairie javascript qui va nous permettre de concevoir un constructeur pour tous les objets à afficher. Chacun des ces objets aura alors des propriétés de positionnement, et deux options d’affichage : visible ou caché. Commençons par programmer le constructeur et les attributs dont héritera l’objet. Dans le fichier jeu.js, mettre les lignes de code :

    function Sprite(filename, left,top){
    	this._node = document.createElement("img");
    	this._node.src = filename;
    	this._node.style.position="absolute";
    	this._node.style.height="100px";
    	this._node.style.width="auto";
    	this._node.style.left=left+"px";
    	this._node.style.top=top+"px"
    	document.body.appendChild(this._node);
    }

    Explications:

    • La function Sprite(filename, left,top){ : C’est une fonction de creation d’objets (contient des this et commence par majuscule)
    • Sprite : l’element à créer
    • this : l’objet lui meme et _node , c’est l’élément correspondant, avec tous ses attributs, tel qu’on l’avait défini de maniere statique dans le premier document html.

    On peut déjà positionner l’objet à l’écran en écrivant dans la partie <script> de la page html : (ce sera alors la première ligne mise entre les balises <script> et </script>

    let vaisseau = Sprite('ship.png',400,500);

    Ce qui devrait construire un objet vaisseau, et ajouter un nouvel élément sur la page : l’image du vaisseau à la position 400px,500px.

    Les propriétés de (re)positionnement

    <input type="checkbox" id="toggle" class="visually-hidden">
    
    <div class="control-me">
    
      <p>On souhaite maintenant ajouter des méthodes particulières à l'objet, qui permettront de le déplacer facilement (le <span class="ital">repositionner</span>).</p>
    
      <p>On pourrait le réaliser à l'aide d'une affectation simple, comme on l'a déjà vu dans le cours précédent. Par exemple, avec : 
      <code>Sprite.posX</code></p>
    
      <p>Ici, on va utiliser la méthode Object.defineProperty(), qui permet de préciser le comportement attendu, potentiellement différent de celui par défaut.</p>
    
      <p>On veut maintenant que la nouvelle propriété <code>left</code> soit accessible en ecriture ET en lecture de la manière suivante : 
      <ul>
      <li>Ecriture : Avec le signe <code>=</code> d'affectation =>  <code>vaisseau.left = 400;</code> </li>
      <li>Lecture : Sans le signe <code>=</code> pour accéder à la valeur => <code>vaisseau.left</code> </li>
      </ul>
      </p>
    
    </div>
    

    Une fois cette nouvelle méthode attachée au constructeur Sprite, on peut le représenter avec le schéma suivant :

    classe sprite
    classe Sprite

    L’objet que l’on définira à partir de cette classe héritera des propriétés et des méthodes, que l’on appelera avec l’instruction objet.propriété ou objet.methode

    Pour ajouter les méthodes : Dans le fichier jeu.js, enlever l’accolade finale du constructeur et mettre :

    Object.defineProperty(this,"left", {
    	get: function(){
    		return this._left;
    	},
    	set: function(value){
    		this._left=value;
    		this._node.style.left=this._left+"px";
    	}
    });

    Object.defineProperty permet de definir une propriété pour l’objet que l’on a créé : on passe l’objet avec l’argument this

    une propriété est un ensemble de 2 methodes :

    • une methode get d’acces en lecture.
    • une methode set d’acces en ecriture

    Remarquer que l’on utilise _leftpour le nommage d’une prorieté qui reste privée (locale) dans ce constructeur.

    Cette methode, on va y acceder avec le nom de proprieté left:

    On fait par exemple dans le script de la page principale : (ligne à écrire à la suite des autres instruction, avant la fermeture </script> dans la page html)

    vaisseau.left = 400;

    Le signe = va indiquer que l’on invoque la propriété leften ecriture (on dit que l’on invoque le setter), et cela va modifier l’attribut css style avec la nouvelle règle left : 400px`.

    Rafraichissons la page. Dans la console : explorons les attributs de l’élément associé à l’objet vaisseau : On peut alors vérifier les valeurs prises pour les propriétés CSS des attributs.

    Ouvrir la console du navigateur, et saisir :

    > vaisseau._node.style
    < CSSStyleDeclaration {0: "position", 1: "height", 2: "width", 3: "left", 4: "top", alignContent: "", alignItems: "", alignSelf: "", alignmentBaseline: "", all: "", …}
    > vaisseau._node.style["height"]
    < "100px"

    On sait maintenant positionner horizontalement le vaisseau. Avec de nouvelles déclarations dans le même format, on peut aussi :

    • positionner verticalement (propriete CSS top)
    • modifier la propriete CSS display dont les valeurs possibles sont :
      • none : n’affiche pas
      • block : affiche

    le script jeu.js

    Avec le constructeur Sprite( ) tel qu’il a été défini dans le paragraphe précédent, le script jeu.js est alors :

    function Sprite(filename, left,top){
    
    	this._node = document.createElement("img");
    	this._node.src = filename;
    	this._node.style.position="absolute";
    	this._node.style.height="100px";
    	this._node.style.width="auto";
    	//this._node.style.left=left+"px";
    	//this._node.style.top=top+"px"
    	document.body.appendChild(this._node);
    
      Object.defineProperty(this,"left", {
       get: function(){
    		return this._left;
    	},
    	set: function(value){
    		this._left=value;
    		this._node.style.left=this._left+"px";
    	}
    	});
    
    	Object.defineProperty(this,"top", {
    	get: function(){
    		return this._top;
    	},
    	set: function(value){
    		this._top=value;
    		this._node.style.top=this._top+"px";
    	}
    	});
    
    	Object.defineProperty(this,"display", {
    	get: function(){
    		return this._node.style.display;
    	},
    	set: function(value){
    		this._top=value;
    		this._node.style.display=value;
    	}
    	});
    
    	this.left=left;
    	this.top = top;
    }

    Positionner les éléments

    Le reste du script sera mis entre les balises <script>de la page html. On peut avoir accès à la dimension de l’écran avec un propriété de l’objet :

    document : document.body.clientWidth

    Centrer le vaisseau, au mileu de l’écran, en position basse avec l’instruction : remplacer let vaisseau = Sprite('ship.png',400,500); par :

    let vaisseau = new Sprite("ship.png", document.body.clientWidth/2, 500);

    A vous de jouer : ajouter 3 aliens que vous devrez repartir sur la largeur de l’écran, en position haute. Nommez les : alien1, alien 2, alien3.

    Et ajoutez le missile, à une position quelconque, mais modifiez immédiatement sa propriété displaypour qu’il reste caché : ajouter :

    missile.display="none";

    éléments
    à gauche : missile visible, à droite : missile caché

    Gestionnaires d’évènements

    On ajoute un gestionnaire d’evenements lié aux touches appuyées avec :

    document.onkeydown = function (event) {

    lorsque l’on appuie sur une touche, cela genere un evenement "event" et appelle une fonction avec le parametre l’un des attributs possibles de event qui est keyCode : comme ici, l’evenement est lié aux touches appuyées, on peut demander le keyCode de ces touches :

    Mettre les lignes suivantes dans le programme de la page html :

    document.onkeydown = function (event) {
    	console.log(event.keyCode);
    	}

    Cliquer alors dans la fenêtre du navigateur pour lui donner le focus, puis tester en appuyant sur diverses touches du clavier la valeur affichée dans la console :

    • f : 70
    • flèche droite : 39
    • flèche gauche : 37
    • s : 83
    • space : 32

    Pour faire avancer le vaisseau à droite lorsque l’on appuie sur la touche f ou la flèche droite, il faut alors mettre :

    document.onkeydown = function (event) {
        if (event.keyCode==70 || event.keyCode==39 ){
    				vaisseau.left+=10;
    }

    A vous de jouer : ajouter alors, dans le même bloc de code lié à la gestion d’evenements du clavier, les instructions consitionnelles qui feront :

    • avancer le vaisseau à gauche pour s ou pour flèche gauche
    • faire apparaitre le missile juste devant le vaisseau lorsque l’on appuie sur la barre espace.
    • limiter le déplacement à gauche et à droite pour ne pas que le vaisseau sorte de l’écran.

    Animer les éléments

    On va modifier à intervalle de temps réguliers les aliens et le missile, ce qui donnera l’illusion d’une trajectoire.

    méthode setInterval()

    Les méthodes setTimeout et setInterval sont des méthodes de l’objet Window. Ce sont des processus indépendants qui, quand ils sont lancés par une instruction, ne bloquent pas l’affichage du reste de la page ni les actions de l’utilisateur. Elles permettent de placer dans la pile des prochaines fonctions à exécuter une fonction particulière. Javascript exécute cette pile fonction après fonction dans l’ordre de la pile.

    • SetTimeout indique un délai avant exécution
    • setInterval déclenche une opération à intervalles réguliers
    • ClearTimeout interrompt le décompte de setTimeout et de setInterval

    Syntaxe : var intervalID = scope.setInterval(func ou bloc de code, [delay (en ms)]);

    Ce compteur de temps est identifié de manière unique : window.setInterval renvoie une valeur numérique qui permet cette identification.

    Dans le fichier jeu.js, en dehors du constructeur Sprite( ) (à la suite), ajouter :

    Sprite.prototype.startAnimation = function (fct, interval) {
    	if (this._clock) window.clearInterval (this._clock);
    	// s'il y a deja un missile qui est envoyé, clearInterval
    	// retire le timer qui lui était lié et en met un nouveau
    	var _this=this;
    	// on demarre un intervalle que l'on associe à l'objet this
    	// on déclare une nouvelle variable locale avec l'underscore _this
    	// dont la portée sera descendante. Cette variable pourra être utilisée 
    	// par la fonction executée par setInterval
    	this._clock=window.setInterval(function(){
    		fct(_this);
    	},interval);
    };
    
    Sprite.prototype.stopAnimation = function() {
    	window.clearInterval(this._clock);
    };

    Lorsque la touche barre espace est appuyée : on appelle la méthode startAnimation pour l’objet missile. Cette méthode appelle la fonction setInterval qui va associer un timer à l’objet lorsque l’on fait nom_de_l_objet.startAnimation(fct,interval). L’un des paramètres de la fonction setIntervalest justement une fonction, fct. On met moveMissile comme fonction de callback. Le timer associé à l’objet, appelle à intervalle de temps régulier cette fonction qui est passée en paramètre (ce que l’on appelle un callback). L’intervalle de temps est donné par la paramètre interval. Ce qui modifie la pile d’appel des fonctions dans le programme.

    pile d'appel des fonctions
    fonction callback et pile d'appel des fonctions

    La deuxieme propriété, stopAnimation, permet de retirer le timer avec l’instruction clearInterval().

    Remarques : voir en annexe en bas du document

    animation du missile

    On va alors ajouter la fonction moveMissile(missile) qui sera appelée par setInterval : Dans la partie <script> du programme de la page html : en dehors de la fonction anonyme executée par onkeydown, on ajoute :

    function moveMissile(missile){
    		missile.top -=10;
    		if (missile.top<100) {
    		  missile.stopAnimation(); // sortie de l'écran : on retire le timer de l'objet
    		  missile.display = "none";
    		}
    	}

    Lorsque la fonction est appelée, cela modifie la position du missile (on soustrait 10 px à sa position par rapport au haut de la page)

    dans le bloc de code associé à la condition sur l’évenement de la touche appuyée (la n°32), ajouter : missile.startAnimation(moveMissile,20);

    Le bloc de code doit maintenant avoir le contenu suivant :

    if (event.keyCode == 32){
    	if (missile.display=="none"){
    	// condition qui permet de ne lancer un missile que 
    	// si aucun missile n'est deja en vol
    	missile.display="block";
    	missile.left = vaisseau.left+vaisseau._node.width/2;
    	missile.top = vaisseau.top;
    	missile.startAnimation(moveMissile,20);
    	}
    }

    animation des aliens

    On créé ensuite l’animation des aliens, avec un déplacement à droite puis à gauche, à l’aide de 2 nouvelles fonctions :

    function moveAlienToRight(alien){
    		alien.left += 10;
    		if (alien.left > document.body.clientWidth-vaisseau._node.width){
    			alien.stopAnimation();
    			alien.top += 50;
    			alien.startAnimation(moveAlienToLeft,40);
    		}
    	}
    
    	function moveAlienToLeft(alien){
    		alien.left -= 10;
    		if (alien.left < 0){
    			alien.stopAnimation();
    			alien.top += 50;
    			alien.startAnimation(moveAlienToRight,40);
    		}
    	}
    	
    	alien1.startAnimation(moveAlienToRight,40);

    Puis on lance l’animation pour chacun des autres aliens : alien2.startAnimation(moveAlienToRight,40); par exemple pour le 2e alien.

    Enfin, on va programmer une méthode de verification de collision de sprite, mais au niveau de la librairie de sprites.

    Ajout d’une méthode checkCollision

    Dans le fichier jeu.js, ajouter les lignes de code suivantes pour vérifier si deux sprites se chevauchent

    Sprite.prototype.checkCollision = function (other){
    	return (( this.top + this._node.height > other.top) && 
    		(this.top<(other.top+other._node.height)) &&
    		(this.left+this._node.width>other.left) &&
    		(this.left<other.left+other._node.width))
    }

    Si on veut savoir si le sprite missile chevauche le sprite alien1, on fait, dans la fonction de déplacement du missile : missile.checkCollision(alien1)

    La fonction retourne alors true si les 2 sprites se chevauchent. L’appel de cette méthode de missile se fera dans la fonction moveMissile(missile). Ajouter les lignes suivantes :

    if (alien1.display != "none" && missile.checkCollision(alien1)){
    			// on ne fait un test QUE si l'alien est visible
    			// sinon le missile traverse l'écran
    			missile.display="none";
    			missile.stopAnimation();
    			alien1.display="none";
    			alien1.stopAnimation();
    			// on retire l'alien
    		}

    Prolongement

    Il reste maintenant à programmer les conditions de collision du missile avec les autres aliens, et aussi la condition de collision des aliens avec le vaisseau, ce qui amènerait un Game Over.

    Enfin, pour aller plus loin, on pourrait imaginer d’ajouter encore plus d’aliens, comme expliqué dans la vidéo (lien en début de document), de gérer un Score, et de pouvoir recommencer la partie.

    Annexe

    1. Pour comprendre en détail la manière avec laquelle on a programmé ce timer, il faudra revoir, dans le cours précédent ce que sont : une fonction callback, une fonction lambda, un objet et son prototype
    2. Remarque à propos de la portée des variables : Le problème du this

    Le code executé par setInterval() se fait dans un contexte séparé de celui de la fonction qui l’appelle. Conséquence : le mot clé thisne pointe pas vers l’objet local , mais il est associé au contexte global, window. En dehors de tout contexte, pour un navigateur, this est l’objet window.

    C’est la raison pour laquelle on choisit ici de déclarer : var _this = this; juste avant la fonction anonyme qui fait appel à _this

    Programme complet

    page html

    <html>
    <head>
    	<title>My space invader</title>
    	<script src="jeu.js"></script>
    <style>
    	html,body {margin : 0px; padding: 0px; width : 100%; height: 100%}
    	body {background: url('fond.jpg'); background-size: cover; overflow: hidden;}
    </style>
    
    </head>
    <body>
    	
    	<script type="text/javascript">
    		let vaisseau = new Sprite("ship.png",400,500);
    		let alien1 = new Sprite("ufo.png",100,100);
    		let alien2 = new Sprite("ufo.png",400,100);
    		let alien3 = new Sprite("ufo.png",700,100);
    		
    		let missile = new Sprite("missile.png",100,100);
    		missile.display="none";
    		
    		document.onkeydown = function (event) {
    			console.log(event.keyCode);
    			// l'un des attributs possibles de event est keyCode : 
    			// comme ici, l'evenement est lié aux touches appuyées
    			// on peut demander le keyCode de ces touches.
    			// f : 70
    			// s : 83
    			// space : 32
    			if (event.keyCode==70 || event.keyCode==39 ){
    				vaisseau.left+=10;
    			}
    			if (event.keyCode==83 || event.keyCode==37 ){
    				vaisseau.left-=10;
    			}
    			
    
    
    			if (vaisseau.left<=0) vaisseau.left = 0;
    			if (vaisseau.left >= document.body.clientWidth-vaisseau._node.width) vaisseau.left=document.body.clientWidth-vaisseau._node.width;
    			if (event.keyCode == 32){
    				if (missile.display=="none"){
    				// condition qui permet de ne lancer un missile que 
    				// si aucun missile n'est deja en vol
    
    				missile.display="block";
    				missile.left = vaisseau.left+vaisseau._node.width/2;
    				missile.top = vaisseau.top;
    				missile.startAnimation(moveMissile,20);
    				// on appelle la methode startAnimation
    				// associée à l'objet missile
    				// avec la fonction missile comme premier parametre (callback)
    				// et 20 ms comme seconde parametre (mis dans interval
    				// par la fonction anonyme executée lorsque l'on appelle 
    				// la methode)
    				}
    			}
    			
    		}
    			
    	function moveMissile(missile){
    		missile.top -=10;
    		if (missile.top<100) {
    		missile.stopAnimation(); // sortie de l'écran : on retire le timer de l'objet
    		missile.display = "none";
    		}
    		if (alien1.display != "none" && missile.checkCollision(alien1)){
    			// on ne fait un test QUE si l'alien est visible
    			// sinon le missile traverse l'écran
    			missile.display="none";
    			missile.stopAnimation();
    			alien1.display="none";
    			alien1.stopAnimation();
    			// on retire l'alien
    		}
    	}
    
    	function moveAlienToRight(alien){
    		alien.left += 10;
    		if (alien.left > document.body.clientWidth-vaisseau._node.width){
    			alien.stopAnimation();
    			alien.top += 50;
    			alien.startAnimation(moveAlienToLeft,40);
    		}
    	}
    
    	function moveAlienToLeft(alien){
    		alien.left -= 10;
    		if (alien.left < 0){
    			alien.stopAnimation();
    			alien.top += 50;
    			alien.startAnimation(moveAlienToRight,40);
    		}
    	}
    	
    	alien1.startAnimation(moveAlienToRight,40);
    	alien2.startAnimation(moveAlienToRight,40);
    	alien3.startAnimation(moveAlienToRight,40);
    
    	</script>
    </body>
    </html>

    fichier jeu.js

    function Sprite(filename, left,top){
    
    	this._node = document.createElement("img");
    	this._node.src = filename;
    	this._node.style.position="absolute";
    	this._node.style.height="100px";
    	this._node.style.width="auto";
    	//this._node.style.left=left;
    	//this._node.style.top=top;
    	document.body.appendChild(this._node);
    
    
    
    	Object.defineProperty(this,"left", {
    	
    
    	get: function(){
    		return this._left;
    	},
    	set: function(value){
    		this._left=value;
    		this._node.style.left=this._left+"px";
    	}
    	});
    
    	Object.defineProperty(this,"top", {
    	get: function(){
    		return this._top;
    	},
    	set: function(value){
    		this._top=value;
    		this._node.style.top=this._top+"px";
    	}
    	});
    
    	Object.defineProperty(this,"display", {
    	get: function(){
    		return this._node.style.display;
    	},
    	set: function(value){
    		this._top=value;
    		this._node.style.display=value;
    	}
    	});
    
    	this.left=left;
    	this.top = top;
    }
    
    Sprite.prototype.startAnimation = function (fct, interval) {
    	if (this._clock) window.clearInterval (this._clock);
    	// s'il y a deja un missile qui est envoyé, clearInterval
    	// retire le timer qui lui était lié et en met un nouveau
    	var _this=this;
    	// on demarre un intervalle que l'on associe à l'objet this
    	// on déclare une nouvelle variable locale avec l'underscore _this
    	// dont la portée sera descendante. Cette variable pourra être utilisée 
    	// par la fonction déclarée  
    	this._clock=window.setInterval(function(){
    		fct(_this);
    	},interval);
    };
    
    Sprite.prototype.stopAnimation = function() {
    	window.clearInterval(this._clock);
    };
    
    
    Sprite.prototype.checkCollision = function (other){
    	return (( this.top + this._node.height > other.top) && 
    		(this.top<(other.top+other._node.height)) &&
    		(this.left+this._node.width>other.left) &&
    		(this.left<other.left+other._node.width))
    }

    Liens

    Javascript le DOM

    Le DOM

    le DOM ou Document Object Model, une interface qui fait partie du BOM (Browser Object Model) et grâce à laquelle nous allons pouvoir manipuler le contenu HTML et les styles de nos pages.

    Le DOM est ainsi une représentation structurée du document sous forme « d’arbre » crée automatiquement par le navigateur, à partir de sa lecture du document HTML.

    Chaque branche de cet arbre se termine par ce qu’on appelle un nœud, contenant les éléments HTML. On va finalement pouvoir utiliser ces objets, leurs propriétés et leurs méthodes en JavaScript.

    Le DOM fournit le squelette du document

    Inspecter le DOM se fait avec le navigateur

    inspecter le DOM
    inspecter le DOM dans le navigateur

    C’est en particulier l’interface Document que nous allons utiliser pour parcourir le DOM : Toute opération sur le DOM commence avec l’objet document :

    arbre du DOM
    arbre du DOM

    Trois noeuds du DOM sont disponibles directement comme des propriétés de l’objet DOM :

    • document.documentElement
    • document.body
    • document.head

    On verra plus loin les méthodes de parcours de l’arbre du DOM (## parcourir l’arbre du DOM).

    Manipuler les éléments de la page

    accéder à un élément à l’aide d’un sélecteur

    Pour manipuler les éléments d’une page affichée dans le navigateur, on doit accéder à cet élément.

    Or, il n’y a pas de lien direct entre html et javascript : En Javascript, on peut récupérer une instance de HTMLElement correspondant à un élément de la page.

    Cela peut se faire à l’aide des ancres laissées sur ces éléments. On peut les sélectionner, comme en CSS avec leur classe, leur ID ou le nom de la balise. Pour réaliser ceci, on utilise les fonctions suivantes:

    • document.getElementById() permet de sélectionner un élément html à partir de son id.
    • document.querySelector() un sélecteur plus générique qui sélectionne les éléments à la manière des sélecteurs css.

    Un premier exemple : afficher du texte

    lorsque l’on souhaite injecter du texte dans un paragraphe dont l’attribut id="ancre", un élément que l’on aura défini dans la partie html du code avec :

    <p id = "ancre"></p>

    on utilisera dans la partie javascript:

    document.getElementById('ancre').innerHTML = "nouveau texte à afficher".

    Exemple 2 : modifier l’attribut style de l’élément

    soit un élement avec attribut id=‘elem’ de la page : On cherche à atteindre cet élément et en modifier la couleur :

    (écrire le code suivant dans un fichier que vous nommerez exemple1.html)

    <body>
      <h1 id="elem">Un titre qui n'a pas de couleur</h1>
    <script>
    let elem = document.getElementById('elem');
    elem.style.background = 'red';
    </script>
    </body>

    On met cet élément dans une variable elem. Puis on peut modifier ses attributs, comme par exemple celui style pour la couleur.

    Ouvrir le fichier avec un navigateur. La couleur du titre devrait apparaitre … en rouge !

    Exemple 3 : utilisation de querySelector

    Cette méthode associée à document permet d’utiliser les mêmes règles de selection que lorsque l’on utilise le CSS. On peut donc utiliser comme paramètre : le nom de la balise ‘p’, la classe de l’élément ‘.maclasse’, l’identifiant ‘#elem’, …

    voir la page consacrée sur w3schools

    parcourir l’arbre du DOM

    La propriété childNodes de l’interface Node renvoie une liste sous forme de tableau des nœuds enfants de l’élément donné. Le premier nœud enfant reçoit l’indice 0 comme pour tout tableau.

    Et pour obtenir l’élément parent d’un noeud, on utilise la propriété parentElement.

    Exemple : Vous pouvez tester cet exemple en enregistrant le code suivant dans un fichier que vous nommerez exemple3.html:

    <body>
    <div>
      <p id="myP">Un peu de texte, <a>un lien</a> et <strong>une portion en emphase</strong></p>
    </div>
    </body>

    Ouvrir alors la page pour l’afficher dans le navigateur.

    Cette page a alors l’arbre de DOM suivant qui lui est associé :

    arbre du DOM
    arbre du DOM

    Le premier enfant de <p> est un nœud textuel, alors que le dernier enfant est un élément <strong>. Cet élément <strong> possède pour noeud enfant un noeud textuel dont le contenu et une portion en emphase

    Dans la console, saisir une à une les instructions suivantes : (sans les commentaires)

    > let paragraph = document.getElementById('myP'); // pour stocker le noeud parent.
    > let first = paragraph.firstChild; // parcours de l'arbre jusqu'au 1er enfant
    > alert(first.nodeValue); // pour récuperer le contenu du noeud textuel
    
    arbre du DOM
    contenu textuel du premier enfant

    Puis :

    > let last = paragraph.lastChild;
    > alert(last.firstChild.data); // pour recuperer le contenu textuel de la balise
    
    arbre du DOM
    contenu textuel du dernier enfant

    On peut réaliser cette dernière manipulation en ayant recours à la liste de tous les enfants de paragraph: en écrivant dans la console :

    > paragraph.childNodes

    arbre du DOM
    liste de tous les enfants du noeud parent

    On peut lire dans la console que le noeud textuel (<strong>Une portion avec emphase</strong>) est au rang 3 dans la liste des noeuds enfants (childNodes).

    On affiche alors son contenu textuel : dans la console, écrire :

    > let last = paragraph.childNodes[3]
    > alert(last.firstChild.data)
    arbre du DOM
    contenu textuel de last

    Pour finir, on peut modifier à volonté les éléments textuels en modifiant la valeur renvoyée par .data ou .nodeValue :

    Dans la console :

    > last.firstChild.data = 'un autre texte'
    arbre du DOM
    modification du contenu textuel de last

    Ajouter un paragraphe dans la page

    Pour créer un nouvel élément dans la page :

    • créer un nouveau noeud an appelant la fonction creatElement associée à document
    • ajouter la balise textuelle associée à ce noeud s’il y en a une
    • ajouter eventuellement des attributs à cet élément: setAttribute(attribut,valeur)
    • ajouter cet élement directement à son noeud parent: appenChild

    Exemple :

    <head>
    <meta charset="utf-8" />
    <script>
          var x = 10;
    
          /*
          Affiche la valeur de la variable x. Puis incrémente de 1 la valeur de la variable x
           */
          function addXToThePage() {
            let newP = document.createElement('p');
            newP.innerHTML = "<p>La valeur de x = " + x + "</p>";
            newP.setAttribute('style', 'color : red;');
            document.getElementById("newPar").appendChild(newP);
            x = x + 1;
          }
        </script>
      </head>
    <body>
        <button onclick="addXToThePage();">
          Clique ici pour afficher la valeur de la variable x
        </button>
        <div id="newPar"></div>
    </body>

    Résultat : (cliquer sur le bouton pour tester le programme)

    Lire et modifier un tableau

    Le programme suivant montre l’utilisation d’un formulaire. Lors du clic sur le bouton, on accède aux valeurs des champs du formulaire avec la propriété .value associée à l’élément du formulaire.

    On recopie alors chacune des colonnes du tableau avec ces valeurs.

    Pour accéder à chaque élément de la page, on utilise les règles de selection vues plus haut, avec document.getElementById et document.querySelector.

    L’exemple présenté ici est incomplet et ne renvoie dans le tableau que le champ prenom. Il faudra completer le script pour renvoyer aussi les noms et email.

    Prénom Nom email
    Nom complet

    <body>
    <table>
         <thead>
           <tr>
             <th>Prénom</th>
             <th>Nom</th>
             <th>email</th>
           </tr>
         </thead>
         <tbody>
           <tr class="client1">
             <td class="first"></td><td class="last"></td><td class="mail"></td>
           </tr>
         </tbody>
    </table>
       
    <form>
         <fieldset>
           <legend>Nom complet</legend>
           <ol>
             <li>
               <label for="prenom">Saisir le prénom</label>
               <input id="prenom"  type="textarea" name="prenom" placeholder="prenom"/>
             </li>
             <li>
               <label for="nom">Saisir le nom</label>
               <input id="nom" type="textarea" name="nom" placeholder="nom" />
             </li>
             <li>
               <label for="email">E-mail</label>
               <input
                 id="email"
                 type="email"
                 name="email"
                 placeholder="exemple@domaine.com"
                 required
               />
             </li>
           </ol>
         </fieldset>
    </form> 
    
    <button onclick="buildTable();">  Soumettre </button>
    <script>
         function buildTable(){
             let prenom = document.getElementById("prenom").value;
             let nom = document.getElementById("nom").value;
             let email = document.getElementById("email").value;
    
             // champ prenom
             let contenu =document.querySelector('.client1>.first');
             contenu.textContent=prenom;
         
             // champ nom
           
             // champ email
         }
    </script>
    </body>

    concevoir une page avec tableau en 100% javascript

    Dans l’exemple suivant, on va voir la création d’un tableau d’une seule rangée, mais avec de nombreuses cellules. On va donc utiliser une boucle bornée, pour sa création, mais aussi pour relever les valeurs.

    Une table en HTML est réalisée à partir d’éléments qui ont la hierarchie suivante :

    L’élément form est parent d’un élément table, lui même parent de tbody, parent de tr (le ou les rangs) qui possède, lui plusieurs enfant td, un par cellule :

    arbre du DOM
    arbre du DOM pour le tableau

    On commence par selectionner le noeud de l’élément form :

    let form = document.getElementsByTagName("form")[0];

    Au début du script on créé les différents noeuds pour ces éléments. Par exemple :

    let tbl = document.createElement("table");

    On créé un noeud pour l’élément input qui sera mis dans chaque cellule. Ce noeud est affecté à la variable cellText.

    On créé les attributs de cet élément. On utilise la méthode setAttribute(attribut,valeur) :

    cellText.setAttribute("type", "text");

    On ajoute alors le noeud au DOM avec :

     document.body.appendChild(cellText);

    L’élément créé est alors : <input type="text">

    Pour chaque cellule td du tableau, on ajoute l’élément input :

    cell.appendChild(cellText);

    Puis on ajoute l’élément td au noeud tr :

    row.appendChild(cell);

    Puis l’élément tr à tbody, lui même à table, et table à form.

    arbre du DOM
    inspecteur web : console

    See the Pen DOM tableau by tixidor (@tix06) on CodePen.

    Liens

    Python algo KNN

    Algorithme des k plus proches voisins

    notebook

    Le notebook présenté ici se trouve à l’adresse tix06.github.io/jupyterlite_NSI

    Choisir le dossier TP4_data_analyse puis le notebook algoKNN.ipynb.

    Exercez vous en suivant le tutoriel avec ce notebook.

    Principe

    On cherche une correspondance entre les caractéristiques physiques d’un joueur de basket et son poste sur le terrain.

    Pour simplifier, on considerera que les postes sont au nombre de trois :

    • le joueur Centre, noté ‘C’ (position 5 sur le schéma)
    • Le joueur Ailier, noté ‘F’ (positions 3 et 4 sur le schéma)
    • Le joueur arrière ou meneur de jeu, noté ‘G’ (positions 1 et 2 sur le schéma)
    image URI

    Il nous faut, pour rechercher une correspondance, avoir accès à une base de données des joueurs de basket, jouant par exemple dans un même championnat.

    En étudiant cette première population, on va pouvoir prédire quel poste pourrait occuper un nouveau joueur entrant dans ce championnat (qui serait drafté), à partir de ses seules caracteristiques physiques.

    Cette idée est un peu simpliste : le poste occupé sur le parquet ne dépend pas, bien sur des seules caractéristiques physiques, mais aussi des copétences du joueur.

    Mais nous allons chercher dans ce TP si l’idée est plutôt cohérente.

    On traite alors un jeu de données bi-dimentionnelles à N classes (où N estle nombre de postes occupés par les joueurs).

    On va pour cela utiliser l’algorithme des k-plus-proches-voisins. C’est l’un des algorithmes les plus utilisés dans le domaine de l’apprentissage automatique ou machine learning.

    Comme pour tous les types d’apprentissage automatique, le principe est le suivant :

    • on commence par étudier une population donnée, dite d’entrainement. La qualité d’échantillonnage utilisé pour cette population va déterminer la bonne prédiction par cet algorithme. L’étude de cette population doit permettre de créer des ensembles d’objets aux propriétés similaires. Par exemple, l’ensemble constitué des joueurs de type Centre seront probablement plus grands et plus forts que les autres joueurs.

    • On dispose ensuite d’une population exterieure à cet échantillonnage. On cherche à prevoir leur position sur le terrain par rapport à leurs caractéristiques physiques, d’après les résultats de l’étude préalable.

    La ligue de basket NBA

    Les données sont issues de la page : [https://fr.global.nba.com/playerindex/](https://fr.global.nba.com/playerindex/]

    tableau joueurs NBA
    extrait du tableau des joueurs de NBA

    La ligue de basket americaine contient environ 400 joueurs professionnels. La plupart de nationalité américaine. On dispose d’un extrait de ce fichier (voir dans le dossier datas), constitué de 57 joueurs, classés par ordre alphabetique.

    Chargement du fichier base de données

    Python : librairies numpy et pandas

    Le traitement des données se fera en langage Python.

    On commence par charger les librairies utiles pour le traitement de ces données. Puis on transforme celles-ci en un DataFrame, une sorte de tableau à 2 entrées. Les valeurs de taille et de poids sont toutes de type float après ce premier traitement.

    import numpy as np
    import pandas as pd
    data = pd.read_csv("datas/joueursNBA2020.csv", sep=";")
    tableau_reduit=data[['nom','equipe','poste','taille','poids','experience','pays']].dropna()
    tableau_reduit['poids']=tableau_reduit['poids'].replace(to_replace ='kg', value = '', regex = True)
    tableau_reduit['poids']=tableau_reduit['poids'].astype('float')
    tableau_reduit['taille']=tableau_reduit['taille'].astype('float')
    tableau_reduit.head() # on affiche le debut du tableau avec la fonction .head()

    Filtrer les données du DataFrame

    On peut maintenant filtrer les joueurs du tableau selon le poste du joueur. On utilise pour cela la fonction .loc associée au DataFrame. On met en paramètre un predicat qui sera testé pour chacun des objets du DataFrame. Seuls les objets au prédicat true sont conservés :

    ensemble = tableau_reduit.loc[tableau_reduit['poste']=='C']

    Question : Dans cet exemple : A quel poste jouent les joueurs conservés dans le DataFrame ensemble? Vérifiez le dans la console…

    Afficher les joueurs sur un graphique taille-poids

    On créé une fonction points qui ajoute le nuage de points pour chacun des éléments de la liste postes mise en paramètre. On créé un nuage de points de couleur et d’étiquette différent pour chaque poste occupé.

    Les paramètres de cette fonction :

    • postes : on peut y mettre le caractère correspondant au poste comme ‘G’, ‘F’, ou ‘C’. On peut aussi y mettre une liste constituée de certains, ou tous les postes.
    • Les autres paramètres sont optionnels : il s’agit de la taille et de la forme du marqueur, et de la transparence.
    import matplotlib.pyplot as plt
    from matplotlib.patches import Ellipse, Circle 
    
    def points(postes,size=20,marker='o',alpha=0.5):
        """
        fonction qui ajoute des points au graphique existant
        
        Le paramètres :
        * postes peut être une liste de postes comme par exemple ['G','F','C']
        ou bien un seul poste, comme par exemple 'C'
        * les autres paramètres sont optionnels
        """
        for poste in postes:
            ensemble = tableau_reduit.loc[tableau_reduit['poste']==poste]
            x=ensemble['taille']
            y=ensemble['poids']
            plt.scatter(x,y,label=poste, s=size, marker=marker, alpha=alpha)

    Avec les lignes suivantes, on affiche sur un même graphique les joueurs du tableau jouant aux postes ‘G’, ‘F’, ‘C’.

    Les joueurs du poste ‘C’ sont mis en relief avec un marqueur plus gros.

    Question : Repérez à quel endroit se regroupent les joueurs ‘C’…

    plt.title('caractéristiques des joueurs de NBA 2020')
    plt.xlabel("taille")
    plt.ylabel("poids")
    plt.grid(which='major', linestyle='-', linewidth='0.5', color='red')
    points(['F','G'])
    
    points('C',100,'D',1)
    axes = plt.gca()
    plt.legend()
    plt.savefig('datas/centre.png')
    plt.show()

    joueurs au poste ‘C’ dans la population NBA joueurs au poste ‘C’ dans la population NBA

    Travail : Utilisez la fonction points pour représenter les 3 ensembles ‘C’, ‘F’ et ‘G’. Mais cette fois, on veut mettre en relief :

    • les joueurs ‘F’ dans un 2e graphique
    • Puis mettre en relief les joueurs ‘G’ dans un 3e graphique.
    # Correction
    plt.title('caractéristiques des joueurs de NBA 2020')
    plt.xlabel("taille")
    plt.ylabel("poids")
    plt.grid(which='major', linestyle='-', linewidth='0.5', color='red')
    points(['G','C'])
    
    points('F',100,'D',1)
    axes = plt.gca()
    plt.legend()
    plt.savefig('datas/ailier.png')
    plt.show()

    joueurs au poste ‘F’ dans la population NBA joueurs au poste ‘F’ dans la population NBA

    # Correction
    plt.title('caractéristiques des joueurs de NBA 2020')
    plt.xlabel("taille")
    plt.ylabel("poids")
    plt.grid(which='major', linestyle='-', linewidth='0.5', color='red')
    points(['F','C'])
    
    points('G',100,'D',0.5)
    axes = plt.gca()
    plt.legend()
    plt.savefig('datas/arriere.png')
    plt.show()

    joueurs au poste ‘G’ dans la population NBA joueurs au poste ‘G’ dans la population NBA

    Prediction du poste du joueur

    population dont le poste est inconnu

    Certains joueurs ont des caractéristiques qui les rendent plus polyvalents.

    Question : En observant le tableau_reduit en entier : Quels sont ces postes polyvalents ?

    Ces joueurs n’ont été mis sur aucun des graphiques d’apprentissage vus plus haut. Et si vous utilisiez un algorithme prédictif pour deviner le meilleur poste auquel ils devraient être ? Nous allons étudier en détail cet algorithme, des k plus proches voisins…

    Prenons par exemple les joueurs polyvalents à l’étiquette “G-F”. Ces joueurs, sont-ils plutôt pressentis pour être G (arrière), ou F (ailier) ?

    C’est ce que nous allons chercher à déterminer.

    Travail : en utilisant la méthode .loc associée au DataFrame tableau_reduit : filtrer les joueurs dont le poste est ‘G-F’, et affecter ce nouveau DataFrame à la variable ensemble Afficher alors ce nouveau tableau

    # Correction
    ensemble = tableau_reduit.loc[tableau_reduit['poste']=='G-F']
    ensemble

    Choisir un joueur

    Travail : Repérer le numéro de l’index du premier joueur au poste ‘G-F’ dans ce tableau. Afficher l’ensemble des informations relatives à ce joueur à l’aide de l’instruction ensemble.loc[numero index]

    # Correction
    ensemble.loc[9]

    Utiliser la fonction joueur() pour l’afficher sur le graphique

    Affichons un marqueur pour ce joueur au milieu de la distribution d’entrainement. Pour cela, on utilise une fonction de nom joueur() dont les paramètres sont les suivants :

    • num : le numero de l’index du joueur dans le tableau
    • rayon : le rayon du cercle dans lequel on recherche les k-plus proches voisins. Ce rayon est mesuré dans une unité relative au poids du joueur. L’echelle de l’axe des abscisses, la taille étant très différente, on réalise un calcul prenant en compte le ration DX/DY pour exprimer l’éloignement dans cette direction (un ecart de 10kg n’a pas la même signification qu’un écart de 10cm…)
    def joueur(num, rayon):
        """
        positionne le point relatif au joueur de numero num
        et trace un cercle de rayon r exprimé dans une unité relative à l'axe des Y
        Le demi axe de l'ellipse pour X est calculé par rapport au ratio = DX/DY : 
        r_X = r_y*ratio
        """
        ratio = 0.005 # echelle des X / echelle des Y
        plt.title('caractéristiques des joueurs de NBA 2020')
        plt.xlabel("taille")
        plt.ylabel("poids")
        plt.grid(which='major', linestyle='-', linewidth='0.5', color='red')
        points(['F','G','C'])
        x = ensemble.loc[num]['taille']
        y = ensemble.loc[num]['poids']
        plt.scatter(x,y,label=poste, s=50, marker='P', alpha=1)
        circle = plt.Circle((x, y), 1, color='r')
        fig = plt.gcf()  # gcf() signifie obtenir le chiffre actuel
        ax = fig.gca()  # gca() signifie Obtenir l'axe actuel
        ax.set_aspect(ratio)  # je choisi le ratio DX/DY pour les echelles des axes
        ax.add_artist(Ellipse((x, y), rayon*ratio, rayon, color='yellow',alpha=0.2))
        plt.legend()
        plt.savefig('datas/joueur'+str(num)+'.png')
        plt.show()

    Afficher le joueur sur le graphique

    Travail : utiliser la fonction joueur() pour afficher un marqueur pour ce joueur. On prendra un rayon égal à 20 pour le paramètre rayon.

    # correction
    joueur(9,20)

    joueurs n°9 dans la population NBA joueurs n°9 dans la population NBA

    L’algorithme des k-plus proches voisins

    L’algorithme des k-plus proches voisins peut s’écrire en langage naturel :

    1. trouver dans la collection d’entrainement les k plus proches voisins du joueur
    2. Parmi ces proches voisins, trouver la classification majoritaire
    3. Renvoyer la classification majoritaire

    Travail : Commencez par fabriquer un DataFrame ensembleG contenant tous les joueurs au poste ‘G’.

    Puis, avec cette même methode, construire les DataFrame ensembleF et ensembleC

    # Correction
    ensembleG = tableau_reduit.loc[tableau_reduit['poste']=='G']
    ensembleF = tableau_reduit.loc[tableau_reduit['poste']=='F']
    ensembleC = tableau_reduit.loc[tableau_reduit['poste']=='C']

    Enfin, construire un DataFrame ensemble qui sera réalisé par concaténation des 3 premiers.

    Afficher les premieres lignes de ce DataFrame (avec la fonction .head()

    Aide sur la fonction concat : ensemble = pd.concat([DataFrame1,DataFrame2,DataFrame3])

    # Correction
    ensemble = pd.concat([ensembleG,ensembleF,ensembleC])
    ensemble.head()

    Puis ajoutons une nouvelle colonne avec la distance au joueur de numero num dans le graphique :

    def distance(num,ratio):
        x = tableau_reduit.loc[num]['taille']
        y = tableau_reduit.loc[num]['poids']
        ensemble['dist'] = ensemble.apply(lambda row: (((row["taille"] - x)/ratio)**2 + (row["poids"] - y)**2)**0.5, axis=1)
        # On trie le tableau par valeur dist croissante
        ensemble_trie = ensemble.sort_values(by = 'dist')
        return ensemble_trie
    ensemble_trie = distance(9,0.005)
    ensemble_trie

    Trier les résultats

    On voudrait maintenant dénombrer, par poste, les joueurs aux caractéristiques les plus proches de notre joueur au poste inconnu. Sur un echantillon des k premiers joueurs du tableau précédent.

    Travail : Créer une fonction knn(k) qui renvoie un dictionnaire score avec pour chacune des clés, ‘G’, ‘F’, et ‘G’, le nombre de joueurs du tableau parmi les k premiers.

    # Correction
    def knn(k):
        score={'G':0,'F':0,'C':0}
        for i in range(k):
            z=ensemble_trie.index[i]
            if ensemble_trie.loc[z]['poste']=='G' : 
                score['G']+=1
            elif ensemble_trie.loc[z]['poste']=='F' :
                score['F']+=1  
            else : score['C']+=1
        return score  

    On peut afficher les 3 premiers joueurs du tableau trié, avec l’une des méthodes associée au DataFrame :

    DataFrame.head(nombre de lignes à afficher)

    ensemble_trie.head(3)
    knn(3)

    Travail : Ecrire une fonction qui renvoie le poste le plus représenté selon la valeur de k choisie. Faites alors quelques essais. Conclure quand à la pertinence du résultat selon la valeur de k choisie.

    Prolongement

    On peut réaliser ce même travail : pour rechercher les k plus proches voisins :

    • d’un autre joueur au profil ‘G-F’
    • pour un joueur d’un autre profil, comme par exemple ‘F-G’

    Liens

    Python Datas analyse

    Notebooks associés

    Intelligence artificielle (IA)

    L’intelligence artificielle désigne des algorithmes plus ou moins évolués qui traitent des problèmes dont la résolution fait appel à l’intelligence humaine. Ils imitent des actions humaines.

    Le comportement de l’algorithme évolue au cours du temps, en fonction des données qui lui sont fournies.

    Aujourd’hui, ce sont les chatbots qui illustrent le mieux cette notion d’IA. Il existe ainsi:

    • les chatbots basés sur des règles: (plus simples que l’ IA):
      • suivent un ensemble de règles pré définies
      • servent pour un flux de discussion prédeterminé
      • doivent être configurés à chaque mise à jour
    • les chatbots basés sur IA:
      • comprennent le contexte, interprètent l’intention d’une conversation
      • peuvent apprendre des interactions
      • peuvent traiter des projets plus complexes

    Les chatbots issus de l’IA conversationnelle: sont des technologies grâce auxquelles les logiciels peuvent converser avec des personnes en utilisant le langage naturel.

    Analyse de données et machine learning

    une définition

    imaginons que vous vouliez créer une IA qui vous donne le prix d’un appartement à partir de sa superficie.

    Dans les années 1950, vous auriez fait un programme du type « si la superficie est inférieure à 20m², le prix vaut 60 000€, si elle est entre 20m² et 30m², le prix vaut 80 000€, etc… », ou peut-être « prix = superficie*3 000 ».

    Mais ce type de problème ne peut pas être résolu de manière satisfaisante avec de telles approximations: il vaudrait mieux constater le prix de plusieurs appartements, issus de différents quartiers, de qualités différentes (des variables, comme la superficie, l’exposition, le vis-à-vis…). On pourra alors estimer le prix d’un nouvel appartement non-référencé selon ses caractéristiques (ses variables).

    C’est ce type de démarche qui est attendu lorsque l’on fait du machine learning, ou de l’apprentissage autonome. C’est un sous-domaine de l’intelligence artificielle. En pratique, le programme va analyser une partie des données pour rechercher les corrélations ou les similitudes entre les objets. Il va alors former des classes, ou établir des relations, ou des probabilités.

    Le machine learning est un domaine large, qui comprend de très nombreux algorithmes. Parmi les plus célèbres, on retrouve :

    • Les régressions (linéaires, multivariées, polynomiales, régularisées, logistiques…) : ce sont des courbes qui approximent les données
    • L’algorithme de Naïve Bayes : l’algorithme donne la probabilité de la prédiction, sachant les événements antérieurs. Par exemple, quel est le prix le plus probable sachant que l’appartement X fait 43.7m², qu’il occupe une position privilégiée dans le quartier Montmartre, en rez de jardin, sans parking, sans vis-à-vis… voir à ce sujet l’excellent article sur le blog sciencesetonnantes de David Louapre : probabilités conditionnelles (Bayes)
    • Le clustering : toujours grâce aux mathématiques, on va grouper les données en paquets de manière à ce que dans chaque paquet les données soient les plus proches possibles les unes des autres. C’est utilisé notamment pour des recommandations (films, articles achetés…)
    • Les arbres de décision : en répondant à un certain nombre de questions et en suivant les branches de l’arbre qui portent ces réponses, on arrive à un résultat (avec un score de probabilité)
    • Ainsi que des algorithmes plus perfectionnés reposant sur plusieurs techniques de statistiques

    Les domaines professionnels

    Tous les champs professionnels, du moment où il y a des données qui sont collectées : dans l’entreprise, le commerce, dans la recherche, …

    Ces données sont collectés à partir d’objets connectés, à partir de l’activité des internautes sur les sites de e-commerce (marketing digital), des statistiques d’utilisation de produits, de véhicules, de bâtiments, voire des données collectées suite à des évènements naturels, biologiques, etc.

    Ces données peuvent servir les domaines de la santé (suivi de la propagation d’épidémies, aide au diagnostic,… des transports (analyse de flux,), de l’environnement (prévisions météorologiques, contrôle de la pollution), mais aussi dans l’analyse de la clientèle dans l’industrie et le commerce.

    En se basant sur des informations passées, les techniciens spécialisés dans l’observation des grosses données (big datas) peuvent ainsi faire des prévisions dans chacun de ces domaines. Ou prendre des décisions en fonction des variables.

    Le principe : on récupère les données, on les nettoie, on les explore, puis on utilise nos algorithmes pour créer de l’intelligence (artificielle) qui aide à la prévision/décision. Ces algorithmes sont basés sur des outils statistiques. La machine qui execute un tel algorithme est capable d’apprendre de manière autonome, dans une séquence où les données collectées servent à établir un modèle. La machine améliore son modèle grâce à un score associé à l’exploitation des données. Puis elle utilise ce modèle lorsque le score est optimal pour résoudre une série de problèmes.

    Exemples :

    • biologie :
      • Expressions de gènes (transcriptome, relation gène / protéines)
      • Paléontologie et évolutions
    • médecine : Pharmacovigilance
    • chimie :
      • Prédiction de la toxicité des molécules, mécanismes réactionnels
    • physique :
      • Astronomie : répertoire des corps célestes
      • Expériences en physique des particules (LHC au CERN)
    • sciences environnementales :
      • Comprendre les milieux naturels, l’impact de l’homme, etc
    • sciences sociales :
      • Analyse d’opinions sur le Web
      • Analyse des recherches sur le Web : Google Trends

    Vocabulaire

    • dataset : jeu de données. Ce jeu de données peut en contenir un petit nombre ou un très grand nombre de données (big data). Ces données peuvent être discretes (qualitatives) ou continues (valeurs numériques).

    • big data : données massives. Des données qui sont collectées en continu et en grande quantité. Cela constitue un flux si important qu’il est obligatoire d’utiliser des techniques de traitement spécifiques au domaine du machine learning pour pouvoir les exploiter. On décrit le big data à l’aide des 3V : Volume, Velocity (peu de temps pour traiter les données), Variety (des données diverses)

    • Une classe : c’est un champ particulier à valeurs discrètes.

    • Différents type de programmes en analyse de données : programme de classification, de prédiction, d’estimation, d’association.

    • La classification : consiste à examiner les caractéristiques d’un objet et lui attribuer une classe :

      • attribuer ou non un prêt à un client
      • établir un diagnostice
      • placer une roche, une espèce végétale, animale… dans une catégorie
    • Prédiction : consiste à prédire la valeur future d’un attribut en fonction d’autres attributs. Deux exemples :

      • Regression : estimer le chiffre d’affaire d’un nouveau magasin, estimer le prix du loyer en fonction de la surface de l’habitation
      • classification supervisée : estimer la probabilité qu’un client pratique un sport donné à partir de l’historique de ses achats
    • Modèles prédictifs : utilisent les données avec des résultats connus pour développer des modèles permettant de prédire les valeurs d’autres données.

    • Modèle descriptif : propose des descriptions des données pour aider à la prise de décision. C’est un modèle surtout utilisé en segmentation et association.

    • Apprentissage supervisé : les données à analyser comprennent à la fois des données d’entrée et de sortie. On connait la classe des objets, et on cherche à prévoir l’appartenance à une de ces classes pour tout nouvel objet.

    Lorsque l’on cherche à comprendre ou définir une relation entre les données, on peut pratiquer une association : qui consiste à déterminer les attributs qui sont corrélés :

    C’est ce que l’on réalise lorsque l’on fait l’analyse d’un panier de courses au supermarché (ou sur un site d’e-commerce) : poisson et vin blanc sont deux articles qui vont souvent occuper ensembles le panier.

    • Apprentissage non supervisé : Seules les entrées sont fournies. Par exemple : identifier des familles de fournisseurs et de clients pour faire un mailing ciblé

    Une technique pratiquée en apprentissage non supervisé : la Segmentation : consiste à former des groupes homogène à l’intérieur d’une population (des clusters).

    Les étapes du traitement de données

    • Aggréger ces données dans un data lake.
    • Nettoyer les données. C’est à dire s’assurer qu’elles sont consistantes, sans valeurs aberrantes ni manquantes, et mises dans le bon format.
    • Explorez les données. Cette étape doit permettre de mieux comprendre les différents comportements et de bien saisir le phénomène sous-jacent. On cherche:
      • soit à réaliser une classification, par exemple sous forme arborescente. C’est ce que l’on cherche à réaliser lorsque l’on peut discriminer la population à trier à partir de critères qualitatifs. L’idée est alors de trouver les bonnes clés de tri, qui vont partager la population.
      • soit à chercher une corrélation entre grandeurs, si celle-ci sont numériques. Chaque donnée observée est l’expression d’une variable aléatoire générée par une distribution de probabilité. On cherche alors à énoncer une conclusion du type : “suite à l’exploration, il y a clairement une relation entre X et Y, ces 2 grandeurs semblent liées par une relation de regression linéaire (ou non linéaire) du type Y = a*X + b (ou autre)”.
    • Modéliser les données.
      • Dans le premier cas, à partir de valeurs dites discrètes (des catégories), on devra réaliser une segmentation des objets en entrée en différentes catégories. La prédiction réalisée à partir d’une nouvelle entrée donne en sortie une liste de labels possibles.
      • Dans le deuxième cas, il s’agira d’un traitement statistique des données.
    illutration de la différence entre classification et regression linéaire

    illutration de la différence entre classification et regression linéaire

    • Déployer le modèle. Une fois le modèle établi, on va encore le vérifier et l’ajuster à partir de certaines des données : il faudra donc prévoir une séparation initiale de ces données : certaines des données servent à générer le modèle (le training set). Les autres sont celles qui vont permettre de valider (tester) ou améliorer si besoin le modèle (le testing set).
    • Prévoir la catégorie ou faire de la prédiction à partir des nouvelles données.

    Le machine learning est l’apprentissage d’un modèle statistique par la machine grâce à des données d’entraînement. Un problème de machine learning comporte parmi les étapes une mesure des performances. S’il améliore les performances sur cette tâche lorsqu’on lui fournit les données d’entraînement, on dit alors qu’il apprend.

    Exemples

    On pourra retrouver ces exemples plus en détail dans leur page originale : https://openclassrooms.com/fr/courses/4011851-initiez-vous-au-machine-learning/5868296-transformez-des-besoins-metiers-en-problemes-de-machine-learning

    Comment recommander un produit à un client

    mots clés : Données discretes, règles d’association, apprentissage non supervisé.

    La recommandation est une problématique qui revient très souvent dans l’ananlyse de données pour le marketing électronique. La recommandation se base sur des similarités entre utilisateurs, ou bien des similarités entre produits. Ce filtrage collaboratif repose sur l’adage : Si deux personnes ont aimé des contenus identiques par le passé, elles ont une probabilité élevée d’aimer les mêmes choses dans le futur.

    Sur l’image ci-dessous, on regarde par exemple ce qu’ont voté les utilisateurs similaires, c’est-à-dire ceux qui ont déjà voté la même chose sur d’autres produits (surlignés en vert). On peut alors prédire ce qu’aurait voté notre utilisateur sur le produit cherché, et ne proposer que les produits sur lesquels il aurait mis un pouce vert.

    Les utilisateurs similaires (en vert) n'ont pas aimé le produit que notre utilisateur n'a pas encore noté. L'algorithme aura donc tendance à prédire une mauvaise note et à ne pas recommander le produit ici

    Les utilisateurs similaires (en vert) n'ont pas aimé le produit que notre utilisateur n'a pas encore noté. L'algorithme aura donc tendance à prédire une mauvaise note et à ne pas recommander le produit ici

    Les utilisateurs similaires (en vert) n’ont pas aimé le produit que notre utilisateur n’a pas encore noté. L’algorithme aura donc tendance à prédire une mauvaise note et à ne pas recommander le produit ici.

    En pratique : On peut voir la liste des profils utilisateurs comme une matrice. L’objectif d’un algorithme de recommandation est de remplir les cases vides de cette matrice. Quel serait le score de Gregory (dernière ligne du tableau) pour l’article “ordinateur portable”, marqué avec un ?. Il faudra établir une correspondance entre les objets et les profils.

    Il existe alors plusieurs méthodes d’association :

    • l’association basée sur les clients (voir exemple ci-dessus)

    On pourrait par exemple, calculer un coefficient de similitude entre Gregory et les autres usagers pour tous les articles renseignés, puis établir une liste triée.

    • l’association basée sur les objets (l’exemple dit du panier de la ménagère)
    une liste d'achats

    une liste d'achats

    Cette fois on ne s’interesse plus au profil du client, mais on cherche une règle d’occurence entre les objets. Pour trouver les associations entre 2 produits, on construit le tableau de co-occurrence montrant combien de fois 2 produits ont été achetés ensemble.

    tableau de co-occurence

    tableau de co-occurence

    Ici : le produit A apparaît dans 80% des achats, le produit C n’apparaît jamais en même temps que le produit E, les produits A et D apparaissent simultanément dans 40% des achats. Ces observations peuvent suggérer une règle de la forme : « Si un client achète le produit A ALORS il achète le produit D ».

    On cherche alors à générer des règles du type : si A alors D avec, pour chacune, un pourcentage de confiance. Par exemple, cette règle apparaissant ici apparaissant dans 40% des achats, on considère que le pourcentage de confiance est égal à 40%.

    Le clustering

    mots clés : Données continues, apprentissage non supervisé, algorithme des k-plus proches voisins

    Le clustering désigne les méthodes de regroupement automatique de données qui se ressemblent le plus en un ensemble de “nuages”, appelés clusters. On cherche repérer, et mesurer la similarité entre les différentes données. Par exemple, les points sur le graphe ci-dessous peuvent être considérés comme similaires s’ils sont proches en termes de distance.

    L'objectif du clustering est de retrouver les différents clusters de données, c'est-à-dire de regrouper les données similaires entre elles

    L'objectif du clustering est de retrouver les différents clusters de données, c'est-à-dire de regrouper les données similaires entre elles

    On pourra étudier cet exemple en détail avec la page Python algo KNN de ce même site.

    utilisation d’un arbre de décision

    mots clés : Données discretes ou continues, classes, attributs, segmentation.

    • A partir dʼun ensemble de valeurs d’attributs, il sʼagit de prédire la valeur d’un autre attribut (variable cible).
    • Un arbre est équivalent à un ensemble de règles de décision.

    L’idée est de bien choisir l’(les) attribut(s) discriminant(s). L’arbre est construit en découpant successivement les données en fonction des variables prédictives. L’algorithme qui realise ce travail utilise des grandeurs statistiques pour mesurer la qualité de la segmentation.

    Une fois l’arbre construit, pour prédire la classe (la variable cible) d’une nouvelle entrée (une instance), il faut parcourir l’arbre depuis la racine jusqu’à la feuille.

    Exemple 1 : Il s’agit de prédire si, selon la météo(ciel, temp., humidité et vent), on va aller jouer au tennis.

    construction d'un arbre de décision

    construction d'un arbre de décision

    Chaque chemin, depuis la racine jusqu’à une feuille est une règle de décision. Par exemple ici : si ('ciel' == 'soleil') et ('temp.' == 'doux') et ('humidité' = 'élevée') et ('vent' == 'faible' ) alors (classe = 'oui')

    Exemple 2 : Arbres de classification et régression

    On peut aussi réaliser ce type de segmentation avec des attributs à valeurs continues. On cherche alors à regrouper déterminer des clusters à partir du regroupement des classes.

    L’exemple suivant montre la répartition des éléments dans un diagramme (x1;x2). Une fois ce premier travail réalisé, on pourra construire un arbre de classification à partir des tests sur x1 et x2. Par exemple

    si x2<0.42 alors classe = 'Vert'
    résultat obtenu par recherche de clusters sur un jeu de données bidimensionnelles à trois classes

    résultat obtenu par recherche de clusters sur un jeu de données bidimensionnelles à trois classes

    Liens

    documents utilisés pour la redaction de la page

    Approfondissement

    Python algo de recommandation

    Algorithmes de recommandation

    Lien vers le notebook en ligne : https://mybinder.org/v2/gh/tix06/notebooks_classif/master

    Choisir alors le fichier : algorithme de recommandation.ipynb

    Il s’agit d’un cas très classique d’algorithme utilisé dans le web marketing. Un client choisit et met dans ses favoris un article, ou dans son panier. Le site lui propose des articles compatibles, ou similaires. La recommandation peut être basée sur la description de ces articles. L’algorithme va alors chercher les articles qui ont le plus de points communs dans leur description; c’est à dire le plus de mots communs dans leur description.

    articlesCompatibles.png articlesCompatibles.png

    La première étape pour calculer les similarités consiste à découper les descriptions en listes de mots (c’est la tokenisation) puis à prendre les racines des mots, les stems.

    Extraire les mots d’un texte

    Prenons un exemple avec le texte suivant :

    texte = """
    Mardi 20 février, à la médiathèque des Mureaux (Yvelines), le chef de l’Etat a accompagné
    la locataire de la rue de Valois pour la remise officielle du rapport
    sur les bibliothèques, rédigé par leur ami commun, l’académicien
    Erik Orsenna, avec le concours de Noël Corbin, inspecteur général
    des affaires culturelles. L’occasion de présenter les premières
    mesures en faveur d’un « plan bibliothèques ».
    """

    On utilise alors une expression regulière, ; |, |\' |\n |\s+,pour découper le texte, et conserver les stems dans une liste. C’est ce que réalisera ici la fonction decoupe(texte) :

    import re
    def decoupe(texte):
        """
        utilise une expression regulière pour découper le texte (en paramètre) : 
        - le découpage se fait en fonction de ; ou , ou ' ou \n ou un (ou +) espaces
        - on conserve enfin les stems qui font 4 caractères ou plus
        la fonction retourne une liste de stems
        un stem peut être présent plusieurs fois dans la liste retournée
        """
        texte_decoupe = list(re.split('; |, |\' |\n |\s+',texte))
        texte_mini=[]
        for t in texte_decoupe:
            match = re.match('[a-z]{4,}',t)
            if match!=None:
                texte_mini.append(match.group(0))
        return texte_mini
    texte_mini = decoupe(texte)
    texte_mini
    ['chef',
     'accompagn',
     'locataire',
     'pour',
     'remise',
     'officielle',
     'rapport',
     'biblioth',
     'leur',
     'commun',
     'avec',
     'concours',
     'inspecteur',
     'affaires',
     'culturelles',
     'premi',
     'mesures',
     'faveur',
     'plan',
     'biblioth']
    

    Recommandation d’un article à partir de sa description

    traitement du fichier de données en csv

    import pandas as pd
    df = pd.read_csv("datas/descriptif.csv", sep=";")
    df

    bande dessinee roman ordinateur console de jeux
    0 une bande dessinee est un ouvrage illustre rac... un roman est un ouvrage avec du texte raconte... un ordinateur est un dispositif pour produire ... une console de jeu est un dispositif pour joue...
    # on créé une liste contenant les articles : 
    col = list(df.keys())
    # on créé une liste (descriptif) contenant, pour chaque article, une liste avec TOUS les mots retenus dans la description
    descriptif = []
    for cle in col:
        desc = df[cle][0]
        descriptif.append(decoupe(desc))
    descriptif
    [['bande',
      'dessinee',
      'ouvrage',
      'illustre',
      'racontant',
      'histoire',
      'images',
      'aventure',
      'fantaisie',
      'lire'],
     ['roman',
      'ouvrage',
      'avec',
      'texte',
      'raconte',
      'histoire',
      'biogaphie',
      'aventure',
      'documentaire',
      'lire'],
     ['ordinateur',
      'dispositif',
      'pour',
      'produire',
      'consulter',
      'objets',
      'numeriques',
      'communiquer',
      'calculer',
      'jouer',
      'lire',
      'videos'],
     ['console',
      'dispositif',
      'pour',
      'jouer',
      'jeux',
      'videos',
      'lire',
      'videos',
      'aventure',
      'fantaisie']]
    

    Vecteurs

    L’étape suivante consiste à stocker chacune des descriptions traitées sous forme de vecteurs en base de données.

    Chaque ligne est un vecteur qui correspond à une description, chaque colonne correspond à un stem.

    La fonction mots retourne une liste contenant tous les mots de descriptif, de manière unique. (les mots qui apparaissent plusieurs fois dans descriptif ne sont renvoyés qu’une seule fois dans la liste mot

    La fonction tab créé un tableau où les lignes correspondent au nombre d’occurences de ce mot dans la description de l’objet. La ligne de rang 1 correspond aux occurences pour le premier objet de la description, la ligne de rang 2 au 2e objet de la description,…

    Pour avoir des valeurs normalisées, on transforme ces occurences en une frequence :

    $$f(mot) = \tfrac{nb\quad occurences}{nb\quad mots}$$
    def mots(descriptif):
        """
        retourne la liste de tous les mots de descriptif, de manière unique, dans une seule liste
        """
        liste_de_mots = []
        for desc in descriptif:
            for i in desc : 
                if not(i in liste_de_mots):
                    liste_de_mots.append(i)
        return liste_de_mots
    
    mots(descriptif)
    ['bande',
     'dessinee',
     'ouvrage',
     'illustre',
     'racontant',
     'histoire',
     'images',
     'aventure',
     'fantaisie',
     'lire',
     'roman',
     'avec',
     'texte',
     'raconte',
     'biogaphie',
     'documentaire',
     'ordinateur',
     'dispositif',
     'pour',
     'produire',
     'consulter',
     'objets',
     'numeriques',
     'communiquer',
     'calculer',
     'jouer',
     'videos',
     'console',
     'jeux']
    
    def tab(descriptif):
        """
        retourne la liste tableau avec les occurences pour chaque article (chaque rang) 
        des mots retenus (mots)
        une colonne par mot
        """
        tableau = []
        mots_elements = mots(descriptif)
        for desc in descriptif:
            ligne = []
            nombre_de_mots = len(desc)
            ligne = [desc.count(mot)/nombre_de_mots for mot in mots_elements]
            tableau.append(ligne)
        return tableau
    tableau = tab(descriptif)
    print(tableau)
    [[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 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, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.1, 0.0, 0.0, 0.1, 0.0, 0.1, 0.0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 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], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.08333333333333333, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.08333333333333333, 0.08333333333333333, 0.08333333333333333, 0.08333333333333333, 0.08333333333333333, 0.08333333333333333, 0.08333333333333333, 0.08333333333333333, 0.08333333333333333, 0.08333333333333333, 0.08333333333333333, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.2, 0.1, 0.1]]
    
    # visualisation
    df2=pd.DataFrame(tableau,index=col,columns=mots(descriptif))
    df2
    bande dessinee ouvrage illustre racontant histoire images aventure fantaisie lire … produire consulter objets numeriques communiquer calculer jouer videos console jeux
    bande dessinee 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.100000 … 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.0
    roman 0.0 0.0 0.1 0.0 0.0 0.1 0.0 0.1 0.0 0.100000 … 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.0 0.0
    ordinateur 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.083333 … 0.083333 0.083333 0.083333 0.083333 0.083333 0.083333 0.083333 0.083333 0.0 0.0
    console de jeux 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.1 0.1 0.100000 … 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.100000 0.200000 0.1 0.1

    Calcul des similarités

    La dernière étape est celle du calcul des similarités. Cela consiste à appliquer la similarité cosinus 2 à 2 pour tous les produits de la base de données :

    $$s_{ij}=\tfrac{u_i\cdot u_j}{||ui||\cdot||uj||}$$

    On cherche alors une règle de similitude, du type : A=>B (si on aime A alors on aurait tendance à aussi apprécier B)

    import numpy as np
    def cosij(ui,uj):
        """
        retourne le resultat du calcul de s_ij pour 2 valeurs ui(i) et uj(j)
        paramètres :
        les vecteurs ui et uj de modules mod(ui) et mod(uj)
        """
        s=0
        for i in range(len(ui)):
            s += ui[i]*uj[i]/(mod(ui)*mod(uj))
        return s
    
    def mod(u):
        """
        calcule le module du vecteur mis en paramètre
        """
        s=0
        for i in range(len(u)):
            s += u[i]*u[i]
        s = s**0.5
        return s
    
    def matrice_cos(A,B):
        """
        retourne la matrice de similitude entre 2 listes 
        de dimension 2 (liste de liste), A et B mises en paramètre
        """
        C = np.zeros(shape=(len(A),len(B)))
        for i in range(len(A)):
            for j in range(len(B)):
                C[i,j]=cosij(A[i],B[j])
        return C
    
    mat=matrice_cos(tableau,tableau)
    mat
    array([[1.        , 0.4       , 0.09128709, 0.27386128],
           [0.4       , 1.        , 0.09128709, 0.18257419],
           [0.09128709, 0.09128709, 1.        , 0.5       ],
           [0.27386128, 0.18257419, 0.5       , 1.        ]])
    
    # visualisation du tableau grace à son DataFrame
    df3=pd.DataFrame(mat,index=col,columns=col)
    df3
    bande dessinee roman ordinateur console de jeux
    bande dessinee 1.000000 0.400000 0.091287 0.273861
    roman 0.400000 1.000000 0.091287 0.182574
    ordinateur 0.091287 0.091287 1.000000 0.500000
    console de jeux 0.273861 0.182574 0.500000 1.000000
    # visualisation à l'aide d'un outil en couleur
    import seaborn as sns
    import matplotlib.pyplot as plt
    col = list(df3.keys())
    sns.heatmap(mat, square=True, annot=True, cbar=False
                , xticklabels=list(col)
                , yticklabels=list(col))
    <matplotlib.axes._subplots.AxesSubplot at 0x1a17767250>
    

    png png

    # visualisation avec matplotlib (un peu moins lisible)
    plt.matshow(mat, cmap='rainbow');

    png png

    Interpretation

    On voit assez facilement que :

    • la bande dessinée est proche dans sa description avec le roman, avec un score de 0.4, et un un peu moins proche de la console de jeux (score de 0.27)
    • l’ordinateur est compatible avec la console de jeux, avec un score de 0.5
    • La description de la bande dessinnée et du roman ne contient presque aucun point commun avec l’ordinateur
    def articles(tab):
        tab=tab.sort_values(ascending=False)
        articles = list(tab.index.values)
        recom = 'l\'article \033[1m {0:15} \033[0;0m est similaire à \033[1m{1:15}\033[0;0m voire peut être un peu à \033[1m{2:15}\033[0;0m'.format(articles[0],articles[1],articles[2])
        return recom
    
    def recommandation(dataf):
        texte=[]
        col = list(dataf.keys()) 
        for c in col:
            tab_red=[]
            tab_red = dataf[c]
            texte.append(articles(tab_red))
        return texte
    
    texte = recommandation(df3)
    for t in texte:
        print(t)
    l'article  bande dessinee   est similaire à roman           voire peut être un peu à console de jeux
    l'article  roman            est similaire à bande dessinee  voire peut être un peu à console de jeux
    l'article  ordinateur       est similaire à console de jeux voire peut être un peu à roman          
    l'article  console de jeux  est similaire à ordinateur      voire peut être un peu à bande dessinee 
    

    definir des classes à l’aide d’une représentation en graphe

    import matplotlib.pyplot as plt
    import networkx as nx
    
    mat=matrice_cos(tableau,tableau)
    col = list(df3.keys())
    
    G = nx.Graph()
    
    def makeG(mat,col):
        """
        creation du graphe G à partir : 
        - du paramètre col : la liste des lés (colonnes) du DataFrame fg3 (equiv à la matrice de similitude)
        - du paramètre mat : la matrice de similitude déjà calculée
        Les noeuds du graphe sont constitués à partir des articles
        Les arêtes sont pondérés d'un poids weight qui est la valeur lue dans la matrice de similitude mat
        """
        for i in range(len(mat[:,0])):
            for j in range(len(mat[0,:])):
                G.add_edge(col[i], col[j], weight=mat[i,j])
        return G
    
    
        
    
    #G.add_edge('a', 'b', weight=0.6)
    
    
    def drawG(G,seuil):
        """
        segmentation de arêtes en fonction du paramètre seuil
        - les arêtes de weight >= seuil sont représentées en trait plein sur le graphe
        - celle de weight < seuil sont représentées en trait pointillé
        """
        elarge = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] >= seuil]
        esmall = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] < seuil]
        pos = nx.spring_layout(G)  # positions for all nodes
        # nodes
        nx.draw_networkx_nodes(G, pos, node_size=700)
        # edges
        nx.draw_networkx_edges(G, pos, edgelist=elarge,width=6)
        nx.draw_networkx_edges(G, pos, edgelist=esmall,width=2, alpha=0.5, edge_color='b', style='dashed')
        # labels
        nx.draw_networkx_labels(G, pos, font_size=20, font_family='sans-serif')
        plt.axis('off')
        plt.show()
        
    G = makeG(mat,col)
    drawG(G,0.3)

    png png

    Interprétation

    Il apparait ici clairement 2 classes en choisissant seuil = 0.3 :

    • les articles du genre littérature
    • les articles du genre électronique

    Classification

    L’arbre de classification peut être utile dans le cas L’apprentissage par arbre de décision désigne une méthode basée sur l’utilisation d’un arbre de décision comme modèle prédictif. Dans ces structures d’arbre, les feuilles représentent les valeurs de la variable-cible (les classes) et les embranchements correspondent à des combinaisons de variables d’entrée qui mènent à ces valeurs. En analyse de décision, un arbre de décision peut être utilisé pour représenter de manière explicite les décisions réalisées et les processus qui les amènent.

    Une des variables d’entrée est sélectionnée à chaque nœud intérieur (ou interne, nœud qui n’est pas terminal) de l’arbre selon une méthode qui dépend de l’algorithme.

    L’arbre est en général construit en séparant l’ensemble des données en sous-ensembles en fonction de la valeur d’une caractéristique d’entrée. Il est construit de manière récursive. C’est un algorithme glouton.

    Plus de détail : https://fr.wikipedia.org/wiki/Arbre_de_décision_(apprentissage)

    Il existe ainsi les :

    • arbres de classification (feuille = classe)
    • arbres de regression, qui permettent de prédire une quantité réelle

    Les algorithmes pour construire les arbres de décision sont construits en divisant l’arbre du sommet vers les feuilles en choisissant à chaque étape une variable d’entrée qui réalise le meilleur partage de l’ensemble d’objets, comme décrit précédemment. Pour choisir la variable de séparation sur un nœud, les algorithmes testent les différentes variables d’entrée possibles et sélectionnent celle qui maximise un critère donné.

    suite : voir la page sur les arbres de décision : graphes_mini_prog.md

    Liens

    Python arbre decision

    Arbres de classification

    Lien vers le notebook en ligne : https://mybinder.org/v2/gh/tix06/notebooks_classif/master

    Choisir alors le fichier : graphes_mini_prog.ipynb

    Définition

    Un arbre de classification est utile pour réaliser des prévisions de manière explicite. C’est un outil utilisé

    • pour les algorithmes de backtracking (modéliser une partie d’echecs)
    • pour l’appentissage automatisé (machine learning) supervisé (les classes des entrées sont connue)

    Pour le machine learning l’arbre peut évoluer et se restructurer à partir d’informations reçues.

    A partir des valeurs des données en entrée, l’algorithme va créer des règles pour segmenter, au mieux, la population (les index des entrées) à chaque noeud. En descendant dans l’arbre de classification, on parcourt ses noeuds. Le nombre d’éléments qu’il reste à classer diminue du noeud parent vers un noeud fils : tous les éléments se répartissent sur tous les noeuds fils.

    Enfin, lorsque les éléments d’un noeuds ont tous la même classe, alors la division est terminée. Ce noeud est alors une feuille.

    Exemple : ici, les noeuds 4, 6, 7, 8, 9, 10 sont des feuilles. Ces noeuds contiennent chacun une partie des éléments qui ont servi à construire l’arbre. La totalité de ces éléments occupent le noeud racine, numéro 0, puis sont répartis dans les feuilles selon leur classe.

    exemple d’arbre de classification exemple d’arbre de classification

    Principe

    Utilisation de la librairie sklearn pour créer un arbre de classification/décision à partir d’un fichier de données.

    L’arbre de decision est construit à partir d’une segmentation optimale qui est réalisée sur les entrées (les lignes du tableau).

    Jouer ou ne pas jouer

    fichier de données

    Ici, le fichier de données est datas/jouer0.png. Il contient les données méteorologiques et les classes (jouer/ne pas jouer au golf) pour plusieurs types de conditions météo (les lignes).

    Ce fichier ne devra contenir que des données numériques (mis à part la première ligne, contenant les étiquettes des colonnes, les features).

    Classifier puis prédire

    Une fois l’arbre de classification établi, on pourra le parcourir pour prédire la classe d’une nouvelle entrée, en fonction de ses valeurs : l’arbre sert alors comme une aide à la décision.

    En pratique, il faudra créer une structure qui contient l’arbre, avec ses noeuds, leur association, et les tests qui sont effectués pour descendre d’un noeud parent à l’un des ses noeuds fils. On peut choisir d’utiliser un dictionnaire python pour contenir cette structure. Le dictionnaire étant un tableau associatif.

    Comme les données sont toutes numériques, les tests réalisés à chaque noeud, pour traduire la division des éléments s’écrivent de la manière suivante :

    Soit X une liste de listes contenant : les éléments à classer, et les valeurs pour chacun des éléments :

    X[i] fait alors référence à la valeur des éléments pour la colonne n°i.

    pour touts les éléments présents au noeud courant : 
        si X[i] <= valeur_seuil alors :
            descendre vers le noeud fils gauche
            sinon : descendre vers le noeud fils droit

    Import des librairie et création de l’arbre de décision

    from sklearn import tree
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.tree import export_text
    import pandas as pd
    df = pd.read_csv("datas/jouer0.csv",sep=";")
    #col = df.columns
    X = df.iloc[:,:-1] # les données sont toutes les colonnes du tableau sauf la dernière
    y = df.iloc[:,-1]  # les classes sont dans la dernière colonne (jouer/ne pas jouer)
    
    clf = tree.DecisionTreeClassifier()
    clf = clf.fit(X, y)  # on entraine l'arbre à l'aide du jeu de données
    df

    temps température humidité vent jouer
    0 1 30 85 0 0
    1 1 27 90 1 0
    2 0 28 78 0 1
    3 -1 21 96 0 1
    4 -1 20 80 0 1
    5 -1 18 70 1 0
    6 0 18 65 1 1
    7 1 22 95 0 0
    8 1 21 70 0 1
    9 -1 24 80 0 1
    10 1 24 70 1 1
    11 0 22 90 1 1
    12 0 27 75 0 1
    13 -1 22 80 1 0

    accéder au paramètres calculés pour l’arbre

    # Using those arrays, we can parse the tree structure:
    
    n_nodes = clf.tree_.node_count
    children_left = clf.tree_.children_left    # noeud fils gauche pour le noeud courant (ou -1 si aucun noeud enfant)
    children_right = clf.tree_.children_right  # noeud fils droit pour le noeud courant (ou -1 si aucun noeud enfant)
    feature = clf.tree_.feature                # numéro de la colonne pour la valeur testée 
    #                                          # par exemple : feature = 0 <=> temps
    #                                          # par exemple : feature = 1 <=> temperature ...                                            
    threshold = clf.tree_.threshold            # valeur seuil du test realisé au noeud courant

    Exploration de la structure de données

    for i in  range(n_nodes):
        print('noeud :',i)
        print('fg :',children_left[i])
        print('fd :', children_right[i])
        print('feature : ',feature[i])
        print('thershold :',threshold[i])
        print('----------')
        
    noeud : 0
    fg : 1
    fd : 6
    feature :  0
    thershold : 0.5
    ----------
    noeud : 1
    fg : 2
    fd : 3
    feature :  3
    thershold : 0.5
    ----------
    noeud : 2
    fg : -1
    fd : -1
    feature :  -2
    thershold : -2.0
    ----------
    noeud : 3
    fg : 4
    fd : 5
    feature :  0
    thershold : -0.5
    ----------
    noeud : 4
    fg : -1
    fd : -1
    feature :  -2
    thershold : -2.0
    ----------
    noeud : 5
    fg : -1
    fd : -1
    feature :  -2
    thershold : -2.0
    ----------
    noeud : 6
    fg : 7
    fd : 8
    feature :  2
    thershold : 77.5
    ----------
    noeud : 7
    fg : -1
    fd : -1
    feature :  -2
    thershold : -2.0
    ----------
    noeud : 8
    fg : -1
    fd : -1
    feature :  -2
    thershold : -2.0
    ----------
    

    creation d’une structure de type dictionnaire pour contenir l’arbre

    Cette struture contiendra aussi les conditions, afin de pouvoir l’utiliser pour décision.

    def isleaves(node):
        if (children_left[node]==-1 & children_right[node]==-1) :
            return True
        else:
            return False
    
    
    def construct(node_id):
        arbre[node_id] = {}
        #if node_id != 0:
        if isleaves(node_id):
            return {'node':node_id}
        else : 
            return {'node':node_id,'feature':feature[node_id],'threshold':threshold[node_id],'fg':construct(children_left[node_id]),'fd':construct(children_right[node_id])}
            
    arbre = {}       
    construct(0)
    {'node': 0,
     'feature': 0,
     'threshold': 0.5,
     'fg': {'node': 1,
      'feature': 3,
      'threshold': 0.5,
      'fg': {'node': 2},
      'fd': {'node': 3,
       'feature': 0,
       'threshold': -0.5,
       'fg': {'node': 4},
       'fd': {'node': 5}}},
     'fd': {'node': 6,
      'feature': 2,
      'threshold': 77.5,
      'fg': {'node': 7},
      'fd': {'node': 8}}}
    
    # visualisation du graphe en console
    r = export_text(clf, feature_names=None)
    print(r)
    |--- feature_0 <= 0.50
    |   |--- feature_3 <= 0.50
    |   |   |--- class: 1
    |   |--- feature_3 >  0.50
    |   |   |--- feature_0 <= -0.50
    |   |   |   |--- class: 0
    |   |   |--- feature_0 >  -0.50
    |   |   |   |--- class: 1
    |--- feature_0 >  0.50
    |   |--- feature_2 <= 77.50
    |   |   |--- class: 1
    |   |--- feature_2 >  77.50
    |   |   |--- class: 0
    
    # visualisation rapide de l'arbre de classification
    tree.plot_tree(clf)
    [Text(167.4, 190.26, 'X[0] <= 0.5\ngini = 0.459\nsamples = 14\nvalue = [5, 9]'),
     Text(83.7, 135.9, 'X[3] <= 0.5\ngini = 0.346\nsamples = 9\nvalue = [2, 7]'),
     Text(41.85, 81.53999999999999, 'gini = 0.0\nsamples = 5\nvalue = [0, 5]'),
     Text(125.55000000000001, 81.53999999999999, 'X[0] <= -0.5\ngini = 0.5\nsamples = 4\nvalue = [2, 2]'),
     Text(83.7, 27.180000000000007, 'gini = 0.0\nsamples = 2\nvalue = [2, 0]'),
     Text(167.4, 27.180000000000007, 'gini = 0.0\nsamples = 2\nvalue = [0, 2]'),
     Text(251.10000000000002, 135.9, 'X[2] <= 77.5\ngini = 0.48\nsamples = 5\nvalue = [3, 2]'),
     Text(209.25, 81.53999999999999, 'gini = 0.0\nsamples = 2\nvalue = [0, 2]'),
     Text(292.95, 81.53999999999999, 'gini = 0.0\nsamples = 3\nvalue = [3, 0]')]
    
    décider de jouer avec un arbre de décision

    décider de jouer avec un arbre de décision

    Contenu de chaque noeud :

    • la condition qui est testée : par ex au noeud 0, X[0]<=0.5 (le temps est moins bien qu’ensoleillé) VRAI => à gauche, FAUX => à droite
    • le coefficient de gini (qui doit être égal à 0 ou presque dans les feuilles)
    • le nombre d’éléments dans le noeud
    • value = le nombre d’éléments de chaque classe [classe 0 : ne jouent pas, classe 1 : jouent]
    arbre = construct(0)
    print(arbre)
    {'node': 0, 'feature': 0, 'threshold': 0.5, 'fg': {'node': 1, 'feature': 3, 'threshold': 0.5, 'fg': {'node': 2}, 'fd': {'node': 3, 'feature': 0, 'threshold': -0.5, 'fg': {'node': 4}, 'fd': {'node': 5}}}, 'fd': {'node': 6, 'feature': 2, 'threshold': 77.5, 'fg': {'node': 7}, 'fd': {'node': 8}}}
    

    Liens

    Python graphe et NPI

    tracer un arbre à partir d’une expression NPI

    NPI : notation polonaise inversée

    En particulier : on dispose d’une expression en NPI, du type :

    L3 = [7,8,'-',6,'*',10,3,'+','*']

    Et on veut créer et afficher le graphe correspondant :

    On utilisera le script :

    L3 = [7,8,'-',6,'*',10,3,'+','*']
    
    D = makeTree(L3)
    G = nx.Graph()
    graphDict(D)

    Dont l’instruction suivante va générer le dictionnaire à partir de l’expression NPI (fonction npiTree recursive):

    D = makeTree(L3)
    D
    # affiche {'*': ({'*': ({'-': (7, 8)}, 6)}, {'+': (10, 3)})}

    Ce dictionnaire peut être alors parcouru avec des elgorithmes recursifs, comme par exemple celui de la fonction createEdges qui est un parcours en profondeur.

    Le script permet aussi de créer une structure intermédiaire sous forme de dictionnaire, et permet d’afficher le graphe à partir de tout dictionnaire D :

    G = nx.Graph()
    graphDict(D)

    Le graphe est dans le format networkx. On pourra consulter la notice à l’adresse suivante :

    def hierarchy_pos(G, root=None, width=1., vert_gap = 0.2, vert_loc = 0, xcenter = 0.5):
    
        '''
        From Joel's answer at https://stackoverflow.com/a/29597209/2966723.  
        Licensed under Creative Commons Attribution-Share Alike 
    
        If the graph is a tree this will return the positions to plot this in a 
        hierarchical layout.
    
        G: the graph (must be a tree)
    
        root: the root node of current branch 
        - if the tree is directed and this is not given, 
          the root will be found and used
        - if the tree is directed and this is given, then 
          the positions will be just for the descendants of this node.
        - if the tree is undirected and not given, 
          then a random choice will be used.
    
        width: horizontal space allocated for this branch - avoids overlap with other branches
    
        vert_gap: gap between levels of hierarchy
    
        vert_loc: vertical location of root
    
        xcenter: horizontal location of root
        '''
        if not nx.is_tree(G):
            raise TypeError('cannot use hierarchy_pos on a graph that is not a tree')
    
        if root is None:
            if isinstance(G, nx.DiGraph):
                root = next(iter(nx.topological_sort(G)))  #allows back compatibility with nx version 1.11
            else:
                root = random.choice(list(G.nodes))
    
        def _hierarchy_pos(G, root, width=1., vert_gap = 0.2, vert_loc = 0, xcenter = 0.5, pos = None, parent = None):
            '''
            see hierarchy_pos docstring for most arguments
    
            pos: a dict saying where all nodes go if they have been assigned
            parent: parent of this branch. - only affects it if non-directed
    
            '''
    
            if pos is None:
                pos = {root:(xcenter,vert_loc)}
            else:
                pos[root] = (xcenter, vert_loc)
            children = list(G.neighbors(root))
            if not isinstance(G, nx.DiGraph) and parent is not None:
                children.remove(parent)  
            if len(children)!=0:
                dx = width/len(children) 
                nextx = xcenter - width/2 - dx/2
                for child in children:
                    nextx += dx
                    pos = _hierarchy_pos(G,child, width = dx, vert_gap = vert_gap, 
                                        vert_loc = vert_loc-vert_gap, xcenter=nextx,
                                        pos=pos, parent = root)
            return pos
    
    
        return _hierarchy_pos(G, root, width, vert_gap, vert_loc, xcenter)
    import matplotlib.pyplot as plt
    import networkx as nx
    import re
    
    
    
    
    
    def deversepile(p1,p2):
        while p1!=[]:
            p2.append(p1.pop())
        return p2
    
    def npiTree(L):
        """transforme l'expression NPI en un dictionnaire
        respectant les priorités de calcul
        Attention : la liste doit d'abord être mise à l'envers
        Utilise un algorithme recursif
        
        Params :
        --------
        L : list : expression NPI
        Returns : 
        ---------
        dictionnaire 
        
        exemple : 
        ---------
        [7,8,'-',6,'*',10,3,'+','*'] => {'*': ({'*': ({'-': (7, 8)}, 6)}, {'+': (10, 3)})}
        """
        #print('npiTree')
        if len(L)==1: # condition d'arret de l'appel recursif
            return L[0]
        fg = L.pop()
        fd = L.pop()
        pere = L.pop()
        #print('L : {}'.format(L))
        D={}
        if pere in ['*','+','-']: # données sous la forme : 'op',fg,fd
            D[pere]=fg,fd
            L.append(D)
        else : # données sous la forme : 'op0',('op1',fg1,fd1),fg0 => 'op0',fg0,fg0
            fg0 = fg
            fg1 = fd
            fd1 = pere
            pere1 = L.pop()
            D[pere1]=fg1,fd1
            L.append(D)
            L.append(fg0)
        #print('L : {}'.format(L))
        return npiTree(L)
    
    def makeTree(L_NPI):
        """transforme liste issue d'une NPI
        en un dictionnaire D
        La liste est d'abord mise à l'envers avec deversepile
        puis on appelle la fonction npiTree
        Params :
        --------
        L_NPI : liste
        Returns :
        ---------
        D : dictionnaire à transformer en graphe
        """
        D={}
        p1 = []
        deversepile(L_NPI,p1) 
        D = npiTree(p1)
        return D
    
    def decoupe(texte):
        """transforme la chaine de caractere correspondant au dictionnaire de l'arbre
        en une liste
        Params : 
        --------
        texte : string : la chaine à découper
        Returns :
        ---------
        texte_decoupe : la liste
        """
        texte_decoupe = list(re.findall('[{}():,*+-]|\w+',texte))
        return texte_decoupe
    
    def creerNodes(D):
        """modifie la liste ou chaque item (valeur numerique ou operateur) est remplacé par le no de noeud
        on créé aussi le noeud et son etiquette à partir de l'item
        Params : 
        --------
        D : dict : dictionnaire correspondant a l'arbre
        Returns :
        ---------
        eval(chaine) : dict : dictionnaire avec les no de noeud à la place des items
        """
        texte = decoupe(str(D))
        index = 1
        for i,c in enumerate(texte):
            if c[0] in ['*','+','-','0','1','2','3','4','5','6','7','8','9']:
                G.add_node(index,label=c)
                texte[i]=str(index)
                index+=1
        chaine = ''.join(texte)        
        return eval(chaine)
    
    
    def createEdges(D,key0=None):
        """créé une liste de tuple correspondant aux aretes de l'arbre
        l'algorithme utilise un parcours en profondeur recursif et ajoute la nouvelle arete
        à une liste LL
        Params : 
        --------
        D : dict : represente l'arbre à parcourir
        key0 : list ou int : le noeud parent
        Returns : 
        ---------
        LL[0] : contient un seul element : la liste de toutes le aretes
        tous les operateurs sont mis dans une liste de 1 élément. Il faudra sortir ces elements de la liste pour pouvoir 
        acceder au aretes seuls.
        """
        if not isinstance(D,dict):
            #print((key0,D))
            LL.append((key0,D))
            return LL[0]
        else:
            key = list(D.keys())
            #return key
            if key0!=None :
                #print((key0,key))
                LL.append((key0,key))
    
        createEdges(D[key[0]][0],key)
        createEdges(D[key[0]][1],key)
        
    
    
    
    def graphDict(D):
        """construction du graphe G au format de la lib networkx
        et affiche le graphe
        Params : 
        --------
        D : dict issu de la chaine NPI ou autre
        Returns :
        ---------
        G : graphe format networkx
        
        
        """
        Dnum =creerNodes(D)
        
    
        global LL # necessaire pour utiliser LL dans la fonction createEdges recursive
        LL=[]
        createEdges(Dnum)
    
        # arranger le format des elements de la liste d'aretes (suprimer le format list de certains elements)
        for i,c in enumerate(LL):
            c0 = c[0]
            c1 = c[1]
            if isinstance(c0,list):c0=c[0][0]
            if isinstance(c1,list):c1=c[1][0]
            c = c0,c1
            LL[i]=c
        #print(LL)   
    
        # Dict d'etiquette des noeuds
        liste = list(G.nodes(data='label'))
        labels_nodes = {}
        for noeud in liste:
            labels_nodes[noeud[0]]=noeud[1]
        
        #labels_nodes
        G.root = 1
        G.add_edges_from(LL)
        #print(list(G.edges()))
        pos1 = hierarchy_pos(G,G.root)    
        nx.draw(G, pos=pos1, labels=labels_nodes, with_labels=True, font_size=15, font_family='sans-serif', node_color='pink',alpha=0.9)
        plt.savefig('datas/NPI1.png')
        plt.show()
        return G
        
    # expression NPI
    L3 = [7,8,'-',6,'*',10,3,'+','*']
    
    D = makeTree(L3)
    G = nx.Graph()
    graphDict(D)

    <networkx.classes.graph.Graph at 0x7fc60ce94a10>
    
    list(G.nodes(data='label'))
    [(1, '*'),
     (2, '*'),
     (3, '-'),
     (4, '7'),
     (5, '8'),
     (6, '6'),
     (7, '+'),
     (8, '10'),
     (9, '3')]
    
    list(G.edges())
    [(1, 2), (1, 7), (2, 3), (2, 6), (3, 4), (3, 5), (7, 8), (7, 9)]
    
    D
    {'*': ({'*': ({'-': (7, 8)}, 6)}, {'+': (10, 3)})}
    
    Dnum =creerNodes(D)
    Dnum
    {1: ({2: ({3: (4, 5)}, 6)}, {7: (8, 9)})}
    

    Python Pandas

    Python : la librairie pandas

    notebook

    Le notebook présenté ici est à télécharger à l’adresse suivante :

    Binder Binder

    https://mybinder.org/v2/gh/tix06/notebook_datas.git/master

    Puis choisir : gestionBase_de_donnees_python.ipynb

    Exercez vous en suivant le tutoriel avec ce notebook.

    présentation

    Pandas fournit des structures de données puissantes et simples à utiliser, ainsi que les moyens d’opérer rapidement des opérations sur ces structures.

    Cette librairie va utiliser et faire des opérations sur un objet : le DataFrame Ce DataFrame est très similaire aux tables des bases de données relationnelles (type MySQL, PostgreSQL, etc.) que l’on manipule grâce au langage SQL.

    Ce notebook est inspiré du cours en ligne :

    https://openclassrooms.com/fr/courses/4452741-decouvrez-les-librairies-python-pour-la-data-science/5558996-passez-de-numpy-a-pandas

    représentation d’un tableau avec la librairie numpy

    numpy est une librairie utile pour de nombreuses applications mathématiques. numpy permet de manipuler facilement des tableaux. Un tableau est une liste contenant une nouvelle liste pour chacun de ses éléments. C’est une liste de listes.

    L’avantage de manipuler des tableaux, (array), plutôt que des listes, c’est de pouvoir réaliser des calculs sur les valeurs comme si la structure de donnée était une matrice.

    On va voir ici que cette représentation des données n’est pas la meilleure façon qu’il soit lorsqu’on l’utilise pour une collection (par exemple pour des informations).

    Prenons l’exemple de la programmation d’une salle de cinéma de type cinémathèque :

    On renseigne pour chacune des salles de ce cinéma (pour chacune des lignes), les valeurs : le titre du film (colonne 1), horaire (colonne 2), realisateur (col 3), année (col 4).

    #************************************#
    #****** un premier exemple **********#
    #******* de numpy à panda ***********#
    #************************************#
    
    import numpy as np
    tableau2D = [
        ['la rage aux poings', '18h00' , 'Eric le Hung', 1975], # film projeté dans la salle 1
        ['le million' , '15h00', 'René Clair', 1931], # dans la salle 2
        ['Rendez vous à Badenberg', '21h00'  , 'René Meurice', 1970], # dans la salle 3
        ['Le cercle rouge', '18h05', 'Jean-Pierre Melville', 1970], # dans la salle 4
    ]
    tableau_numpy = np.array(tableau2D)
    tableau_numpy
    # acceder à l'élément de rang 3 de la ligne 0 : 
    tableau_numpy[0,3]
    # acceder à TOUS les elements au rang 0 (donc la première colonne)
    tableau_numpy[:,0]

    C’est assez pratique certes, mais tableau_numpy[:, 0] quand cette colonne possède un descripteur (le nom du film), ce n’est pas très explicite.

    On va voir maintenant ce qu’apporte la représentation des données avec la librairie Pandas.

    représentation des données avec la librairie pandas

    Les données sont maintenant mises dans un DataFrame, et plus un tableau array.

    #***************************#
    #**** creer un DataFrame ***#
    #***************************#
    
    import pandas as pd  # on importe la librairie pandas
    tableau2D_df = pd.DataFrame(tableau2D) # on créé un DataFrame tableau2D_df à partir de l'array tableau2D
    tableau2D_df # et on l'affiche
    #******************************************#
    #********** passage du tableau np *********#
    #*** ainsi que les index et descripteurs **#
    #******************************************#
    
    tableau2D_df = pd.DataFrame(tableau_numpy,
                                    index = ['salle 1', 'salle 2', 'salle 3','salle 4'],
                                    columns = ['titre', 'horaire', 'realisateur', 'année'])
    tableau2D_df

    On peut maintenant réduire le tableau en une seule colonne, par exemple celle dont l’etiquette est horaire. On obtient alors une serie de données.

    # reduire le tableau (SELECT)
    tableau2D_df.horaire     # 1ere methode
    tableau2D_df['horaire'] # 2e methode

    Et si l’on a besoin d’une série comprenant 2 colonnes (ou plus), on utilise la syntaxe suivante :

    tableau2D_df[["titre","horaire"]]

    parcours et exploration des données

    On peut utiliser une boucle bornée qui, à chaque itération, donne :

    • l’indice
    • le contenu de la serie pour cet index (c’est à dire les valeurs et leur etiquette pour chacun des objets)

    On utilise la fonction iterrow associée au DataFrame :

    for index, valeurs in DataFrame.iterrows() : 
        ...
    # parcourir
    for ind_ligne, contenu_ligne in tableau2D_df.iterrows():
        print("Voici le film de la %s :" % ind_ligne)
        print(contenu_ligne)
        print("--------------------")

    accéder à un seul des objets de la collection

    Cette fois, plutôt que d’utiliser une boucle bornée et d’afficher TOUS les objets de la collection, on cherche à en afficher un seul.

    Cette fois le tri ne se fait pas selon une colonne, comme par exemple pour tableau2D_df['horaire'] mais par ligne, avec :

    `tableau_2D_df.loc[‘salle 3’] par exemple

    On aura ainsi le descriptif du film programmé dans cette salle.

    # acceder à un objet
    tableau2D_df.iloc[2] # Avec iloc(), indexation positionnelle
    tableau2D_df.loc["salle 3"] # Avec loc(), indexation par label

    Rechercher un film

    On va maintenant trier le tableau jusqu’à trouver l’élement correspondant.

    On cherche par exemple, dans quelle salle passe le film ‘Rendez vous à Badenberg’ : La colonne correspondant à cette valeur est celle dont l’etiquette est 'titre'. On écrit alors une expression logique, qui est évaluée pour chaque objet, et qui renvoie true si le titre correspond à celui recherché, et false sinon.

    La console affiche alors une serie de données :

    # trier (WHERE)
    tableau2D_df["titre"] == 'Rendez vous à Badenberg'

    Question : Ecrire l’instruction qui renverra true pour toutes les salles projettant un film réalisé en 1970. Testez votre instruction dans la cellule suivante.

    filtrer les données du tableau

    On va maintenant appliquer l’expression logique vue plus haut pour reduire le DataFrame aux seuls objets pour lesquels l’expression renvoie true. On dit que l’on a filtré les données.

    Premier exemple : filtrage du tableau pour ne conserver que la salle dans laquelle passe le film ‘Rendez vous à Badenberg’. On obtient alors un nouveau DataFrame, mais réduit.

    # masquer (WHERE)
    tableau_filtre = tableau2D_df[tableau2D_df["titre"] == 'Rendez vous à Badenberg']
    
    tableau_filtre # on affiche le tableau filtré

    Exemple 2 : on cherche le complémentaire de l’expression precedente : filtrer et renvoyer tous les films DIFFERENTS de *`Rendez vous à Badenberg’

    On utilise pour cela le symbole ~ (tild) devant l’expression dont on veut le complémentaire :

    tableau_comp = tableau2D_df[~(tableau2D_df["titre"] == 'Rendez vous à Badenberg')]
    tableau_comp

    Exemple 3 : filtrer par rapport aux dates de réalisation.

    Travail : ecrire l’instruction qui renvoie un nouveau DataFrame, mais uniquement avec des films réalisés en 1970

    trier le tableau

    On peut vouloir maintenant afficher les films dans l’ordre croissant de diffusion dans la journée. Pour des raisons de commodité, on modifie le format de l’heure de diffusion pour que le type de données soit float et non str. Par exemple : ‘18h00’ => 18.00

    tableau2D_df['horaire']=[18,15,20,18.1]
    tableau2D_df # on affiche le tableau

    On peut maintenant trier ce tableau selon l’horaire :

    tableau2D_df.sort_values(by ='horaire')

    Et voilà, vous n’avez plus aucun excuse pour rater une seance ;-)

    Traitement de données en csv

    Le fichier joint joueursNBA2020.csv est un extrait des joueurs professionnels de basket de NBA, pour la saison 2019-2020. On va utiliser la librairie pandas pour ouvrir puis explorer ce fichier.

    #******************************************#
    #******************** fichier csv *********#
    #******************************************#
    data = pd.read_csv("datas/joueursNBA2020.csv", sep=";")
    data

    Les données recupérées doivent souvent être remises en forme. Le tableau ci-dessus présente plusieurs problèmes qui doivent être traités avant de pouvoir exploiter les données :

    • Il y a des colonnes Unnamed qui ne servent à rien : elles seront à supprimer
    • Il y a plus de lignes que de joueurs. Ces lignes ont pour valeur NaN. Il faudra aussi les supprimer.
    • Le poids des joueurs, dans la colonne ‘poids’ est exprimé sous format str. Les valeurs sont écrites avec l’unité, kg. Il vaudra mieux les tranformer en type float, en retirant les caractères kg.
    #***************************************#
    # en pratique **************************#
    # selection des colonnes renseignées    #
    # et suppression des lignes NaN         #
    # avec .dropna()                        #
    #***************************************#
    tableau_reduit=data[['nom','equipe','poste','taille','poids','experience','pays']].dropna()
    #*************************************#
    # puis `cast` de la colonne poids     #
    # les valeurs sont de type str et     #
    # combinent des float avec kg         #
    # par exemple 89.8 kg                 #
    #*************************************#
    
    tableau_reduit['poids']=tableau_reduit['poids'].replace(to_replace ='kg', value = '', regex = True) 
    #************************************#
    # puis conversion du type            #
    # str vers float                     #
    # **********CAST ********************#
    #************************************#
    
    tableau_reduit['poids']=tableau_reduit['poids'].astype('float')
    tableau_reduit.loc[1]['poids']
    tableau_reduit

    Et voila, il n’y a plus qu’à explorer ce tableau de données. On peut par exemple :

    • filtrer le tableau pour n’afficher que les joueurs du poste ‘C’
    • filtrer les joueurs pour ne conserver que les joueurs de nationalité autre que americaine.
    • Trier les joueurs par taille, ou par poids

    Travail : Testez certaines des propositions faites ici…

    Liens

    Python graphes Networkx

    tracé de graphes avec Networkx

    Les scripts suivants permettent de choisir entre plusieurs types de configuration pour tracer un graphe avec Networkx, module Python.

    On pourra choisir de personaliser :

    • la couleur d’un noeud
    • l’etiquette des noeuds
    • l’étiquette des arêtes
    • le type de trait (plein ou en pointillés) des arêtes

    Déclaration du graphe

    import matplotlib.pyplot as plt
    import networkx as nx
    from numpy import array
    
    G = nx.Graph()
    # definition des noeuds
    G.add_node(0,label='A',col='pink')
    G.add_node(1,label='B',col='red')
    G.add_node(2,label='C',col='white')
    G.add_node(3,label='D',col='white')
    G.add_node(4,label='E',col='white')
    G.add_node(5,label='F',col='blue')
    # definition des aretes
    G.add_edge(0,1,weight=6,styl='dashed')
    G.add_edge(0,2,weight=5,styl='solid')
    G.add_edge(0,4,weight=1,styl='solid')
    G.add_edge(4,1,weight=5,styl='solid')
    G.add_edge(4,2,weight=1,styl='solid')
    G.add_edge(4,3,weight=3,styl='solid')
    G.add_edge(2,3,weight=8,styl='solid')
    G.add_edge(4,5,weight=6,styl='dashed')
    G.add_edge(3,5,weight=9,styl='solid')

    Exploration de la structure de données

    couleur des noeuds

    liste = list(G.nodes(data='col'))
    colorNodes = {}
    for noeud in liste:
        colorNodes[noeud[0]]=noeud[1]
    colorNodes
    {0: 'pink', 1: 'red', 2: 'white', 3: 'white', 4: 'white', 5: 'blue'}
    

    Pour les couleurs des noeuds, le format doit être en liste (de la taille du nombre de noeuds)

    colorList=[colorNodes[node] for node in colorNodes]
    colorList
    ['pink', 'red', 'white', 'white', 'white', 'blue']
    

    etiquettes de noeuds

    Pour les étiquettes de noeuds, le format doit être un dictionnaire.

    liste = list(G.nodes(data='label'))
    labels_nodes = {}
    for noeud in liste:
        labels_nodes[noeud[0]]=noeud[1]
    labels_nodes
    {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F'}
    

    ou bien :

    labels={node:label for node,label in G.nodes(data='label')}
    labels
    {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F'}
    

    labels des arêtes

    format : dictionnaire.

    Utile pour les applications de type algorithme de Dijkstra.

    Dans les autres cas, on pourra remplir la liste avec des guillemets : labels_edges = {edge:'' for edge in G.edges}

    labels_edges = {}
    labels_edges = {edge:G.edges[edge]['weight'] for edge in G.edges}
    #labels_edges = {edge:'' for edge in G.edges}
    labels_edges
    {(0, 1): 6,
     (0, 2): 5,
     (0, 4): 1,
     (1, 4): 5,
     (2, 4): 1,
     (2, 3): 8,
     (3, 4): 3,
     (3, 5): 9,
     (4, 5): 6}
    

    style du trait de l’arête

    format : liste

    liste = list(G.edges(data='styl'))
    edges_style = {}
    edges_style = {edge:G.edges[edge]['styl'] for edge in G.edges}
    edges_style
    {(0, 1): 'dashed',
     (0, 2): 'solid',
     (0, 4): 'solid',
     (1, 4): 'solid',
     (2, 4): 'solid',
     (2, 3): 'solid',
     (3, 4): 'solid',
     (3, 5): 'solid',
     (4, 5): 'dashed'}
    
    edg_style = [edges_style[node] for node in edges_style]
    edg_style
    ['dashed',
     'solid',
     'solid',
     'solid',
     'solid',
     'solid',
     'solid',
     'solid',
     'dashed']
    

    Tracé du graphe

    # positions for all nodes
    pos = nx.spring_layout(G)  
    
    # nodes
    nx.draw_networkx_nodes(G, pos, node_size=700,node_color=colorList,alpha=0.9)
                   
    # labels
    nx.draw_networkx_labels(G, pos, labels=labels_nodes, \
                            with_labels=True,font_size=20, \
                            font_color='black', \
                            font_family='sans-serif')
    
    # edges
    nx.draw_networkx_edges(G, pos,width=1)
    nx.draw_networkx_edge_labels(G, pos,width=1, edge_labels=labels_edges, style='dashed', font_color='red')
    
    
    
    plt.axis('off')
    plt.savefig('datas/fig1.png')
    plt.show()

    png png

    Utilisation d’une fonction multitracés

    fonction multigraphes

    def multigraphe(G,pos,name,edg=True,dashed=False):
        """
        tracé d'un graphe G à partir des options obligatoires : 
        label et col pour G.nodes : 
        G.add_node(0,label='A',col='pink')
        weight et styl pour G.edges :
        G.add_edge(0,1,weight=6,styl='dashed')
        
        Params :
        --------
        G : graphe
        
        pos : un dictionnaire qui contient les positions des différents noeuds
        obtenu à partir de : pos = nx.spring_layout(G)
              
        name : chaine de caractères finissant par l'extension .png par ex monfichier.png
        
        edg : option pour affichage des etiquettes sur les aretes
        par defaut edg vaut 'True' et l'etiquette EST affichée ('False' sinon)
        
        dashed : option pour tracer un graphe en solid + en pointillé avec l'option styl de G.edges
        """
        # liste de couleurs pour les noeuds
        liste = list(G.nodes(data='col'))
        colorNodes = {}
        for noeud in liste:
            colorNodes[noeud[0]]=noeud[1]
        colorList=[colorNodes[node] for node in colorNodes]
        # Dict d'etiquette des noeuds
        liste = list(G.nodes(data='label'))
        labels_nodes = {}
        for noeud in liste:
            labels_nodes[noeud[0]]=noeud[1]
        # Dict d'etiquette des aretes
        labels_edges = {}
        
        if edg : 
            labels_edges = {edge:G.edges[edge]['weight'] for edge in G.edges}
        else :
            labels_edges = {edge:'' for edge in G.edges}
        
        # Division en 2 des aretes : solid et dashed
        elarge = [(u, v) for (u, v, w) in G.edges(data=True) if w['styl'] == 'solid']
        esmall = [(u, v) for (u, v, w) in G.edges(data=True) if w['styl'] == 'dashed']
        
        # positions for all nodes : 
        # à mettre en parametre pour que chaque graphe ait la même disposition
        # pos = nx.spring_layout(G)  
    
        # nodes
        nx.draw_networkx_nodes(G, pos, node_size=700,node_color=colorList,alpha=0.9)
                   
        # labels
        nx.draw_networkx_labels(G, pos, labels=labels_nodes, \
                            with_labels=True,font_size=20, \
                            font_color='black', \
                            font_family='sans-serif')
    
        # edges
        if dashed:
            nx.draw_networkx_edges(G, pos, edgelist=elarge,width=3)
            nx.draw_networkx_edges(G, pos, edgelist=esmall,width=3, alpha=0.5, edge_color='b', style='dashed')
            
        else :
            nx.draw_networkx_edges(G, pos,width=1)
            nx.draw_networkx_edge_labels(G, pos,width=1, edge_labels=labels_edges, font_color='red')
    
        plt.axis('off')
        fichier='datas/'+ name
        plt.savefig(fichier)
        plt.show()

    Exemples

    pos = nx.spring_layout(G)
    pos
    {0: array([ 0.27974646, -0.89916229]),
     1: array([ 0.92773482, -0.4219083 ]),
     2: array([-0.56455338, -0.41641877]),
     3: array([-0.64887674,  0.39760485]),
     4: array([0.2899486 , 0.33988451]),
     5: array([-0.28399977,  1.        ])}
    
    multigraphe(G,pos,'fig1.png')

    png png

    multigraphe(G,pos,'fig2.png',False)

    png png

    multigraphe(G,pos,'fig3.png',False,True)

    png png

    G.add_node(1,label='B',col='blue')
    multigraphe(G,pos,'fig3.png',False,True)

    png png

    Python Labyrinthe

    Créer et resoudre un labyrinthe

    Les scripts suivants permettent de créer un labyrinthe de manière aléatoire, et d’exploiter la structure de données de ce labyrinthe. On pourra ainsi tester quelques algorithmes relatifs au parcours de ce labyrinthe. Les scripts en permettent une visualisation.

    Définitions des classes

    class Pile:
        def __init__(self):
            self.lst = [] 
        
        def empty(self):
            return self.lst == [] 
        
        def push(self, x):
            self.lst.append(x)
    
        def pop(self):
            if self.empty():
                raise ValueError("pile vide") 
            return self.lst.pop()
        
    def explorer(laby): 
        pile = Pile()
        pile.push((0, laby.q - 1)) 
        laby.tab[0][laby.q - 1].etat = False 
        while True:
            i, j = pile.pop()
            if i == laby.p - 1 and j == 0:
                break
            if j > 0 and laby.tab[i][j].S and laby.tab[i][j-1].etat:
                pile.push((i, j)) 
                pile.push((i, j-1)) 
                laby.tab[i][j-1].etat = False
            elif i < laby.p-1 and laby.tab[i][j].E and laby.tab[i+1][j].etat: 
                pile.push((i, j))
                pile.push((i+1, j))
                laby.tab[i+1][j].etat = False
            elif j < laby.q-1 and laby.tab[i][j].N and laby.tab[i][j+1].etat: 
                pile.push((i, j))
                pile.push((i, j+1))
                laby.tab[i][j+1].etat = False
            elif i > 0 and laby.tab[i][j].W and laby.tab[i-1][j].etat: 
                pile.push((i, j))
                pile.push((i-1, j))
                laby.tab[i-1][j].etat = False
        return pile.lst
        
    class Case:
        def __init__(self):
            self.N = False 
            self.W = False 
            self.S = False 
            self.E = False 
            self.etat = False
    
    class Labyrinthe:
        def __init__(self, p, q):
            self.p = p
            self.q = q
            self.tab = [[Case() for j in range(q)] for i in range(p)]
        
        def show(self):
            plt.plot([0, 0, self.p, self.p, 0], [0, self.q, self.q, 0, 0], linewidth=2) 
            for i in range(self.p-1):
                for j in range(self.q):
                    if not self.tab[i][j].E:
                        plt.plot([i+1, i+1], [j, j+1], 'b') 
            for j in range(self.q-1):
                for i in range(self.p):
                    if not self.tab[i][j].N:
                        plt.plot([i, i+1], [j+1, j+1], 'b') 
            
            plt.axis([-1, self.p+1, -1, self.q+1])
            plt.show()
            
        def solution(self):
            sol = explorer(self) 
            X, Y = [], []
            for (i, j) in sol:
                X.append(i+.5)
                Y.append(j+.5) 
            X.append(self.p-.5)
            Y.append(.5)
            plt.plot(X, Y, 'r', linewidth=2) 
            self.show()
    
    def creation(p, q):
        laby = Labyrinthe(p, q)
        pile = Pile()
        i, j = randint(p), randint(q) 
        pile.push((i, j)) 
        laby.tab[i][j].etat = True 
        while not pile.empty():
            i, j = pile.pop()
            v = []
            if j < q-1 and not laby.tab[i][j+1].etat:
                v.append('N')
            if i > 0 and not laby.tab[i-1][j].etat:
                v.append('W')
            if j > 0 and not laby.tab[i][j-1].etat:
                v.append('S')
            if i < p-1 and not laby.tab[i+1][j].etat:
                v.append('E') 
            if len(v) > 1:
                pile.push((i, j)) 
            if len(v) > 0:
                c = v[randint(len(v))] 
                if c == 'N':
                    laby.tab[i][j].N = True
                    laby.tab[i][j+1].S = True
                    laby.tab[i][j+1].etat = True 
                    pile.push((i, j+1))
                elif c == 'W':
                    laby.tab[i][j].W = True 
                    laby.tab[i-1][j].E = True 
                    laby.tab[i-1][j].etat = True 
                    pile.push((i-1, j))
                elif c == 'S':
                    laby.tab[i][j].S = True 
                    laby.tab[i][j-1].N = True 
                    laby.tab[i][j-1].etat = True 
                    pile.push((i, j-1))
                else:
                    laby.tab[i][j].E = True 
                    laby.tab[i+1][j].W = True 
                    laby.tab[i+1][j].etat = True 
                    pile.push((i+1, j))
        return laby

    Librairies

    from numpy.random import randint
    import matplotlib.pyplot as plt

    Un premier exemple

    laby = creation(6, 5) 
    laby.solution()

    png png

    Exploration de la structure de données

    def directions(laby,i,j):
        """les directions possibles pour la case courante
        i : int numero de ligne
        j : numero de la colonne
        
        retourne une liste (tuple) des points cardinaux possibles
        """
        L = []
        if laby.tab[j][i].N == True: L.append('N')
        if laby.tab[j][i].S == True: L.append('S')
        if laby.tab[j][i].E == True: L.append('E')
        if laby.tab[j][i].W == True: L.append('W')
        return tuple(L)

    Un labyrinthe est un tableau de cases laby.tab[j][i] ayant chacune pour propriétés : N,S,E,W

    • i : int numero de ligne
    • j : numero de la colonne

    Pour chacune de ces propriétés, par exemple laby.tab[j][i].Non renseigne une valeur True ou False

    • True : direction possible
    • False : impossible (mur)

    Créer un labyrinthe vide

    def labyrinthe(lines,col):
        """
        Params : 
        --------
        lines : int : nombre de lignes du labyrinthe
        col : int : nombre de colonnes
        
        Returns : 
        ---------
        tab2 : list : tuples de 1 à 4 éléments correspondants aux directions libres ('N', 'S', E', 'W')
        sortie : tracé du labyrinthe
        
        Variables :
        -----------
        p : nombre de colonnes (=largeur)
        q : nombre de lignes (=hauteur)
        """
        laby = creation(col, lines)
        tab2 = [[0]*laby.p for i in range(laby.q)]
        for i in range(laby.q):
            for j in range(laby.p):
                tab2[i][j] = directions(laby,i,j)
        Labyrinthe.show(laby)
        return tab2
    
    tab=labyrinthe(5,6)

    png png

    tab
    [[('N',), ('N', 'E'), ('E', 'W'), ('E', 'W'), ('E', 'W'), ('N', 'W')],
     [('N', 'S'), ('S', 'E'), ('N', 'W'), ('N', 'E'), ('W',), ('N', 'S')],
     [('N', 'S', 'E'), ('N', 'W'), ('N', 'S'), ('S', 'E'), ('E', 'W'), ('S', 'W')],
     [('N', 'S'), ('N', 'S'), ('S', 'E'), ('N', 'W'), ('N', 'E'), ('N', 'W')],
     [('S',), ('S', 'E'), ('E', 'W'), ('S', 'E', 'W'), ('S', 'W'), ('S',)]]
    

    Remarque : Les lignes sont mises dans l’ordre inverse du dessin du labyrinthe :

    Tracé du labyrinthe

    def mur(dir,i,j):
        """trace les murs des directions fermées
        dir est un tuple contenant les directions libres
        """
        line = 10
        if not('N' in dir[i][j]) : plt.plot([j,j+1],[i+1,i+1],'black',linewidth=line)
        if not('S' in dir[i][j]) : plt.plot([j,j+1],[i,i],'black',linewidth=line)
        if not('E' in dir[i][j]) : plt.plot([j+1,j+1],[i,i+1],'black',linewidth=line)
        if not('W' in dir[i][j]) : plt.plot([j,j],[i,i+1],'black',linewidth=line)
            
    def murs(tab):
        for i in range(len(tab)):
            for j in range(len(tab[i])):
                mur(tab,i,j)
        plt.plot([0, 0, len(tab[0]), len(tab[0]), 0], [0, len(tab), len(tab), 0, 0], 'blue',linewidth=10)
        plt.savefig('labyrinthe.png')

    On peut faire l’économie du tracé eventuel côté S et côté W grace au tracé des cases adjacentes.

    murs(tab)

    png png

    Parcours du labyrinthe

    fonctions utiles

    def nexto(c,direc):
        """retourne les coordonnées lors du deplacement
        selon la position actuelle et la direction
        Params :
        --------
        c : tuple (ligne,colonne) correspondant à (y,x) dans le plan cartesien
        direct : str : 'N', 'S', E', 'W'
        
        Returns :
        ---------
        tuple : (int,int) correspondant à (ligne,colonne)
        """
        i,j = c[0],c[1]
        if direc=='N' : return (i+1,j)
        if direc=='S' : return (i-1,j)
        if direc=='E' : return (i,j+1)
        if direc=='W' : return (i,j-1)
    
    def visited(c,L,couleur):
        """retourne la couleur du noeud de coord c et 
        de liste de directions possibles L selon celle de ses voisins
        
        Params : 
        --------
        c : tuple : (ligne,colonne) correspondant à (y,x) dans le plan cartesien
        L : list : tuples de 1 à 4 éléments correspondants aux directions libres ('N', 'S', E', 'W')
        couleur : List dimension 2 contenant des elements str
                  'white' si noeud non visité, 
                  'green' si le noeud est en cours de visite, 
                  'red' si tous les noeuds ont été visités autour de lui
        Returns : 
        ---------
        couleur : str : 'green' si le noeud est en cours de visite, 'red' si tous les noeuds 
                  ont été visités autour de lui
        """
        i,j = c[0],c[1]
        coul='red'
        for direc in L:
            coord = nexto(c,direc)
            if couleur[coord[0]][coord[1]]=='white':coul='green'
        print(c,coul)
        return coul
        

    une premiere idée : colorer les noeuds du chemin en vert

    def trouvercheminiter(start,end,tab):
        """recherche du chemin jusqu'à la sortie dans le labyrinthe
        en utilisant une technique qui s'apparente au parcours en profondeur
        avec backtracking
        on utilise une pile de noeuds visités
        
        Params :
        --------
        start : tuple de coord dans le labyrinthe
        end : tuple de coord dans le labyrinthe
        tab : liste de liste contenant pour chaque tuple de coordonnées un tuple de directions possibles
        
        Variables :
        -----------
        couleur : une table de la couleur du noeud ('red' si aucune nouvelle direction possible,
        'green' si en cours de visite, 'white' si jamais visité)
        
        Returns:
        --------
        la liste couleur
        
        """
        p = Pile()
        p.push(start)
        c = start
        couleur = [['white']*len(tab[0]) for i in range(len(tab))]
        
        # precaution pour eviter debordement
        compt = 0
        
        while (not p.empty()) and (not c == end) and compt<100:
            compt+=1
            c = p.pop()
            L = tab[c[0]][c[1]]
            couleur[c[0]][c[1]]=visited(c,L,couleur) # c est retiré de la pile et coloré en green ou red
            
                
            for direc in L:
                coord = nexto(c,direc)
                if couleur[coord[0]][coord[1]]=='white': # le noeud fils est coloré en blanc dans la direction D
                    for n in tab[coord[0]][coord[1]]:
                        p.push(coord) 
                        # alors on ajoute le noeud fils dans la direction D au sommet de la pile
                        # n fois afin de reconsidérer sa couleur à chaque fois que l'on depile
                    
                    
        return couleur
    trouvercheminiter((len(tab)-1,0),(0,len(tab[0])-1),tab)
    (4, 0) green
    (3, 0) green
    (2, 0) green
    (2, 1) green
    (3, 1) green
    (4, 1) green
    (4, 2) green
    (4, 3) green
    (4, 4) green
    (3, 4) green
    (3, 5) green
    (4, 5) red
    (3, 5) red
    (3, 4) red
    (4, 4) red
    (3, 3) green
    (3, 2) green
    (2, 2) green
    (1, 2) green
    (1, 1) green
    (0, 1) green
    (0, 2) green
    (0, 3) green
    (0, 4) green
    (0, 5) green
    
    
    
    
    
    [['white', 'green', 'green', 'green', 'green', 'green'],
     ['white', 'green', 'green', 'white', 'white', 'white'],
     ['green', 'green', 'green', 'white', 'white', 'white'],
     ['green', 'green', 'green', 'green', 'red', 'red'],
     ['green', 'green', 'green', 'green', 'red', 'red']]
    

    Une autre approche : mémoriser les étapes de la solution

    def solution(start,end,tab):
        """trouve la solution au labyrinthe et trace ce chemin
        La recherche du chemin jusqu'à la sortie dans le labyrinthe
        utilise une technique qui s'apparente au parcours en profondeur
        avec backtracking
        on utilise une pile de noeuds visités
        
        Params :
        --------
        start : tuple de coord dans le labyrinthe
        end : tuple de coord dans le labyrinthe
        tab : liste de liste contenant pour chaque tuple de coordonnées un tuple de directions possibles
        
        
        
        Returns:
        --------
        la liste couleur
        
        Variables : 
        -----------
        couleur : une table de la couleur du noeud ('red' si aucune nouvelle direction possible,
        'green' si en cours de visite, 'white' si jamais visité)
        
        p : Pile() utile pour la recherche du parcours
        pchemin : Pile() utile pour memoriser ce chemin
        """
        p = Pile()
        pchemin = Pile()
        p.push(start)
        c = start
        couleur = [['white']*len(tab[0]) for i in range(len(tab))]
        
        
        while (not p.empty()) and (not c == end):
            c = p.pop()
            pchemin.push(c)
            L = tab[c[0]][c[1]]
            couleur[c[0]][c[1]]=visited(c,L,couleur) # c est retiré de la pile et coloré en green ou red
            
            noeud = pchemin.pop()
            
            while couleur[noeud[0]][noeud[1]] == 'red':
                noeud = pchemin.pop() # il peut y avoir plusieurs fois le noeud successivement dans la pile
            
            pchemin.push(noeud) # on remet le dernier noeud retiré non rouge
                
            for direc in L:
                coord = nexto(c,direc)
                if couleur[coord[0]][coord[1]]=='white': # le noeud fils est coloré en blanc dans la direction D
                    #for n in tab[coord[0]][coord[1]]:
                        p.push(c)
                        p.push(coord) 
                        # alors on ajoute le noeud fils dans la direction D au sommet de la pile
                        # ainsi que son noeud parent
                    
                    
        return pchemin.lst
    
    def murSolution(tab,L):
        xList=[]
        yList=[]
        for i in range(len(tab)):
            for j in range(len(tab[i])):
                mur(tab,i,j)
        plt.plot([0, 0, len(tab[0]), len(tab[0]), 0], [0, len(tab), len(tab), 0, 0], 'blue',linewidth=10)
        for n in range(len(L)):
            yList.append(L[n][0]+0.5)
            xList.append(L[n][1]+0.5)
        plt.plot(xList,yList,'red',linewidth=2)
                
    L= solution((len(tab)-1,0),(0,len(tab[0])-1),tab)
    L
    (4, 0) green
    (3, 0) green
    (2, 0) green
    (2, 1) green
    (3, 1) green
    (4, 1) green
    (4, 2) green
    (4, 3) green
    (4, 4) green
    (3, 4) green
    (3, 5) green
    (4, 5) red
    (3, 5) red
    (3, 4) red
    (4, 4) red
    (4, 3) green
    (3, 3) green
    (3, 2) green
    (2, 2) green
    (1, 2) green
    (1, 1) green
    (0, 1) green
    (0, 2) green
    (0, 3) green
    (0, 4) green
    (0, 5) green
    
    
    
    
    
    [(4, 0),
     (3, 0),
     (2, 0),
     (2, 1),
     (3, 1),
     (4, 1),
     (4, 2),
     (4, 3),
     (4, 3),
     (3, 3),
     (3, 2),
     (2, 2),
     (1, 2),
     (1, 1),
     (0, 1),
     (0, 2),
     (0, 3),
     (0, 4),
     (0, 5)]
    
    murSolution(tab,L)

    png png

    mémoriser TOUTES les étapes du parcours

    def parcours(start,end,tab):
        """trouve la solution au labyrinthe et trace ce chemin
        p : Pile() utile pour la recherche du parcours
        pchemin : Pile() utile pour memoriser tout le chemin
        on insère dans le chemin toutes les arêtes empruntées : 
        pour le chemin entre c1 et c2, on insère c1 puis c2
        """
        p = Pile()
        pchemin = Pile()
        p.push(start)
        c = start
        couleur = [['white']*len(tab[0]) for i in range(len(tab))]
        
        
        while (not p.empty()) and (not c == end):
            c = p.pop()
            pchemin.push(c) # chaque fois que l'on depile, on rempile dans pchemin
            L = tab[c[0]][c[1]]
            couleur[c[0]][c[1]]=visited(c,L,couleur) # c est retiré de la pile et coloré en green ou red
            
            
                
            for direc in L:
                coord = nexto(c,direc)
                if couleur[coord[0]][coord[1]]=='white': # le noeud fils est coloré en blanc dans la direction D
                        p.push(c) # on remet le noeud parent afin de reconsidérer sa couleur à chaque fois que l'on depile
                        # et le chemin arriere CONTINU pour le tracé
                        p.push(coord) 
                        # alors on ajoute le noeud fils dans la direction D au sommet de la pile
                        
        return pchemin.lst
    L = parcours((len(tab)-1,0),(0,len(tab[0])-1),tab)
    L
    (4, 0) green
    (3, 0) green
    (2, 0) green
    (2, 1) green
    (3, 1) green
    (4, 1) green
    (4, 2) green
    (4, 3) green
    (4, 4) green
    (3, 4) green
    (3, 5) green
    (4, 5) red
    (3, 5) red
    (3, 4) red
    (4, 4) red
    (4, 3) green
    (3, 3) green
    (3, 2) green
    (2, 2) green
    (1, 2) green
    (1, 1) green
    (0, 1) green
    (0, 2) green
    (0, 3) green
    (0, 4) green
    (0, 5) green
    
    
    
    
    
    [(4, 0),
     (3, 0),
     (2, 0),
     (2, 1),
     (3, 1),
     (4, 1),
     (4, 2),
     (4, 3),
     (4, 4),
     (3, 4),
     (3, 5),
     (4, 5),
     (3, 5),
     (3, 4),
     (4, 4),
     (4, 3),
     (3, 3),
     (3, 2),
     (2, 2),
     (1, 2),
     (1, 1),
     (0, 1),
     (0, 2),
     (0, 3),
     (0, 4),
     (0, 5)]
    
    murSolution(tab,L)

    png png

    Python turtle Labyrinthe

    Utiliser le module turtle

    Le script suivant présente les classes et fonctions utiles pour :

    • tracer un labyrinthe complet
    • parcourir le labyrinthe selon une méthode de parcours en profondeur
    • tracer ce parcours animé avec turtle

    Utilisation :

    tab=labyrinthe(5,6)
    
    L = parcours((len(tab)-1,0),(0,len(tab[0])-1),tab)
    
    afficheTurtle(tab,L)

    librairies

    from numpy.random import randint
    import matplotlib.pyplot as plt
    import turtle

    classes utiles

    class Pile:
        def __init__(self):
            self.lst = [] 
        
        def empty(self):
            return self.lst == [] 
        
        def push(self, x):
            self.lst.append(x)
    
        def pop(self):
            if self.empty():
                raise ValueError("pile vide") 
            return self.lst.pop()
    """    
    def explorer(laby): 
        pile = Pile()
        pile.push((0, laby.q - 1)) 
        laby.tab[0][laby.q - 1].etat = False 
        while True:
            i, j = pile.pop()
            if i == laby.p - 1 and j == 0:
                break
            if j > 0 and laby.tab[i][j].S and laby.tab[i][j-1].etat:
                pile.push((i, j)) 
                pile.push((i, j-1)) 
                laby.tab[i][j-1].etat = False
            elif i < laby.p-1 and laby.tab[i][j].E and laby.tab[i+1][j].etat: 
                pile.push((i, j))
                pile.push((i+1, j))
                laby.tab[i+1][j].etat = False
            elif j < laby.q-1 and laby.tab[i][j].N and laby.tab[i][j+1].etat: 
                pile.push((i, j))
                pile.push((i, j+1))
                laby.tab[i][j+1].etat = False
            elif i > 0 and laby.tab[i][j].W and laby.tab[i-1][j].etat: 
                pile.push((i, j))
                pile.push((i-1, j))
                laby.tab[i-1][j].etat = False
        return pile.lst
    """    
    class Case:
        def __init__(self):
            self.N = False 
            self.W = False 
            self.S = False 
            self.E = False 
            self.etat = False
    
    class Labyrinthe:
        def __init__(self, p, q):
            self.p = p
            self.q = q
            self.tab = [[Case() for j in range(q)] for i in range(p)]
        
        def show(self):
            plt.plot([0, 0, self.p, self.p, 0], [0, self.q, self.q, 0, 0], linewidth=2) 
            for i in range(self.p-1):
                for j in range(self.q):
                    if not self.tab[i][j].E:
                        plt.plot([i+1, i+1], [j, j+1], 'b') 
            for j in range(self.q-1):
                for i in range(self.p):
                    if not self.tab[i][j].N:
                        plt.plot([i, i+1], [j+1, j+1], 'b') 
            
            plt.axis([-1, self.p+1, -1, self.q+1])
            plt.show()
        """
        def solution(self):
            sol = explorer(self) 
            X, Y = [], []
            for (i, j) in sol:
                X.append(i+.5)
                Y.append(j+.5) 
            X.append(self.p-.5)
            Y.append(.5)
            plt.plot(X, Y, 'r', linewidth=2) 
            self.show()
        """
    def creation(p, q):
        laby = Labyrinthe(p, q)
        pile = Pile()
        i, j = randint(p), randint(q) 
        pile.push((i, j)) 
        laby.tab[i][j].etat = True 
        while not pile.empty():
            i, j = pile.pop()
            v = []
            if j < q-1 and not laby.tab[i][j+1].etat:
                v.append('N')
            if i > 0 and not laby.tab[i-1][j].etat:
                v.append('W')
            if j > 0 and not laby.tab[i][j-1].etat:
                v.append('S')
            if i < p-1 and not laby.tab[i+1][j].etat:
                v.append('E') 
            if len(v) > 1:
                pile.push((i, j)) 
            if len(v) > 0:
                c = v[randint(len(v))] 
                if c == 'N':
                    laby.tab[i][j].N = True
                    laby.tab[i][j+1].S = True
                    laby.tab[i][j+1].etat = True 
                    pile.push((i, j+1))
                elif c == 'W':
                    laby.tab[i][j].W = True 
                    laby.tab[i-1][j].E = True 
                    laby.tab[i-1][j].etat = True 
                    pile.push((i-1, j))
                elif c == 'S':
                    laby.tab[i][j].S = True 
                    laby.tab[i][j-1].N = True 
                    laby.tab[i][j-1].etat = True 
                    pile.push((i, j-1))
                else:
                    laby.tab[i][j].E = True 
                    laby.tab[i+1][j].W = True 
                    laby.tab[i+1][j].etat = True 
                    pile.push((i+1, j))
        return laby

    autres definitions utiles

    def directions(laby,i,j):
        """les directions possibles pour la case courante
        i : int numero de ligne
        j : numero de la colonne
        
        retourne une liste (tuple) des points cardinaux possibles
        """
        L = []
        if laby.tab[j][i].N == True: L.append('N')
        if laby.tab[j][i].S == True: L.append('S')
        if laby.tab[j][i].E == True: L.append('E')
        if laby.tab[j][i].W == True: L.append('W')
        return tuple(L)
    
    def labyrinthe(lines,col):
        """
        Params : 
        --------
        lines : int : nombre de lignes du labyrinthe
        col : int : nombre de colonnes
        
        Returns : 
        ---------
        tab2 : list : tuples de 1 à 4 éléments correspondants aux directions libres ('N', 'S', E', 'W')
        sortie : tracé du labyrinthe
        
        Variables :
        -----------
        p : nombre de colonnes (=largeur)
        q : nombre de lignes (=hauteur)
        """
        laby = creation(col, lines)
        tab2 = [[0]*laby.p for i in range(laby.q)]
        for i in range(laby.q):
            for j in range(laby.p):
                tab2[i][j] = directions(laby,i,j)
        Labyrinthe.show(laby)
        return tab2
    
    def nexto(c,direc):
        """retourne les coordonnées lors du deplacement
        selon la position actuelle et la direction
        Params :
        --------
        c : tuple (ligne,colonne) correspondant à (y,x) dans le plan cartesien
        direct : str : 'N', 'S', E', 'W'
        
        Returns :
        ---------
        tuple : (int,int) correspondant à (ligne,colonne)
        """
        i,j = c[0],c[1]
        if direc=='N' : return (i+1,j)
        if direc=='S' : return (i-1,j)
        if direc=='E' : return (i,j+1)
        if direc=='W' : return (i,j-1)
    
    def visited(c,L,couleur):
        """retourne la couleur du noeud de coord c et 
        de liste de directions possibles L selon celle de ses voisins
        
        Params : 
        --------
        c : tuple : (ligne,colonne) correspondant à (y,x) dans le plan cartesien
        L : list : tuples de 1 à 4 éléments correspondants aux directions libres ('N', 'S', E', 'W')
        couleur : List dimension 2 contenant des elements str
                  'white' si noeud non visité, 
                  'green' si le noeud est en cours de visite, 
                  'red' si tous les noeuds ont été visités autour de lui
        Returns : 
        ---------
        couleur : str : 'green' si le noeud est en cours de visite, 'red' si tous les noeuds 
                  ont été visités autour de lui
        """
        i,j = c[0],c[1]
        coul='red'
        for direc in L:
            coord = nexto(c,direc)
            if couleur[coord[0]][coord[1]]=='white':coul='green'
        #print(c,coul)
        return coul
        
    def parcours(start,end,tab):
        """trouve la solution au labyrinthe et trace ce chemin
        p : Pile() utile pour la recherche du parcours
        pchemin : Pile() utile pour memoriser tout le chemin
        on insère dans le chemin toutes les arêtes empruntées : 
        pour le chemin entre c1 et c2, on insère c1 puis c2
        """
        p = Pile()
        pchemin = Pile()
        p.push(start)
        c = start
        couleur = [['white']*len(tab[0]) for i in range(len(tab))]
        
        
        while (not p.empty()) and (not c == end):
            c = p.pop()
            pchemin.push(c) # chaque fois que l'on depile, on rempile dans pchemin
            L = tab[c[0]][c[1]]
            couleur[c[0]][c[1]]=visited(c,L,couleur) # c est retiré de la pile et coloré en green ou red
            
            
                
            for direc in L:
                coord = nexto(c,direc)
                if couleur[coord[0]][coord[1]]=='white': # le noeud fils est coloré en blanc dans la direction D
                        p.push(c) # on remet le noeud parent afin de reconsidérer sa couleur à chaque fois que l'on depile
                        # et le chemin arriere CONTINU pour le tracé
                        p.push(coord) 
                        # alors on ajoute le noeud fils dans la direction D au sommet de la pile
                        
        return pchemin.lst

    fonctions particulières au module turtle

    def turtleWall(dir,i,j):
        """trace les murs des directions fermées
        dir est un tuple contenant les directions libres
        """
        larg = len(tab[0])
        haut = len(tab)
    
        fenX = 600
        fenY = fenX*haut/larg
    
        scaleX = (fenX-20)/larg
        scaleY = (fenY-20)/haut
    
        x0=-fenX/2+10
        y0=-fenY/2+10
        
        if not('N' in dir[i][j]) :
            turtle.penup()
            turtle.setpos(x0+j*scaleX,y0+(i+1)*scaleY)
            turtle.setheading(0)
            turtle.pendown()
            turtle.forward(scaleX)
        if not('S' in dir[i][j]) : 
            turtle.penup()
            turtle.setpos(x0+j*scaleX,y0+i*scaleY)
            turtle.setheading(0)
            turtle.pendown()
            turtle.forward(scaleX)
        if not('E' in dir[i][j]) : 
            turtle.penup()
            turtle.setpos(x0+(j+1)*scaleX,y0+i*scaleY)
            turtle.setheading(90)
            turtle.pendown()
            turtle.forward(scaleY)
        if not('W' in dir[i][j]) : 
            turtle.penup()
            turtle.setpos(x0+j*scaleX,y0+i*scaleY)
            turtle.setheading(90)
            turtle.pendown()
            turtle.forward(scaleY)
            
    def turtleLab(tab):
        for i in range(len(tab)):
            for j in range(len(tab[i])):
                turtleWall(tab,i,j)
        #plt.plot([0, 0, len(tab[0]), len(tab[0]), 0], [0, len(tab), len(tab), 0, 0], 'blue',linewidth=10)
        #plt.savefig('laby.png')
    
    def turtlePath(tab,L):
        """tracé du parcours dans le labyrinthe à l'aide de la tortue
        Params:
        -------
        tab : Liste de liste contenant des str : 'N','S','W','E' = le labyrinthe
        L : Liste de tuples correspondant aux cases visitées
        sortie : 
        --------
        le dessin du parcours animé
        """
        larg = len(tab[0])
        haut = len(tab)
    
        fenX = 600
        fenY = fenX*haut/larg
    
        scaleX = (fenX-20)/larg
        scaleY = (fenY-20)/haut
    
        x0=-fenX/2+10
        y0=-fenY/2+10
        
        turtle.penup()
        turtle.pencolor("red")
        turtle.setpos(x0+scaleX/2,y0+scaleY*4+scaleY/2) # depart
        turtle.showturtle()
        turtle.pendown()
        start = L[0]
        for c in L[1:]:
            #angle = 90*(c[0]-start[0]) # si deplacement uniquement vertical
            if c[0]!=start[0] : 
                depl = scaleY # vertical
                angle = 90*(c[0]-start[0])
            else : 
                depl = scaleX # horizontal
                angle = 90 - 90*(c[1]-start[1])
            if c[1]<start[1] : angle = 180 # deplacement à gauche
            turtle.setheading(angle)
            turtle.forward(depl)
            start = c

    fonction principale pour affichage de l’animation turtle

    def afficheTurtle(tab,L):
        larg = len(tab[0])
        haut = len(tab)
    
        fenX = 600
        fenY = fenX*haut/larg
    
        scaleX = (fenX-20)/larg
        scaleY = (fenY-20)/haut
        turtle.setup(fenX, fenY)  #Largeur : 600px, Hauteur : 400px
    
        turtle.bgcolor((0.9, 0.9, 0.9))
        turtle.hideturtle()
        turtle.penup()
        turtle.setpos(-fenX/2+10,-fenY/2+10)
        turtle.setheading(90)
    
        turtle.pendown()
        #turtle.speed(0)
        turtle.tracer(False) # tracer le Laby avant de demarrer l'animation avec la tortue
        turtle.pensize(2)
    
        turtle.forward(fenY-20)
        turtle.left(-90)
        turtle.forward(fenX-20)
        turtle.left(-90)
        turtle.forward(fenY-20)
        turtle.left(-90)
        turtle.forward(fenX-20)
        turtle.left(-90)
    
        turtleLab(tab)
    
        turtle.tracer(True) # fin du tracé du Laby
    
        turtle.speed(6)
    
        turtlePath(tab,L) # animation du parcours par la tortue
    
    
    
    
        #calling for the mainloop()
        turtle.mainloop()

    Programme

    tab=labyrinthe(5,6)
    
    L = parcours((len(tab)-1,0),(0,len(tab[0])-1),tab)
    
    afficheTurtle(tab,L)

    gif gif

    Modèle prédictif

    Principe

    Un modèle prédictif ne peut être établi qu’à partir d’une étude prealable de données. Une étude statistique permet de repérer si certains paramètres sont liés entre eux. Alors, si ces données étaient suffisamment nombreuses et précises, il est possible d’établir des lois mathematiques sur ces données. Une manière de représenter ce lien entre paramètres est d’établir une loi de regression linéaire, par exemple.

    A partir de nouvelles données, on peut alors, grâce à une simulation, prédire le comportement futur du nouvel objet. A condition que celui-ci fasse partie de la même famille d’objets que ceux qui ont permis d’établir le modèle.

    Un exemple de prédiction

    Aller sur la page Exoplanet.eu.

    Cliquer sur le lien online tool here au milieu de la page de description.

    La page suivante permet de simuler le comportement d’une planete dans son système stellaire. Il suffit de choisir certains paramètres comme par exemple:

    • la distance de la planète à son étoile
    • la courbure de sa trajectoire
    • sa période de revolution
    • le type d’étoile
    • sa couverture oceanique
    • …
    choix des paramètres de la planète
    Choix des paramètres de la planète

    La simulation demarre une fois que l’on clique sur le bouton START.

    modeles predictifs
    Simulation du comportement de la planète

    Le logiciel utilise alors un modèle prédictif, établi à partir de l’observation de nombreuses autres planètes ou corps celestes, pour déterminer la temperature de surface de l’astre au cours du temps, sa trajectoire, etc…

    A tester vous même: faire un test à l’aide du simulateur.

    Python unittest

    Utilisation du module unittest avec le calcul des nombres premiers

    avant de démarrer cette partie, il est recommandé de consulter :

    Définition: Un test unitaire est un test réalisé sur une portion du programme, typiquement sur une fonction.

    Le module unittest offre des outils de test de code, comme la classe TestCase. Le but est des vérifier que votre code génère des résultats corrects, conformes au attentes.

    En pratique: test du calcul de la liste de nombres premiers

    • Ouvrir l’editeur Trinket.io editeur python

    • Dans le fichier main.py, on mettra les fonctions de test. Ce sera le fichier main que l’on executera.

    • Créer un deuxieme fichier python, que l’on renommera prime.py. Celui-ci contiendra les fonctions à tester.

    modules nombres premiers et test unitaire
    modules associés au programme de test

    Contenu du fichier prime.py

    def prem1(n) :
        """Renvoie True si l’entier est premier et False sinon"""
        # script à completer
        return True
        
    
    def liste_prime1(N):
        """etablit une liste de nombres premiers de 0 a N"""
        L=[]
        for j in range(N+1):
            if prem1(j):
                L.append(j)
        return L

    Contenu du fichier main.py

    import unittest
    import prime 
    
    class PrimeTestCase(unittest.TestCase):
      """Test pour prime.py"""
      
      def test_prime(self):
        """compare avec liste de nombres premiers"""
        
        wiki =[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
        
        premiers = prime.liste_prime1(100)
        self.assertEqual(premiers,wiki)
        
    if __name__=='__main__':
      unittest.main()

    Dans le fichier à executer, main.py: On commence par importer le module unittest ainsi que le module prime qui contient les fonctions à tester.

    Les noms des classes de test se terminent généralement par TestCase (scenario de test). La classe créée pour le test, PrimeTestCase doit être une classe enfant de unittest.TestCase.

    Chaque test à créer est une méthode. Toute méthode dont le nom commence par test_ est exécutée lors du test. La méthode test_prime1 appelle donc la fonction liste_prime du module prime avec la valeur 100, puis vérifie que son résultat est conforme à la liste wiki, grâce à un test d’assertion assertEqual.

    Ici, la fonction prem1 n’est pas bien renseignée, et le test échoue. On peut remonter jusqu’à l’erreur dans le Traceback qui est affiché en console.

    # extrait du Traceback
    Tests failed in  PrimeTestCase.test_prime  
    Ran 1 tests, passed: 0 failed: 1

    A vous de jouer

    Compléter la fonction prem1 afin que celle-ci calcule bien les nombres premiers entre 0 et 100. Puis lancer le test à l’aide de la classe PrimeTestCase.

    • Le test se déroule t-il correctement?
    • Que se passe t-il si on modifie la valeur 100 dans l’instruction premiers = prime.liste_prime1(100) de la méthode test_prime de la classe PrimeTestCase? Conclure

    La suite du TP: La spirale d’Ulam

    Lien vers la suite du TP

    Securite informatique

    Chiffrements symétriques

    Vocabulaire

    • Chiffrer: transformer les caractères d’un texte pour le rendre incompréhensible, sauf pour celui qui possède la clé de chiffrement.
    • Déchiffrer: transformer le texte chiffré en texte clair à l’aide de la clé de chiffrement
    • Décrypter: transformer le texte chiffré en texte clair sans posséder la clé.
    • Cryptologie: science du secret: possède deux branches
      • cryptographie: étude de l’art du chiffrement
      • cryptanalyse: analyse des méthodes de chiffrement pour les casser (décrypter)

    à quoi sert le chiffrement?

    Le chiffrement a pour but de protéger nos données, nos communications, mais aussi de signer nos messages et de s’assurer que l’on communique bien avec la bonne personne:

    • Authentification: L’authentification est la procédure qui consiste, pour un système informatique, à vérifier l’identité d’une entité (personne, programme, machine).
    • L’intégrité des données désigne le fait que les données ne soient pas modifiées au cours d’une communication ou de leur stockage.
      Ainsi, si vous envoyez un texte chiffré sur un canal non sécurisé, le texte chiffré pourra être intercepté et altéré par un attaquant avant d’atteindre son destinataire. Pour contrôler cette intégrité, on associe au message une valeur de contrôle.
    • La confidentialité: Le chiffrement permet de protéger la confidentialité de vos données à l’aide d’une clé secrète.

    Le chiffrement par décalage, ou chiffre de Caesar

    Le chiffre de César fonctionne par décalage des lettres de l’alphabet.

    Chiffrement par décalage - wikipedia

    Cet algorithme de chiffrement utilise une fonction périodique pour transformer les rangs de chaque lettre:

    a b c d e f g h i j k l m n o p q r s t u v w x y z
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

    Compléter l’algorithme du chiffrement de César. On suppose qu’il existe une clé c correspondant au décalage utilisé. Le message clair est m et le message chiffré est m_chiffre

    Pour chaque lettre l du message m:
      l_chiffre = ...
      m_chiffre = ...

    Facilité du décryptage

    Décryptage par FORCE BRUTE: Combien y-a-t-il de clés possibles à essayer pour celui qui réalise le décryptage? Conclure.

    Un chiffrement par substitution monoalphabetique

    Le chiffrement par substitution monoalphabetique: Chaque lettre de l’alphabet est transformée en une nouvelle lettre. Et cette nouvelle lettre est unique (sinon, il y aurait ambigüité, et le déchiffrement ne serait pas possible). Ici, la fonction utilisée pour le chiffrement de César, est un simple décalage:

    $$x \rightarrow x + cle$$

    Mais il peut y avoir d’autres fonctions plus complexes utilisées. Voire, même aucune fonction, mais une table de correspondance entre lettre en clair et symbole chiffré. La clé aurait alors la longueur de l’alphabet.

    Le chiffrement par monosubstitution a été également utilisé par différentes méthodes utilisant une table.

    <a href="

    Carré de Polybe - le mot « bonjour » est ainsi chiffré par le carré de Polybe :12 34 33 24 34 45 42 - wikipedia

    Vous trouvez cette méthode de chiffrement trop simpliste? Regardez alors sa déclinaison avec le chiffrement de Playfair, qui associe une clé à la table de Polybe, et rajoute du pseudo aléatoire dans le chiffrement:

    VIDEO: chiffrement de Playfair - youtube - Astuces et tutoriels

    Decryptage par analyse fréquentielle

    Le code issu du carré de Polybe a été utilisé par les prisonniers, qui transmettaient leur message en tapant sur les murs (Tap code).

    Le problème avec ce type de chiffrement monoalphabetique, est qu’il est possible de repérer comment sont transformées certaines lettres à partir de l’analyse fréquentielle du message chiffré.

    On peut alors utiliser la frequence des lettres pour dechiffrer et comparer avec la frequence moyenne dans une langue. (200 caracteres suffisent). Il y a aussi tout un tas de statistique, comme les lettres uniques, doubles lettres, finales, etc… C’est un marqueur suffisant pour savoir comment le code est fait.

    frequence des lettres en français, calculée sur la lecture de plusieurs ouvrages classiques (10 millions de caracteres)

    Ce n’est pas le cas du chiffrement de Playfair, car celui-ci utilise une methode de substitution d’un groupe de lettres: c’est une substitution polyalphabetique.

    Une amélioration: Substitution polyalphabétique

    L’analyse des fréquences est moins pertinente lorsque le message a été chiffré avec un chiffrement polyalphabétique (qui tend à rendre aléatoire la fréquence des lettres).

    Polyalphabetique: Se dit d’un chiffre où un groupe de n lettres est codé par un groupe de n symboles. Le chiffrement Playfair, vu plus haut s’apparente à une substitution polyalphabetique, puisqu’il substitue des digrammes (groupes de 2 lettres) dans le texte d’origine.

    L’exemple suivant montre une polysubstitution simple avec une clé de longueur 3 qui va décaler les lettres de l’alphabet :

    On définit la clé ‘123’ qui indique que le premier caractère sera décalé d’une position, le second de 2 et le troisième de 3 positions, etc.

    Le mot : WIKIPEDIA donne donc dans ce cas XKNJRHEKD.

    Mais si on chiffre le mot : AAAAAAAAA cela donnera BCDBCDBCD. La lettre A ne donne pas toujours la même correspondance chiffrée. Mais on peut analyser la périodicité et en déduire la longueur de la clé. La connaissance de la longueur de la clé est essentielle pour pouvoir pratiquer l’analyse frequentielle.

    La machine Enigma utilisait ce principe de codage.

    Enigma est une machine électromécanique portative servant au chiffrement et au déchiffrement de l'information. - wikipedia

    La machine utilise des rotors qui sont mis en position selon une clé. L’alphabet est chiffré selon la position initiale de ces rotors. Ceux-ci se décalent lors de l’utilisation. Ce qui modifie l’alphabet chiffré et augmente sérieusement la complexité.

    Déchiffrer se fait avec la même machine, à condition d’utiliser la même clé.

    Son utilisation la plus célèbre fut celle faite par l’Allemagne nazie, avant et pendant la Seconde Guerre mondiale, la machine étant réputée inviolable selon ses concepteurs.

    Le principe de la machine Enigma était connu. Le concepteur savait à l’avance que certains modèles pourraient être volés par les alliés. Ce qui fit son efficacité, c’est le nombre immense de combinaisons possibles pour les réglages initiaux de la machine et le choix de la clef brute du message.

    Les cryptanalystes britanniques, dont Alan Turing, purent continuer les travaux du mathématicien polonais Marian Rejewski. Ils furent, dans des circonstances favorables, capables de decrypter les messages Enigma, ce qui donna un avantage certain aux alliés pendant la guerre.

    Points communs des chiffrements symétriques

    Ces algorithmes fonctionnent selon:

    • Entrée
    • repetition n fois de substitutions et permutations. Utilise une clé unique pour chiffrer et dechiffrer.
    • Sortie

    Fondamentaux de la cryptographie moderne

    Les principes de Kerckhoff (6 principes, 3 restent aujourd’hui preponderants malgrès la difference de technologie)

    1. Materiellement sûr: Si on a un temps infini, on finira par trouver le code, mais le message n’aura plus d’interêt.
    2. Ce n’est pas l’algorithme qui est secret, ce sont les paramètres. L’algorithme constitue un systeme de confiance. C’est d’ailleurs le même algorithme qui est utilisé par tout le monde et pour tout.
    3. Il faut changer ou modifier la clé toutes les x utilisations.

    Les effets recherchés:

    • Diffusion: propriété où la redondance statistique dans un texte en clair est dissipée dans les statistiques du texte chiffré. (Claude Shannon).
    • Confusion: correspond à une volonté de rendre la relation entre la clé de chiffrement et le texte chiffré la plus complexe possible (Claude Shannon).

    Consequence: L’effet d’avalanche: une modification même minime en entrée va entrainer de grandes modifications en sortie.

    Chiffrements asymétriques

    Pour le chiffrement symétrique, le seul secret, c’est la clé de chiffrement. Cette clé doit avoir, pour des raisons pratiques, une longueur raisonnable (64, 128, 256 bits). Ce chiffrement permet de communiquer de manière confidentielle, ou de préserver la confidentialité de nos données sur un disque dur. Le problème avec le seul chiffrement symétrique, c’est qu’il ne permet pas de repondre aux besoins d’authentification (reconnaitre l’identité) et d’authenticité (le message n’a pas été modifié).

    Pour comprendre ces termes, on utilise le scenario suivant. Alice et Bob sont 2 personnes qui veulent echanger des messages de manière sécurisée. Une 3e personne, appelée Trudy joue le rôle d’un attaquant.

    Le trio Alice - Bob - Trudy

    Le chiffrement asymétrique utilise plusieurs clés, une pour le chiffrement, et une autre pour le dechiffrement. Il repose sur des propriétés mathématiques de l’arithmetique modulaire. (voir principe du chiffrement RSA)

    Principe du chiffrement RSA

    Confidentialité

    Il doit y avoir 2 clés. L’une de ces clés doit rester secrête, et conservée par l’expediteur du message: c’est la clé privée. L’autre clé utile pour le chiffrement et le dechiffrement est partagée: elle est dite publique. On peut indifféremment chiffrer avec la clé publique et déchiffrer avec celle privée, ou l’inverse.

    VIDEO chiffrement asymetrique (demarrer à 4min28) - chaine ScienceEtonnante

    Ainsi, comme la clé de Bob est publique, Alice peut utiliser cette clé pour chiffrer le message qu’elle veut lui envoyer, un peu comme si elle mettait le message dans un coffre (celui de Bob). Et Bob, qui possède la clé privée correspondante (la clé de son coffre) peut alors déchiffrer le message d’Alice.

    Chiffrement asymetrique

    Authentification

    On peut utiliser cet algorithme pour authentifier l’auteur du message, et réaliser une signature numérique.

    Imaginons que Bob utilise sa clé privée pour chiffrer un message M. Il l’envoie à Alice, qui, en utilisant la clé publique de Bob, pourra le déchiffrer. Elle pourra ainsi s’assurer que Bob en est bien à l’origine et que son contenu n’a pas été modifié.

    En effet, comme il est le seul à posséder la clé privée, ce message M vient bien de Bob.

    Compléter la situation où Bob envoie un message de type Bonjour à Alice, en utilisant sa clé privée:

    Bonjour Alice - via chiffrement asymetrique

    Le point faible de cet échange vient de la distribution de la clé publique entre Bob et Alice.

    Cet échange n’est réellement sécurisé qu’à la condition que la clé publique de Bob, vienne bien de Bob. Et que personne ne se soit introduit dans la discussion pour substituer la clé publique de Bob par la sienne (attaque de l’homme du milieu).

    Compléter la situation suivante où Eve réalise une attaque dite de l’homme du milieu. Elle envoie au préalable sa propre clé publique à Alice et Bob. Puis elle se fait passer pour chacun des 2 lors de la discussion.

    Bonjour Alice, bonjour Bob - Eve

    Pour s’authentifier, Bob doit d’abord envoyer à Alice un certificat, qui contient sa clé publique mais aussi d’autres informations qui permettent de verifier la validité de ce certificat, en particulier l’emetteur: le nom de l’autorité de certification, une infrastructure à clé publique (PKI) qui a validé l’identité de Bob.

    Certificats: Les navigateurs permettent d’ouvrir les pages des sites qui ont pu être authentifiés. Pour faire ceci, les navigateurs intègrent un certain nombre de certificats reconnus. Pour les autres, ils utilisent une chaine de certification: les navigateurs font confiance à certaines autorités de certification, qui ont au préalable, certifié leurs clients (possesseurs de sites web).

    Si la chaine de confiance est rompue, votre navigateur affiche cette image qui va certainement vous dissuader de poursuivre votre navigation:

    certificat non reconnu

    En pratique, le certificat est un ensemble d’informations sur le propriétaire du domaine, la durée de validité, l’algorithme utilisé pour l’authentification, la clé publique, et surtout l’emetteur. Lorsqu’Alice reçoit le certificat que lui envoie Bob, elle consulte l’emetteur du certificat pour verifier qu’il s’agit bien du bon certificat, que celui-ci appartient bien à Bob.

    procedure d'echange de certificat

    Principe d’une communication securisée HTTPS

    Lors d’une communication HTTPS: les objectifs d’authentification, authenticité et de confidentialité sont remplis. Lors du protocole de communication, les chiffrements asymétriques et symétriques sont tous 2 utilisés:

    Que Se Passe-t-il Entre un Navigateur Web (client) et un Serveur ?

    • le client demande au serveur que celui-ci s’authentifie (1)
    • Le serveur envoie au navigateur une copie de son certificat SSL (2)
    • Le navigateur vérifie s’il fait confiance à ce certificat SSL. Si oui,le client envoie de manière sécurisée une clé de session qui servira pour la communication (3). L’envoie de la clé se fait à l’aide du chiffrement asymétrique (RSA). Le client utilise la clé publique du serveur pour cet envoi.
    • Cette clé sera utilisée pour des chiffrements symétriques entre le client et le serveur (4).
    établissement d'une communication securisée - OVH

    Signature numérique: Lorsqu’on utilise sa propre clé privée pour envoyer un message, et qu’une autorité de certification peut garantir l’origine de cette clé privée, alors ce message envoyé a valeur de signature numérique. Il permet d’authentifier l’emetteur du message.

    Exercices

    Substitution monoalphabétique: Code de César

    • Question 1: Quelle clé a été utilisée pour chiffer ce texte (avec l’algorithme de César)?
    jyfwavnyhwopl hwwspxbll
    • Question 2: Décrypter ce message.

    • Question 3: Proposer un programme en python qui chiffre un message clair m en un message codé selon la clé numérique c.

    Aide:

    • La fonction ord('x') retourne un entier correspondant à la position d’un caractère dans la table ascii.
      Par exemple, ord('A') retourne 65, ord('B') retourne 66,…

    • La fonction chr(N) retourne le caractère de rang N: chr(65) retourne ‘A’.

    Substitution polyalphabétique: Chiffrement de Playfair

    A partir des explications données dans la video:

    • Question 1: Construisez la matrice pour l’algorithme de Playfair avec la clé estienne.
    • Question 2: Chiffrer le message: COUPERLETRANSMETTEUR.
    • Question 3: S’agit-il d’une méthode utilisant la substitution monoalphabetique, ou polyalphabetique?
    • Question 4: Est-ce qu’avec cette méthode, le decryptage peut être facilité par l’analyse fréquentielle?

    Frequences des lettres dans un texte

    La fonction suivante retourne une liste de 26 valeurs de type float, donnant dans l’ordre de l’alphabet, la frequence pour chaque lettre dans un texte:

    def freq(m):
        frequences = [0]*26
        n = len(m)
        for c in m:
        ...
    • Question 1: Compléter le script de la fonction freq.

    Soient les deux textes chiffrés suivants:

    a. DGFHTMOMEIAMTLMFGOKFGOKEGDDTRWEIAKZGFGFSTEKGOMLASTTIFG FOSTLM FTFGOK MGWMFG OKRTSA JWTWTA WDTFMG FDAOLT WMOSSA FGOKET WKRWFD TEIAFM ROAZSG MOFKOT FFTXAW MLARGW ETWKJW AFROSD OAWSTA WDAMOF HGWKDT STEITK SADAOF

    b. YOHGMV MFCBRB GWFNIZ ZPSURW FUOIPU WYITFA NIETGG DOCKAC PQE- BEW PMXEMK VGRAIL KWWXZO CILGPM QOVCGE GMYEBQ RYACJM WX- ULFR VQMDCY LZFYZM YTPCRF DCRJNS FIHIQG RZEPRC VWMDIL KGYDQO RVFMXM CRCNIM UGRBKR BOOIUG PQCBVZ NEYACE

    • Question 2: L’un des 2 a été chiffré avec un algorithme de substitution mon-alphabetique, et l’autre, poly-alphabétique. Lequel est mono-alphabétique?

    Chiffrement symetrique par la fonction XOR

    Cet exercice est inspiré du TP cryptographie du site de hmalherbe.fe - NSI

    La fonction XOR est la fonction du OU EXCLUSIF.

    • Question 1: Donner la table de vérité de la fonction XOR
    • Question 2: Programmer la fonction xor en python qui retourne le resultat de XOR appliqué aux 2 paramètres a et b.

    Exemple:

    >>> xor(0,1)
    >>> 1

    On utilisera pour cet exercice les fonctions suivantes, qui permettent de transformer un texte en binaire, à partir du code ascii des lettres:

    def text2bin(texte):
        """ convertit une chaine de caracteres en binaire
        param:
        texte: str, une chaine de caracteres
        return:
        bin: str, une sequence de 8 bits par caracteres
        chaque sequence de 8 bits est la valeur du code ascii du caractere
        convertie en binaire (sur un octet)
        exemple:
        >>> text2bin('HELLO')
        >>> '0100100001000101010011000100110001001111'
        """
        bin = ''
        for l in texte:
            bits = f'{ord(l):b}'
            # f est une fonction de formatage et convertit
            # une valeur decimale ord(l) en binaire
            # ord(l) donne la valeur numerique correspondant au caractere ascii l
            oct = octet(bits)
            bin += oct
        return bin
    
    def octet(bits):
        """ rajoute les 0 au nombre binaire pour mettre en format de 8 bits
        """
        byte = str(bits)
        for i in range(8-len(bits)):
            byte = '0' + byte
        return byte
    • Question 3: programmer toutes ces fonctions dans un fichier python (ou un notebook). Tester en particulier la fonction text2bin sur un texte relativement court (2 caractères). Recopier le résultat obtenu.

    La fonction suivante transforme une séquence de chiffres binaires en une valeur décimale:

    def bin2dec(oct):
        # oct est un str de 8 caracteres
        n = 0
        for i in range(len(oct)):
            n += int(oct[-i-1])*2**i
        return n

    Exemple:

    >>> bin2dec('001001')
    >>> 9
    • Question 4: Utiliser cette fonction pour écrire le script de bin2text, la fonction inverse de text2bin, qui, pour une sequence binaire donnée, de longueur multiple de 8 bits, retourne la chaine de caracteres correspondants.

    Le XOR (OU exclusif) est très utilisé dans les protocoles de chiffrement symétrique. En effet, c’est une opération qui est sa propre réciproque, ce qui n’est pas le cas du ET ni du OU.

    On souhaite chiffrer un message (par exemple une chaîne de caractères) à l’aide d’une clé binaire. Seuls des caractères ASCII sont utilisés.

    • Question 5: Ecrire le script de cette fonction, que l’on appelera chiffre_xor. Cette fonction prend 2 paramètres: la séquence de bits à chiffrer, ainsi que la clé de chiffrement. Cette clé est de dimension inférieure ou égale au premier paramètre. Il faudra l’appliquer de manière périodique aux bits de la séquence à chiffrer (voir cours sur le chiffrement poly-alphabetique).
    • Question 6: Utiliser les fonctions du programme pour:
      • convertir un message secret en une sequence binaire
      • chiffrer cette sequence binaire avec l’algorithme XOR, en utilisant la clé 10101
      • afficher le message chiffré
      • dechiffrer le message
      • afficher le message dechiffré

    Liens