180 likes | 353 Views
2. Diagramas de Estado. ¿Qué es y para qué se usa?. Una técnica para desarrollar programas Espacialmente adecuado para programas que tienen que analizar una secuencia de datos y decir algo respecto de ella
E N D
¿Qué es y para qué se usa? • Una técnica para desarrollar programas • Espacialmente adecuado para programas que tienen que analizar una secuencia de datos y decir algo respecto de ella • Un diagrama de estados nos permite visualizar los diferentes estados por los que va pasando un programa. • Las transiciones de un estado a otro se realizan ya sea incondicionalmente o bajo una condición. • Además, pueden ir acompañadas de una acción que se realiza junto con la transición.
Ejemplo: Contar palabras de una frase • Simplificación: la frase está almacenada en un string s, y termina con un punto String s = "Este es un ejemplo."; • Para este ejemplo, una "palabra" es cualquier secuencia de caracteres consecutivos distintos de blanco (y punto). • Estrategia: examinar los caracteres del string de izquierda a derecha, usando charAt(k) • Lo que se haga con cada carácter depende si estábamos dentro o fuera de una palabra. • Esto último corresponde a los estados del programa.
Programa: El miope np = 0; k = 0; • estado = FUERA; while(estado != FIN){ c = s.charAt(k); if( estado==FUERA ) if( c!=' ' ) { • estado = DENTRO; ++np; ++k; } elseif (c == ‘.’) estado = FIN; else ++k; else // estado==DENTRO if( c==' ' ) { • estado = FUERA; • ++k; • } elseif (c == ‘.’) • estado = FIN; • else • ++k; } Esto lo podría generar un autómata tomando como input la tabla
Programa: 2 versiones más “procesadas” k = 0; np = 0; while( s.charAt(k)!='.' ) { // estado==FUERA while( s.charAt(k)==' ' ) ++k; if( s.charAt(k)=='.' ) break; ++np; ++k; // estado==DENTRO while( s.charAt(k)!=' ' && s.charAt(k)!='.' ) ++k; if( s.charAt(k)=='.' ) break; ++k; } np = 0; estado = FUERA; k = 0; while((c=s.charAt(k))!='.'){ if( estado==FUERA ) { if( c!=‘ ') { ++np; estado = DENTRO; } } else // estado==DENTRO if( c==' ' ) estado = FUERA; } ++k; }
Ejemplo: Un sistema de alerta ambiental Un sistema de alerta de la calidad del aire emite una señal verde cada vez que la medición del aire está bajo el valor 50. Si esta medición sobrepasa los 50 entonces se emite una señal roja. Para volver a emitir una señal verde deben venir por lo menos 3 mediciones bajo los 50, durante las cuales se emite una señal amarilla. Suponga que las medidas para el día se ingresan por teclado cada minuto . Al final del día se ingresa un valor negativo y el computador responde con el número de minutos en que se emitió una señal verde, roja y amarilla. input<=50/++V; input>50/++R; R=V=A=0; input>50/++R; V R input>50/++R; input>50/++R; input<=50/++V; input<=50/++A; A1 A2 input<=50/++A;
V = R = A = 0; • estado = Verde; while((n=input() >=0){ if( estado==Verde) if( n >50) { • estado = Rojo;++R; } else ++V; elseif (estado = Rojo) if( n <= 50 ) { • estado = Amarillo1; ++A; • } else • ++R; • elseif (estado = Amarillo1) • if( n <= 50 ) { • estado = Amarillo2; ++A; • } else • estado = Rojo;++R; • } • else • if( n <= 50 ) { • estado = Verde; ++V; • } else • estado = Rojo;++R; • } } Programa: dos versiones V = R = A = 0; • estado = Verde; while((n=input() >=0){ if( n >50) { • estado = Rojo;++R; • } else //n < 50 if (estado = Rojo) • estado = Amarillo1; ++A; • } elseif (estado = Amarillo1) • estado = Amarillo2; ++A; • else • estado = Verde; ++V; }
Relación Invariante-Diagrama • Un invariante se puede asociar a un estado del diagrama • Ejemplo: • Reordenar los elementos de a[0], ..., a[n] dejando a la izquierda los <0 y a la derecha los >=0.
Solución 1 • Un invariante conocido: • Su diagrama < 0 >=0 desconocidos i j
Solución 2 • Invariante alternativo: • Su diagrama < 0 desconocidos >=0 i j
Chequeo de expresiones PROBLEMA: Escribir una función con encabezado pubicstaticdouble valor(String s) que recibe como parámetro un string que contiene un número real terminado con un ; y entregue su valor. Si el número está mal escrito debe retornar Math.MAXDOUBLE (el máximo double que puede guardar java). No usar substring !!! Acepta: 345.45; 456; .34; ; (retorna cero) No Acepta: 345.45.34; 456,34; .34e; ; (retorna cero)
El automata(c = s.charAt(k)) c>= ‘0’ && c<=‘9’/ val+=(c-’0’)/n;n*=10;k++; c>= ‘0’ && c<=‘9’/val=val*10 +c-’0’;k++; c== ‘.’ /n=10;k++; Val = 0.0; k = 0; Entero Decimal c== ‘;’/return val c>= ‘;’/return val Error c== ‘;’/return val Fin c == otro/ returnMath.maxDouble;
El programa // Version 1double valor = 0;int n; int final ENTERO =1, DECIMAL =2, ERROR =3, FIN =0; estado = ENTERO;for( k=0; k < s.length() && estado != FIN && estado != ERROR; ++k ){if( estado== ENTERO)if( s.charAt(k) <= '9' && s.charAt(k) >= '0' ) valor = valor*10 + s.charAt(k)-'0';else if (s.charAt(k) == ';')estado = FIN; else if (s.charAt(k) == '.') { n = 10;estado = DECIMAL;else estado = ERROR;else if(estado == DECIMAL) if( s.charAt(k) <= '9' && s.charAt(k) >= '0' ) {valor = valor + (s.charAt(k)-'0')/n;n = n*10; } else if (s.charAt(k) == ';')estado = FIN;else estado = ERROR; }if (estado == FIN)return valor else return Math.MAXDOUBLE;
El programa // Version 2 double valor = 0; k = 0; while(k < s.length() && s.charAt(k) <= '9' && s.charAt(k) >= '0') { valor = valor*10 + s.charAt(k)-'0'; k++; } if (s.charAt(k) == ';') return valor else if (s.charAt(k) != '.') return Math.MAXDOUBLE; int n = 10; while (k < s.length() && s.charAt(k) <= '9' && s.charAt(k) >= '0') { valor = valor + (s.charAt(k)-'0')/n; n = n*10; k++; } if (s.charAt(k) == ';') return valor else return Math.MAXDOUBLE;
Propuestos • 1- Dibujar un autómata que reconozca expresiones (termine en un estado final si está bien escrita, en uno de error si no) del tipo: • unavariable=345+438; o sea <nombre_de_variable>=<entero><op><entero>; • 1.1 permita uno o más espacios entre los elementos (variable, signo igual, enteros, • operación, punto-coma) • 1.2 después del signo = puede venir un solo número, o una cadena de • <entero>(<op><entero>)* • 1.3 haga una función que devuelva el valor de la expresión suponiendo que • solo vienen sumasde números positivos si está bien escrita, o devuelve el valor -1; • 2- Dibujar un autómata que quede en un estado final si los primeros dos caracteres de una entrada que puede ser infinitamente larga (no cabe en una variable) coinciden con los últimos dos. • 3- Escribir una función que tenga el encabezado publicstatic true valido(String s) que retorna true si el string s empieza con uno o más caracteres 'a' seguidos por uno o más caraceters 'b' y terminados con uno o más caracteres 'c' seguido por un carácter ';'. Además debe imprimir (con System.out.println(....) ) la cantidad de caracteres a, b y c que venían en la secuencia. Por ejemplo: aabbbbcc; , abbbbc; , abc;, aaabc; son secuencias válidas. bbbccc; , axbbccc; , aaaccc; , aabcc (no tiene ';' al final) son inválidas.