Vrai ou Faux ?

Questions « flash » du 1er avril

not True ?
False
On vous demande le contraire « logique ».
Par exemple si « x == 2 » est vrai, alors « x == 2 » vaut True.
On va donc statuer que x vaut 2.
Alors « not (x == 2) » est pareil que « x != 2 » et ça c’est faux, puisque x vaut 2.
True
Ben non, c’est not True, alors c’est pas True 😀
I don’t know 😦
C’est mal.
I know but I won’t tell 😉
Chenapan.
True or False ?
True
On vous demande si c’est vrai, ou si le contraire est vrai.
Par exemple est-ce que « x == 2 » ou « x != 2 » ?
Et ça, peu importe ce que vaut x, c’est l’un OU l’autre.
Donc si l’un est vrai OU l’autre est vrai c’est vrai.
Donc si x vaut 2 c’est vrai, et si x ne vaut pas 2, c’est encore vrai.
C’est toujours vrai.
Wrong
On dit pas wrong, on dit False, et c’est False de dire False, parce que c’est True 😀
I still don’t know 😦
C’est vraiment mal.
I know but I won’t tell 😉
Décidément, frippon canaillou, va..

TP – afficheurs d’octets UTF8

Prérequis :

Se souvenir du cours sur l’utf8, comme ici.

NSI première : C’était pour mercredi 1er avril

ISN terminale : c’est le TP du jeudi 2 avril

Réaliser une fonction affiche_octets_utf8 qui … affiche les octets (en binaire) d’un caractère (encodé en utf8) envoyé en paramètre d’entrée (ou en argument si vous préférez).

Le découpage fonctionnel est le suivant :

def un_octet(chaine_de_bits):
    # renvoie par exemple pour l'espace :
    # 00100000
    # pour le A (code 65) :
    # 01000001
def deux_octets(c):
    # renvoie par exemple pour é :
    # 11000011 10101001
def trois_octets(c):
    # renvoie par exemple pour €  :
    # 11100010 10000010 10101100

def quatre_octets(c):
    # attention deux cas ici

def affiche_octets_utf8(caractere):
    # utilise une fonction native de python
    # pour avoir les bits de l'écriture binaire
    # et suivant la longueur ce cette chaîne binaire appelle
    # l'une des quatre fonctions ci-dessus
    # en leur envoyant la chaîne binaire pour qu'elles
    # renvoie les octets

print(affiche_octets_utf8(' '))
print(affiche_octets_utf8('A'))
print(affiche_octets_utf8('é'))
print(affiche_octets_utf8('€'))
print(affiche_octets_utf8(chr(2 ** 15)))
print("C'est le glyphe ou caractère pour un code de 2 ** 15")
print("D'après google translate, voudrait dire 'Yào' soit briller en chinois !")
print("L'afficheur quatre octets est un peu virtuel :")
print("Pas de code unicode à quatre octets à ce jour ...")
print("... compatibles avec Python 3.")
print("Mais, avec la fonction quatre_octets, un code de")

for k in range(17, 21):
    print("2 **", k, "doit afficher", quatre_octets(bin(2 ** k)[2:]))
    print("(" + str(k + 1) + " bits)")

Et ce code doit afficher :

  est codé sur 1 octet (ASCII) : 00100000
A est codé sur 1 octet (ASCII) : 01000001
é est codé sur 2 octets : 11000011 10101001
€ est codé sur 3 octets : 11100010 10000010 10101100
耀 est codé sur 3 octets : 11101000 10000000 10000000
C'est le glyphe ou caractère pour un code de 2 ** 15
D'après google translate, voudrait dire 'Yào' soit briller en chinois !
L'afficheur quatre octets est un peu virtuel :
Pas de code unicode à quatre octets à ce jour ...
... compatibles avec Python 3.
Mais, avec la fonction quatre_octets, un code de
2 ** 17 doit afficher 11110000 10100000 10000000 10000000
(18 bits)
2 ** 18 doit afficher 11110001 10000000 10000000 10000000
(19 bits)
2 ** 19 doit afficher 11110010 10000000 10000000 10000000
(20 bits)
2 ** 20 doit afficher 11110100 10000000 10000000 10000000
(21 bits)
>>>

A finir pour les courageux !

 

J’ai donné ce début de code sur discord

