viernes, 3 de mayo de 2024

Descifrador de códigos.

 Basado en el proyecto de la Raspberripy Org "Codebreakers".

¿Qué es lo que haremos en este post?


Analizaremos un gráfico para intentar descifrar un código, mientras aprendemos sobre listas y funciones en Python.

Que haremos:

- Definir una función que acepte una serie de parámetros y devuelva un valor.
- Usar los bucles "for" y "while" para repetir tareas.
- Crear un gráfico para mostrar la frecuencia de unos datos.

El programa que crearemos puede codificar o descodificar un mensaje secreto desde un archivo *.txt adjunto, o también podremos analizar la frecuencia de las letras en un mensaje. Estos datos se mostrarán en un gráfico de frecuencias, que mostrará con que frecuencia cada letra aparece en el mensaje secreto.

Nos basaremos en el cifrado Atbash. Este cifrado es uno de los más antiguos que se conocen en el mundo. Originariamente desarrollado en el idioma hebreo, utiliza el alfabeto y lo relaciona en orden inverso para crear el mensaje secreto. El nombre deriva de la primera, última, segunda y penúltima letras hebreas: Aleph, Taw, Bet y Shin.

Cifrando el alfabeto.


Para empezar vamos a crear un diccionario para tus letras cifradas.  El programa comenzará con dos estructuras de datos. La primera es una lista de todas las letras que existen en nuestro alfabeto y la segunda el un diccionario para el código. Para ahorrar teclear código, puedes crear la lista desde una cadena de texto usando la función list().

Empieza el programa con el siguiente código:

#Estructura de datos
#Lista creada desde una cadena de texto
ALFABETO = list(" abcdefghijklmnñopqrstuvwxyz ")
codigo = {}
La lista ALFABETO, como puedes ver, contiene un espacio al principio y al final de las letras. Esto lo hemos hecho para preservar los espacios que existan en el texto del mensaje. Sin embargo en una codificación fuerte esto no debería ser así, ya que hace que los mensajes sean más fáciles de decodificar. En este proyecto hemos mantenido los espacios para que que pueda ver más fácilmente el funcionamiento del programa.

Creando una nueva lista con el alfabeto invertido.


Necesitamos crear una nueva lista pero con el alfabeto, pero invertido. Puedes usar la funcion list() de nuevo para ayudarte con esto. Puedes usar la función reversed() para invertir el orden de una lista existente.

Crea la función crear_codigo. A continuación crea una lista que almacene el alfabeto pero al revés en una lista.

# Crear el código Atbash invirtiendo el alfabeto
def crear_codigo():
    inversa = list(reversed(ALFABETO))


Codificando el alfabeto.


"Codificar" es cuando conviertes datos de un formato a otro. Ahora tienes dos listas. Una contiene la lista del alfabeto en su orden normal y la otra en su orden inverso. Vamos a usar ambas para rellenar un diccionario. La llave almacenará almacenará el alfabeto en su orden normal y el valor correspondiente guardará el diccionario al revés.

El diccionario codigo es muy importante porque lo usaremos para hacer coincidir cada letra del mensaje usando las llaves y sus correspondientes valores.

Dentro de la función crear_codigo, rellena el diccionario usando los datos de ambas listas. Usa un bucle "for" para obtener la longitud de la lista del alfabeto y completar el diccionario con los datos. 

La función len() se usa para obtener la longitud de un objeto, como puede ser una lista. Aquí se usar para que el bucle "for" itere tantas veces como elementos tiene la lista "ALFABETO", es decir su longitud. 

def crear_codigo():
    # reversa del ALFABETO
    inversa = list(reversed(ALFABETO))
    
    for i in range(len(ALFABETO)): # Longitud de una lista
        codigo[ALFABETO[i]] = inversa[i]
        # Rellena el alfabeto con una letra y su correspondiente
        # letra códificada.

