Skip to content

nirPrfne

Énoncé

Le mardi, c'est cryptographie (la rime fonctionne également avec quasiment tous les jours de la semaine). Dans ce TP nous nous intéressons au chiffrement par décalage. Cette méthode, aussi connue sous le nom de "chiffre de César" ou encore rotx était utilisée par l'empereur pour ne pas être "sniffé" par la poste impériale.

Le principe est très simple comme l'illustre le schéma ci-dessous. Une lettre est transformée par un décalage / une rotation d'une certaine quantité (3 sur le schéma) vers la droite dans l'ordre alphabétique. Lorsque l'on arrive à la fin de l'alphabet, c'est à dire sur Z on recommence au début, c'est à dire sur A. Les minuscules restent des minuscules, et les majuscules restent des majuscules.


exemple de décalage de 3

Les objectifs de ce TP sont les suivants :

  • s'entraîner à la lecture de documentation d'interface de programmation ;
  • faire connaissance avec monsieur ASCII et madame UNICODE ;
  • créer et écrire dans un fichier depuis un programme python.

Votre travail consiste tout d'abord à implémenter les deux fonctions du module rotx dont le squelette vous est fourni ici et affiché ci dessous.

 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
27
28
29
"""Module d'encodage/décodage par rotation"""


def rot(decalage, lettre):
    """Renvoie la lettre donnée encodée par rotation.

    Le décalage utilisé pour la rotation est spécifié en paramètre.
    Préconditions :
       - lettre est une chaîne de caractères de taille 1 ;
       - lettre est un soit une lettre majuscule
         soit une lettre minuscule.
    """
    # TODO
    ...


def rot13(lettre):
    """Encode la lettre donnée par rotation de 13 caractères
    (correspond au nombre de lettre du nom du TP !).

    Pour répondre à une question qui revient souvent :
    "Oui cette fonction est ultra simple, et s'implémente
    en une seule ligne".

    Préconditions :
       - lettre est une chaîne de caractères de taille 1.
    """
    # TODO
    ...

Nous vous demandons de vérifier les préconditions et de lancer une exception de type ValueError si celles-ci ne sont pas vérifiées.

Ensuite, vous devrez réaliser un programme decodeur_nom_tp.py qui effectue les opérations suivantes :

  • demande à l'utilisateur de saisir un nom de fichier et crée un fichier portant ce nom dans le répertoire courant (écrasement si fichier déjà existant) ;
  • utilise le module rotx pour décoder chacune des lettres du nom de ce TP (nirPrfne, encodé avec un décalage de 13) et écrit le résultat dans le fichier créé à l'étape précédente ;
  • affiche sur la sortie standard votre prénom encodé par un décalage de 4 en utilisant un seul appel à la fonction print, c'est à dire en exploitant le fait que cette fonction puisse recevoir un nombre variable d'arguments. Comme nous l'avons vu dans le TD2, vous utiliserez le paramètre sep de la fonction print pour obtenir un affichage sans espaces entre les caractères encodés.

Vous aurez besoin de lire les pages d'aide concernant les mots clefs et les fonctions ci-dessous :

  • chr aide disponible avec help(chr)
  • ord aide disponible avec help(ord)
  • print aide disponible avec help(print)
  • input aide disponible avec help(input)
  • open aide disponible avec help(open)

Correction

Cliquez ici pour révéler la correction.

Voici le code d'une correction possible.

Fichier rotx.py :

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""Module d'encodage/décodage par rotation"""


def rot(decalage, lettre):
    """Renvoie la lettre donnée encodée par rotation.

    Le décalage utilisé pour la rotation est spécifié en paramètre.
    Préconditions :
       - lettre est une chaîne de caractères de taille 1 ;
       - lettre est un soit une lettre majuscule
         soit une lettre minuscule.
    """

    # Vérification des préconditions
    if len(lettre) != 1:
        raise ValueError("Lettre doit être une chaîne de caractères de longueur 1")
    code_ascii = ord(lettre)
    est_majuscule = code_ascii >= ord("A") and code_ascii <= ord("Z")
    est_minuscule = code_ascii >= ord("a") and code_ascii <= ord("z")
    if not (est_majuscule or est_minuscule):
        raise ValueError("Lettre doit être une majuscule ou une minuscule")

    # On rotationne
    if est_majuscule:
        premiere_lettre = "A"
    else:
        premiere_lettre = "a"
    code_ascii_normalise = code_ascii - ord(premiere_lettre)
    code_ascii_rotatione = (code_ascii_normalise + decalage) % 26 + ord(premiere_lettre)

    # On renvoie le caractère correspondant au nouveau code
    return chr(code_ascii_rotatione)



def rot13(lettre):
    """Encode la lettre donnée par rotation de 13 caractères
    (correspond au nombre de lettre du nom du TP !).

    Pour répondre à une question qui revient souvent :
    "Oui cette fonction est ultra simple, et s'implémente
    en une seule ligne".

    Préconditions :
       - lettre est une chaîne de caractères de taille 1.
    """
    return rot(13, lettre)

Fichier decodeur_nom_tp.py :

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/usr/bin/env python3
"""Décodeur du nom du tp"""

import rotx


def main():
    """point d'entrée du programme"""

    # On demande le nom du fichier à l'utilisateur
    nom_fichier = input(
        "Donnez le nom du fichier qui contiendra le résultat puis taper 'entrée':\n"
    )

    # On ouvre le fichier puis on écrit dedans
    # La version pythonique c'est "with open"
    # pour ne pas à avoir à faire close
    # mais ça cache plein de choses :
    #   - notion de context manager
    #   - surcharge de __enter()__
    #   - surcharge de __exit()__
    # et on ne veut rien cacher (pour le
    # moment au moins)
    fichier = open(nom_fichier, "w", encoding="utf8")
    fichier.write(rotx.rot13("n"))
    fichier.write(rotx.rot13("i"))
    fichier.write(rotx.rot13("r"))
    fichier.write(rotx.rot13("P"))
    fichier.write(rotx.rot13("r"))
    fichier.write(rotx.rot13("f"))
    fichier.write(rotx.rot13("n"))
    fichier.write(rotx.rot13("e"))

    # On ferme le fichier
    fichier.close()

    # On affiche l'encodage de son prénom
    # avec un rot 4 en utilisant un seul
    # appel à print et sans variable.
    # La fonction print accepte un nombre
    # variable d'arguments et un argument
    # optionnel sep
    print(
        rotx.rot(4, "M"), rotx.rot(4, "a"), rotx.rot(4, "n"), rotx.rot(4, "u"), sep=""
    )


main()

Une correction détaillée en vidéo est également disponible. Attention, l'opérateur with de python est utilisé dans cette vidéo. Cet opérateur, utilisé avec la fonction open, va se charger de garantir que le fichier sera fermé une fois que le flot de contrôle sortira du bloc associé.

Exercices