Curso de introducción a la programación con Python¶

    Autor: Luis Fernando Apáez Álvarez
    -Curso PyM-
    Tarea 6: Cifrado César
    Fecha de Entrega: 21 de Agosto del 2022
    SOLUCIÓN

Contenido¶

  • Introducción
  • Decifrando el mensaje
  • Adicional

Descripción: En esta tarea utilizaremos el concepto de funciones para implementar el cifrado césar en Python. Con ello lograremos convertir palabras que tienen sentido y significado, a palabras que a primera vista no tienen sentido y significado. Lo anterior representaría una especie de código de lenguaje que no puede ser entendido, en primera instancia, por el resto de personas que no conocen dicho código. Por ejemplo, podemos convertir la palabra cifrado a la palabra djgsbep, donde ésta última ya no es entendible, sin embargo, para alguien que conozca nuestro código de lenguaje, sabra cómo decifrar el mensaje. Puedes indagar más sobre criptografía o, en particular, sobre el cifrado césar, accediendo a los siguientes links:

  • Criptografía
  • Cifrado César


(Tiempo estimado: 50 minutos)



Introducción ¶

La parte de funciones de está tarea estará dedicada a la criptografía. Veremos el cifrado césar y su implementación en Python.

Este cifrado es de los más antiguos y, actualmente, poco seguros. Consiste en trabajar con un alfabeto desplazado una cierta longitud. Por ejemplo, podemos considerar el alfabeto desplazado en un letra de tal manera que:

  • a pasa a ser la b en nuestro nuevo alfabeto;
  • b pasa a ser la c en nuestro nuevo alfabeto;
  • c pasa a ser la d en nuestro nuevo alfabeto;
  • d pasa a ser la e en nuestro nuevo alfabeto;
  • e pasa a ser la f en nuestro nuevo alfabeto;

etcétera. De tal manera, si deseamos escribir la palabra cifrado con nuestro nuevo alfabeto obtendríamos la palabra djgsbep.

Para ello, lo primero que haremos será preguntarle al usuario la palabra que desea cifrar y crearemos una lista con las palabras del alfabeto:

In [2]:
# 1: pedimos al usuario que ingrese la palabra que desea cifrar

palabra = input("Ingrese su palabra: ")

# creamos una lista con las letras del alfabeto
alfabeto = ['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']
Ingrese su palabra: cifrado

Ahora, buscamos recorrer una vez (o en longitud 1) las letras del alfabeto original para así poder escribir cifrado como la palabra djgsbep. Lo que haremos será:

In [3]:
# 2: Obtenemos los indices de las letras de la 
# palabra que ingreso el usuario, respecto a la
# lista alfabeto

for letra in palabra:
    print(alfabeto.index(letra))
2
8
5
18
0
3
15

Después, como queremos recorrer nuestro alfabeto en una posición (o en longitud 1), entonces utilizaremos los índices anteriores y les sumaremos una unidad:

In [5]:
# Los siguientes indices corresponde a las
# posiciones de las letras de la palabra cifrado
# Por ejemplo, los siguientes indices
# corresponden a las letras de la palabra
# djgsbep
for letra in palabra:
    print(alfabeto.index(letra) + 1)
3
9
6
19
1
4
16
In [6]:
# Usando los indices anteriores podemos obtener
# la letra correspondiente dentro de nuestro alfabeto.

# Accederemos a las letras correspondientes
# a dichos indices dentro de alfabeto
for letra in palabra:
    print(alfabeto[alfabeto.index(letra) + 1])
d
j
g
s
b
e
p

Con lo cual ya hemos conseguido cifrar la palabra deseada. Podemos unir las letras anteriores para formar una solo palabra:

In [8]:
# Nos auxiliamos de una cadena vacia
palabra_cifrada = ""

for letra in palabra:
    # unimos o concatenamos cada letra
    palabra_cifrada += alfabeto[alfabeto.index(letra) + 1]

# Veamos la palabra ya unida
print(palabra_cifrada)
djgsbep

Continuando, ahora debemos implementar el código para poder manejar palabras que contengan la letra z, pues, por ejemplo, veamos qué ocurre con palabras como zoom:

In [9]:
# El usuario ingresa su palabra y la convertirmos
# a  minusculas para evitar errores pues nuestro
# alfabeto fue definido con minusculas
palabra = input("Ingrese su palabra: ")

# Cadena vacia que contendra la palabra cifrada
palabra_cifrada = ""

for letra in palabra:
    # unimos o concatenamos cada letra
    palabra_cifrada += alfabeto[alfabeto.index(letra) + 1]

# Veamos la palabra ya unida
print(palabra_cifrada)
Ingrese su palabra: zoom
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Input In [9], in <cell line: 7>()
      6 # Realizamos el cifrado
      7 for letra in palabra:
----> 8     print(alfabeto[alfabeto.index(letra) + 1])

IndexError: list index out of range

