Programación 2 Lección 8. Diseño recursivo de algoritmos por inmersión Problemas Problemas de diseño recursivo 1 Problema 1. Diseñar sin bucles: /** * Pre: valores!=null * Post: sumaDatos(valores) = * (SIGMA alfa EN [0,valores.length-1].valores[alfa]) */ public static double sumaDatos (double[] valores) { … ? … } Problemas de diseño recursivo 2 Diseño por inmersión (debilitando la postcond.) /** * Pre: valores!=null * Post: sumaDatos(valores) = * (SIGMA alfa EN [0,valores.length-1].valores[alfa]) */ public static double sumaDatos (double[] valores) /** * Pre: ??? * Post: sumaDatos(valores,???) = * (SIGMA alfa EN [0,???].valores[alfa]) */ private static double sumaDatos (double[] valores, int ???) Problemas de diseño recursivo 3 Diseño por inmersión (debilitando la postcond.) /** * Pre: valores!=null * Post: sumaDatos(valores) = * (SIGMA alfa EN [0,valores.length-1].valores[alfa]) */ public static double sumaDatos (double[] valores) /** * Pre: valores!=null AND hasta>=0 AND hasta<=valores.length-1 * Post: sumaDatos(valores,hasta) = * (SIGMA alfa EN [0,hasta].valores[alfa]) */ private static double sumaDatos (double[] valores, int hasta) Problemas de diseño recursivo 4 /** * Pre: valores!=null * Post: sumaDatos(valores) = * (SIGMA alfa EN [0,valores.length-1].valores[alfa]) */ public static double sumaDatos (double[] valores) { return sumaDatos(valores, valores.length-1); } /** * Pre: valores!=null AND hasta>=0 AND hasta<=valores.length-1 * Post: sumaDatos(valores,hasta) = * (SIGMA alfa EN [0,hasta].valores[alfa]) */ private static double sumaDatos (double[] valores, int hasta) { if (???) { ??? } else { ??? } } 5 /** * Pre: valores!=null * Post: sumaDatos(valores) = * (SIGMA alfa EN [0,valores.length-1].valores[alfa]) */ public static double sumaDatos (double[] valores) { return sumaDatos(valores, valores.length-1); } /** * Pre: valores!=null AND hasta>=0 AND hasta<=valores.length-1 * Post: sumaDatos(valores,hasta) = * (SIGMA alfa EN [0,hasta].valores[alfa]) */ private static double sumaDatos (double[] valores, int hasta) { if (hasta==0) { ??? } else { ??? } } 6 /** * Pre: valores!=null * Post: sumaDatos(valores) = * (SIGMA alfa EN [0,valores.length-1].valores[alfa]) */ public static double sumaDatos (double[] valores) { return sumaDatos(valores, valores.length-1); } /** * Pre: valores!=null AND hasta>=0 AND hasta<=valores.length-1 * Post: sumaDatos(valores,hasta) = * (SIGMA alfa EN [0,hasta].valores[alfa]) */ private static double sumaDatos (double[] valores, int hasta) { if (hasta==0) { return valores[hasta]; } else { return valores[hasta] + sumaDatos(valores, hasta-1); } } 7 Problema 2. Diseñar sin bucles: /** * Pre: valores!=null * Post: seleccionar(valores) = T * AND T.length = * (NUM alfa EN [0,valores.length-1].valores[alfa]>=0.0) * AND (PT alfa EN [0,T.length-1].T[alfa]>=0.0 * AND (NUM beta EN [0,valores.length-1]. * valores[beta]=T[alfa]) * = (NUM beta EN [0,T.length-1].T[beta]=T[alfa])) */ public static double[] seleccionar (double[] valores) Problemas de diseño recursivo 8 /** * Pre: valores!=null * Post: seleccionar(valores) = T * AND T.length = * (NUM alfa EN [0,valores.length-1].valores[alfa]>=0.0) * AND (PT alfa EN [0,T.length-1].T[alfa]>=0.0 * AND (NUM beta EN [0,valores.length-1]. * valores[beta]=T[alfa]) * = (NUM beta EN [0,T.length-1].T[beta]=T[alfa])) */ public static double[] seleccionar (double[] valores) { double[] nueva = new double[contar(valores,valores.length-1)]; copiar(valores, nueva, 0, 0); return nueva; } Problemas de diseño recursivo 9 /** * Pre: valores!=null AND hasta<=valores.length-1 * Post: contar(valores,hasta) * = (NUM alfa EN [0,hasta].valores[alfa]>=0.0) */ private static int contar (double[] valores, int hasta) { /* falta escribir su código */ } Problemas de diseño recursivo 10 /** * Pre: valores!=null AND hasta<=valores.length-1 * Post: contar(valores,hasta) * = (NUM alfa EN [0,hasta].valores[alfa]>=0.0) */ private static int contar (double[] valores, int hasta) { if (hasta<0) { return 0; } else if (valores[hasta]>=0.0) { return 1 + contar(valores, hasta-1); } else { return contar(valores, hasta-1); } } Problemas de diseño recursivo 11 /** * Pre: valores!=null AND desde<=valores.length AND i<=nueva.length * AND nueva.length = * (NUM alfa EN [0,valores.length-1].valores[alfa]>=0.0) * AND (PT alfa EN [0,i-1].nueva[alfa]>=0.0 * AND (NUM beta EN [0,desde-1].valores[beta]=nueva[alfa]) * = (NUM beta EN [0,i-1].nueva[beta]=nueva[alfa])) * Post: (PT alfa EN [0,T.length-1].nueva[alfa]>=0.0 * AND (NUM beta EN [0,valores.length-1].valores[beta]=nueva[alfa]) * = (NUM beta EN [0,nueva.length-1].nueva[beta]=nueva[alfa])) */ private static void copiar (double[] valores, double[] nueva, int desde, int i) { /* falta escribir su código */ } Problemas de diseño recursivo 12 /** * Pre: valores!=null AND desde<=valores.length AND i<=nueva.length * AND nueva.length = * (NUM alfa EN [0,valores.length-1].valores[alfa]>=0.0) * AND (PT alfa EN [0,i-1].nueva[alfa]>=0.0 * AND (NUM beta EN [0,desde-1].valores[beta]=nueva[alfa]) * = (NUM beta EN [0,i-1].nueva[beta]=nueva[alfa])) * Post: (PT alfa EN [0,T.length-1].nueva[alfa]>=0.0 * AND (NUM beta EN [0,valores.length-1].valores[beta]=nueva[alfa]) * = (NUM beta EN [0,nueva.length-1].nueva[beta]=nueva[alfa])) */ private static void copiar (double[] valores, double[] nueva, int desde, int i) { if (desde<valores.length) { if (valores[desde]>=0.0) { nueva[i] = valores[desde]; ++i; } copiar(valores, nueva, desde+1, i); } } 13 Problema 3. Diseñar sin bucles: /** * Pre: (EX alfa EN [0,valores.length-1].valores[alfa]>0.0) * Post: posiciónPositivo(valores)>=0 * AND posiciónPositivo(valores)<=valores.length-1 * AND T[posiciónPositivo(valores)]>0.0 */ public static int posiciónPositivo (double[] valores) Problemas de diseño recursivo 14 /** * Pre: (EX alfa EN [0,valores.length-1].valores[alfa]>0.0) * Post: posiciónPositivo(valores)>=0 * AND posiciónPositivo(valores)<=valores.length-1 * AND T[posiciónPositivo(valores)]>0.0 */ public static int posiciónPositivo (double[] valores) { ??? } /** * Pre: (EX alfa EN [desde,valores.length-1].valores[alfa]>0.0) * AND desde>=0 * Post: posiciónPositivo(valores,desde)>=desde * AND posiciónPositivo(valores,desde)<=valores.length-1 * AND T[posiciónPositivo(valores,desde)]>0.0 */ private static int posiciónPositivo (double[] valores, int desde) 15 /** * Pre: (EX alfa EN [0,valores.length-1].valores[alfa]>0.0) * Post: posiciónPositivo(valores)>=0 * AND posiciónPositivo(valores)<=valores.length-1 * AND T[posiciónPositivo(valores)]>0.0 */ public static int posiciónPositivo (double[] valores) { return posiciónPositivo(valores, 0); } /** * Pre: (EX alfa EN [desde,valores.length-1].valores[alfa]>0.0) * AND desde>=0 * Post: posiciónPositivo(valores,desde)>=desde * AND posiciónPositivo(valores,desde)<=valores.length-1 * AND T[posiciónPositivo(valores,desde)]>0.0 */ private static int posiciónPositivo (double[] valores, int desde) 16 /** * Pre: (EX alfa EN [desde,valores.length-1].valores[alfa]>0.0) * AND desde>=0 * Post: posiciónPositivo(valores,desde)>=desde * AND posiciónPositivo(valores,desde)<=valores.length-1 * AND T[posiciónPositivo(valores,desde)]>0.0 */ private static int posiciónPositivo (double[] valores, int desde) { if (valores[desde]>0.0) { return desde; } else { /* (EX alfa EN [desde+1,valores.length-1].valores[alfa]>0.0) AND (desde+1)>=0 */ return posiciónPositivo(valores, desde+1); } } Problemas de diseño recursivo 17 Problema 4. Diseñar sin bucles: /** * Pre: T!=null AND T = To * Post: (PT alfa EN [0,T.length-1].T[alfa]=To[T.length-1-alfa]) */ public static <Dato> void invertir (Dato[] T) Problemas de diseño recursivo 18 /** * Pre: T!=null AND T = To * Post: (PT alfa EN [0,T.length-1].T[alfa]=To[T.length-1-alfa]) */ public static <Dato> void invertir (Dato[] T) /** * Pre: T!=null AND * (PT alfa EN [0,invertidos-1]. T[alfa]=To[T.length-1-alfa] * AND T[T.length-1-alfa]=To[alfa]) * AND (PT alfa EN [invertidos,T.length-invertidos-1]. * T[alfa]=To[alfa]) * Post: (PT alfa EN [0,T.length-1].T[alfa]=To[T.length-1-alfa]) */ private static <Dato> void invertir (Dato[] T, int invertidos) Problemas de diseño recursivo 19 /** * Pre: T!=null AND T = To * Post: (PT alfa EN [0,T.length-1].T[alfa]=To[T.length-1-alfa]) */ public static <Dato> void invertir (Dato[] T) { invertir(T,0); } /** * Pre: T!=null AND * (PT alfa EN [0,invertidos-1].T[alfa]=To[T.length-1-alfa] * AND T[T.length-1-alfa]=To[alfa]) * AND (PT alfa EN [invertidos,T.length-invertidos-1]. * T[alfa]=To[alfa]) * Post: (PT alfa EN [0,T.length-1].T[alfa]=To[T.length-1-alfa]) */ private static <Dato> void invertir (Dato[] T, int invertidos) Problemas de diseño recursivo 20 /** * Pre: T!=null AND * (PT alfa EN [0,invertidos-1].T[alfa]=To[T.length-1-alfa] * AND T[T.length-1-alfa]=To[alfa]) * AND (PT alfa EN [invertidos,T.length-invertidos-1]. * T[alfa]=To[alfa]) * Post: (PT alfa EN [0,T.length-1].T[alfa]=To[T.length-1-alfa]) */ private static <Dato> void invertir (Dato[] T, int invertidos) { if (invertidos<T.length/2) { Dato aux = T[invertidos]; T[invertidos] = T[T.length-1-invertidos]; T[T.length-1-invertidos] = aux; invertir(T, invertidos+1); } } Problemas de diseño recursivo 21 Problema 5. Diseñar sin bucles: /** * Pre: T!=null AND T = To * Post: (PT alfa EN [0,T.length-1]. * (To[alfa].compareTo(d)<=0 -> T[alfa]=To[alfa]) * AND (To[alfa].compareTo(d)>0 -> T[alfa]=null)) */ public static <Dato extends Comparable <Dato>> void eliminar (Dato[] T) Problemas de diseño recursivo 22 /** * Pre: T!=null AND T = To * Post: (PT alfa EN [0,T.length-1]. * (To[alfa].compareTo(d)<=0 -> T[alfa]=To[alfa]) * AND (To[alfa].compareTo(d)>0 -> T[alfa]=null)) */ public static <Dato extends Comparable <Dato>> void eliminar (Dato[] T) /** * Pre: T!=null AND hasta<=T.length-1 * Post: (PT alfa EN [0,hasta]. * (To[alfa].compareTo(d)<=0 -> T[alfa]=To[alfa]) * AND (To[alfa].compareTo(d)>0 -> T[alfa]=null)) */ private static <Dato extends Comparable <Dato>> void eliminar (Dato[] T, int hasta) Problemas de diseño recursivo 23 /** * Pre: T!=null AND T = To * Post: (PT alfa EN [0,T.length-1]. * (To[alfa].compareTo(d)<=0 -> T[alfa]=To[alfa]) * AND (To[alfa].compareTo(d)>0 -> T[alfa]=null)) */ public static <Dato extends Comparable <Dato>> void eliminar (Dato[] T) { eliminar(T, T.length-1); } /** * Pre: T!=null AND hasta<=T.length-1 * Post: (PT alfa EN [0,hasta]. * (To[alfa].compareTo(d)<=0 -> T[alfa]=To[alfa]) * AND (To[alfa].compareTo(d)>0 -> T[alfa]=null)) */ private static <Dato extends Comparable <Dato>> void eliminar (Dato[] T, int hasta) 24 /** * Pre: T!=null AND hasta<=T.length-1 * Post: (PT alfa EN [0,hasta]. * (To[alfa].compareTo(d)<=0 -> T[alfa]=To[alfa]) * AND (To[alfa].compareTo(d)>0 -> T[alfa]=null)) */ private static <Dato extends Comparable <Dato>> void eliminar (Dato[] T, int hasta) { if (hasta>=0) { if (T[hasta].compareTo(d)>0) { T[hasta] = null; } /* (To[hasta].compareTo(d)<=0 -> T[hasta]=To[hasta]) AND (To[hasta].compareTo(d)>0 -> T[hasta]=null) */ eliminar(T, hasta-1); } /* (PT alfa EN [0,hasta].(To[alfa].compareTo(d)<=0 -> T[alfa]=To[alfa]) AND (To[alfa].compareTo(d)>0 -> T[alfa]=null)) */ } Problemas de diseño recursivo 25 26