Crear una herramienta que verifique si una cadena es un palíndromo ignorando espacios y mayúsculas, y que permita deshacer/rehacer verificaciones para volver rápidamente a resultados previos.
Se usa una pila para comparar simultáneamente los extremos. Dos enfoques:
El ejemplo a continuación opta por el segundo enfoque para mantenerlo simple.
Mantenemos dos pilas de cadenas:
Cuando se ejecuta una nueva verificación, se límpia la pila Redo.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX 256
typedef struct Nodo {
char *texto;
struct Nodo *sig;
} Nodo;
typedef struct {
Nodo *top;
} PilaStr;
static void pila_init(PilaStr *p) { p->top = NULL; }
static int pila_is_empty(const PilaStr *p) { return p->top == NULL; }
static void pila_push(PilaStr *p, const char *texto) {
Nodo *n = malloc(sizeof(Nodo));
if (!n) return;
n->texto = strdup(texto);
n->sig = p->top;
p->top = n;
}
static char *pila_pop(PilaStr *p) {
if (pila_is_empty(p)) return NULL;
Nodo *tmp = p->top;
char *texto = tmp->texto;
p->top = tmp->sig;
free(tmp);
return texto;
}
static void pila_clear(PilaStr *p) {
while (!pila_is_empty(p)) {
free(pila_pop(p));
}
}
static void normalizar(const char *entrada, char *salida) {
int idx = 0;
for (size_t i = 0; entrada[i]; ++i) {
if (isalnum((unsigned char)entrada[i])) {
salida[idx++] = (char)tolower((unsigned char)entrada[i]);
}
}
salida[idx] = '\0';
}
static int es_palindromo(const char *texto) {
char limpio[MAX];
normalizar(texto, limpio);
int len = (int)strlen(limpio);
for (int i = 0; i < len / 2; ++i) {
if (limpio[i] != limpio[len - 1 - i]) return 0;
}
return 1;
}
typedef struct {
PilaStr historial;
PilaStr redo;
} Verificador;
void verificador_init(Verificador *v) {
pila_init(&v->historial);
pila_init(&v->redo);
}
void verificador_check(Verificador *v, const char *texto) {
char resultado[300];
snprintf(resultado, sizeof(resultado), "\"%s\" => %s", texto,
es_palindromo(texto) ? "PALINDROMO" : "NO PALINDROMO");
pila_push(&v->historial, resultado);
pila_clear(&v->redo);
}
const char *verificador_undo(Verificador *v) {
if (pila_is_empty(&v->historial)) return "Nada para deshacer";
char *ultimo = pila_pop(&v->historial);
pila_push(&v->redo, ultimo);
free(ultimo);
return pila_is_empty(&v->historial) ? "Historial vacio" : v->historial.top->texto;
}
const char *verificador_redo(Verificador *v) {
if (pila_is_empty(&v->redo)) return "Nada para rehacer";
char *valor = pila_pop(&v->redo);
pila_push(&v->historial, valor);
free(valor);
return v->historial.top->texto;
}
void verificador_clear(Verificador *v) {
pila_clear(&v->historial);
pila_clear(&v->redo);
}
int main(void) {
Verificador v;
verificador_init(&v);
verificador_check(&v, "Anita lava la tina");
verificador_check(&v, "Hola mundo");
printf("%s\n", verificador_undo(&v));
printf("%s\n", verificador_redo(&v));
verificador_check(&v, "Yo hago yoga hoy");
printf("%s\n", v.historial.top->texto);
verificador_clear(&v);
return 0;
}