pues, como la z está en la última posición del alfabeto, entonces alfabeto.index("z") + 1 excede los índices que maneja la lista alfabeto. Para solucionar este problema escribimos:

In [10]:
# creamos una lista con las letras del alfabeto
alfabeto = ['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']

# El usuario ingresa su palabra y la convertirmos
# a  minusculas para evitar errores pues nuestro
# alfabeto fue definido con minusculas
palabra = input("Ingrese su palabra: ").lower()

# Cadena vacia que contendra la palabra cifrada
palabra_cifrada = ""

for letra in palabra:
    # para el caso en que la letra sea la z:
    if alfabeto.index(letra) == len(alfabeto) - 1:
        # agregaremos la primer letra del
        # alfabeto (la a) la cual tiene indice 0
        palabra_cifrada += alfabeto[0]
    else:
        # continuamos uniendo cada letra
        palabra_cifrada += alfabeto[alfabeto.index(letra) + 1]

# Veamos la palabra ya unida
print(palabra_cifrada)
Ingrese su palabra: zoom
appn

Lo que deberás hacer será considerar el código de la celda anterior e implementarlo en una función con las siguientes especificaciones:

  1. Deberás colocar el tipo de retorno esperado.
  2. Deberás agregar una breve descripción de lo que hace tu función.
  3. Tu función deberá recibir un solo parámetro, y deberá retornar la cadena de texto de la palabra ingresada a tu función pero ahora cifrada. Por ejemplo

print(tu_funcion("Mundo"))

Salida:

nvñep

In [2]:
# Escribe aqui la definicion de la funcion
# que se te pide:

# Lo siguiente solo es una idea, pudiste haber
# definido tu funcion de otra manera
# --------------------------------------------------
# --------------------------------------------------

def cifrado(palabra) -> str:
    """Función de un parámetro que cifra la 
    palabra ingresada recorriendo el alfabeto en una posición.
    Por ejemplo:
    * a se convierte en b,
    * f se convierte en g,
    * z se convierte en a"""
    # creamos una lista con las letras del alfabeto
    alfabeto = ['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']
    # Convertimos la palabra ingresada a minusculas
    palabra = palabra.lower()
    # Cadena vacia que contendra la palabra cifrada
    palabra_cifrada = ""
    # Proceso de cifrado:
    for letra in palabra:
        # para el caso en que la letra sea la z:
        if alfabeto.index(letra) == len(alfabeto) - 1:
            # agregaremos la primer letra del
            # alfabeto (la a) la cual tiene indice 0
            palabra_cifrada += alfabeto[0]
        else:
            # continuamos uniendo cada letra
            palabra_cifrada += alfabeto[alfabeto.index(letra) + 1]
    # retornamos la palabra cifrada
    return palabra_cifrada

# Probamos la funcion:
print(cifrado("Mundo"))
print(cifrado("Zoom"))
print(cifrado("CIFRADO"))
nvñep
appn
djgsbep

Decifrando el mensaje ¶

Lo que realizaremos ahora será decifrar el mensaje que hemos cifrado previamente. Esto es, si tenemos la palabra nvñep, ahora decifraremos el mensaje para obtener la palabra mundo

Para ello deberás implementar el procedimiento inverso de lo que hicimos antes:

In [1]:
# creamos una lista con las letras del alfabeto
alfabeto = ['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']

# El usuario ingresa su palabra y la convertirmos
# a  minusculas para evitar errores pues nuestro
# alfabeto fue definido con minusculas
palabra_a_decifrar = input("Ingrese su palabra: ").lower()

# Cadena vacia que contendra la palabra DEcifrada
palabra_decifrada = ""

for letra in palabra_a_decifrar:
    # unimos las letras
    palabra_decifrada += alfabeto[alfabeto.index(letra) - 1]

# Veamos la palabra ya unida
print(palabra_decifrada)
Ingrese su palabra: nvñep
mundo

Vemos que el caso de decifrar es más sencillo. Por ejemplo, si consideramos la letra z que tiene el último índice en nuestra lista, al considerar la letra en la posición anterior obtenemos, sin problema alguno, la letra y. Para el caso de la a que tiene el índice 0, al considerar su índice menos el uno obtenemos el número -1, pero sabemos que alfabeto[-1] nos permite acceder al último elemento de nuestra lista, por lo cual, la "letra previa" a la letra a es la letra z.

Lo que deberás hacer será considerar el código de la celda de código anterior e implementarlo en una función con las siguientes especificaciones:

  1. Deberás colocar el tipo de retorno esperado.
  2. Deberás agregar una breve descripción de lo que hace tu función.
  3. Tu función deberá recibir un solo parámetro, y deberá retornar la cadena de texto de la palabra ingresada a tu función pero ahora decifrada.
In [22]:
# Escribe aqui la definicion de la funcion
# que se te pide:

