unidad didáctica 8
TRANSCRIPT
Tratamientos secuenciales I
Fundamentos de Programación
Departamento de Lenguajes y Sistemas Informáticos
Unidad Didáctica 8
Versión 1.0.0
UD8: Tratamientos secuenciales I
Índice
Introducción
Objetivo
Estructura lógica
Metodología - Resolución de problemas
Tratamientos:
Operaciones aritméticas:
“suma/producto”
Preguntas sobre propiedades:
“existe/para todo”
Máximos, mínimos
UD8: Tratamientos secuenciales I
Introducción
Conceptos necesarios, ya vistos:
Diseño de tipos => creación de objetos.
Diseño de programas iterativos => uso de estructuras de
control iterativas o “bucles” (for clásico, for extendido, while)
Uso de agregados de objetos: List, Set, etc.
Conceptos nuevos:
Extraer información útil para un usuario final sobre los datos
contenidos en un agregado de objetos.
UD8: Tratamientos secuenciales I
Objetivo
Dado un agregado de objetos (un List, un Set, etc.), nos
planteamos preguntas del tipo:
¿cuánto vale la suma de los …?
¿y el producto de los que verifican que …?
¿existe algún objeto que verifique …?
¿todos los objetos que cumplen que … verifican ...?
¿cuál es el valor más grande de los que … ?
¿según el orden … cuál es mayor que … ?
actualiza todos los objetos que …
etc.
Cada una de esas preguntas y otras similares pueden
implementarse a través de métodos con una
ESTRUCTURA COMÚN
UD8: Tratamientos secuenciales I
Estructura lógica – Ejemplo I
¿Cómo se calcula la suma de los cuadrados de los
números enteros contenidos en un Vector de Enteros?
Como el agregado es un Vector usamos un for extendido para
recorrerlo. El código lo concretamos en un método que
tomando un Vector como parámetro devuelve el resultado
esperado.
public static Integer sumaCuadrados(Vector<Integer> v){
}
public static Integer sumaCuadrados(Vector<Integer> v){
Integer suma=0;
for (Integer e: v){
suma = suma + e*e;
}
return suma;
}
UD8: Tratamientos secuenciales I
Estructura lógica – Ejemplo II
Sumar los cuadrados de los enteros contenidos en un
vector o en una secuencia que son múltiplos de 3.
public static Integer sumaCuadradosMultiplos3(Vector<Integer> v){
}
public static Integer sumaCuadradosMultiplos3(Vector<Integer> v){
Integer suma=0;
for(Integer e: v){
if(Enteros.esMultiplo(e,3)){
suma = suma + e*e;
}
}
return suma;
}
public static Integer sumaCuadradosIntervaloMultiplos3(Integer a,
Integer b, Integer c){
}
public static Integer sumaCuadradosIntervaloMultiplos3(Integer a,
Integer b, Integer c){
if(!(b>a && c>0)) throw new IllegalArgumentException();
Integer suma=0;
for(Integer e= a; e<=b; e=e+c){
if(Enteros.esMultiplo(e,3))
suma = suma + e*e;
}
return suma;
}
UD8: Tratamientos secuenciales I
Estructura lógica
¿Cuál es entonces nuestro esquema?
Elementos a destacar:
Acumulador: es una variable que acumula el resultado calculado
hasta ese momento. Se inicializa al valor adecuado para la secuencia o
el agregado vacío y es del tipo del resultado que queramos calcular. En
el ejemplo, la variable es suma que se inicializa a cero y es de tipo
Integer, como el resultado.
Filtro: es una expresión lógica sin efectos laterales que nos sirve para
escoger los elementos del agregado sobre los que vamos a hacer el
cálculo. En este caso es la expresión Enteros.esMultiplo(e,3).
Expresión: es una expresión que a partir de cada objeto del agregado
calcula el valor que se va acumulando. En este caso la expresión es e*e.
UD8: Tratamientos secuenciales I
Metodología - Resolución de problemas
Opciones:
1. Resolución mediante construcción directa de un bucle
(for extendido).
2. Generalización del código: diseño con tipos genéricos
e identificando las partes variables del método. Éstas se
pasarán como parámetros. En el caso de que el agregado
sea un Vector, las partes variables son: el agregado, el
filtro y la expresión.
A CONTINUACIÓN …
CLASE COLECCIONES(segunda parte de la asignatura)
UD8: Tratamientos secuenciales I
Operaciones aritméticas
Sumatorio
• Operador: +
• Elemento Neutro: 0
ESQUEMA:
Double suma = 0.0;
for(T o: it){
if(…){
suma = suma + … ;
}
}
return suma;
UD8: Tratamientos secuenciales I
Operaciones aritméticas
public static Integer suma(List<Integer> l){
Integer suma = 0;
for(Integer e: l)
suma = suma + e;
return suma;
}
99 44 33 11 22
Iteración nº e suma
77
0 … 0
UD8: Tratamientos secuenciales I
Operaciones aritméticas
public static Integer suma (List<Integer> l){
Integer suma = 0;
//mostrar(“suma”+suma);
for(Integer e: l){
suma = suma + e;
//mostrar(e);
//mostrar(“suma”+suma);
}
return suma;
}
99 44 33 11 22
Iteración nº e suma
77
0 … 0
1 7 (0+7)
2 9 (0+7)+9
3 4 ((0+7)+9)+4 … etc …
UD8: Tratamientos secuenciales I
Operaciones aritméticas
Producto
• Operador: *
• Elemento Neutro: 1
ESQUEMA:
Double prod = 1.0;
for(T o: it){
if(…){
prod = prod * … ;
}
}
return prod;
UD8: Tratamientos secuenciales I
Preguntas sobre propiedades
P Q ! P P || Q P && Q
true true false true true
true false false true false
false true true true false
false false true false false
(Repasemos cómo funcionan los operadores lógicos)
TABLA DE VERDAD:
UD8: Tratamientos secuenciales I
Preguntas sobre propiedades
Propiedad:
¿para todo elemento se verifica?
• Operador: &&
• Elemento Neutro: true
ESQUEMA:
Boolean r = true;
for(T o: it){
if(…){
r = r && … ;
}
}
return r;
UD8: Tratamientos secuenciales I
Preguntas sobre propiedades
Propiedad:
¿existe algún elemento que verifica que …?
• Operador: ||
• Elemento Neutro: false
ESQUEMA:
Boolean r = false;
for(T o: it){
if(…){
r = r || … ;
}
}
return r;
UD8: Tratamientos secuenciales I
Preguntas sobre propiedades
// ¿Existe algún número par en v?
public static Boolean existePar (List<Integer>
l){
Boolean res = false;
for(Integer e: l)
res = res || (e%2==0);
return res;
}
99 44 33 11 22
Iteración nº ¿e es par? res
77
UD8: Tratamientos secuenciales I
Preguntas sobre propiedades
// ¿Existe algún número par en v?
public static Boolean existePar (List<Integer> l){
Boolean res = false;
for(Integer e: l)
res = res || (e%2==0);
return res;
}
99 44 33 11 22
Iteración nº ¿e es par? res
0 --- false
1 false false || false -> false
2 false false || false -> false
3 true false || true -> true
4
77
false true || false -> true … etc …
¿Cómo sería un método que responda si todos los elementos son números pares?
UD8: Tratamientos secuenciales I
Preguntas sobre propiedades
// ¿Existe algún número par en v?
public static Boolean existePar (List<Integer> l){
Boolean res = false;
for(Integer e: l)
res = res || (e%2==0);
return res;
}
Nota:
Tratamiento no eficiente pues encuentra un
elemento que cumple la propiedad y sin
embargo sigue con las comprobaciones.
¿cómo podemos conseguir la eficiencia?
UD8: Tratamientos secuenciales I
Preguntas sobre propiedades//Versión eficiente nº1: (uso de break)
public static Boolean existeParEficienteN1 (List<Integer> l){
Boolean res = false;
for(Integer e: l){
res = res || (e%2==0);
if(e%2==0)
break;
}
}
return res;}
//Versión eficiente nº2: (“variable de frenado” dentro de un while)
public static Boolean existeParEficienteN2 (List<Integer> l){
Boolean res = false;
int i=0;
while(i<l.size() && !res){
if(l.get(i)%2==0){
res = true;
}
i++;//¿qué ocurre si olvidamos esta instrucción?
}return res;}
UD8: Tratamientos secuenciales I
Preguntas sobre propiedades
¿para todo …? VERSIÓN EFICIENTE
ESQUEMA:
Boolean r = true;
for(T o: it){
if(…){
r = r && … ;
if(!r){
break;
}
}
}
return r;
UD8: Tratamientos secuenciales I
Preguntas sobre propiedades
¿existe …? VERSIÓN EFICIENTE
ESQUEMA:
Boolean r = false;
for(T o: it){
if(…){
r = r || … ;
if(r){
break;
}
}
}
return r;
UD8: Tratamientos secuenciales I
Máximos, mínimos
máximo vs. mínimo:
• Elemento neutro: null
• Operador:
operación comparación 2 a 2
ESQUEMA:T a=null;
for(T e:it)
//a = (a==null? e: Utiles.max(e,a));
if(a==null)
a = e;
else
a = Utiles.max(e,a);
return a;
(análogo para
el mínimo)
UD8: Tratamientos secuenciales I
Máximos, mínimos
máximo vs. mínimo: (versión con filtrado)
• Elemento neutro: null
• Operador:
operación comparación 2 a 2
ESQUEMA:T a=null;
for(T e:it)
if(…){
a = (a==null? e: Utiles.max(e,a));
}
if(a==null)
throw new NoSuchElementException(“…”);
return a;
(análogo para
el mínimo)
UD8: Tratamientos secuenciales I
Máximos, mínimos
99 44 33 11 22
Iteración nº ¿mayor(a,res)->? resultado
77
0
1
2
3
4
resultado ->7 ---
(7,9)->9 resultado ->9
(9,4)->9 resultado ->9
… etc …
UD8: Tratamientos secuenciales I
Máximos, mínimos
//El ejemplo anterior:(versión “intuitiva”)
public static Integer maxValor(List<Integer> l){
//Primer candidato el primer elemento
Integer res = l.get(0);
for(Integer e:l){//¿Nuevo elemento mayor? Si fuera así, lo cambio
if(res.compareTo(e)<0)//if(res<e)
res = e;
}
return res ;
}
UD8: Tratamientos secuenciales I
Máximos, mínimos
/*El ejemplo anterior:
*(versión basada en operador binario máximo de dos
*elementos)*/
public static Integer
maxValor_version2(List<Integer> l){
Integer a=null;
for(Integer e:l)
a = a==null? e: Utiles.max(e,a);
return a;
}
UD8: Tratamientos secuenciales I
Máximos, mínimos
public class Utiles{
/*Método auxiliar para calcular el máximo de dos
*elementos: tipos genéricos (ampliando a
*supertipos) usando orden natural del tipo */
public static <E extends Comparable<? super
E>> E max(E e1, E e2){
return e1.compareTo(e2)>= 0 ? e1 : e2;
}
// …
}
UD8: Tratamientos secuenciales I
Máximos, mínimos
El esquema para el máximo y el mínimo puede ser
mejorado si el tratamiento del primer elemento es
incluido en el máximo binario:
//Versión “robusta” de max binario
public static <T extends Comparable<? super T>> T max(T o1, T o2) {
T o=null;
if(o1!=null && o2!=null){
if(o1.compareTo(o2)>=0)
o=o1;
else
o=o2;
} else {
if(o1==null)
o=o2;
if(o2==null)
o=o1;
}
return o;
}
UD8: Tratamientos secuenciales I
Máximos, mínimos
máximo vs. mínimo: versión mejorada
El tratamiento del primer elemento está incluido en el
operador binario Utiles.max(-,-).
ESQUEMA:T a=null;
for(T e:it)
a = Utiles.max(e,a);
}
return a;
Nota 1: la opción de filtrado se puede añadir de
manera análoga a como se hizo con la versión anterior
Nota 2: el uso del operador Utiles.max(-,-) en su
versión robusta evita el disparo de excepciones
cuando haya valores perdidos (null) en el agregado.
(análogo para
el mínimo)
UD8: Tratamientos secuenciales I
Búsquedas
Búsqueda
• Operador: =
• Elemento Neutro: --
ESQUEMA:
T b = null;
for(T e: it){
if(...){
b=e;
break;
}
}
return b;