Está en la página 1de 10

INSTITUTO POLITECNICO NACIONAL

UNIDAD PROFESIONAL INTERDISCIPLINARIA DE


INGENIERÍA Y CIENCIAS SOCIALES Y
ADMINISTRATIVAS

ALEJANDRE RIVERA GERARDO ADONAY


2020600048

TEORIA DE LENGUAJES Y COMPILADORES


3CM42

galejandrer1400@alumno.ipn.mx
gerardoaxrv@hotmail.com

LICENCIATURA EN CIENCIAS DE LA INFORMATICA


Dado el alfabeto

Σ={0,1}Σ={0,1}

construir un Autómata Finito Determinista de 4 estados como máximo, que acepte


el lenguaje representado por la siguiente expresión regular

((01+10)(11)∗0)∗(01+10)(11)∗((01+10)(11)∗0)∗(01+10)(11)∗

Vamos a representar el autómata por partes, es decir, iremos obteniendo


autómatas hasta llegar al autómata final que se pide.

El primer autómata que vamos a escribir es de cuatro estados y acepta el


siguiente lenguaje

(01+10)(01+10)

No hacemos ningún comentario ya que el autómata es simple.

Ahora vamos a añadir las cadenas (11)*, es decir, el siguiente autómata acepta el


lenguaje

(01+10)(11)∗(01+10)(11)∗

Hemos añadido sólo un arco etiquetado con 1 del estado 4 (el final) al estado 2.

Veamos su funcionamiento:

 como el arco empieza en el estado final, cabe la posibilidad de no usarse,


es decir, lo que corresponde con el elemento
ε de (11)∗ε de (11)∗

 que el arco acabe en el estado 2 asegura que una vez se accede al arco,
necesariamente tiene que haber otro 1 para poder alcanzar el estado final,
es decir, este arco sirve para concatenar la palabra 11,

El siguiente paso es el lenguaje

((01+10)(11)∗0)∗((01+10)(11)∗0)∗

Queremos que todas las palabras anteriores terminen con un 0 y, además, la


expresión está encerrada bajo un *, por lo que tendrá que haber un arco al estado
inicial de modo que exista la posibilidad de recorrer el autómata tantas veces
como se desee.

Está claro que el arco etiquetado con 0 tiene que comenzar en el estado 4. Nos
vemos obligados a cambiar el estado final ya que, hasta ahora, no todas las
palabras acaban en 0 (sólo la palabra 10). Así pues, el estado final actual será el
estado inicial anterior:

Observaciones:

 El estado 1 es estado inicial y estado final. Esto no supone ningún problema


ya que el último * incluye la posibilidad de tomar la palabra vacía

εε

En el siguiente paso vamos a concatenar las palabras del lenguaje

(01+10)(11)∗(01+10)(11)∗

a las que ya teníamos anteriormente. Como la expresión anterior la hemos


obtenido, en realidad, en el primer diagrama, será suficiente cambiar el estado
final al estado 4:
Observaciones: si llamamos

a=(01+10)(11)∗a=(01+10)(11)∗

el lenguaje que queremos representar es

(a0)∗a(a0)∗a

De este modo,

 si sólo se accede al estado 4 (estado final) una vez, la palabra es de la


forma a
 si se accede n + 1 veces al estado 4, la palabra es de la forma

(a0)1(a0)2...(a0)na0(a0)1(a0)2...(a0)na0

donde el subíndice de cada paréntesis indica el número de veces que se


repite la secuencia a0.

Por tanto, se trata de una palabra del lenguaje.

Tabla de la función de transición del AFD:


//PROGRAMA QUE LEE UN ARCHIVO Y EXPORTA A OTRO ARCHIVO CON OTRO NOMBRE Y LO MUESTRA

//EN LA CONSOLA

//

//

//Arias Arellano Alexis

//3NM41

//

#include <stdlib.h>

#include <stdio.h>

#include <iostream>

#include <fstream>

#include <time.h>

#include <string>

using namespace std;

//Se generan variables globales para evitar el paso de parametros o argumentos entre las funciones

int i=0, j=0, k=0, l=0, w=0;

int guardacn;

int temp;

int cn=0; //Numero de datos a ordenar

int n=0; //Numero de datos a ordenar

char arreglo[1000000000]; //Tamaño del arreglo 10

int cont=0;