# Lo siguiente solo es una idea, pudiste haber
# definido tu funcion de otra manera
# --------------------------------------------------
# --------------------------------------------------

def decifrado(palabra) -> str:
    """Función de un parámetro que DEcifra la 
    palabra ingresada recorriendo hacia atrás 
    el alfabeto en una posición.
    Por ejemplo:
    * a se convierte en z,
    * f se convierte en e,
    * z se convierte en y"""
    # creamos una lista con las letras del alfabeto
    alfabeto = ['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']
    # Convertimos la palabra ingresada a minusculas
    palabra_a_decifrar = palabra.lower()
    # Cadena vacia que contendra la palabra cifrada
    palabra_decifrada = ""
    # Proceso de decifrado:
    for letra in palabra_a_decifrar:
        # unimos las letras
        palabra_decifrada += alfabeto[alfabeto.index(letra) - 1]
    # retornamos la palabra decifrada
    return palabra_decifrada

# Probamos la funcion:
print(decifrado("nvñep"))
print(decifrado("appn"))
print(decifrado("djgsbep"))
mundo
zoom
cifrado

Adicional ¶

Recordemos que, da una frase (más de una palabra), podemos crear una lista de todas las palabras que la componen utilizando el método split(). Por ejemplo:

In [7]:
# Frase
msj = "Hola Mundo, Bienvenidos"

# Separamos la cadena anterior por espacios en blanco
lista_de_palabras = msj.split(" ")
print(lista_de_palabras)
['Hola', 'Mundo,', 'Bienvenidos']

Con base en lo anterior, podemos crear una función para cifrar toda una frase, para lo cual utilizaremos la función que definimos antes cifrado():

In [14]:
# Creamos una funcion para cifrar todo un mensaje o frase
def cifrado_frase(msj) -> str:
    """Función para cifrar el mensaje ingresado
    en el valor del parámetro msj. La función
    retornará el mensaje total cifrado"""
    
    # Dividimos las palabras de msj
    lista_palabras = msj.lower().split(" ")
    
    # Ciframos cada una de las palabras de dicha lista
    # para lo cual utilizaremos la funcion cifrado():
    
    # creamos una cadena vacia para almacenar la frase
    # cifrada
    msj_cifrado = ""
    for palabra in lista_palabras:
        # Manejamos los casos en que nuestras palabras
        # tengan al final comas o puntos
        if palabra[-1] == ",":
            msj_cifrado += cifrado(palabra[:-1]) + ", "
        elif palabra[-1] == ".":
            msj_cifrado += cifrado(palabra[:-1]) + ". "
        # Para el resto agregaremos espacios en blanco
        # despues de la concatenacion
        else:
            msj_cifrado += cifrado(palabra) + " "
    # Retornamos el mensaje cifrado
    return msj_cifrado
In [19]:
# Podemos a prueba nuestra funcion
print(cifrado_frase("Hola Mundo, Bienvenidos"))
print(cifrado_frase("Este mensaje no se va a entender"))
print(cifrado_frase("Hola. Mucho gusto."))
ipmb nvñep, cjfñwfñjept 
ftuf nfñtbkf ñp tf wb b fñufñefs 
ipmb. nvdip hvtup. 

Lo que haremos ahora será definir una función para decifrar el mensaje:

In [20]:
# Creamos una funcion para decifrar todo un mensaje o frase
def decifrado_frase(msj) -> str:
    """Función para decifrar el mensaje ingresado
    en el valor del parámetro msj. La función
    retornará el mensaje total decifrado"""
    
    # Dividimos las palabras de msj
    lista_palabras = msj.lower().split(" ")
    
    # Deiframos cada una de las palabras de dicha lista
    # para lo cual utilizaremos la funcion decifrado():
    
    # creamos una cadena vacia para almacenar la frase
    # decifrada
    msj_decifrado = ""
    for palabra in lista_palabras:
        # Manejamos los casos en que nuestras palabras
        # tengan al final comas o puntos
        if palabra[-1] == ",":
            msj_decifrado += decifrado(palabra[:-1]) + ", "
        elif palabra[-1] == ".":
            msj_decifrado += decifrado(palabra[:-1]) + ". "
        # Para el resto agregaremos espacios en blanco
        # despues de la concatenacion
        else:
            msj_decifrado += decifrado(palabra) + " "
    # Retornamos el mensaje decifrado
    return msj_decifrado
In [23]:
# Podemos a prueba nuestra funcion
print(decifrado_frase("ipmb nvñep, cjfñwfñjept"))
print(decifrado_frase("ftuf nfñtbkf ñp tf wb b fñufñefs"))
print(decifrado_frase("ipmb. nvdip hvtup."))
hola mundo, bienvenidos 
este mensaje no se va a entender 
hola. mucho gusto. 

In [ ]:
# Decifra este mensaje: "rvf cvfñp rvf mmfhbtuf ibtub brvj, hsbdjbt."