martes, 3 de julio de 2018

Encriptar y desencriptar en Python con la clave MURCIELAGO

Reto: Encriptación

Encriptar y desencriptar frases usando la clave MURCIELAGO. Cada letra de la frase que coincida con alguna letra de la clave se sustituye por un número siguiendo el orden 0123456789.



Los Scouts utilizan este sistema de encriptación para enviarse mensajes. Cada caracter del mensaje se compara con la clave MURCIELAGO. Si el caracter se encuentra entre las letras de la clave se sustituye por un digito numérico siguiendo el orden 0123456789. Si la letra no está en la clave simplemente se deja como está.

MURCIELAGO
0123456789

Por ejemplo, veamos en que se convierte la palabra abecedario.

ABECEDARIO
7B535D7249


Método 1

Con input solicitamos la frase a encriptar y la convertimos en mayúsculas. Si el usuario no da una frase y pulsa Enter se tomará como frase la palabra HOLA. Las funciones que usamos para encriptar y desencriptar usan replace que actúa sobre un string reemplazando un caracter por otro. Usamos muchas variables para ir reemplazando los caracteres, otra solución hubiera sido usar un bucle.

def encriptar(y):
  x1=y.replace('M', '0')
  x2=x1.replace('U', '1')
  x3=x2.replace('R', '2')
  x4=x3.replace('C', '3')
  x5=x4.replace('I', '4')
  x6=x5.replace('E', '5')
  x7=x6.replace('L', '6')
  x8=x7.replace('A', '7')
  x9=x8.replace('G', '8')
  x0=x9.replace('O', '9')
  return x0

def desencriptar(p):
  x1=p.replace('0', 'M')
  x2=x1.replace('1', 'U')
  x3=x2.replace('2', 'R')
  x4=x3.replace('3', 'C')
  x5=x4.replace('4', 'I')
  x6=x5.replace('5', 'E')
  x7=x6.replace('6', 'L')
  x8=x7.replace('7', 'A')
  x9=x8.replace('8', 'G')
  x0=x9.replace('9', 'O')
  return x0

y= input("¿Qué frase quieres encriptar?").upper() or 'HOLA'
z=encriptar(y)
print(z)
print(desencriptar(z))


Método 2

En este caso usamos listas. Primero obtenemos la frase a encriptar con un input, lo pasamos a minúsculas. Si se pulsa Enter se toma como frase la palabra 'hola'. La cadena x se convierte en la lista y. Copiamos el valor de la lista y en otras dos listas w y z que al estar fuera de las funciones serán variables globales.
Las funciones usan bucles for que recorren los elementos de la lista y van sustituyendo caracteres en una dirección al encriptar y al contrario al desencriptar. Al final de cada función convertimos la lista resultante en una cadena alfanumérica usando joint.



x= input("¿Que frase quieres encriptar?").lower() or 'hola'
y= list(x)
w=z=y

def encriptar(p):
  for i in range(len(p)):
    if p[i] == 'm':
      z[i] = '0'
    elif p[i] == 'u':
      z[i] = '1'
    elif p[i] == 'r':
      z[i] = '2'
    elif p[i] == 'c':
      z[i] = '3'
    elif p[i] == 'i':
      z[i] = '4'
    elif p[i] == 'e':
      z[i] = '5'
    elif p[i] == 'l':
      z[i] = '6'
    elif p[i] == 'a':
      z[i] = '7'
    elif p[i] == 'g':
      z[i] = '8'
    elif p[i] == 'o':
      z[i] = '9'
  print(''.join(z))

def desencriptar(q):
  for i in range(len(q)):
    if q[i] == '0':
      w[i] = 'm'  
    elif q[i] == '1':
      w[i] = 'u'
    elif q[i] == '2':
      w[i] = 'r'
    elif q[i] == '3':
      w[i] = 'c'
    elif q[i] == '4':
      w[i] = 'i'
    elif q[i] == '5':
      w[i] = 'e'
    elif q[i] == '6':
      w[i] = 'l'
    elif q[i] == '7':
      w[i] = 'a'
    elif q[i] == '8':
      w[i] = 'g'
    elif q[i] == '9':
      w[i] = 'o'
  print(''.join(w))

encriptar(y)
desencriptar(z)


Método 3

