El algoritmo de Karaca

Solución en JavaScript al reto semanal n. 50 de @MoureDev

JavGuerra,

Cifrado

En este post resuelvo, en JavaScript el reto de programación consistente en desarrollar una función que es capaz de encriptar y desencriptar texto utilizando el algoritmo de encriptación de Karaca.

Descubrí esta semana, un poco tarde, los retos de programación semanales de Mouredev para 2022 y me atrajo el enunciado de este ejercicio.

Busqué información en Internet sobre el algoritmo, encontrando lo siguiente:

Make a function that encrypts a given input with these steps:
Input: “apple”
Step 1: Reverse the input: “elppa”
Step 2: Replace all vowels using the following chart:
a => 0, e => 1, i => 2, o => 3, u => 4 # “1lpp0”
Step 3: Add “aca” to the end of the word: “1lpp0aca”
Output: “1lpp0aca”
All inputs are strings, no uppercases and all output must be strings.

Y me tomé la libertad de corregir la relación entre vocales y números que, en la fuente original publicada por Furkan Karaca, en el portal de retos Edabit parece no ser correcta.

El algoritmo, sin una aparente utilidad práctica, es un buen ejercicio de programación que combina el uso de expresiones regulares, uso de arreglos y cadenas y lógica.

Entendiendo el problema

Lo que pide el ejercicio es que nuestra función debe poder codificar y decodificar un texto, en minúsculas, que le pasemos por parámetro. Este texto, lógicamente, no puede estar vacío.

Cualquier dato que le pasemos que no sea texto debe impedir la ejecución de la codificación/decodificación. La función puede devolver un error, o bien el dato original suministrado. Opto por esta segunda posibilidad.

La cadena de caracteres suministrada a la función puede tener espacios al inicio y/o al final, incluso puede contener sólo espacios, por lo que amerita limpiar la cadena, y que esta contenga algo más que sólo espacios.

La cadena no puede contener sólo números, esto equivaldría a suministrar un número entero a la función. De hecho, el algoritmo presenta un problema importante con esto. Si se le suministra un frase que contenga dígitos en el rango del mapeo de vocales (0-1-2-3-4) no realizará bien el cifrado, pues tomará estos dígitos como parte del descifrado, mostrando un galimatías. Ej. «100 horas» -> «s0r3h 001aca» -> «eaa horas».

Para saber si se puede decodificar una cadena proporcionada, es decir, para saber si está codificada con el algoritmo de Karaca, se debe cumplir que esta termine con un «aca», que contenga algún número entre el 0 y el 4, y que su longitud sea mayor que la de la cadena de control «aca». De no cumplirse esto, se entiende que la cadena que se proporciona a la función no está codificada, y entonces puede ser codificada.

Para realizar la conversión, se debe recorrer la cadena teniendo en cuenta el mapeo de vocales del enunciado (a => 0, e => 1, i => 2, o => 3, u => 4) y viceversa.

Resolución

El algoritmo de Karaca en JavaScript, atendiendo a las consideraciones anteriores, es el siguiente:

01. /**
02.  * Función en JavaScript que encripta y desencripta texto en minúsculas en 
03.  * inglés, sin números, utilizando el algoritmo de encriptación de Karaca.
04.  * @param {String} str
05.  * @returns String
06.  * @author Javier Guerra
07.  */
08. function karacaAlgorithm(str = "") {
09. 
10.    str = str ?? "";
11.
12.    if (typeof str === "string" && str.trim().length && str.match(/\D/g)) {
13.        
14.        str = str.trim().toLowerCase().split("").reverse().join("");
15.
16.        const vowels = "aeiou".split("");
17.        const control = "aca";
18.
19.        if (
20.            str.startsWith(control) &&
21.            str.match(/\d/g) &&
22.            str.length > control.length
23.        ) {
24.            // decode
25.            str = str.slice(control.length);
26.            vowels.forEach((chr, i) => {
27.                if (str.includes(i)) str = str.replaceAll(i, chr);
28.            });
29.        } else {
30.            // encode
31.            vowels.forEach((chr, i) => {
32.                if (str.includes(chr)) str = str.replaceAll(chr, i);
33.            });
34.            str += control;
35.        }
36.    }
37.
38.    return str.toString();
39. }

En la línea 8, con el valor por defecto "" del parámetro se evita el error si llamemos a la función sin ningún parámetro, devolviendo una cadena vacía.

en la línea 10 se comprueba que el parámetro recibido no está colando un valor null o undefined con el operador coalescente nulo (??).

En la línea 12 se comprueba que el dato recibido es una cadena, que tiene al menos un carácter, y cuenta con alguna consonante. De no ser así, se devuelve el parámetro recibido.

En la línea 14 se realizan varias conversiones al parámetro recibido: se limpian los espacios iniciales y/o finales, se pasa la cadena a minúsculas, y se invierte la cadena. Esto último se hace mediante la concatenación de varios métodos: split, para convertir la cadena en un arreglo, reverse para invertir el orden del contenido del arreglo y join para unir el contenido del arreglo en una cadena.

Las líneas 16 y 17 definen las variables que usaremos en el algoritmo.

En la comprobación de las líneas de la 19 a la 23 se decide si se va a decodificar la cadena recibida, es decir, si se cumple que la cadena termina en «aca», contiene algún dígito y su longitud es mayor que la longitud de «aca». Si es así, se lleva a cabo la codificación a partir de la línea 25. en caso contrario, se lleva a cabo la codificación a partir de la línea 31.

Para la decodificación, primero se elimina el control «aca» y luego se recorre el arreglo de vocales con forEach, de tal forma que si alguno de los elementos del arreglo es encontrado en la cadena a decodificar, este se sustituye por la vocal correspondiente.

Para la codificación se lleva a cabo el proceso contrario. Al recorrer el arreglo de vocales, se sustituye el dígito por la vocal correspondiente. Luego se añade la cadena de control «aca».

Por último, se devuelve el resultado de las operaciones sobre la cadena recibida convertida a cadena, por si el valor recibido fue un número, ya que la función debe devolver una cadena.

Prueba

El siguiente código de prueba debe poder codificar y decodificar la cadena original suministrada obteniendo la cadena original como resultado.

// Testing
const str = "Solving an equation produces, instantly, great euphoria.";
console.log(karacaAlgorithm(str));
console.log(karacaAlgorithm(karacaAlgorithm(str)));

El resultado esperado debe ser:

.02r3hp41 t01rg ,yltn0tsn2 ,s1c4d3rp n32t04q1 n0 gn2vl3saca
solving an equation produces, instantly, great euphoria.

La frase, en inglés, incluye las palabras equation y euphoria que cuentan con todas las vocales.

Enlaces

Comentarios

← Volver