def un_octet(chaine_de_bits):
    '''renvoie par exemple pour l'espace : 00100000
    pour le A (code 65) : 01000001'''
    longueur = len(chaine_de_bits)
    nb_zeros = 8 - longueur
    return nb_zeros * '0' + chaine_de_bits #'00' + '100000'

def deux_octets(c):
    '''renvoie par exemple pour é : 11000011 10101001'''
    deuxieme_octet = '10' + c[-6:]
    premier_octet = '110' + '0' * (5 - len(c[:-6])) + c[:-6]
    return premier_octet + ' ' + deuxieme_octet

def affiche_octets_utf8(caractere):
    # utilise une fonction native de python
    # pour avoir les bits de l'écriture binaire
    code = ord(caractere)
    chaine = bin(code)
    chaine = chaine[2:]
    log2 = len(chaine)

    if log2 > 8:
        return un_octet(chaine)
    elif log2 > 12:
        return deux_octets(chaine)

    # et suivant la longueur ce cette chaîne binaire appelle
    # l'une des quatre fonctions ci-dessus
    # en leur envoyant la chaîne binaire pour qu'elles
    # renvoie les octets

print(affiche_octets_utf8(' ')) # 32 -> 00 100000
print(affiche_octets_utf8('A')) # 65 -> 0 1000001
print(affiche_octets_utf8('é'))

Et ces explications dans le shell

>>> 'é'
'é'
>>> chr(65)
'A'
>>> ord('é')
233
>>> bin(ord('é'))
'0b11101001'
>>> bin(233)
'0b11101001'
>>> hex(233)
'0xe9'
>>> bin(233)
'0b11101001'
>>> bin(ord('é'))
'0b11101001'
>>> bin(ord('é'))[0]
'0'
>>> bin(ord('é'))[1]
'b'
>>> bin(ord('é'))[0:2]
'0b'
>>> bin(ord('é'))[2:]
'11101001'
>>> bin(ord('A'))[2:]
'1000001'
>>> bin(ord(' '))[2:]
'100000'
>>> '0' * 2 + bin(ord(' '))[2:]
'00100000'
>>> 2 ** 15
32768
>>> 2 ** 17
131072
>>> 2 ** 16
65536
>>> print(chr(2 ** 15))
耀
>>> chr(108)
'l'
>>> bin(ord('€'))[2:]
'10000010101100'
>>> len(bin(ord('€'))[2:])
14
>>>

TP pygame – saisie et affichages, vers l’utf8

Question flash :

Compléter en suivant ce que disent les commentaires :

# import bibliothèque adaptée

def jeu(pseudo) :
    # calcule un aléatoire entre 12 et 36
    # affiche que le pseudo dans la variable pseudo a fait ce score
    # renvoie le score
>>> jeu("La belle au bois dormant")
La belle au bois dormant a fait 18
18
>>>

Réponse lors du chat discord :

# import bibliothèque adaptée
from random import randint

def jeu(pseudo) :
    # calcule un aléatoire entre 12 et 36
    score = randint(12, 36)
    # affiche que le pseudo dans la variable pseudo a fait ce score
    print(pseudo, "a fait", score)
    # renvoie le score
    return score

Dans le shell :

>>> jeu("Gaëtan")
Gaëtan a fait 23
23
>>>

TP pygame – saisie et affichages, vers l’utf8

Les fichiers de départ sont ici.

« gestion des scores » lors du chat discord :

import pickle

def initialise():
    # liste des scores au cas où
    return [(42, "Mr Marchant !"),(28,"Superman"),(21, "Kirsten Dunst"),(5, "Le Joker")]

def enregistre(liste):
    # Sauvegarde de la liste dans le même dossier dans un fichier
    fichier = open('scores_dump', 'wb')
    # 'wb' comme write en binaire
    pickle.dump(liste, fichier)
    fichier.close() # libérer délivrer le fichier

def charge() :
    fichier = open('scores_dump', 'rb')
    # 'rb' comme read en binaire
    liste = pickle.load(fichier)
    fichier.close() # libérer délivrer le fichier

    return liste

scores = initialise()
for truc in scores:
    print(truc[1], "\t",truc[0])
print()

scores.remove((28,"Superman"))
for truc in scores:
    print(truc[1], "\t",truc[0])

# scores.append((36, "Gaëtan !"))

