You have intercepted a poorly evolved terrorist cell that uses Caesar's method as a cipher. Messages are always in English. What they do is replace each letter with another letter by moving the alphabet K positions. So, for example, if we move the alphabet two positions forward, we would get the following correspondence:
**A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
CDEFGHIJKLMNOPQRSTUVWXYZAB **
Of course this method has a very simple attack:
Try all possible substitutions;
Calculate for each possible substitution the next measure between the expected relative frequency of each letter Ei, and the obtained **Oi **using the formula: (Ei-Oi)^2 / Ei
Your program should read a line of text with at most 10^4 characters.
Your program should print the required offset and the deciphered text. Your program should only handle letters (upper or lower case).
Write a program that reads a line of text and decrypts it. Use the table below for the value Ei (third column) of each letter:
E 11.1607% 56.88 M 3.0129% 15.36
A 8.4966% 43.31 H 3.0034% 15.31
R 7.5809% 38.64 G 2.4705% 12.59
I 7.5448% 38.45 B 2.0720% 10.56
O 7.1635% 36.51 F 1.8121% 9.24
T 6.9509% 35.43 Y 1.7779% 9.06
N 6.6544% 33.92 W 1.2899% 6.57
S 5.7351% 29.23 K 1.1016% 5.61
L 5.4893% 27.98 V 1.0074% 5.13
C 4.5388% 23.13 X 0.2902% 1.48
U 3.6308% 18.51 Z 0.2722% 1.39
D 3.3844% 17.25 J 0.1965% 1.00
P 3.1671% 16.14 Q 0.1962% 1.00
Examples: ** Input 1**
GXOXKFHKX
Output 1
7 NEVERMORE
Input 2
Oj wz, jm ijo oj wz, ocvo dn ocz lpznodji: Rczoczm 'odn ijwgzm di ocz hdiy oj npaazm.
Output 2
5 To be, or not to be, that is the question: Whether 'tis nobler in the mind to suffer.
#include <stdio.h>
#include <string.h>
double tab[26] = {43.31, 10.56, 23.13, 17.25, 56.88, 9.24,
12.59, 15.31, 38.45, 1.00, 5.61, 27.98,
15.36, 33.92, 36.51, 16.14, 1.00, 38.64,
29.23, 35.43, 18.51, 5.13, 6.57, 1.48,
9.06, 1.39};
void calcularfrequencias(const char texto[], double frequencias[])
{
int letras = 0;
for (int i = 0; texto[i] != '\0'; i++)
{
char c = texto[i];
if (c >= 'A' && c <= 'Z')
{
frequencias[c - 'A']++;
letras++;
}
else if (c >= 'a' && c <= 'z')
{
frequencias[c - 'a']++;
letras++;
}
}
for (int i = 0; i < 26; i++)
{
frequencias[i] /= letras;
}
}
int encontrardeslocamento(double frequencias[])
{
int deslocamento = 0;
double menor = 1e9;
for (int i = 0; i < 26; i++)
{
double diferenca = 0.0;
for (int j = 0; j < 26; j++)
{
int x = (j + i) % 26;
diferenca += (frequencias[j] - tab[x]) * (frequencias[j] - tab[x]);
}
if (diferenca < menor)
{
menor = diferenca;
deslocamento = i;
}
}
return deslocamento;
}
void decifrar(char texto[], int deslocamento)
{
for (int i = 0; texto[i] != '\0'; i++)
{
char c = texto[i];
if (c >= 'A' && c <= 'Z')
{
printf("%c", ((c - 'A' + deslocamento) % 26) + 'A');
}
else if (c >= 'a' && c <= 'z')
{
printf("%c", ((c - 'a' + deslocamento) % 26) + 'a');
}
else
{
printf("%c", c);
}
}
}
int main()
{
char texto_cifrado[10000];
if (fgets(texto_cifrado, sizeof(texto_cifrado), stdin) != NULL)
{
double frequencias[26];
calcularfrequencias(texto_cifrado, frequencias);
int deslocamento = encontrardeslocamento(frequencias);
printf("%d ", deslocamento);
decifrar(texto_cifrado, deslocamento);
}
return 0;
}
I tried this but when I try it it doesnt works in one input: Gx ‘Fwnwj—fwnwjegjw’.”
the output should be: 8 Of ‘Never—nevermore’.”
but in this code the output is 21 Bs ‘Arire—arirezber’.” and I can't figure it out.
Thank you for your help.
frequencias
at the beginning and (2) you forgot to divide the difference by Ei, which istab[x]
in your code.