Ahora tenemos un problema a solventar. En el idioma español existen los acentos. Para usarlos en nuestro código tenemos que pasar las letras acentuadas como letras normales ya que si no no se procesarían al no estar en el diccionario. Para solventarlo añadimos el diccionario caracteres_especiales y luego añadimos sus elementos al diccionario codigo.

# Crear el código Atbash invirtiendo el alfabeto
def crear_codigo():
    # reversa del ALFABETO
    inversa = list(reversed(ALFABETO))
    
    for i in range(len(ALFABETO)): # Longitud de una lista
        codigo[ALFABETO[i]] = inversa[i]
        # Rellena el alfabeto con una letra y su correspondiente
        # letra códificada.
    
    # Lista de caracteres especiales y sus equivalentes en el alfabeto normal
    caracteres_especiales = {'á': 'a', 'é': 'e', 'í': 'i', 'ó': 'o', 'ú': 'u'}
    
    # Agregar caracteres especiales al diccionario de códigos
    codigo.update(caracteres_especiales)   

Crear una función de entrada "main.py" es útil para llamar a las funciones que se necesitan cuando comienza el programa. Creemos una función main.py que llame a la función crear_codigo. 

# Comienzo
def main():
    crear_codigo()

main()

Probar y depurar el código.


Para probar que el diccionario se ha creado correctamente, vamos a imprimir el diccionario completo. El programa hasta ahora tiene que verse de esta forma:

# Crear el código Atbash invirtiendo el alfabeto
def crear_codigo():
    # reversa del ALFABETO
    inversa = list(reversed(ALFABETO))
    
    for i in range(len(ALFABETO)): # Longitud de una lista
        codigo[ALFABETO[i]] = inversa[i]
        # Rellena el alfabeto con una letra y su correspondiente
        # letra códificada.

    # Lista de caracteres especiales y sus equivalentes en el alfabeto normal
    caracteres_especiales = {'á': 'a', 'é': 'e', 'í': 'i', 'ó': 'o', 'ú': 'u'}

    # Agregar caracteres especiales al diccionario de códigos
    codigo.update(caracteres_especiales)
    
    print(codigo)

#Estructura de datos
#Lista creada desde una cadena de texto
ALFABETO = list("abcdefghijklmnñopqrstuvwxyz")
codigo = {}

# Comienzo
def main():
    crear_codigo()

main()
Ejecuta el código para ver si el diccionario se ha creado correctamente. Deberías ver un patrón que empieza con la letra "a" emparejada con la letra "z" y la letra "b" emparejada con la letra "y" y así sucesivamente.

SALIDA:

{' ': ' ', 'a': 'z', 'b': 'y', 'c': 'x', 'd': 'w', 'e': 'v', 'f': 'u', 'g': 't',
 'h': 's', 'i': 'r', 'j': 'q', 'k': 'p', 'l': 'o', 'm': 'ñ', 'n': 'n', 'ñ': 'm',
 'o': 'l', 'p': 'k', 'q': 'j', 'r': 'i', 's': 'h', 't': 'g', 'u': 'f', 'v': 'e',
 'w': 'd', 'x': 'c', 'y': 'b', 'z': 'a', 'á': 'a', 'é': 'e', 'í': 'i', 'ó': 'o',
 'ú': 'u'}

Codificar un mensaje.


En este apartado crearemos una función que pueda tomar un texto, lo transforma y te lo devuelva cifrado. 

Empezaremos comentando el print que usamos para ver si funcionaba nuestro código.

def crear_codigo():
    # reversa del ALFABETO
    inversa = list(reversed(ALFABETO))
    
    for i in range(len(ALFABETO)): # Longitud de una lista
        codigo[ALFABETO[i]] = inversa[i]
        # Rellena el alfabeto con una letra y su correspondiente
        # letra códificada.

    # Lista de caracteres especiales y sus equivalentes en el alfabeto normal
    caracteres_especiales = {'á': 'a', 'é': 'e', 'í': 'i', 'ó': 'o', 'ú': 'u'}

    # Agregar caracteres especiales al diccionario de códigos
    codigo.update(caracteres_especiales)

    #print(codigo) 

