Possibilité de réponse à une activité proposée par NumWorks
message = "LOI SMPJOSMPQUWOI IGZP WZ OZIOSTLO HO AGZZMQIIMZAOI MTIPBMQPOI BOIWLPMZP HO BMQIGZZOSOZPI LGCQUWOI MNNLQUWOI M HOI GTXOPI HQDOBI OLI UWO LOI OZIOSTLOI SMPJOSMPQUWOI, LOI ZGSTBOI, LOI VGBSOI… SOBAQ KQEQNOHQM !"
# Codes ASCII de 'A' à 'Z'
alphabet = range(65, 91)
def decode(txt):
# Stats sur les lettres
stats = []
for a in alphabet: stats.append(txt.count(chr(a)))
# On garde les 2 meilleurs scores
# qui devraient correspondre aux lettres 'E' et 'S'
best = sorted(enumerate(stats), key=lambda x:x[1], reverse = True)[:2]
# Substitutions probables pour 'E' et 'S'
# 0 pour 'A', 1 pour 'B'...
x,y = best[0][0], best[1][0]
# On cherche les transformations affines a*x+b
# qui envoient x vers 4 (lettre 'E') et y vers 18 (lettre 'S')
for a in range(27):
for b in range(27):
if (a * x + b) % 26 == 4 and (a * y + b) % 26 == 18:
# Si on trouve une transformation
# on traduit le texte en effectuant
# la même transformation pour les autres lettres
s = ''
for c in txt:
l = chr(65 + (a * (ord(c)-65) + b) % 26) if ord(c) in alphabet else c
s += l
# Affichage du résultat
print('y={}x+{} mod 26\n{}'.format(a,b,s))
message = "LOI SMPJOSMPQUWOI IGZP WZ OZIOSTLO HO AGZZMQIIMZAOI MTIPBMQPOI BOIWLPMZP HO BMQIGZZOSOZPI LGCQUWOI MNNLQUWOI M HOI GTXOPI HQDOBI OLI UWO LOI OZIOSTLOI SMPJOSMPQUWOI, LOI ZGSTBOI, LOI VGBSOI... SOBAQ KQEQNOHQM !" alphabet = range(65, 91) def decode(txt): stats = [] for a in alphabet: stats.append(txt.count(chr(a))) best = sorted(enumerate(stats), key=lambda x:x[1], reverse = True)[:2] x,y = best[0][0], best[1][0] for a in range(27): for b in range(27): if (a * x + b) % 26 == 4 and (a * y + b) % 26 == 18: s = '' for c in txt: l = chr(65 + (a * (ord(c)-65) + b) % 26) if ord(c) in alphabet else c s += l print('y={}x+{} mod 26\n{}'.format(a,b,s)) decode(message)