En este caso no usamos una conversión carácter a carácter sino que, en las funciones, mediante un bucle for, recorremos todos los elementos de la lista.
Al encriptar si el carácter de la frase analizado está en la clave MURCIELAGO lo convertimos en un dígito numérico que se corresponde con la posición de ese carácter en la clave, comenzando a contar por cero, que es justo por donde se comienzan a contar los elementos de una lista en Python. Si el carácter analizado no está en la clave simplemente se deja como está.
Al desencriptar si detectamos que el carácter es un dígito numérico se sustituye por el carácter de la clave MURCIELAGO que ocupa ese orden, comenzando a contar por cero. Y en caso contrario se deja el carácter no numérico como está.

clave='MURCIELAGO'
codigo=list(clave)
frase=input("¿Qué frase quiere encriptar?").upper() or 'HOLA'

def encriptar(f):
  salida=''
  for i in f:
    if i in clave:
      salida+=str(codigo.index(i))
    else:
      salida+=i
  return(salida)

def desencriptar(f):
  texto=''
  for i in f:
    if i.isdigit():
      texto+=codigo[int(i)]
    else:
      texto+=i
  return(texto)

w=encriptar(frase)
print(w)
print(desencriptar(w))


Puede consultar otro post donde se utiliza un código similar al del método 3, aunque no exactamente igual. Puede verlo en el siguiente enlace.



Método 4

Creamos el diccionario d que utiliza como clave los números del cero al nueve y como valor las letras que componen la palabra 'murcielago'. Disponemos de dos funciones, una para encriptar y otra para desencriptar. Solicitamos al usuario una frase para encriptar o si pulsa Enter se tomará la palabra 'hola'. Esta entrada que capturamos con input se transforma en una lista de letras con list, y se asigna a la variable x. Llamamos a la función encriptar pasándola dos parámetros, la variable x junto al diccionario d.
La función encriptar recoge los parámetros x y d. Nos metemos en un primer bucle for que recorre para la variable i tantos valores numéricos como longitud tenga la variable x, comenzando por cero. El segundo bucle for dará a la variable j valores entre cero y nueve. Se verificará el condicional if si se cumple que la letra analizada de la palabra x es igual a la letra j-ésima de la palabra 'murcielago'. Por ejemplo, si la palabra introducida es 'hola', esto se cumplirá por primera vez cuando la letra 'o' que en 'hola' equivale a la letra de índice j=1 coincide con la letra 'o' de la palabra 'murcielago', que es la de índice j=9. Al cumplirse la condición se sustituye en la palabra x la letra i-ésima por el valor j convertido en cadena con usando str.
Las letras que no encuentren coincidencia con el código 'murcielago' no se sustituirán por números y se dejarán con la letra que tienen. La función encriptar devuelve mediante return la lista x convertida en string usando join.
La función desencriptar recibe como parámetros w y d, donde w contiene la frase ya enciptada en forma de string. Por ejemplo, en el caso de introducir 'hola', la variable w sería 'h967'. Se inicializa la lista h como lista vacía. Nos metemos en un bucle for donde la variable i tomará todos los valores de la cadena w, gracias al uso de la magnífica partícula in, que en programación con Python nos ahorra usar otro bucle par ir recorriendo todos los elementos que deseamos analizar. Dentro del bucle tenemos un condicional if que se cumple cuando el carácter i es de tipo dígito. Es ese caso, cuando se cumple la condición, lo que se hace es añadir a la lista h el elemento i-ésimo del diccionario d. Y si no se cumple la condición se añadirá a la lista h el caracter i. La función desencriptar mediante print nos muestra en pantalla la lista h convertida en string usando join.

d = {0:'m',1:'u',2:'r',3:'c',4:'i',5:'e',6:'l',7:'a',8:'g',9:'o'}
def encriptar(x,d):
  for i in range(len(x)):
    for j in range(10):
      if x[i]==d.get(j):
        x[i]=str(j)
  return ''.join(x)
def desencriptar(w,d):
  h=[]
  for i in w:
    if i.isdigit():
      h+=d[int(i)]
    else:
      h+=i
  print(''.join(h))
x=list(input("¿Qué frase quieres encriptar?").lower() or 'hola')
z=encriptar(x,d)
print(z)
desencriptar(z,d)

3 comentarios:

  1. Hola muy buna tarde, si yo necesito crear una lista, por ejemplo que 00 sea A, que 01 sea B, que 02 sea C, y asi sucesivamente hata llegar a la Z. me da error cuando son dos digitos, podrias ayudarme por favor

    ResponderEliminar
    Respuestas
    1. talvez podrias intentar convertir esos 01 02 03 y asi, en cadenas

      Eliminar
  2. Hola,

    Hemos hecho otro post en el blog que intenta solucionar tu pregunta.
    Puedes verlo en la pagina principal del blog o aquí.


    Gracias por tu pregunta.
    Un saludo.

    ResponderEliminar