Definiendo la función Atbash.

Vamos a crear una función para codificar un texto usando el cifrado Atbash. Empieza definiendo la función Atbash, con un parámetro llamado texto. Los parámetros te permiten pasar valores para que sean usados en las funciones. 

def atbash(texto):

Convirtiendo el texto a minúsculas.

Lo primero que necesita la función es convertir el texto que le pasemos a minúsculas. Necesitamos crear una nueva variable, la podemos llamar salida, para guardar el mensaje codificado.

def atbash(texto):
    """Codifica o decodifica una línea de texto.
    Atbash es símetrico.
    """
    texto = texto.lower() # Convierte el texto en minúsculas.
    salida = ""

Codificando el texto.

Lo próximo que haremos será codificar el texto que habremos pasado a la función. Utilizaremos un bucle for para iterar sobre cada letra del texto y convertirla en una letra codificada usando el diccionario codigo. Finalmente devolveremos el mensaje codificado.

def atbash(texto):
    """Codifica o decodifica una línea de texto.
    Atbash es símetrico.
    """
    texto = texto.lower() # Convierte el texto en minúsculas.
    salida = ""
    
    for letra in texto:
        if letra in codigo:
            salida += codigo[letra]
    
    return salida

Probar y depurar.

Ahora que tenemos la función vamos a probarla codificando algo de texto y ver que funciona. Localiza la función main() y añade una llamada a la función atbash(). Podemos pasar el texto "Codificar es fácil"

Si todo ha ido bien la salida del programa sería:

>>> %Run main.py
xlwrurxzi vh uaxro 

Creando un menú.


Ahora lo que haremos será crear un menú para que el usuario pueda elegir que es lo que quiere hacer. Empezaremos creando una función llamada "menu":

def menu():
    """Crea un menú basado en texto."""
Tu menú necesita un bucle que pregunte al usuario que es lo que quiere hacer hasta que introduzca una opción válida. Tenemos que definir una variable llamada "elección" que de momento no tendrá ningún valor.  Esto permitirá al bucle while ejecutar su primer bucle.

def menu():
    """Crea un menú basado en texto."""
    eleccion = "" # El bucle comienza con una elección no válida.

Usando un bucle while para obtener lo que teclee el usuario.

Lo que queremos es que el bucle se rompa solamente cuando se haya escogido una opción válida. Queremos que el bucle while se siga ejecutando mientras no se escoja una opción válida.

Puedes usar un bucle while para ejecutar un trozo de código mientras una condición se verdadera (True). En nuestro caso vamos a definir que mientras que el usuario no elija la letra "d" o la "f" el bucle se continuará ejecutando. Lo que pretendemos es que si se pulsa una "c" se codifique/decodifique un mensaje que habremos guardado en un archivo de texto y si pulsa una "f" se muestre un gráfico con la frecuencia de las letras en ese mensaje. 

def menu():
    """Crea un menú basado en texto."""
    eleccion = ""
    
    while elección != 'c' and eleccion != 'f':
        eleccion = input('''Por favor, introduce c to codificar/decodificar texto,
o f para realizar un análisis de frecuencias: ''')

Una vez que el usuario ha introducido una elección correcta, el bucle finaliza. A continuación crearemos una sentencia 'if' que ejecutará la función atbash si el usuario introduce una 'c'

Tu decidirás que sucederá cuando el usuario introduzca una 'f' en un paso posterior.

Debajo de la última línea (¡asegurándote de tener todavía una sangría!), escribe:

