Artículo original escrito por: Sonya Moisset
Artículo original: Two Ways to Check for Palindromes in JavaScript
Traducido y adaptado por: Sil Zubikarai
Este artículo está basado en la Certificación de freeCodeCamp, Algoritmos de JavaScript y Estructuras de Datos, del desafío "Comprobador de palíndromos".
Un palíndromo es una palabra, frase, número, u otra secuencia de caracteres que se lee de la misma forma hacia adelante que hacia atrás. La palabra "palíndromo" fue usada por primera vez por el dramaturgo Inglés Ben Jonson en el siglo 17, de las raíces griegas palin ("de nuevo") y dromos (camino, dirección). — fuente. Wikipedia.
En este artículo, voy a explicar dos acercamientos, el primero construido con funciones y el segundo usando un bucle for.
Desafío de Algoritmos
Regresa verdadero si la cadena de texto es un palíndromo. De otra forma, regresa falso.
Un palíndromo es una palabra o enunciado que es escrito de la misma forma de adelante y al-revés, ignorando la puntuación, las mayúsculas, y el espaciado.
Nota. Vas a necesitar remover todos los caracteres no alfanuméricos (puntuación, espacios y símbolos) y convertir todo en minúsculas para comprobar por palíndromos.
Pasaremos la cadena de texto en varios formatos, como "racecar", "RaceCar", y "race CAR" entre otros.
function palindrome(str) {
return true;
}
palindrome("eye");
Casos de prueba proporcionados
- palíndromo ("race car") debe regresar verdadero.
- palíndromo ("not a palidrome") debe regresar falso.
- palíndromo("A man, a plan, a canal. Panama") debe regresar verdadero
- palíndromo("never odd or even") debe regresar verdadero.
- palíndromo("nope") debe regresar falso.
- palíndromo("almostomla") debe regresar falso.
- palíndromo("My age is 0, 0 si ega ym.") debe regresar verdadero.
- palíndromo("1 eye for of 1 eye") debe regresar falso.
- palíndromo(“0_0 (: /-\ :) 0–0”) debe regresar verdadero.
¿Qué expresión regular necesitaremos para pasar el último caso de prueba?
Las expresiones regulares son patrones usados para hacer coincidir combinaciones de caracteres de cadenas.
Cuando la búsqueda de una coincidencia requiere algo más que una coincidencia directa, el patrón incluye caracteres especiales.
Para pasar el ultimo caso de prueda, podemos usar dos Expresiones Regulares:
/[^A-Za-z0–9]/g or o
/[\W_]/g
\W elimina todos los caracteres no-alfanuméricos.
- \W coincide con cualquier carácter que no sea palabra.
- \W es el equivalente a [^A-Za-z0-9_].
- \W coincide cualquier cosa que no esté entre los corchetes.
¿Qué significa esto?
[^A-Z] coincide cualquier cosa que no este encerrada entre A y Z
[^a-z] coincide cualquier cosa que no este encerrada entre a y z
[^0-9] coincide cualquier cosa que no este encerrada entre 0 y 9
[^_] coincide cualquier cosa que no este encerrada en _
Pero en nuestro caso, necesitamos palíndromo (“0_0 (: /-\ :) 0–0”) para regresar true, que significa “_(: /-\ :)–” tiene que coincidir.
Necesitaremos añadir "_" para pasar este caso de prueba especifico.
Ahora tenemos “\W_”
Necesitaremos también añadir la bandera g para búsqueda global.
Finalmente tenemos “/[\W_]/g”
/[\W_]/g fue usado por puros propósitos demostrativos para mostrar como RegExp trabaja. /[^A-Za-z0-9]/g es el más sencillo RegExp a escoger.
1. Comprobar por palíndromos con funciones incorporadas
Para esta solución, usaremos varios métodos:
- El método toLowerCase() para regresar el valor de la cadena de llamada convertida en minúsculas.
- El método replace() para regresar la nueva cadena con algunas o todas las coincidencias de un patrón con un remplazo. Usaremos un RexExp que hemos creado antes.
- El método split() una cadena objeto en un arreglo de cadenas separando la cadena en sub cadenas.
- El método reverse() invierte un arreglo en su lugar. El primer elemento del arreglo se convierte en el último y el último en el primero.
- El método join() junta todos los elemento de un arreglo en una cadena.
function palindrome(str) {
// Paso 1. Pon en minuscula la cadena y usa el RexEXP para remover los caracteres no deseados en el.
var re = /[\W_]/g; // or var re = /[^A-Za-z0-9]/g;
var lowRegStr = str.toLowerCase().replace(re, '');
// str.toLowerCase() = "A man, a plan, a canal. Panama".toLowerCase() = "a man, a plan, a canal. panama"
// str.replace(/[\W_]/g, '') = "a man, a plan, a canal. panama".replace(/[\W_]/g, '') = "amanaplanacanalpanama"
// var lowRegStr = "amanaplanacanalpanama";
// Paso 2. Utiliza los métodos de encadenamiento con funciones integradas.
var reverseStr = lowRegStr.split('').reverse().join('');
// lowRegStr.split('') = "amanaplanacanalpanama".split('') = ["a", "m", "a", "n", "a", "p", "l", "a", "n", "a", "c", "a", "n", "a", "l", "p", "a", "n", "a", "m", "a"]
// ["a", "m", "a", "n", "a", "p", "l", "a", "n", "a", "c", "a", "n", "a", "l", "p", "a", "n", "a", "m", "a"].reverse() = ["a", "m", "a", "n", "a", "p", "l", "a", "n", "a", "c", "a", "n", "a", "l", "p", "a", "n", "a", "m", "a"]
// ["a", "m", "a", "n", "a", "p", "l", "a", "n", "a", "c", "a", "n", "a", "l", "p", "a", "n", "a", "m", "a"].join('') = "amanaplanacanalpanama"
// So, "amanaplanacanalpanama".split('').reverse().join('') = "amanaplanacanalpanama";
// And, var reverseStr = "amanaplanacanalpanama";
// Paso 3. Revisa si reverseStr es estrictamente igual a lorRegStr y regresa un BooLean
return reverseStr === lowRegStr; // "amanaplanacanalpanama" === "amanaplanacanalpanama"? => true
}
palindrome("A man, a plan, a canal. Panama");
Sin comentarios:
function palindrome(str) {
var re = /[\W_]/g;
var lowRegStr = str.toLowerCase().replace(re, '');
var reverseStr = lowRegStr.split('').reverse().join('');
return reverseStr === lowRegStr;
}
palindrome("A man, a plan, a canal. Panama");
2. Revisa por un palíndromo con un bucle FOR
La media indexación (len/2) tiene beneficios cuando procesa grandes cadenas de texto. Revisamos el final de cada parte y dividimos el número de iteraciones dentro del bucle FOR por dos.
function palindrome(str) {
// Paso 1.La primera parte es igual que la anterior
var re = /[^A-Za-z0-9]/g; // or var re = /[\W_]/g;
str = str.toLowerCase().replace(re, '');
// Paso 2. Crea el bucle FOR
var len = str.length; // var len = "A man, a plan, a canal. Panama".length = 30
for (var i = 0; i < len/2; i++) {
if (str[i] !== str[len - 1 - i]) { // Siempre y cuando los caracteres de cada parte coincidad, el bucle FOR debera seguir.
return false; // Cuando los caracteres ya no coinciden, false es regresado y salimos del bucle FOR.
}
/* Aqui len/2 = 15
For each iteration: i = ? i < len/2 i++ if(str[i] !== str[len - 1 - i])?
1st iteration: 0 yes 1 if(str[0] !== str[15 - 1 - 0])? => if("a" !== "a")? // false
2nd iteration: 1 yes 2 if(str[1] !== str[15 - 1 - 1])? => if("m" !== "m")? // false
3rd iteration: 2 yes 3 if(str[2] !== str[15 - 1 - 2])? => if("a" !== "a")? // false
4th iteration: 3 yes 4 if(str[3] !== str[15 - 1 - 3])? => if("n" !== "n")? // false
5th iteration: 4 yes 5 if(str[4] !== str[15 - 1 - 4])? => if("a" !== "a")? // false
6th iteration: 5 yes 6 if(str[5] !== str[15 - 1 - 5])? => if("p" !== "p")? // false
7th iteration: 6 yes 7 if(str[6] !== str[15 - 1 - 6])? => if("l" !== "l")? // false
8th iteration: 7 yes 8 if(str[7] !== str[15 - 1 - 7])? => if("a" !== "a")? // false
9th iteration: 8 yes 9 if(str[8] !== str[15 - 1 - 8])? => if("n" !== "n")? // false
10th iteration: 9 yes 10 if(str[9] !== str[15 - 1 - 9])? => if("a" !== "a")? // false
11th iteration: 10 yes 11 if(str[10] !== str[15 - 1 - 10])? => if("c" !== "c")? // false
12th iteration: 11 yes 12 if(str[11] !== str[15 - 1 - 11])? => if("a" !== "a")? // false
13th iteration: 12 yes 13 if(str[12] !== str[15 - 1 - 12])? => if("n" !== "n")? // false
14th iteration: 13 yes 14 if(str[13] !== str[15 - 1 - 13])? => if("a" !== "a")? // false
15th iteration: 14 yes 15 if(str[14] !== str[15 - 1 - 14])? => if("l" !== "l")? // false
16th iteration: 15 no
End of the FOR Loop*/
}
return true; // Ambas partes son estrictamente iguales, y regresa true => La cadena de texto es un palindromo.
}
palindrome("A man, a plan, a canal. Panama");
Sin comentarios:
function palindrome(str) {
var re = /[^A-Za-z0-9]/g;
str = str.toLowerCase().replace(re, '');
var len = str.length;
for (var i = 0; i < len/2; i++) {
if (str[i] !== str[len - 1 - i]) {
return false;
}
}
return true;
}
palindrome("A man, a plan, a canal. Panama");
Espero que hayas encontrado esto de utilidad.