|
| 1 | +/*======================================================================= |
| 2 | +========== AUTOMATA FINITO DETERMINISTICO =========== |
| 3 | +========================================================================*/ |
| 4 | + |
| 5 | +#include <iostream> // Librerias |
| 6 | +#include <string> // Librerias |
| 7 | +#include <sstream> // Librerias |
| 8 | +#include <fstream> // Librerias |
| 9 | +#include <vector> // Librerias |
| 10 | +#include <map> // Librerias |
| 11 | +#include <algorithm> // Librerias |
| 12 | + |
| 13 | + |
| 14 | +/*================================================== |
| 15 | +======== DEFINAMOS A UN AUTOMATA ========== |
| 16 | +==================================================*/ |
| 17 | +typedef struct{ //============= Nodo de nuestro automata ==== |
| 18 | + int Nombre; //Numero de nodo que eres (un ID) |
| 19 | + std::map <char, int> FnTransicion; //Guardamos una fn individual de a donde apunta |
| 20 | + bool EresEstadoFinal; //¿Eres el estado final? |
| 21 | +}Estado; //LLamare a esto Estado |
| 22 | + |
| 23 | +class DFA{ //============== CLASE AUTOMATA ============= |
| 24 | + private: //Mis variables, no tus variables |
| 25 | + |
| 26 | + std::vector<Estado> EstadosDelDFA; //Es el Vector de Estados para trabajar |
| 27 | + short int EstadoInicial; //Nos apunta a un estado inicial |
| 28 | + std::vector<char> Alfabeto; //Y esto es nuestro alfabeto |
| 29 | + std::vector<int> EstadosFinales; //Subconjuntos de Estados finales |
| 30 | + |
| 31 | + Estado *EstadoActual; //Crea un Estado Actual |
| 32 | + bool ElAutomataPuedeSeguir; //Nos dice si el automata aun puede llegar qfinal |
| 33 | + bool ElAutomataEstaEnQValido; //Nos dice si estamos en un estado valido |
| 34 | + |
| 35 | + public: //Tus metodos, para ti |
| 36 | + |
| 37 | + DFA(std::string nombreArchivo); //Crea nuestro automata |
| 38 | + void InformacionDelDFA(); //Muestra la Tabla del Automata |
| 39 | + |
| 40 | + bool CorreElAutomata(char Letra, bool Muestro); //Mueve solo una linea al automata |
| 41 | + void AnalizarArchivo(char *Lectura, char *Aceptada, bool Muestra); //Mueve todo un archivo |
| 42 | + |
| 43 | + void ReiniciaAutomata(){ //Funcion Auxiliar: Regresa el estado incial |
| 44 | + EstadoActual = &EstadosDelDFA[EstadoInicial]; //Apuntamos al estado inicial |
| 45 | + ElAutomataPuedeSeguir = true; //Suponemos que simpre tendras posibilidades |
| 46 | + ElAutomataEstaEnQValido = true; //Suponemos que simpre tendras posibilidades |
| 47 | + } |
| 48 | + |
| 49 | + bool EstoyEnEstadoFinal(){ //Funcion Auxiliar: Nos dice si gano |
| 50 | + if(!ElAutomataPuedeSeguir) return false; //Sino, ya valio |
| 51 | + if(!ElAutomataEstaEnQValido) return false; //Sino, ya valio |
| 52 | + return EstadoActual->EresEstadoFinal; //Sino, dejalo elegir |
| 53 | + } |
| 54 | +}; |
| 55 | + |
| 56 | + |
| 57 | +/*================================================== |
| 58 | +======== EL AUTOMATA TODA LOS DATOS ========== |
| 59 | +==================================================*/ |
| 60 | +DFA::DFA(std::string nombreArchivo){ //============== ES DONDE SALE LA MAGIA======= |
| 61 | + std::string basura; //Este sera el recolector de basura del txt |
| 62 | + int NumeroDeEstados, numDeFinales, numSimbolos, temporal; //Algunas variables necesarias |
| 63 | + char letra; //Algunas variables necesarias |
| 64 | + |
| 65 | + std::ifstream EntradaDeDatos(nombreArchivo.c_str()); //Este sera el archivo de la informacion |
| 66 | + EntradaDeDatos >> basura; //Leemos el titulo del archivo y lo ignoramos |
| 67 | + |
| 68 | + EntradaDeDatos >> basura; // == Leemos Q: === |
| 69 | + EntradaDeDatos >> NumeroDeEstados; //Leemos el numero de estado |
| 70 | + EstadosDelDFA.resize(NumeroDeEstados); //Numero de Estados |
| 71 | + std::vector<bool> EstadosFinalesCubeta(NumeroDeEstados, false); |
| 72 | + |
| 73 | + EntradaDeDatos >> basura; // == Leemos el q0: == |
| 74 | + EntradaDeDatos >> EstadoInicial; //Y lo apuntamos aqui |
| 75 | + |
| 76 | + EntradaDeDatos >> basura; // == Leemos el F: == |
| 77 | + EntradaDeDatos >> numDeFinales; //Y lo apuntamos aqui |
| 78 | + |
| 79 | + for (int i = 0, temporal; i < numDeFinales; i++){ //Leamos cada final |
| 80 | + EntradaDeDatos >> temporal; //Y lo vamos guardando |
| 81 | + EstadosFinalesCubeta[temporal] = true; //Y lo cambiamos a true |
| 82 | + EstadosFinales.push_back(temporal); //Guardando |
| 83 | + } |
| 84 | + |
| 85 | + EntradaDeDatos >> basura; // == Leemos el Σ: == |
| 86 | + EntradaDeDatos >> numSimbolos; //Y lo apuntamos aqui |
| 87 | + |
| 88 | + for (int i = 0 ; i < numSimbolos; i++){ //Leamos cada letra |
| 89 | + EntradaDeDatos >> letra; //Y lo vamos guardando |
| 90 | + Alfabeto.push_back(letra); //Guardando |
| 91 | + } |
| 92 | + |
| 93 | + EntradaDeDatos >> basura >> basura; // == Leemos el ∂: == |
| 94 | + for (int i = 0, EstadoActual; i < NumeroDeEstados; i++){ //Leamos cada final |
| 95 | + EntradaDeDatos >> EstadoActual; //Y guardemos en que estado estamos |
| 96 | + EstadosDelDFA[i].Nombre = EstadoActual; //Y le damos un nombre |
| 97 | + EstadosDelDFA[i].EresEstadoFinal = EstadosFinalesCubeta[i]; //Y guardamos ahora si si es un estado final |
| 98 | + |
| 99 | + char letraQueLeo; //Veamos la direccion |
| 100 | + int sigEstado; |
| 101 | + |
| 102 | + for (int j = 0; j < Alfabeto.size(); j++) //Para cada letra del alfabeto |
| 103 | + EstadosDelDFA[i].FnTransicion[Alfabeto[j]] = EstadoInicial; //Supongamos que apuntan al origen |
| 104 | + |
| 105 | + while(true){ |
| 106 | + EntradaDeDatos >> letraQueLeo; //Vemos que letra leemos |
| 107 | + if(letraQueLeo == '=') break; //Si es esta corremos |
| 108 | + EntradaDeDatos >> sigEstado; //Y guardamos el numero |
| 109 | + |
| 110 | + EstadosDelDFA[i].FnTransicion[letraQueLeo] = sigEstado; //Y le decimos ahora a donde apunta |
| 111 | + } |
| 112 | + EntradaDeDatos >> letraQueLeo; //Leemos el otro = que esta |
| 113 | + } |
| 114 | + ReiniciaAutomata(); |
| 115 | +} |
| 116 | + |
| 117 | + |
| 118 | +/*================================================== |
| 119 | +======== MOSTRAMOS INFORMACION DEL DFA ========== |
| 120 | +==================================================*/ |
| 121 | +void DFA::InformacionDelDFA(){ //======= VAMOS A MOSTRAR A NUESTRO AUTOMATA ======= |
| 122 | + std::cout<<"\n===== INFORMACION DEL DFA ========"; //Mensaje de bienvenida |
| 123 | + |
| 124 | + |
| 125 | + std::cout<<"\n\nQ (Cantidad de Estados): "<< EstadosDelDFA.size(); //Y lo mostramos por pantalla |
| 126 | + std::cout<<"\n\nq0 (Estado Inicial): q"<<EstadoInicial; //Y lo mostramos por pantalla |
| 127 | + |
| 128 | + std::cout<<"\n\nF (Estados Finales): "<<EstadosFinales.size()<<"\n"; //Y lo mostramos por pantalla |
| 129 | + for (int i = 0; i < EstadosFinales.size(); i++) //Y para cada uno |
| 130 | + std::cout<<" - q"<<EstadosFinales[i]<<"\n"; //Lo mostramos |
| 131 | + |
| 132 | + std::cout<<"\nΣ (Alfabeto): \n"; //Y lo mostramos por pantalla |
| 133 | + std::cout<<" "<<Alfabeto[0]; //Lo mostramos |
| 134 | + for (int i = 1; i < Alfabeto.size(); i++) std::cout<<", "<<Alfabeto[i]; //Lo mostramos por pantalla |
| 135 | + |
| 136 | + for (int i = 0, temporal; i < EstadosDelDFA.size(); i++){ //Para cada elemento del automata |
| 137 | + std::cout<<"\n\n == Estado "<<i<<": ===\n"; //Muestro un mensajito |
| 138 | + |
| 139 | + for (int j = 0, apuntador; j < Alfabeto.size(); ++j){ //Para cada letra |
| 140 | + char temporal = Alfabeto[j]; //Vamos a probar con a, b, c.. |
| 141 | + apuntador=EstadosDelDFA[i].FnTransicion.find(temporal)->second; //Vamos a ver a donde apuntas |
| 142 | + std::cout<<" (q"<<i<<",'"<<temporal<<"') = q"<<apuntador<<"\n"; //Mostramos por pantalla |
| 143 | + } |
| 144 | + } |
| 145 | +} |
| 146 | + |
| 147 | + |
| 148 | +/*=========================================================== |
| 149 | +======== EJECUTA SOLO UNA LINEA DEL AUTOMATA ========= |
| 150 | +===========================================================*/ |
| 151 | +bool DFA::CorreElAutomata(char Letra, bool Muestro){ //============= ESTO ES LO BUENO !! ========== |
| 152 | + |
| 153 | + if(ElAutomataPuedeSeguir == false) return false; //Ya termino la cadena! |
| 154 | + |
| 155 | + |
| 156 | + for (int i = 0; i < Alfabeto.size(); i++){ //Recorremos el alfabeto |
| 157 | + if(Alfabeto[i] == Letra) break; //Si encontre la letra dentro sal |
| 158 | + |
| 159 | + if(i == (Alfabeto.size()-1)){ //Si llegaste aqui es que no esta |
| 160 | + ElAutomataPuedeSeguir = false; //pero obvio no puedes seguir |
| 161 | + return ElAutomataPuedeSeguir; //bye |
| 162 | + } |
| 163 | + } |
| 164 | + |
| 165 | + if(ElAutomataEstaEnQValido == false) return true; //Si ya estas en un estado invalido, para que le hacen |
| 166 | + |
| 167 | + if(EstadoActual->FnTransicion.count(Letra) == 0){ //Si hay una transicion valida |
| 168 | + ElAutomataEstaEnQValido = false; //Si hay una transicion valida |
| 169 | + return true; //Si hay una transicion valida |
| 170 | + } |
| 171 | + if (EstadoActual->FnTransicion[Letra] == -1){ |
| 172 | + ElAutomataEstaEnQValido = false; //Si hay una transicion valida |
| 173 | + return true; //Si hay una transicion valida |
| 174 | + } |
| 175 | + |
| 176 | + if(Muestro) std::cout<<"\n(q"<<EstadoActual->Nombre<<", '"<<Letra; //Mensajes |
| 177 | + |
| 178 | + EstadoActual = &EstadosDelDFA[EstadoActual->FnTransicion[Letra]]; //Vamos al siguiente estado |
| 179 | + if(Muestro) std::cout<<"') = q"<<EstadoActual->Nombre; //Mensajes |
| 180 | + |
| 181 | + return true; //Todo bien |
| 182 | +} |
| 183 | + |
| 184 | + |
| 185 | +/*=========================================================== |
| 186 | +======== ANALIZA UN ARCHIVO ENCONTRANDO PALABRAS ====== |
| 187 | +===========================================================*/ |
| 188 | + |
| 189 | +void DFA::AnalizarArchivo(char *Lectura, char *Aceptada, bool Muestra){ //============= ESTO ES LO BUENO !! ========== |
| 190 | + |
| 191 | + FILE *CadenasDeLectura, *CadenaAuxiliar, *CadenaAceptadas; //Sean nuestros lectores |
| 192 | + |
| 193 | + fclose(fopen(Aceptada, "w")); //Empecemos por borrar lo que teniamos |
| 194 | + |
| 195 | + CadenasDeLectura = fopen(Lectura, "r"); //Abramos nuestras archivos |
| 196 | + CadenaAuxiliar = fopen(Lectura, "r"); //Abramos nuestras archivos |
| 197 | + CadenaAceptadas = fopen(Aceptada, "a"); //Abramos nuestros archivos |
| 198 | + |
| 199 | + char LetraQueAnalizo, LetraEscribir; //Tengamos una letra temporal |
| 200 | + bool LaCadenaPaso = false; //Y veamos si la cadena paso |
| 201 | + |
| 202 | + if(Muestra) std::cout << "\n\n=== AUTOMATA BUSCANDO CADENAS"; //Mostramos mensajito |
| 203 | + if(Muestra) std::cout << " VALIDAS Y MOSTRANDO ===\n\n"; //Mostramos mensajito |
| 204 | + |
| 205 | + while(true){ //Sigamos eternamente XD |
| 206 | + LetraQueAnalizo = fgetc(CadenasDeLectura); //Leemos una letra |
| 207 | + |
| 208 | + if (CorreElAutomata(LetraQueAnalizo, Muestra) == true){ //Si acepto la letra actual |
| 209 | + LaCadenaPaso = EstoyEnEstadoFinal(); //Y vemos si paso sabiendo si esta en estado final |
| 210 | + } |
| 211 | + else{ //Sino acepto que la letra |
| 212 | + |
| 213 | + if(LaCadenaPaso && Muestra) std::cout << "\nCadenaPaso: '"; //Pero llegamos justo al final de la cadena |
| 214 | + |
| 215 | + while((LetraEscribir=getc(CadenaAuxiliar))!=LetraQueAnalizo){ //Mientras mi puntero vaya atras |
| 216 | + if(LaCadenaPaso){ //Y si la caden paso |
| 217 | + if(Muestra) printf("%c", LetraEscribir); //Ve mostrando cual cadena paso |
| 218 | + fprintf(CadenaAceptadas, "%c", LetraEscribir); //Guardemos en el archivo |
| 219 | + } |
| 220 | + } |
| 221 | + |
| 222 | + if (LaCadenaPaso){ //Y si la cadena paso |
| 223 | + fprintf(CadenaAceptadas, "\n"); //Guardemos en el archivo |
| 224 | + if(Muestra) std::cout << "'\n"; //Espacios de Estilo |
| 225 | + } |
| 226 | + |
| 227 | + std::cout << "\n"; |
| 228 | + |
| 229 | + ReiniciaAutomata(); //Reiniciamos el automata |
| 230 | + LaCadenaPaso = false; //Pero suponemos que no ha pasado la cadena |
| 231 | + |
| 232 | + if(LetraQueAnalizo == EOF) break; //Si ya llegaste al final de la cadena, sal! |
| 233 | + } |
| 234 | + } |
| 235 | + |
| 236 | + fclose(CadenasDeLectura); //Cierras el archivo |
| 237 | + fclose(CadenaAuxiliar); //Cierras el archivo |
| 238 | + fclose(CadenaAceptadas); //Cierras el archivo |
| 239 | + |
| 240 | +} |
| 241 | + |
0 commit comments