def menu():
    """Crea un menú basado en texto."""
    eleccion = ""
    
    while eleccion != 'c' and eleccion != 'f':
        eleccion = input('''Por favor, introduce c to codificar/decodificar texto,
o f para realizar un análisis de frecuencias: ''')
        
        if eleccion == 'c':
            print("Pasando tu mensaje a través del cifrado...")
            mensaje = "Mi mensaje secreto"
            codigo = atbash(mensaje)
            print(codigo)

Cambia la cadena que dice "Mi mensaje secreto" por el texto que tu quieras. Este texto será el que se codifique o decodifique.

Al final de la función main() teclea menu() para llamar a la función cuando se ejecute el programa:

# Comienzo
def main():
    crear_codigo()
    #print(atbash("Codificar es fácil"))
    menu()
Ejecuta el código. Teclea 'c' y presiona Enter para codificar tu mensaje.

SALIDA.

>>> %Run main.py
Por favor, introduce c to codificar/decodificar texto,
o f para realizar un análisis de frecuencias: 
c
Pasando tu mensaje a través del cifrado...
ñr ñvnhzqv hvxivgl
En el próximo paso usaremos la función atbash para codificar el contenido de un archivo de texto.

Codificar texto desde un archivo.


Cargar el texto desde un archivo es más eficiente que teclear o copiar un gran texto para pasárselo al programa. Vamos a crear la función obtener_texto(). Esta función tiene un argumento que es el nombre del archivo a cargar. Usamos este argumento para cargar el archivo y pasárselo a la variable texto, que una vez quitados los saltos de línea es devuelto por la función. El código quedaría tal que así:

def obtener_texto(nombre_archivo):
    """Obtiene y devuelve texto desde un archivo."""
    with open(nombre_archivo) as f:
        texto = f.read().replace('\n', " ") # tenemos que eliminar los saltos de línea.
        return texto
La función en el menú necesita codificar el mensaje secreto desde un archivo de texto. Reemplaza tu mensaje secreto con la función obtener_texto(). Así quedaría el código:

def menu():
    """Crea un menú basado en texto."""
    eleccion = ""
    
    while eleccion != 'c' and eleccion != 'f':
        eleccion = input('''Por favor, introduce c to codificar/decodificar texto,
o f para realizar un análisis de frecuencias: \n''')
        
        if eleccion == 'c':
            print("Pasando tu mensaje a través del cifrado...")
            mensaje = obtener_texto('datos.txt')
            codigo = atbash(mensaje)
            print(codigo)
Crea en el mismo directorio un archivo llamado datos.txt, edítalo e introduce en el tu propio mensaje secreto.

Ejecuta tu código para ver si se muestra el mensaje codificado después de pulsar la letra 'c' en el menú.

SALIDA.

>>> %Run main.py
Por favor, introduce c para codificar/decodificar texto,
o f para realizar un análisis de frecuencias: 
c
Pasando tu mensaje a través del cifrado...
vhgv vh fn ñvnhzqv wv kifvyz kziz evi hr vo xlwrurxzwli wv gvcglh ufnxrlnz xliivxgzñvngv

Decodificando el mensaje.


El cifrado atbash codifica el mensaje utilizando el reverso de las letras del alfabeto, como ya hemos visto. Esto significa que exactamente el mismo código que hemos utilizado para codificar el mensaje vale para decodificarlo. Puedes probarlo, usando el código encriptado. Copialo y pégalo en el archivo datos.txt y vuelve a ejecutar el código de nuevo.

>>> %Run main.py
Por favor, introduce c para codificar/decodificar texto,
o f para realizar un análisis de frecuencias: 
c
Pasando tu mensaje a través del cifrado...
este es un mensaje de prueba para ver si el codificador de textos funciona correctamente 

Se mostrará la versión descodificada, es decir tu mensaje original.


Crear un analizador de frecuencias.


En este paso vamos a crear una función que nos muestre la frecuencia con la que las letras del alfabeto aparecen en tu texto.