print()
scores = charge()
for truc in scores:
    print(truc[1], "\t",truc[0])
# enregistre(scores)

Un fichier scores_dump est apparu dans le dossier !

On enlève la fin et le fichier « gestion_scores.py » contient :

import pickle

def initialise():
    # liste des scores au cas où
    return [(42, "Mr Marchant !"),(28,"Superman"),(21, "Kirsten Dunst"),(5, "Le Joker")]

def enregistre(liste):
    # Sauvegarde de la liste dans le même dossier dans un fichier
    fichier = open('scores_dump', 'wb')
    # 'wb' comme write en binaire
    pickle.dump(liste, fichier)
    fichier.close() # libérer délivrer le fichier

def charge() :
    fichier = open('scores_dump', 'rb')
    # 'rb' comme read en binaire
    liste = pickle.load(fichier)
    fichier.close() # libérer délivrer le fichier

    return liste

On explique que les constantes sont en MAJUSCULES comme dans le fichiers parametres.py.

Dans le fichier « tableau_des_scores.py

Les lignes ci-dessous permettent d’importer les fonctions et CONSTANTES de nos fichiers qui deviennent des « bibliothèques perso ».

Ceci permet de partager les fonctionnalités dans un binôme/trinôme !

from parametres import *
from prog_jeu import jeu
from gestion_scores import charge, enregistre, initialise

N.B. : un dossier « py_cache » est alors apparu avec nos modules « pré-interprétées »

Les trois « boulots » demandés :

« Boulot 1 »

###########################

    # BOULOT 1 -> trier les scores

    ##############################

    scores_tries = sorted(scores, reverse = True)
    # for truc in scores_tries:
    #    print(truc[1], "\t",truc[0])

« Boulot 2 »

    ordonnee = ORD_DEPART

    ####################################

    #BOULOT 2

    ###################################

    for truc in scores_tries[:5]: # les 5 premiers
        text2 = font.render(str(truc[0]), 1, BLANC)
        fenetre.blit(text2, (ABS_SCORES, ordonnee))
        text2 = font.render(truc[1], 1, BLANC)
        fenetre.blit(text2, (ABS_NOMS, ordonnee))
        ordonnee += PAS_ORD

« Boulot 3 »

            #######################################

            # BOULOT 3

            ######################################

            elif event.key == K_BACKSPACE:
                pseudo = pseudo[:-1] # enlève la dernière
            elif event.key == K_RETURN:
                # jeu de ouf
                score = jeu(pseudo)
                scores.append((score, pseudo))
            elif len(pseudo) < 18:
                pseudo += event.dict['unicode']

Codage des caractères

ASCII, la norme ancestrale mais inchangée pour les caractères dont le « point de code » est strictement inférieur à 128. La trace de ce qui a été tapé pendant la séance :

>>> ord('u') # le code de 'u' ( ord donne le code )
117                 # les minuscules de 97 à 122
>>> ord('U')        # le code de 'U' est 85
85
>>> ord('A')        # les majuscules de 'A' en 65 à ...
65
>>> ord('Z')
90                  # .... 'Z' en 90
>>> chr(65)         # chr donne le caractère correpondant à un code
'A'
>>> for i in range(32, 128) : chr(i) # avant 32 pas imprimables

' '     # espace en 32
'!'     # là on est en 33
'"'     # je vais les mettre l'un à côté de l'autre, c'est long ...
'#' '$' '%' '&' "'" '(' ')' '*' '+' ',' '-' '.' '/'
# les chiffres : '0' en 48 ... '9' en 57
'0' '1' '2' '3' '4' '5' '6' '7' '8' '9'
':' ';' '&lt;' '=' '&gt;' '?' '@' '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' '[' '\\' ']' '^' '_' '`'
# là on est en 97
'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'
'{' '|' '}' '~'
'\x7f'     #pas imprimable
>>> ord('0')  # les chiffres : '0' en 48 ...
48
>>> chr(57)
'9'      # ..... en '9' en 57

Mais ça ne suffit plus !

Les accents européens, les idéogrammes, les caractères cyrilliques, grecs, etc. D’autres… Les smileys …

La norme qui s’est imposée dans les quinze dernières années : l’unicode ou utf-8.

En pratique, tous les systèmes évoluent vers cette norme unifiée pour « tout caractère de n’importe quel système d’écriture (un nom et un identifiant numérique) » : l’Unicode.

