A raíz de un post levantado ayer (contar la cantidad de palabras dentro de una frase), recibo en mi bandeja de correo electrónico una nueva consulta, muy interesante: saber si una frase es palindrómica
Si esto no queda muy claro, recurrimos a wikipedia:
Un palíndromo (del griego palin dromein, volver a ir hacia atrás) es una palabra, número o frase que se lee igual hacia adelante que hacia atrás. Si se trata de un número, se llama capicúa. Habitualmente, las frases palindrómicas se resienten en su significado cuanto más largas son.
Afortunadamente la gente de la wiki también nos nutre de una buena cantidad de ejemplos; transcribo algunos:
- ¿Acaso hubo búhos acá?
- La ruta nos aportó otro paso natural
- No di mi decoro, cedí mi don
- Nada, yo soy Adán
Si planteamos este asunto desde un punto de vista meramente lógico, no es difícil de resolver. Pero para arribar a buen puerto, debemos analizar todos los problemas con los cuales nos encontraremos, antes de comenzar con la codificación en VBA.
a) Letras mayúsculas: será conveniente convertir toda la frase original a mayúsculas o minúsculas, ya que no tienen importancia dentro de un palíndromo.
b) Espacios en blanco: eliminarlos a todos.
c) Signos de puntuación: idem anterior.
d) Letras con acentos: cambiar las letras con acento por la misma letra, pero sin el acento. Ej: á por a, é por e, y así con todas. Aqui deberemos crear una rutina que busque letra x letra, reemplazando todas aquellas que presenten acentos.
Existen muchas formas de encarar esta tarea, recuerden que en programación no hay una "fórmula mágica". La solución que brindo al respecto solo intenta realizarlo de la forma mas sencilla posible y utilizando las estructuras comunes, a los fines de analizar parte por parte el código y tomar de el lo que nos sirva, para así poder incorporarlo en cualquiera de nuestros proyectos.
Abrimos un nuevo libro, dando la posibilidad de ingresar la frase en A1
Nos dirigimos al editor de VBA (alt + F11), agregamos un módulo e incorporamos el siguiente código, al cual lo comenté convenientemente para una mejor interpretacion:
'en una constante guardo todos los caracteres que tienen acento y 'en la otra los mismos caracteres, sin acentos, para luego utili 'zarlas en la funcion: Const CON_ACENTOS = "áàäâÁÀÄÂéèëêÉÈËÊíìïîÍÌÏÎóòöôÓÒÖÔúùüûÚÙÜÛýÿÝ" Const SIN_ACENTOS = "aaaaAAAAeeeeEEEEiiiiIIIIooooOOOOuuuuUUUUyyY" Public Sub DetectarPalindromos() Dim FraseOriginal, FraseOriginalLimpia As String Dim Palindromo As String Dim X, Largo As Integer 'tomo la frase original y quito los especios en blanco 'al principio y fin, con la funcion TRIM() FraseOriginal = Trim([a1]) 'ahora llevo toda esa cadena de texto a minúsculas: FraseOriginal = LCase(FraseOriginal) 'bien, vamos a quitar los posibles acentos presentes en 'la frase que nos ocupa, llamando a la funcion que 'hemos creado a esos efectos: FraseOriginal = QuitarAcentos(FraseOriginal) [c1] = "" [c2] = "" '=========================================== 'hasta aqui tenemos: la frase original sin espacios en 'blanco al principio y fin, totalmente convertida a mi 'núsculas y sin acentos. 'debemos por lo tanto, armar una nueva frase, sin los 'espacios en blanco entre cada palabra: 'almaceno la cantidad de caracteres de la frase: Largo = Len(FraseOriginal) 'la recorro con un bucle, usando a MID() para identifi 'car cada caracter. For X = 1 To Largo 'tomo una sola letra, aplicando TRIM() a dicho 'caracter c = Trim(Mid(FraseOriginal, X, 1)) 'si ese caracter NO era un espacio en blanco, voy 'formando la nueva frase: If c <> "" Then 'si el caracter analizado NO es una letra en 'minusculas: If Asc(c) >= 97 And Asc(c) <= 122 Then FraseOriginalLimpia = FraseOriginalLimpia & c End If End If Next X '=========================================== 'si la frase original era "Acaso hubo búhos acá", les 'comento que ahora llegamos a: "acasohubobuhosaca" 'como un palindromo debe leerse igual de atras hacia 'adelante, tengo que dar vuelta esa frase y al resulta 'do compararlo. lo hacemos recorriendo la frase al revés For X = Largo To 1 Step -1 Palindromo = Palindromo & Mid(FraseOriginalLimpia, X, 1) Next X 'comparamos: If Palindromo = FraseOriginalLimpia Then MsgBox "la frase es un palindromo" Else MsgBox "la frase no es un palindromo" End If 'y agregamos en la planilla las dos frases resultantes, 'para informar correctamente al usuario: [c1] = FraseOriginalLimpia [c2] = Palindromo End Sub Public Function QuitarAcentos(ByVal strNombre As String) As String Dim intCont As Integer For intCont = Len(CON_ACENTOS) To 1 Step -1 strNombre = Replace(strNombre, Mid(CON_ACENTOS, intCont, 1), _ Mid(SIN_ACENTOS, intCont, 1)) Next QuitarAcentos = strNombre End Function
El resultado verdadero:
El resultado falso:
pueden observar los resultados en C1 y C2: no hay espacios en blanco, todo convertido a minúsculas, la frase invertida, sin signos de puntuación, etc.
Resta aclarar, para aquellos que desconocen la función que utilicé dentro del primer bucle: todos sabemos que cualquier cosa que ingresemos al ordenador, este lo convierte en números. Bueno, las letras no son la excepcion.
Como determino, de forma sencilla, si el caracter es una letra o un signo de puntuación? Utilizando la función Asc(), que me retorna el codigo Ascii del caracter. Si hablamos de letras minúsculas, el número Ascii de la letra "a" es el 97, y el de la "z" el 122. Entonces.... si el Asc() de un caracter es mayor o igual a 97 y a la vez es menor o igual a 122 (es decir, en castellano, si está entre la "a" y la "z"), lo utilizo para formar mi nueva frase. Caso contrario, lo descarto, ya que no estoy frente a una letra minúscula.
Les dejo un ejercicio por resolver, para que practiquen: existen aún un problema y se trata de la muy castellana letra "ñ", cuyo código Ascii es 164. Tal cual plantee la solución, si aparece una letra ñ habría posibles errores.
Me encuentro en la obligación y alegría de dedicarle este post a mi buen amigo Manuel Arboleda, quien siempre tiene palabras muy alentadoras para mi blog.
link al archivo
Como determino, de forma sencilla, si el caracter es una letra o un signo de puntuación? Utilizando la función Asc(), que me retorna el codigo Ascii del caracter. Si hablamos de letras minúsculas, el número Ascii de la letra "a" es el 97, y el de la "z" el 122. Entonces.... si el Asc() de un caracter es mayor o igual a 97 y a la vez es menor o igual a 122 (es decir, en castellano, si está entre la "a" y la "z"), lo utilizo para formar mi nueva frase. Caso contrario, lo descarto, ya que no estoy frente a una letra minúscula.
Les dejo un ejercicio por resolver, para que practiquen: existen aún un problema y se trata de la muy castellana letra "ñ", cuyo código Ascii es 164. Tal cual plantee la solución, si aparece una letra ñ habría posibles errores.
Me encuentro en la obligación y alegría de dedicarle este post a mi buen amigo Manuel Arboleda, quien siempre tiene palabras muy alentadoras para mi blog.
link al archivo
- Obtener enlace
- Correo electrónico
- Otras aplicaciones
Etiquetas
Macros
Etiquetas:
Macros
- Obtener enlace
- Correo electrónico
- Otras aplicaciones
Comentarios
Publicar un comentario