El análisis de frecuencias mide con que frecuencia algo aparece de esta forma podrás buscar patrones de ocurrencia en esos datos. Es posible descifrar cifrados monoalfabeticos (si conoces el idioma en el que se encuentra el mensaje) observando la frecuencia con la que aparece cada letra y comparándolo con las letras más utilizadas en ese idioma. Lo explicaremos en más detalle más adelante.

Empezaremos creando una función que tome tu texto y cuente el número de veces que cada letra del alfabeto aparece en él y luego convierta ese número de apariciones en un porcentaje para que puedas compararlo con la frecuencia de las letras en español.

Vamos al lio. Define una función llamada frecuencia que tome como argumento tu texto, luego convierta el mensaje en minúsculas y lo pase todo a una lista.

def frecuencia(texto):
    """Calcula la frecuencia de las letras en un texto"""
    texto = list(texto.lower())
Crea un diccionario llamado frec donde vamos a almacenar el número de veces que aparece cada letra en el texto. Luego recorreremos el texto a través de un bucle for y añadiremos al diccionario el número de veces que aparece cada letra. Para posteriormente calcular las frecuencias almacenamos el número total de palabras en la variable letras_totales.

def frecuencia(texto):
    """Calcula la frecuencia de las letras en un texto"""
    texto = list(texto.lower())
    
    frec = {}
    
    for letra in texto:
        frec[letra] = frec.get(letra, 0) + 1
Por ejemplo si la primera letra del texto fuese una 'a' el programa busca si existe una clave en el diccionario con la 'a'. Usamos el método get ya que si existe la clave en el diccionario nos devuelve su valor y si no es así, porque fuese la primera aparición, nos devolverá el número cero en vez de un error.
Cada vez que aparece la letra en el texto le sumamos uno a su valor.

Una vez que ya tengamos el número total de veces que cada letra aparece en el mensaje vamos a calcular su frecuencia  a través de un bucle. No queremos que se tengan en cuenta los espacios en blanco para el calculo de las frecuencias, así que añadimos el condicional if para añadir solo las letras. Añade un return a la función para que podamos usar el diccionario con las frecuencias en cualquier parte del código.

def frecuencia(texto):
    """Calcula la frecuencia de las letras en un texto"""
    texto = list(texto.lower())
    
    frec = {}
        
    for letra in texto:
        if letra != " ":
            frec[letra] = frec.get(letra, 0) + 1
    
    letras_totales = sum(frec.values()) #numero total de letras sin espacios en blanco
        
    for letra in frec:
        frec[letra] = frec[letra] / letras_totales * 100  # Convierte números en porcentajes.
    
    return frec

Extendiendo el menú para incluir la opción 'f'.


Ahora que tenemos una función que calcula la frecuencia de las letras en el mensaje, necesitamos un enlace para ejecutarla a través del menú. Hasta ahora el usuario solo podía escoger la opción 'c' para codificar o decodificar un mensaje. Si tecleaba la letra 'f' no ocurría nada. Vamos a añadir esta opción para mostrar un análisis de frecuencias con la función que hemos creado anteriormente.

Debajo del comando if que verifica si el usuario ha pulsado una 'c',  necesitamos añadir el comando elif para que el usuario pueda escoger la opción 'f' para realizar un análisis de frecuencias e imprimirlas.

Deja una línea en blanco después de la sentencia 'if ' y añade el siguiente código:

def menu():
    """Crea un menú basado en texto."""
    eleccion = ""
    
    while eleccion != 'c' and eleccion != 'f':
        eleccion = input('''Por favor, introduce c para codificar/decodificar texto,
o f para realizar un análisis de frecuencias: \n''')
        
        if eleccion == 'c':
            print("Pasando tu mensaje a través del cifrado...")
            # mensaje = "Mi mensaje secreto"
            mensaje = obtener_texto('datos.txt')
            codigo = atbash(mensaje)
            print(codigo)
            
        elif eleccion == 'f':
            mensaje = obtener_texto('datos.txt')
            codigo = atbash(mensaje)
            mensaje_frec = frecuencia(codigo)
            print(mensaje_frec)
