1

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.

6
  • What are the frequencies your program determines for the correct 8 an dfor the wrong 21? Does it make sense that you program selects 21, juding by those numbers? I ask because it separtes the two major possible mistakes: a) mistake in measuring the frequencies b) deciding upong that data.
    – Yunnosch
    Commented Mar 10 at 12:45
  • There are two errors, (1) you do not zero out frequencias at the beginning and (2) you forgot to divide the difference by Ei, which is tab[x] in your code. Commented Mar 10 at 13:02
  • @Yunnosch already solved it, I forgot to add two things, thanks!
    – Birdy
    Commented Mar 10 at 14:05
  • And are you now going to share your solution by adding an answer post? Or will you otherwise delete this question?
    – Yunnosch
    Commented Mar 10 at 14:06
  • 2
    No. Create an answer post. Do not add the solution to the question please. Even only adding "SOLVED" does not match the concepts of StackOverflow. You should be able to create an answer post here, otherwise describe what prevents you. I will try to help you get to the root of thastoddity.
    – Yunnosch
    Commented Mar 10 at 14:11

1 Answer 1

1

Adjustement:

frequencias [i] = 0;

so it begins with a clear array before it starts to calculate, without keeping values in frequencias [i] otherwise it would start with frequencias[last value calculated];

and

diferenca += (frequencias[j] - tab[x]) * (frequencias[j] - tab[x]) / tab [x];

dividing the "diferenca" by the expected frequency tab [x] (it needs to be the respective formula they give in the assignment).

#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[]) 
{    for (int i = 0; i < 26; i++) 
{
frequencias [i] = 0;

}
    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]) / 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;
}
4
  • Assuming that you are turning a comment into an answer, please say so. (The comments author decided not to make an answer, so it is fine that you do. And it might only be my opinion that you should nevertheless mention it. Just a recommendation.)
    – Yunnosch
    Commented Mar 10 at 14:23
  • @Yunnosch it says I only can accept my own answer in two days
    – Birdy
    Commented Mar 10 at 14:24
  • Find help with formatting your post here: stackoverflow.com/help/formatting .
    – Yunnosch
    Commented Mar 10 at 14:24
  • Yes, you cannot accept your own answer for a certain time. That is true. Do you have a question concerning that rule?
    – Yunnosch
    Commented Mar 10 at 14:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.