Your SlideShare is downloading. ×
  • Like
Apuntes de fundamentos de programacion 2
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Apuntes de fundamentos de programacion 2

  • 1,941 views
Published

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
1,941
On SlideShare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
28
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Universidad Mayor de San Andr´se Facultad de Ciencias Puras y Naturales Carrera de Inform´tica aFundamentos de la Programaci´n o Jorge Humberto Ter´n Pomier a <teranj@acm.org> La Paz - Bolivia, Diciembre 2006
  • 2. ii
  • 3. PrefacioMotivaci´n o Los conceptos presentados se estudian en muchas de las materias delpregrado de la carrera de inform´tica, con el rigor necesario. Sin embargo, aen mi experiencia docente he podido ver que hay muchos estudiantes quecarecen de elementos pr´cticos con los que puedan aplicar directamente los aconceptos aprendidos y lo que se pretende es cubrir este vac´ıo. El presente texto trata de introducir los conceptos de programaci´n, a oestudiantes de pregrado con un enfoque nuevo. Para una adecuada compresi´n de la tem´tica presentada en el libro, el o alector debr´ tener alguna experiencia en el desarrollo de programas. El libro ano pretende ense˜ar a codificar programas, sino a resolver problemas. nContenido Se presentan en el cap´ ıtulo 1, los conceptos de algor´ ıtmica elemental conel prop´sito de introducir a los estudiantes, al concepto de la eficiencia de los oprogramas. El cap´ ıtulo dos introduce los conceptos de an´lisis de algoritmos con una aserie de ejercicios aplicados. Se incluyen algunos laboratorios que tienen elprop´sito de que, los estudiantes asimilen estos conceptos en forma experi- omental. El cap´ ıtulo tres introduce el concepto de la teor´ de n´meros, introdu- ıa uciendo las librer´ de Java. Se muestran ejemplos de n´meros grandes y ıas uaplicaciones en la criptograf´ ıa. El cap´ ıtulo 4 trata de la escritura de programas con miras a la prueba delc´digo. En este cap´ o ıtulo se introduce un concepto que es el dise˜o por con- n iii
  • 4. ivtratos y la forma de aplicar en Java. Aunque este concepto fue introducidoinicialmente en el lenguaje Eifel, actualmente tiene mucho inter´s en el de- esarrollo de aplicaciones. El texto no trata de trabajar en conceptos de l´gica oformal en su totalidad, lo que propone es una introducci´n a estos conceptos opara facilitar la prueba del c´digo en forma din´mica. o a El cap´ ıtulo 5 complementa el cap´ ıtulo 4 con conceptos de clasificaci´n y ob´squeda . Se introducen laboratorios y las bibliotecas Java para clasificar. u El cap´ıtulo 6 est´ orientado a explicar como se encara la programaci´n a ode problemas de combinatoria b´sica. a El cap´ ıtulo 7 explica como utilizar las librer´ del lenguaje Java y como ıasresolver problemas con pilas, listas enlazadas, conjuntos, ´rboles y colas de aprioridad. EL cap´ ıtulo 8 introduce al estudiante a los problemas de retroceso (bac-tracking) con problemas t´ ıpicos, como recorrido de grafos y permutaciones. El cap´ ıtulo 9 introduce a la geometr´ computacional. Muestra como cons- ıatruir una librer´ de rutinas b´sicas para desarrollar aplicaciones relacionadas ıa aa la geometr´ y muestra las librer´ Java as´ como las posibilidades que se ıa ıas ıtienen con las mismas. El lenguaje que se escogi´ fue el Java, primero porque la formaci´n o oest´ orientada a la programaci´n orientada a objetos. Segundo porque el a olenguaje es de amplia utilizaci´n en las empresas y en la educaci´n. o o Los enunciados orientados a la programaci´n fueron tomados de los con- ocursos de programaci´n, fueron traducidos al espa˜ol manteniendo los datos o nde entrada y salida en ingl´s. Esto se hizo para permitir a los interesados eresolver los problemas y poder validar sus respuestas con el Juez en L´ ıneade Valladolid, en su p´gina web http://acm.uva.es. Estos ejercicios llevan aadelante el n´mero de problema del Juez en L´ u ınea de Valladolid.Aplicaci´n en el aula o Esta tem´tica puede aplicarse en el transcurso de un semestre en clases ate´ricas, pr´cticas y de laboratorio. o a Los laboratorios proponen ejercicios que tienen la finalidad de evaluarexperimentalmente la ejecuci´n de los algoritmos. Esto permite que los estu- odiantes obtengan una vivencia de los resultados te´ricos. o Se puede aplicar en una clase de teor´ de dos per´ ıa ıodos y una segundaclase que ser´ de ejercicios o laboratorio. ıa
  • 5. vContenido del CD El CD adjunto contiene los programas presentados en el texto. Hay queaclarar que todos han sido codificados utilizando el compilador Java 1.5 deSun Microsystems. El cap´ ıtulo 4 relacionado a JML fue codificado con laversi´n 1.4, dado que a la fecha de la redacci´n de la obra no estaba disponible o ouna versi´n de JML que funcionara con la versi´n 1.5. o oAgradecimientos Quiero agradecer a mi esposa, a mis hijos por los aportes realizados yfinalmente al Dr. Miguel Angel Revilla por dejarme reproducir ejercicios delJuez en L´ınea. Lic. Jorge Ter´n Pomier, M.Sc. a
  • 6. vi
  • 7. ´ Indice generalPrefacio III1. Algor´ıtmica elemental 1 1.1. Introducci´n . . . . . . . . . . . . . o . . . . . . . . . . . . . . . 1 1.2. Algoritmo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.3. Problemas e instancias . . . . . . . . . . . . . . . . . . . . . . 2 1.4. Eficiencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.5. Qu´ considerar y qu´ contar . . . . e e . . . . . . . . . . . . . . . 4 1.5.1. Operaciones elementales . . . . . . . . . . . . . . . . . 6 1.5.2. An´lisis del mejor caso, caso a medio y peor caso . . . . 6 1.5.3. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.5.4. Laboratorio . . . . . . . . . . . . . . . . . . . . . . . . 72. An´lisis de algoritmos a 11 2.1. Introducci´n . . . . . . . . . . . . . . o . . . . . . . . . . . . . . 11 2.2. Notaci´n orden de . . . . . . . . . . o . . . . . . . . . . . . . . 11 2.2.1. Propiedades de O grande de n . . . . . . . . . . . . . . 12 2.3. Notaci´n asint´tica condicional . . . o o . . . . . . . . . . . . . . 13 2.4. Notaci´n omega . . . . . . . . . . . . o . . . . . . . . . . . . . . 13 2.5. Notaci´n teta . . . . . . . . . . . . . o . . . . . . . . . . . . . . 13 2.6. An´lisis de las estructuras de control a . . . . . . . . . . . . . . 14 2.6.1. Secuenciales . . . . . . . . . . . . . . . . . . . . . . . . 14 2.6.2. Ciclos For . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.6.3. Llamadas recursivas . . . . . . . . . . . . . . . . . . . 15 2.6.4. Ciclos while y repeat . . . . . . . . . . . . . . . . . . . 15 2.6.5. An´lisis del caso medio . . . . a . . . . . . . . . . . . . . 16 2.6.6. An´lisis amortizado . . . . . . a . . . . . . . . . . . . . . 17 2.7. Soluci´n de recurrencias . . . . . . . o . . . . . . . . . . . . . . 18 vii
  • 8. viii ´ INDICE GENERAL 2.7.1. M´todo por substituci´n . . . . . . . . . e o . . . . . . . . 18 2.7.2. Cambio de variables . . . . . . . . . . . . . . . . . . . 19 2.7.3. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.7.4. M´todo iterativo . . . . . . . . . . . . . e . . . . . . . . 20 2.7.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.7.6. Teorema master . . . . . . . . . . . . . . . . . . . . . . 22 2.7.7. Soluci´n general de recurrencias lineales o . . . . . . . . 23 2.8. Ejercicios resueltos . . . . . . . . . . . . . . . . . . . . . . . . 27 2.9. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.10. Nota sobre el c´lculo integral . . . . . . . . . . a . . . . . . . . 343. Teor´ de n´ meros ıa u 35 3.1. Introducci´n . . . . . . . . . . . . . . . . . . . . . o . . . . . . . 35 3.2. Variables del lenguaje Java . . . . . . . . . . . . . . . . . . . . 35 3.3. C´lculo del m´ximo com´n divisor . . . . . . . . a a u . . . . . . . 37 3.3.1. Divisibilidad . . . . . . . . . . . . . . . . . . . . . . . . 38 3.3.2. Algoritmos extendido de Euclides . . . . . . . . . . . . 41 3.4. M´ ınimo com´n m´ltiplo . . . . . . . . . . . . . . u u . . . . . . . 43 3.5. Aritm´tica modular . . . . . . . . . . . . . . . . . e . . . . . . . 43 3.5.1. Propiedades . . . . . . . . . . . . . . . . . . . . . . . . 44 3.5.2. Congruencias . . . . . . . . . . . . . . . . . . . . . . . 45 3.5.3. Inverso multiplicativo . . . . . . . . . . . . . . . . . . . 45 3.5.4. Soluci´n de ecuaciones . . . . . . . . . . . o . . . . . . . 45 3.6. N´meros primos . . . . . . . . . . . . . . . . . . . u . . . . . . . 47 3.6.1. Generaci´n de primos . . . . . . . . . . . . o . . . . . . . 47 3.6.2. Factorizaci´n . . . . . . . . . . . . . . . . o . . . . . . . 49 3.6.3. Prueba de la primalidad . . . . . . . . . . . . . . . . . 51 3.6.4. Teorema de Fermat . . . . . . . . . . . . . . . . . . . . 51 3.6.5. Prueba de Miller - Rabin . . . . . . . . . . . . . . . . . 52 3.6.6. Otras pruebas de primalidad . . . . . . . . . . . . . . . 52 3.7. Bibliotecas de Java . . . . . . . . . . . . . . . . . . . . . . . . 53 3.7.1. Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . 54 3.8. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 3.8.1. Problema 136 - N´meros Feos . . . . . . . u . . . . . . . 57 3.8.2. Problema 10042 - N´meros De Smith . . . u . . . . . . . 58 3.8.3. Problema 10104 - El problema de Euclides . . . . . . . 59 3.8.4. Problema 10139 - Factovisors . . . . . . . . . . . . . . 59 3.8.5. Problema 106 - Fermat vs. Pit´goras . . . a . . . . . . . 60
  • 9. ´INDICE GENERAL ix4. Codificaci´n con miras a la prueba o 61 4.1. Introducci´n . . . . . . . . . . . . . . . o . . . . . . . . . . . . . 61 4.2. Algunos errores de programaci´n . . . o . . . . . . . . . . . . . 62 4.3. Especificaci´n de programas . . . . . . o . . . . . . . . . . . . . 66 4.3.1. ¿Por qu´ especificar? . . . . . . e . . . . . . . . . . . . . 68 4.3.2. ¿Qu´ especificar? . . . . . . . . e . . . . . . . . . . . . . 69 4.3.3. ¿C´mo especificar? . . . . . . . o . . . . . . . . . . . . . 70 4.3.4. Invariantes . . . . . . . . . . . . . . . . . . . . . . . . . 71 4.3.5. Ejercicios propuestos . . . . . . . . . . . . . . . . . . . 74 4.4. Aplicaciones de las invariantes . . . . . . . . . . . . . . . . . . 75 4.4.1. Principio de correctitud . . . . . . . . . . . . . . . . . 84 4.5. Dise˜o por contratos . . . . . . . . . . n . . . . . . . . . . . . . 85 4.5.1. Especificaci´n de contratos . . . o . . . . . . . . . . . . . 88 4.5.2. Invariantes . . . . . . . . . . . . . . . . . . . . . . . . . 90 4.6. Prueba est´tica . . . . . . . . . . . . . a . . . . . . . . . . . . . 91 4.7. Prueba din´mica . . . . . . . . . . . . a . . . . . . . . . . . . . 92 4.7.1. Afirmaciones . . . . . . . . . . . . . . . . . . . . . . . 92 4.8. Programaci´n bajo contratos con JML o . . . . . . . . . . . . . 95 4.8.1. Especificaci´n de invariantes . . o . . . . . . . . . . . . . 97 4.8.2. Cuantificadores . . . . . . . . . . . . . . . . . . . . . . 98 4.8.3. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 995. Aplicaciones de b´ squeda y clasificaci´n u o 101 5.1. Introducci´n . . . . . . . . . . . . . . . . . . . . . o . . . . . . . 101 5.2. Algoritmos de b´squeda . . . . . . . . . . . . . . u . . . . . . . 101 5.2.1. Prueba exhaustiva . . . . . . . . . . . . . . . . . . . . 105 5.2.2. Representaci´n gr´fica de la b´squeda . . o a u . . . . . . . 107 5.3. Clasificaci´n . . . . . . . . . . . . . . . . . . . . . o . . . . . . . 111 5.3.1. Clasificaci´n en Java . . . . . . . . . . . . o . . . . . . . 113 5.3.2. Algoritmos de clasificaci´n . . . . . . . . . o . . . . . . . 117 5.3.3. Laboratorio . . . . . . . . . . . . . . . . . . . . . . . . 127 5.3.4. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 127 5.3.5. Ejemplo de aplicaci´n . . . . . . . . . . . o . . . . . . . 127 5.4. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 5.4.1. Problema 10107 - Hallar la mediana . . . . . . . . . . . 131 5.4.2. Problema 10295 - C´lculo de salario . . . . a . . . . . . . 132 5.4.3. Problema 331 - Contando los intercambios . . . . . . . 134 5.4.4. Problema 499 - Hallar la frecuencia . . . . . . . . . . . 135
  • 10. x ´ INDICE GENERAL6. Combinatoria b´sica a 137 6.1. Introducci´n . . . . . . . . . . . . . . . . . . . . . . . o . . . . . 137 6.2. T´cnicas b´sicas para contar . . . . . . . . . . . . . . e a . . . . . 137 6.3. Coeficientes binomiales . . . . . . . . . . . . . . . . . . . . . . 139 6.4. Algunas secuencias conocidas . . . . . . . . . . . . . . . . . . 141 6.4.1. N´meros de Fibonacci . . . . . . . . . . . . . u . . . . . 141 6.4.2. N´meros Catalanes . . . . . . . . . . . . . . . u . . . . . 142 6.4.3. N´mero Eulerianos . . . . . . . . . . . . . . . u . . . . . 143 6.4.4. N´meros de Stirling . . . . . . . . . . . . . . . u . . . . . 146 6.4.5. Particiones enteras . . . . . . . . . . . . . . . . . . . . 146 6.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 6.5.1. Problema 357 - Formas de combinar monedas . . . . . 149 6.5.2. Problema 369 - Combinaciones . . . . . . . . . . . . . 150 6.5.3. Problema 10338 - Mal educados . . . . . . . . . . . . . 151 6.5.4. Problema 10183 - Secuencia de Fibonacci . . . . . . . . 1527. Estructuras de datos elementales 153 7.1. Introducci´n . . . . . . . . . . . o . . . . . . . . . . . . . . . . . 153 7.2. Pilas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 7.3. Listas enlazadas . . . . . . . . . . . . . . . . . . . . . . . . . . 157 7.4. Conjuntos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 7.5. Clases map . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 7.6. Clases para ´rboles . . . . . . . a . . . . . . . . . . . . . . . . . 164 7.7. Clases para colas de prioridad . . . . . . . . . . . . . . . . . . 166 7.8. Ejercicios para laboratorio . . . . . . . . . . . . . . . . . . . . 1688. Backtracking 171 8.1. Introducci´n . . . . . . . . . . . . . . . . o . . . . . . . . . . . . 171 8.2. Recorrido de grafos . . . . . . . . . . . . . . . . . . . . . . . . 171 8.3. Constuir todos los subconjuntos . . . . . . . . . . . . . . . . . 175 8.4. Construir todas las permutaciones . . . . . . . . . . . . . . . . 179 8.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 8.5.1. Prolema 195 - Anagramas . . . . . . . . . . . . . . . . 182 8.5.2. Prolema 574 - Sum It Up . . . . . . . . . . . . . . . . 183 8.5.3. Problema 524 - Anillos de primos . . . . . . . . . . . . 185 8.5.4. Problema 216 - Hacer la l´ ınea . . . . . . . . . . . . . . 186
  • 11. ´INDICE GENERAL xi9. Geometr´ computacional ıa 189 9.1. Introducci´n . . . . . . . . . . . . . . . . . . . o . . . . . . . . . 189 9.2. Geometr´ . . . . . . . . . . . . . . . . . . . . ıa . . . . . . . . . 190 9.3. Librer´ de Java . . . . . . . . . . . . . . . . ıas . . . . . . . . . 196 9.4. Cercos convexos . . . . . . . . . . . . . . . . . . . . . . . . . . 198 9.5. Clase Java para pol´ıgonos . . . . . . . . . . . . . . . . . . . . 205 9.6. C´lculo del per´ a ımetro y ´rea del pol´ a ıgo-no. . . . . . . . . . . . 207 9.7. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 9.7.1. Problema 378 - L´ ıneas que intersectan . . . . . . . . . 211 9.7.2. Problema 273 - Juego de Palos . . . . . . . . . . . . . 212 9.7.3. Problema 218 - Erradicaci´n de moscas o . . . . . . . . . 214 9.7.4. Problema 476 - Puntos en rect´ngulos a . . . . . . . . . 216A. Fundamentos matem´ticos a 219 A.1. Recordatorio de logaritmos . . . . . . . . . . . . . . . . . . . . 219 A.2. Recordatorio de series . . . . . . . . . . . . . . . . . . . . . . 220 A.2.1. Series simples . . . . . . . . . . . . . . . . . . . . . . . 220 A.2.2. Serie aritm´tica . . . . . . . . . e . . . . . . . . . . . . . 220 A.2.3. Serie geom´trica . . . . . . . . . e . . . . . . . . . . . . . 220 A.2.4. Propiedades de la sumatorias . . . . . . . . . . . . . . 221 A.2.5. Series importantes . . . . . . . . . . . . . . . . . . . . 221 A.3. Combinatoria b´sica . . . . . . . . . . a . . . . . . . . . . . . . 222 A.3.1. F´rmulas importantes . . . . . o . . . . . . . . . . . . . 222 A.4. Probabilidad elemental . . . . . . . . . . . . . . . . . . . . . . 223 A.5. T´cnicas de demostraci´n . . . . . . . e o . . . . . . . . . . . . . 224 A.5.1. Demostraci´n por contradicci´n o o . . . . . . . . . . . . . 224 A.5.2. Demostraci´n por inducci´n . . o o . . . . . . . . . . . . . 224
  • 12. xii ´ INDICE GENERAL
  • 13. Cap´ ıtulo 1 Algor´ ıtmica elemental1.1. Introducci´n o En este cap´ıtulo empezamos el estudio de los algoritmos. Empezaremosdefiniendo algunos t´rminos tales como algoritmo, problema, instancia, efi- eciencia e investigaremos m´todos para probar la eficiencia de los mismos. e Existen m´todos formales para realizar pruebas rigurosas sobre la correc- eci´n de los programas ´sta tem´tica est´ fuera del alcance del texto pero o e a aser´ mencionada m´s adelante solo como referencia. a a1.2. Algoritmo Definimos como algoritmo a un conjunto de pasos necesarios para re-solver un problema ya sea manualmente o por m´todos mecanizados que, eson los m´s usuales en la actualidad. El concepto de algoritmos fue definido ainicialmente por el matem´tico Persa Al-Khowˆrizmˆ en el siglo diecinueve. a a ı La ejecuci´n de un algoritmo no debe incluir procedimientos intuitivos o oque requieran creatividad. Por ejemplo, una receta de cocina puede denomi-narse un algoritmo si contiene las instrucciones precisas para preparar algo,siempre y cuando no tenga detalles tales como sal al gusto, o cocinar hastaque est´ suave, que son apreciaciones subjetivas del que prepara la receta. e Debemos indicar que los algoritmos deben cumplir un requisito funda-mental y es que todo algoritmo debe terminar en un n´mero finito de pasos. uSi consideramos el sistema operativo veremos que no es un algoritmo porqueno termina nunca, dado que est´ en un ciclo infinito. a 1
  • 14. 2 1. ALGOR´ ITMICA ELEMENTAL Podemos citar algunos ejemplos de algoritmos conocidos, el m´todo de emultiplicar que aprendimos en la escuela, el algoritmo para verificar si unn´mero es primo y muchos otros. u1.3. Problemas e instancias Si pensamos los procedimientos para multiplicar n´meros que conocemos uveremos que hay varias formas de resolver el problema de multiplicaci´n. oTenemos los m´todos que aprendimos en la escuela, m´todos por divisi´n y e e omultiplicaci´n por 2 denominado multiplicaci´n a la rusa y otros. ¿Cu´l de o o a´stas posibles soluciones hay que implementar? Esta decisi´n corresponde ae oun ´rea muy desarrollada en el campo de la inform´tica denominada an´lisis a a ade algoritmos. Una instancia particular ser´ por ejemplo multiplicar el n´mero 123 por ıa uel 4567 pero un algoritmo debe ser capaz de funcionar correctamente no soloen una instancia del m´todo sino m´s bien en todas las instancias posibles. e a Para demostrar que un algoritmo es incorrecto, es suficiente demostrarque es incorrecto para una instancia . As´ como es dif´ probar que un ı ıcilteorema es correcto tambi´n es dif´ probar que un algoritmo es correcto. e ıcil Existen limitaciones propias de las computadoras que ponen restriccio-nes a los algoritmos. Estas pueden ser debido al tama˜o de los n´meros, n uespacio de memoria o almacenamiento. En el an´lisis de los algoritmos, se atrata de analizarlos en forma abstracta inicialmente, pero en el transcursodel texto tambi´n tocaremos aspectos espec´ e ıficos sobre la implementaci´n y ola eficiencia de los mismos.1.4. Eficiencia Cuando tenemos que resolver un problema pueden existir muchos algo-ritmos disponibles. Obviamente quisi´ramos escoger el mejor. De aqu´ nos e ıviene la pregunta ¿Cu´l es mejor? a Si tenemos un problema sencillo con algunas pocas instancias escogemos,lo m´s f´cil y nos despreocupados de la eficiencia. a a Para analizar ´sto tenemos dos m´todos. El m´todo emp´rico tambi´n e e e ı ellamado a posteriori, consiste en programar todos los m´todos y probarlos econ diferentes instancias y con la ayuda de la computadora analizamos y
  • 15. 1.4. EFICIENCIA 3escogemos alguno. El segundo llamado m´todo apriori es el an´lisis te´rico del algoritmo, e a oque con la ayuda de las matem´ticas podemos determinar la cantidad de los arecursos requeridos por cada algoritmo en base del tama˜o de las instancias nconsideradas. El tama˜o de una instancia normalmente est´ definida por el n´mero de n a ubits, en el caso de un grafo por el n´mero de nodos y v´rtices, o en otros u epor el n´mero de elementos a procesar. La ventaja del m´todo te´rico es que u e ono depende de la computadora, lenguaje de programaci´n o implementaci´n o oparticular. En el tratamiento del tema utilizaremos en algunos casos un m´todo eh´ıbrido donde se determinar´ la eficiencia en forma te´rica y se hallar´n los a o avalores num´ricos en forma experimental. e Retornando a la pregunta debemos indicar que la eficiencia se mide entiempo. Para esto diremos que un programa toma un tiempo del orden t(n)para una instancia de tama˜o n. M´s adelante trataremos un t´rmino m´s n a e ariguroso que es la notaci´n asint´tica. o o Si tratamos el tiempo en segundos uno podr´ pensar si tengo una m´qui- ıa ana m´s r´pida el tiempo ser´ menor. ¿C´mo es que este m´todo te´rico llega a a a o e oa ser efectivo? Consideremos que el algoritmo toma un tiempo en segundos t1 (n) parauna m´quina en particular y t2 (n) para otra. Para un n´mero n suficiente- a umente grande podemos hallar unas constantes a y b tales que at(n) = bt(n)esto nos dice que cualquier ejecuci´n del algoritmo est´ acotado por una o afunci´n t(n) y existen unas constantes positivas de proporcionalidad que nos odan el tiempo. Esto indica que si cambiamos de equipo podemos ejecutar elalgoritmo 10 o 100 veces m´s r´pido y que este incremento est´ dado solo a a apor una constante de proporcionalidad. La notaci´n asint´tica dice que un algoritmo toma un tiempo del orden o ode, en funci´n del tama˜o de la instancia . Existen algoritmos que ocurren o nmuy frecuentemente y ameritan tener un nombre que a su vez se denominantasas de crecimiento. Se denominan algoritmos: Constantes los que cuyo tiempo de proceso no depende del tama˜o de n la instancia. Lineales a los que toman tiempos proporcionales a n.
  • 16. 4 1. ALGOR´ ITMICA ELEMENTAL Cuadr´ticos a los que toman tiempos proporcionales a n2 . a C´bicos a los que toman tiempos proporcionales a n3 . u Polinomiales o exponenciales a los que toman tiempos proporcionales a n3 , nk . Logar´ ıtmicos los proporcionales a log n. Exponenciales los que toman tiempos proporcionales a 2n .A´n cuando es deseable siempre un algoritmo m´s eficiente desde el punto u ade vista te´rico podemos en muchos casos escoger en la implementaci´n otro, o odado que las constantes ocultas pueden ser muy grandes y no llegar a ser taneficientes para las instancias que deseamos procesar. La figura 1.1 representalas ordenes magnitud de los algoritmos.1.5. Qu´ considerar y qu´ contar e e Consideremos por ejemplo que queremos hallar el m´ximo de tres n´meros a ua, b, c. Para resolver ´sto escribimos el siguiente c´digo: e omaximo=0maximo=Max(a,b)maximo=Max(c,maximo)Max (a,b) if a > b return a else return b Se puede ver que se requieren exactamente dos comparaciones para deter-minar el valor m´ximo de a, b, c. Si escribi´ramos Max(Max(a,b),c) tambi´n a e ese realizar´ dos comparaciones. Este mismo algoritmo lo podemos escribir ıancomo sigue:maximo=0if (a > b)
  • 17. ´ ´1.5. QUE CONSIDERAR Y QUE CONTAR 5 Figura 1.1: Ordenes de magnitud de algoritmos if(a > c) maximo = a else maximo = celse if b > c maximo = b else maximo = c Vemos que a´n cuando hemos codificado m´s comparaciones en la ejecu- u aci´n solo se ejecutan dos como el caso anterior. Se hace necesario establecer o
  • 18. 6 1. ALGOR´ ITMICA ELEMENTALque es lo que debemos considerar en los programas, ´sto hace necesario defi- enir, lo que se entiende por operaciones elementales.1.5.1. Operaciones elementales Es una operaci´n cuyo tiempo de ejecuci´n est´ acotado por una constante o o aque solo depende de una implementaci´n particular como ser la m´quina, el o alenguaje de programaci´n, etc. o En el ejemplo que realizamos estaremos interesados en medir el n´mero de ucomparaciones necesarias para hallar el m´ximo. El resto de las operaciones alas consideramos operaciones elementales. En el caso de la suma de elementos de un vector lo que deseamos medires la cantidad de sumas realizadas para resolver el problema y las operacio-nes de comparaci´n necesarias para implementar una soluci´n, se consideran o ooperaciones elementales.1.5.2. An´lisis del mejor caso, caso medio y peor caso a El tiempo que toma un algoritmo puede variar considerablemente en fun-ci´n de diferentes instancias de un mismo tama˜o. Para comprender esto o nmejor consideremos el ejemplo del programa de clasificaci´n por inserci´n. o oinserci´n(t) ofor i=1 to n x= t[i] j=i-1 while j > 0 and x<t[j] t[j+1]=t[j] j=j-1 t[j+1]=x Consideremos un conjunto A en el cual queremos procesar el algorit-mo de ordenar. Para ordenar A utilizar´ ıamos inserci´n(A). Si la instancia oA est´ previamente ordenada en forma ascendente podemos probar que el atiempo de proceso es el ´ptimo porque solo inserta valores en el vector y no orealiza intercambios. En el caso de que el vector estuviera ordenado en orden descendente porcada elemento hay que recorrer todo el vector intercambiando los valores.Este claramente es el peor comportamiento que podemos tener.
  • 19. ´ ´1.5. QUE CONSIDERAR Y QUE CONTAR 7 Si el vector estuviera ordenado en forma ascendente no realizar´ ning´n ıa uintercambio y este es el mejor caso en el que se puede estar. Sin embargo si el vector estuviera desordenado en forma aleatoria el com-portamiento se considera del caso medio. Cuando el tiempo de respuesta de un problema es cr´ ıtico normalmenteanalizamos el peor caso que es mucho m´s f´cil de analizar que el caso medio. a aPor lo tanto un an´lisis util de un algoritmo requiere un conocimiento a priori a ´de las instancias que vamos a procesar.1.5.3. Ejercicios 1. Si deseamos verificar que un n´mero es primo, explique si lo que se u desea contar para hallar la eficiencia del algoritmo es: a) el n´mero de u d´ ıgitos b) el n´mero de divisiones que se deben realizar. u 2. Indique que es lo que deber´ıamos contar en el caso de escribir un al- goritmo para multiplicar dos n´meros a fin de hallar el n´mero de u u operaciones requeridas para completar el algoritmo. 3. Suponiendo que el tiempo de proceso de una instancia es un mili segun- dos. ¿En qu´ porcentaje se incrementa el tiempo de proceso al doblar el e tama˜o de la instancia ? si el algoritmo es a) exponencial, b) logar´ n ıtmi- co, c) cuadr´tico? a1.5.4. Laboratorio Se quiere analizar el comportamiento del algoritmo de ordenar por elm´todo de inserci´n en forma experimental. Para esto seguiremos los si- e oguientes pasos: 1. Codificar el algoritmo. 2. Crear una instancia ordenada en forma ascendente. 3. Tomar el tiempo de proceso para diferentes tama˜os de instancias. n 4. Repetir el proceso para una instancia ordenada en forma descendente. 5. Luego para una instancia generada aleatoriamente. 6. Tabular los datos.
  • 20. 8 1. ALGOR´ ITMICA ELEMENTAL 7. Interpretar los resultados.Para realizar ´ste experimento construimos el siguiente programa Java: eimport java.util.*;public class Isort { /** * Rutina Principal para la prueba experimental del * programa de ordenar por el m´todo de inserci´n e o * * @param args * 0 crear las instancias en forma descendente * 1 crear las instancias en forma ascendente * 2 crear las instancias en forma aleatoria */ public static void main(String[] args) { int opcion = Integer.parseInt(args[0]); int instanciaMaxima = 1000000; long tiempoInicio, tiempoFin, tiempoTotal; for (int i = 10; i < instanciaMaxima; i = i * 10) { Arreglo arreglo = new Arreglo(opcion, i); tiempoInicio = System.currentTimeMillis(); arreglo.Ordena(); tiempoFin = System.currentTimeMillis(); tiempoTotal = tiempoFin - tiempoInicio; System.out.println("Tama~o de la instancia " + i n + " Tiempo de proceso " + tiempoTotal); } }}class Arreglo { int[] t = new int[100000]; Random generador = new Random(); int n;
  • 21. ´ ´1.5. QUE CONSIDERAR Y QUE CONTAR 9 Arreglo(int opcion, int n) { this.n = n; for (int i = 0; i < n; i++) { switch (opcion) { case 0: t[i] = i; break; case 1: t[i] = 10000 - i; break; case 2: t[i] = generador.nextInt(10000); } } } void Ordena() { int x, j; for (int i = 1; i < n; i++) { x = t[i]; j = i - 1; while ((j > 0) && (x < t[j])) { t[j + 1] = t[j]; j = j - 1; t[j + 1] = x; } } return; }} El resultado de los tiempos de ejecuci´n, en mili segundos, obtenidos en ola prueba del programa se ven en el cuadro 1.1. Como se ve el peor caso es cuando la instancia que creamos est´ ordenada aen forma descendente. El caso medio se da cuando el vector est´ ordenado aaleatoriamente. En diferentes ejecuciones del programa veremos que el tiempode proceso que se obtiene en el caso medio var´ Esto se debe a que los datos ıa.
  • 22. 10 1. ALGOR´ ITMICA ELEMENTAL Tama˜o n Ordenada Ordenada instancia Instancia Ascendente Descendente Aleatoria 10 0 0 0 100 0 0 0 1000 0 20 10 10000 0 1722 861 100000 10 237622 110229 Cuadro 1.1: Tiempo de ejecuci´n en milisegundos oque se generan no est´n en el mismo orden. Situaci´n que no se da en las a ootras instancias generadas. Una buena aplicaci´n de ´ste c´digo se da en los o e ocasos en que los conjuntos de datos a los que vamos aplicar el m´todo, est´n e acasi totalmente ordenados.
  • 23. Cap´ ıtulo 2 An´lisis de algoritmos a2.1. Introducci´n o Para el an´lisis de los algoritmos es muy importante determinar la eficien- acia de los mismos. Esto se logra a trav´s del c´lculo del tiempo de proceso o e acomplejidad . Como no existen mecanismos normalizados para el c´lculo de aestos tiempos, solo nos referimos al tiempo tomado por el algoritmo multi-plicado por una constante. A esto denominamos notaci´n asint´tica. Existen o otres conceptos, la notaci´n omega, la notaci´n teta y la notaci´n O grande o o osimbolizadas por Ω, θ y O respectivamente. En el texto se enfocar´ al an´li- a asis del tiempo de proceso con la notaci´n O. Se recomienda la bibliograf´ o ıa[McC01] y [EH96]2.2. Notaci´n orden de o La notaci´n orden de nos permite especificar la magnitud m´xima de o auna expresi´n. Sea por ejemplo una funci´n t(n) = 5n2 y podemos pensar o oque n es como el tama˜o de una instancia de un algoritmo dado. Ahora nsupongamos que esta funci´n representa la cantidad de recursos que gasta el oalgoritmo, ya sea el tiempo de proceso, almacenamiento de memoria u otros.Las constantes solo representan valores de una implementaci´n dada y no otienen que ver con el tama˜o de la instancia. n En este caso decimos que esta funci´n t(n) es del orden n2 dado que osolo est´ acotado por una constante. Esto se denomina O grande de t(n) y amatem´ticamente lo representamos como O(n2 ). a 11
  • 24. 12 ´ 2. ANALISIS DE ALGORITMOS2.2.1. Propiedades de O grande de n Para aclarar lo que representa O grande de n describamos sus propieda-des: 1. Regla del valor m´ximo. Dadas dos funciones f (n) y g(n) que pertene- a cen a los n´meros reales positivos incluyendo el cero u O(f (n) + g(n) = max(f (n), g(n)) por ejemplo si se tiene la funci´n t(n) = 5n3 + log n − n aplicando o la regla del valor m´ximo tenemos que O(t(n)) = max(5n3 , log n, −n) a 3 cuyo valor es O(n ). 2. Igualdad de logaritmos. En la notaci´n O la expresi´n o o O(loga n) = O(logb n) que, claramente es incorrecto en las matem´ticas, pero es correcta en a la notaci´n O. o Esto se demuestra aplicando la propiedad de los logaritmos para el cambio de base loga n = logb n/logb a. Notamos que el denominador es una constante y como en la notaci´n O no se escriben las constantes o queda demostrado. 3. Propiedad reflexiva. La notaci´n O es reflexiva dado que: o f (n) O(f (n)) 4. Propiedad transitiva. Sif (n) O(g(n))yg(n) O(h(n))entoncesf (n) O(h(n)). 5. Propiedades de l´ ımites. f (n) + a) si l´ n→∞ ım g(n) ⇒ f (n) O(g(n)) y g(n) O(f (n)) f (n) b) si l´ n→∞ ım g(n) = 0 ⇒ f (n) O(g(n)) pero g(n)¬ O(f (n)) c) si l´ n→∞ f (n) = +∞ ⇒ ım g(n) f (n)¬ O(g(n)) pero g(n) O(f (n))
  • 25. ´ ´2.3. NOTACION ASINTOTICA CONDICIONAL 132.3. Notaci´n asint´tica condicional o o Muchos algoritmos son m´s f´ciles de analizar si restringimos nuestra a aatenci´n a instancias que cumplen alguna condici´n tales como ser una po- o otencia de 2, ser de un tama˜o determinado. Consideremos por ejemplo, un nalgoritmo cuyo resultado para n = 1 es t(n) = 1 y para otros valores to-ma nt(n − 1). Este algoritmo se expresa como una soluci´n recursiva que se oescribe como sigue: 1 si n = 1, T (n) = nT (n − 1) en otros casos.en las secciones siguientes estudiamos como resolver ´stas ecuaciones deno- eminadas recurrencias.2.4. Notaci´n omega o La notaci´n omega que la representamos por Ω se utiliza para representar ola cota inferior de un algoritmo. Por ejemplo el algoritmo de ordenamientopor inserci´n demora O(n2 ) en el peor caso sin embargo la cota inferior para olos programas de clasificaci´n que trabajan unicamente por comparaciones o ´es Ω(n log n) por lo tanto podemos decir que no existen algoritmos de clasi-ficaci´n que en su peor caso sean mejores que Ω(n log n). o Sea t(n) Ω(f (n)) si existe una constante real y positiva d tal que la re-laci´n t(n) ≥ df (n) sea cierta para una cantidad infinita de valores de n, si obuscamos que la relaci´n se cumpla para un n´mero finito de valores de n, o uentonces f (n) es el l´ ımite inferior del algoritmo.2.5. Notaci´n teta o Cuando analizamos un algoritmo estar´ ıamos muy satisfechos si nuestroalgoritmo estuviera acotado simult´neamente por Ω y O. Por esta raz´n se a ointroduce la notaci´n θ. Decimos que un algoritmo es en θ(f (n)) o que f (n) oes de orden exacto si: θ(f (n)) = O(f (n)) ∩ Ω(f (n))
  • 26. 14 ´ 2. ANALISIS DE ALGORITMOSEsta notaci´n se utiliza muy poco y como podr´ apreciar tiene un mayor o agrado de dificultad. Comunmente se utiliza la notaci´n O y para mostrar la orelaci´n contra el mejor algoritmo posible usamos la notaci´n Ω. o o2.6. An´lisis de las estructuras de control a2.6.1. Secuenciales Sean p1 y p2 dos fragmentos de un algoritmo y sean t1 y t2 los tiempos quetoman cada uno respectivamente. La regla de secuencias indica que el tiempode ejecuci´n de la secuencia p1 ; p2 toma un tiempo t1 + t2 . Por la regla del ovalor m´ximo el tiempo es (max(O(t1 ), O(t2 )). Este an´lisis considera que a ap1 y p2 son independientes. Esto es que, el proceso p2 no depende de losresultados de p1 .2.6.2. Ciclos For Consideremos el programa siguiente for i = 1 to m p(i)En este programa no confundamos m con n que es el tama˜o de una instancia. nSi p(i) toma un tiempo constante t y no depende de i entonces este tiempose repetir´ m veces y denotamos esto como: a m m t=t 1 = tm = O(m) i=1 i=1En un caso mas general donde t(i) no es constante y depende de i deber´ ıamoscalcular el resultado de la siguiente sumatoria: m t(i) i=1
  • 27. ´2.6. ANALISIS DE LAS ESTRUCTURAS DE CONTROL 152.6.3. Llamadas recursivas El an´lisis recursivo de un algoritmo es normalmente casi directo y una asimple inspecci´n normalmente nos da una ecuaci´n de recurrencia que re- o opresenta el comportamiento del mismo. Consideremos el problema de buscarun elemento t en un arreglo a recursivamente busca (n) if n =0 return -1 else if a[n]= t return n else return busca(n-1)En este algoritmo podemos ver que para los casos en que n es 0 el tiempoque toma es una constante, cuando encuentra el valor tambi´n el tiempo es euna constante. En los otros casos depende del valor n − 1. Esto podemosrepresentar por una funci´n recurrente de la siguiente forma: o   −1 si n = 0, T (n) = 0 si a[n] = t, T (n − 1) + h(n) en otros casos. El valor de h(n) es el n´mero de operaciones elementales requeridas en cada urecursi´n. Podemos resolver esta recurrencia y demostrar que la soluci´n es o oO(n).2.6.4. Ciclos while y repeat Los ciclos while y repeat son mucho m´s dif´ a ıciles de analizar porque noexiste una forma de saber cuantas veces se va a ejecutar. Para terminar unciclo hay que probar alguna condici´n que nos dar´ un valor de termina- o aci´n.Consideremos el c´digo siguiente : o o ejemplo(n) i=0 while n>1 if par(n) n=n/2
  • 28. 16 ´ 2. ANALISIS DE ALGORITMOS i=i+1 else n=3n/2 i=i+1 return iEn este ejemplo no podemos decidir a simple vista cuantas veces se ejecutala instrucci´n i = i + 1 se ve que cada vez que n es una potencia de 2 se opasar´ por la parte par(n) y cuya cantidad de veces ser´ el log2 n. ¿Qu´ po- a a edemos decir cuando es impar?. ¿El algoritmo termina?. Estas interroganteslas dejamos para el an´lisis del lector. a En muchos casos ser´ necesario aplicar la teor´ de probabilidades para a ıapoder determinar las veces que una instrucci´n se ejecuta. Si podemos deducir ouna recurrencia a partir del algoritmo podemos hallar f´cilmente su O(n). a ejemplo(n) i=0 while n>1 n=n/2 i=i+1 return i En este ejercicio vemos que los valores que toma n son n, n/2, n/4... porlo tanto podemos escribir esta recurrencia como 1 si n < 2, T (n) = T (n/2) + 1 en otros casos. y luego de resolverla podemos indicar que el resultado es O(log n). Losm´todos para resolver recurrencias se explicar´n m´s adelante. e a a2.6.5. An´lisis del caso medio a Consideremos el algoritmo de ordenar por el m´todo de inserci´n e oinserci´n(t) ofor i=1 to n x= t[i] j=i-1 while j > 0 and x<t[j]
  • 29. ´2.6. ANALISIS DE LAS ESTRUCTURAS DE CONTROL 17 t[j+1]=t[j] j=j-1 t[j+1]=xDe este algoritmo podemos ver que en el mejor caso, vale decir cuando losdatos vienen ordenados en forma ascendente, el tiempo es lineal y el peorcaso es de orden cuadr´tico que se da en el caso inverso.¿Cu´l es el com- a aportamiento en el caso promedio? Para resolver esta interrogante se hacenecesario conocer a priori la funci´n de distribuci´n de probabilidad de las o oinstancias que, el algoritmo debe resolver. La conclusi´n del an´lisis del caso o amedio depende de esta suposici´n.o Supongamos que todas las permutaciones posibles de las instancias pue-den ocurrir con la misma probabilidad para determinar el resultado en prome-dio debemos sumar el tiempo que, toma ordenar cada uno de las n! posiblesinstancias. Definamos el rango parcial de T [i] como la posici´n que, ocupar´ o ıaen el arreglo si estuviera ordenado. Supongamos que 1 ≤ i ≥ n y estamosingresando en ciclo while, T [i − 1] contiene los mismos elementos que antes,dado que T [i] todav´ no se ha insertado. Este rango parcial estar´ entre 1 y ıa ai y lo llamaremos k. La cantidad de veces que los elementos del vector se desplazar´n es i − ak + 1 porque los elementos hasta i − 1 ya est´n ordenados. Como tenemos i aelementos la probabilidad que i ocurra es 1/i de aqu´ calculamos el tiempo ıque toma el ciclo while i 1 i+1 ci = (i − k + 1) = i k=1 2como tenemos n elementos en el ciclo principal debemos sumar los tiemposde las instrucciones interiores dando n n n n i+1 i 1 n2 + 3n ci = = + = i=1 i=1 2 i=1 2 i=1 2 42.6.6. An´lisis amortizado a El an´lisis del peor caso es muchas veces muy pesimista. Supongamos que atenemos un programa con un vector que almacena valores y queremos en-contrar el valor m´ınimo. Si el vector est´ ordenado devolver el primero toma aun tiempo constante. Supongamos que enviamos a esta rutina un n´mero u
  • 30. 18 ´ 2. ANALISIS DE ALGORITMOSy si existe devuelve el valor m´ ınimo y si no existe inserta el valor y luegodevuelve el valor m´ ınimo. ¿Cu´nto tiempo toma el algoritmo? En el peor acaso toma el tiempo de insertar y de buscar, sin embargo muchas veces so-lamente tomar´ el tiempo de buscar. Para entender el tiempo amortizado de aeste algoritmo podemos pensar que, en cada b´squeda ahorramos un poco upara gastarlo cuando tengamos que realizar un inserci´n. Esto nos muestra oclaramente que el tiempo amortizado depende de la probabilidad de que ten-gamos inserciones y cual la probabilidad de que tengamos solo b´squedas. uLa esperanza matem´tica es una buena medida para estos an´lisis. a a2.7. Soluci´n de recurrencias o Como ya vimos los algoritmos se pueden representar en forma de ecua-ciones recurrentes aqu´ explicaremos tres m´todos de soluci´n, substituci´n ı e o oo adivinaci´n, iterativos y un m´tdo general para casos especiales. o e2.7.1. M´todo por substituci´n e o El m´todo de substituci´n que bien puede llamarse m´todo por adivi- e o enaci´n se basa en adivinar de que forma es la soluci´n, luego aplicamos la o ohip´tesis inductiva para valores menores y demostrando que ´sto se cum- o eple, decimos que nuestra suposici´n es correcta. Consideremos el siguiente oejemplo: 1 n = 1, T (n) = (2.7.1) 2T (n/2) + n otros casos.La recurrencia 2.7.1 puede escribirse como la ecuaci´n o 2T (n/2) + n (2.7.2)Primero buscamos una soluci´n y suponemos que el tiempo asint´tico O(n) o ode esta ecuaci´n es O(n log n). Debemos probar que ´sta es una funci´n para o e ola cual todos los valores de T (n) son menores con lo cual se demuestra quees una cota superior. Suponiendo que esta soluci´n es aplicable a n/2 para una constante arbi- o
  • 31. ´2.7. SOLUCION DE RECURRENCIAS 19traria c en la ecuaci´n 2.7.2 tenemos: o n n T (n) ≤ 2c( log ) + n 2 2 n = cn log + n 2 = cn log n − cn log 2 + n = cn log n − cn + n ≤ n log n para c ≥ 1Con lo cual estar´ probada nuestra suposici´n. Como ver´ en algunas con- ıa o adiciones es dif´ de probar esta recursi´n. Por ejemplo, consideremos que ıcil oT (1) = 1 reemplazando nuestra hip´tesis se tiene T (1) = c1 log 1 que da oT (1) = c0 y para cualquier valor de c vemos que no es posible probar nues-tra suposici´n por lo que, es usual imponer algunas restricciones tales como oprobar desde T (2). Realizar suposiciones acertadas es muy complicado, por lo que se hacenecesario realizar diferentes pruebas con valores m´ximos y m´ a ınimos parahallar la soluci´n. Lo que estamos realizando es una hip´tesis inductiva y en o omuchas ocasiones podemos agregar m´s constantes por ejemplo, T (n) ≤ cn− ab, el restar algunas constantes de los t´rminos de menor orden es considerada epor muchos como una soluci´n intuitiva. o Este m´todo es un problema, la cota superior probada no garantiza que eexiste otra cota superior que sea menor a la probada. Consideremos porejemplo que se hubiese elegido n2 como una cota superior tambi´n se hubiera e 2probado cierta porque O(n log(n)) ∈ O(n ).2.7.2. Cambio de variables En muchos casos las soluciones tienen formas que no hemos visto antespor lo que no podemos plantear la soluci´n. Consideremos la ecuaci´n: o o √ T (n) = 2T ( n) + log nPodemos simplificar esta ecuaci´n reemplazando n por 2m que nos da o m T (2m ) = 2T (2 2 ) + log 2m m T (2m ) = 2T (2 2 ) + m
  • 32. 20 ´ 2. ANALISIS DE ALGORITMOSahora reemplacemos T (2m ) por S(m) m S(m) = 2S( )+m 2Esta soluci´n ya la conocemos y sabemos que es O(n log n) entonces reem- oplazando en esta respuesta las substituciones que hemos realizado T (n) = T (2m ) = S(m) = O(m log m) = O(log n log log n).2.7.3. Ejercicios 1. Muestre que la soluci´n de T (n) = T (n/2) + 1 es O(log n) o 2. Muestre que la soluci´n de T (n) = T (n/2 + 17) + 1 es O(log n) o √ 3. Resuelva la recurrencia T (n) = T ( n) + 1 realizando cambio de varia- bles2.7.4. M´todo iterativo e El m´todo iterativo es mucho mejor porque no requiere adivinanzas que, epueden hacernos suponer verdaderos resultados err´neos. Pero a cambio se orequiere un poco m´s de ´lgebra. Consideremos la siguiente recursi´n: a a o 1 n = 1, T (n) = T ( n ) + 1 otros casos. 2para resolver ´sta vamos comenzar en T (n) y vamos a desarrollar la misma e n n T (n) = T ( ) + 1 reemplazando n por 2 2 n = T( ) + 2 4 n = T( ) + 3 8 hasta hallar la forma general n = T( k) + k 2cuando n = 1 termina y por lo tanto T (1) toma la forma de: n T (1) = 1 = k 2
  • 33. ´2.7. SOLUCION DE RECURRENCIAS 21reemplazando tenemos: T (n) = 1 + k = 1 + log nde aqu´ sabemos que el tiempo asint´tico de esta recursi´n es O(log n). Re- ı o osolvamos con este m´todo la ecuaci´n 2.7.1 e o 1 n = 1, T (n) = 2T ( n ) + n otros casos. 2desarrollando la recursi´n tenemos o n T (n) = 2T ( ) + n 2 n n = 2(2T ( ) + ) + n 4 2 n n = 4T ( ) + 2 + n 4 2 n = 4T ( ) + 2n 4 n n = 4(2T ( ) + ) + 2n 8 4 n = 8T ( ) + 3n termina cuando 8 = 2k T (1) + knEste algoritmo termina cuando llegamos a T (1); donde toma el valor de 1cuando n/2k = 1. Despejando el valor de k tenemos k = log n reemplazando: T (n) = 2k + kn = n + n log n = O(n log n)Ejemplo:Dar las cotas superiores para T(n) en las siguiente recurrencia. Asumiendoque T(n) es constante para n ≤ 1. T (n) = T (n − 1) + nSoluci´n: oDesarrollando la recursi´n tenemos: o T (n) = T (n − 2) + (n − 1) + n = T (n − 3) + (n − 2) + (n − 1) + n
  • 34. 22 ´ 2. ANALISIS DE ALGORITMOSque toma la forma de n i i=1resolviendo tenemos n(n + 1) 2 2por lo que la cota superior es O(n )2.7.5. Ejercicios 1. Resolver T (n) = 3T (n/2) + n. 2. Resolver T (n) = T (n/3) + T (2n/3) + n. 3. Resolver T (n) = T (n − a) + T (a) + n2.7.6. Teorema master Existen muchas recursiones que tienen la forma n T (n) = aT ( ) + f (n) (2.7.3) bLa ecuaci´n 2.7.3 es un caso t´ o ıpico de soluciones que aplican la t´cnica divide ey vencer´s donde a representa el n´mero de llamadas recursivas T (n/b) el a utama˜o de las llamadas y f (n) el trabajo realizado en cada recursi´n. Esta n oecuaci´n nos da las siguientes soluciones: o   si f (n) = nlogb a− , ≥ 0 ⇒ O(nlogb a ),   si f (n) = nlogb a   ⇒ O(nlogb a log n),   si f (n) = nlogb a+ , ≥ 0 ⇒ O(f (n)),    para polinomios donde  T (n) = (2.7.4)  f (n) = cnk se simplifica   si a > bk   ⇒ O(nlogb a ),   si a = bk   ⇒ O(nk log n),  si a < bk ⇒ O(nk ) La demostraci´n del teorema se puede consultar en la bibliograf´ [GB96] o ıacitada al final del texto. Resuelva los siguientes ejercicios utilizando el teorema master:
  • 35. ´2.7. SOLUCION DE RECURRENCIAS 23 1. n T (n) = 2T ( ) + n 2 En este caso vea que a = 2, b = 2, k = 1 y f (n) = nk aplicando el teorema estamos en el caso a = bk por lo que la soluciones es T (n) = O(nk log n) = O(n log n) 2. T (n) = 9T (n/3) + n Veamos a = 9, b = 3, k = 1 por lo que a ≥ bk entonces la soluci´n es o log3 9 n = O(n2) 3. T (n) = T (2n/3) + 1 Veamos a = 1, b = 2/3, k = 0 por lo que a = bk entonces la soluci´n es o O(nk log n) = O(log n)Ejercicios Resolver utilizando el teorema master. 1. T (n) = 4T (n/2) + n. 2. T (n) = 4T (n/2) + n2 . 3. T (n) = 4T (n/2) + n3 .2.7.7. Soluci´n general de recurrencias lineales o Las recurrencias de la forma a0 tn + a1 tn−1 + .... + ak tn−k = f (n) (2.7.5)se denominan: ecuaci´n l´ o ıneal, homog´nea y de coeficientes constantes. Cuan- edo f (n) es 0 se denomina homog´nea y en otros casos no homog´nea. Una e ebuena descripci´n de como resolver estas recurrencias pueden ver en los libros ode Grimaldi [Gri77] y Knuth [RLG94]
  • 36. 24 ´ 2. ANALISIS DE ALGORITMOSSoluci´n de recurrencias homog´neas o e La soluci´n de una ecuaci´n t(n) puede representarse como la combinacion o olineal de funciones por ejemplo c1 f (n) + c2 g(n).Consideremos la expresi´n o p(x) = a0 xk + a1 xk−1 + .... + ak = 0La soluci´n trivial es cuando x = 0 no es de inter´s. Esta ecuaci´n se denomi- o e ona ecuaci´n caracter´ o ıstica o polinomio caracter´ ıstico. Recordando el ´lgebra, aun polinomio de orden k tiene exactamente k ra´ ıces y puede factorizarsecomo k p(x) = (x − ri ) i=1donde ri son las soluciones de p(x) = 0. Cualquier ri es una soluci´n a ´ste o epolinomio por lo que tambi´n son una soluci´n a t(n) porque cualquier com- e obinacion lineal tambien conforma una soluci´n, por lo que podemos concluir oque k n t(n) = (ci ri ) i=1las soluciones se dan para cualquier constante que se escoja, siempre que lasra´ sean distintas. ıcesEjemplo Consideremos la secuencia de Fibonacci: n si n = 0, n = 1, f (n) = f (n − 1) + f (n − 2) otros casos.reescribimos esta ecuaci´n para satisfacer la ecuaci´n 2.7.5 o o f (n) − f (n − 1) − f (n − 2) = 0Esta ecuaci´n tiene un polinomio caracter´ o ıstico x2 − x − 1 = 0que tiene como soluci´n las ra´ o ıces √ √ 1+ 5 1− 5 r1 = y r2 = 2 2
  • 37. ´2.7. SOLUCION DE RECURRENCIAS 25entonces la soluci´n general es o n n f (n) = c1 r1 + c2 r2ahora utilizando las condiciones iniciales podemos hallar las constantes c1 , c2 c1 + c2 = 0 r1 c 1 + r2 c 2 = 1resolviendo obtenemos 1 1 c1 = √ y c2 = − √ 5 5reemplazando en la ecuaci´n obtenemos o √ √ 1 1+ 5 n 1− 5 n f (n) = √ [( ) −( ) ] 5 2 2Solucici´n de recurrencias no homog´neas o e La recurrencias de la forma a0 tn + a1 tn−1 + .... + ak tn−k = bn p(n) (2.7.6) b es una constante p(n) es un polinomio en n de grado d.Consideremos la recurrencia siguiente: t(n) − 2t(n − 1) = 3n (2.7.7)en este caso b = 3 y p(n) = 1 es un polinomio de grado 0, para resolvereste problema primero lo convertimos a un problema familiar, la recurrenciahomog´nea. Multiplicamos por tres la ecuaci´n 2.7.7 e o 3t(n) − 6t(n − 1) = 3n+1 (2.7.8)ahora cambiemos n − 1 por n 3t(n − 1) − 6t(n − 1) = 3n (2.7.9)
  • 38. 26 ´ 2. ANALISIS DE ALGORITMOSrestando 2.7.7 de 2.7.8 tenemos una ecuaci´n homog´nea o e t(n) − 5t(n − 2) + 6t(n − 2) = 0 (2.7.10)el polinomio caracter´ ıstico es x2 − 5x + 6 = (x − 2)(x − 3)por lo que, las soluciones son de la forma t(n) = c1 2n + c2 3nSin embargo no es cierto que cualquier constante arbitraria producir´ la asoluci´n correcta porque la ecuaci´n 2.7.7 no es la misma que la 2.7.10. o oPodemos resolver la ecuaci´n original en base de t(0) y t(1). La funci´n o ooriginal implica que t1 = 2t0 + 3 por lo que, las ecuaciones a resolver son: c1 + c2 = t(0) 2c1 + 3c2 = 2t(0) + 3de donde obtenemos c1 = t(0) − 3 y c2 = 3. Resolviendo esto tenemos t(n) = (t(0) − 3)2n + 3n+1que es independiente de la soluci´n inicial t(n) O(3n ) o
  • 39. 2.8. EJERCICIOS RESUELTOS 272.8. Ejercicios resueltos 1. ¿Cu´nto tiempo toma el siguiente algoritmo? a l=0 for i=1 to n for j=1 to n^2 for k=1 to n^3 l=l+1 Soluci´n: o Recordando que los ciclos for son las sumas de los tiempos individuales de los procedimientos interiores podemos escribir n n2 n3 T (n) = ( ( 1)) i=1 j=1 k=1 n n2 = ( n3 ) i=1 j=1 n 3 2 =n n i=1 = n n n = n6 3 2 2. ¿Cu´nto tiempo toma el siguiente algoritmo? a l=0 for i=1 to n for j=1 to i for k=1 to j l=l+1 Soluci´n: o
  • 40. 28 ´ 2. ANALISIS DE ALGORITMOS En este caso no todas las sumas son hasta n n i j T (n) = ( ( 1)) i=1 j=1 k=1 n i = ( j) i=1 j=1 n i+1 = i i=1 2 n i2 i = ( + ) i=1 2 2 n n i2 i = + i=1 2 i=1 2 n(n + 1)(2n + 1) n + 1 = + 12 2 2 (n + n)(2n + 1) n + 1 = + 12 2 2n3 + 3n2 + n n + 1 = + 12 2 3 = O(n ) 3. Resolver utilizando el teorema master procedure DC(n) if n < = 1 DC(n/2) for j=1 to n^3 x[j]=0 Soluci´n o Del an´lisis vemos que a 1 n = 1, T (n) = 3 T (n/2) + n otros casos. De donde tenemos a = 1, b = 2, k = 3 lo que nos lleva al caso 1 < 23 dando como soluci´n O(nk ) = O(n3 ). o
  • 41. 2.8. EJERCICIOS RESUELTOS 29 4. Resolver utilizando el teorema master procedure DC(n) if n < = 1 for i=1 to 8 DC(n/2) for j=1 to n^3 x[j]=0 Soluci´n o Del an´lisis vemos que hay la parte de algoritmo que divide el problema a DC(n/2) se procesa 8 veces lo que cambia el problema anterior a 1 n = 1, T (n) = 8T (n/2) + n3 otros casos. De donde tenemos a = 8, b = 2, k = 3 lo que nos lleva al caso 8 = 23 dando como soluci´n O(nk log n) = O(n3 log n). o 5. Dar las cotas superiores para T(n) en las siguientes recurrencias. Asu- miendo que T(n) es constante para n ≤ 1. n T (n) = 2T ( ) + n3 2 Soluci´n: o Desarrollando la recursi´n tenemos: o n T (n) = 2T ( ) + n3 2 n n = 2(2T ( ) + ( )3 ) + n3 4 2 n n3 = 4T ( ) + 2( ) + n3 4 2 n n n3 = 4(2T ( ) + ( )3 ) + 2( ) + n3 8 4 2 n n 3 n3 = 8T ( ) + 4( ) + 2( ) + n3 8 4 2 De aqu´ vemos que para un t´rmino i toma la forma ı e i−1 i n n T (n) = 2 T ( i ) + 2k ( k )3 2 k=0 2
  • 42. 30 ´ 2. ANALISIS DE ALGORITMOS n T(1) se da cuando 2i = 1 entonces i = log(n) reemplazando tenemos: i−1 1 2 T (n) = n + n3 ( ) k=1 2k i−1 1 = n + n3 ( ) k=1 4k i−1 1 1 − ( 1 )i−1 4 ( )= 1 k=1 4k 1− 4 4 1 = (1 − i−1 ) 3 4 4 1 1 = − 3 3 4i−2 4 1 1 = − 3 3 22i−2 4 1 1 = − 2 log(n)−2 3 32 4 1 4 = − 3 3 n2 4 1 4 T (n) = n + n3 ( − ) 3 3 n2 4 4 = n + n3 − n) 3 3 por lo que, la cota superior es O(n3 ) 6. Dar las cotas superiores para T(n) en las siguientes recurrencias. Asu- miendo que T(n) es constante para n ≤ 2. n √ T (n) = 2T ( ) + n 4 Soluci´n: o Desarrollando la recursi´n tenemos: o n n √ T (n) = 2(2T ( )+ )+ n 42 4 n n √ = 4T ( )+2 + n 42 4
  • 43. 2.8. EJERCICIOS RESUELTOS 31 De aqu´ vemos que para un t´rmino i toma la forma ı e i−1 n i n T (n) = 2 T ( i ) + 2k ( ) 4 k=1 4k n t(1) se da cuando 4i = 1 entonces i = log4 (n) adem´s notamos que a i i 2 4 = (2 ) reemplazando tenemos: i−1 i n √ = 2 T (1) + 2k + n k=1 4k i−1 n √ n = + n+ 2k 2 k=1 2k2 i−1 n √ √ = + n+ n 2 k=1 n √ √ = + n + (i − 1) n 2 n √ √ = + n + (log4 (n) − 1) n 2 n √ √ √ = + n + log4 (n) n − n 2 √ por lo que la cota superior es O(log(n) n). 7. Dar las cotas superiores para T(n) asumiendo que T(n) es constante para n ≤ 2. √ T (n) = 2T ( n) + 1 Soluci´n: o Desarrollando la recursi´n tenemos: o 1 T (n) = 2T (n 2 ) + 1 1 2 = 4T (n( 2 ) ) + 2 + 1 1 3 = 8T (n( 2 ) ) + 4 + 2 + 1 que toma la forma de k=i−1 1 i ( 2 )i T (n) = 2 T (n )+ 2k k=0 1 i ( 2 )i = 2 T (n ) + 2i − i
  • 44. 32 ´ 2. ANALISIS DE ALGORITMOS 1 i cuando n( 2 ) = 2 estamos en T(2) que es constante 1 ( )i log(n) = log(2) = 1 2 2i = log(n) T (n) = log(n)T (2) + log(n) − 1 = 2 log(n) − 1 la cota superior es O(log n)2.9. Ejercicios 1. Resolver las siguientes recurrencias utilizando el teorema master, ve- rificar con el m´todo de substituci´n y desarrollando la recurrencia. e o Asuma que T(1)=1. a) T (n) = 2T ( n ) + log(n) 2 b) T (n) = 3T ( n ) + log(n) 3 c) T (n) = 4T ( n ) + log(n) 4 d ) T (n) = 2T ( n ) + n2 2 e) T (n) = 2T ( n ) + n3 2 f ) T (n) = 2T ( n ) + n4 2 √ g) T (n) = (n)T ( n) + n 2. Hallar el O(n) del siguiente programa de b´squeda binaria. u int l,u,m; l=0; u=n-1; while(l<u) { m=(l+u)/2 if (a[mid]< x) l=m+1 else if (a[mid]> x) l=m-1 else
  • 45. 2.9. EJERCICIOS 33 return ("hallado") } return ("no existe">) 3. Hallar el O(n) del siguiente programa para hallar el m´ximo com´n a u divisor. Sugerencia escribir el tama˜o de la instancia en cada iteraci´n n o y aproximar a una serie arm´nica. o mcd(m,n) { while (n> 0){ resto=m%n m=n n=resto } return (m) } 4. Hallar el O(n) del siguiente programa de exponenciaci´n. o pot(x,n) { if (n=0) return 1 if (n==1) return x if (par(n)) return (pot(x*x,n/2)) else return (pot(x*x,n/2)*x) } 5. Realizar una prueba experimental para comprobar las cotas superiores de los programas anteriormente propuestos. 6. Codificar el programa de b´squeda binaria en forma recursiva y hallar u el O(n) 7. Se tienen dos programas A y B cuyo tiempo de ejecuci´n es 150 log(n) o 2 milisegundos y 150n respectivamente. Indique que programa es mejor para n < 100,n < 1, 000, n > 10, 000
  • 46. 34 ´ 2. ANALISIS DE ALGORITMOS2.10. Nota sobre el c´lculo integral a Cuando tenemos una sumatoria, desde nuestras clases de c´lculo, asocia- amos la misma a una integral. Como la sumatoria es acotada, se podr´ pensar ıaen utilizar una integral definida. Consideremos por ejemplo la siguiente sumatoria y su resultado: n n(n + 1)(2n + 1) i2 = (2.10.1) i=0 6 Si suponemos que es posible hallar el resultado integrando la sumatoriase tiene lo siguiente: i3 n n 3 2 i = 0ni = |0 = +c (2.10.2) 3 3 Claramente las ecuaciones 2.10.1 y 2.10.2 son diferentes. ¿Entonces paraqu´ podemos utilizar el c´lculo integral? e a Bien, si queremos obtener la cota superior en la ejecuci´n de un algoritmo, odebemos obtener o(f (n)) de las 2.10.1 y 2.10.2 n(n + 1)(2n + 1) O( ) = n3 6 n3 O( + c) = n3 3 Como ve, ambos resultados nos dan la misma cota superior. En el librode matem´ticas concretas de Donald Knuth [RLG94] se puede encontrar un am´todo para hallar el resultado de una suma a trav´s del c´lculo. e e a
  • 47. Cap´ ıtulo 3 Teor´ de n´ meros ıa u3.1. Introducci´n o Se hace muy importante la teor´ de n´meros en el aprendizaje de la pro- ıa ugramaci´n. Este conocimiento permite comprender los aspectos que hacen al oproceso computacional, tales como las capacidades de la m´quina, el tama˜o a nm´ximo de n´meros que se pueden tratar y como trabajar con n´meros m´s a u u agrandes. En el tratamiento de este cap´ ıtulo se toman en cuenta los aspectos rela-tivos al tiempo de proceso para hacer eficiente los algoritmos expuestos.3.2. Variables del lenguaje Java El lenguaje de programaci´n Java tiene varios tipos de variables enteras oque se muestran en el cuadro 3.1. tipo Nro. Bytes Nro. Bits Rango de n´meros permitido u byte 1 bytes 8 bits desde − (2 + 1) hasta + 27 7 short 2 bytes 16 bits desde − (215 + 1) hasta + 215 int 4 bytes 32 bits desde − (231 + 1) hasta + 231 long 8 bytes 64 bits desde − (263 + 1) hasta + 263 Cuadro 3.1: Tipos de variables enteras en Java Para evaluar el tiempo de proceso de las operaciones de suma, multi-plicaci´n y divisi´n construimos un programa que repita muchas veces una o o 35
  • 48. 36 3. TEOR´ DE NUMEROS IA ´operaci´n, midiendo el tiempo de ejecuci´n. Esto permite determinar cuanto o otiempo consumen los diferentes tipos de variables y escoger la m´s adecuada apara mejorar el tiempo de proceso. El programa siguiente nos permite me-dir el tiempo que toma la operaci´n de multiplicar realizando 10.000.000 de ooperaciones de multiplicaci´n para una variable entera. opublic class Tiempos { /** * Programa para medir el tiempo de proceso en * milisegundos de las operaciones elementales * suma , Multiplicaci´n y divisi´n o o * @author Jorge Teran * @param args * none */ public static void main(String[] args) { int j = 1; long tiempoInicio, tiempoFin, tiempoTotal; tiempoInicio = System.currentTimeMillis(); for (int i = 1; i < 10000000; i++) { j = j * 3; } tiempoFin = System.currentTimeMillis(); tiempoTotal = tiempoFin - tiempoInicio; System.out.println( "Tiempo de proceso de la Multiplicacion " + tiempoTotal); tiempoInicio = System.currentTimeMillis(); }} Una vez procesado este programa contruimos el cuadro 3.2 para compararel tiempo de proceso para cada tipo de variable. Se puede observar que unaoperaci´n de divisi´n demora mucho m´s que una operaci´n de multiplica- o o a oci´n. Tambi´n se observa que las operaciones de tipo long demoran casi el o edoble de tiempo que las operaciones enteras.
  • 49. ´ ´ ´3.3. CALCULO DEL MAXIMO COMUN DIVISOR 37 Operacion tipo Tiempo en mseg para 10.000.000 repeticiones suma int 110 suma long 190 multiplicaci´n o int 140 multiplicaci´n o long 230 divisi´n o int 771 divisi´n o long 2334Cuadro 3.2: Comparaci´n de los tiempos de ejecuci´n de las operaciones o ob´sicas a3.3. C´lculo del m´ximo com´ n divisor a a u Dados dos n´meros enteros se denomina m´ximo com´n divisor al m´xi- u a u amo n´mero que es divisor de ambos n´meros. Como ejemplo, tomemos los u un´meros 20 y 8. Los divisiores del n´mero 20 son: 20,10, 5,4 y 2. Los divi- u usores del n´mero 8 son el 8, 4 y 2. De aqu´ vemos que el m´ximo com´n u ı a udivisor es el n´mero 4. Para resolver adecuadamente este problema se con- utruye un programa, inicialmente con la idea explicada, calculamos su O(n)para posteriormente buscar un soluci´n m´s eficiente. o a Para realizar una primera aproximaci´n a la soluci´n del problema pro- o obaremos todos los n´meros hallando el m´ximo n´mero que divida a ambos. u a uMcd(int a, int b) { int mcd() { int i; for (i=b; i>1;i--){ if (((a%i==0) && (b%i==0))) { break; } } return (i); }}An´lisis: a Se puede apreciar que primero a > b cuando hallamos el primer divisoreste ya es m´ximo porque comenzamos en b y vamos restando de uno en uno. a
  • 50. 38 3. TEOR´ DE NUMEROS IA ´En el peor caso cuando el m´ximo com´n divisor es 1 el algoritmo realiza el a um´ximo n´mero de operaciones. Para calcular el O(n) requerimos resolver a u 1 1=b i=bo sea O(n). Para mejorar este algoritmo se hace necesario analizar algunaspropiedades matem´ticas. a3.3.1. Divisibilidad En la teor´ de n´meros la notaci´n a|b se lee a divide b significa que ıa u ob = ka para alg´n k > 0. Tambi´n se dice que b es m´ltiplo de a. u e u Si a|b decimos que a es un divisor de b por ejemplo los divisores de 20son: 1, 2,4,5 ,10 y 20. Todo entero a, es divisible por el divisor trivial 1. Los divisores no trivialesse denominan factores. Cuando un n´mero tiene como unico divisor el n´mero 1 y a si mismo se u ´ udenomina n´mero primo. uTeorema 1. Para cualquier entero a y un n´mero positivo n existen enteros uk y r tal que 0 ≤ r < n y a = qn + r El valor q = a/n se denomina cociente de la divisi´n y r de denomina oresiduo o resto. El valor r tambi´n se expresa como r = a mod n. De esto evemos que n|a si y solo si a mod n = 0 Si d|b y d|a entonces d es un com´n divisor de a y b. En este caso, se uverifica d|(a + b) y en un caso m´s general d|(xa + yb) a si b|a y a|b significa que a = ±b si b|a significa que b ≤ a o que a = 0El m´ximo com´n divisor de dos n´meros a, b ambos diferentes a cero, se a u udenomina al divisor com´n m´s grande de a, b. Se lo denominamos como u amcd(a, b). Se define mcd(0, 0) = 0. Algunas propiedades son las siguientes:
  • 51. ´ ´ ´3.3. CALCULO DEL MAXIMO COMUN DIVISOR 39 mcd(a, b) = mcd(b, a) mcd(a, b) = mcd(−a, b) mcd(a, b) = mcd(|a| , |b|) mcd(a, ka) = a mcd(a, 0) = |a|Teorema 2. Si a, b son n´meros enteros, diferentes de cero el mcd(a, b) es uel elemento m´s peque˜o del conjunto {ax + by} donde x, y ∈ Z. a nDemostraci´n. Sea q = a/s y sea s el entero m´s peque˜o de la combina- o a nci´n lineal de a y b. Entonces o a mod s = a − qs = a − q(ax + by) = a(1 − qx) + b(qy)Esto muestra que a mod s es una combinaci´n lineal de a y b. El n´mero o um´s peque˜o que puede dar a mod s es 0 dado que a mod s < s. Podemos a nhacer un an´lisis similar y encontrar lo mismo para b. Esto indica que s|a y aque s|b por lo que s es un divisor com´n de a y b. u De ac´ vemos que mcd(a, b) ≥ s. Dado que el mcd(a, b) > 0 y que s divide aa ambos a y b debe dividir tambi´n a una combinaci´n lineal de a y b por lo e oque mcd(a, b) ≤ s. Si mcd(a, b) ≥ s y mcd(a, b) ≤ entonces mcd(a, b) = sDe este teorema podemos deducir las siguientes propiedades: Dados los n´meros enteros positivos a, b, n u si n|ab y mcd(a, n) = 1 entonces b|n. mcd(na, nb) = n mcd(a, b). Si d|a y d|b entonces mcd(a, b)|d.Teorema 3. (Teorema de Euclides) Para cualesquiera dos enteros no nega-tivos a, b mcd(a, b) = mcd(a, mcd(a mod b))
  • 52. 40 3. TEOR´ DE NUMEROS IA ´Demostraci´n. Se puede escribir a como tb + r y reemplazando se tiene o mcd(a, b) = mcd(tb + r, b)cualquier divisor com´n de b y a debe dividir tb + r. Cualquier divisor de de utb tambi´n es divisor de b que implica que cualqiuier divisor de b debe dividir ea r. Ahora vamos a aplicar el algoritmo denominado de Euclides para hallarel m´ximo com´n divisor de dos n´meros. Primeramente escribiremos una a u ufunci´n recursiva para hacer m´s simple el c´lculo de su complejidad. o a aMcd(a,b)if (b==0) return (a) else Mcd(b, a%b)Esta recursi´n la podemos escribir como o 1 si n = 0, T (n) = n T ( b ) + 1 en otros casos.Como ve toma la forma del teorema master n T (n) = aT ( ) + nk bdonde b reduce su tama˜o en a mod b en cada iteraci´n por lo que podemos n oaplicar el teorema y se ve que a = 1, b = a mod b, k = 0 donde a = bk . Estonos dice que el tiempo que toma algoritmo en su peor caso es O(log n). Para ahorrar la memoria utilizada por la recursi´n se presenta una solu- oci´n recursiva opublic class Euclides {/*** Programa para hallar el* maximo comun divisor* con el metodo de Euclides* @author Jorge Teran
  • 53. ´ ´ ´3.3. CALCULO DEL MAXIMO COMUN DIVISOR 41*/int a, b;Euclides(int a, int b) { if (a>b){ this.a = a; this.b = b; } else { this.b = b; this.a = a; } } int mcd() { int r=b; while (b> 0){ r=a%b; a=b; b=r; } return (a); }}3.3.2. Algoritmos extendido de Euclides El algoritmo de Euclides Extendido muestra como calcular los valores x, yde la expresi´n ax + by = mcd(a, b). Conocemos que o mcd(a, b) = mcd(b, r)donde: r = a − b a/bsuponiendo que conocemos x y y tal que rx + by = mcd(b, r) = mcd(a, b)
  • 54. 42 3. TEOR´ DE NUMEROS IA ´reemplazando (a − b a/b )x + by + = mcd(a, b)reordenando ax + b(y − y a/b ) = mcd(a, b) Vemos que cuando a = 0 el valor de x debe ser 0 y y = 1 El siguiente programa realiza el c´lculo de los valores x, y a/*Programa para el algoritmo * extendido de Euclides * @author Jorge Teran * */void eMcd (int a, int b){int x, yAnt, r, aIni, bIni, sr,q;aIni = a;bIni = b;x = 1;yAnt = 0;while (b != 0){ r = a % b; q=a/b; a = b; b = r; sr = x - yAnt*q; x = yAnt; yAnt = sr; } System.out.print("mcd= "+a); System.out.print(" x= "+x); System.out.println(" y= "+((a-x*aIni)/bIni));} Para una mayor comprensi´n se muestra un ejemplo de una ejecuci´n. o oHallemos ax + by = mcd(a, b) con a = 97 y b = 66. El cuadro 3.3 ejemplificala ejecuci´n del programa. o Como se ve la ecuaci´n ax + by = mcd(a, b) se cumple con los ultimos o ´valores obteniendo 97 · (−17) + 66 · 25
  • 55. 3.4. M´ ´ ´ INIMO COMUN MULTIPLO 43 a b q=a/b r mcd sr x y 97*x+66*y 97 66 1 31 66 1 0 1 66 66 31 2 4 31 -2 1 -1 31 31 4 7 3 4 15 -2 3 4 4 3 1 1 3 -17 15 -22 3 3 1 3 0 1 66 -17 25 1 Cuadro 3.3: Prueba de ejecuci´n del algoritmo de extendido de Euclides o3.4. M´ ınimo com´ n m´ ltiplo u u El m´ınimo com´n m´ltiplo (mcm) de dos n´meros es el n´mero m´s u u u u apeque˜o que es divisible por ambos n´meros. Por ejemplo el m´ n u ınimo com´n um´ltiplo entre 9 y 6 es 18. Para el c´lculo del m´ u a ınimo com´n m´ltiplo no u uexiste un algoritmo similar al de Euclides que facilite hallar este n´mero. uEste n´mero se expresa como sigue: u mcm(a, b) = min{k, k > 0 y a|k y b|k} sin embargo es posible probar que mcd(a, b)mcm(a, b) = abEn el ejemplo podemos ver que el mcd(9, 6) es 3 y que 3x18 = 54 = 9x63.5. Aritm´tica modular e La aritm´tica modular es una de las aplicaciones m´s importantes de e ala teor´ de n´meros. Est´ representada por la funci´n mod . La funci´n ıa u a o om´dulo representa el resto de la divisi´n. Por ejemplo a mod b significa que o oqueremos hallar el resto de a que representamos como b a a mod b = a − b (3.5.1) bLa aritm´tica modular tambi´n define un sistema de numeraci´n. Veamos e e opor ejemplo la secuencia:0 mod 3, 1 mod 3, 2 mod 3, 3 mod 3, 4 mod 3....evaluando tenemos 0, 2, 1, 0, 1... que equivale a la numeraci´n en base 3. o
  • 56. 44 3. TEOR´ DE NUMEROS IA ´3.5.1. Propiedades Presentamos algunas propiedades importantes de la aritm´tica modular. eSuma (x + y) mod m = (x mod m + y mod m) mod m. Por ejemplo (8 + 7) mod 3 = 15 mod 3 = 0 y por la propiedad de la suma (8 mod 3 + 7 mod 3) mod 3Resta La resta es solo la suma con valores negativos por los que (x − y) mod m = (x mod m − y mod m) mod m.Multiplicaci´n La multiplicaci´n xy mod m = (x mod m)(y mod m) o o mod m. Esto se da debido a que la multiplaci´n es simplemente una o suma repetida.Divisi´n No existe el inverso de la multiplicaci´n como la conocemos por o o ejemplo veamos dx mod m = dy mod m se puede pensar que pode- mos simplificar d obteniendo x mod m = y mod m, que no se cumple en todos los casos. Veamos un ejemplo 6 · 2 mod 3 = 6 · 1 mod 3 = 0 si simplificamos el 6 tenemos 2 mod 3 = 1 = 1 mod 3 = 2. Solo es posible realizar estas simplificaciones cuando el mcd(d, m) = 1.Existen muchas aplicaciones de la aritm´tica modular, por ejemplo en el ecalendario los d´ de la semana correponden a una aritm´tica m´dulo 7, las ıas e ohoras, minutos y segundos corresponden al m´dulo 60. Hallar el ultimo d´ o ´ ıgitode un n´mero decimal corresponde a una aritm´tica m´dulo 10. u e o El ejemplo que se presenta es extractado de [MAR03]. Hallar el ultimo ´ 100d´ ıgito del n´mero 2 . Para ´sto no es necesario hallar el valor del exponente u ey luego obtener el ultimo d´ ´ ıgito se puede resolver como sigue: 23 mod 10 = 8 26 mod 10 = (8 · 8) mod 10 = 4 212 mod 10 = (4 · 4) mod 10 = 6 224 mod 10 = (6 · 6) mod 10 = 6 248 mod 10 = (6 · 6) mod 10 = 6 296 mod 10 = (6 · 6) mod 10 = 6 2100 mod 10 = 29 6 · 23 · 21 mod 10 = 6 · 8 · 2 mod 10 = 6
  • 57. ´3.5. ARITMETICA MODULAR 453.5.2. Congruencias Se dice que a es congruente b m´dulo m cuando (a − b)/m = km. Se oescribe a ≡ b mod mEsto equivale a que a, b son m´ltiplos de m Algunas propiedades de las con- ugruencias son:Propiedad reflexiva a ≡ aPropiedad sim´trica a ≡ b ⇒ b ≡ a ePropiedad transitiva a ≡ b ≡ c ⇒ a ≡ cSuma a ≡ b y c ≡ d ⇒ (a + c) ≡ (b + d) mod mMultiplicaci´n a ≡ b y c ≡ d ⇒ (ac) ≡ (bd) mod m con b, c enteros oPotencias a ≡ b ⇒ an ≡ bn mod mSi se quiere conocer si 2n −1 es m´ltiplo de 3. Es decir que (2n −1) mod 3 = 0. uPodemos aplicar la propiedad de la potencia y escribir 2 ≡ −1 mod 3 dedonde 2n ≡ (−1)n mod 3. Por lo tanto es m´ltiplo de 3 cuando n es par. u3.5.3. Inverso multiplicativo Consideremos que mcd(a, n) = 1 entonces existen enteros b y c tales queba + cn = 1. Esto se puede escribir como ba ≡ 1 mod n. De aqu´ b se ıdenomina inverso multiplicativo de a.3.5.4. Soluci´n de ecuaciones o La ecuaci´n de congruencia de primer orden est´ definida como: o a ax ≡ b( mod m)Estas ecuaciones tienen soluci´n solo si mcd(a, m)|b Para resolver este tipo ode ecuaci´n se sigue la siguiente estrategia. o ax − b = km ax = b + km y buscamos un k tal que a|(b + km)
  • 58. 46 3. TEOR´ DE NUMEROS IA ´ hallamos xEjemplos: 1. Resolver 6x ≡ 5(mod/3). como mcd(6, 3) = 2 no es divisor de 5,no se tiene una soluci´n. o 2. Resolver 4x ≡ 10(mod/6) 4x = 10 + k6 4x = 10 + 6 con k = 1 x=4 si reemplazamos el valor de x encontrado tenemos: 4 · 4 ≡ 6( mod 6)tambi´n pueden plantearse sistemas de ecuaciones de congruencias, por ejem- eplo, si recogemos una cantidad de cajas en las cuales vienen 3 equipos ytenemos 2 equipos sueltos. Por otro lado si recibimos la misma cantidad deequipos, en cajas en las cuales vienen 5 equipos y tenemos 1 equipo suelto.Se desea conocer cuantos equipos se recibieron. Esto se puede escribir como: x ≡ 3( mod 7) (3.5.2) 5x ≡ 7( mod 12) (3.5.3)si la soluci´n de 3.5.2 es x = 3 + k7 para alg´n valor k podemos reemplazar o ux en la segunda ecuaci´n obteniendo: o 5(3 + k7) ≡ 7( mod 12) 15 + 35k ≡ 7( mod 12) 35k ≡ −8( mod 12)significa que k = 8+12t para alg´n t reemplazando en 3.5.2 x = 3+(8+12k)7 uque da x = 59 + 84t de donde x = 59.
  • 59. ´3.6. NUMEROS PRIMOS 473.6. N´ meros primos u La teor´ de los n´meros primos ha tenido un desarrollo muy intenso con ıa ulas aplicaciones de criptograf´ En esta secci´n le dedicamos un especial in- ıa. oter´s debido a las complejidades que lleva ´ste cuando se trabaja con n´meros e e ugrandes. Se define como primo el n´mero entero positivo que es divisible solamente upor 1 o por si mismo. Los primeros n´meros primos son 2, 3, 5, 7, 11, 19... uComo se ve el unico n´mero primo par es el n´mero 2. El n´mero 1 no ´ u u ues parte de los n´meros primos, sin embargo, algunos autores amplian la udefinici´n para incluirlo. o Para muchas aplicaciones es necesario realizar un test de primalidad quesignifica verificar si el n´mero es primo o no. Esto se puede realizar por udivisiones sucesivas sin embargo no es un m´todo muy adecuado cuando se etrata de n´meros grandes. u3.6.1. Generaci´n de primos o Es posible probar la primalidad de un n´mero n en un tiempo proporcio- √ unal a O( n) con el siguiente c´digo de divisiones sucesivas oj = 2;while (j * j <= n) { if ((i%j)==0) break; //no primo j++;} El problema que representa este m´todo es la cantidad de divisiones que ehay que realizar. Como ya vimos el tiempo que toma una divisi´n es mucho omayor al de la suma. Para convertir ´stas divisiones en suma de n´meros, la e uforma m´s f´cil es a trav´s del m´todo denominado la criba de Erat´stenes. a a e e o La criba de Erat´stenes se contruye a partir de los m´ltiplos de los n´me- o u uros como sigue 1. Se marcan los m´ltiplos de 2. u 2. Luego los de 3, 5, 7, etc. sucesivamente.
  • 60. 48 3. TEOR´ DE NUMEROS IA ´ M´ltiplo de u 2 3 4 5 6 7 8 9 10 11 12 13 14 15 2 x x x x x x 3 x x x x 5 x x Marcados x x x x x x x x Cuadro 3.4: Ejemplo de una criba de Erat´stenes o 3. Una vez completado el marcado los no marcados son los n´meros pri- u mos. Como se observa en el cuadro 3.4 se marcan en la primera pasada losm´ltiplos de 2, la segunda pasada los m´ltiplos de 3 y as´ sucesivamente. u u ıAl terminar el proceso los d´ ıgitos no marcados son los n´meros primos. El usiguiente programa muestra como contar cuantos n´meros primos hay hasta u100.000.000.import java.util.*;/** * Programa contar los n´meros primos u * hasta n = 100,000,000 utilizando la * Criba de Eratostenes * @author Jorge Teran */public class Criba { public static void main(String[] s) { int n = 100000000; long inicio = System.currentTimeMillis(); BitSet a = new BitSet(n + 1); int contar = 0; int i = 2, j = 0; // construccion de la cribafor (i = 2; i * i <= n; i = i + 1) { //el siguiente control es para no pasar //por valores ya tomados en cuenta if (!a.get(i)) { for (j = i + i; j <= n; j = j + i) { a.set(j);
  • 61. ´3.6. NUMEROS PRIMOS 49 } } } // contar los n´meros primos u for (i = 2; i <= n; i++) { if (!a.get(i)) { contar++;}} long fin = System.currentTimeMillis(); System.out.println(contar + " primos"); System.out.println((fin - inicio) + " milisegundos"); }} En la computadora demor´ 78.013 milisegundos dando el resultado de o5.761.455 primos. Los n´meros primos que pueden calcularse a trav´s de este m´todo se u e econsideran n´meros peque˜os. El n´mero m´ximo depende de la memoria u n u ade la m´quina, la implementaci´n realizada y el lenguaje de programaci´n. a o oVea que si almacena solo los n´meros impares puede almacenar el doble de un´meros en la criba. u La p´gina http://primes.utm.edu/ proporciona un acceso importante a la ateor´ de n´meros primos y publica la cantidad de primos por rango conocidos ıa ua la fecha, est´n detallados en el cuadro 3.5. a3.6.2. Factorizaci´n o La factorizaci´n de un n´mero consiste en descomponer el mismo en sus o udivisores. Se demuestra que todos los factores son n´meros primos. Analice uque si uno de sus factores es un n´mero compuesto tambi´n podr´ descom- u e ıaponerse en factores. Para una demostraci´n m´s formal vean [THCR90]. o a La forma de expresar ´stos factores es como sigue: an1 an2 an3 .... e 1 2 3 Los factores primos de 168 son 2, 2, 2, 3, 7 que se expresa como 23 · 3 · 7 =168. El siguiente c´digo muestra el proceso de factorizaci´n de n´meros. Hay o o uque indicar que este proceso es aplicable a n´meros peque˜os. u n
  • 62. 50 3. TEOR´ DE NUMEROS IA ´ Hasta Cantidad de Primos 10 4 100 25 1.000 168 10.000 1.229 100.000 9.592 1.000.000 78.498 10.000.000 664.579 100.000.000 5.761.455 1.000.000.000 50.847.534 10.000.000.000 455.052.511 100.000.000.000 4.118.054.813 1.000.000.000.000 37.607.912.018 10.000.000.000.000 346.065.536.839 100.000.000.000.000 3.204.941.750.802 1.000.000.000.000.000 29.844.570.422.669 10.000.000.000.000.000 279.238.341.033.925 100.000.000.000.000.000 2.623.557.157.654.233 1.000.000.000.000.000.000 24.739.954.287.740.860 10.000.000.000.000.000.000 234.057.667.276.344.607 100.000.000.000.000.000.000 2.220.819.602.560.918.840 1.000.000.000.000.000.000.000 21.127.269.486.018.731.928 10.000.000.000.000.000.000.000 201.467.286.689.315.906.290 Cuadro 3.5: Cantidad de primos por rango conocidos a la fecha
  • 63. ´3.6. NUMEROS PRIMOS 51Factores (Long N){/** * Programa para hallar los factores Primos * @author Jorge Teran */System.out.print( "Los factores primos de: " + N + " son: "); for (long i = 2; i <= N / i; i++) { while (N % i == 0) { System.out.print(i + " "); N = N / i; } } // Si el primer factor ocurre una sola vez if (N > 1) System.out.println(N); else System.out.println();}3.6.3. Prueba de la primalidad La prueba de primalidad es simple para n´meros primos peque˜os. Se u npuede hacer por divisiones sucecivas, a´n cuando, es mejor utilizar una criba ucon n´meros precalculados. Las dificultades en el c´lculo de n´meros primos u a uradica cuando los n´meros a tratar son grandes. Esto hace necesario buscar uotros m´todos para determinar la primalidad de los mismos. Analizamos ealgunos m´todos sin ahondar en las demostraciones que est´n ampliamente e adesarrolladas en la teor´ de n´meros y el ´rea de criptograf´ ıa u a ıa.3.6.4. Teorema de Fermat Este teorema indica que todo n´mero primo cumple la relaci´n: u o an−1 ≡ 1 mod n ∀a ≤ n (3.6.1)por lo que parece suficiente realizar este c´lculo para determinar la primali- adad.
  • 64. 52 3. TEOR´ DE NUMEROS IA ´ Desafortunadamente solo sirve para conocer si un n´mero es compuesto udado que para algunos n´meros primos no se cumple. Estos n´meros se de- u unominan n´meros de Carmichael . Veamos por ejemplo el n´mero compuesto u u561: 2561−1 mod 561 = 1Algunos n´meros que no cumplen este teorema son el 561, 1105, 1729. Estos un´meros se denominan pseudo primos. u Para determinar si un n´mero es compuesto podemos comenzar un al- ugoritmo con a = 2 y el momento que no se cumpla el teorema podemosdecir que el n´mero es compuesto. En otros casos se indica que el n´mero es u uprobablemente primo. La utilidad de este m´todo se ve en el tratamiento de n´meros grandes e udonde la facilidad de la exponenciaci´n m´dulo es mucho m´s eficiente que o o ala divisi´n. o3.6.5. Prueba de Miller - Rabin .- Este algorimo tiene su nombre por los autores del mismo. Esta prue-ba provee un algoritmo probab´ ılistico eficiente aprovechando algunas carac-ter´ısticas de las congruencias. Dado un entero n impar, hagamos n = 2r s + 1 con s impar. Escogemosun n´mero entero aleatoriamente y sea ´ste 1 ≤ a ≤ n. Si as ≡ 1 mod (n) o u e 2j sa ≡ −1 mod (n) para alg´n j, que este en el rango 0 ≤ j ≤ r − 1, se dice uque n pasa la prueba. Un n´mero primo pasa la prueba para todo a. u Para utilizar este concepto se escoge un n´mero aleatorio a. Si pasa la uprueba, probamos con otro n´mero aleatorio. Si no pasa la prueba decimos uque el n´mero es compuesto. Se ha probado que la probabilidad de que, un un´mero a pase la prueba, es de 1 por lo que hay que realizar varias pruebas u 4para tener m´s certeza. a El prop´sito de comentar este algoritmo es el hecho que la implementaci´n o ode Java ya lo incluye en sus m´todos para trabajar con n´meros grandes por e ulo que, no desarrollaremos el algoritmo en extenso.3.6.6. Otras pruebas de primalidad En la (http://mathworld.wolfram.com/search/) enciclopedia de matem´- aticas Mathworld se pueden encontrar otras pruebas de primalidad tanto
  • 65. 3.7. BIBLIOTECAS DE JAVA 53probabil´ısticas, como determin´ ısticas de las que mencionamos: Curva el´ ıpti-ca, test de primalidad de Adleman-Pomerance-Rumely, AKS de Agragual,Lucas-Lehmer, Ward’s y otros. Muchos de ´stos m´todos no se han visto efectivos para la prueba de e eprimalidad cuando se trata de n´meros grandes. u3.7. Bibliotecas de Java La aritm´tica de n´meros grandes es esencial en varios campos tales como e ula criptograf´ Las bibliotecas de Java incluyen una variedad de funciones ıa.para el tratamiento de ´stos n´meros. e u Constructores BigInteger(String val) Permite construir un n´mero grande a partir u de una cadena BigInteger(int largo, int certeza, Random r) Permite construir un n´mero probablemente primo de la longitud de bits especifica- u da, la certeza especificada y random es un generador de n´meros u aleatorios. M´todos e add(BigInteger val) Devuelve this + val compareTo(BigInteger val) Compara this con val y devuelve −1, 0, 1 para los casos que sean <, =, > respectivamente intValue() Devuelve el valor entero de this gcd(BigInteger val) Halla el m´ximo com´n divisor entre this y val a u isProbablePrime(int certeza) .- Prueba si el n´mero es probable- u mente primo con el grado de certeza especificado. Devuelve falso si el n´mero es compuesto. u mod(BigInteger m) Devuelve el valor this mod m modInverse(BigInteger m) Retorna el valor this−1 mod m modPow(BigInteger exponente, BigInteger m) Devuelve thisexponente mod m
  • 66. 54 3. TEOR´ DE NUMEROS IA ´ multiply(BigInteger val) Devuelve this ∗ val pow(int exponente) Devuelve thisexponente probablePrime(int longitud, Random rnd) Devuelve un n´merou probablemente primo. El grado de certeza es 100. Y rnd es un generador de n´meros aleatorios. u remainder(BigInteger val) Devuelve this %val subtract(BigInteger val) Devuelve this − val toString(int radix) Devuelve una cadena en la base especificada.3.7.1. Ejemplo Hallar un n´mero primo aleatorio de 512 Bits. La funci´n probablePrime u outiliza para ´sto las pruebas de Miller-Rabin y Lucas-Lehmer. e/** *Programa para hallar un numero * primo de 512 bits * @author Jorge Teran * */import java.math.BigInteger;import java.util.Random; public class PrimoGrande { public static void main(String args[]) { Random rnd = new Random(0); // generar un probable primo de 512 bits // con una probabilidad de que sea compuesto // de 1 en 2 elevado a l00. BigInteger prime = BigInteger.probablePrime(512, rnd); System.out.println(prime); }}
  • 67. 3.7. BIBLIOTECAS DE JAVA 55Un ejemplo de ejecuci´n del programa es: o11768683740856488545342184179370880934722814668913767795511297683943548586519985787950858001297977310173110996763173093591148833987835653326488053279071057 Veamos otro ejemplo. Supongamos que queremos desarrollar el algoritmode encriptaci´n de llave p´blica RSA . El algoritmo consiste en hallar dos o un´meros d, e que cumplan la propiedades siguientes: c = me mod n y m = ucd mod n. Para resolver esto procedemos como sigue: 1. Escoger dos n´meros primos p y q con p = q u BigInteger p = new BigInteger(longitud/2, 100, r); BigInteger q = new BigInteger(longitud/2, 100, r); 2. Calcular n = pq n = p.multiply(q); 3. Escoger e que sea relativamete primo a (p-1)(q-1) BigInteger m = (p.subtract(BigInteger.ONE)) .multiply(q.subtract(BigInteger.ONE)); e = new BigInteger("3"); while(m.gcd(e).intValue() > 1) e = e.add(new BigInteger("2")); 4. Calcular el multiplicativo inverso de e d = e.modInverse(m); 5. Publicar la clave p´blica como el par p = (e, n) u 6. Publicar la clave privada como el par s = (d, n)Veamos el c´digo completo. Aqu´ hay que hacer notar que en Java existen dos o ıclases para hallar n´meros aleatoreos, Random y SecureRandom. La difrencia uentre ambas est´ en que la clase SecureRandom hace la semilla inicial de ageneraci´n de n´meros menos predecible. Esto significa que de una ejecuci´n o u oa otra la secuencia aleatoria no va a ser la misma.
  • 68. 56 3. TEOR´ DE NUMEROS IA ´import java.math.BigInteger;public class Principal { /** * Programa para utilizar la Clase RSA * @author Jorge Teran * @param args ninguno */ public static void main(String[] args) { Rsa a = new Rsa (100); //Hallar d y e de 100 Bits BigInteger mensaje=new BigInteger("64656667686970"); BigInteger cifrado= a.cifrado(mensaje); BigInteger limpio= a.decifrado(cifrado); System.out.println(mensaje); System.out.println(cifrado); System.out.println(limpio); }}import java.math.BigInteger;import java.security.SecureRandom;class Rsa{ private BigInteger n, d, e; public Rsa(int longitud){ SecureRandom r = new SecureRandom(); BigInteger p = new BigInteger(longitud/2, 100, r); BigInteger q = new BigInteger(longitud/2, 100, r); n = p.multiply(q); BigInteger m = (p.subtract(BigInteger.ONE)) .multiply(q.subtract(BigInteger.ONE)); e = new BigInteger("3"); while(m.gcd(e).intValue() > 1) e = e.add(new BigInteger("2")); d = e.modInverse(m); }
  • 69. 3.8. EJERCICIOS 57 public BigInteger cifrar(BigInteger mensaje) { return mensaje.modPow(e, n); } public BigInteger decifrar(BigInteger mensaje) { return mensaje.modPow(d, n); }}3.8. Ejercicios A continuaci´n se presentan varios problemas que est´n asociados a la o atem´tica presentada. Estos problemas se pueden ver en su versi´n original en a oingl´s en el sitio de la Universidad de Valladolid http://online-judge.uva.es/. eEl n´mero de problema especificado es el n´mero de problema publicado en u ula UVA. Esto se utilizar´ tambi´n en cap´ a e ıtulos posteriores.3.8.1. Problema 136 - N´ meros Feos u Los n´meros feos son n´meros cuyos unicos factores primos son 2, 3, o 5. u u ´ La secuencia 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, .... Muestra los primeros 11 n´- umeros feos. Por convenci´n se incluye el 1. o Esto equivale a encontrar los n´meros que se pueden formar por 2a 3b 5c . uEscriba un programa que encuentre e imprima el n´mero 1500.u Entrada y salida.- No existe entrada en este problema. La salida debeconsistir de una l´ ınea reemplazando n´mero con el n´mero calculado. u u Ejemplo de salida The 1500’th ugly number is n´mero. u
  • 70. 58 3. TEOR´ DE NUMEROS IA ´3.8.2. Problema 10042 - N´ meros De Smith u Mientras le´ su gu´ de tel´fonos en 1982, Albert Wilansky, un matem´ti- ıa ıa e aco de la universidad de Lehigh, not´ que el n´mero de tel´fono de su cu˜ado o u e nH. Smith ten´ la siguiente caracter´ ıa ıstica peculiar: La suma de los d´ ıgitos deese n´mero era igual a la suma de los d´ u ıgitos de los factores primos de esen´mero. El n´mero de tel´fono de Smith era 493-7775. Este n´mero se pue- u u e ude escribir como el producto de sus factores primos de la siguiente manera:4937775 = 3 ∗ 5 ∗ 5 ∗ 65837. La suma de todos los d´ ıgitos del n´mero de tel´fono es 4 + 9 + 3 + 7 + u e7 + 7 + 5 = 42, y la suma de los d´ ıgitos de los factores primos es igualmente3 + 5 + 5 + 6 + 5 + 8 + 3 + 7 = 42. Wilansky fue as´ que sorprendido por ısu descubrimiento que nombr´ a este tipo de n´meros; con el nombre de su o ucu˜ado, N´meros de Smith. Una lista peque˜a de n´meros de Smith es 4, n u n u22, 27, 58, 85, 94, 121, 166, 202, 265. Pues esta observaci´n es tambi´n verdad para cada n´mero primo, Wi- o e ulansky decidi´ m´s adelante que el n´mero primo no es igual que el n´mero o a u ude Smith y ´l los excluy´ de la definici´n. e o o Problema.- Wilansky public´ un art´ o ıculo acerca de los n´meros de Smith uen ”Two Year College Mathematics Journal”. Fue capaz de presentar unacolecci´n de diversos n´meros de Smith: Sin embargo, Wilansky no pod´ o u ıadar un n´mero de Smith que sea m´s grande que el n´mero de tel´fono de u a u esu cu˜ado. Esta es su tarea, encontrar los n´meros de Smith que son m´s n u agrandes que 4937775. Entrada.- El n´mero que se introduce en la primera l´ u ınea de entrada es eln´mero de casos de prueba. Cada caso de prueba consiste de una l´ u ınea que 9contiene un solo n´mero entero positivo m´s peque˜o que 10 . u a n Salida.- Para cada valor de n, se tiene que calcular el n´mero de Smith um´s peque˜o, que sea mayor a n (o que est´ por encima de n) e imprimir a n ecada n´mero en una sola l´ u ınea. Asumir que existe tal n´mero. u Ejemplo de entrada Ejemplo de salida 1 4937775 4937774
  • 71. 3.8. EJERCICIOS 593.8.3. Problema 10104 - El problema de Euclides Desde la ´poca de Euclides se conoce que para cualquier entero positivo eA y B existen enteros X y Y que AX + BY = D, donde D es el m´ximo acom´n divisor de A y B. El problema es encontrar los correspondientes X, Y uy D. Entrada.- La entrada consiste de un conjunto de l´ ıneas con n´meros en- uteros A y B, separados por un espacio (A, B < 1000000001). Salida.- Para cada l´ ınea de entrada la salida debe consistir de tres enterosX, Y y D, separados por un espacio.Si hay m´ltiples X y Y , debes imprimir uel par para el cual |X| + |Y | es m´ ınimo (primordialmente). Ejemplo de entrada Ejemplo de salida 46 -1 1 2 17 17 0 1 173.8.4. Problema 10139 - Factovisors La funci´n factorial, n! est´ definida para todos los enteros no negativos o acomo sigue: 0! = 1n! = n ∗ (n − 1)! (n > 0) La entrada para el programa consiste de varias l´ ıneas. Cada una conte- 31niendo dos enteros no negativos, n y m, menores a 2 . Cada l´ ınea de salidaconsiste de una l´ ınea indicando si m divide a n!, en el formato que se muestra. Ejemplo de entrada Ejemplo de salida 69 9 divides 6! 6 27 27 does not divide 6! 20 10000 10000 divides 20! 20 100000 100000 does not divide 20! 1000 1009 1009 does not divide 1000!
  • 72. 60 3. TEOR´ DE NUMEROS IA ´3.8.5. Problema 106 - Fermat vs. Pit´goras a Las pruebas asistidas por computadora ocupan un verdadero nicho enlas ciencias de la computaci´n. La primera prueba de muchos problemas ofue completado con la ayuda de un programa de computadora. Esfuerzoscorrientes en verificaci´n han tenido ´xito en verificar la traducci´n de c´digo o e o ode alto nivel a nivel del chip. Este problema trata de calcular cifras relacionadas a una parte del ultimo ´teorema de Fermat: que explica que no existen soluciones enteras para an +bn = cn con n > 2. Problema Dado un entero positivo N , escriba un programa que calculedos valores respecto la soluci´n de o x2 + y 2 = z 2donde x, y, y z son valores enteros positivos menores o iguales N . Se tieneque computar el n´mero de triples (x, y, z) que sean primos relativos, tal que ux < y < z, es decir no tienen un com´n divisor mayor que 1. Tambi´n tiene u eque calcular el n´mero de valores tal que p no es parte de alg´n triple. u u Entrada.- La entrada consiste de una secuencia de enteros positivos, unopor l´ ınea. Cada entero en el archivo de entrada es menor o igual a 1, 000, 000.La entrada termina con fin de archivo. Salida.- Para cada entero N en el archivo de entrada imprime dos enterosseparados por un espacio. El primer entero es el n´mero de primos relativos utriples (tal que cada componente del triple es ≤ N . El segundo n´mero ues el n´mero de enteros positivos que no son parte de alg´n triple cuyos u ucomponentes son ≤ N . Debe haber una l´ ınea de salida por cada l´ ınea deentrada. Ejemplo de entrada Ejemplo de salida 10 14 25 49 100 16 27
  • 73. Cap´ ıtulo 4 Codificaci´n con miras a la o prueba4.1. Introducci´n o La prueba de programas de software ha sido siempre un campo muy ´rido ay no se ha tomado en cuenta en el momento del desarrollo del c´digo. Para odesarrollar programas m´s fiables se hace necesario planificar la verificaci´n a odel c´digo al momento de su construcci´n. Durante muchos a˜os se han o o nprometido programas que podr´ verificar a otros. Desde la d´cada de los ıan e60 seguimos esperando. A´n no existe esta posibilidad. u Hoy en d´ se hace mucho m´s importante la verificaci´n de los progra- ıa a omas. Existen programas en diferentes industrias que, en caso de fallas puedencausar inclusive la muerte de personas y otros que no permiten pruebas ex-perimentales. Como ejemplo, podemos mencionar los programas que controlan el vuelode los aviones, servomecanismos asistidos por computadora e inclusive mu-chos de los electrodom´sticos que existen en su hogar. e Tradicionalmente la prueba del software ha sido presentada como un de-talle de pruebas denominadas de caja negra y caja blanca. Las pruebas decaja negra son aquellas que se enfocan en el exterior del m´dulo sin importar oel c´digo. Las pruebas de caja blanca son m´s amplias y tratan de verificar o ael c´digo probando partes indicando la cobertura del c´digo probado. Estos o oplanes de prueba han dado como resultado que durante la explotaci´n del osoftware siguen apareciendo errores no detectados en la prueba. 61
  • 74. 62 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA Hoy en d´ se tiene un conocimiento m´s profundo de la programaci´n y ıa a ose pueden realizar muchas m´s verificaciones que, solo las de la caja negra aque pueden indicarnos bien o mal. El control de calidad y la verificaci´n de programas nos permite encontrar oerrores de los programas. La codificaci´n es una de las habilidades requeridas opara esto. En el presente cap´ ıtulo presentaremos una serie de t´cnicas que ayudan ea la prueba y mantenimiento del c´digo. No se trata de ninguna manera ode entrar en el campo de la verificaci´n formal de programas, sin embargo, oespero que sirva de una buena introducci´n. Se presenta la especificaci´n o oformal, las aserciones y la programaci´n por contrato. o4.2. Algunos errores de programaci´n o Cuando revisaba las revistas Comunicati´n of the ACM [KBO+ 05] en- ocontr´ una serie de preguntas sobre errores existentes en diferentes c´digos. e oEstos errores normalmente no son vistos por los programadores proveen unapuerta por donde se producen fallos mal intencionados durante la explotaci´n odel programa. Por este motivo quiero presentar este tema. El desborde de la memoria se produce cuando se accede fuera de lasdimensiones de la variable definida. Por ejemplo salirse del tama˜o de un nvector incrementando el tama˜o del ´ n ındice fuera de los l´ ımites del mismo. Veamos un ejemplo:void copia(char[] b) { char[] datos = new char(100); for (int i=1;i< b.length; i++) datos[i]=b[i] .. .. .. } returnEn el segmento de c´digo expuesto se puede apreciar que se copia el vector ob a datos pudiendo causarse un desborde en datos si es que b es de mayortama˜o que datos. n
  • 75. ´4.2. ALGUNOS ERRORES DE PROGRAMACION 63 Normalmente, durante la ejecuci´n, se obtendr´ un error de ´ndice fuera o a ıde rango. Cuando colocamos un programa en producci´n generalmente se orecompilan los c´digos con argumentos de optimizaci´n y el control de ´ o o ındicesfuera de rango queda eliminado. En estos casos al no producirse este error seobtienen mensajes tales como error de segmentaci´n, error de bus. o Estos errores se producen al reescribir parte del c´digo con datos, al salirse odel rango del vector datos. Como, se va ha reescribir parte del c´digo, un ointruso puede enviar una serie de c´digos que quiere ejecutar. o Veamos un ejemplo escrito en lenguaje C.//programa para desplegar el primer// argumento de la l´nea de comando ı// desp.c// Autor Jorge Teran#include <stdio.h>#include <stdlib.h>#include <string.h> int main(int argc, char *argv[]) { char copia[2]; strcpy(copia,argv[1]); printf("%sn", copia); return 0; } Como se ve este programa despliega en pantalla el argumento introducidoen la l´ ınea de comando, y la ejecuci´n del mismo se ve as´ o ı:>desp 1212Que pasa si en la invocaci´n al mismo colocamos m´s de dos d´ o a ıgitos?>desp 1234512345Cuando llegamos a 6 d´ ıgitos obtenemos una lista interminable de
  • 76. 64 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA>desp 123456123456123456123456....Claramente hemos invadido el ´rea de c´digo y eliminado parte de la instruc- a oci´n return de la rutina printf. Si introducimos m´s valores se obtienen otros o aerrores. Como se dijo, ´sto puede ser un mecanismo para introducir c´digos e oa un programa y hacer que realice algo para lo que no ha sido dise˜ado. n Es posible que se cambie el c´digo para realizar un chequeo de ´ndice o ıfuera de rango durante la copia pero, consume m´s tiempo de proceso. a Lo que queremos expresar con este ejemplo es que a´n cuando un pro- ugrama haya sido probado y se supone que funciona correctamente puedepresentar fallas. Tal es el caso de la rutina strcpy mostrada. Con respecto al lenguaje de programaci´n podemos preguntarnos cual olenguaje ofrece mejores condiciones en el tiempo de proceso durante la eje-cuci´n del programa. La respuesta es bastante obvia. Cuanto m´s controles o ase tengan se demorar´ m´s tiempo de proceso. Y en caso contrario se tienen a aalgunas inseguridades a cambio de una mejora en la ejecuci´n. o En el caso del lenguaje Java al ejecutarse en un entorno cerrado proveecontrol sobre la ejecuci´n del c´digo que es inexistente en el lenguaje C. Esto o ohace que este tipo de problemas no se presenten en algunos lenguajes comoel Java. Existen algunas soluciones que se pueden adoptar para resolver este tipode problemas por ejemplo, introducir un control de sub´ ındices durante lacopia, proteger la memoria donde se encuentra la direcci´n de retorno a solo olectura. Estas acciones hacen el tiempo de proceso m´s lento. a La programaci´n Java no est´ exenta de fallas que se producen en la eje- o acuci´n del c´digo, por situaciones no previstas. Para ejemplificar supongamos o ola clase N ombre que tiene un m´todo para devolver el nombre. eclass Nombre { String nombre; Nombre(String n) { nombre=n; }
  • 77. ´4.2. ALGUNOS ERRORES DE PROGRAMACION 65 String devuelveNombre() { return (nombre); }}Suponga que quiere utilizar la clase N ombre como sigue: Nombre persona = new Nombre(nombrePersona); int largo=persona.devuelveNombre().trim().length(); Analizando vemos que se trata de calcular la longitud del nombre. ¿Qu´ pasa cuando nombreP ersona es un valor nulo? e Claramente obtendremos un error de ejecuci´n indicando la l´ o ınea dondese produjo el error. El mensaje del sistema no dice cual es la causa del error. Para solucionar este problema en medio de la ejecuci´n de un sistema ose tiene que corregir el programa para tomar en cuenta este posible errormodificando el c´digo como sigue: o Nombre persona = new Nombre(nombrePersona); int largo=0; String dato = persona.devuelveNombre(); if (dato == null) { System.err.println("Error grave: Falta la propiedad ’nombre’ "); } else { largo=dato.trim().length(); }Ahora estamos seguros que el programa funciona y que, cuando da el erroridentifica claramente el problema. Bien supongamos que, ahora que est´ se-aguro que el programa no falla se pone el programa en ejecuci´n en un sistema odistribu´ıdo, puede ocurrir que no se encuentre la clase persona y el sistemafalle. Para esto hay que volver a corregir el c´digo adicionando un control: o
  • 78. 66 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA Nombre persona = new Nombre(nombrePersona); if (persona == null) { System.err.println( "Error grave: clase Persona no disponible"); } int largo=0; String dato = persona.devuelveNombre(); if (dato == null) { System.err.println( "Error grave: Falta la propiedad ’nombre’ "); } else { largo=dato.trim().length(); }Estas consideraciones hacen necesario especificar el c´digo de una forma que, ose pueda determinar una serie de problemas con mucha anticipaci´n. o4.3. Especificaci´n de programas o La especificaci´n de programas tienen su origen en Hoare [Hoa83] quien odesarroll´ las bases para la especificaci´n formal de programas. Tambi´n o o epuede ver un excelente trabajo que describe esta axiom´tica en [CK79]. a Cuando se especifica un programa hay que considerar que no solo puedetener errores, tambi´n puede ser que est´ equivocada la especificaci´n del e e omismo. Por esta raz´n tambi´n deben verificarse las especificaciones de los o emismos. Aunque no es parte del texto un tratamiento riguroso de la verifica-ci´n y prueba de programas, es necesario introducir este tema que se estudia oen los cursos de m´todos formales. e
  • 79. ´4.3. ESPECIFICACION DE PROGRAMAS 67Precondici´n Son lo valores iniciales que toman las variables del programa, o o tambi´n los pre requisitos necesarios para su correcto funcionamiento. e Por ejemplo puede ser que una variable no sea nula, que los datos esten ordenados, la existencia de una clase, etc.Post condici´n Son los valores finales que toman las variables del programa o Todo programa consiste de tres partes: 1. Inicializaci´n o 2. Preservaci´n de propiedades o 3. Terminaci´n oLa preservaci´n de propiedades se denomina invariante y es lo que nos permite overificar el c´digo. o Llamemos a {P } precondici´n, a {Q} post condici´n y C un programa. o oLa notaci´n o {P }C{Q}significa que si partimos de un estado P despu´s de que el programa termine ellegaremos al estado Q. Esta notaci´n se debe a Hoare [Hoa83]. oEjemplo: {X = 1}X = X + 1{X = 2}Este peque˜o c´digo especifica que si X es inicialmente 1 una vez corrido el n oprograma X toma el valor de 2 que es claramente verdadero. Normalmente en esta notaci´n las precondiciones y las variables se escri- oben en letras may´sculas. Las letras min´sculas se utilizan para especificar u uvalores. Por ejemplo para indicar que la variable X toma una valor arbitrariox se escribe X = x. Una expresi´n del tipo {P }C{Q} es una especificaci´n de correctitud o oparcial porque para verificar que es correcta, no es necesario que el programaC termine. Una especificaci´n m´s fuerte es la especificaci´n de correctitud total en o a ola que se pide la prueba de que el programa termine. La notaci´n que se outiliza para esto es: [P ]C[Q]
  • 80. 68 ´ 4. CODIFICACION CON MIRAS A LA PRUEBAla relaci´n que existe entre ambas definiciones es: o correctitud total = terminacion + correctitud parcialPor ejemplo si queremos especificar la correctitud total de que los valores deX, Y se intercambian podemos escribir: [X = x ∧ Y = y] R = X; X = Y ; Y = R [X = y ∧ Y = x] No todas las variables deben especificarse en una precondici´n, veamos ocomo ejemplo una divisi´n por restas sucesivas: o {Y = y ∧ X = y} R = X; Q = 0; W HILE Y ≤ R R = R − Y ;Q = Q + 1 {R < y ∧ X = R + (Y xQ)}Este ejemplo es menos intuitivo para la verificaci´n pero nos indica clara- omente que el resultado depende de los valores de X y Y . El valor de Q y Rest´n especificados solo en la post condici´n. a o Como no se especificaron en la precondici´n no se puede decir nada de oellos antes de la ejecuci´n del c´digo. o o4.3.1. ¿Por qu´ especificar? e La primera pregunta que uno se hace es por qu´ especificar?. Uno puede eespecificar para tener mayor documentaci´n del sistema, desea una descrip- oci´n m´s abstracta o porque desea realizar un an´lisis del mismo. o a a Lo que uno debe preguntarse es porque especificar formalmente y lasrespuestas que se pueden conseguir de desarrolladores profesionales son: 1. Mostrar que una propiedad se mantiene globalmente en un programa Se quiere caracterizar la condici´n de correctitud. o Se quiere mostrar que la propiedad es realmente una invariante. Se quiere mostrar que mi sistema cumple alg´n criterio de alto u nivel en el dise˜o. n
  • 81. ´4.3. ESPECIFICACION DE PROGRAMAS 69 2. Manejo de errores Se quiere especificar que ocurre cuando se produce un error. Se quiere especificar que las cosas correctas ocurren cuando se produce un error. Se quiere estar seguro que no exista este error. 3. Completitud Se quiere estar seguro que se ha cubierto todos los casos, inclu- yendo los casos de error. Se quiere saber si el programa que he dise˜ado es computacional- n mente completo. 4. Especificar interfases Se quiere definir una jerarqu´ de clases. ıa Se quiere una descripci´n m´s formal de la interfase del usuario. o a 5. Manejar la complejidad El dise˜o est´ muy complicado para manejar todo en la cabeza y n a necesitamos una forma de pensar en pedazos m´s peque˜os. a n Cumplir los requisitos legales de algunos pa´ ıses. 6. Cambiar el control Cada vez que cambio un pedazo de c´digo quisiera conocer que o otras partes son afectadas sin mirar todos los m´dulos y sin mirar o el c´digo fuente. o4.3.2. ¿Qu´ especificar? e Los m´todos formales no est´n desarrollados de tal forma que un sistema e aentero y muy grande pueda ser especificado completamente. Solo se puedenespecificar algunos aspectos tales como funcionalidad y comportamiento deun sistema de tiempo real. Al escribir una especificaci´n uno debe decidir si la descripci´n es reque- o orida y permitida. ¿Puede o debe? Una vez que uno tiene claro lo que hay queespecificar uno puede determinar que puede formalizarse.
  • 82. 70 ´ 4. CODIFICACION CON MIRAS A LA PRUEBACondiciones de correctitud Esto implica la noci´n de una condici´n global de correctitud que el sis- o otema debe mantener.Invariantes La forma de caracterizar algunas condiciones que no cambian de un esta-do a otro se denominan invariantes. Las invariantes son una buena forma decaracterizar las propiedades deseadas de un sistema. Formalizar las transicio-nes le permite probar que se mantienen durante la ejecuci´n del programa. oComportamiento observable Se denomina cuando se especifica el comportamiento del sistema cuandointeract´a con su ambiente. uPropiedades de entidades Las propiedades m´s importantes de las entidades se expresan comunmen- ate por el tipo. La correspondencia entre este tipo de propiedades se verificapor el compilador. Sin embargo, para entidades estructuradas podemos verotras propiedades de las que, podemos anotar por ejemplo: Orden. ¿Los elementos est´n ordenados? a Duplicados. ¿Se Permiten? Rangos. ¿Pueden acotarse los elementos de alguna manera? Acceso asociativo. ¿Los elementos se recuperan por ´ ındices o llaves? Forma ¿El objeto tiene una estructura lineal, jer´rquica, arbitraria, a gr´fica, etc? a4.3.3. ¿C´mo especificar? o Dado que entiende lo que desea especificar y lo que desea obtener puedeempezar a especificar. La t´cnica principal es la descomposici´n y abstracci´n. e o oPara ´sto damos algunas ideas: e
  • 83. ´4.3. ESPECIFICACION DE PROGRAMAS 71 Abstraer. No piense como programador. Piense en funci´n de la definici´n, no de la funcionalidad o o Trate de construir teor´ no solo modelos ıas, No piense en forma computacional4.3.4. Invariantes Definamos con m´s claridad una invariante. Una invariante es una pro- apiedad que es verdadera y no cambia durante le ejecuci´n del programa. Esta opropiedad engloba a la mayor parte de los elementos o variables del progra-ma. Cada ciclo tiene una propiedad invariante. Las invariantes explican lasestructuras de datos y algoritmos. Las propiedades de las invariantes deben mantenerse cuando se modificael programa. La invariante obtenida se utiliza en un proceso est´tico para averificar la correctitud del programa. Las invariantes son utilies en todos los aspectos de la programaci´n: di- ´ ose˜o, codificaci´n, prueba, mantenimiento y optimizaci´n. Presentamos una n o olista de usos a fin de motivar a la utilizaci´n de las mismas por los progra- omadores. Escribir mejores programas.- Muchos autores coinciden que se pueden construir mejores programas cuando se utilizan especificaciones en el dise˜o de los programas. Las invariantes formalizan en forma precisa n el contrato de un trozo de c´digo. El uso de invariantes informalmente o tambi´n ayuda a los programadores. e Documentar el programa.- Las invariantes caracterizan ciertos aspec- tos de la ejecuci´n del programa y proveen una documentaci´n valiosa o o sobre el algoritmo, estructura de datos y los conocimientos a un nivel necesario para modificar el programa. Verificar las suposiciones.- Teniendo las invariantes las podemos utilizar en la verificaci´n del progrma observando que no cambian a medida que o se procesa. Evitar errores.- Las invariantes pueden prevenir que el programa realice cambios que accidentalmente cambien las suposiciones bajo las cuales su funcionamiento es correcto.
  • 84. 72 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA Formar un espectro.- El espectro de un programa son propiedades me- dibles en el programa o su ejecuci´n. Algunas de ´stas son el n´mero de o e u l´ ıneas ejecutadas por el prgrama, el tama˜o de la salida o propiedades n est´ticas como la complejidad. La diferencia entre varios aspectos nos a muestran cambios en los datos o el programa. Ubicar condiciones inusuales.- Condiciones inusuales o excepcionales deben llamar la atenci´n a los programadores porque pueden ser causa o de posibles errores. Crear datos de prueba.- Las invariantes pueden ayudar en la generaci´n o de datos de prueba de dos maneras. Pueden infringir intencionalmente las invariantes ampliando los datos de prueba. La otra es de mantener las invariantes para caracterizar el uso correcto del programa. Pruebas.- Prueba de teoremas, an´lisis de flujo de datos, chequeo del a modelo y otros mecanismos automatizados o semi automatizados pue- den verificar la correctitud del programa con respecto a su especifica- ci´n. oEjemplos 1. Mostrar que la invariante es P X N = xn ∧ x = 0 P:=1; IF not (x=0) while not (N=0) IF IMPAR(N) P=PxX N=N /2 X=X x X ELSE P=0 aqu´ la precondici´n es {X = x∧N = n} y la post condici´n {P = xn }. ı o o Veamos varios detalles del programa: Tiene tres variables P, N, X. Los valores iniciales son un valor x, n cualesquiera, precondici´n. o La post condici´n indica que el resultado es xn . o
  • 85. ´4.3. ESPECIFICACION DE PROGRAMAS 73 Iteraci´n o N P X P XN 1 9 1 2 512 - 9 2 2 – - 4 2 4 512 2 2 2 4 – - 2 2 16 512 3 1 2 16 – - 1 2 256 512 4 1 512 256 512 - 0 512 256 – - 0 512 65536 – Cuadro 4.1: Valores que toman la variables durante la ejecuci´n o Para mostrar que P X n es una invariante tomamos dos valores X, N . Supongamos que X = 2 y N = 9. Con estos valores contruimos el cuadro 4.1 que muestra los valores que toman las variables durante la ejecuci´n. o Como ve hemos anotado todos los valores que toman las variables in- volucradas y anotado los valores que toman al final de cada iteraci´n o calculando la supuesta invariante . Comprobamos que es correcta por- que sus valores no cambian. 2. Las invariantes pueden tomar diferentes formas, consideremos por ejem- plo el siguiente programa precondici´n {M ≥ 1 ∧ N = n} o X=0; for (N=1; N<M; M++) X=X+M post condici´n {X = (M (M − 1))/2} o En este ejemplo vemos que efectivamente X en cualquier momento representa el resultado de la sumatoria hasta el n´mero de iteraci´n en u o que se encuentra. Esto indica que la invariante es: N −1 X= i i=0
  • 86. 74 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA 3. Indicar cuales son las precondiciones y post condiciones de un ciclo f or. for (I=1; I<=N; N++{ .... .... } Aqu´ vemos que I debe ser una variable definida, al principio del ciclo ı toma el valor de 1 y al terminar el mismo toma en valor de N +1. No se ha caracterizado una invariante dado que no se ha escrito un programa al interior del ciclo. 4. Considere el algoritmo de Euclides para hallar el m´ximo com´n divisor a u y caracterice cu´l es la invariante del problema. a Mcd(a,b) if (b==0) return (a) else Mcd(b, a%b) Recordando el teorema de Euclides, dados dos n´meros a, b se cumple u M cd(a, b) = M cd(b, a %b) por lo tanto esta expresi´n es la invariante que se cumple durante la o ejecuci´n de todo el programa. o4.3.5. Ejercicios propuestos 1. Determinar la invariante del ciclo siguiente: X=0; while (X < 20){ X=X+5; } 2. Considere un programa de b´squeda secuencial que devuelve la posici´n u o del elemento buscado, o −1 cuando no existe. Cu´l es la invariante a apropiada?
  • 87. 4.4. APLICACIONES DE LAS INVARIANTES 75 int buscar(int [] v, int t){ // precondici´n el vector v no esta ordenado o // precondici´n t es el valor a buscar o int i=0; while ((i<v.length()&&(v[i]!=t){ i++; } if (i<n) return (i) else return (-1) } //post condici´n devuelve -1 cuando no existe y o // devuelve la posici´n i cuando existe o 3. Considere una clase que coloca y saca elementos en una estructura de pila. Escriba un programa e indique cu´les son las precondiciones, post a condiciones e invariantes de la clase? 4. Probar que la invariante del procedimiento de divisi´n por restas suce- o civas es X = R + (Y xQ) {Y = y ∧ X = y} R = X; Q = 0; W HILE Y ≤ R R = R − Y ;Q = Q + 1 {R < y ∧ X = R + (Y xQ)}4.4. Aplicaciones de las invariantes Las aplicaciones de las invariantes se orientan basicamente en el desarrolloy verificaci´n de los programas. Durante el proceso, el de verificar que las opropiedades se cumplen durante la ejecuci´n. En la verificaci´n est´n los o o am´todos formales que vienen de la l´gica formal y de aquellos procedentes e odel c´lculo de predicados [Red90]. a
  • 88. 76 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA Lo que se presenta es el desarrollo de programas utilizando los principiosde verificaci´n para, posteriormente introducirnos a la tem´tica de verficar o ael funcionamiento del programa en tiempo de ejecuci´n.o El m´todo que se sigue consiste de los siguientes pasos: e 1. Especificar el problema. 2. Escribir las pre y post condiciones . 3. Identificar las variables del problema. 4. Encontrar la invariante . 5. Codificar el ciclo, manteniendo la invariante en cada instante. 6. Prueba del programa. Desarrollemos como ejemplo, el proceso de dividir un n´mero por otro uhallando el residuo, utilizando restas sucesivas. Planteamiento del problema.- Dados dos n´mero X, Y hallar Q denomi- unado cociente y R denominado residuo tal que Q sea el cociente de la divisi´n oy R sea el residuo. Comenzamos escribiendo las pre y post condiciones/* Programa que realiza una divisi´n por restas sucesivas o * Precondici´n: x toma un valor y la variable y es > 0 o * Post condici´n: x=y*q +r o * Donde q es el cociente y * r es el resto*/ El proceso contin´a identificando las variables del programa que, las codi- uficamos directamente:/* Programa que realiza una divisi´n por restas sucesivas o * Precondici´n: x toma un valor entero o * y la variable entera y es > 0 * Post condici´n: x=y*q +r o * Donde q es el cociente y * r es el resto*/
  • 89. 4.4. APLICACIONES DE LAS INVARIANTES 77divide(int x,int y) {int q,r;..........} En este momento identificamos las caracter´ ısticas y las invariantes delproblema utilizando las variables definidas en la pre y post condici´n . Pri- omero el algoritmo consiste en restar sucecivamente el valor del divisor hastahallar el cociente y el resto. Segundo observamos que el resto debe ser menorque el dividendo caso contrario se puede seguir restando. Los valores inicialesde las variables q, r ser´n q = 0, y r = y respectivamente. a Codificando estas consideraciones/* Programa que realiza una divisi´n por restas sucesivas o * Precondici´n: x toma un valor entero o * y la variable entera y es > 0 * Post condici´n: x=y*q +r o * Donde q es el cociente y * r es el resto*/divide(int x,int y) {int q=0;int r=y;while (r > = x) {..........}..........} La invariante del ciclo debe mantenerse durante toda el ciclo. En nuestrocaso es obvio que la invariante es x = q · y + r/* Programa que realiza una divisi´n por restas sucesivas o * Precondici´n: x toma un valor entero o * y la variable entera y es > 0
  • 90. 78 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA * Post condici´n: x=y*q +r o * Donde q es el cociente y * r es el resto*/divide(int x,int y) {int q=0;int r=y;while (r > = x) { //invariante x=y*q +rr=r-y;q++; }} reacomodando los comentarios tenemos la versi´n final. o/* Programa que realiza una divisi´n por restas sucesivas o * Precondici´n: x toma un valor entero o * y la variable entera y es > 0 */divide(int x,int y) {int q=0;int r=y;while (r > = x) { //invariante x=y*q +rr=r-y;q++; } /* Post condici´n: x=y*q +r o * Donde q es el cociente y * r es el resto*/} La invariante se verifica que es matem´ticamente correcta. Tomando un aejemplo de ejecuci´n para un caso particular se puede ver que la invariante ono cambia. Vemos por ejemplo 9/2 :
  • 91. 4.4. APLICACIONES DE LAS INVARIANTES 79 Iteraci´n o x y q r x=y*q +r 0 9 2 0 9 9 1 9 2 1 7 9 2 9 2 2 5 9 3 9 2 3 3 9 4 9 2 4 1 9 Como se observa en cada iteraci´n se ha mantenido la invariante. o Veamos un ejemplo que utiliza dos bucles. Especifiquemos el programapara construir la criba de Eratostenes. Lo que se quiere es un vector dondelos todos los m´ltiplos de alg´n n´mero est´n marcados. Los que no son u u u em´ltiplos son n´meros primos y no est´n marcados. u u a De aqu´ se ve que, la precondici´n del problema es un vector que tiene dos ı oestados: marcado y no marcado. Los marcados son los n´meros no primos. uAl tener solo dos estados se puede utilizar un vector de bits. Escribimos laprecondici´n, post condici´n as´ como, los elementos requeridos en el c´digo. o o ı oimport java.util.*;/** * Programa para construir los numeros primos * hasta = 100.000.000 * utilizando la Criba de Eratostenes * Precondici´n: o * Un vector de bits con todos sus valores en cero */public class Criba { public static void main(String[] s) { int n = 100000000; BitSet a = new BitSet(n + 1);}}/** * Post condici´n: o * Un vector de bits con los numeros primos en cero. */ Ahora debemos construir las invariantes del ciclo. Recordemos que lo quese hace en el algoritmo es marcar todos los m´ltiplos de 2, 3, 4, 5, .... hasta la u
  • 92. 80 ´ 4. CODIFICACION CON MIRAS A LA PRUEBAra´ cuadrada del n´mero m´ximo. Como se requieren dos ciclos tambi´n se ız u a erequieren dos invariantes. El resultado obtenido es:import java.util.*;/** * Programa para construir los numeros primos * hasta = 100.000.000 * utilizando la Criba de Eratostenes * Precondici´n: o * Un vector de bits con todos sus valores en cero */public class Criba { public static void main(String[] s) { int n = 100000000; BitSet a = new BitSet(n + 1); int i = 2, j = 0; // construcci´n de la criba o for (i = 2; i * i <= n; i++) { //Invariante hasta i-1 se han marcado todos los //multiplos de i - 1 para i > 2 if (!a.get(i)) { for (j = i + i; j <= n; j=j+i;) { //Invariante j es multiplo de i a.set(j); } } }}}/** * Post condici´n: o * Un vector de bits con los numeros primos en cero. */ Ahora completemos con las pre y post condiciones de cada ciclo. Lascorrespondientes al primer ciclo son las mismas del programa. Las corres-
  • 93. 4.4. APLICACIONES DE LAS INVARIANTES 81pondientes al segundo ciclo son: Precondici´n: Los m´ltiplos de i no han sido o umarcados. Post condici´n: Los m´ltiplos de i han sido marcados. Introdu- o uciendo las mismas tenemos la versi´n final. oimport java.util.*;/** * Programa para construir los numeros primos * hasta = 100,000,000 * utilizando la Criba de Eratostenes * Precondici´n: o * Un vector de bits con todos sus valores en cero */public class Criba { public static void main(String[] s) { int n = 100000000; BitSet a = new BitSet(n + 1); int i = 2, j = 0; // construcci´n de la criba o for (i = 2; i * i <= n; i++) { //Invariante hasta i-1 se han marcado todos los //multiplos de i - 1 para i > 2 if (!a.get(i)) { //Precondici´n: o // los multiplos de i no han sido marcados for (j = i + i; j <= n; j=j+i;) { //Invariante j es multiplo de i a.set(j); } //Post condici´n: o //los multiplos de i han sido marcados } }}}/** * Post condici´n: o //Un vector de bits con los numeros primos en cero. */
  • 94. 82 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA Una de las aplicaciones de las invariantes es caracterizar el desarrollo deun programa. El siguiente ejemplo muestra el desarrollo de un programa queeval´a la serie de Fibonacci que, como ver´ es dif´ de comprender si no se u a ıcilsigue el desarrollo. La serie de Fibonacci es formada por la ecuaci´n t(n)+t(n−1) con t(0) = o1. Un programa para evaluar esta secuencia de n´meros ser´ el siguiente: u ıa//Precondicion: N>=0 y=1; n=0; x=0; while(n!=N){ x=y; y=x+y; n++; }//Post condicion x=Fibonacci(N)Para mejorar el tiempo de proceso de este algoritmo, reescribimos las siguien-tes l´ ıneas de c´digo: x = y y y = x + y como una ecuaci´n matricial: o o x 0 1 x = (4.4.1) y 1 1 yDenominando estas matrices A, B tenemos x 0 1 A= B= (4.4.2) y 1 1 Si reemplazamos 4.4.2 en el programa la parte del ciclo se convierte en: while(n!=N){ A=B*A n++; }donde A y B son matrices. Analizando vemos que lo que se est´ calculando a nes A = B A. De aqu´ se puede ver que la invariante del ciclo es: ı n x 0 1 0 = (4.4.3) y 1 1 1
  • 95. 4.4. APLICACIONES DE LAS INVARIANTES 83 Se ve que lo que tenemos es una potencia de una matriz. Con esta idea po-demos aplicar el m´todo que mostramos para hallar una potencia en tiempo elogar´ ıtmico. Inicialmente hallemos las siguientes potencias: 2 0 1 0 1 0 1 1 1 = = (4.4.4) 1 1 1 1 1 1 1 2 4 1 1 1 1 1 1 2 3 = = (4.4.5) 1 2 1 2 1 2 3 5Esto nos lleva al hecho que, no demostraremos, de que todas las potenciaspares tienen la forma: a b (4.4.6) b a+bCalculando B · B se tiene que: a = a · a + b · by b = b · a + a · b + b · b. Calculando A · B se tiene que: x = a · x + b · yy y = b · x + a · y + b · y. Recordando que el algoritmo mejorado a O(log(n)) para hallar las poten-cias trabaja bajo el siguiente m´todo: e while(n!=N){ si par(n) B=B*B n=n/2 si impar(n) A=A*B n=n-1 }Llevando ´sto al c´digo se tiene el programa final: e o
  • 96. 84 ´ 4. CODIFICACION CON MIRAS A LA PRUEBApublic class Fibonacci { /** * Programa para hallar el Fibonacci 8,n=8 * @author Jorge Teran * @param args * none */ public static void main(String[] args) { int n=8,a=0,b=1,x=0,y=1,temp=0; while(n!=0){ if(n%2==0){ temp = a*a + b*b; b = b*a + a*b + b*b; a=temp; n=n/2; } else { temp = a*x + b*y; y = b*x + a*y + b*y; x=temp; n=n-1; } } System.out.println("x= "+x); System.out.println("y= "+y); }}Como se ve en la ejecuci´n del programa x = F ibonacci(n − 1) y y = oF ibonacci(n). En este programa se ve claramente que la especificaci´n de ola invariante es esencial para entender el programa final.4.4.1. Principio de correctitud El principio de correctitud se define como:
  • 97. ˜4.5. DISENO POR CONTRATOS 85 inicializaci´n La invariante es verdadera cuando se ejecuta el programa o por primera vez. preservaci´n la invariante se preserva al principio, al final de cada uno o de los ciclos del programa y cuando este termina. terminaci´n El programa termina y produce los resultados esperados. o Esto puede probarse utilizando los hechos que hacen la invariante.El proceso de prueba moderno consiste en verificar el principio de correcti-tud. Puede realizarse, en forma est´tica (l´gica formal) y en forma din´mica a o adurante la realizaci´n del c´digo. o o4.5. Dise˜ o por contratos n El dise˜o por contratos tiene sus or´ n ıgenes en 1990 con los trabajos deBertrand Meyer y el lenguaje de programaci´n Eifel. Consiste en establecer orelaciones cuyo fundamento est´n en la l´gica formal entre las diferentes a oclases del programa. La motivaci´n principal para desarrollar el dise˜o por contratos es la reu- o ntilizaci´n del c´digo. El dise˜o por contratos es un m´todo de la ingenier´ de o o n e ıasoftware para la fiabilidad y aplicable a la programaci´n orientada a objetos. o La fiabilidad del software se puede ver como dos aspectos: primero lacorrectitud y segundo la robustez. Para describir la correctitud, supongamos que le traen 100,000 l´ ıneas dec´digo y le preguntan si es correcto o no. Claramente no se puede decir mucho oal respecto, lo que se requiere es una especificaci´n detallada para verificar oque el producto satisface la especificaci´n. o Un elemento de software no es correcto o incorrecto por s´ mismo. Es ıcorrecto o incorrecto con respecto a su especificaci´n. o Definimos la correctidud como una tupla de pares de elementos: correctitud = (especif icacion, codigo). La robustez es la facilidad que tiene un programa para reaccionar enforma razonable a condiciones que no est´n en la especificaci´n. a o En la construcci´n de programas existen dos metodolog´ principales o ıasque, son la programaci´n defensiva y programaci´n por contratos. o o
  • 98. 86 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA La programaci´n defensiva se basa en ir agregando controles a fin de overificar posibles errores durante la ejecuci´n del programa. En este tipo de oprogramaci´n se tiene cada vez m´s c´digo, haciendo que el c´digo nuevo o a o orequiera introducir nuevos controles. Sup´ngase que se tiene una rutina que devuelve el resultado de dividir oa/b el c´digo podr´ ser o ıaint divide (int a, int b){ return a/b;} Aplicando la programaci´n defensiva se tendr´ que codificar los posibles o ıaerrores, por ejemplo b > 0 o si a puede estar en un rango de valores yas´ sucecivamente todas las posibles situaciones que puedan ocurrir a fin de ıque, la respuesta sea adecuada. int Divide (int a, int b){ if (!(b>0)){ System.out.println("error b=0") } ...... ...... ...... return a/b; }Como se ve el concepto de una simple divisi´n ha sido complicada con una oserie de operaciones que ocultan el pr´posito de la rutina Divide. o La programaci´n por contratos toma los conceptos de la l´gica formal o oy la especificaci´n de programas. Esta metodolog´ de dise˜o establece una o ıa nrelaci´n contractual entre clases especificando los requerimientos y los resul- otados esperados. Esto se realiza incluyendo precondiciones, post condicionese invariantes. Se puede ver como un contrato entre personas donde cada una de laspartes tiene una obligaci´n que cumplir. En el ejemplo que vimos no es oobligaci´n de Divide que, los valores que recibe sean correctos, m´s bien el o ade dividir correctamente. La obligaci´n del programa que llama a Divide es oel de pasar los datos correctos.
  • 99. ˜4.5. DISENO POR CONTRATOS 87 Normalmente utilizamos la palabra bug para referirnos a cualquier tipode problema de software. Esta palabra es un poco ambigua por lo que hayque definir los problemas que existen. Un producto de software puede tener tres tipos de problemas: errores,defectos y fallos. Error es una mala decisi´n realizada durante el desarrollo odel software. Un defecto es una propiedad que hace que no se adecue a suespecificaci´n. Un fallo es un evento incorrecto que, en su comportamiento oesperado, ocurre en alguna de sus ejecuciones. La programaci´n por contratos divide en obligaciones y beneficios entre oproveedor y cliente.Cliente Es un programa que hace uso de un objeto (programa) conoce la interfaz de la clase y no sabe nada de la implementaci´n oProveedor Es un programa (objeto) que es utilizado por un cliente, cons- truye la documentaci´n, la mantiene y publica una interfaz. o El siguiente cuadro muestra los beneficios y obligaciones de clientes yproveedores: Obligaciones Beneficios Cliente Satisfacer la precondici´n o Obtener los resultados de la post condici´n o Proveedor Satisfacer la post condici´n o Un proceso m´s simple a gracias a que se pre- sume que se satisface la precondici´n o En nuestro caso el programa que llama a la rutina de dividir debe ga-rantizar que los datos enviados son correctos y el programa que realiza ladivisi´n garantiza que la respuesta es correcta. o En el enfoque tradicional se presentan varios problemas: El cliente no entiende en que situaciones puede utilizar una clase. El cliente no entiende las consecuencias de utilizar un m´todo. e Cuando se cambia un c´digo, ¿C´mo se consigue que la interfaz se o o mantenga?
  • 100. 88 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA Si la interfaz cambia, ¿C´mo se entera el cliente? o Con esta metodolog´ es muy f´cil determinar la causa de un fallo en un ıa aprograma: Una falla en la precondici´n es una manifestaci´n de una falla en el o o cliente Una falla en la post condici´n es una manifestaci´n de una falla en el o o proveedor. En un contrato entre cliente y proveedor se pueden dar dos situaciones,la primera es que el contrato se cumpla con lo cual no hay que hacer abso-lutamente nada, o puede que, el contrato se rompa en cuyo caso se puedeutilizar una clase especializada para manejar el error o simplemente terminarel proceso indicando la causa de la falla. En todo el proceso de dise˜o por contratos se debe evitar la redundancia. nEsta regla es el opuesto de la programaci´n defensiva. No est´ por dem´s o a arealizar controles en el c´digo, sin embargo, pueden hacer el c´digo muy o opoco entendible. En el dise˜o bajo contratos se debe colocar estos controles nen las precondiciones. El objetivo es la simplicidad, al agregar c´digo redundante en la progra- omaci´n defensiva, se hace el software m´s complicado. Al agregar m´s c´digo o a a ohay que agregar m´s controles y as´ sucesivamente. a ı4.5.1. Especificaci´n de contratos o Los contratos se especifican a trav´s de cla´sulas que definen las pre y e upost condiciones. Las precondiciones se especifican con la cla´sula requires y ulas post condiciones con la cla´sula ensures. u Supongamos que se quiere especificar una clase Tiempo que tiene losm´todos ponerHora, ponerMinutos, ponerSegundos, tiempoTranscurrido. e Una posible implementaci´n puede ser crear tres variables hora, minutos, osegundos y a trav´s de un algoritmo hallar el tiempo transcurrido. e Otra implementaci´n puede ser hallar el tiempo transcurrido desde un omomento determinado, por ejemplo, el principio del a˜o. De esta forma es nposible almacenar el tiempo en una sola variable entera. Con este m´todo ese puede simplificar el hallar el tiempo transcurrido a restar dos variablesenteras.
  • 101. ˜4.5. DISENO POR CONTRATOS 89 Con el sistema de dise˜o por contrato solo se debe especificar el contrato nque las clases deben cumplir y no la implementaci´n. La clase ponerHora se opuede especificar como sigue:void ponerHora(int h)/* requieres 0 <= h <= 23 * ensures hora=h * ensures old minutos = minutos * ensures old segundos = segundos*/ Esta especificaci´n garantiza que la hora est´ en un rango permitido, que o alos minutos y segundos no cambian y que la variable h toma el valor de hora.Una implementaci´n de esta especificaci´n podr´ ser o o ıavoid ponerHora(int h)/* requieres 0 <= h <= 23 * ensures hora=h * ensures minutos = minutos * ensures segundos = segundos*/ hora=h;} Si analizamos el c´digo propuesto, parece que la post condici´n es una o oredundancia del c´digo. Hay que hacer notar que la post condici´n hora=h o oindica que lo que se espera, es que la variable hora tome el valor h. El c´digo oindica como se hace esto. Si se hubiera escogido la segunda forma de implementar, se tendr´ un ıac´digo m´s complejo y la misma especificaci´n. Esto permite que podamos o a ocambiar el c´digo sin tener que avisar este cambio a todos los clientes, fa- ocilitando la reusabilidad y mantenimiento al haber mantenido los contratosentre clientes y proveedores. Cada pre y post condici´n debe satisfacer los siguientes requerimientos: o Las pre y post condici´n aparece en la documentaci´n oficial distribuida o o a autores de m´dulos cliente. o Es posible justificar la precondici´n en base de la especificaci´n sola- o o mente.
  • 102. 90 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA Cada caracter´ıstica que aparece en la pre y post condici´n debe es- o tar disponible a cada cliente cuya ejecuci´n est´ disponible (regla de o e disponibilidad).4.5.2. Invariantes El el dise˜o por contratos se tienen dos tipos de invariantes, las invariantes nde clase y las invariantes de bucles o ciclos. Las invariantes de clase describen propiedades globales que deben preser-varse entre todas las rutinas. En cambio las invariantes de bucle describenlas propiedades que deben preservarse entre las variables de un bucle. Una invariante es correcta si y solo si cumple: La creaci´n de un procedimiento p, cuando se aplica a los argumentos o que satisfacen la precondici´n, satisface la invariante I. o Cuando termina una rutina exporta sus resultados, cuando satisface la precondici´n dando un estado I, tambi´n satisface la invariante. Ter- o e mina en uno estado que satisface la invariante En la clase Tiempo la invariante quedar´ especificada como: ıaTiempo (){ Invariant 0 < = hora < =24 Invariant 0 < = minutos < =59 Invariant 0 < = segundos < =59} El estado global de la clase especificada indica que cuando cambiamos lahora, los valores hora, minutos y segundos est´n en el rango correcto. a Una especificaci´n de la clase tiempo puede ser como sigue: opublic clase Tiempo (){ Invariant 0 < = hora < =24 Invariant 0 < = minutos < =59 Invariant 0 < = segundos < =59ponerHora(int h){}
  • 103. ´4.6. PRUEBA ESTATICA 91/* requieres 0 <= h <= 23 * ensures hora=h * ensures minutos = minutos * ensures segundos = segundos*/}ponerMinutos(int m){}/* requieres 0 <= h <= 23 * ensures minutos=m * ensures hora = hora * ensures segundos = segundos*/............. En cada m´todo se deber´ especificar las invariantes del ciclo apropiadas e aen funci´n de la implementaci´n. o o Como se ve estos conceptos simplifican la construcci´n del programa y lo ohacen m´s legible. En Java se puede implementar a trav´s de varios progra- a emas utilitarios que, se muestran en la siguiente secci´n. o4.6. Prueba est´tica a Las pruebas est´ticas de c´digo utilizan la l´gica formal para probar que a o oaplicando a la precondici´n la invariante se llega a la post condici´n. Es- o otas pruebas se realizan aplicando una serie de reglas de la l´gica formal. El oprop´sito de presentar estas reglas es mostrar en forma simple como se apli- ocan en el proceso de prueba. El texto de la Dra Tanja Vos [Vos01], provee laprueba y un extensa explicaci´n de esta tem´tica. o a A fin de ejemplificar el proceso que se sigue veamos un ejemplo muysencillo: La regla de bloques indica que dada una precondici´n {P }, con un c´digo o oC se llega a la post condici´n {Q}. Las variables locales no deben figurar en ola precondici´n y post condici´n. Ejemplo: o o {X = x}X = X + 1{X = x + 1}
  • 104. 92 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA El procedimiento de prueba consiste en reemplazar las variables de laprecondici´n en el c´digo para obtener la post condici´n. En el ejemplo re- o o oemplazamos valor de la variable X obteniendo: {X = x}x = x + 1{X = x + 1}finalmente reemplazamos la x y se obtiene la post condici´n. o En el caso de las secuencias se procede de forma similar Dada una se-cuencia de instrucciones C1 ; C2 ; ...Cnuna precondici´n {P } y la post condici´n {Q}, ´sta secuencia de instrucciones o o epuede expresarse como: {P } {P1 }C1 ; {Q1 }{P2 }C2 ; {Q2 }......{Pn }Cn ; {Qn } {Q} De este desarrollo se ve que P1 es consecuencia de P y que P2 es con-secuencia de Q1 y sucecivamente hasta llegar a Q que es consecuencia deQn . Para este proceso existen reglas, para secuencias, bloques, condicionales,bucles while, for y todos les elementos utilizados en la programaci´n. o4.7. Prueba din´mica a La prueba din´mica es la que se realiza en tiempo de ejecuci´n y el len- a oguaje de programaci´n brinda el m´todo de afirmaciones a trav´s de la ins- o e etrucci´n assert. Con aplicaciones adicionales se pueden verificar las precon- odiciones, post condicones e invariantes. Estos controles son insertados en elc´digo autom´ticamente con afirmaciones. En estos desarrollos se encuentra o aiContract, JM SAssert [Fel05], y Java Modeling Language (JM L).4.7.1. Afirmaciones Las afirmaciones son una forma de verificar en tiempo de ejecuci´n, ciertas ocondiciones que se deben cumplir durante la ejecuci´n del programa. Esta oopci´n viene en Java despu´s de la versi´n 1.4. La utilizaci´n dentro del o e o o
  • 105. ´4.7. PRUEBA DINAMICA 93lenguaje Java se realiza con la instrucci´n assert que tiene las dos formas osiguientes: assert expresion1; assert expresion1 : expresion2; En la primera forma expresion1 es una expresi´n booleana que el pro- ogramador afirma ser verdadera durante la ejecuci´n del programa. o En la segunda forma se agrega expresion2 que es un mecanismo parapasar una cadena que ser´ mostrada en caso de fallar la afirmaci´n. a o Cuando uno ejecuta un programa en modo de prueba est´ interesado aen que se procesen las afirmaciones, sin embargo, cuando est´ en modo de aproducci´n se desea eliminar estas instrucciones para mejorar el tiempo de oproceso. Por este motivo al invocar la ejecuci´n del programa se debe incluir ola opci´n −ea para que se ejecuten. Por ejemplo se queremos ejecutar el oprograma Ejemplo con las afirmaciones habilitadas se coloca java − ea Ejemplo El propio lenguaje Java trae la opci´n que permite habilitar las afirma- ociones propias del lenguaje a fin de diagnosticar posibles errores propios delJava, esto se hace con la opci´n −esa. Recordando el ejemplo de la secci´n o oanterior: Nombre persona = new Nombre(nombrePersona); int largo=0; String dato = persona.devuelveNombre(); if (dato == null) { System.err.println("Error grave: Falta la propiedad ’nombre’ "); } else { largo=dato.trim().length(); }
  • 106. 94 ´ 4. CODIFICACION CON MIRAS A LA PRUEBASe observa que el control sobre el nombre se hace permanentemente. Cuandoel sistema est´ completamente depurado es muy probable que no se requiera arealizar este control. Utilizando la instrucci´n assert queda como sigue: o Nombre persona = new Nombre(nombrePersona); int largo=0; String dato = persona.devuelveNombre(); assert dato == null : "Falta la propiedad ’nombre’ " largo=dato.trim().length(); Como puede observar el programa ha quedado en formas m´s comprensi- able y la cantidad de c´digo a revisar es menor, pudiendo habilitar o desabilitar oel control en tiempo de ejecuci´n. o Retomando el ejemplo de la criba de Eratostenes en versi´n final. Rees- ocribimos algunas invariantes y precondiciones en una instrucci´n assert para oobtener:import java.util.*;public class Criba { public static void main(String[] s) { int n = 100000000; BitSet a = new BitSet(n + 1); int i = 2, j = 0; for (i = 2; i * i <= n; i++) { //Invariante hasta i-1 se han marcado todos los //multiplos de i - 1 para i > 2 if (!a.get(i)) { //Precondici´n: o // los multiplos de i no han sido marcados assert !a.get(i) : "Procesando multiplos " + i +" dos veces" for (j = i + i; j <= n; j=j+i;) { //Invariante j es multiplo de i assert i%j == 0: " J no es multiplo de I" a.set(j); } }
  • 107. ´4.8. PROGRAMACION BAJO CONTRATOS CON JML 95 }}}/** * Post condici´n: o //Un vector de bits con los numeros primos en cero. */Ahora en una ejecuci´n normal del programa se ve que no hay ning´n pro- o ublema. Sin embargo, al codificar el c´digo se puede haber escrito con un oerror: for (j = i + i; j <= n; j++;) { //Invariante j es multiplo de i assert i%j == 0: " J no es multiplo de I"Este error que puede pasar desapercibido por la costumbre de escribir elc´digo de esa forma. En el tiempo de ejecuci´n al habilitar las invariantes se o oobtiene el mensaje de error. Esta forma de describir el c´digo requiere que se busquen formas de es- opecificar las pre, post condiciones e invariantes del programa. Como se ve ´stos conceptos simplifican la construcci´n del programa y lo e ohace m´s legible. a4.8. Programaci´n bajo contratos con JML o Existen varias herramientas que se pueden utilizar para implementar laprogramaci´n bajo contratos en Java. La siguiente lista muestra una serie de oherramientas disponibles: Herramienta Descripci´n o Jass Java with Asertions Icontract Java Design by Contract Jcontract Java Design by Contract Jcontractor Java Design by Contract JML Java Modeling Language Esc/java Extended Static Checker De estas herramientas hay que destacar que Esc/java trata de realizaruna verificaci´n est´tica del c´digo utilizando principios de la l´gica formal. o a o o
  • 108. 96 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA El JML aprovecha los mecanismos de la especificaci´n de programas y de ola documentaci´n para incluir los elementos del contrato incorporados en un oprograma Java y herramientas para compilar y ejecutar el c´digo. o La precondici´n se incluye con la instrucci´n requires y la post condici´n o o ocon ensures. Las anotaciones se escriben en l´ ıneas de comentarios con la forma/ ∗ @....@ ∗ /. En el ejemplo el c´digo completo queda como sigue: o public class Divide { /*@ requires b > 0 ; @ ensures result * b <= a ; @*/ public static int Div (int a, int b){ return (a/b); } }En este caso probamos la clase desde la entrada principal y la clase Dividetiene la obligaci´n de verificar la precondici´n y la post condici´n. En el o o oejemplo la precondici´n es que b > 0 para evitar la divisi´n por cero y la post o ocondici´n para garantizar que el resultado de la divisi´n no sea incorrecto. o o Para compilar el c´digo con JML se procede como sigue: o jmlc Divide.javaEste proceso incluye todas las afirmaciones necesarias para verificar las inva-riantes, pre y post condiciones. Para ejecutar el programa se procede de lasiguiente manera: jmlrac Divide Ahora supongamos que el programa de la divisi´n produce un resultado oerr´neo en el programa hemos colocado o return (a*b); en lugar dereturn (a/b);
  • 109. ´4.8. PROGRAMACION BAJO CONTRATOS CON JML 97obtendremos un error explicando la causa de la fallaException in thread "main"org.jmlspecs.jmlrac.runtime.JMLInternalNormalPostconditionError: by method Divide.Divregarding specifications atFile "Divide.java", line 4, character 23 when ’b’ is 3 ’a’ is 10 ’result’ is 30 at Divide.Div(Divide.java:446) at Divide.internal$main(Divide.java:14) at Divide.main(Divide.java:548)4.8.1. Especificaci´n de invariantes o En la programaci´n por contratos se tienen dos tipos de invariantes. Las oinvariantes de ciclo que son las que se cumplen durante la ejecuci´n del ciclo y olas invariantes de clase que deben ser v´lidas antes y despu´s de la ejecuci´n a e ode la clase. La forma de especificar las invariantes es a trav´s de la cl´usula e ainvariant. Para ejemplificar las invariantes de ciclo se utiliza la instrucci´n oloop invariant delante de la instrucci´n que especifica el ciclo. Por ejemplo: o static int Suma (int n) { int suma=0; //@ loop_invariant suma %5 == 0; for (int i=0; i<n; i=i+5) { suma+=i; } return suma; }En el c´digo se ve que la invariante especifica que suma es m´ltiplo de 5 en o ucada instante durante el ciclo for. Las invariantes de clase se especifican al principo de la clase con la cl´usula ainvariant Veamos un ejemplo:
  • 110. 98 ´ 4. CODIFICACION CON MIRAS A LA PRUEBApublic abstract class Inv1 { boolean[] vector; //@ invariant vector != null && vector.length == 7; Invariant() { vector = new boolean[7]; }}Esta especificaci´n indica que el vector no es nulo, tiene una longitud de 7 y oestos valores no se modifican en la ejecuci´n de la clase. o4.8.2. Cuantificadores Los cuantificadores son los descritos en el cuadro 4.2: La sintaxis de los Cuantificador Descripci´n o forall para todo exists existe sum suma product producto num of n´mero de u max m´ximo a min m´ınimo Cuadro 4.2: Cuantificadorescuantificadores es como sigue: {cuantif icador int V ariable; rango; codigo}Adicionalmente se incluye la old(variable) para obtener el valor anterior ala ejecuci´n del c´digo. o o Como ejemplo veamos una funci´n que suma los elementos de un vec- otor. Antes de la ejecuci´n del c´digo es necesario que el vector no sea nulo o o(precondici´n), en la post condici´n hay que verificar que el vector no ha o ocambiado y que el resultado es realmente la suma. Esto queda especificadocomo sigue:
  • 111. ´4.8. PROGRAMACION BAJO CONTRATOS CON JML 99public class Vector { /*@ requires a != null; @ ensures result == @ (sum int i; 0 <= i && i < a.length; a[i] ) @ && a == old(a) @ && (forall int i; @ 0 <= i && i< a.length; a[i] == old(a[i])); @*/ static int Suma (int[] a) { int suma=0; for (int i=0; i<a.length; i++) { suma+=a[i]; } return suma; } }JML es un lenguaje mucho m´s completo. Se puede obtener el manual de a +referencia de [LPC 02].4.8.3. Ejercicios Instalar JML en su equipo. Para ´sto es necesario que tome en cuenta eque, algunas versiones de JML solo funcionan con la versi´n 1.4 de Java. A ola hora de escribir el texto no funcionaba adecuadamente con la versi´n 1.5 ode Java. 1. Programar los ejercicios de la secci´n 4.3.5 y comprobar las invariantes, o pre y post condiciones utilizando JML. 2. Especificar en JML una clase hora que tenga los m´todos siguientes: e ponerHora, ponerMinutos, ponerSegundos, verHora, verMinutos, verSe- gundos, tiempoTranscurrido. Tiempo transcurrido es la resta del tiempo entre dos horas. 3. Realizar dos implementaciones diferentes de la clase hora en base a la especificaci´n anterior. o
  • 112. 100 ´ 4. CODIFICACION CON MIRAS A LA PRUEBA 4. Crear un programa para utilizar la clase hora y verificar que ambas implementaciones funcionan.
  • 113. Cap´ ıtulo 5 Aplicaciones de b´ squeda y u clasificaci´n o5.1. Introducci´n o La b´squeda y la clasificaci´n tienen una serie de aplicaciones que ser´n u o adescritas en las siguientes secciones. Se proceder´, de m´todos generales a a ecasos particulares que reducen el tiempo de proceso. El proceso de especi-ficaci´n se realiza como se mostr´ en el cap´ o o ıtulo anterior especificando lasinvariantes, pre y post condiciones sin entrar en la demostraci´n de ´stas. o eLos libros de Horstman [CSH05] proporcionan una buena descripci´n de las olibrer´ de Java. ıas5.2. Algoritmos de b´ squeda u La b´squeda de elementos ha sido analizada en diferentes entornos, me- umoria, bases de datos, texto plano y otros. Cada algoritmo de b´squeda da ucomo resultado una eficiencia diferente en funci´n de como se ha organizado ola informaci´n. La b´squeda en forma gen´rica se presenta como, el mecanis- o u emo de hallar un elemento en un vector del cual solo conocemos, el n´mero ude elementos que contiene. Este algoritmo, denominado b´squeda secuencial, uviene especificado como sigue:public class Sec { /* Programa de busqueda secuencial 101
  • 114. 102 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION *@ author Jorge Teran */ static int buscar(int[] v, int t) { /*@ requires v != null ; @ requires t != null ; @ ensures (hallo = -1) @ || (hallo < v.length && hallo >=0); @*/ int hallo = -1;// @ loop_invariant i < v.length && hallo = -1; for (int i = 0; i < v.length; i++) if (v[i] == t) { hallo = i; break; } return (hallo); }Aplicando la teor´ vista se determina que el tiempo de ejecuci´n del algo- ıa oritmo es proporcional n 1=n i=0Esto significa que es necesario conocer m´s sobre el conjunto de datos para amejorar el tiempo de b´squeda. Este concepto hace que se puedan realizar ub´squedas espec´ u ıficas para cada conjunto de datos a fin de mejorar el tiempode proceso. Sup´ngase que se tiene una lista de n´meros enteros entre 0 y n. Estos o un´meros corresponden al c´digo de producto en un almac´n. Dado un n´mero u o e use quiere conocer si este pertenece al almac´n. Para esto podemos organizar elos n´meros de varia formas. Se puede colocar la informaci´n en un vector y u oproceder con el esquema de b´squeda anterior obteniento un tiempo O(n) = un. ¿Ser´ posible obtener un tiempo O(n) = 1 ?. a La respuesta es s´ Consideremos un c´digo n peque˜o entonces podemos ı. o narmar un vector de bits en memoria, qu´ indique que n´meros existen y e ucuales no. Se quiere cambiar la b´squeda secuencial aprovechando algunas carac- uter´ısticas particulares al problema, suponiendo que los datos est´n previa- amente ordenados.
  • 115. ´5.2. ALGORITMOS DE BUSQUEDA 103 Esta soluci´n debe funcionar tanto para enteros, cadenas y reales siempre oy cuando todos los elementos sean del mismo tipo. La respuesta se almacenaen un entero p que representa la posici´n en el arreglo donde se encuentra oel elemento t que estamos buscando, −1 indica que el elemento buscado noexiste en el arreglo. Esta b´squeda denominada b´squeda binaria, resuelve el problema re- u ucordando permanentemente el rango en el cual el arreglo almacena t. Inicial-mente el rango es todo el arreglo y luego es reducido comparando t con elvalor del medio y descartando una mitad. El proceso termina cuando se hallael valor de t o el rango es vac´ En una tabla de n elementos en el peor caso ıo.realiza log2 n comparaciones. La idea principal es que t debe estar en el rango del vector. Se utiliza ladescripci´n para construir el programa. oprecondici´n el vector esta ordenado oinicializar el rango entre $0..n-1$loop {invariante: el valor a buscar debe estar en el rango} si el rango es vacio terminar y avisar que t no esta en el arreglo calcular m que es el medio del rango use m con una prueba para reducir el rango si se encuentra t en el proceso de reducci´n o terminar y comunicar su posici´n oLa parte esencial del programa es la invariante que al principio y final de cadaiteraci´n nos permite tener el estado del programa y formalizar la noci´n o ointuitiva que ten´ ıamos. Se construye el programa utilizando refinamiento sucesivo haciendo quetodos los pasos respeten la invariante del mismo. Primero buscaremos una representaci´n del rango digamos l..u entonces la oinvariante es el rango debe estar entre l..u. El pr´ximo paso es la inicializaci´n o oy debemos estar seguros que respeten la invariante, la elecci´n obvia es l = o0, u = n − 1. Codificando un programa con los conceptos detallados previamente tene-mos: precondici´n x debe estar ordenado o post condici´n p especifica la posici´n o o
  • 116. 104 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION o p es -1 cuando no existe l=0; u=n-1 loop {invariante: debe estar en el rango l,u} si el rango es vacio terminar y avisar que t no esta en el arreglo calcular m que es el medio del rango use m con una prueba para reducir el rango si se encuentra t en el proceso de reducci´n o terminar y comunicar su posici´n oContinuando con el programa vemos que el rango es vac´ cuando l > u. en ıoesta situaci´n terminamos y devolvemos p = −1. Llevando esto al programa otenemos:precondici´n x debe estar ordenado o post condici´n p especifica la posici´n o o o p es -1 cuando no existe l=0; u=n-1 loop {invariante: debe estar en el rango l,u} if l > u p=-1; break; calcular m que es el medio del rango use m con una prueba para reducir el rango si se encuentra t en el proceso de reducci´n o terminar y comunicar su posici´n oAhora calculamos m con m = (l + u)/2 donde / implementa la divisi´n oentera. Las siguientes l´ ıneas implican el comparar t con x[m] en la que haytres posibilidades, por igual, menor y mayor. Con lo que el programa quedacomo sigue: precondici´n x debe estar ordenado o post condici´n p especifica la posici´n o o o p es -1 cuando no existe l=0; u=n-1 loop {invariante: debe estar en el rango l,u}
  • 117. ´5.2. ALGORITMOS DE BUSQUEDA 105 if l > u p=-1; break; m=(l+u)/2; case x[m]< t : l=m+1; x[m]= t : p=m: break; x[m]> t : u=m-1Se deja como ejercicio para el lector comprobar que el tiempo de ejecuci´n ode este algoritmo es proporcional a log(n). Para resolver esto f´cilmente se apuede reescribir en forma recursiva y aplicar el teorema master.5.2.1. Prueba exhaustiva Ahora es necesario probar la b´squeda binaria. El primer paso es el de uconvertir la invariante, pre y post condiciones con afirmaciones o utilizandoel lenguaje JML. Sin embargo, esto no garantiza que el programa funcionecorrectamente para todos los casos. Consideremos el siguiente pseudo c´digo y realicemos una prueba de es- ocritorio:public class b´squeda { u public static int BusquedaBinaria(int[] x, int t) { int l = 0; int u = x.length - 1; int m = 0; int p = -1; while (l <= u) { m = (l + u) / 2; if (x[m] < t) l= m ; else if (x[m] == t) { p = m; break; } else u = m; } return p;
  • 118. 106 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION } Aparentemente es correcto, pero una prueba de escritorio extensiva eslarga y aburrida. Por esto es conveniente construir un conjunto de datos deprueba, para lo cual, utilizamos el siguiente c´digo: oint[] x = new int[MAXIMO];for (int i = 0; i < MAXIMO; i++) { x[i] = i * 5; }En este conjunto de datos conocemos perfectamente el contenido del vector,vale decir que, si buscamos un m´ltiplo de 5 deber´ encontrarlo. u ıa Un programa puede estar probado o certificado. Decimos que esta probadocuando funciona correctamente con los datos de prueba utilizados. Decimos que el programa est´ certificado cuando funciona correctamente acon todos los posibles casos que pueden ocurrir. Por ejemplo, con el vector de datos construidos podemos probar con al-gunos valores y ver que funciona adecuadamente. ¿Podremos decir lo mismopara todo los valores? Para realizar esta prueba vamos a buscar todos los elementos introducidosal vector y verificar que los encuentra y devuelve el resultado correcto. Elc´digo es el siguiente: ofor (int i = 0; i < MAXIMO; i++) { if (b´squeda.BusquedaBinaria(x, i * 5) != i) { u System.out.println("Error al buscar " + i*5); }Ahora sabemos que se prueba la b´squeda de todos los valores existentes en uel vector y no produce errores. Los valores que no existen en el vector pueden pertenecer a cualquierrango de datos. Por esto se hace necesario buscar un elemento no existenteentre cada uno de los valores introducidos obteniendo el sigiente c´digo: ofor (int i = 0; i < MAXIMO; i++) { if (b´squeda.BusquedaBinaria(x, i * 5 + 1) != -1) { u System.out.println("Error al buscar " + i*5+1); }
  • 119. ´5.2. ALGORITMOS DE BUSQUEDA 107Este c´digo nos certifica que el programa es correcto en un determinado oconjunto de datos. Que podemos decir si ampliamos el tama˜o del vector? nSolo que se ha probado y puede que funcione pero, no est´ certificado. El ac´digo completo es: opublic static final int MAXIMO = 1000;public static void main(String[] args) { System.out.println("Creando el vector"); int[] x = new int[MAXIMO]; for (int i = 0; i < MAXIMO; i++) { x[i] = i * 5; } System.out.println("Buscando elementos existentes"); for (int i = 0; i < MAXIMO; i++) { if (b´squeda.BusquedaBinaria(x, i * 5) != i) { u System.out.println("Error al buscar " + i*5); } } System.out.println("Buscando elementos no existentes"); for (int i = 0; i < MAXIMO; i++) { if (b´squeda.BusquedaBinaria(x, i * 5 + 1) != -1) { u System.out.println("Error al buscar " + i*5+1); } } System.out.println("Fin de la prueba");}Nos preguntamos que es lo que se debe especificar. Generalmente se debencolocar las invariantes, pre y post condiciones. Sin embargo es util tambi´n ´ eafirmar o especificar el O(n) para verificar el funcionamiento del programaen los tiempos previstos o detectar bucles infinitos.5.2.2. Representaci´n gr´fica de la b´ squeda o a u Una representaci´n gr´fica puede ser adecuada para mostrar como fun- o aciona un programa. Esto hace que de un golpe de vista se determine que elprograma funcione, aparentemente sin errores.
  • 120. 108 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION Para realizar una representaci´n gr´fica del programa de b´squeda binaria o a uconstruimos una l´ ınea para mostrar el rango de b´squeda. El programa debe user capaz de mostrar como se reduce el rango y contar el n´mero de iteraciones udel mismo. Para ejemplificar ´sto se muestra un programa que construye un vector econ los n´meros pares entre 0 y 60. Luego permite buscar un valor mostrando uel proceso seguido en la b´squeda. uimport java.awt.*;import java.awt.event.*;import java.awt.geom.*;import javax.swing.*;import javax.swing.event.*;public class Busbin { public static void main(String[] args) { TextFrame frame = new TextFrame(); frame.setSize(640,480); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }}class TextFrame extends JFrame{public TextFrame(){setTitle("b´squeda Binaria"); uDocumentListener listener = new TextoFieldListener();// agregar un panel con el texto a buscarJPanel panel = new JPanel();panel.add(new JLabel("Buscar:"));queBuscaField = new JTextField("30", 5);panel.add(queBuscaField);queBuscaField.getDocument().addDocumentListener(listener);
  • 121. ´5.2. ALGORITMOS DE BUSQUEDA 109add(panel, BorderLayout.NORTH);// agregar el graficomuestra = new DrawPanel();add(muestra, BorderLayout.CENTER);pack();}// recuperar el valor a buscarpublic void setTexto(){try { int queBuscas = Integer.parseInt( queBuscaField.getText().trim()); muestra.muestra(queBuscas); }catch (NumberFormatException e) {}//no se reliza nada si no se puede interpretar los datos }public static final int DEFAULT_WIDTH = 640;public static final int DEFAULT_HEIGHT = 480;private JTextField queBuscaField;private DrawPanel muestra;private class TextoFieldListener implements DocumentListener { public void insertUpdate(DocumentEvent event) {setTexto();} public void removeUpdate(DocumentEvent event) {setTexto();} public void changedUpdate(DocumentEvent event) {}}}class DrawPanel extends JPanel { int t=30, incrementos=20, medio=0,maximo=30;
  • 122. 110 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION int[] v = new int[maximo + 1]; public DrawPanel(){ for (int i = 0; i <= maximo; i++) { v[i] = i * 2; }}public void muestra(int x){ t=x; repaint();}public void paintComponent(Graphics g) { super.paintComponent(g); int desde=20, topY=100, hasta=600,l=0,u=maximo,m=0; Graphics2D g2 = (Graphics2D) g; g2.setPaint(Color.WHITE); g2.fillRect(0,0,640,480); g2.setColor(Color.BLACK); int hallo=-1,contador=0;// dibujar String explica="Las lineas representan el "+ "rango en el cual se busca"; g.drawString(explica, ((desde+hasta)/2 ) - (explica.length()*3), topY); while (l <= u) { topY += incrementos; m = (l + u) / 2; medio = (hasta + desde) / 2; g.drawString("" + contador++, 5, topY); g.drawString("" + v[l], desde, topY); g.drawString("" + v[u], hasta, topY); g.drawString("" + v[m], medio, topY); g2.draw(new Line2D.Double(desde, topY, hasta, topY)); if (v[m] < t) { l = m + 1; desde = medio + 1; } else if (v[m] == t) { topY += incrementos;
  • 123. ´5.3. CLASIFICACION 111 Figura 5.1: Representaci´n gr´fica de la b´squeda binaria o a u g.drawString("" + contador++, 5, topY); g.drawString("" + v[m],(hasta + desde)/ 2,topY); hallo = m; break; } else { u = m - 1; hasta = medio - 1; } } }}La salida del programa se ve en la figura 5.1 que, muestra como se va redu-ciendo el rango de b´squeda hasta encontrar el valor. A la izquierda se ve un ucontador con el n´mero de iteraci´n. u o5.3. Clasificaci´n o La clasificaci´n o procedimiento de ordenar es uno de los problemas m´s o aimportantes en la computaci´n y existen un sin n´mero de problemas de o uprogramaci´n que requieren de ella. A continuaci´n se detallan una serie de o oaplicaciones sin pretender que sean todas.
  • 124. 112 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION C´mo podemos probar que en un grupo de elementos no existen elemen- o tos duplicados? Bien para esto ordenamos el conjunto y posteriormente verificamos que no existen valores tales que x[i] = x[i + 1] recorriendo el conjunto para todos los valores de i permitidos. C´mo podemos eliminar los duplicados? Ordenamos el conjunto de da- o tos y luego utilizamos dos ´ındices haciendo x[j] = x[i]. Se incrementa el valor de i y j en cada iteraci´n. Cuando se halla un duplicado solo o incrementa i. Al finalizar ajustamos el tama˜o del conjunto al valor de n j. Supongamos que tenemos una lista de trabajos que tenemos que rea- lizar con una prioridad espec´ıfica. Puede ser por ejemplo una cola de impresi´n donde se ordenan los trabajos en funci´n de alguna priori- o o dad. Para esto ordenamos los trabajos seg´n la prioridad y luego se u los procesa en este orden. Por supuesto que hay que tomar recaudos al agregar nuevos elementos y mantener la lista ordenada. Una t´cnica muy utilizada para agrupar ´ e ıtems es la denominada cor- tes de control. Por ejemplo, si se desea obtener los totales de sueldo por departamento en una organizaci´n, ordenamos los datos por el de- o partamento que, se convierte en el elemento de control y luego cada vez que cambia imprimimos un total. Esto se denomina un corte de control. Pueden existir varios cortes de control, por ejemplo secci´n, o departamento, etc. Si deseamos hallar la mediana de un conjunto de datos podemos indicar que la mediana est´ en el medio. Por ejemplo para hallar el elemento a k ´simo mayor bastar´ en acceder a x[k]. e ıa Cuando queremos contar frecuencias y desconocemos el n´mero de ele- u mentos existentes o este es muy grande, ordenando y aplicando el con- cepto de control, con un solo barrido podemos listar todos las frecuen- cias. Para realizar uni´n de conjuntos se pueden ordenar los conjuntos, reali- o zar un proceso de intercalaci´n. Cuando hay dos elementos iguales solo o insertamos uno eliminando los duplicados. En el caso de la intersecci´n intercalamos los dos conjuntos ordenados o y dejamos uno solo de los que existan en ambos conjuntos.
  • 125. ´5.3. CLASIFICACION 113 Para reconstruir el orden original es necessario crear un campo adicio- nal que mantenga el original para realizar una nueva ordenaci´n para, o reconstruir el orden original. Como vimos tambi´n se pueden ordenar los datos para realizar b´sque- e u das r´pidas. a5.3.1. Clasificaci´n en Java o Los m´todos propios del Java proveen rutinas para ordenar objetos que efacilitan el desarrollo de aplicaciones. Para ordenar vectores que pueden ser de tipos int, long, short, char, byte,float o double es suficiente utilizar la clase Arrays con el m´todo sort, el esiguiente ejemplo genera 10 n´meros al azar y los ordena. uimport java.util.*;/** * Programa ordenar enteros * utilizando el metodo de java * @author Jorge Teran */public class SortVect { public static void main(String[] args) { int[] x = new int[10]; Random gen = new Random();//Generar 10 n´meros enteros entre 0 y 100 u for (int i = 0; i < 10; i++) x[i] = gen.nextInt(100);//Ordenar en forma ascendente Arrays.sort(x);//mostrar los n´meros ordenados u for (int i = 0; i < 10; i++) System.out.println(x[i]); }}
  • 126. 114 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACIONCuando se requiere ordenar un objeto se hace necesario crear un mecanismopara comparar los elementos del objeto. Construyamos una clase P ersonaque almacene nombre, apellido y nota.import java.util.*;class Persona { private String nombre; private String apellido; private int nota; public Persona(String no, String ap, int n) { nombre = no; apellido = ap; nota = n; } public String getNombre() { return nombre; } public String getApellido() { return apellido; } public int getNota() { return nota; }}Para crear diferentes instancias de P ersona se procede como sigue:Persona[] alumnos = new Persona[3];alumnos[0] = new Persona("Jose","Meriles", 70);alumnos[1] = new Persona("Maria","Choque",55);alumnos[2] = new Persona("Laura","Laura", 85); Si se requiere ordenar ´stos alumnos por nota no es posible utilizar direc- etamente Arrays.sort(alumnos) dado que el m´todo de clasificaci´n no conoce e ocu´les y qu´ campos comparar para realizar el ordenamiento. a e
  • 127. ´5.3. CLASIFICACION 115 Por esto es necesario primeramente escribir un m´todo que resuelva el eproblema. En nuestro ejemplo creamos el m´todo compareTo. Este nombre ees un nombre reservado de Java y lo que realiza es una sobrecarga de m´todo ereemplazando el m´todo de Java con el nuestro. e Los valores que debe devolver son −1 cuando es menor, 0 cuando es igualy 1 cuando es mayor. Lo que hace este m´todo es comparar el valor presente econ otro pasado a la rutina. Esta rutina utiliza el m´todo qsort para ordenar elos valores. Esta rutina queda como sigue:public int compareTo(Persona otro){ if (nota < otro.nota) return -1; if (nota > otro.nota) return 1; return 0; } Ademas es necesario especificar que la clase persona incluye el m´todo eComparable y se especifica as´ ı:class Persona implements Comparable<Persona>El programa final queda implementado en el siguiente c´digo: oimport java.util.*;/** * Programa ordenar objetos * utilizando el metodo de java * @author Jorge Teran */public class OrdObjeto { public static void main(String[] args) { Persona[] alumnos = new Persona[3]; alumnos[0] = new Persona("Jose", "Meriles", 70); alumnos[1] = new Persona("Maria", "Choque", 55); alumnos[2] = new Persona("Laura", "Laura", 85); Arrays.sort(alumnos); for (Persona e : alumnos)
  • 128. 116 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION System.out.println("Nombre=" + e.getNombre() + ", Apellido= " + e.getApellido() + ", nota=" + e.getNota()); }}class Persona implements Comparable<Persona> { private String nombre; private String apellido; private int nota; public Persona(String no, String ap, int n) { nombre = no; apellido = ap; nota = n; } public String getNombre() { return nombre; } public String getApellido() { return apellido; } public int getNota() { return nota; } public int compareTo(Persona otro) { if (nota < otro.nota) return -1; if (nota > otro.nota) return 1; return 0;
  • 129. ´5.3. CLASIFICACION 117 }}5.3.2. Algoritmos de clasificaci´n o Dado que el lenguaje ya incluye un soporte para realizar clasificacionescon un algoritmo parece que no es necesario revisar algorimos de clasificaci´n. oEn la realidad existen problemas que pueden ser resueltos m´s eficientemente acon un algoritmo espec´ ıfico. Esto se logra conociendo como est´n los datos aque pretendemos procesar. Los algoritmos para ordenar se clasifican en algoritmos generales y par-ticulares. Los algoritmos generales se pueden aplicar sin importarnos comoson los datos, en cambio los algoritmos particulares son aplicables a casosespeciales para obtener un mejor tiempo de proceso. Entre los algoritmos generales se explica el m´todo de clasificaci´n por e oinserci´n, el qsort, ordenaci´n por selecci´n y el de burbuja. o o oM´todo de la burbuja e El m´todo de la burbuja es el m´s simple y el m´s antiguo. Tambien hay e a aque mencionar que es el m´todo m´s lento para ordenar. e a El m´todo consiste en comparar todos los elementos de la lista con el eelemento de su lado. Si se requiere se realiza un intercambio para que est´n en eel orden previsto. Este proceso se repite hasta que todos los elementos est´neordenados. Vale decir que, en alguna pasada no se realiza ning´n intercambio. u El c´digo para este algoritmo es el siguiente: ovoid Burbuja (int[] x) { int i, j, temp; int n=x.length; for (i = (n - 1); i >= 0; i--) { for (j = 1; j <= i; j++) { if (x[j - 1] > x[j]) { temp = x[j-1]; x[j-1] = x[j]; x[j] = temp; } } }
  • 130. 118 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACIONComo se ve en el programa en el primer ciclo se recorren todos los elementos.El segundo ciclo se encarga de que el ultimo elemento sea el mayor de todos. ´ Analizando el programa se puede determinar que, el tiempo de procesoen el caso general es: 0 j=i 0 n−1 = i=n i=n−1 j=1 i=n−1 2como se ve, demora un tiempo proporcional a O(n2 ) que lo hace impr´ctico. aPodemos mencionar como una ventaja la simplicidad de la codificaci´n yocomo desventaja la ineficiencia del algoritmo. Existen otros m´todos que tambi´n tienen un tiempo similar pero que e eson mucho m´s eficientes que mencionamos a continuaci´n. a oClasificaci´n por inserci´n o o Cuando se tiene un conjunto de cartas en la mano lo que hacemos estomar una carta y buscar su ubicaci´n e insertarla en su sitio hasta ordenar otodas. Para ´sto podemos suponer que el primer elemento est´ en su lugar y e aproceder a colocar los siguientes en funci´n del primer elemento. o void Insercion(int[] x) { int i, j, temp; int n = x.length; for (i = 1; i < n; i++) { for (j = i; j > 0 && x[j - 1] > x[j]; j--) { temp = x[j-1]; x[j-1] = x[j]; x[j] = temp; } } }Para explicar el funcionamiento del algoritmo supongamos que inicialmentetenemos la siguiente secuencia de n´meros u 62 46 97 0 30Inicialmente suponemos que el primer valor es el menor y lo insertamos enla primera posici´n que, es el lugar donde estaba inicialmente, luego se toma o
  • 131. ´5.3. CLASIFICACION 119el siguinte valor y se ve si le corresponde estar antes o despu´s, en el ejemplo ese produce un intercambio 46 62 97 0 30 En la siguiente iteraci´n tomamos el 97 y se ve que, no debe recorrerse ohacia adelante por lo que no se hace ning´n intercambio. Luego se realiza lo umismo con el siguiente elemento recorriendo todo el vector e insertando elelemento en el lugar apropiado, obteniendo 0 46 62 97 30esto se repite hasta obtener el vector ordenado. Realizando el an´lisis del algoritmo se ve que el tiempo de ejecuci´n es a oproporcional a n−1 j=1 n−1 n−1 = i=n i=1 j=i i=1 2 La ventaja de este algoritmo es que es m´s simple que, el anterior y a´n a ucuando su tiempo de proceso es tambi´n proporcional a n2 es m´s eficiente e ay puede afinarse para ser m´s eficiente. El c´digo siguiente muestra el al- a ogoritmo mejorado para ser m´s eficiente. El tiempo de proceso sigue siendo aproporcional a O(n2 )void Insercion2(int[] x) { int i, j, temp; int n = x.length; for (i = 1; i < n; i++) { temp=x[i]; for (j = i; j > 0 && x[j - 1] > temp; j--) { x[j] = x[j-1]; } x[j] = temp; } }Como se observa se ha mejorado la parte que corresponde a constuir el espaciopara introducir el elemento siguiente reduciendo el n´mero de intercambios. u
  • 132. 120 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACIONOrdenaci´n por selecci´n o o Una alternativa al problema de ordenaci´n es el concepto de escoger el oelemento m´s peque˜o y reemplazarlo por el primer elemento, luego repetir a nel proceso para el segundo, tercero y as´ sucesivamente. El resultado es el ısiguiente programa void Seleccion(int[] x) { int i, j; int min, temp; int n = x.length; for (i = 0; i < n - 1; i++) { min = i; for (j = i + 1; j < n; j++) { if (x[j] < x[min]) min = j; } temp = x[i]; x[i] = x[min]; x[min] = temp; } }Como se observa este algoritmo es similar al algoritmo de inserci´n con tiem- o 2po similar y proporcional a O(n )Algoritmo de clasificaci´n r´pida o a El qsort cuyo nombre en ingl´s es QuickSort o tambi´n denominado al- e egoritmo de clasificaci´n r´pida ya fue publicada por C.A.R. Hoare en 1962. o ay se basa en dividir el vector en dos mitades utilizando un elemento denomi-nado pivote de tal forma que todos los elementos mayores al pivote est´n en eun vector y los restantes en el segundo vector. Como inicial pivote se puedetomar el primer elemento o uno al azar. Este proceso se repite en forma recursiva hasta tener el vector ordenado.A partir de este enfoque podemos realizar una primera aproximaci´n a lo oque viene ser el algoritmo:Ordenar (l,u){ if (u >= l) {
  • 133. ´5.3. CLASIFICACION 121 hay como maximo un elemento por lo tanto no hacer nada } hallar un pivote p para dividir en vector en dos Ordenar (l,p-1) Ordenar (p+1,u)}Aqu´ como digimos el problema es encontrar el punto de partici´n denomi- ı onado pivote. Utilizando el concepto que la invariante es que los valores entrex[m] y x[i] son menores al pivote x[l] podemos contruir el siguiente c´digo opara hallar el pivote.int m = l;//invariante los valores entre x[m] y x[i]//son menores al pivote x[l]for (int i = l + 1; i <= u; i++) { if (x[i] < x[l]) { temp = x[++m]; x[m] = x[i]; x[i] = temp; } }temp = x[l]; x[l] = x[m]; x[m] = temp;Supongamos que tenemos los siguientes datos: 27 2 81 81 11 87 80 7Iniciamos un contador m en el primer valor y tomando x[l] = 27 como pivotey se recorre el vector comparando cada uno de los valores con el pivotehaciendo un intercambio entre (m+1) y la posici´n del vector, obteniendo oen el primer intercambio entre el n´mero 2 que es menor que el pivote y el un´mero de la posici´n m que es casualmente el 2, obteniendo: u o 27 2 81 81 11 87 80 7
  • 134. 122 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACIONEl segundo intercambio es entre el 11 que es menor que el pivote y el 81obteniento: 27 2 11 81 81 87 80 7El tercer intercambio se produce con el 7 y el 81 obteniendo 27 2 11 7 81 87 80 81Para finalizar intercambiamos el pivote con la posici´n del ultimo n´mero o ´ umenor al pivote Obteniendo un vector donde todos los elementos menores alpivote est´n a la izquierda y los mayores a la derecha. a 7 2 11 27 81 87 80 81Este proceso se puede repetir recursivamente para el vector a la izquierda delpivote y para el que est´ a la derecha obteniento finalmente: a private void qsort(int[] x, int l, int u) { if (l >= u) return; int m = l, temp;//invariante los valores entre x[m] y x[i]// son menores al pivote x[l] for (int i = l + 1; i <= u; i++) { if (x[i] < x[l]) { temp = x[++m]; x[m] = x[i]; x[i] = temp; } } temp = x[l]; x[l] = x[m]; x[m] = temp; qsort(x, l, m - 1); qsort(x, m + 1, u); }Analizando el c´digo anterior podemos ver que el tiempo de proceso se puede ocalcular, utilizando los m´todos vistos en los cap´ e ıtulos anteriores 1 si n = 1, T (n) = 2T (n/2) + n en otros casos.
  • 135. ´5.3. CLASIFICACION 123En la ecuaci´n anterior n corresponde al ciclo f or que recorre todo los ele- omentos del vector reordenando el vector seg´n el pivote. Las siguientes dos ullamadas al programa hacen que 2T (n/2). Aplicando el teorema master ob-tenemos que el tiempo de proceso es proporcional a n log(n). Aunque no se divide exactamente a la mitad se ha tomado este valorpara mostrar como mejora la eficiencia . En la realidad se puede mejorar enfunci´n de como est´ el conjunto de datos y como se elige al pivote. o a En el caso de que el vector est´ previamente ordenado el tiempo de pro- eceso ser´ mayor. El proceso de elegir un pivote aleatoriamente produce un aalgoritmo m´s estable. Es posible optimizar el m´todo de ordenaci´n r´pida a e o apero no se tratar´ en el texto. Cuando uno requiere un algoritmo de estas acaracter´ısticas normalmente recurre a las rutinas ya implementadas en laslibrer´ del lenguaje. ıas Se pueden mejorar a´n m´s los algoritmos de clasificaci´n? En casos par- u a oticulares se puede obtener algoritmos proporcionales a O(n) en el caso m´s ageneral, el mejor algoritmo es proporcional a n log(n). Una demostraci´n se opuede leer en el texto de [GB96]Algoritmos de una pasada Considere las siguientes condiciones para los datos de entrada, se disponede memoria, suficiente, los datos son enteros positivos sin repetici´n en el orango de 0 a N, donde N es el n´mero m´ximo existente. Para ordenar estos u an´meros se puede utilizar cualquiera de los algoritmos descritos para ordenar. u Para mejorar el proceso de ordenar consideremos la siguiente estructuraBitSet a = new BitSet(max + 1);Si cada posici´n del vector representa a uno de los n´meros del vector se o uutiliza un bit para almacenar cada uno de los n´meros. En este caso es uposible leer los n´meros de entrada y encender el bit que le corresponde. uRecorriendo el vector se pueden imprimir los n´meros a los que corresponden ulos bits encendidos en forma ordenada. El resultado proporciona el siguiente algoritmo. public void bitSort(int[] x) { int max=0, j=0; for(int i =0; i< x.length; i++){ if (x[i] > max)
  • 136. 124 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION max=x[i]; } BitSet a = new BitSet(max + 1); // Hasta aqui todos los valores de // a estan en cero for(int i =0;i< x.length; i++) a.set(x[i]); for(int i =0;i<= max; i++){ if (a.get(i)) x[j++]=i ; } }Analizando el algoritmo se ve que se tienen tres ciclos que recorren todos losdatos dando un tiempo de ejecuci´n proporcional a O(n). oComparaci´n pr´ctica de la eficiencia de los algoritmos o a A fin de comparar los algoritmos de clasificaci´n es necesario hacer una ocorrida de los mismos sobre el mismo conjunto de datos. Para esto realizamosel siguiente programa:/**Programa para probar los diferentes * algoritmos de ordenaci´n o * @author Jorge Teran * */import java.util.*;public class pruebaMetodos { public static int MAXIMO = 10000; public static void main(String[] args) { //generar MAXIMO n´meros sin repetidos u int[] x = new int[MAXIMO]; int[] y = new int[MAXIMO]; for (int i = 0; i < MAXIMO; i++) x[i]=i;
  • 137. ´5.3. CLASIFICACION 125 Random gen = new Random(); int temp, j; for (int i = 0; i < MAXIMO; i++){ j = gen.nextInt(MAXIMO); temp = x[i]; x[i] = x[j]; x[j]=temp; } System.out.println("Tama~o de la instancia"+MAXIMO); n long tiempoInicio, tiempoFin, tiempoTotal; Metodos sort =new Metodos(); //obtener una copia de x para ordenar //para siempre utilizar el mismo conjunto de datos System.arraycopy(x,0,y,0,MAXIMO); tiempoInicio = System.currentTimeMillis(); sort.Burbuja(y); tiempoFin = System.currentTimeMillis(); tiempoTotal = tiempoFin - tiempoInicio; System.out.println(" M´todo Burbuja " e + " Tiempo de proceso " + tiempoTotal); System.arraycopy(x,0,y,0,MAXIMO); tiempoInicio = System.currentTimeMillis(); sort.Insercion(y); tiempoFin = System.currentTimeMillis(); tiempoTotal = tiempoFin - tiempoInicio; System.out.println(" M´todo Insercion " e + " Tiempo de proceso " + tiempoTotal); System.arraycopy(x,0,y,0,MAXIMO); tiempoInicio = System.currentTimeMillis(); sort.Insercion2(y); tiempoFin = System.currentTimeMillis(); tiempoTotal = tiempoFin - tiempoInicio; System.out.println(" M´todo Insercion2 " e + " Tiempo de proceso " + tiempoTotal);
  • 138. 126 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION System.arraycopy(x,0,y,0,MAXIMO); tiempoInicio = System.currentTimeMillis(); sort.Seleccion(y); tiempoFin = System.currentTimeMillis(); tiempoTotal = tiempoFin - tiempoInicio; System.out.println(" M´todo Seleccion " e + " Tiempo de proceso " + tiempoTotal); System.arraycopy(x,0,y,0,MAXIMO); tiempoInicio = System.currentTimeMillis(); sort.quickSort(y); tiempoFin = System.currentTimeMillis(); tiempoTotal = tiempoFin - tiempoInicio; System.out.println(" M´todo quickSort " e + " Tiempo de proceso " + tiempoTotal); System.arraycopy(x,0,y,0,MAXIMO); tiempoInicio = System.currentTimeMillis(); sort.bitSort(y); tiempoFin = System.currentTimeMillis(); tiempoTotal = tiempoFin - tiempoInicio; System.out.println(" M´todo bitSort " e + " Tiempo de proceso " + tiempoTotal); }}obteniendo los siguientes resultados para el proceso de 100.000 n´meros ge- unerados aleatoriamente. M´todo e Tiempo de proceso en miliseg Burbuja 265.251 Inserci´n o 114.364 Inserci´n2 o 86.795 Selecci´n o 155.854 quickSort 110 bitSort 30Hay que observar que antes de cada proceso hemos realizado una copia delvector original para que la comparaci´n sea adecuada al mismo conjunto de o
  • 139. ´5.3. CLASIFICACION 127datos. En funci´n del tama˜o del conjunto el comportamiento de los algorit- o nmos ser´ diferente y es posible comprobarlo experimentalmente. El tiempo aque demor´ el m´todo de Java para 100.000 n´meros aleatorios 60 milise- o e ugundos.5.3.3. Laboratorio Para probar que el sort de burbuja toma un tiempo menor al qsort solose requiere hallar un n que cumpla la relaci´n o n−1 n < n log(n) 2Algebraicamente podemos hallar ´stos valores. Pero sabemos que una im- eplementaci´n particular est´ afectada por una constante que var´ seg´n el o a ıa ugrado de eficiencia con el que fue programado, el lenguaje o las caracter´ ısticasdel conjunto de datos. Lo que, se pide es que realice una implementaci´n de los algoritmos ex- oplicados y encuentre experimentalmente el n´mero de elementos para los que uun algoritmo sea mejor que otro. Este proceso debe realizarse tanto para un vector ordenado de maneraaleatorea, ascendente y descendente.5.3.4. Ejercicios 1. Describir las invariantes de ciclo para el algoritmo de Burbuja. 2. Describir las invariantes de ciclo para el algoritmo de Inserci´n. o 3. Describir las invariantes de ciclo para el algoritmo de Selecci´n. o5.3.5. Ejemplo de aplicaci´n o Se presenta el problema 120 publicado en el Juez de Valladolid Espa˜a y nque es un t´ıpico problema de ordenaci´n. o Cocinar panqueques en una sart´n es bastante complicado porque sin eimportar cuanto se esmere todos tendr´n un di´metro diferente. Para la a apresentaci´n de la pila usted los puede ordenar por tama˜o de tal manera o nque cada panqueque es m´s peque˜o que los que est´n m´s abajo. El tama˜o a n a a nest´ dado por el di´metro. a a
  • 140. 128 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION La pila se ordena por una secuencia de volteos. Un volteo consiste eninsertar una esp´tula entre dos panqueques y volteando todos los panqueques aen la esp´tula (colocando en orden reverso la subpila). Un volteo se especifica aindicando la posici´n del panqueque en la base de la subpila a ser volteado. oEl panqueque de la base tiene la posici´n 1 y el de encima n. o La pila se especifica dando el di´metro de cada panqueque en orden en aque aparecen. Por ejemplo considere las tres pilas de panqueques en el cual8 es el panqueque encima de la pila de la izquierda 8 7 2 4 6 5 6 4 8 7 8 4 5 5 6 2 2 7 La pila de la izquierda puede ser transformada a la pila del medio porvolteo(3). La del medio puede transformarse en la de la derecha con volteo(1).Entrada La entrada consiste en secuencias de pilas de panqueques. Cada pilaconsiste de 1 a 20 panqueques y cada panqueque tendr´ un di´metro entero a aentre 1 y 100, la entrada se termina con un fin de archivo. Cada pila est´ dada aen una fila con el panqueque de arriba primero y el de la base al final. Todosellos separados por un espacio.Salida Para cada pila de panqueques su programa debe imprimir la pilaoriginal en una l´ınea seguido de una secuencia de volteos que ordena la pilade panqueques de tal forma que el panqueque m´s grande este abajo y el m´s a apeque˜o arriba, la secuencia de volteos debe terminar con un 0 indicando que nno se requieren m´s volteos. Cuando la pila est´ ordenada no se deben realizar a am´s volteos. aEjemplo entrada1 2 3 4 55 4 3 2 15 1 2 3 4Ejemplo Salida1 2 3 4 505 4 3 2 11 0
  • 141. ´5.3. CLASIFICACION 1295 1 2 3 41 2 0Soluci´n Para resolver el ejercicio en cuesti´n lo primero que se debe evaluar o oes si se parece a alg´n algoritmo, conocido de clasificaci´n. El segundo paso u oes el de determinar si el algoritmo provisto por el lenguaje de programaci´noresuelve el problema, pues no vamos a contruir un algoritmo existiendo unoque resuelve el problema. Como se ve es muy parecido al m´todo de inserci´n por lo que codifica- e oremos ´ste y agregaremos los requerimientos del problema. e Primero un m´todo para invertir la pila de panqueques que denominare- emos reverso. void reverso(int[] pan, int l) { int temporal = 0; int i = 0; int j = l; while (i < j) { temporal = pan[i]; pan[i] = pan[j]; pan[j] = temporal; i++; j--; } return;En segundo lugar codificamos el m´todo buscando el lugar apropiado para erealizar la inserci´n que se consigue llamando a reverso o void inicio() {...... c = 0; l = l - 1; ver(pan, l); // listar el orden original for (int i = l; i > 0; i--) { max = i; for (int j = i - 1; j >= 0; j--) if (pan[j] > pan[max])
  • 142. 130 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION max = j; if (max != i) { if (max == 0) System.out.print((l + 1 - i) + " "); else System.out.print((l+1-max) + " " + (l+1-i) + " "); reverso(pan, max); reverso(pan, i); } } System.out.println("0"); } } void ver(int[] pan, int l) {//lista los datos instroducidos for (int i = 0; i < l; i++) System.out.print(pan[i] + " "); System.out.print(pan[l] + "n"); } }Intencionalmente hemos omitido la parte de la lectura de datos porque esirrelevante en la explicaci´n del procedimiento de resoluci´n. o o
  • 143. 5.4. EJERCICIOS 1315.4. Ejercicios5.4.1. Problema 10107 - Hallar la mediana La mediana juega un importante rol en el mundo de las estad´ ısticas. Pordefinici´n, esta es un valor que divide una colecci´n en dos partes iguales. En o oeste problema tiene que determinar el flujo medio de algunos enteros largos.Supongamos que, tenemos cinco n´meros {1, 3, 6, 2, 7}. En este caso, 3 es la umediana como tiene exactamente dos n´meros en cada lateral. {1, 2} y {6, 7}. u Si fueran un n´mero par de valores como {1, 3, 6, 2, 7, 8}, solamente un uvalor n puede dividir esta colecci´n en dos partes iguales, as´ nosotros con- o ısideramos el promedio de la mitad de estos valores {3, 6}. De esa manera,la mediana ser´ (3 + 6)/2 = 4,5. En este problema tu tienes que imprimir asolamente la parte entera, no los decimales. Como resultado, acordado eneste problema, la mediana debe ser 4. Entrada.- El archivo de entrada consiste de una serie de enteros X (0 <=X < 231 ) y el n´mero total de enteros N es menor que 10.000. Los n´meros u upueden tener espacios blancos, antes o despu´s. e Salida.- Para cada entrada imprime el valor de la mediana con los valoresintroducidos hasta el momento. Ejemplo de entrada Ejemplo de salida 1 1 3 2 4 3 60 3 70 4 50 27 2 4
  • 144. 132 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION5.4.2. Problema 10295 - C´lculo de salario a Cada empleado en un trabajo burocr´tico tiene una descripci´n de su a otrabajo en un peque˜o p´rrafo, que describe las responsabilidades del mismo. n a La descripci´n del trabajo est´ combinado con aspectos tales como expe- o ariencia para definir su salario. El sistema libera al personal de recursos humanos de tener que juzgar enforma inteligente como valorar a un empleado. El proceso consiste en juzgaral empleado en base de una serie de frases buscando las palabras que implicanresponsabilidad. Debe implementar un sistema simplificado de c´lculo de salarios. Dado aun diccionario de palabras y un n´mero de descripciones de trabajos debe ucalcular el salario de cada persona. La primera entrada contiene dos n´meros enteros positivos m <= 1000 uque corresponden al n´mero de palabras en el diccionario y un n´mero n <= u u100 que indica el n´mero de descripciones de trabajo. u Cada palabra del diccionario contiene una palabra y un valor que es unn´mero real entre 0 y 1.000.000. Seguidamente vienen las descripciones de ulos puestos de trabajos que consisten en una o varias l´ ıneas de texto queterminan en un punto. Para cada descripci´n del texto debe imprimir el salario calculado que es ola suma de los puntos asignados en las palabras de la descripci´n que figuran oen el diccionario. Entrada.- 7 2administer 100000spending 200000manage 50000responsibility 25000expertise 100skill 50money 75000the incumbent will administer the spending of kindergarden milk money andexercise responsibility for making change he or she will share responsibility forthe task of managing the money with the assistant whose skill and expertiseshall ensure the successful spending exercise.this individual must have the skill to perform a heart transplant and expertisein rocket science
  • 145. 5.4. EJERCICIOS 133. Ejemplo de salida.-700150150
  • 146. 134 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION5.4.3. Problema 331 - Contando los intercambios La clasificaci´n como se vi´ puede realizarse intercambiando valores ad- o oyacentes utilizando el m´todo de la burbuja e Si realizamos un listado de los pares de n´meros a ser intercambiados se uobtiene un mapa de intercambios y la secuencia en que se deben realizar. Porejemplo, si se quiere ordenar un vector cuyos elementos son 3, 2, 1 se puedeordenar intercambiando los valores A2 y A3, despu´s A1 y A2, y finalmente eA2 con A3. Si el par identificado en el mapa de intercambios por el ´ındice del vectordel primer elemento a ser intercambiado, el proceso anterior se caracteri-zar´ como 2 1 2. a Es util hacer notar que pueden existir muchas formas de intercambiar ´objetos adyacentes para ordenar un vector. El vector anteriormente descriptoque, contiene 3 2 1, tambi´n puede ser ordenado intercambiando A1 y A2, eluego A2 y A3 y finalmente A1 y A2. El mapa de intercambios en estasecuencia es 1 2 1. Se pide que para, un arreglo se cuente el n´mero de mapas de intercambio udiferentes que existen. Pensando un poco podemos llegar a la conclusi´n de oque existen infinitos mapas de intercambio. Con el ejemplo anterior podemosescribir 1 1 1 2 1 que tambi´n dejar´ el vector en forma ascendente. La pre- e agunta se refiere a encontrar los mapas de intercambio existentes, que tenganel m´ınimo de intercambios. Entrada La entrada es un conjunto de casos arbitrarios seguidos de un 0.Cada caso de entrada comienza con un n´mero n que indica el tama˜o del u narreglo. Salida Para cada caso de entrada imprima un mensaje como los mostradosindicando el n´mero de mapas existentes, que en ning´n caso pasar´ de 5. u u a Ejemplo de entrada2 9 72 12 503 3 2 13 9 1 50Ejemplo de salidaThere are 1 swap maps for input data set 1.
  • 147. 5.4. EJERCICIOS 135There are 0 swap maps for input data set 2.There are 2 swap maps for input data set 3.There are 1 swap maps for input data set 4.5.4.4. Problema 499 - Hallar la frecuencia El problema consiste en hallar las letras que ocurren con mayor frecuenciaen una l´ınea de texto. La salida contiene la lista de letras que incurrieron con la m´xima fre- acuencia seguido de la frecuencia. La lista de letras debe estar en min´sculas y en forma ordenada. u Ejemplo de entradaWhen riding your bicycle backwards down a one-way street, if thewheel falls of a canoe,how many ball bearings does it take to fillup a water buffalo?Hello Howard.Ejemplo de salidae6al 7a3Hlo 2
  • 148. 136 ´ ´ 5. APLICACIONES DE BUSQUEDA Y CLASIFICACION
  • 149. Cap´ ıtulo 6 Combinatoria b´sica a6.1. Introducci´n o La combinatoria es la disciplina de las matem´ticas que se refiere a las at´cnicas de contar. En realidad lo que trata de responder es a la pregunta e¿cu´ntos son? sin tener que contarlos. a En general las t´cnicas de contar proveen una serie de alternativas al emomento de tener que escribir programas complicados que cuenten todos losvalores y permiten tener expresiones, que solucionen el problema aplicandof´rmulas simples. o6.2. T´cnicas b´sicas para contar e a En esta parte recordaremos una serie de f´rmulas de la combinatoria y omostraremos como son aplicadas en la programaci´n. No desarrollaremos los oconceptos matem´ticos porque no corresponde a lo que el texto pretende, aque es mostrar la forma de resolver problemas.Regla del Producto Si un conjunto A tiene |A| posibilidades y el B tiene |B| posibilidades entonces existen |A| x |B| formas de combinar ´stos. e Por ejemplo si tengo 4 tipos de autom´viles y 3 colores se tienen 12 o combinaciones. Estas combinaciones pueden representarse en una ma- triz cuadrada almacenando en cada celda una combinaci´n. En el caso o de tres conjuntos con una matriz de tres dimensiones, vea que el espacio ocupado o el recorrido de los elementos se hace cada vez m´s grande a 137
  • 150. 138 ´ 6. COMBINATORIA BASICARegla de la suma Si un conjunto A tiene |A| posibilidades y el B tiene |B| posibilidades entonces existen |A| + |B| posibles formas en las que A o B pueden ocurrir. En el ejemplo anterior si uno de los autom´viles, o o de los colores es errado, existen 4 + 3 = 7 posibles ´ ıtems fallados.Regla inclusi´n y exclusi´n Esta es una regla generalizada de la suma. o o Supongamos que tenemos autom´viles de 5 colores y minibuses de 6 o colores y queremos conocer cu´ntos colores diferentes existen. En este a caso tenemos dos conjuntos que se superponen. Esto significa sumar la cantidad de colores de ambos y restar los que sean comunes a ambos que se expresa como: |A| ∪ |B| = |A| + |B| − |A| ∩ |B|Permutaciones Una permutaci´n es un arreglo de n ´ o ıtems donde cada ´ıtem aparece solo una vez. Existen 3! permutaciones para un conjunto de tres elementos. Si los elementos son 123 las permutaciones vienen a ser 123 132 231 213 312 321. Para un n arbitrario son n!. hay que observar que a medida que aumenta n el n´mero de permutaciones aumenta muy u r´pidamente. aSubconjuntos Un subconjunto es la selecci´n de algunos elementos de n o ıtems. Para un conjunto arbitrario existen 2n posibles subcon- posibles ´ juntos, por ejemplo para 3 elementos existen 23 subconjuntos, ´sto es: e 1,2,3,12,13,23,123 y el conjunto vac´ A medida que crece n, r´pida- ıo. a mente se llega a tiempos de proceso muy grandes.Cadenas Cuando tratamos con cadenas o sea una secuencia de ´ ıtems con n repetici´n, se tienen m distintas secuencias. Para 3 elementos con re- o petici´n se tienen 27 casos que son 111, 112, 113, 121, 122, 123, 131, o 132, 133, 211, 212, 213, 221, 222, 223, 231, 232, 233, 311, 312, 313, 321, 322, 323, 331, 332, 333. El n´mero crece m´s r´pidamente a medida u a a que crece m. En muchos casos podemos encontrar que lo que tenemos es una funci´n obiyectiva o sea un asociaci´n uno a uno con otro conjunto. En este caso opodemos resolver el problema de contar cualquiera de los dos conjuntos. Porejemplo si decimos que cada planta est´ en una maceta da lo mismo contar alas plantas o las macetas. Si una maceta pudiera tener m´s de una planta aesto ya no es cierto.
  • 151. 6.3. COEFICIENTES BINOMIALES 1396.3. Coeficientes binomiales Los coeficientes binomiales se refieren a calcular n kque es el n´mero de formas posibles de escoger k elementos de n posibilidades. uQue elementos se cuentan m´s comunmente? aComit´s Cuantas maneras hay de formar un comit´ de k miembros con n e e personas. La respuesta se halla por la definici´n. oCaminos en un matriz C´antas maneras hay de viajar desde la esquina u superior hasta la esquina inferior derecha en una matriz de m x n caminando solamente hacia abajo o hacia la izquierda? Cada camino debe consistir de m + n pasos n hacia abajo y m a la derecha, por lo que existen: n+m n nCoeficientes de (a + b)n Cu´l es el coeficiente de ak bn−k claramente a k porque cuenta el n´mero de formas que podemos utilizar para escoger u k elementos de n.Tri´ngulo de Pascal Para calcular los coeficientes binomiales de puede a realizar utilizando directamente la f´rmula o n n! = k k!(n − k)! Sin embargo los c´lculos intermedios pueden hacer que el trabajo con a n´meros grandes sea inadecuado o de tiempo muy largo, una alternativa u es utilizar el tri´ngulo de Pascal. a n p(n) p(n,1) p(n,2) p(n,3) p(n,4) p(n,5) p(n,6) 1 1 2 1 1 3 1 2 1 4 1 3 3 1 5 1 4 6 4 1 6 1 5 10 10 5 1 7 1 6 15 20 15 6 1
  • 152. 140 ´ 6. COMBINATORIA BASICA Lo interesante de ´ste tri´ngulo es que calcula los coeficientes binomia- e a les sin tener que realizar factoriales. Para calcular n tomados de k en tiempo constante podemos construir el tri´ngulo de Pascal a /**Programa para constuir el * triangulo de Pascal * @author Jorge Teran * */ public static void tri´ngulo(int[][] x) { a // Invariante cada linea debe comenzar con uno for (int i=0;i<MAXIMO;i++) x[i][0]=1; // Invariante cada linea debe terminar con uno for (int i=0;i<MAXIMO;i++) x[i][i]=1; for (int i=1;i<MAXIMO;i++) // Invariante cada linea debe sumar 2**i for (int j=1;j<=i;j++) x[i][j]=x[i-1][j-1]+x[i-1][j]; } } luego es posible hallar n tomados de k public static int nTomadosDek( int [][] x,int n, int k) { return x[n][k]; } Ahora explicamos cu´les son las invariantes del tri´ngulo de Pascal. a a Primero cada l´ ınea debe comenzar y terminar con 1. Y en segundo ınea la suma de sus valores da 2i . Esto es lugar en cada l´ k=i i = 2i k k=0
  • 153. 6.4. ALGUNAS SECUENCIAS CONOCIDAS 141 F´ ıjese que en ´sta implementaci´n se utiliza solo la mitad del arreglo e o bidimensional creado. Una propiedad interesante es que la suma de las diagonales del tri´ngulo a da los n´meros de Fibonacci, que se presentan en la siguiente secci´n, u o veamos esto con los datos del ejemplo: Diagonal Suma 1 1=1 2 1=1 3 1+1=2 4 2+1=3 5 1+3+1=5 6 3+4+1=8 Otras propiedades del tri´ngulo de Pascal pueden verse en a http://mathworld.wolfram.com/6.4. Algunas secuencias conocidas6.4.1. N´ meros de Fibonacci u Los n´meros de Fibonacci son la secuencia de n´meros definidos por la u uecuaci´n: o T (n) = T (n − 1) + T (n − 2)Teniendo definido que T (0) = 0 y T (1) = 1, se genera la siguiente secuencia1, 1, 2, 3, 5, 8, 13, 21, ... Los n´meros Fibonacci aparecen en diferentes ´mbitos, desde la cripto- u agraf´ como menciona Dan Brown en su novela C´digo DaVinci, en la na- ıa, oturaleza existen ejemplos, en cristalograf´ y en la descripci´n de la posici´n ıa o ode las semillas en las plantas de girasol. Para hallar el t´rmino en´simo de la secuencia podemos utilizar los m´to- e e edos de resoluci´n de recurrencias obteniendo: o √ √ n 1 1+ 5 n 1− 5 T (n) = √ (( ) −( ) 5 2 2Una explicaci´n detallada se halla en el texto de Matem´tica Discreta de o aGrimaldi [Gri77].
  • 154. 142 ´ 6. COMBINATORIA BASICA Los n´meros de Fibonacci satisfacen tambi´n la siguinte relaci´n del m´xi- u e o amo com´n divisor u M CD(Fn , Fm ) = FM CD(n,m) Tambi´n se puede ver que los n´meros de Fibonacci tienen la carater´ e u ısticade que al dividirse m´dulo m, producen una secuencia c´ o ıclica. Fibonacci mod 2 mod 3 mod 4 1 1 1 1 1 1 1 1 2 0 2 2 3 1 0 3 5 1 2 1 8 0 2 0 13 1 1 1 21 10 0 1 34 00 1 2 55 00 1 36.4.2. N´ meros Catalanes u Los n´meros Catalanes son los n´meros que est´n asociados a la f´rmula u u a o n−1 1 2n Cn = Ck Cn−1−k = n+1 n k=0Los primeros n´meros Catalanes son: 1,1,2,5,14,42,132,429 y se pueden ob- utener como sigue: n´mero Catalan Valor u C0 1 C1 1 C2 C0 C1 + C1 C0 = 2 C3 C0 C2 + C1 C1 + C2 C0 = 5 C4 C0 C3 + C1 C2 + C2 C1 + C3 C0 = 14Estos n´meros se presentan en diferentes problemas, veamos por ejemplo ula siguiente secuencia {−1, −1, −1, 1, 1, 1}. ¿De cu´ntas maneras se pueden aordenar para que las sumas parciales de los elementos sea positiva?
  • 155. 6.4. ALGUNAS SECUENCIAS CONOCIDAS 143 Estos elementos son {1, 1, 1, −1, −1, −1}, {1, 1, −1, 1, −1, −1},{1, 1, −1, −1, 1, −1}, {1, −1, 1, 1, −1, 1} y {1, −1, 1, −1, 1, −1}. Esta secuencia corresponde al n´mero Catal´n 3 que es 5, que tambi´n u a epodemos calcular de la combinatoria 1 6 =5 3+1 3 Algunos otros ejemplos de aplicaci´n de los n´meros Catalanes son los o usiguientes. ¿De cu´ntas formas se pueden colocar 3 par´ntesis de tal manera que a e cada par´ntesis de apertura tenga su respectivo de cierre? La respuesta e es el n´mero Catal´n 3, veamos ((())), ()(()), (())(), (()()) y ()()() u a Dado un pol´ ıgono regular de n v´rtices, de cu´ntas formas se puede e a dividir en n − 2 tri´ngulos, si las diferentes orientaciones se cuentan en a forma diferente?. Un cuadrado se puede dividir en dos tri´ngulos con a una l´ ınea entre sus v´rtices las posibilidades son 2. En un pent´gono se e a hace con, dos l´ıneas y se obtienen 3 tri´ngulos y el n´mero de casos es a u n´mero Catal´n 3 o sea 5. u a Dados dos candidatos A y B que en una elecci´n, cada uno obtiene o n votos (empate). De cuantas maneras se puede contar los votos de tal forma que al realizar el recuento, el candidato A siempre est´ por e delante del candidato B. Este tambi´n el n´mero Catal´n n. e u a6.4.3. N´ mero Eulerianos u Sea p = {a1 , a2 , ...an }, deseamos conocer todas las permutaciones quecumplen la relaci´n ai < ai+1 . Por ejemplo si p = {1, 2, 3, 4} se construyen otodas las permutaciones de p y contamos los casos en los que se cumple larelaci´n de orden: o
  • 156. 144 ´ 6. COMBINATORIA BASICA Permutaci´n o Cu´ntos cumplen Permutaci´n a o Cu´ntos cumplen a 1234 3 2134 2 1243 2 2143 1 1324 2 2314 2 1342 2 2341 2 1423 2 2413 2 1432 1 2431 1 3124 2 4123 2 3142 1 4132 1 3214 1 4213 1 3241 1 4231 1 3412 2 4312 1 3421 1 4321 0por ejemplo la permutaci´n 2341 tiene 2 < 3 y 3 < 4 que son dos casos que ocumplen la relaci´n de orden. Cu´ntas permutaciones de 4 elementos tienen o ados casos que cumplen la relaci´n de orden?. Este valor est´ representado o apor n´mero Euleriano u k+1 n n+1 = (−1)j (k − j + 1)n k j j=0si contamos los valores del ejemplo vemos que son 11. Si organizamos estos n´meros en un tri´ngulo se obtiene el tri´ngulo u a aEuleriano n n n n n n n 0 1 2 3 4 5 1 1 2 1 1 3 1 4 1 4 1 11 11 1 5 1 26 66 26 1 6 1 57 302 302 57 1 Analizando la tabla de permutaciones realizada vemos que 4 4 4 4 =1 = 11 = 11 =1 0 1 2 3
  • 157. 6.4. ALGUNAS SECUENCIAS CONOCIDAS 145corresponden al tri´ngulo presentado. a Este tri´ngulo puede generarse de la siguiente relaci´n de recurrencia: a o n n−1 n−1 =k + (n − k + 1) (6.4.1) k k k−1 Una propiedad interesante de los n´meros Eulerianos que, puede utilizarse ucomo invariante es que: n n = n! k k=0 El presente programa genera dicho tri´ngulo utilizando la recurrencia a6.4.1/**Programa para construir el * triangulo Euleriano * @author Jorge Teran **/public class Eulerian { public final static int MAXIMO=6; public static void main(String[] args) { int [][] x = new int [MAXIMO][MAXIMO]; for (int i=0;i<MAXIMO;i++) x[i][1]=1; for (int i=0;i<MAXIMO;i++) x[i][i]=1; for (int i=2;i<MAXIMO;i++) for (int j=2;j<=i;j++) x[i][j]=(i-j+1)*x[i-1][j-1] +j*x[i-1][j]; for (int i=1;i<MAXIMO;i++){ System.out.println(" "); for (int j=1;j<=i;j++) System.out.print(x[i][j]+" "); } }}
  • 158. 146 ´ 6. COMBINATORIA BASICA6.4.4. N´ meros de Stirling u Consideremos un conjunto con n elementos, el n´mero total de subcon- u njuntos que podemos formar es 2 . Nos preguntamos cu´ntos conjuntos de k asubconjuntos podemos formar que excluyan el elemento vac´ y la uni´n de ıo oellos, nos da el conjunto original? Para comprender el problema considere el conjunto p = {1, 2, 3, 4} todoslos conjuntos de 2 elementos son: 1 {(1),(2,3,4)} 2 {(2),(1,3,4)} 3 {(3),(2,1,4)} 4 {(4),(2,3,1)} 5 {(1,2),(3,4)} 6 {(1,3),(2,4)} 7 {(1,4),(2,3)}Como podemos calcular este valor?. Primeramente veamos que un conjunto ¯ ¯de n elementos se puede dividir en dos conjuntos {A, A} y {A, A} Comotenemos dos conjuntos existen dos conjuntos vac´ entonces el total de sub- ıos,conjuntos que puede tener A y A ¯ son 2n − 2. Como no nos importa el orden,vale decir que el complemento est´ antes o despu´s hay que tomar la mitad e ede los elementos, esto es: 2n − 2 = 2n − 1 2 En el caso de dividir en dos subconjuntos es relativamente simple dehallar el resultado. En cambio cuando tenemos un n´mero mayor se hace um´s complicado. a Estos n´meros se denominan n´meros de Stirling de segundo orden. Pa- u ura calcular S(n, k) se puede utilizar, al igual que los ejemplos anteriores lasiguiente recurrencia: S(n, k) = S(n − 1, k) + kS(n − 1, k)Hay que tomar en cuenta que los l´ ımites son: S(n, 1) = 1, y S(n, n) = 1.6.4.5. Particiones enteras Se quiere contar de cu´ntas formas se puede escribir un n´mero entero a upositivo como la suma de enteros positivos. Ahora el orden de los sumandos
  • 159. 6.4. ALGUNAS SECUENCIAS CONOCIDAS 147es irrelevante. Cada una de estas formas se denomina partici´n y cada uno ode los sumandos parte. Por ejemplo: 1 5=1+1+1+1+1 2 5=1+1+1+2 3 5=1+2+2 4 5=1+1+3 5 5=2+3 6 5=1+4 7 5=5En este caso la partici´n de 5 tiene 7 posibles particiones. Este problema no olo desarrollaremos y mencionaremos la recurrencia As´ analizamos este ejemplo veremos que hay 1 partici´n de 5 elementos, ı o1 de 4, 2 de 3, 2 de 2 y 1 de 1. Sea p(n, k) el n´mero total de elementos de uuna partici´n de k elementos entonces el n´mero de particiones o u k=n p(n) = p(n, k) k=1Estos valores tambi´n nos proporcionan un tri´ngulo que puede armarse con e ala siguiente recurrencia: p(n, k) = p(n − 1, k − 1) + p(n − k, k)Considerando que p(1, 1) = 1 y que p(n, k) = siendo k > n. El siguienteprograma produce el resultado deseado./**Programa para hallar las * particiones enteras * @author Jorge Teran **/public class ParticionEntera { public final static int MAXIMO = 8; public static void main(String[] args) { int[][] x = new int[MAXIMO][MAXIMO]; for (int i = 1; i < MAXIMO; i++)
  • 160. 148 ´ 6. COMBINATORIA BASICA n p(n) p(n,1) p(n,2) p(n,3) p(n,4) p(n,5) p(n,6) p(n,7) 1 1 1 2 2 1 1 3 3 1 1 1 4 5 1 2 1 1 5 7 1 2 2 1 1 6 11 1 3 3 2 1 1 7 15 1 3 4 3 2 1 1 Cuadro 6.1: Tri´ngulo para hallar las particiones a for (int j = 1; j <= i; j++) { if (j == 1 || j == i) x[i][j] = 1; else x[i][j] = x[i - j][j] + x[i - 1][j - 1]; } for (int i = 1; i < MAXIMO; i++) { System.out.println(" "); for (int j = 1; j <= i; j++) System.out.print(x[i][j] + " "); } }}El resultado del proceso produce el tri´ngulo que mostramos en el cuadro a6.1 donde la p(n,k) esta representado por la fila y la columna. Para hallarel n´mero total de particiones solo hay que sumar los elementos de una fila. uEstos est´n sumarizados en la columna p(n). a
  • 161. 6.5. EJERCICIOS 1496.5. Ejercicios6.5.1. Problema 357 - Formas de combinar monedas Despu´s de realizar la compra en una tienda de departamentos, el cambio efue de 17 centavos. El recibi´ una moneda de 10 centavos una de 5 centavos oy dos de dos centavos. D´ despues realizando compras recibi´ otra vez ıas o17 centavos de cambio, en dos monedas de 5 centavos y 7 de un centavo.Luego se pregunt´ ¿en cuantas tiendas puedo comprar y recibir cambio de o17 centavos, en diferentes combinaciones de monedas? Despu´s de pensar eobtuvo la respuesta, que es 6. Considere el problema general, realice un programa para determinar eln´mero de combinaciones de monedas de 1c, 5c, 10c, 25c, y 50c que se pueden uutilizar para dar esa cantidad de cambio.Entrada.- La entrada consiste de una serie de n´meros entre 1 y 30.000 in- uclusive, una por l´ ınea de entrada.Salida.- La salida consiste en una frase que indica el n´mero de formas que uexisten de dar cambio.There are $m$ ways to produce n cents change.There is only 1 way to produce n cents change.Ejemplo de entrada.-17114Ejemplo de salida.-There are 6 ways to produce 17 cents change.There are 4 ways to produce 11 cents change.There is only 1 way to produce 4 cents change.
  • 162. 150 ´ 6. COMBINATORIA BASICA6.5.2. Problema 369 - Combinaciones Calcular el n´mero de formas que N objetos tomados de M, en un tiempo udado pueden ser un gran desaf´ cuando N y/o M llegan a ser muy grandes. ıoPor consiguiente hay que hacer un programa que calcule los siguientes: datos:5 ≤ n ≤ 100 y 5 ≤ m ≤ 100 y m ≤ n Calcule el valor exacto de: n! c= (n − m)!m! Se puede asumir que el valor final de C no sobrepasa un entero de 32 bits. Como antecendente, el valor exacto de 100! es:93,326,215,443,944,152,681,699,238,856,266,700,490,715,968,264,381,621,468,592,963,895,217,599,993,229,915,608,941,463,976,156,518,286,253,697,920,827,223,758,251,185,210,916,864,000,000,000,000,000,000,000,000Entrada y salida La entrada de este programa puede ser una o m´s l´a ıneasque contienen 0 ´ m´s espacios, un valor para N, uno ´ m´s espacios y un o a o avalor para M . La ultima l´ ´ ınea de la entrada dos ceros. El programa debeterminar cuando lee esta l´ ınea. La salida para el programa debe estar en la forma:N things taken M at a time is C exactly.Ejemplo de entrada 100 6 20 5 18 6 0 0 Ejemplo de salida100 things taken 6 at a time is 1192052400 exactly.20 things taken 5 at a time is 15504 exactly.18 things taken 6 at a time is 18564 exactly.
  • 163. 6.5. EJERCICIOS 1516.5.3. Problema 10338 - Mal educados Se coloc´ un letrero en un panel consistente en casillas individuales para ocada letra. Durante el evento algunos estudiantes decidieron cambiar el ordende las letras. De cu´ntas formas unicas y sin repetici´n se pueden organizar a ´ olas letras? Entrada y salida En la primera l´ ınea viene un entero que indica el n´mero ude conjuntos de datos de prueba. Este valor es inferior a 30.001. Cada entrada consiste de letras escritas todas en may´sculas. Para ca- uda palabra, escriba el n´mero de formas diferentes, en las que se pueden ureorganizar las letras contando el arreglo original. Cada palabra tiene un m´ximo de 20 letras y no incluye caracteres de apuntuaci´n. o El n´mero de arreglos siempre podr´ almacenarse en un entero de tipo u along. Tome en cuenta que el n´mero m´s grande que se puede almacenar en u auna variable entera es 12!. Ejemplo de entrada3HAPPYWEDDINGADAMEjemplo de salidaData set 1: 60Data set 2: 2520Data set 3: 12
  • 164. 152 ´ 6. COMBINATORIA BASICA6.5.4. Problema 10183 - Secuencia de Fibonacci Utilizando la secuencia de Fibonaci se quiere calcular cu´ntos n´meros a ucaben en un determinado rango. Entrada y salida La entrada consiste en varios casos de prueba. Cada casode prueba consiste en dos n´meros a,b con a, b ≤ 10100 . El proceso termina ucuando a,b estan en 0. Ejemplo de entrada10 1001234567890 98765432100 0Ejemplo de salida54
  • 165. Cap´ ıtulo 7 Estructuras de datos elementales7.1. Introducci´n o En el presente cap´ ıtulo se hace una introducci´n a las estructuras de datos ob´sicas. La intenci´n de ´ste cap´ a o e ıtulo es orientar en el uso de estructuras quevienen implementadas en el lenguaje de programaci´n Java. No se trata de ointroducir los conceptos que corresponden a los cursos de estructura de datos,sino m´s bien, de reutilizar las herramientas provistas. a7.2. Pilas Una de las estructuras m´s simples es la pila. La estructura de pila es una alista en la que solo se pueden ingresar y sacar valores por un solo lugar. Estaspilas se denominan tambi´n listas LIFO (last in first out). Esto significa que eel ultimo valor introducido es el primero en salir. ´ En esta estructura solo se pueden insertar objetos al final, extraer elultimo objeto o mirar el ultimo. En Java ´sto equivale a los m´todos push,´ ´ e epop y peek. Para mostrar como se realiza esta implementaci´n utilizaremos la clase oAlumno, que almacena nombre y c´digo.opublic class Alumno { String nombre; 153
  • 166. 154 7. ESTRUCTURAS DE DATOS ELEMENTALES int c´digo; opublic Alumno(String nombre, int c´digo) { o this.nombre=nombre; this.c´digo=c´digo; o o }public String verNombre() { return nombre; }public int verCodigo() { return c´digo; o }} El siguiente c´digo implementa la clase pila, ingresando objetos de tipo oAlumno y luego list´ndolos. El siguiente programa realiza lo indicado. aimport java.io.*;import java.util.*;/** * Ejemplo de manejo de pilas * @author Jorge Teran * @param args * none */public class pila { public static void main(String[] args) { // definir una pila de alumnos Stack<Alumno> pila = new Stack(); // almacenar los alumnos Alumno alm1 = new Alumno("Juan", 11); pila.push(alm1); alm1 = new Alumno("Maria", 17); pila.push(alm1); alm1 = new Alumno("Jose", 25); pila.push(alm1); // Recuperar el elemento de encima System.out.println(pila.peek().verNombre()); // Imprimir la pila
  • 167. 7.2. PILAS 155 while (!pila.isEmpty()) System.out.println(pila.pop().verNombre()); }} Para ejemplificar la utilizaci´n de pilas supongamos que queremos verifi- ocar si una secuencia de par´ntesis y corchetes est´ bien anidada. Considere- e amos algunos casos La secuencia (([])) es una secuencia bien anidada. La secuencia (([)]) es una secuencia mal anidada, un corchete no puede cerrarse con un par´ntesis. e La secuencia ((()) est´ mal, porque le falta un par´ntesis de cierrre. a e Para resolver este tipo de problemas una pila es un m´todo apropiado. La eestrategia de soluci´n es el almacenar en la pila todas las llaves de apertura y ocada vez que aparece una de cierre obtenemos un elemento de la pila y debeser una llave de apertura correspondiente a la de cierre. Cuando se quiere recuperar un elemento de la pila y est´ vac´ indica que a ıa,sobran llaves de cierre. Cuando se termina el proceso la pila debe estar vac´ıa,caso contrario, quiere decir que hay m´s llaves de apertura que de cierre en ala expresi´n a ser analizada. o Esto nos lleva al siguiente c´digo: oimport java.io.*;import java.util.*;/** * Ejemplo de manejo de pilas * Comprobaci´n de parentisis bien anidados o * @author Jorge Teran * @param args * parentesis y corchetes * EjemploPila ()()(((()[) */public class EjemploPila { public static void main(String[] args) { //String cadena="(([]))(";
  • 168. 156 7. ESTRUCTURAS DE DATOS ELEMENTALES String cadena=args[0]; String caracter,delapila; // definir una pila de cadena Stack<String> pila = new java.util.Stack(); for (int i=0; i< cadena.length();i++){ caracter=cadena.substring(i,i+1); if (caracter.compareTo("(")==0) pila.push(")"); else if (caracter.compareTo("[")==0) pila.push("]"); else { if (pila.isEmpty()){ System.out.println("Sobran llaves de cierre"); System.exit(0); } delapila=pila.pop(); if (delapila.compareTo(caracter)==1){ System.out.println("Mal anidada"); System.exit(0); } } } if (!pila.isEmpty()) System.out.println("Sobran llaves de apertura"); else System.out.println("Bien anidada"); }} Los m´todos disponibles para pilas son: e M´todo e Descripci´n o push(E elemento) Agrega un elemento a la pila. pop() Extrae el ultimo elemento introducido. ´ peek() Lee el ultimo elemento introducido. ´ isEmpty() Devuelve true si la pila est´ vac´ a ıa.
  • 169. 7.3. LISTAS ENLAZADAS 1577.3. Listas enlazadas Las listas enlazadas tienen la ventaja de que permiten ingresar elementosen cualquier lugar de la lista sin necesidad de tener que hacer un espacio comoen los vectores. En una lista enlazada existen varias posiciones en las que sepuede introducir un elemento, supongamos la lista que tiene los elementosabc existen cuatro lugares donde se pueden insertar los nuevos valores, estosson: abc, a bc, ab c y abc . El lenguaje Java provee una clase denominada iterador que permite re-correr la clase. Cuando insertamos elementos consecutivos se introducen enel orden que se env´ ıan. Cuando el iterador apunta al principio se introducenal principio, si est´ apuntando al final de la lista se introducen despu´s del a eultimo elemento. El interador, es el que indica donde se puede introducir el´elemento. Los m´todos de Java para listas enlazadas son los siguientes: e M´todo e Descripci´n o add(E elemento) Agrega un elemento a la lista. add(int i, E elemento) Agrega un elemento en la posici´n i. o addFirst(E elemento) Agrega un elemento al principio. addLast(E elemento) Agrega un elemento al final. clear() Borra la lista. addAll(int i,coleccion) Agrega toda una colecci´n en la o posici´n i. o remove(int i) Quita y devuelve el elemento de la posici´n i. o removeFirst() Quita y devuelve el primer elemento. removeLast() Quita y devuelve el ultimo elemento. ´ set(int i, E elemento) Cambia el elemento de la posici´n i. o isEmpty() Devuelve true si la lista esta vac´ ıa. contains(E elemento) Devuelve true si la lista contiene el elemento. size() Devuelve el n´mero de elementos. u Hay que hacer notar que las listas no son una estructura de datos ade-cuadas para el acceso aleatoreo. Cada vez que se busca un elemento o recorrela lista siempre comienza desde el principio.
  • 170. 158 7. ESTRUCTURAS DE DATOS ELEMENTALES La colecci´n para listas enlazadas provee una clase para recorrer la lista ollamada iterador que tiene los siguientes m´todos: e M´todo e Descripci´n o ListIterator(E) Crea un iterador para visitar elementos de la lista. set(E elemento) Cambia el ultimo elemento visitado. ´ hasPrevious() Devuelve true si tiene un elemento anterior. previous() Devuelve el elemento anterior. nextIndex() Devuelve el ´ındice que ser´ llamado en la ıa pr´xima iteraci´n. o o En el siguiente ejemplo se crean dos listas y se introducen elementos de laclase Alumno. Luego se utiliza el iterador para recorrer la lista. Finalmentese muestra el m´todo removeAll que permite remover todos los elementos ede una lista que est´n en la otra. apublic class ListaEnlazada {/** * Ejemplo de lista enlazada * @author Jorge Teran * @param args * none */ public static void main(String[] args) { Alumno alm; LinkedList<Alumno> uno = new LinkedList<Alumno>(); uno.add(new Alumno("Juan", 11)); uno.add(new Alumno("Maria", 17)); ListIterator<Alumno> aIter = uno.listIterator(); // desplegar la lista uno System.out.println("Listar la lista UNO"); while (aIter.hasNext()) { alm = aIter.next(); System.out.println(alm.verNombre()); }
  • 171. 7.3. LISTAS ENLAZADAS 159 List<Alumno> dos = new LinkedList<Alumno>(); dos.add(new Alumno("Jose", 25)); dos.add(new Alumno("Laura", 8)); ListIterator<Alumno> bIter = dos.listIterator(); // agregar los alumnos de lista dos // a la lista uno while (bIter.hasNext()) { uno.add(bIter.next()); } System.out.println( "Despues de agregar la lista DOS"); // Reiniciar el iterador y listar la lista uno aIter = uno.listIterator(); while (aIter.hasNext()) { alm = aIter.next(); System.out.println(alm.verNombre()); } // quitar los elementos de la lista dos de uno en uno uno.removeAll(dos); System.out.println( "Listar despues de quitar la lista DOS"); // Reiniciar el iterador y listar la lista uno aIter = uno.listIterator(); while (aIter.hasNext()) { System.out.println(aIter.next().verNombre()); } }}Para realizar listas doblemente enlazadas es suficiente crear una lista con unaclase de tipo lista. De esta forma se pueden crear listas con cualquier nivelde anidamiento.
  • 172. 160 7. ESTRUCTURAS DE DATOS ELEMENTALES7.4. Conjuntos El manejo de conjuntos es similar, al de las listas con la condici´n que, ono se permiten elementos repetidos y el orden no es relevante. La implementaci´n de un conjunto se hace como una estructura de ti- opo Set y esta estructura viene implementada en HashSet. Para definir unconjuto conjA hay que escribir lo siguiente:Set<String> conjA = new HashSet<String>();Los m´todos disponibles para la clase set son los siguientes: e M´todo e Descripci´n o add(E elemento) Agrega un elemento al conjunto. clear() Borra el conjunto. addAll(coleccion) Agrega toda una colecci´n. o removeAll(coleccion) Elimina todos los elementos de la colecci´n que existan en el conjunto. o remove(Object objeto) Elimina el objeto del conjunto. Devuelve true si ha sido eliminado. isEmpty() Devuelve true si el conjunto esta vac´ıo. contains(E elemento) Devuelve true si el conjunto contiene el elemento. size() Devuelve el n´mero de elementos del u conjunto. Los m´todos para recorrer los conjuntos se realizan con la clase Iterator eque tiene los siguientes m´todos: e M´todo e Descripci´n o Iterator(E) Crea un iterador para visitar elementos del conjunto. hasNext() Si existe un pr´ximo elemento devuelve true. o next() Avanza al pr´ximo elemento. oPara utilizar la clase Iterator se procede como sigue: Primero creamos el iterador sobre el conjunto
  • 173. 7.4. CONJUNTOS 161 Iterator<String> iter = conjA.iterator(); Para recorrer el conjunto while (iter.hasNext()) Finalmente para acceder a elementos individuales podemos utilizar iter.next(). Por ejemplo para desplegar el elemento: System.out.println(iter.next()); En el siguiente ejemplo se muestra como introducir elementos, recorrer elconjunto y como hallar la intersecci´n de dos conjuntos. oimport java.util.*;/** * Ejemplo manejo de conjuntos * @author Jorge Teran * @param args * none */public class Conjuntos { public static void main(String[] args) { Set<String> conjA = new HashSet<String>(); conjA.add("aaa"); conjA.add("bbb"); conjA.add("aaa"); conjA.add("ccc"); conjA.add("ddd"); Set<String> conjB = new HashSet<String>(); conjB.add("aaa"); conjB.add("bbb"); conjB.add("bbb"); conjB.add("xxx");
  • 174. 162 7. ESTRUCTURAS DE DATOS ELEMENTALES conjB.add("yyy"); //hallar conjB interseccion conjA Set<String> conjC = new HashSet<String>(); conjC.addAll(conjA); // para intersectar A y B // hacemos C=A-B y luego A-C conjC.removeAll(conjB); conjA.removeAll(conjC); //listar Iterator<String> iter = conjA.iterator(); while (iter.hasNext()) System.out.println(iter.next()); }}7.5. Clases map Las clases donde se almacenan los valores como clave y valor se denominaclase Map por ejemplo, si se quiere almacenar color=rojo donde color es laclave y rojo es el valor se puede almacenar y recuperar por la clave. Los m´todos de la clase Map est´n descriptos en el cuadro 7.1. e a El recorrido de la clase Map se puede realizar por clave, valor o por ambos.Para definir un recorrido de una clase Map por clave se procede como sigue:Iterator<String> iter = preferencias.keySet().iterator();Para definir un recorrido por valor:Iterator<String> iter = preferencias.values().iterator();Para recorrer por ambos hay que tomar en cuenta que Iterator no permi-te definir dos cadenas como es la definici´n de Map. Por esto es necesario ocambiar el recorrido como sigue:Map.Entry<String, String> datos : preferencias.entrySet()Luego podemos acceder a la clave con datos.getKey() y a los valores atrav´s de datos.getValue(). e En el siguiente ejemplo, se introducen pares de elementos y luego se re-corre el conjunto Map listando clave y valor.
  • 175. 7.5. CLASES MAP 163 M´todo e Descripci´no put(Clave, Valor) Agrega un elemento Map. get(Clave) Devuelve el elemento Map con la clave especificada. clear() Borra el conjunto Map. remove(Object objeto) Elimina el objeto del conjunto con la clave especificada. Devuelve true si es eliminado. isEmpty() Devuelve true si el conjunto Map esta vac´ıo. containsValue(Object elemento) Devuelve true si el conjunto contiene el valor. containsKey(Object elemento) Devuelve true si el conjunto contiene la clave. size() Devuelve el n´mero de elementos u del conjunto Map. Cuadro 7.1: M´todos de la clase map eimport java.util.*;/** * Ejemplo de la estructura map * @author Jorge Teran * @param args * none */public class PruebaMap { public static void main(String[] args) { Map<String, String> preferencias = new HashMap<String, String>(); preferencias.put("color", "rojo"); preferencias.put("ancho", "640"); preferencias.put("alto", "480"); //listar todo System.out.println(preferencias); // Quitar color
  • 176. 164 7. ESTRUCTURAS DE DATOS ELEMENTALES preferencias.remove("color"); // cambiar una entrada preferencias.put("ancho", " 1024"); // recuperar un valor System.out.println("Alto= " + preferencias.get("alto")); // iterar por todos los elementos for (Map.Entry<String, String> datos : preferencias.entrySet()) { String clave = datos.getKey(); String valor = datos.getValue(); System.out.println( "clave=" + clave + ", valor=" + valor); } }}7.6. Clases para ´rboles a En el Java tenemos la clase de ´rboles que permite mantener ordenados alos elementos de un conjunto a medida que, se introducen los elementos.Para poder implementar ´sto es necesario tener una clase de comparaci´n e oque permita decidir en que rama del ´rbol corresponde insertar un elemento, apara esto agregamos a la clase Alumno el siguiente m´todo. epublic int compareTo(Alumno other) { return c´digo - other.c´digo; o o }que superpone el m´todo de comparaci´n que solo se utiliza con los tipos e ode datos b´sicos; vea que, lo que se est´ comparando es el c´digo y la res- a a o
  • 177. ´7.6. CLASES PARA ARBOLES 165puesta puede ser 0,1 o -1. En la definici´n de la clase es necesario agregar oimplements Comparable<Alumno> quedando como sigue:public class Alumno implements Comparable<Alumno> {Luego el siguiente c´digo ingresa Alumnos a un ´rbol organizado por c´digo o a oimport java.util.*;/** * Ejemplo de la estructura de Arboles * @author Jorge Teran * @param args * none */public class Arbol { public static void main(String[] args) { TreeSet<Alumno> alm = new TreeSet<Alumno>(); alm.add(new Alumno("Juan", 11)); alm.add(new Alumno("Maria", 17)); alm.add(new Alumno("Jose", 25)); alm.add(new Alumno("Laura", 8)); System.out.println(alm);}No siempre es el unico orden que deseamos tener, por ejemplo si se desea ´ordenar por nombre, no es posible especificar dos clases de comparaci´n. Por oeste motivo podemos crear otro ´rbol especificando su clase de comparaci´n. a oTreeSet<Alumno> ordenarPorNombre = new TreeSet<Alumno>( new Comparator<Alumno>() { public int compare(Alumno a, Alumno b) { String nombreA = a.verNombre(); String nombreB = b.verNombre(); return nombreA.compareTo(nombreB); } }); ordenarPorNombre.addAll(alm); System.out.println(ordenarPorNombre); }}
  • 178. 166 7. ESTRUCTURAS DE DATOS ELEMENTALESLa instrucci´n ordenarPorNombre.addAll(alm) permite insertar todo el oa´rbol alm en el ´rbol ordenarPorNombre. Los m´todos de la clase TreeSet a eson los siguientes: M´todo e Descripci´n o add(E elemento) Agrega un elemento al ´rbol. a clear() Borra el ´rbol. a addAll(coleccion) Agrega toda una colecci´n. o remove(Object objeto) Elimina el objeto del ´rbol. a Devuelve true si ha sido eliminado isEmpty() Devuelve true si el ´rbol est´ vac´ a a ıo. contains(E elemento) Devuelve true si el conjunto contiene el elemento. size() Devuelve el n´mero de elementos del ´rbol. u a Los m´todos para recorrer el ´rbol elemento por elemento se realiza con e ala clase Iterator especificando que el iterador es alumno y se procede comosigue:Iterator<Alumno> iter = alm.iterator(); while (iter.hasNext()) System.out.println(iter.next());7.7. Clases para colas de prioridad Las colas de prioridad tienen la caracter´ ıstica de estar basadas en la es-tructura de datos denominada mont´ ıculo. La caracter´ıstica principal es quecada elemento introducido est´ asociado a una prioridad. A medidad que ase van introduciendo valores se van organizando para que al recuperar uno,siempre se recupere primero, el que tiene menos prioridad. La aplicaci´n t´ o ıpica de ´sta cola es por ejemplo el organizar una lista ede impresi´n por prioridad a medida que se introducen y procesan trabajos, osiempre se procesa primero el de menor prioridad. Para ejemplificar el uso en Java presentamos el siguiente ejemplo quemuestra como se introducen y obtienen uno a uno lo elementos comenzandodel valor m´ınimo.
  • 179. 7.7. CLASES PARA COLAS DE PRIORIDAD 167import java.util.*;/** * Ejemplo de Cola de prioridad * @author Jorge Teran * @param args * none */public class ColaPrioridad {public static void main(String[] args) {PriorityQueue<Alumno> cp = new PriorityQueue<Alumno>();cp.add(new Alumno("Juan", 11));cp.add(new Alumno("Maria", 17));cp.add(new Alumno("Jose", 25));cp.add(new Alumno("Laura", 8));System.out.println("Sacando elementos...");Alumno datos;while (!cp.isEmpty()) {datos = cp.remove();System.out.println( datos.verCodigo() + " = " + datos.verNombre());}}}Analizando el c´digo vemos que los datos ingresados ser´n extra´ o a ıdos seg´n ula prioridad. En este ejemplo, hemos tomado como prioridad el c´digo, dado oque a la clase Alumno se ha adicionado el m´todo comparTo del ejemplo eanterior que utiliza el campo c´digo en la comparaci´n. Por esto, la salida o odel programa est´ en el orden 8, 11, 18, 25. a Los m´todos disponibles para las colas de prioridad est´n descriptos en e ael cuadro 7.2.
  • 180. 168 7. ESTRUCTURAS DE DATOS ELEMENTALES M´todo e Descripci´n o add(E elemento) Agrega un elemento a la cola de prioridad. clear() Borra la cola de prioridad. addAll(coleccion) Agrega toda una colecci´n. o remove() Elimina el elemento m´s peque˜o. a n isEmpty() Devuelve true si est´ vac´ a ıa. contains(E elemento) Devuelve true si el conjunto contiene el elemento. size() Devuelve el n´mero de elementos. u Cuadro 7.2: M´todos de las colas de prioridad e7.8. Ejercicios para laboratorio Los siguientes ejercicios de laboratorio tienen el objetivo de determinar enla pr´ctica las estructuras m´s eficientes para resolver diferentes problemas. a aPara esto se deben tomar los tiempos de ejecuci´n de cada estructura de odatos, construir la siguiente tabla y analizar los resultados. Estructura Tiempo de ejecuci´n o Pila Lista enlazada Arbol Cola de prioridad Conjuntos Map 1. Hallar el tiempo de insertar 10.000 datos a una pila, lista enlazada, a ´rbol, cola de prioridad. Explicar la ventaja de cada una de ellas. 2. Insertar 10.000 n´meros aleatorios a cada una de las estructuras es- u tructuras presentadas en el cap´ıtulo y encontrar cual es m´s eficiente a para hallar los 100 m´s peque˜os. a n 3. En una combinaci´n de operaciones: 10 % recorrer ordenado, 30 % bus- o car, 40 % insertar y 20 % remover un valor arbirario. Realice un ejercicio con 10.000 valores y analice tres estructuras de datos. Escoja las m´s a adecuada.
  • 181. 7.8. EJERCICIOS PARA LABORATORIO 169 4. Repetir el ejercicio tres para 10.100, 1.000, 10.000 y 100.000 valores. Indicar en qu´ casos es m´s conveniente cada estructura. e a
  • 182. 170 7. ESTRUCTURAS DE DATOS ELEMENTALES
  • 183. Cap´ ıtulo 8 Backtracking8.1. Introducci´n o Backtracking significa ir atr´s. Esto implica llevar un registro de los even- atos pasados, con el prop´sito, de realizar un proceso m´s inteligente. Aunque o aeste m´todo aparenta una b´squeda exhaustiva, no examina todas las com- e ubinaciones posibles. Este tema es introducido mostrando el recorrido de un grafo que muestrael concepto de volver a un estado anterior. Posteriormente se trabaja construyendo subconjuntos y permutaciones.Para este tipo de problemas se desarrolla una implementaci´n b´sica que o aconsiste de tres partes: una que determina si hemos hallado una soluci´n, la osegunda que procesa la soluci´n y la tercera que realiza el proceso. o8.2. Recorrido de grafos Un ejemplo t´ıpico de algoritmo de retroceso es el hallar un camino desdeun origen hasta un destino en grafo. Consideremos el grafo de la figura 8.1: Si partimos del nodo A y queremos llegar al nodo G tenemos dos estra-teg´ para hallar un camino. Una de ellas es hacer todas las combinaciones ıasposibles partiendo del origen. La segunda es empezar a recorrer el grafo re-trocediendo un lugar cada vez que se llegue a un nodo del que no podamosavanzar m´s.a El proceso comienza en nodo A, y se va al primer nodo que encontramosel nodo B. Ver figura 8.2. 171
  • 184. 172 8. BACKTRACKING Figura 8.1: Ejemplo de un grafo Figura 8.2: Muestra el recorrido del nodo A a B Del nodo B se procede hasta el nodo E que es el primer nodo que encon-tramos. No hay forma en ´ste momento de elegir el nodo F porque no sabemos esi nos lleva al destino. De esta forma llegamos al nodo C y posteriormente aD. Ver figura 8.3. Cuando llegamos al nodo D ya no se puede seguir (figura 8.4), por lo que,es necesario regresar al nodo anterior C y vemos que no hay ning´n otro unodo para visitar, retrocedemos una vez m´s llegando a E y continuamos. a Cuando llegamos al punto final imprimimos el recorrido. Cuando el al-goritmo llega al inicio y no hay nodos que no hayamos visitado termina sinencontrar un camino. Para programar hemos construido una matriz para representar el grafo.En esta matriz la filas y columnas representan los nodos y la posici´n (i,j) oindica que existe un camino cuando tiene un 1 y un 0 cuando no existe uncamino. Para el grafo de ejemplo la matriz que constuimos es:
  • 185. 8.2. RECORRIDO DE GRAFOS 173 Figura 8.3: Muestra el recorrido hasta el nodo C Figura 8.4: Muestra el proceso de retorceso A B C D E F G A 0 1 0 0 1 0 0 B 0 0 0 0 1 1 0 C 0 0 0 1 0 0 0 D 0 0 0 0 0 0 0 E 0 0 1 0 0 1 0 F 0 0 0 1 0 0 1 G 0 0 0 0 0 0 0 Para el proceso se comienza con la posici´n 0. Cada vez que pasamos por oun nodo lo marcamos como visitado. Esto es para evitar ciclos y volver arealizar un recorrido anterior. Cuando se llega a un nodo que no va a ning´n ulado regresamos (bactrack) al nodo anterior para buscar una nueva ruta. Elnodo anterior se ha guardado en una estructura de pila. El programa recorre el grafo mostrado y produce la ruta en orden inversolistando: 6 5 4 1 0.
  • 186. 174 8. BACKTRACKING/**Programa para mostrar el * recorrido de un grafo * @author Jorge Teran */import java.util.Stack;import java.util.Vector;public class Grafo2 { static void Camino(int[][] g) { int i = 0; Stack<Integer> pila = new Stack(); // visitados int[] v = new int[g[0].length]; i = 0; while (v[v.length - 1] == 0) { pila.push(i); v[i] = 1; i = Buscar(g, v, i); if ((i == -1) && (v[v.length - 1] == 0)) { if (pila.empty()) { System.out.println("No Hay Ruta "); System.exit(0); } else { //bactracking al anterior i = (int) pila.pop(); i = (int) pila.pop(); } } } System.out.println("Ruta en Orden Inverso "); while (!pila.empty()) { i = (int) pila.pop(); System.out.print(" " + i); } } static int Buscar(int[][] g, int[] v, int fila) { int hallo = -1, i;
  • 187. 8.3. CONSTUIR TODOS LOS SUBCONJUNTOS 175 for (i = 0; i < g[0].length; i++) { // System.out.println("busca ="+g[fila][i]); if ((g[fila][i] == 1) && (v[i] == 0)) { hallo = i; break; } } // System.out.println("Hallo ="+hallo); return hallo; } public static void main(String[] args) { int[][] g = new int[7][7]; // Nodos A=0,B=1,C=2,D=3,E=4,F=5,G=6 g[0][1] = 1; g[0][4] = 1; g[1][4] = 1; g[1][5] = 1; g[2][3] = 1; g[3][0] = 0; g[4][2] = 1; g[4][5] = 1; g[5][3] = 1; g[5][6] = 1; g[6][0] = 0; Camino(g); }}8.3. Constuir todos los subconjuntos Consideremos el problema de construir todos los subconjuntos de un con-junto de tama˜o n. El n´mero total de subconjuntos es 2n − 1 sin contar el n uconjunto vac´ Por ejemplo si n = 3 existen 7 subconjuntos. ıo. Consideremos el conjunto {1,2,3} los 7 posibles subconjuntos son: {1 2 3}, {1 2 }, {1 3 }, {1 }, {2 3 }, {2 } y {3 }. Para construir un programa que construya ´stos subconjuntos inicialmen- e
  • 188. 176 8. BACKTRACKINGte se construye un vector de unos y ceros para representar las posibles solu-ciones. Al inicio de cada recursi´n preguntamos si hemos hallado una soluci´n o opara procesar. Si no se hall´ una soluci´n guardamos el vector de soluciones o oy probamos una nueva soluci´n. En este problema hemos considerado una osoluci´n cuando llegamos al ultimo elemento del conjunto. o ´ Luego regresamos a un estado anterior y comenzamos la b´squeda de una unueva soluci´n. La instrucci´n subset[cur] = true; se usa para indicar que o oeste elemento puede ser parte de la soluci´n. Luego se procesa recursivamente ouna nueva soluci´n. o Cuando hallamos una soluci´n se retorna al estado anterior y marcamos oel ultimo elemento como procesado. EL c´digo que halla esta soluci´n es el ´ o osiguiente:/**Programa para hallar todos los * subconjuntos * @author Jorge Teran */public class Subconjuntos { private static void procesarSolucion( boolean[] conjuntos) { // imprimir la solucion, // conjuntos indica cuales imprimir System.out.print("{"); for (int i = 0; i < conjuntos.length; i++) if (conjuntos[i]) System.out.print((i + 1) + " "); System.out.println("}"); } public static boolean esSolucion( boolean[] conjuntos, int posicionActual) { // cuando se llego al final del vector // no se puede seguir iterando return (conjuntos.length == posicionActual); }
  • 189. 8.3. CONSTUIR TODOS LOS SUBCONJUNTOS 177 public static void imprimeSubconjuntos( boolean[] conjuntos,int posicionActual) { if (esSolucion(conjuntos, posicionActual)) { procesarSolucion(conjuntos); } else { conjuntos[posicionActual] = true; // procesar una nueva solucion imprimeSubconjuntos(conjuntos, posicionActual + 1); // retornar (bactrack) al caso anterior conjuntos[posicionActual] = false; imprimeSubconjuntos(conjuntos, posicionActual + 1); } } public static void main(String[] args) { boolean[] conjuntos = new boolean[3]; // Inicialmente conjuntos esta todo en false imprimeSubconjuntos(conjuntos, 0); }}Al analizar el proceso se observa que se procede a marcar las posibles solu-ciones cambiando el arreglo que hemos denominado conjuntos cambiando elestado de 000 a 100, 110 y 111. Cuando se llega a marcar tres elementos seimprime la primera soluci´n {1, 2, 3 }. o En ´ste momento la pila de la recurci´n contiene los valore 000, 100, 110 e oy 111. En el proceso recursivo la pila es la que guarda los resultados previos. Ahora se produce un retroceso, el arreglo que almacena los estados con-tiene 111 que se recupera de la pila. Luego se cambia el estado del ultimo bit ´a 0 para indicar que ya fue procesado y volvemos a llamar recursivamenteal programa almacenando en la pila el 110, que produce la soluci´n {1, 2 o}. Al terminar sale este valor de la pila y regresa al valor almacenado 100.Se procede a marcar el 101 el bit 2 y se contin´a el proceso. El proceso del uprograma se muestra en el cuadro 8.1.
  • 190. 178 8. BACKTRACKING Bits de Estado Posici´n Actual o Retroceso Soluci´n o 100 0 110 1 111 2 {1, 2, 3 } 111 2 Fin Recursi´n 1 o 110 2 {1, 2 } 110 Fin Recursi´n 2 o 100 1 Fin Recursi´n 1 o 101 2 {1, 3 } 100 2 Fin Recursi´n 1 o 100 2 {1 } b 100 2 Fin Recursi´n 2 o 100 1 Fin Recursi´n 2 o 000 0 Fin Recursi´n 1 o 010 1 011 2 {2,3} 010 2 Fin Recursi´n 1 o 010 2 {2} 010 2 Fin Recursi´n 2 o 000 1 Fin Recursi´n 1 o 001 2 {3} Fin Recursi´n 2 o Cuadro 8.1: Proceso realizado para construir todos los subconjuntos
  • 191. 8.4. CONSTRUIR TODAS LAS PERMUTACIONES 1798.4. Construir todas las permutaciones Para construir todas las permutaciones de un conjunto tambi´n se utiliza ela t´cnica de backtrackig. En este ejemplo se ha constru´ un programa e ıdosimilar al anterior con una clase que procesa la soluci´n y otra que determina osi ha llegado la soluci´n. o El programa intercambia valores empezando del primer valor en formarecursiva al igual que el programa de hallar todos los subconjuntos. Comienzaintercambiando el primer elemento con el ultimo, en un ciclo. Recursivamente ´retornando al estado anterior cuando se halla una permutaci´n. o/**Programa para hallar todas * las permutaciones * @author Jorge Teran*/public class Permutaciones {// imprimir las n! permutaciones en desorden private static void procesarSolucion(String[] a) { for (int i = 0; i < 3; i++) { System.out.print(a[i]); } System.out.println(" "); } public static boolean esSolucion(int posicionActual) { // cuando se llego al final del vector // no se puede seguir iterando return (posicionActual == 1); } private static void permutar( String[] a, int n) { if (esSolucion(n)) { procesarSolucion(a); return; } for (int i = 0; i < n; i++) { swap(a, i, n-1);
  • 192. 180 8. BACKTRACKING permutar(a, n-1); swap(a, i, n-1); } } private static void swap(String[] a, int i, int j) { String c; c = a[i]; a[i] = a[j]; a[j] = c; } public static void main(String[] args) { String[] a = new String[3]; a[0]="a"; a[1]="b"; a[2]="c"; permutar(a,3); }}El resultado que se obtiene del programa es: bca, cba, cab, acb, bac, abc. Como se ve en el ejemplo anterior los resultados no est´n en orden. En aorden significa que los resultados deben estar en la siguiente secuencia: abc,acb, bac, bca, cab, cba. Esto significa realizar todos los intercambios man-teniendo el primer elemento, luego llevar el segundo elemento al principio yas´ sucesivamente. ı Para realizar ´sto hemos utilizado una estructura de vector que, permite einsertar y extraer objetos. Se crearon dos vectores, uno para almacenar lascombinaciones que se van formando y otro que mantiene el vector original.El siguiente c´digo permite realizar estas permutaciones. o/**Programa para hallar todas * las permutaciones en orden * @author Jorge Teran*/import java.util.Vector;public class PermutacionesEnOrden { private static void procesarSolucion(Vector a) { System.out.println(a); }
  • 193. 8.4. CONSTRUIR TODAS LAS PERMUTACIONES 181 public static boolean esSolucion(int posicionActual) { // cuando se llego al final del vector // no se puede seguir iterando return (posicionActual == 0); } private static void permutar( Vector auxiliar, Vector original) { int N = original.size(); if (esSolucion(N)) { procesarSolucion(auxiliar); } else { for (int i = 0; i < N; i++) { String proximo = (String) original.remove(i); auxiliar.add(proximo); permutar(auxiliar, original); original.add(i, proximo); auxiliar.remove(proximo); } } public static void main(String[] args) { Vector v = new Vector(); String[] a = new String[3]; a[0] = "a"; a[1] = "b"; a[2] = "c"; for (int i = 0; i < a.length; i++) { String s = a[i]; v.add(s); } permutar(new Vector(), v); }}
  • 194. 182 8. BACKTRACKING8.5. Ejercicios8.5.1. Prolema 195 - Anagramas Se pide que escriba un programa que genere todas las posibles palabrasde un conjunto de letras, por ejemplo: dada la palabra abc su programa debeexplorar las diferentes combinaciones de tres letras y escribir estas palabrasabc, acb, bac, bca, cab and cba. En las palabras le´ıdas de la entrada, algunas pueden aparecer repetidas.Para una palabra de entrada su programa no debe producir palabras repeti-das, y las palabras deben escribirse en orden alfab´tico. e Entrada El archivo de entrada consiste de varias palabras. La prime-ra l´ ınea contiene un n´mero que indica el n´mero de palabras del archivo. u uCada l´ ınea siguiente contiene una palabra. Una palabra consiste de letrasmin´sculas y may´sculas de la A a la Z. Las letras may´sculas y min´sculas u u u use consideran diferentes. Salida Para cada palabra del archivo de entrada el archivo debe conte-ner todas las palabras diferentes que pueden ser generadas con las letras deuna palabra. Las palabras generadas de una palabra de entrada deben im-primirse en orden alfab´tico. Las letras may´sculas van adelante de las letras e umin´sculas. u Ejemplo de entrada2aAbacba Ejemplo de salida Aab aabc Aba aacb aAb abac abA abca bAa acab baA acba baac baca bcaa caab caba cbaa
  • 195. 8.5. EJERCICIOS 1838.5.2. Prolema 574 - Sum It Up Dado un total n y una lista n de enteros, hallar todas las distintas sumasque suman t. Por ejemplo si t = 4, n = 6 y la lista es [4, 3, 2, 2, 1, 1], existen 4sumas diferentes que suman 4. Estas son: 4, 3+1, 2+2, y 2+1+1. Un n´mero upuede utilizarse tantas veces como ocurre en la lista. Un solo n´mero puede uutilizarse como una suma. Entrada EL archivo de entrada contiene uno o m´s casos de prueba. Uno apor l´ınea. Cada caso de prueba contiene el total t, seguido de n que es eln´mero de enteros de la lista, seguidos de n enteros. Si n = 0 se termina el uarchivo de entrada. En otros casos t es un entero positivo t ≤ 1000. El tama˜o nde la lista es de 1 a 12, 1 ≤ n ≤ 12. Los enteros positivos son menores a 100.Los n´meros est´n separados por un espacio. Los n´meros de la lista est´n u a u aen orden descendente y existen n´meros repetidos u Salida Para cada caso de prueba primero escriba la l´ ınea Sums of el totaly dos puntos. Luego escriba cada suma, una por l´ ınea. Si no hay sumasescriba la l´ınea NONE. Los n´meros en cada suma deben aparecer en orden udescendente. Las sumas deben ordenarse en orden descendente. En otraspalabras las sumas con el mismo primer n´mero deben ordenarse por el usegundo. Si los dos primeros n´meros igualan debe ordenarse por el tercero y uas´ sucesivamente. Todas las sumas deben ser diferentes y no pueden aparecer ım´s de dos veces. a Ejemplo de entrada4 6 4 3 2 2 1 15 3 2 1 1400 12 50 50 50 50 50 50 25 25 25 25 25 250 0 Ejemplo de salidaSums of 4:43+12+22+1+1Sums of 5:NONESums of 400:
  • 196. 184 8. BACKTRACKING50+50+50+50+50+50+25+25+25+2550+50+50+50+50+25+25+25+25+25+25
  • 197. 8.5. EJERCICIOS 1858.5.3. Problema 524 - Anillos de primos Un anillo est´ compuesto de n c´ a ırculos como se muestra en el diagrama.Se pide colocar un n´mero natural en cada uno de los c´ u ırculos, la condici´n es oque la suma de los n´meros de dos c´ u ırculos adyacentes deben ser un n´mero uprimo. Se pide que el n´mero del primer c´ u ırculo debe ser siempre 1. Entrada n, (0 < n <= 16) Salida En la salida cada l´ ınea representa una serie de n´meros del c´ u ırculo.Comenzando con el n´mero 1 los n´meros deben satisfacer la condici´n tanto u u oen el sentido del reloj y como en el sentido contrario. Ejemplo de Entrada68 Ejemplo de salidaCase 1:1 4 3 2 5 61 6 5 2 3 4Case 2:1 2 3 8 5 6 7 41 2 5 8 3 4 7 61 4 7 6 5 8 3 21 6 7 4 3 8 5 2
  • 198. 186 8. BACKTRACKING8.5.4. Problema 216 - Hacer la l´ ınea Una red de computadoras requiere que las computadoras de una red est´n einterconectadas. El problema considera una red lineal de tipo bus, en la que las computado-ras est´n conectadas exactamente a otras dos, excepto a las computadoras ade los extremos. La imagen muestra las computadoras como puntos negros y sus ubicacio-nes en la red est´n identificadas como coordenadas en el plano. a Las distancias entre las computadores est´n puestas en pies. Por varias arazones, es necesario minimizar la distancia del cable. Debe construir un programa que determine como debe establecerse di-cha cadena a fin de minimizar el total del cable requerido. En la instalaci´n oque se est´ construyendo, el cable se instalar´ por el piso. La distancia total a aser´ igual a la distancia entre las computadoras adyacentes m´s 16 pies adi- a acionales para conectar del piso a las computadoreas y facilitar la instalaci´n. o La figura muestra la forma ´ptima de conectar las computadoras y la odistancia total de cable requerida para ´sta configuraci´n es (4 + 16) + (5 + e o16) + (5,83 + 16) + (11,18 + 16) = 90,01 pies. Entrada El archivo de entrada consiste de una serie de conjuntos de datos.Cada conjunto comienza con el n´mero que indica el n´mero de computado- u u
  • 199. 8.5. EJERCICIOS 187ras en la red. Cada red tiene al menos 2 computadoras y un m´ximo de 8. aUn n´mero cero en el n´mero de computadoras indica el final de la entrada. u u Despu´s de especificar el n´mero de computadoras en la red, cada l´ e u ıneaadicional le dar´ las coordenadas de cada computadora. Estas coordenadas ason enteros en el rango de 0 a 150. No existen dos computadoras en el mismolugar, y cada una est´ listada una sola vez. a Salida La salida para cada red debe tener una l´ ınea que incluya el n´mero de la ured, determinada por su posici´n en los datos de entrada. Luego una l´ o ınea queespecifica la longitud del cable que ser´ cortado para conectar dos compu- atadoras adyacentes. Al final se incluir´ una oraci´n indicando la cantidad de a ocable utilizado. En el listado las longitudes de cable a recortar que, van de un extremo alotro de la red. Utilice un formato similiar a la provista. Separe los datos deuna red imprimiento una l´ ınea de asteriscos e imprima las distancias con dosdecimales. Ejemplo de Entrada65 1955 2838 10128 62111 8443 116511 2784 99142 8188 3095 383132 7349 8672 1110 Ejemplo de Salida
  • 200. 188 8. BACKTRACKING**********************************************************Network #1Cable requirement to connect (5,19) to (55,28) is 66.80 feet.Cable requirement to connect (55,28) to (28,62) is 59.42 feet.Cable requirement to connect (28,62) to (38,101) is 56.26 feet.Cable requirement to connect (38,101) to (43,116) is 31.81 feet.Cable requirement to connect (43,116) to (111,84) is 91.15 feet.Number of feet of cable required is 305.45.**********************************************************Network #2Cable requirement to connect (11,27) to (88,30) is 93.06 feet.Cable requirement to connect (88,30) to (95,38) is 26.63 feet.Cable requirement to connect (95,38) to (84,99) is 77.98 feet.Cable requirement to connect (84,99) to (142,81) is 76.73 feet.Number of feet of cable required is 274.40.**********************************************************Network #3Cable requirement to connect (132,73) to (72,111) is 87.02 feet.Cable requirement to connect (72,111) to (49,86) is 49.97 feet.Number of feet of cable required is 136.99.
  • 201. Cap´ ıtulo 9 Geometr´ computacional ıa9.1. Introducci´n o La geometr´ computacional trata de una serie conceptos que se definen ıaa continuaci´n: oTriangulaci´n de pol´ o ıgonos Triangulaci´n es la divisi´n de un pol´ o o ıgono plano en un conjunto de tri´ngulos, usualmente con la restricci´n de que a o cada lado del tri´ngulo sea compartido por dos tri´ngulos adyacentes. a aProblemas de partici´n La triangulaci´n es un caso especial de la par- o o tici´n de un pol´ o ıgono. Lo que trata normalmente es de particionar el pol´ıgono en objetos convexos m´s peque˜os, porque es m´s f´cil traba- a n a a jar con objetos peque˜os. nProblemas de intersecci´n En el plano los problemas de intersecci´n es- o o t´n relacionados con encontrar los puntos de intersecci´n de todos los a o segmentos que se forman con los puntos especificados. En dimensiones superiores se analizan tambi´n la intersecci´n de poliedros. e oCerco convexo o convex hull Un cerco convexo crea un subconjunto de un plano denominado plano convexo, s´ y solo s´ cualquier segmento de ı ı recta de los puntos especificado est´ en este subconjunto. aB´ squeda geom´trica La b´squeda geom´trica se refiere a tres problemas u e u e principales: ubicaci´n de un punto en un pol´ o ıgono, visibilidad para conocer las ´reas visibles al iluminar con un rayo de luz y las b´squedas a u en un subconjunto espec´ ıfico. 189
  • 202. 190 9. GEOMETR´ COMPUTACIONAL IAAreas de pol´ıgonos Comprende los m´todos para calcular el ´rea de un e a pol´ ıgono, dada una lista de puntos.Una descripci´n de las tem´ticas que trata el campo de la geometr´ compu- o a ıatacional se puede encontrar en [Cha94]. Iniciaremos el desarrollo de ´ste cap´ e ıtulo con concepto de geometr´ y ıaluego se describir´ la geometr´ computacional. En ambos casos se mostrar´n a ıa aalgunos algoritmos y la implementaci´n de las librer´ de Java. o ıas9.2. Geometr´ ıa La geometr´ es el estudio matem´tico de elementos en el espacio, por ıa aejemplo puntos, l´ ıneas, planos y vol´menes. A´n cuando esta geometr´ ha u u ıasido estudiada ampliamente se quiere mostrar como se implementa compu-tacionalmente y c´mo un conjunto b´sico de m´todos nos ayuda a resolver o a euna variedad de problemas si tener que resolver cada uno, reduciendo signi-ficativamente el tiempo de desarrollo. Una buena bibliograf´ para temas de ıageometr´ se puede leer en [Leh88]. ıa Bien para definir un punto crearemos la clase P unto con dos par´metros ael valor del eje x y el valor del eje y. El c´digo para definir este objeto es: o/* Clase para definir un punto * @author Jorge Teran */ public Punto(double x, double y) { super(); this.x = x; this.y = y; }Los valores se han definido como double para permitir la implementaci´n de olos m´todos que efect´an c´lculos cuyos resultados no son enteros. e u a En el desarrollo de ´sta clase se han definido una serie de m´todos ge- e enerales que nos permiten resolver una variedad de problemas. Tomando losconceptos de la geometr´ se presenta la distancia a otro punto y el ´rea de ıa, aun tri´ngulo que est´ formada por tres puntos. a a El resultado da la siguiente clase:
  • 203. 9.2. GEOMETR´ IA 191/* Clase para definir un punto * @author Jorge Teran */public class Punto { double x, y; public Punto(double x, double y) { super(); this.x = x; this.y = y; } double X() { return (x); } double Y() { return (y); } public String toString() { return ("(" + x + "," + y + ")"); } double Distancia(Punto p) { double d = 0; d = (x - p.X()) * (x - p.X()) + (y - p.Y()) * (y - p.Y()); d = Math.sqrt(d); return d; } double areaTriangulo(Punto b, Punto c) { double d = 0; d = x * b.X() - y * b.X() + y * c.X() - x * c.Y() + b.X() * c.Y() -c.X() * b.Y();
  • 204. 192 9. GEOMETR´ COMPUTACIONAL IA d = Math.abs(d / 2); return d; }}Para definir una recta en el plano existen varias alternativas, se puede utilizarla expresi´n y = ax + b sin embargo tiene el problema que cuando la recta oes paralela al eje y dado que la pendiente es infinita haciendo que haya quetomar algunos recaudos. Existe una representaci´n m´s apropiada que es ax + by + c = 0 que es la o aque se construy´ en este ejemplo. Tambi´n puede definirse la recta con dos o epuntos. En la clase que se ha construido se ha tomado las dos anteriores y laque se define por un punto m´s una pendiente. Cuando se dan los dos puntos aconstru´ımos los valores a, b, c desde ´sta especificaci´n. e o A fin de poder comparar dos n´meros no enteros hemos construido una uvariable que la hemos llamado ERROR. Esto se hace porque las operacionesde punto flotante no dan un valor exacto. Los m´todos implementados son: punto de intersecci´n, prueba de l´ e o ıneasparalelas, pendiente, l´ ınea perpendicular que pasa por un punto. La clasecompleta queda como sigue:public class Linea {/* Clase para definir una linea * @author Jorge Teran */ double a, b, c; public Linea(double a, double b, double c) { this.a = a; this.b = b; this.c = c; } public Linea(Punto p1, Punto p2) { this.a = p1.Y() - p2.Y(); this.b = -p1.X() + p2.X(); this.c = p1.X() * p2.Y() - p1.Y() * p2.X(); }
  • 205. 9.2. GEOMETR´ IA 193 public Linea(Punto p, double m) { double a, b; a = m; b = 1; c = -(a * p.X() + b * p.Y()); } public static final double ERROR = 0.0001; double A() { return a; } double B() { return b; } double C() { return c; } Punto Interseccion(Linea l) { double x, y; if (Paralelas(l)) { System.out.println("Error: Lineas parelas"); // System.exit(0); } x = (l.B() * c - b * l.C()) / (l.A() * b - a * l.B()); if (Math.abs(b) > ERROR) y = -(a * x + c) / b; else y = -(l.A() * x + l.C()) / l.B();
  • 206. 194 9. GEOMETR´ COMPUTACIONAL IA return (new Punto(x, y)); } Boolean Paralelas(Linea l) { return ((Math.abs(a - l.A()) <= ERROR) && ((Math.abs(b - l.B()) <= ERROR))); } double Pendiente() { if (b == 0) // pendiente infinita return (0); else return (a / b); } Linea lineaPerpendicularPunto(Punto l) { return (new Linea(-b, a, (b * l.X() - a * l.Y()))); } public String toString() { return (a + "x+" + b + "y+" + c + "=0"); }}Se pueden construir una variedad de clases para manejar diferentes figurasgeom´tricas que incluyan funciones b´sicas que, combinadas permiten resol- e aver algunos problemas utilizando sus funciones. Como ejemplo, consideremos una lista de puntos de la cu´l queremos ahallar cu´les son los dos puntos m´s cercanos. a a
  • 207. 9.2. GEOMETR´ IA 195Para resolver ´sto definimos un vector de puntos y con dos ciclos compara- emos exaustivamente todas las posibilidas hallando la distancia m´ ınima. Este 2c´digo con tiempo de ejecuci´n proporcional a O(n ) es el siguiente: o opublic class minimoPuntos {/* * @author Jorge Teran */ public static void main(String[] args) { Punto[] p = new Punto[5]; double minimo = 999999, d = 0; int punto1 = 0, punto2 = 0; p[0] = new Punto(8, 16); p[1] = new Punto(8, 11); p[2] = new Punto(12, 16); p[3] = new Punto(24, 10); p[4] = new Punto(13, 8); for (int i = 0; i < 5; i++) { for (int j = i + 1; j < 5; j++) { d = p[i].Distancia(p[j]); if (d < minimo) { minimo = d; punto1 = i; punto2 = j; } } } System.out.println("Los puntos m´s cercanos son :"); a System.out.println(p[punto1] + " y " + p[punto2]); System.out.println("Con distancia :" + minimo); }}Para mostrar la utilizaci´n de los m´todos construidos hallaremos la distancia o ede un punto al punto con el cual una recta tiene la distancia m´s corta, esto aes:
  • 208. 196 9. GEOMETR´ COMPUTACIONAL IAComo se ve en el dibujo lo que se quiere hallar es el punto con el cual una l´ ıneatrazada desde el punto forman un ´ngulo recto. Para ´sto primero hallamos a euna recta perpendicular, a la recta que pase por el punto especificado. Luegohallamos la intersecci´n de las dos rectas, y finalmente la distancia entre ´stos o edos puntos. Como ve no es necesario resolver matem´ticamente este problema aa fin de codificarlo, lo que se hace es utilizar las funciones disponibles. Elresultado es el siguiente:public class PruebaGeo {/* * @author Jorge Teran */ public static void main(String[] args) { Punto p4 = new Punto(4,-1); Linea l4 = new Linea(3,-4,12); Linea l5 = l4.lineaPerpendicularPunto(p4); Punto p5 = l5.Interseccion(l4); System.out.println("Distancia = "+p5.Distancia(p4)); }}9.3. Librer´ de Java ıas En el lenguaje Java se cuentan con funciones trigonom´tricas en la clase eMath, Se presentan las principales en el cuadro 9.1 Tambi´n se dispone del paquete java.awt.geom que provee una serie de eclases que facilitan el desarrollo de programas que tratan con problemasgeom´tricos. Existen clases para puntos, l´ e ıneas , rect´ngulos, ´reas, y pol´ a a ıgo-nos. Algunos de ´stos m´todos se muestran en el cuadro 9.2. e e
  • 209. 9.3. LIBRER´ IAS DE JAVA 197 Constante PI Math.PI Arco coseno Math.acos(double a) Arco seno Math.asin(double a) Arco tangente Math.atan(double a) Seno Math.sin(double a) Coseno Math.cos(double a) Tangente Math.tan(double a) Coseno hiperb´lico o Math.cosh(double x) Seno hiperb´lico o Math.sinh(double x) Valor de la hipotenusa Math.hypot(double x, double y) Convertir a grados toDegrees(double anguloRadianes) Convertir a radianes toRadians(double anguloGrados) Cuadro 9.1: Funciones trigonom´tricas del Java e Construir un punto Point2D.Double(double x, double y) Distancia a otro punto distance(Point2D p) Construir una l´ ınea Line2D.Double(Point2D p1, Point2D p2) Contiene el punto p contains(Point2D p) Intersecta con el rect´ngulo intersects(Rectangle2D r) a Intersecta la l´ ınea intersectsLine(Line2D l) Distancia al punto p ptLineDist(Point2D p) Cuadro 9.2: Funciones para puntos y l´ ıneas
  • 210. 198 9. GEOMETR´ COMPUTACIONAL IA El siguiente programa muestra el uso de ´ste paquete de Java. eimport java.awt.geom.*;/* * @author Jorge Teran */public class ClasesJava { public static void main(String[] args) { Point2D.Double p1 = new Point2D.Double(3, 5); Point2D.Double p2 = new Point2D.Double(3, 35); System.out.println("p1= " + p1); System.out.println("p2= " + p2); System.out.println("Distancia de p1 a p2= " + p1.distance(p2)); Line2D.Double l = new Line2D.Double(p1, p2); Point2D.Double p3 = new Point2D.Double(7, 5); System.out.println("Distancia al punto P3= " + l.ptLineDist(p3)); Line2D.Double l2 = new Line2D.Double(p3, p2); System.out.println("l intersecta a l2= " + l.intersectsLine(l2)); System.out.println("l contiene a p2= " + l.contains(p2)); }}9.4. Cercos convexos Dado un conjunto de puntos S se define un el cerco convexo, el conjuntoconvexo m´s peque˜o que contenga a todos los puntos de S. a n Cuando graficamos en la pantalla los puntos (x,y) hay que tomar en cuen-ta que el (0,0) es el extremo superior izquierdo de la pantalla. Consideremoslos siguientes puntos:
  • 211. 9.4. CERCOS CONVEXOS 199El cerco convexo se forma con los puntos (86,34), (57,39), (41,98), (110,85).Una propiedad del cerco convexo es que todos los segmentos de recta confor-mada por los puntos del conjunto est´n en el interior del cerco convexo. La afigura siguiente muestra el cerco y se puede observar que todos los puntosest´n contenidos por el cerco. a Para hallar cercos convexos existen varios algoritmos desarrollados. Con-sideremos inicialmente que comparemos un punto con cada uno de los seg-mentos de recta que se pueden formar y decidir si est´ al interior del cerco. aEste proceso claramente involucra tres ciclos, uno para cada punto y dos paraarmar los segmentos de recta a probar. Esto genera un algorimo proporcionala O(n3 ).
  • 212. 200 9. GEOMETR´ COMPUTACIONAL IA Figura 9.1: Alternativas para comparar un punto con una l´ ınea A fin de implementar la comparaci´n de un punto con respecto a una ol´ ınea es necesario tomar en cuenta diferentes alternativas. Supongamos queel segmento de recta entre los puntos p1 y p2 donde el p1.x = p2.x, o seaparalelas al eje y. En este caso con referencia al primer punto obtendremos larespuesta verdadera cuando p1.x < p2.x. Esto significa que el punto est´ m´s a aa la izquierda de p1. La figura 9.1 lo esquematiza. La figura 9.2 muestra el caso cuando el punto se encuentra en el segmentode recta. Cuando el segmento de recta no es perpendicular al eje y se pre-sentan varios casos de los que solo mostramos algunos en la figura 9.3. Parahallar la posici´n de un punto con relaci´n a un segmento de recta se ha o oagregado un m´todo de la clase L´nea que da true si el punto esta m´s a la e ı aizquierda del segmento de recta. El c´digo es el siguiente: o public boolean aIzquierda(Punto p) { double pendiente=Pendiente(); if (this.sinPendiente) { if (p.x < p1.x) return true; else { if (p.x == p1.x) { if (((p.y > p1.y) && (p.y < p2.y)) || ((p.y > p2.y) && (p.y < p1.y)))
  • 213. 9.4. CERCOS CONVEXOS 201 Figura 9.2: Punto en el segmento de la rectaFigura 9.3: Caso en que el segmento de recta no es perpendicular al eje Y
  • 214. 202 9. GEOMETR´ COMPUTACIONAL IA return true; else return false; } else return false; } } else { double x3 = (((p.x + pendiente * (pendiente * p1.x - p1.y + p.y)) / (1 + pendiente * pendiente)) ); double y3 = ((pendiente * (x3 / 1 - p1.x) + p1.y)); if (pendiente == (double) 0) { if ((p.y ) > y3) return true; else return false; } else { if (pendiente > (double) 0) { if (x3 > (p.x )) return true; else return false; } else { if ((p.x * 1) > x3) return true; else return false; } } } }Para construir el c´digo que halle el cerco convexo se ha realizado un pro- ograma de ejemplo, que es el siguiente:
  • 215. 9.4. CERCOS CONVEXOS 203import java.awt.Graphics;import java.util.Vector;/* Programa oara hallar un * cerco convexo * @author Jorge Teran */public class Convexo { public static void main(String[] args) { Vector puntos = new Vector(); Vector cerco = new Vector(); int i, j, k; puntos.addElement(new Punto(57, 39)); puntos.addElement(new Punto(41, 98)); puntos.addElement(new Punto(60, 75)); puntos.addElement(new Punto(64, 59)); puntos.addElement(new Punto(110, 85)); puntos.addElement(new Punto(86, 34)); puntos.addElement(new Punto(87, 71)); System.out.println("Punto"); for (k = 0; k < puntos.size(); k++) { System.out.println((Punto) puntos.elementAt(k)); } boolean masIzquierdo, masDerecho; for (i = 0; i < puntos.size(); i++) { for (j = (i + 1); j < puntos.size(); j++) { masIzquierdo = true; masDerecho = true; Linea temp = new Linea( (Punto) puntos.elementAt(i), (Punto) puntos.elementAt(j)); for (k = 0; k < puntos.size(); k++) { if ((k != i) && (k != j)) { if (temp.aIzquierda( (Punto)puntos.elementAt(k)))
  • 216. 204 9. GEOMETR´ COMPUTACIONAL IA masIzquierdo = false; else masDerecho = false; } } if (masIzquierdo || masDerecho) { cerco.addElement(new Linea((Punto) puntos.elementAt(i), (Punto) puntos.elementAt(j))); } } } System.out.println("Cerco Convexo"); for (k = 0; k < cerco.size(); k++) { System.out.println(((Linea) cerco.elementAt(k)).p1 + "," + ((Linea) cerco.elementAt(k)).p2); } }} Existen varios algoritmos m´s eficientes para hallar el cerco convexo de alos que se mencionan Graham,Jarvis Quick hull. Alejo Hausner del departamento del ciencias de la computaci´n de la ouniversidad de Princeton ha desarrollado unas animaciones que, muestran laejecuci´n de estos algoritmos. o Se pueden ver en su p´gina web: ahttp://www.cs.princeton.edu/¬ah/alg anim/version1/ConvexHull.html El m´todo de Graham de basa en e Encontrar el punto m´s extremo. Se escoge el punto con una coordenada a y m´s grande. Se denomina pivote y se garantiza que est´ en el cerco a a convexo. Se ordenan los puntos en forma ascendente en funci´n del ´ngulo que o a forman con el pivote, terminamos con un pol´ ıgono con forma de estrella. Luego se construye el cerco recorriendo el contorno del pol´ ıgono.
  • 217. 9.5. CLASE JAVA PARA POL´ IGONOS 205El m´todo de Jarvis de basa en: e Se inicializa en alg´n punto que, se garantiza pertenece al cerco u Se recorren los puntos buscando cual est´ m´s a la izquierda, ese es- a a tar´ en el cerco. aEl m´todo de Quick hull de basa en: e Dado un segmento de l´ ınea AB cuyos dos puntos que conocemos est´n a en el cerco convexo. Se halla el punto m´s alejado a este segmento formando un tri´ngulo a a ABC. Los puntos que est´n en el interior del tri´ngulo no pueden ser del arco a a convexo. Con los puntos que est´n afuera del segmento AB se crea un a conjunto y con los que est´n fuera del segmento BC otro. Con estos a dos conjuntos se repite el proceso recursivamente.9.5. Clase Java para pol´ ıgonos Las clases de Java para el manejo de pol´ ıgonos es la clase Polygon() quecrea un pol´ ıgono vac´ Los m´todos de esta clase son: ıo. e Agregar un punto addPoint(int x, int y) Verifica si el punto est´ al interior a del pol´ıgono contains(Point p) Obtiene las coordenadas de un rect´ngulo que contiene al pol´ a ıgono getBounds() Verifica si el pol´ ıgono intersecta con el rect´ngulo a intersects(Rectangle2D r)Cuando construimos un pol´ ıgono la forma de la figura est´ dada por el orden aen el que ingresamos los puntos. El siguiente c´digo ejemplifica el uso de la oclase Polygon().import java.awt.Polygon;import java.awt.Point;/*
  • 218. 206 9. GEOMETR´ COMPUTACIONAL IA * @author Jorge Teran */public class pol´gono { ıpublic static void main(String[] args) {Polygon puntos = new Polygon();int i, j, k;puntos.addPoint(57, 39);puntos.addPoint(41, 98);puntos.addPoint(60, 75);puntos.addPoint(64, 59);puntos.addPoint(110, 85);puntos.addPoint(86, 34);puntos.addPoint(87, 71);Point p= new Point (60,75);System.out.println(puntos.getBounds());System.out.println(p);System.out.println(puntos.contains(p));}}Este c´digo inserta los puntos del ejemplo de cerco convexo, produciendo un orect´ngulo que incluye todos los puntos. ajava.awt.Rectangle[x=41,y=34,width=69,height=64]Si realizamos la pruebaPoint p= new Point (60,75);System.out.println(puntos.contains(p));Veremos que las respuesta es f alse debido a que la clase pol´ıgono no halla uncerco convexo, y este punto no es interior al pol´ıgono. En cambio si creamosun pol´ ıgono con los puntos (57, 39), (41, 98), (110, 85), (86, 34) obtendremostrue dado que el punto est´ en el interior del pol´ a ıgono.
  • 219. 9.6. CALCULO DEL PER´ ´ IMETRO Y AREA DEL POL´ ´ IGO-NO. 2079.6. C´lculo del per´ a ımetro y ´rea del pol´ a ıgo- no. Para hallar el per´ ımetro de un pol´ ıgono, es suficiente con hallar la distan-cia entre dos puntos consecutivos y sumar. Cuando se quiere hallar el ´rea ano es tan simple. Consideremos el siguiente pol´ ıgonoPara poder determinar el ´rea de ´ste se requiere triangulizar el mismo. Esto a ees dividir en tri´ngulos y sumar. aEl proceso de triangular se inicia numerando los v´rtices del pol´ e ıgono de0 a n − 1. Luego tomamos la l´ ınea entre los puntos 0 y n − 1 como base ybuscamos un punto con el cual producen un tri´ngulo que no contenga puntos ainteriores. De esta forma se divide el pol´ ıgono en tres partes. Un tri´ngulo y ados subpol´ ıgonos uno a la izquierda y otro a la derecha. Si un subpol´ ıgono
  • 220. 208 9. GEOMETR´ COMPUTACIONAL IAtiene tres lados es un tri´ngulo y no requiere m´s subdivisiones. Luego este a aproceso se repite hasta terminar todos los subpol´ ıgonos. Cada triangulizaci´n de un pol´ o ıgono de n v´rtices tiene n − 2 tri´ngulos e ay n − 3 diagonales. El c´digo para triangular el pol´ o ıgono de ejemplo es el siguiente:import java.awt.Graphics;import java.util.Vector;/* Programa para triangular el poligono * @author Jorge Teran */public class T { public static void main(String[] args) { Vector puntos = new Vector(); Vector triangulo = new Vector(); puntos.addElement(new Punto(57, 39)); puntos.addElement(new Punto(41, 98)); puntos.addElement(new Punto(60, 75)); puntos.addElement(new Punto(64, 59)); puntos.addElement(new Punto(110, 85)); puntos.addElement(new Punto(86, 34)); puntos.addElement(new Punto(87, 71)); Proceso(puntos,triangulo); return; } static void Proceso(Vector puntos, Vector triangulo){ Vector iPuntos = new Vector(); Vector dPuntos = new Vector(); Punto t1,t2,t3; int i, j, k; i=0; j= puntos.size()-1; if (j<2) return; if (j==2){ t1=(Punto) puntos.elementAt(0); t2=(Punto) puntos.elementAt(1);
  • 221. 9.6. CALCULO DEL PER´ ´ IMETRO Y AREA DEL POL´ ´ IGO-NO. 209 t3=(Punto) puntos.elementAt(2); triangulo.addElement(new Linea(t1,t2)); triangulo.addElement(new Linea(t1,t3)); trangulo.addElement(new Linea(t2,t3)); return; } k=buscaTriangulo(puntos); iPuntos=new Vector(); iPuntos.add((Punto)puntos.elementAt(0)); for (i=k;i<puntos.size();i++) iPuntos.add((Punto)puntos.elementAt(i)); Proceso(iPuntos,triangulo); new DibujarPuntos(iPuntos, triangulo); dPuntos=new Vector(); for (i=0;i<=k;i++) dPuntos.add((Punto)puntos.elementAt(i)); Proceso(dPuntos,triangulo); new DibujarPuntos(dPuntos, triangulo); } static int buscaTriangulo(Vector puntos){ int i,pi,ult; ult=puntos.size()-1; for (i = 1;i<puntos.size()-1;i++){ pi=tienePuntoInterior(puntos,i,ult); return pi; } return 0; } static int tienePuntoInterior (Vector puntos,int k,int ult){ Punto t1,t2,t3,t4; t1 = (Punto)puntos.elementAt(0); t2 = (Punto)puntos.elementAt(ult); t3 = (Punto)puntos.elementAt(k); Linea l1 = new Linea(t1,t2); Linea l2 = new Linea(t1,t3); Linea l3 = new Linea(t2,t3);
  • 222. 210 9. GEOMETR´ COMPUTACIONAL IA int i=-1; for (i = 1;i<puntos.size()-1;i++){ if ((i!=k)&&(i!=ult)){ t4 = (Punto)puntos.elementAt(i); if (l1.aIzquierda(t4)) return i; if (l2.aIzquierda(t4)) return i; if (l3.aIzquierda(t4)) return i; } } return i; }}En el libro [Mis97] se muestran diversos algoritmos para triangular pol´ ıgonos.De los que hay que mencionar el algoritmo de Chazelles que puede triangularpol´ ıgonos simples en tiempo lineal.
  • 223. 9.7. EJERCICIOS 2119.7. Ejercicios9.7.1. Problema 378 - L´ ıneas que intersectan Se sabe que todo par de puntos distintos en el plano definen una l´ ınea.Un par de l´ ıneas en el plano pueden intersectarse de tres maneras 1) no hayintersecci´n porque son paralelas, 2) intersectan en una l´ o ınea cuando est´nasobrepuestas y 3) intersectan en un punto. El programa lee repetidamente una serie de cuatro puntos que definendos l´ıneas x y y y determina como intersectan las l´ ıneas. Todos los n´meros ude este problema estaran entre −1000 y 1000 Entrada.- La primera l´ ınea contiene un n´mero N entre 1 y 10 indicando uel n´mero de pares de l´ u ıneas que est´n representadas. Las siguientes N l´ a ıneascontienen los ocho puntos que representan las coordenadas de las l´ ıneas enel formato x1 y1 , x2 y2 ,x3 y3 ,x4 y4 . El punto x1 y1 es distinto del punto x2 y2 . Dela misma forma los puntos x3 y3 y x4 y4 . Salida.- La salida debe ser N + 2 l´ ıneas. La primera l´ ınea de salida esdecir INTERSECTING LINES OUTPUT. Las siguientes l´ ıneas correspondena una l´ ınea de entrada describiendo la forma en la que se intersectan lasl´ ıneas, a) NONE cuando no intersectan b) LINE cuando se sobreponen y c)POINT seguido de las coordenadas x,y del punto de intersecci´n cuando se ointersectan, y al final como ultima l´ ´ ınea END OF OUTPUT. Ejemplo de Entrada.-50 0 4 4 0 4 4 05 0 7 6 1 0 2 35 0 7 6 3 -6 4 -32 0 2 27 1 5 18 50 3 4 0 1 2 2 5Ejemplo de Salida.-INTERSECTING LINES OUTPUTPOINT 2.00 2.00NONELINEPOINT 2.00 5.00POINT 1.07 2.20END OF OUTPUT
  • 224. 212 9. GEOMETR´ COMPUTACIONAL IA9.7.2. Problema 273 - Juego de Palos En este juego un n´mero de palos pl´sticos se esparcen en una mesa y los u ajugadores tratan de removerlos sin mover los otros. En este problema solose quiere conocer si varios pares de palos est´n conectados por un camino ade palos que se tocan. Dada una lista de puntos terminales para algunospalos se pregunta si varios pares de palos est´n conectados o si ninguno aest´ conectado. Dos palos pueden estar conectados indirectamente por otros apalos. Entrada La entrada comienza con un n´mero entero positivo en una l´ u ıneael n´mero de casos que siguen. Esta l´ u ınea est´ seguida por una l´ a ınea en blanco.Tambi´n existe una l´ e ınea en blanco entre dos entradas consecutivas. Un caso de prueba consiste en m´ltiples l´ u ıneas de entrada. La primeral´ ınea ser´ un n´mero entero n > 1 dando el n´mero de palos en la mesa. a u uLas siguientes n l´ ıneas contienen las coordenadas x,y de los dos puntos quedefinen las coordenadas de inicio y fin de los palos. Todas las coordenadas son menos de 100. Los palos son de longitud va-riable. El primer palo se denominara #1, el segundo #2 y as´ sucesivamente. ıLas siguientes l´ıneas contendr´n dos enteros positivos a y b. Debe determinar asi el palo a puede conectarse con el palo b. Cuando a = 0 y b = 0 termina laentrada. No existen palos de longitud 0. Salida Para cada caso de prueba la salida debe seguir la descripci´n. La osalida de dos casos consecutivos se separaran por una l´ ınea en blanco. Excepto si la ultima l´ ´ ınea donde a, b = 0 debe generar una l´ ınea que digaCONNECTED”si el palo a se puede conectar al palo b, o ”NOT CONNEC- ¸TED”, si no pueden conectarse. Un palo se considera conectado a s´ mismo. ı Ejemplo de Entrada171 6 3 34 6 4 94 5 6 71 4 3 53 5 5 55 2 6 35 4 7 21 4
  • 225. 9.7. EJERCICIOS 2131 63 36 72 31 30 0 Ejemplo de salidaCONNECTEDNOT CONNECTEDCONNECTEDCONNECTEDNOT CONNECTEDCONNECTED
  • 226. 214 9. GEOMETR´ COMPUTACIONAL IA9.7.3. Problema 218 - Erradicaci´n de moscas o Los entimologistas en el noreste han colocado trampas para determinar lainfluencia de una variedad de moscas en el ´rea. Se planea estudiar programas ade erradicaci´n que tienen posibilidades de controlar el crecimiento de la opoblaci´n. o El estudios deben organizar las trampas en las que se agarraron moscasen regiones compactas que luego ser´n utilizadas para probar los programas ade erradicacci´n. Una regi´n se define como un pol´ o o ıgono con el per´ımetrom´ınimo que puede encerrar a todas las trampas. Por ejemplo, las trampas de una regi´n particular son representadas por opuntos, el pol´ıgono asociado ser´ el siguiente: ıa Lo que se debe hacer es un programa que, tome como entrada la ubicaci´n ode las trampas en cada regi´n e imprimir las ubicaciones de las trampas que ofiguran en el per´ımetro de la regi´n y la longitud total del per´ o ımetro. Entrada El archivo de entrada contiene los datos de varias regiones. Laprimera l´ınea contiene el n´mero de trampas de una regi´n. Los siguientes u oregistros contienen dos n´meros reales que son las coordenadas de ubicaci´n u ox,y de las trampas. Los datos en un registro no son duplicados y el fin de losdatos de una regi´n se indica con 0. o Salida La salida para una regi´n son tres l´ o ıneas: La primera l´ ınea es eln´mero de la regi´n, la segunda lista los puntos del per´ u o ımetro, y la tercerala longitud del mismo. Una l´ınea en blanco debe separar las diferentes regiones. Ejemplo de en-trada31 24 105 12.3
  • 227. 9.7. EJERCICIOS 21560 01 13.1 1.33 4.56 2.12 -3.271 0.55 04 1.53 -0.22.5 -1.50 02 20Ejemplo de salidaRegion #1:(1.0,2.0)-(4.0,10.0)-(5.0,12.3)-(1.0,2.0)Perimeter length = 22.10Region #2:(0.0,0.0)-(3.0,4.5)-(6.0,2.1)-(2.0,-3.2)-(0.0,0.0)Perimeter length = 19.66Region #3:(0.0,0.0)-(2.0,2.0)-(4.0,1.5)-(5.0,0.0)-(2.5,-1.5)-(0.0,0.0)Perimeter length = 12.52
  • 228. 216 9. GEOMETR´ COMPUTACIONAL IA9.7.4. Problema 476 - Puntos en rect´ngulos a Dado una lista de rect´ngulos y puntos en el plano determinar cu´les a apuntos est´n en que rect´ngulos. a a Entrada La entrada est´ formada for n < 10 rect´ngulos descriptos uno a aen cada l´ınea. Cada rect´ngulo esta descripto por dos puntos especificados apor sus coordenadas en n´meros reales. Estos puntos representan la esquina usuperior izquierda y la esquina inferior derecha. El final de la lista ser´ indicada por un asterisco en la columna uno. a Las siguientes l´ ıneas contienen las coordenadas x,y de los puntos, una porl´ ınea. El final de la lista ser´ indicada por un punto con coordenadas 9999.9, a9999.9, que no se incluyen en la salida. Los puntos que coinciden con el borde del cuadrado, se consideran in-teriores al cuadrado.. Ejemplo de entradar 8.5 17.0 25.5 -8.5r 0.0 10.3 5.5 0.0r 2.5 12.5 12.5 2.5*2.0 2.04.7 5.36.9 11.220.0 20.017.6 3.2-5.2 -7.89999.9 9999.9Ejemplo de salidaPoint 1 is contained in figure 2Point 2 is contained in figure 2Point 2 is contained in figure 3Point 3 is contained in figure 3Point 4 is not contained in any figurePoint 5 is contained in figure 1Point 6 is not contained in any figure
  • 229. Bibliograf´ ıa[Cha94] Bernard Chazelle. Computational geometry: a retrospective. In STOC ’94: Proceedings of the twenty-sixth annual ACM sympo- sium on Theory of computing, pages 75–94, New York, NY, USA, 1994. ACM Press.[CK79] ˜ John C. Cherniavsky and SamuelN. Kamin. A complete and con- sistent hoare axiomatics for a simple programming language. J. ACM, 26(1):119–128, 1979.[CSH05] Gary Cornell Cay S. Horstman. Core Java 2 J2SE 5.0 Volume 1. Sun Microsystems Press, 2005.[EH96] Sartaj Sahni Ellis Horowits. Fundamentals of Algoritms. Com- puter Science Press, 1996.[Fel05] Yishai A. Feldman. Teaching quality object-oriented program- ming. J. Educ. Resour. Comput., 5(1):1–16, 2005.[GB96] Paul Bratley Gilles Brassard. Fundamentals of Algoritms. Prin- tice Hall, 1996.[Gri77] Ralph P. Grimaldi. Matematica Discreta. Addison Wessley, 1977.[Hoa83] C. A. R. Hoare. Communicating sequential processes. Commun. ACM, 26(1):100–106, 1983.[KBO+ 05] Benjamin A. Kuperman, Carla E. Brodley, Hilmi Ozdoganoglu, ˜ T.N. Vijaykumar, and Ankit Jalote. Detection and prevention of stack buffer overflow attacks. Commun. ACM, 48(11):50–56, 2005. 217
  • 230. 218 BIBLIOGRAF´ IA[Leh88] Charles H. Lehmann. Geometr´a Anal´tica. Editorial Limusa, ı ı 1988.[LPC+ 02] G. Leavens, E. Poll, C. Clifton, Y. Cheon, and C. Ruby. Jml reference manual, 2002.[MAR03] Steven S. Skiena Miguel A. Revilla. Programming Challenges. Springer, 2003.[McC01] Jeffrey J. McConnell. Analysis of Algorithms: An Active Learning Approach. Jones and Bartlett Pub, 2001.[Mis97] Mishra. Computational real algebraic geometry. In Jacob E. Goodman and Joseph O’Rourke, editors, Handbook of Discrete and Computational Geometry, CRC Press, 1997. 1997.[Red90] Uday S. Reddy. Formal methods in transformational derivation of programs. In Conference proceedings on Formal methods in software development, pages 104–114, New York, NY, USA, 1990. ACM Press.[RLG94] Oren Patashnik Ronald L. Graham, Donald E. Knuth. Concrete Mathematics. Addison Wessley, 1994.[THCR90] Charles E. Leiserson Thomas H. Cormen and Ronald L. Rivest. Introduction to Algorithms. Massachusetts Institute of Techno- logy, 1990.[Vos01] Tanja Vos. M´todos Formales Especificaci´n y Verificaci´n. Um- e o o sa, 2001.
  • 231. Ap´ndice A e Fundamentos matem´ticos a Para el correcto an´lisis de los programas se requiere recordar algunos aconceptos de las matem´ticas. Se presentan las f´rmulas y m´todos que se a o erequieren en una forma simple sin ahondar en desarrollos te´ricos y demos- otraciones. En el mismo, introducimos las ecuaciones m´s utilizadas y cuyos desarro- allos rigurosos los encontrar´ en los libros de matem´ticas. Algunas referencias a aa ´stos textos est´n en la bibliograf´ e a ıa.A.1. Recordatorio de logaritmos Es necesario recordar los siguientes conceptos de logaritmos que son deuso com´n. u 1. ab = c significa que loga c = b donde a se denomina la base de los lo- garitmos, en el estudio que nos interesa normalmente trabajamos con logaritmos en base 2, pero como se explic´ en cap´ o ıtulos anteriores sim- plemente se utiliza log sin importarnos la base. 2. log(ab) = log(a) + log(b) 3. log(a/b) = log(a) − log(b) 4. log(ab ) = b log(a) 5. logb (x) = loga (x)/ loga (b) 6. alog b = blog a 219
  • 232. 220 ´ A. FUNDAMENTOS MATEMATICOSA.2. Recordatorio de seriesA.2.1. Series simples Supongamos que u(n) es una funci´n definida para n valores. Si sumamos oestos valores obtenemos: s(n) = u(1) + u(2) + u(3)........ + u(n).Es muy com´n el cambiar la notaci´n a la siguiente forma u o sn = u1 + u2 + u3 ........ + un .o simplemente n sn = ui . i=1A.2.2. Serie aritm´tica e Una serie aritm´tica puede expresarse como una secuencia en la que existe euna diferencia constante, llamada raz´n, entre dos elementos contiguos. La onotaci´n matem´tica para describirla es como sigue: o a sn = a, a + d, a + 2d, ........, a + (n − 1)d.La suma de los primeros n t´rminos de una serie aritm´tica puede expresarse e ecomo n n(a1 + an ) d sn = ai = = an + n(n − 1) i=1 2 2donde d es la raz´n ´ sea la diferencia entre dos t´rminos. o o eA.2.3. Serie geom´trica e Una serie geom´trica es una secuencia de t´rminos donde los t´rminos e e etiene la forma a, ar, ar2 , ar3 ...., arnla suma de ´sta serie podemos expresarla como sigue: e n a(1 − rn ) sn = ari = i=0 (1 − r)
  • 233. A.2. RECORDATORIO DE SERIES 221en general la suma de una serie geom´trica tiende a un l´ e ımite solo si rntambi´n tiende a un l´ e ımite. De esto podemos decir que una serie geom´trica ees convergente s´ y solo s´ −1 < r < 1. ı ıA.2.4. Propiedades de la sumatorias Propiedad distributiva n n ci = c i (A.2.1) i=1 i=1Propieadad asociativa n n n (ai + bi ) = ai + bi (A.2.2) i=1 i=1 i=1Propiedad conmutativa ai = ap (i) (A.2.3) i∈K p(i)∈KA.2.5. Series importantes n sn = 1=n (A.2.4) i=1 n sn = i = n(n + 1)/2 (A.2.5) i=1 n sn = i2 = n(n + 1)(2n + 1)/6 (A.2.6) i=1 n sn = ir = nr+1 /r + 1 + pr (n) (A.2.7) i=1donde r es un entero positivo y pr (n) es un polinomio de grado r. n 1 Hn = (A.2.8) i=1 i´sta serie se denomina serie arm´nica serie arm´nica y log(n + 1) < Hn ≤e o o1 + log n
  • 234. 222 ´ A. FUNDAMENTOS MATEMATICOSA.3. Combinatoria b´sica a Una permutaci´n de n objetos es un arreglo ordenado de los objetos. Por oejemplo si tenemos 3 objetos a, b, c los podemos ordenar de 6 maneras: abc acb bac bca cab cba El primer elemento se puede escoger de n formas, luego el segundo den − 1 maneras, y as´ sucesivamente por lo que ı n(n − 1)(n − 2)...,2,1 = n!Una combinaci´n de r objetos de n objetos es una selecci´n de r objetos sin o oimportar el orden y se escribe: n n! = r r!(n − r)!A.3.1. F´rmulas importantes o n n−1 n−1 = + (A.3.1) r r−1 r n n n (1 + x) = 1 + xi (A.3.2) i i=1 n n = 2n (A.3.3) i i=0 n n n n = (A.3.4) i i i=0,i impar i=0,i par
  • 235. A.4. PROBABILIDAD ELEMENTAL 223A.4. Probabilidad elemental La teor´ de la probabilidad est´ asociada a los fen´menos aleatorios, esto ıa a osignifica, los fen´menos cuyo futuro no es predecible con exactitud. o Todas las posibles salidas de un experimento al azar se denomina espaciomuestral. Por ejemplo cuando lanzamos un dado com´n existen seis posibles usalidas que son los n´meros del 1 al 6. Para este experimento el espacio umuestral es S = {1, 2, 3, 4, 5, 6}. El espacio muestral puede ser finito o infinito,contin´o o discreto. Se dice que es discreto cuando el n´mero de puntos de la u umuestra es finito o si pueden ser etiquetados como 1,2,3,4 y as´ sucesivamente. ı Un evento es una colecci´n de puntos de una muestra que a su vez un osubconjunto del espacio muestral. Se dice que un evento ocurre cuando alrealizar un experimento aleatorio obtenemos un elemento de un conjunto.Por ejemplo si lanzamos un dado el resultado obtenido es parte del conjuntode n´meros impares. Denominamos al conjunto u el evento imposible y atodo el conjunto muestral al evento universal. La probabilidad es una medida que asigna a cada evento A del espaciomuestral un valor num´rico un valor P r[A] que da la medida de que A pueda eocurrir. 1. Para cada evento de A ≥ 0 2. P r[S] = 1 3. Si A y B son mutuamente excluyentes vale decir A ∩ B = entonces P r[A ∪ B] = P r[A] + P r[B] ¯ 4. P r[A] = 1 − P r[A] 5. P r[A ∪ B] = P r[A] + P r[B] − P r[A ∩ B] P r[A∩B] 6. P r[A|B] = P r[B] 7. Dos eventos son independientes si P r[A ∩ B] = P r[A]P r[B] 8. Para indicar la suma de los eventos de S utilizamos la notaci´n: o P r[X = x] = P r[Ax ] = P r[s] ∀sεS
  • 236. 224 ´ A. FUNDAMENTOS MATEMATICOS 9. La esperanza matem´tica la representamos como a E[X] = xp(x) = X(s)P r[s] x ∀sεS 2 10. La varianza escribimos como σx y la definimos como E[X] = x(p(x) − E[X])2 x 11. La desviaci´n standard se define como la ra´ cuadrada de la varianza o ız y se representa por el s´ ımbolo σxA.5. T´cnicas de demostraci´n e oA.5.1. Demostraci´n por contradicci´n o o La prueba por contradicci´n es conocida como prueba indirecta y consiste oen demostrar que la negaci´n de una aseveraci´n nos lleva a una contradic- o oci´n. o Por ejemplo si deseamos probar que la proposici´n S es correcta debemos oprimeramente negar S y luego demostrar que ¬S es falso. Ejemplo: Demostrar que existe un n´mero infinito de n´meros primos. u u Para resolver esto se ve que S est´ dada por la frase existe un n´mero a uinfinito de n´meros primos y la negaci´n de ´sta seria existe un n´mero finito u o e ude n´meros primos. si demostramos que esto es una contradicci´n entonces u ola aseveraci´n inicial S es verdadera. o Demostraci´n: Supongamos que existe un n´mero finito de n´meros pri- o u umos P = p1 , p2 , ...., pn entonces si encontramos un n´mero primo Pn+1 habr´ u ı-amos demostrado que el conjunto no contiene a todos los primos por lo cual¬S es falso. Sea Pn+1 = p1 ∗ p2 ....pn + 1 claramente se ve que el resultadoes un n´mero primo, por lo tanto se demuestra que el conjunto de n´meros u uprimos no es finito y queda demostrada nuestra hip´tesis original el conjunto ode n´meros primos es infinito. uA.5.2. Demostraci´n por inducci´n o o Existen dos t´cnicas que normalmente se utilizan que son la deducci´n y la e oinducci´n. La deducci´n consiste en ir de un caso general a un caso particular. o o
  • 237. ´ ´A.5. TECNICAS DE DEMOSTRACION 225En cambio la inducci´n matem´tica trata de establecer una ley general en o abase a instancias particulares. Este razonamiento puede llevar a resultadoserr´neos si no se plantea adecuadamente. Sin embargo la deducci´n siempre o olleva a resultados correctos. El principio de inducci´n matem´tica se basa, primeramente demostrar o ala validez de nuestras suposiciones para valores de 0, 1, 2, .. y luego de que,nos hacemos alguna idea de como se comporta suponemos que, para un valorarbitrario n es correcto. En base de ´sta suposici´n demostramos que para e on − 1 es correcto con lo cual se demuestra nuestra suposici´n original. o
  • 238. ´ Indice alfab´tico ea´rbol, 164 inserci´n, 118 o ejemplo, 165 Java, 113 pivote, 121, 221 r´pida, 120 a eficiencia, 122afirmaciones, 92 selecci´n, 120 o assert, 93 eficiencia, 120 Java, 93 sort, 113algor´ıtmica elemental, 1 una pasada, 123Algoritmo, 1 eficiencia, 124an´lisis amortizado, 17 a coeficientes binomiales, 139apriori, 3 aplicaciones, 139b´squeda, 101 u cola prioridad, 166 binaria, 103, 105 ejemplo, 166 eficiencia, 101 combinatoria, 137 secuencial, 101, 102 contar, 137 eficiencia, 102 complejidad, 11Backtracking, 171 congruencias, 45 ecuaciones, 45, 46cadenas, 138 inverso, 45Carmichael, 52 potencias, 45Cercos convexos, 198 propiedades, 45 ejemplo, 202 reflexiva, 45 m´todos, 204 e sim´trica, 45 eclasificaci´n, 101, 111 o suma, 45 arrays, 113 transitiva, 45 burbuja, 117 conjuntos, 160 eficiencia, 118 ejemplo, 161 comparaci´n, 124 o Construir permutaciones, 179 compareTo, 115 en desorden, 179 226
  • 239. ´ ´INDICE ALFABETICO 227 en orden, 180 recorrido, 171demostraci´n por contradicci´n, 224 o o ineficiencia, 118demostraci´n por Inducci´n, 224 o o instancia, 2, 3, 6, 7, 9–11desviaci´n standard, 224 o invariante, 67, 68, 70–80, 85divide y vencer´s, 22 a aplicaciones, 75divisibilidad, 38divisor com´n, 38 u Java Modeling Language, 96 JML, 96eficiencia, 1–3, 7, 11, 101, 123, 124, anotaciones, 96 127 compilar, 96emp´ ırico, 2 cuantificadores, 98Eratostenes, 47, 94 ejecutar, 96errores de programaci´n, 62 o ensures, 96 ejemplo, 62, 64 invariante, 97 ejemplo C, 63 invariante ciclo, 97espacio muestral, 223 invariante clase, 97especificaci´n, 66 o requires, 96especificar, 107estructuras de datos, 153 listas enlazadas, 157estructuras recursivas, 15 ejemplo, 158estructuras secuenciales, 14 m´todos, 157 eEuclides, 39, 40, 74 logaritmos, 12, 219Euclides complejidad, 40Euclides extendido, 41 m´ximo com´n divisor, 37, 38, 40 a u m´todo iterativo, 20 efactores primos, 49 m´todo te´rico, 3 e ofactorizaci´n, 49 o m´ ınimo com´n m´ltiplo, 43 u uFermat, 51 map, 162Fibonacci, 24, 82, 141 ejemplo, 162 master, 22geom´trica, 221 e Miller - Rabin, 52geometr´ 189, 190 ıa, modular, 43, 44 Java, 196 l´ınea, 192 n´mero Euleriano, 143 u punto, 190 invariante, 145grafo, 171 tri´ngulo, 144 agrafos n´mero Stirling, 146 u ejemplo, 172 n´meros Catalanes, 142 u
  • 240. 228 ´ ´ INDICE ALFABETICO aplicaciones, 143 caja blanca, 61n´meros grandes, 53 u caja negra, 61n´meros primos, 47, 49 u verificaci´n, 61 o generaci´n, 47 o prueba din´mica, 92 anotaci´n asint´tica, 3, 13 o o prueba est´tica, 91 anotaci´n omega, 13 o proceso, 91notaci´n teta, 13 o prueba exaustiva, 105O grande recurrencias, 18 igualdad logaritmos, 12 recurrencias lineales, 23 l´ ımites, 12 regla de la suma, 138 propiedades, 12 regla del producto, 137 transitiva, 12 regla exclusi´n, 138 ooperaciones elementales, 6 regla inclusi´n, 138 oorden de, 11 representaci´n gr´fica, 108 o a RSA, 55permutaci´n, 138, 222 o Serie aritm´tica, 220 epila, 153 Serie geom´trica, 220 e ejemplo Java, 153 Series Simples, 220 lista LIFO, 153 Subconjuntos, 175pol´ıgono, 189 ejemplo, 176 a ´rea, 190 subconjuntos, 138 b´squeda, 189 u substituci´n, 18 o convexo, 189 sumatoria intersecci´n, 189 o propiedades, 221 partici´n, 189 opol´ıgonos te´rica, 3 o Java, 205 teor´ de n´meros, 35 ıa uPost condici´n, 67, 68, 72, 74–77, 79– o tiempo proceso operaciones, 35 81 tipos de algoritmos, 3post condici´n, 91, 96 o tri´ngulo de Pascal, 139 aprecondici´n, 66, 67, 74, 75, 91, 96 o invariante, 140probabilidad, 223 triangulaci´n, 189 oprobable primo, 54 triangular, 207programa certificado, 106, 107programa probado, 106 variables Java, 35prueba de primalidad, 51prueba de programas, 61