Guarda y ejecuta el código. Presiona la tecla 'f' y deberías ver en la consola una relación de las frecuencias con la que las letras aparecen en tu mensaje ya codificado. Los valores que se muestren seguramente serán diferentes de los mostrados aquí.

>>> %Run main.py
Por favor, introduce c para codificar/decodificar texto,
o f para realizar un análisis de frecuencias: 
f
{'v': 18.91891891891892, 'h': 6.756756756756757, 'g': 6.756756756756757,
 'f': 4.054054054054054, 'n': 6.756756756756757, 'ñ': 2.7027027027027026,
 'z': 9.45945945945946, 'q': 1.3513513513513513, 'w': 5.405405405405405,
 'k': 2.7027027027027026, 'i': 8.108108108108109, 'y': 1.3513513513513513,
 'e': 1.3513513513513513, 'r': 5.405405405405405, 'o': 1.3513513513513513,
 'x': 6.756756756756757, 'l': 6.756756756756757, 'u': 2.7027027027027026,
 'c': 1.3513513513513513}


Analizando la frecuencia mediante un gráfico.


Lo primero que tenemos que hacer es instalar la librería Pygal para mostrar el gráfico de las frecuencias. 

pip3 install pygal

En todos los idiomas, cada letra de su alfabeto tiene una "personalidad" o un conjunto de rasgos cuando se usa en ese idioma. Una de las características que tiene una letra en cualquier idioma es la frecuencia con la que aparece. El análisis de frecuencia es el método para descifrar códigos observando la frecuencia con la que se utilizan las letras en el idioma del código y comparándolo con la frecuencia con la que aparecen letras codificadas en un mensaje. En español, la letra e es la letra más utilizada (aparece el 13,68% de las veces), seguida de la 'a' (el 12,53 %). La letra menos utilizada es la w.

En el menú no necesitaremos más la línea print(mensaje_frec) así que lo comentaremos para que se ignore cuando ejecutemos el código. 

 elif eleccion == 'f':
            mensaje = obtener_texto('datos.txt')
            codigo = atbash(mensaje)
            mensaje_frec = frecuencia(codigo)
            # print(mensaje_frec)

Crear el gráfico con las frecuencias.

Vamos a definir una nueva función llamada crear_grafico(). Esta función tendrá dos parámetros, texto y lenguaje. El gráfico será un gráfico de barras que tendrá por título "análisis de frecuencias" y las etiquetas para el eje-x serán las claves del diccionario. (a,b,c...y,z)

El diccionario de frecuencias lo pasaremos posteriormente a la función cuando se la llame a través del parámetro texto.

Primeramente después de haberlo instalado importamos al principio del programa el tipo de gráfico que vamos a crear.

from pygal import Bar

#...
def crear_grafico(texto, lenguaje):
    """Crea el gráfico de frecuencias"""
    grafico = Bar(width=800, height=400, title="Análisis de Frecuencias",
                  x_labels=list(lenguaje.keys()))

Etiquetaremos el gráfico usando la frecuencia con la que las letras aparecen en el mensaje codificado y las frecuencias conocidas de las letras en el idioma español. Estos datos los pasaremos a través de los parámetros texto y lenguaje. 

Para pasar la frecuencia con la que las letras aparecen en un texto genérico en el idioma español, crearemos una variable llamada "spanish" y a través de un diccionario pasaremos las frecuencias.

Tenemos que solucionar un problema. A partir de la versión 3.7 de Python los datos en un diccionario se guardan en el orden en el que se han introducido y aunque no fuera así para poder representar correctamente el gráfico tenemos que emparejar las frecuencias de las letras en el mensaje codificado, con las frecuencias de las letras en el idioma. Es decir si la primera letra de nuestro texto codificado es una 'e' y las segunda una "s" pues tendremos que ordenar todas alfabéticamente y hacer coincidir sus valores con los del diccionario del lenguaje, que están ordenados alfabéticamente.