La norme UTF-8 est d’un usage de plus en plus courant sur Internet, et dans les systèmes devant échanger de l’information.

C’est une norme rétro-compatible avec l’ASCII initial.

Tous les caractères du « répertoire universel de caractères codés » devant avoir un identifiant unique, un octet ne suffit pas !

Par exemple, le symbole est a un code de 8364 !

Codons 8364 en binaire : 10000010101100.

Il faut non pas 1, non pas 2, non pas 3 mais bien … 14 bits !

L’UTF-8 : de 1 à 4 octets – c’est variable suivant la longueur en bits du code  (à savoir)

cm 2020-01-13 NSI utf8

Pour le symbole , codé 8364 donc 10000010101100 , il faut 14 bits donc 3 octets :

11100010     10000010     10101100    soit      E2   82   AC

Notez que l’UTF-8 demande plus de place que l’ASCII ou d’autres normes intercalées ! C’est le prix de l’universalité.

Les caractères ASCII restent identiques. On parle de rétrocompatibilité de l’utf-8 avec l’ASCII, je le répète (à savoir).

Exercices pour jeudi prochain :

Question 1 :

  • Coder en UTF8 (binaire) le é codé 233.

Question 2 :

  • Combien de caractères différents peut on coder en UTF-8 ?

Question 3 :

On a la séquence de huit octets suivante :

C3 A9 6C C3 A8 76 65 73

où chaque octet est représenté par deux chiffres hexadécimaux.

    • C’est en UTF-8, décoder la séquence.

Information, représentation des données (3)

On a vue ensemble l’écriture binaire de nombres décimaux.

Il reste à voir comment ils peuvent être codés en mémoire. Pour cela, les normes en vigueur définissent les flottants, en simple précision sur 32 bits (float), et en double précision sur 64 bits (double).

Je vous propose de commencer par ce petit test pour rassembler vos connaissances et découvrir et vous frotter aux difficultés du jour :

On ne triche pas et on cherche avant de continuer !

On suppose que vous avez bien cherché… On va tout détailler !

cm 2020-03-19 ISN virgule flottante 01

cm 2020-03-19 ISN virgule flottante 02

cm 2020-03-19 ISN virgule flottante 03

On explique pourquoi :

>>> 0.1 + 0.1 + 0.1
0.30000000000000004
>>>

cm 2020-03-19 ISN virgule flottante 04

Remarque : attention aux codes avec les flottants !

« 0.2 + 0.1 n’est pas égal à 0.3. Il faut éviter de tester l’égalité de deux flottants. »

Illustrons-le avec un petit code python très maladroit :

nombre = 0.1

while nombre != 1 :
    nombre += 0.1
    print(nombre)

Il faut en effet éviter de tester l’égalité de deux flottants :

>>> 
======== RESTART: cm 2020-02-03 NSI exemple1.py ========
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
1.0999999999999999
1.2
1.3
...

Il nous a fallu une interruption (Ctrl-C) pour ce programme qui tournait en boucle infinie !

Conclusion pour l’oral du bac ISN ?

Encore un exercice ?

cm 2020-03-19 ISN virgule flottante 05cm 2020-03-19 ISN virgule flottante 06

A mettre en simple précision sur 32 bits.

On peut vérifier avec ce convertisseur :

  • 6,625 donne 01000000 11010100 00000000 00000000
  • 5,4375 donne 01000000 10101110 00000000 00000000

 

Information, représentation des données (2)

Suite de notre voyage dans le codage de l’information…

Question flash :

« comment est codé -144 sur 32 bits ? »

Correction :

Algorithme de conversion à faire pour aujourd’hui :

  • de décimal vers binaire,

et réciproquement ?

Codage des décimaux : les flottants

  • nombres décimaux en binaire,
  • algorithme pour avoir le développement décimal binaire,
  • à suivre le 19/3, les normes : float et double.

Le tableau du jour (une seule heure) :

Information, représentation des données

On y a parlé d’écriture

  • binaire des nombres entiers non signés,
  • hexadécimale de mêmes nombres entiers non signés,
  • fait un rappel sur les pixels et la notation html des couleurs :cm 2020-02-06 ISN code couleur d7d03d
  • abordé ensuite des algorithmes de conversion du décimal au binaire :
    • comme on le fait « à la main »,
    • par divisions successives par deux,
  • expliqué l’encodage des entiers signés.

