Ce billet était initialement paru sur le blog Pydéfis.

Aide pour le défi : Séquence Chiffrée

Récupération des données et idée générale

La récupération des données est la première étape. Un simple copié/collé devrait suffire pour obtenir un programme de ce type :

s="""XSDSBGSCPGSFJOVCZASGOAAOFHWBEISJCIGTSFSNPWSBRSRSAO
BRSFIBSSGQCFHSDOFHSZSUFOAASQOFGWASGDFSJWGWCBGGCBHS
...
LYHXLYNIONYMFYMJLYWUONCIHMUPYWOHAUCFFULXXYWYNNYYMJ
TRTEDJGKDJHXCHETRITJGPEEGTITOKDHBTCDIITHTIAPXHHTOB"""

Cette chaîne de caractères multiligne peut être transformée en liste de chaînes avec la méthode splitlines().

L’idée générale est de traiter chaque ligne une par une. Pour chaque ligne, nous testons les 25 décalages possibles (aucune phrase ne semble avoir été chiffrée avec un décalage de 0). Pour chacune des 25 chaînes de caractères obtenues, nous recherchons un mot probable.

Il est préférable de bien organiser le code : une fonction qui calcule le décalage d’une chaîne, une fonction qui recherche un mot dans chacun des 25 décalages (et qui utilise donc la première fonction) etc…

Décalage de César

Pour chiffrer une chaîne de caractères avec un décalage particulier, il faut parcourir la chaîne de départ, et pour chaque caractère, calculer le caractère décalé.

Python permet de parcourir facilement une chaîne de caractères :

l="CHAPEAUPOINTU"
for c in l :
    print('Caractère : ',c)

Décaler un caractères peut être réalisé de différentes manières, toutes intéressantes :

Méthode «classique»

Nous allons voir ici comment utiliser le code de la lettre :

>>> print(ord('A'))
65
>>> print(ord('Z'))
90

Le code précédent affiche : 65 et 90, qui sont les valeurs numériques (unicode) de ces caractères.

Réaliser un décalage cyclique sur des nombres ne requiert que quelques opérations arithmétiques. Par exemple, si la plage de nombres est 10-20 et qu’on doit décaler $n$ de 6 en prenant garde de cycler (si $n$ vaut 18, 18+6 donne 24 donc… 13), le calcul suivant fait l’affaire : $((n-10)+6)%11+10$

Procédez ainsi sur les codes des caractères et vous obtiendrez le code du caractère chiffré. Revenir au caractère chiffré se fait par l’opération inverse de ord() :

print(chr(65))

Construire la chaîne résultat peut être réalisé à partir d’une liste :

l = ['A', 'B', 'T']
s = ''.join(l)
print(s)

ou de manière itérative :

s=""
for c in ('A','B','T') :
   s=s+c
print(s)

Méthode pythonique

Pour réaliser le décalage de césar de manière un peu plus élégante, vous pouvez regarder :

Utilisation des tranches de listes :

al = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
aldec = al[6:]+al[:6]
print(aldec)

Ces trois éléments permettent de chiffrer facilement avec n’importe quel décalage.

Rechercher une chaîne dans une autre

Recherche un mot qui apparaît dans une chaîne de caractères est immédiat avec la méthode find :

>>> "tototututiti".find("tutu")
True
>>> "tototututiti".find("pouet")
False

ou encore

>>> "tutu" in "tototututiti"
True
>>> "pouet" in "tototututiti"
False