Para ello creamos una lista llamada "valores" que recogerá las frecuencias de las letras del mensaje codificado pero ordenadas alfabéticamente desde la 'a' a la 'z'. A través de un bucle for recorremos las letras "a,b,c...z" y si la letra existe pasamos su valor a la lista y sino pues sustituimos su valor con un cero.

def crear_grafico(texto, lenguaje):
    """Crea el gráfico de frecuencias"""
    grafico = Bar(width=800, height=400, title="Análisis de Frecuencias",
                  x_labels=list(lenguaje.keys()))
    # Etiquetas de las frecuencias para el mensaje codificado.
    valores = []
    for i in lenguaje:
        valores.append(texto.get(i,0))
    grafico.add('Mensaje objetivo', valores)
    # Etiquetas de las frecuencias de las letras en el idioma español
    grafico.add('Lenguaje', list(lenguaje.values()))
    
    grafico.render_to_file('grafico.svg')


# Estructura de datos
# Lista creada desde una cadena de texto
ALFABETO = list(" abcdefghijklmnñopqrstuvwxyz ")
codigo = {}
spanish = {'a': 12.53, 'b': 1.42, 'c': 4.68, 'd': 5.86, 'e': 13.68, 'f': 0.69, 'g': 1.01,
           'h': 0.70, 'i': 6.25, 'j': 0.44, 'k': 0.02, 'l': 4.97, 'm': 3.15, 'n': 6.71,
           'ñ': 0.31, 'o': 8.68, 'p': 2.51, 'q': 0.88, 'r': 6.97, 's': 7.98, 't': 4.63,
           'u': 3.93, 'v': 0.90, 'w': 0.01, 'x': 0.22, 'y': 0.90, 'z': 0.52}

LLamando a la función que representa las frecuencias.

Busca la secuencia elif dentro de la función menu(). Añade una línea de código para utilizar las frecuencias del idioma español y otra para crear el gráfico.

elif eleccion == 'f':
            mensaje = obtener_texto('datos.txt')
            codigo = atbash(mensaje)
            mensaje_frec = frecuencia(codigo)
            # print(mensaje_frec)
            lang_freq = spanish  # Importamos la frecuencia de la letras en español
            # LLama a la función que crea el gráfico
            crear_grafico(mensaje_frec, lang_freq)

Ejecuta el código y puedes ver el archivo del gráfico usando cualquier navegador para abrirlo:

grafico de frecuencias



Analiza el gráfico de frecuencias. 

El gráfico que se ha producido muestra la frecuencia de letras en el idioma español, etiquetado como "Lenguaje". Puedes ver que la letra "e" es la letra más utilizada en el idioma español porque tiene la barra más alta para todos los valores de idioma.

El gráfico de frecuencias también lista la frecuencia de letras en tu mensaje codificado, etiquetado como "Mensaje objetivo". Para averiguar qué codificación se ha utilizado para este mensaje, puedes comparar las barras que muestran el idioma español con las barras en el mensaje codificado. La barra más alta en el texto del mensaje codificado probablemente será una "e". La segunda letra más alta probablemente será una "a", ya que es la siguiente letra más popular.

Los descifradores pueden utilizar la frecuencia de letras para determinar el tipo de codificación que se ha utilizado en el mensaje. Pueden utilizar el método de ensayo y error para predecir qué letra podría representar usando el gráfico como guía.

No obstante ten en cuenta que tu mensaje es muy pequeño lo que dificulta el descifrarlo mediante el análisis de frecuencias. Sin embargo todo se normaliza si codificas un texto lo suficientemente largo.

Puedes encontrar el código de este post en este enlace de Github.

No hay comentarios:

Publicar un comentario