Crea una implementación del cifrado afín, un antiguo sistema de cifrado creado en Oriente Medio.
El cifrado afín es un tipo de cifrado de sustitución monoalfabético. Cada carácter se asigna a su equivalente numérico, se cifra con una función matemática y luego se convierte en la letra correspondiente a su nuevo valor numérico. Aunque todos los cifrados monoalfabéticos son débiles, el cifrado afín es mucho más fuerte que el cifrado Atbash, porque tiene muchas más claves.
La función de cifrado es:
E(x) = (ai + b) mod m
Donde:
i es el índice de la letra, de 0 a la longitud del alfabeto menos 1.m es la longitud del alfabeto.
Para el alfabeto latino, m es 26.a y b son números enteros que conforman la clave de cifrado.Los valores a y m deben ser coprimos (o primos entre sí) para que el descifrado automático tenga éxito, es decir, deben tener el número 1 como su único factor común (puedes encontrar más información en el artículo de Wikipedia sobre enteros coprimos).
Si a no es coprimo con m, tu programa debe indicar que se trata de un error.
De lo contrario, debe cifrar o descifrar con la clave proporcionada.
Para los fines de este ejercicio, los dígitos son válidos como entrada, pero no se cifran.
Los espacios y los caracteres de puntuación se excluyen.
El texto cifrado se escribe en grupos de longitud fija separados por un espacio, siendo el tamaño de grupo tradicional de 5 letras.
Esto sirve para que sea más difícil adivinar el texto cifrado a partir de los límites de las palabras.
La función de descifrado es:
D(y) = (a^-1)(y - b) mod m
Donde:
y es el valor numérico de una letra cifrada, es decir, y = E(x)
a^-1 es el inverso multiplicativo modular (MMI) de a mod m
a y m son coprimos.El MMI de a es x tal que el residuo de dividir ax entre m es 1:
ax mod m = 1
Puedes encontrar más información sobre cómo hallar un inverso multiplicativo modular y qué significa en el artículo de Wikipedia relacionado.
"test" da "ybty" con la clave a = 5, b = 7
"ybty" da "test" con la clave a = 5, b = 7
"ybty" da "lqul" con la clave incorrecta a = 11, b = 7
"kqlfd jzvgy tpaet icdhm rtwly kqlon ubstx" da "thequickbrownfoxjumpsoverthelazydog" con la clave a = 19, b = 13
"test" con la clave a = 18, b = 13 es un error porque 18 y 26 no son coprimosEncontrar el MMI para a = 15:
(15 * x) mod 26 = 1(15 * 7) mod 26 = 1, es decir, 105 mod 26 = 1
7 es el MMI de 15 mod 26
A veces es necesario lanzar una excepción. Cuando lo hagas, siempre debes incluir un mensaje de error significativo que indique cuál es el origen del error. Esto hace que tu código sea más legible y ayuda mucho con la depuración. En los casos en los que sabes que el origen del error será de un tipo determinado, puedes optar por lanzar uno de los tipos de error integrados, pero aun así debes incluir un mensaje significativo.
Este ejercicio en particular requiere que uses la sentencia raise para «lanzar» un ValueError. Las pruebas solo pasarán si tanto haces raise de la exception como incluyes un mensaje con ella.
Para lanzar un ValueError con un mensaje, escribe el mensaje como un argumento del tipo exception:
raise ValueError("a and m must be coprime.")
Regístrate en Exercism para aprender y dominar Python con 17 conceptos146 ejercicios y mentoría humana real, todo gratis.