Programmation niveau 1

Exercice 1 : Deviner le bon nombre

L’objectif de cet exercice est de vous faire développer un programme qui devinera un nombre en plusieurs étapes successives. Disons par exemple que le “nombre à deviner” soit égal à 10, et qu’un utilisateur essaie de le deviner. Il y a trois cas de figure possible :

  • Le nombre entré par l’utilisateur est supérieur au nombre à deviner, ce qui entraînera une réponse du type “le nombre à deviner est inférieur au nombre entré. Réessayez.”,
  • Le nombre entré par l’utilisateur est inférieur au nombre à deviner, ce qui entraînera une réponse du type “le nombre à deviner est supérieur au nombre entré. Réessayez.”,
  • Le nombre entré par l’utilisateur est égal au nombre à deviner, ce qui causera la fin du jeu.

Correction

In [2]:
def guess_a_number(goal):
    my_number = 0

    while my_number != goal:
        my_number = int(input('Enter a number: '))

        if my_number > goal:
            print('The goal is smaller than ' + str(my_number))
        elif my_number < goal:
            print('The goal is greater than ' + str(my_number))

    print('You won!')

guess_a_number(10)
Enter a number: 0
The goal is greater than 0
Enter a number: 11
The goal is smaller than 11
Enter a number: 9
The goal is greater than 9
Enter a number: 10
You won!

Exercice 2 : Le chiffrement de César

L’objectif de cet exercice est de vous faire chiffrer et déchiffrer des messages en utilisant le chiffrement de César. Cette méthode viendrait de Julius César, qui l’aurait utilisée pour chiffrer ses communications privées.

Le chiffrement de César est un algorithme cryptographique par substitution où une lettre de l’alphabet va être remplacée par une autre. La version la plus communément utilisée est de remplacer une lettre par la lettre se situant trois lettres à sa gauche. Par exemple, un D deviendra un A, et un E deviendra un B. Ce procédé est illustré sur la figure suivante :

Illustration du chiffrement de César (source : Wikipédia) Figure 1 : Illustration du chiffrement de César (source : Wikipédia)

Attention : il y a trois cas spéciaux, qui sont A, B, et C qui deviendront X, Y, et Z respectivement.

Pour simplifier l’exercice, on considère que les seules lettres utilisées sont les lettres minuscules et qu’il n’y a pas d’espace entre les mots.

Vous devrez utiliser deux fonctions pour pouvoir réussir les questions suivantes :

  • La fonction chr, qui vous donnera le nombre correspondant au code de la lettre. Par exemple, chr( ′a′ ) retournera la valeur 0, chr( ′b′ ) retournera la valeur 1, et chr( ′z′ ) retournera la valeur 25.
  • La fonction ord, qui vous donnera la lettre correspondant au nombre donné. Par exemple, ord(0) retournera la valeur ′a′ , ord(1) retournera la valeur ′b′ , et ord(25) retournera la valeur ′z′.

Correction

Les fonctions décrites ci-dessus sont des versions simplifiées des vraies fonctions utilisées en Python. Il est néanmoins possible de coder des fonctions qui imiteront ce comportement comme ceci :

In [3]:
def my_ord(number):
    """ Takes an int between 0 and 25 as input and returns a character
    between 'a' and 'z'. """
    
    return chr(ord('a') + number)

def my_chr(character):
    """ Takes a character and returns its position in the alphabet. """
    
    return [my_ord(i) for i in range(26)].index(character)
  1. Fonction encrypt qui prends une chaîne de caractères en entrée et qui retournera la chaîne de caractères encryptée pour un nombre de décalage quelconque :
In [5]:
def encrypt(string, step):
    """ Encrypts string using the Caesar Cipher with a shift of step. """
    
    res = ''
    
    for character in string:
        res += my_ord((my_chr(character) + step) % 26)
        
    return res

print('dad with a shift of -3 becomes ' + encrypt('dad', -3))
print('geography with a shift of 2 becomes ' + encrypt('geography', 2))
dad with a shift of -3 becomes axa
geography with a shift of 2 becomes igqitcrja
  1. Fonction decrypt qui décode une chaîne créée avec encrypt :
In [8]:
def decrypt(string, step):
    """ Decrypts string using the Caesar Cipher with a shift of step. """
    
    res = ''
    
    for character in string:
        # Only difference with encrypt:  |
        res += my_ord((my_chr(character) - step) % 26)
        
    return res

shift = -11

enc = encrypt('geography', shift)
dec = decrypt(enc, shift)

print(enc + ' decrypted is ' + dec)
vtdvgpewn decrypted is geography

Au final, la fonction decrypt fait la même chose que la fonction encrypt, mais avec un shift d'une valeur inverse. Il est donc possible d'écrire la fonction suivante :

In [10]:
def shorter_decrypt(string, step):
    """ Decrypts string using the Caesar Cipher with a shift of step. """
    
    return encrypt(string, -step)

shift = 7

enc = encrypt('geography', shift)
dec = shorter_decrypt(enc, shift)

print(enc + ' decrypted is ' + dec)
nlvnyhwof decrypted is geography
  1. Comment déchiffrer un message chiffré sans connaître le décalage ?
    1. Analyse fréquentielle des lettres pour déterminer quelle lettre est la plus utilisée.
    2. Attaque de force brute où toutes les possibilités vont être testées.