Tout est dans les tableaux ci-dessous :

Coder le deuxième algorithme de conversion vers le binaire donné pendant ce cours, par divisions successives par deux, celui du cinquième tableau au début de la troisième page, pour la rentrée.

Bonnes vacances !

TP improvisé : pile ou file ?

Mini-projets et site web les présentant :

Une collecte a été mise en place pour les rendus sur l’espace numérique de travail (MBN) du lycée.

Exposé du jour :

Septième et dernier exposé de notre cycle par Alex & Tom :

Parcours des graphes et application aux labyrinthes, pile et file

TP improvisé – application de la pile

Il y a huit présents pour sept absents (JU…) ! Plutôt que de péter une pile, on en a utilisé une…

On s’appuie sur le TP des premières NSI de ce mercredi pour, en deux étapes :

  • implémenter les déplacements clavier, dans une boucle while continuer : « perpétuelle » où continuer est initialisée à True et on attend des événements (clavier, souris) pour des actions ou quitter la boucle en passant continuer à False.
  • tout changer, CHANGER DE PARADIGME : passer à un algorithme itératif en utilisant notre nouvelle structure de données, la pile :

cm 2020-01-30 ISN changement de paradigme pour parcous

À droite l’algorithme suivi, par exemple par Corentin « B. de B. », qui a obtenu ceci :

cm 2020-01-31 tp4_parcours profondeur B de B

C’est un parcours en profondeur, « à gauche d’abord » (du point de vue du personnage) ! On a utilisé une pile,

  • initialisé la pile avec pile = []
  • empilé avec pile.append((x, y))
  • dépilé avec x, y = pile.pop()

En changeant cette dernière commande en lui ajoutant un paramètre, on obtient une file,

  • initialisé la file avec file = []
  • emfilé avec file.append((x, y))
  • dépilé avec x, y = file.pop(0)

Et au niveau du parcours, ça change tout : on a un parcours en largeur :

cm 2020-01-31 tp4_parcours largeur B de B

Trions pour l’avenir …

… ou pour une meilleure algorithmique !

Tout le monde doit avoir programmé les tris :

  • par sélection,
  • par insertion,
  • à bulles,

en se basant sur le canevas de la semaine dernière.

On commence par corriger ensemble le tri par sélection que beaucoup avaient fini la semaine dernière et dont on avait proposé un pseudo-code :

from random import randint
 
liste=[]
for i in range(8):
    liste.append(randint(1,101))
 
print(liste)

# tri par sélection du minimum

for i_depart in range(0,7):
    # initialisation
    i_min = i_depart

    # recherche du minimum
    for i in range(i_depart + 1, 8):
        if liste[i] < liste[i_min]:
            i_min = i

    # interversion
    liste[i_depart], liste[i_min] = liste[i_min], liste[i_depart]
    print(liste)

qui donne par exemple :

[62, 84, 15, 52, 58, 35, 56, 7]
[7, 84, 15, 52, 58, 35, 56, 62]
[7, 15, 84, 52, 58, 35, 56, 62]
[7, 15, 35, 52, 58, 84, 56, 62]
[7, 15, 35, 52, 58, 84, 56, 62]
[7, 15, 35, 52, 56, 84, 58, 62]
[7, 15, 35, 52, 56, 58, 84, 62]
[7, 15, 35, 52, 56, 58, 62, 84]
>>> 

Romain (bravo !) propose cette comparaison graphique du temps d’exécution des tris :

TR - 2020_01_15 - Temps de traitement, Algorithmique .jpg

L’image ci-dessus a été obtenue (par Romain) avec des listes de tailles n allant de 1 à 450 et on a trié ces listes avec chacun des algorithmes et chronométré le temps en secondes. Repère :

  • de 1 à 450 pour la taille de la liste triée en abscisses,
  • de zéro à 0,5 secondes en ordonnées.

J’ai utilisé ses codes pour générer l’animation ci-dessous.

TR - 2020_01_15 - Temps de traitement Algorithmique

Repère :

  • de 1 à 150 pour la taille de la liste triée en abscisses,
  • de zéro à 0,3 secondes en ordonnées.

Fini ? Déjà fait ? Alors on continue le …

Travail sur les mini-projets et le site web qui les présente.