Les statistiques au secours des cryptanalystes

<< Graphics`Graphics`

Prétraitement du texte

La première étape consiste à déterminer les fréquences d'apparition des lettres dans la langue désirée (ici le français). Il faut pour cela choisir un extrait assez long (plusieurs milliers de lettres) et bien représentatif de la langue.

extrait = "Entrez ici un texte assez long et représentatif de la langue. Il est seulement interdit de mettre des guillements.";

L'instruction suivante supprime tous les accents et écrit le texte en majuscules.

\(\(maj = 
        ToUpperCase[
          StringJoin[
            Characters[
                ToLowerCase[
                  extrait]] /. {"é" -> "e", "è" -> "e", "ê" -> "e", "ë" -> "e", "à" -> "a", "â" -> "a", "ä" -> "a", "á" -> "a", "î" -> "i", "ï" -> "i", "í" -> "i", "ö" -> "o", "ô" -> "o", "ó" -> "o", "õ" -> "o", "ü" -> "u", "û" -> "u", "ú" -> "u", "ç" -> "c", "ñ" -> "n", "ß" -> "ss", "œ" -> "oe"}]];\)\)

Dans un ordinateur, les lettres majuscules sont codées en code ASCII, du numéro 65 (A) au numéro 90 (Z).

ascii = ToCharacterCode[maj];

On enlève les signes de ponctuation et les espaces pour ne garder que les codes ascii des lettres de A à Z.

ascii = Select[ascii,  (# < 91  &&  # > 64)  &];

On compte le nombre total de lettres.

long = Length[ascii]

Fréquences des lettres

On calcule les fréquences de chaque lettre...

fréquences = 
        Table[N[Count[ascii, j]/long], {j, 65, 90}];

et on affiche le tableau de résultats :

lettres = Table[FromCharacterCode[j], {j, 65, 90}]; 
    TableForm[{lettres, fréquences}, 
      TableDirections -> {Row, Column}]

Pour afficher les diagrammes en bâtons, on utilise les deux instructions suivantes:

barres = 
        Thread[{fréquences, lettres}];
BarChart[barres, PlotRange -> {0, 0.2}, 
        BarStyle -> {RGBColor[0, 0, 1]}];

On peut aussi trier les barres par longueur:

barresTriées = 
        Reverse[Sort[barres]];
BarChart[barresTriées, PlotRange -> {0, 0.2}, 
        BarStyle -> {RGBColor[0, 0, 1]}];

Bigrammes

On affiche une table 26x26 indiquant le nombre d'apparitions de chaque bigramme.

digrammes = Table[0, {26}, {26}];
Table[digrammes[[ascii[[k]] - 64, 
              ascii[[k + 1]] - 64 ]]++, {k, 1, 
          long - 1}];
digrammes // TableForm

On affiche les "nbr" trigrammes les plus fréquents.

entCar[n_] := FromCharacterCode[n + 65];
montrerDigrammes[nbr_]  := 
        Module[{étiqueté, 
            trié}, étiqueté = 
            Flatten[Table[{StringJoin[entCar[k - 1], entCar[j - 1] ], 
                  digrammes[[k, j]]}, {k, 1, 26}, {j, 1, 26}], 
              1]; 
trié = 
            Sort[étiqueté, ((#1[[2]] > #2[[2]]) || ((#1[[2]] == #2[[2]]) && (OrderedQ[{#1, #2}]))) &]; 
Take[trié, 
            nbr] ] ;

montrerDigrammes[20]

Trigrammes

On affiche les "nbr" trigrammes les plus fréquents.

trigrammes = 
        Table[0, {26}, {26}, {26}];

Table[
trigrammes[[ascii[[k]] - 64, 
              ascii[[k + 1]] - 64, 
              ascii[[k + 2]]  - 64]]++,  {k, 1, 
          long - 2}];

entCar[n_] := FromCharacterCode[n + 65];
montrerTrigrammes[nbr_] := 
        Module[{étiqueté, 
            trié}, étiqueté = 
            Select[ Flatten[
                Table[If[
                    trigrammes[[k, j, i]] > 
                      0, {StringJoin[entCar[k - 1], entCar[j - 1],  
                        entCar[i - 1] ], trigrammes[[k, j,  i]]}, {0, 
                      0}], {k, 1, 26}, {j, 1, 26}, {i, 1, 26}], 
                2], (#[[2]] > 
                    0) &]; 
trié = 
            Sort[étiqueté, ((#1[[2]] > #2[[2]]) || ((#1[[2]] == #2[[2]]) && (OrderedQ[{#1, #2}]))) &]; 
If[nbr <= Length[trié], 
            Take[trié, nbr], 
            trié] ] ;

montrerTrigrammes[20]

Travail facultatif

Utilisez la première partie de ce fichier pour trouver les fréquences des lettres dans d'autres langues, par exemple l'allemand, l'italien, l'espagnol, le latin, etc.