int izq=0, der=0, auxiliar=0, pivote=0, temporal=0;

int ban=0;

string nombrearchivo; //nombre del archivo de entrada

string nombrearchivo2; //nombre del archivo de salida

clock_t t_ini, t_fin;

double secs;
struct Entrada { //declaracion de estructura que permiten leer y copiar los numeros en el arreglo
"arreglo"

int valor;

} entrada;

struct Salida { //declaracion de estructura que permiten los numeros ordenados en el arreglo "arreglo"
guardalos en el archivo de salida

int valor;

} salida;

//*** Prototipo o definición del metodo de ordenamiento

void leeArchivo(){

FILE *archivo1; //Crea un apuntador de archivo, utilizando en la función fopen, el


apuntador se le asigná el llamado al archivo

cout<<"\n Teclea el nombre del archivo de entrada (sin espacio, ni caracteres especiales): ";

cin>>nombrearchivo;

nombrearchivo+= ".txt"; // Se le agrega al


nombre del archivo la extension ".txt"

archivo1 = fopen(nombrearchivo.c_str(), "r"); // Se abre el archivo de modo lectura

if(archivo1== NULL ){ // el archivo contiene los numeros a ordenar

cout<<"\n No se puede abrir el archivo "; //si no se puede abrir el archivo termina con error el
programa

exit(1);

else{

cout<<"\n Se abrio el archivo "<<nombrearchivo.c_str()<<" correctamente";

//Lee el archivo y copia los numeros contenidos en el archivo en el arreglo "arreglo"

cn=0;
for (int i=0; !feof(archivo1); i++) { // Repite hasta que sea el fin del archivo

fscanf (archivo1, "%c", &entrada.valor); // Lee el numero contenido en el archivo y lo guarda en la


estructura

arreglo[i]=entrada.valor; // El numero contenido en la estructura lo pasa al arreglo "arreglo"

cn++; // suma 1 al contador de numeros leidos

cn--;

cout<<"\n\n Total de numeros contenidos en el archivo: "<<cn<<"\n\n";

n=cn;

fclose(archivo1); //cierra el archivo de entrada

//Copia la arreglo ordenada en el archivo de salida

void grabaArchivo(){

FILE *archivo2; //Crea un apuntador de archivo, utilizando en la función


fopen, el apuntador se le asigná el llamado al archivo

cout<<"\n Teclea el nombre del archivo de salida (sin espacios, ni caracteres especiales): ";

cin>>nombrearchivo2;

nombrearchivo2+= ".txt"; // se agrega


la extension ".txt"

archivo2 = fopen(nombrearchivo2.c_str(), "w"); // se abre el archivo de modo


escritura

if(archivo2== NULL ){

cout<<"\nNo se puede abrir el archivo ";

exit(1);

else{

cout<<"\n Se abrio el archivo "<<nombrearchivo2.c_str()<<" correctamente\n";


}

//Guarda los numeros ordenados de la arreglo en el segundo archivo

guardacn=0;

for (i=0; i<n; i++) {

salida.valor=arreglo[i];

fprintf(archivo2, "%c", salida.valor);

guardacn++;

cout<<"\n\n\n TEXTO MOSTRADO\n";

for (w=0; w<cn; w++){

cout<<arreglo [w]<< "";

cout<<"\n\n Tiempo en el que sucede el proceso: ";

cout<<"\nEl total de numeros alamacenados en el segundo archivo es: "<<guardacn;

cout<<"\n\n";

fclose(archivo2);

//* Funcio main ()

int main() {

leeArchivo(); // lee y guarda los datos en una lista

t_ini = clock(); // guarda tiempo inicial (antes de ordenar)

//Llama al metodo de ordenamiento

t_fin = clock(); // guarda tiempo final (despues de ordenar)

// Imprime el tiempo que se tardo el metodo en ordenar los datos


secs = (double)(t_fin - t_ini) / (double)CLOCKS_PER_SEC; // determina los milisegundo utilizados

printf("%.16g milisegundos", secs * 1000.0); // imprime el tiempo utilizado

cout<<"\n\n"; // se utiliza printf porque es una sentencia mas poderosa que cout

// permite ver cantidades muy pequeñas o muy


grande

grabaArchivo(); // Copia los numeros ordenados de la arreglo en el archivo de


salida

cout<<"\n\n";

return 0;

También podría gustarte