Вы находитесь на странице: 1из 225

,

COMPUTACION I
Lgica, resolucin de problemas,
algoritmos y programas
FUNDAMENTOS DE INFORMTICA
Lgica, resolucin de problemas,
programas y computadoras
ALLEN B. TUCKER
Bowdoin College
W. JAMES BRADLEY
Calvin College
ROBERT D. CUPPER
Allegheny College
DAVID K. GARNICK
Bowdoin College
Traduccin:
Manuel Ortega Ortiz de Apodaca
Universidad Europea de Madrid
Revisin tcnica:
Antonio Vaquero Snchez
Escuela Superior de Informtica
Universidad Complutense de Madrid
FUNDAMENTOS DE PROGRAMACIN
Algoritmos y estructura de datos
(Segunda edicin)
LUIS JOYANES AGUILAR
Departamento de Lenguajes y Sistemas
Informticos y de Ingeniera de Software
Escuela Universitaria de Informtica
Universidad Pontificia de Salamanca en Madrid
MADRID. BUENOS AIRES. CARACAS. GUATEMALA. LISBOA. MXICO
NUEVA YORK. PANAM. SAN JUAN. SANTAF DE BOGOT. SANTIAGO SAO PAULO
AUCKLAND. HAMBURGO LONDRES. MILN. MONTREAL NUEVA DElHI PARs
SAN FRANCISCO. SIDNEY SINGAPUR STo LOUIS TOKIO. TaRaNTa
Prlogo
\
En el pasado prximo, la Universidad Nacional Abierta ofreca, en el curso introductorio a la
Computacin, contenidos programticos que incluan elementos de la globalidad de temas que
comprende esta disciplina. Al abarcar tan amplio espectro se debilitaba el objetivo final del cur-
so (resolver problemas algortmicos con la ayuda de la' computadora digital), el cual, en trmi-
nos prcticos, lo reflejaba la ponderacin de los objetivos evaluables de la asignatura.
Este nuevo texto delimita los temas tratados a los estrictamente necesarios para el cabal do-
minio del objetivo de aprendizaje general del curso, logrando tratar los temas de importancia con
mayor claridad, extensin y profundidad. Otros temas de la disciplina son trasladados en el dise-
o curricular a un curso introductorio en Informtica y a otros cursos posteriores de los ejes de
Computacin y Sistemas de Informacin de la carrera de Ingeniera de Sistemas.
El texto gua del nuevo curso, un esfuerzo editorial conjunto de la Universidad Nacional
Abierta y McGraw-Hill Interamericana de Venezuela, S. A., aglutina el tratamiento de temas que
van desde conjuntos y funciones, lgica, problemas algortmicos y su solucin, hasta la codifica-
cin de estas soluciones en lenguajes computacionales de alto nivel, por autores de reconocida
trayectoria en la informtica y su enseanza, como son los profesores Allen B. Tucker y David
Garnick, del Bowdoin College; W. James Bradley, del Calvin College; Robert D. Cupper, del
Allegheny College, y Luis Joyanes Aguilar, de la Universidad Pontificia de Salamanca. Los con-
tenidos son selectivamente tomados de los textos Fundamentos de Informtica, lgica, resolucin
de problemas, programas y computadoras, de los cuatro primeros autores, y Fundamentos de
Programacin, algoritmos y estructura de datos, del ltimo, con el objetivo de conformar un tex-
to que cubra los requisitos especficos en trminos de contenidos, del nuevo Plan de Curso de la
asignatura Computacin I de la carrera de Ingeniera de Sistemas de la Universidad Nacional
Abierta, diseado por los profesores Edgar Blanco, NelIy Mendoza y Juana Marrero como Pro-
yecto Especial del rea de Actualizacin de Cursos del Vicerrectorado Acadmico de la mencio-
nada institucin.
DR. EOGAR BLANCO
ING. NELLY MENOOZA
ING. JUANA MARRERO
UNIVERSIDAD NACIONAL ABIERTA
Estudios Profesionales I
Computacin I (301)
Diseo de Instruccin
Edgar Blanco (UNA)
Juana Marrero (UNA)
NelIy Mendoza (UNA)
Especialista en evaluacin
Carmen Velsquez (UNA)
Coordinador de Ingeniera
de Sistemas
Dr. Luis Mrquez Gordones
v
UNIVERSIDAD NACIONAL ABIERTA
Nde .....2.Q.,.9..5.../t.:.f..-::t
Centro de ReQursos Mltiples
e.t. METROPOLITANO
COMPUTACIN l. Lgica, resolucin de problemas, algoritmos y programas
No est permitida la reproduccin total o parcial de este libro, ni su tratamiento infor-
mtico, ni la transmisin de ninguna forma o por cualquier medio, ya sea electrnico,
mecnico, por fotocopia, por registro u otros mtodos, sin el permiso previo y por escri-
to de los titulares del Copyright.
DERECHOS RESERVADOS 2000, respecto a la primera edicin en espaol, por
McGRAW-HILL/INTERAMERICANA DE ESPAA, S. A. U.
Edificio Valrealty, 1." planta
Basauri, 17
28023 Aravaca (Madrid)
ISBN: 84-481-2545-2
Depsito legal: M. 40.896-1999
Compilado de las siguientes obras:
Allen B. Tucker; W. James Bradley; Robert D. Cupper, y David K. Garnick.
FUNDAMENTOS DE INFORMTICA. Lgica, resolucin de problemas, programas
y computadoras.
ISBN: 84-481-1875-8
DERECHOS RESERVADOS 1994, respecto a la primera edicin en espaol. por
McGRAW-HILUINTERAMERICANA DE ESPAA, S. A. U.
Luis Joyanes Aguilar. FUNDAMENTOS DE PROGRAMACIN. Algoritmos y estruc-
tura de datos (Segunda edicin).
ISBN: 84-481-0603-2
DERECHOS RESERVADOS 1996, respecto a la segunda edicin en espaol, por
McGRAW-H1LUINTERAMERICANA DE ESPAA, S. A. U.
Esta obra se termin de
Imprimir en junio del 2005
Litogrfica Ingramex
Centeno Nm. 162 - 1
Col. Granjas Esmeralda
Delegacin Iztapalapa
09810 Mxico, D.F.
I
Nota del editor
COMPUTACIN l. Lgica. resolucin de problemas, algoritmos y programas es una obra naci-
da de la unin de dos textos para atender a las necesidades de la Universidad Nacional Abierta.
Dichos textos son los siguientes:
Tucker, A. B.; Bradley, W. 1.; Cupper, R. D., YGarnick, D. K.: Fundamentos de Informtica.
Lgica, resolucin de problemas, programas y computadoras. Madrid, McGraw-Hill. 1994.
Joyanes Aguilar, L.: Fundamentos de programacin. Algoritmos y estructura de datos. Madrid,
McGraw-Hill. 1996.
Se ha respetado el formato de ambas obras, de ah que el tamao y tipos de letra son distin-
tos. Asimismo, se ha mantenido la numeracin de los captulos de cada libro. Por ello, COMPU-
TACIN I. Lgica. resolucin de problemas, algoritmos y programas comienza en el Captulo 2,
contina hasta el Captulo 6 (correspondientes a la obra de Tucker y otros) y finaliza en los Ca-
ptulos 1 a 5 (pertenecientes al texto de Joyanes).
Madrid. octubre de 1999
vi
Contenido
Prlogo .
Nota del editor .
Captulo 2. Conjuntos y funciones .
2.1. Conjuntos .
2.1.1. Relaciones entre conjuntos: los diagramas de Venn .
2.1.2. Variables tipos y estados .
2.1.3. Operaciones entre conjuntos ..
2.1.4. Propiedades de las operaciones entre conjuntos ..
2).5 Conjuntos de cadenas de caracteres .
EJercIcIos .
2.2. Funciones .
2.2.1. Conceptos bsicos .
2.2.2. Funciones continuas y discretas .
2.2.3. Formas alternativas de definir funciones .
Ejercicios .
2.2.4. Funciones uno-a-uno y funciones inversas .
2.2.5. Funciones booleanas, enteras, exponenciales y logartmicas ..
2..2.6.. . Series finitas y funciones relacionadas .
EJerCICiOS .
2.3. Sumario .
Ejercicios .
Captulo 3. Lgica : .
3.1. Lgica proposicional .
3.1.1. Representaciones de frases en castellano utilizando la lgica proposicional .
3.1.2. Evaluacin de proposiciones: Tablas de verdad .
.. :::::::;::;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
3.2. Razonamiento con proposIcIOnes .
3.2.1. Equivalencia .
3.2.2. Propiedades de la equivalencia ..
3.2.3. Reglas de inferencia: La idea de demostracin .
3.2.4. Estrategias de demostracin .
3..2.5 Resolucin de problemas de la vida real .
EJercIcIos .
3.3. Lgica de predicados .
3.3.1. Los cuantificadores universal y existencial ..
3.3.2. Otros cuantificadores .
3.3.3. Variables libres y ligadas .
3.4. Predicados y programas .
3.4.1. El estado de un clculo ..
3.4.2. Cuantificadores y programacin: bucles .
3.5. Razonamiento con predicados: prueba por induccin ..
3.6.
Captulo 4. Problemas algortmicos y su solucin .
4.1. .. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
4.2. Definicin de problemas y descripcin de algoritmos .
4.2.1. Los estados inicial y final de un algoritmo: entrada y salida .
4.2.2. Los estados intermedios de un clculo: introduccin de variables .
v
vi
I
2
4
4
8
10
JI
13
15
16
18
20
22
24
28
34
33
38
38
41
41
44
47
51
52
54
54
55
58
61
65
66
69
71
76
76
77
77
78
81
86
86
89
90
93
93
93
95
vii
viii Contenido
4.3.
4.4.
4.5.
Captulo 5.
5.1.
5.2.
5.3.
5.4.
5.5.
5.6.
Captulo 6.
6.1.
6.2.
6.3.
6.4.
6.5.
6.6.
Captulo 1.
1.1.

4.3.1. Sintaxis y semntica .
4.3.2. Repeticin y bucles: inicializacin, invarianza y terminacin .
4..3.3 Tres visiones de la misma solucin al problema ..
EjercIcIos ,
Ms problemas algortmicos ..
4.4.1. Clculo de a" ..
4.4.2. Contar palabras de un texto .
I 4.4.3.. . Representacin del problema de Las Tres-en-Raya ..
EjercIcIOs .
Resumen .
Resolucin de problemas algortmicos .
Necesitamos una metodologa .
5.1.1. Generalidades sobre el mtodo MAPS ..
Construccin de software para su reutilizacin: la rutina ..
5.2.1. Encapsulamiento de rutinas para la reutilizacin. Abstraccin procedimental ..
5.2.2. Identificacin de rutinas nuevas y definicin de sus abstracciones ..
5.2.3. Funciones recursivas: Una alternativa a la repeticin ..
5.2.4. Aprendizaje de rutinas ya existentes: Bibliotecas y caractersticas de los lenguajes
5.2.5. Seleccin y reutilizacin de tipos de datos y estructuras ..
5.2.6. de,cadenas de ..
5.2.7 Tlpllcaclon fuerte y coerclOn .
EjerCICIos .
Resolucin de un problema utilizando la metodologa MAPS ..
5.3.1. El dilogo ..
5.3.2. Las especificaciones .
..
Definiciones de abstracciones: unificacin de rutinas viejas con ideas nuevas ..
5.4.1. Reutilizacin de rutinas ..
5.4.2. Utilizacin de la creatividad para disear nuevas rutinas ..
5.4.3. Utilizacin del conocimiento del dominio en el diseo de rutinas nuevas .
Terminacin del caso de estudio ..
5.5.1. Coditicacin ..
5.5.2. Prueba y veriticacin ..
5.5.3. Presentacin .
Resumen .
Ejercicios .
Robustez y prueba de los algoritmos .
.. .. .. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Resolucin de problemas de procesamiento de texto, utilizando MAPS: Criptografa ..
de problemas grticos utilizando MAPS: el Juego de la Vida .
EjerCICIOs .
Garanta de la robustez. Diseo de casos de prueba ..
6.4.1. Ejemplo: Prueba de un procedimiento o funcin completos ..
6.4.2. Ejemplo: Prueba de un programa completo .
Garanta de correccin: verificacin de programas ..
6.5.1. Tableau de demostracin .
6.5.2. La regla de inferencia de la asignacin ..
6.5.3. Reutilizacin de las reglas de inferencia de la lgica .
6.5.4. Reglas para las condicionales ..
6.5.5. Verificacin de bucles .
6.5.6. Verificacin formal frente a verificacin informal de programas ..
Resumen ..
Ejercicios .
Algoritmos y programas ..
Los sistemas de procesamiento de la informacin ..
97
98
100
103
108
111
112
113
116
121
126
130
131
131
132
134
134
140
144
146
147
149
150
152
156
156
158
159
161
162
163
166
167
169
169
171
171
173
174
177
178
182
182
187
196
196
197
202
203
203
206
209
209
212
216
217
218
221
222
Contenido
1.2. Concepto de algoritmo .
1.2.1. Caractersticas de los algoritmos .
1.3. Los lenguajes de programacin .
1.3.1. Instrucciones a la computadora .
1.3.2. Lenguajes mquina .
1.3.3. Lenguajes de bajo nivel .
1.304. Lenguajes de alto nivel .
1.3.5. Traductores de lenguaje .
\ 1.3.5.1. Intrpretes ..
1.3.5.2. Compiladores .
1.3.6. La compilacin y sus fases ..
lA. Datos, tipos de datos y operaciones primitivas ..
104.1 . Datos numricos .
104.2. Datos lgicos (booleanos) .
104.3. Datos tipo carcter y tipo cadena .
1.5. Constantes y variables .
1.6. Expresiones .
1.6.1. Expresiones aritmticas ..
1.6.1.1. Reglas de prioridad .
1.6.2. Expresiones lgicas (booleanas) .
1.6.2. l. Operadores de relacin ..
1.6.2.2. Operadores lgicos ..
. 1.?2.3. Prioridad de los operadores en las expresiones lgicas ..
1.7. FunClOnes mternas .
1.8.
1.8.2. Asignacin lgica .
1.8.3. Asignacin de cadenas de caracteres ..
1.804. Conversin de tipo ..
1.9. Entrada y salida de informacin ..
.. .. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Captulo 2. La resolucin de problemas con computadoras y las herramientas de programacin .
2.1. La resolucin de problemas .
2.2. Anlisis del problema .
2.3. Diseo del algoritmo .
2.3.1. Escritura inicial del algoritmo .
204. Resolucin del problema mediante computadora .
2.5. Representacin grfica de los algoritmos .
2.5.1. Diagramas de flujo ..
2.6. Diagramas de Nassi-Schneiderman (N-S) .
2.7. Pseudocdigo .
A.ctivid.ades de programacin resueltas .
EJercIcIOs .
Captulo 3. Estructura general de un programa .
3.1. Concepto de un programa .
3.2. Partes constitutivas de un programa .
3.3. Instrucciones y tipos de instrucciones .
304. Tipos de instrucciones .
304.1. Instrucciones de asignacin .
304.2. Instrucciones de lectura de datos (entrada) .
304.3. Instrucciones de escritura de resultados (salida) .
304.4. Instrucciones de bifurcacin .
3.5. Elementos bsicos de un programa .
3.5.1. Bucles ..
3.5.2. Contadores .
3.5.3. Acumulador .
3.504. Decisin o seleccin .
3.5.5. Interruptores .
ix
224
225
226
227
227
228
229
230
230
231
231
233
233
235
235
236
237
238
240
242
242
244
245
246
247
248
249
249
249
251
251
257
259
260
260
261
263
265
266
266
276
278
279
284
287
287
288
289
290
290
291
292
292
293
294
296
299
300
301
x Contenido
3.6. Escritura de algoritmos/programas
304
3.6.1. Cabecera del programa o algoritmo
304
3.6.2. Declaracin de variables
304
3.6.3. Declaracin de constantes numricas
305
3.6.4. Declaracin de constantes y variables carcter
305
3.6.5. Comentarios
306
3.6.6. Estilo de escritura de algoritmos/programas
307
de programacin resueltas .
308
EjercIcIOs
313
Captulo 4. Introduccin a la programacin estructurada
315
4. l. Tcnicas de programacin
316
4.2. Programacin modular
316
4.2.1. Tamao de los mdulos
317
4.2.2. Implementacin de los mdulos
318
4.3. Programacin estructurada
319
4.3.1. Recursos abstractos
319
4.3.2. Diseo descendente (top-down)
319
4.3.3. Teorema de la programacin estructurada: estructuras bsicas
320
4.4. Estructura secuencial
320
4.5. Estructuras selectivas
324
4.5.1. Alternativa simple (si-entonces / if-then)
324
4.5.2. Alternativa doble (si-entonces-si_no / if-then-else)
325
4.5.3. mltiple (segn-sea, caso de / case)
331
4.6. Estructuras repettttvas
337
4.6.1 . Estructura mientras (<<while)
340
4.6.2. Estructura repetir (<<repeab
345
4.6.3. Estructura desde/para (<<for)
348
4.6.4. Salidas internas de los bucles
352
4.7. Estructuras de decisin anidadas
358
4.8. Estructuras repetitivas anidadas
362
4.9. La instruccin ir_a (<<goto)
364
de programacin resueltas
365
EjercIcIOs
380
Referencias bibliogrficas
381
Captulo 5. Subprogramas (subalgoritmos): procedimientos y funciones
383
5.1. Introduccin a subalgoritmos o subprogramas
384
5.2. Funciones
386
5.2.1. Declaracin de funciones
387
5.2.2. Invocacin a las funciones
388
5.3. Procedimientos (subrutinas)
393
Sustitucin de argumentos/parmetros
394
5.4. Ambito: variables locales y globales
398
5.5. Comunicacin con subprogramas: pa<o de parmetros
401
5.5.1. Paso de parmetros
402
5.5.2. Paso por valor
403
5.5.3. Paso por referencia
404
5.5.4. Comparaciones de los mtodos de paso de parmetros
405
5.5.5: Sntesis de. la. transmisin de
407
5.6. FuncIOnes y procedimientos como parametros
410
5.7. Los efectos laterales
412
5.7.1. En procedimientos
412
5.7.2. En funciones
413
5.8. Recursin (recursividad)
414
A.ctiv.id.ades de programacin resueltas
417
EjercIcIos
422
CAPTULO 2
CONJUNTOS Y FUNCIONES
En este captulo introducimos las nociones matemticas bsicas sobre los con-
juntos y las funciones, junto con su notacin. Estas nociones son fundamenta-
les para la disciplina de la informtica. Ms adelante veremos cmo los con-
juntos y funciones se entremezclan con las nociones claves de la informtica y
su aplicacin. Estos conceptos y notaciones se utilizarn a lo largo de todo el
texto. (Algunos lectores encontrarn estas materias familiares. Sin embargo,
esta presentacin tiene como objetivo reorientar estas ideas, quiz familiares,
hacia aquellas partes de la informtica en que se utilizan.)
En qu forma se relacionan los conjuntos y funciones con la informtica?
Generalmente, podemos considerar un programa para una computadora,
como la realizacin de una funcin o como una correspondencia entre dos
conjuntos: la entrada del programa que representa un elemento particular del
dominio de la funcin, y la salida que representa el resultado de aplicar la
funcin a dicha entrada. Introduciremos esta idea en este captulo, ejercitndo-
la en las prcticas de laboratorio que le acompaan. En los Captulos 4, 5 Y6
afianzaremos este concepto, ejercitndonos en la programacin y mediante la
discusin exhaustiva de programas. Los conjuntos y las funciones estn tam-
bin ntimamente relacionados con la propia computadora como dispositivo.
As, podemos decir que una computadora es una mquina que realiza una fun-
cin determinada, cuando ejecuta un programa que realiza, paso a paso, dicha
funcin. Tambin se insiste en esta idea en las prcticas de laboratorio que
acompaan a este captulo. Tambin, en el Captulo 7, insistiremos sobre este
concepto al estudiar la estructura de las computadoras.
Algunos conjuntos son especialmente importantes para la programacin y
para las computadoras. Por ejemplo, los nmeros enteros y reales, los valores
booleanos, los caracteres que encontramos en el teclado de la computadora (el
conjunto de caracteres ASCII) y las cadenas * construidas con esos caracte-
* N. del T.: De las diversas traducciones que suelen realizarse de la palabra inglesa string,
hemos preferido la acepcin cadena o cadena de caracteres, que sern utilizadas de forma
indistinta.
2 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
res, representan conjuntos que son esenciales para la informtica; todos ellos
estn incluidos en los lenguajes de programacin y las computadoras moder-
nas. En este captulo estudiaremos la correspondencia que existe en programa-
cin entre estos conjuntos y el concepto de t i p o ~ ~ . Algunas funciones resultan
de vital importancia en programacin. Entre ellas se incluyen las funciones
discretas, la{> funciones exponenciales y logartmicas, y funciones que se repre-
sentan mediante series finitas.
Estudiaremos todas ellas en este captulo, poniendo especial inters en des-
tacar por qu son importantes para la informtica.
2.1. CONJUNTOS
En la vida cotidiana son corrientes las colecciones de objetos o nmeros.
Podemos pensar en la coleccin de personas de nuestra clase, la coleccin de
dgitos y letras de la matrcula de un automvil, o la coleccin de los nombres
de aerolneas que vuelan al aeropuerto 'Hare de Chicago. Estas colecciones,
en el lenguaje matemtico, reciben el nombre de conjuntos. Una descripcin
ms precisa la podemos realizar de la forma siguiente.
Definicin. Un conjunto es cualquier coleccin bien definida de objetos. A
menudo, los objetos que forman un conjunto comparten alguna caracters-
tica en comn. Un elemento de un conjunto es cualquiera de los objetos
que lo constituyen. Se dice que un elemento de un conjunto pertenece a
dicho conjunto. Si S es un conjunto que contiene el elemento x, para expre-
sar que x pertenece a S escribiremos x E S.
Una de las formas de describir un conjunto es encerrando los elementos que lo
componen entre corchetes {y}. Por ejemplo, el conjunto de los das laborables
de la semana se puede describir como:
{Lunes, Martes, Mircoles, Jueves, Viernes}
Las Ecuaciones 2.1 a 2.7 son otros ejemplos de definicin de conjuntos:
{O, 1, 2, 3,4, 5, 6, 7, 8, 9} es el conjunto cuyos elementos son los (2.1)
dgitos decimales.
{O, 1} es el conjunto de dgitos que se utiliza para escribir nmeros (2.2)
binarios.
{a, b, c, ..., z} es el conjunto de letras minsculas del alfabeto. (2.3)
{+, -, *, /} es el conjunto de las cuatro operaciones aritmticas (2.4)
ms importantes.
{1, 2, ... , 100} es el conjunto de nmeros enteros del 1 al 100, ambos (2.5)
inclusive.
Conjuntos y funciones 3
Notacin. Obsrvese la utilizacin de la coma y los puntos suspensivos.
Las comas separan elementos individuales del conjunto, mientras que los
puntos suspensivos (...) denotan la repeticin de un patrn claramente esta-
blecido, como ocurre en las Ecuaciones 2.3 y 2.5.
Tambin podemos definir un conjunto, estableciendo las propiedades que de-
btln satisfacer todos sus elementos, por ejemplo:
{xix es entero y 1 ~ x ~ lOO} (2.6)
Esta notacin requiere una variable al comienzo, una barra vertical y, al final,
una descripcin de los elementos. Con esta notacin, la Ecuacin 2.6 se lee el
conjunto de los x tales que x es un nmero entero entre 1 y 100, ambos
inclusive. Claramente, este ejemplo describe el mismo conjunto de la Ecua-
cin 2.5. La Ecuacin 2.7 es otro ejemplo de esta alternativa para la descrip-
cin de conjuntos:
{plp es un polinomio de grado 2} (2.7)
Ejemplos de elementos del conjunto definido por la Ecuacin 2.7 son los si-
guientes:
x
2
+ 2x + 1 .01n
2
- 100n - 3 SOOOy2 - 67
Algunos conjuntos tienen un nmero finito de elementos, mientras que otros
tienen un nmero infinito de ellos. Por ejemplo, los conjuntos definidos por las
Ecuaciones 2.1 a 2.6 son finitos, mientras el conjunto definido por la Ecua-
cin 2.7 es infinito.
Definicin. Se denomina cardinalidad de un conjunto al nmero de ele-
mentos del que consta. El conjunto vaco es aquel que no contiene ningn
elemento y, por tanto, su cardinalidad es O. El conjunto vaco se simboliza
por {} o por </>.
Por ejemplo, la cardinalidad del conjunto definido por la Ecuacin 2.3 es 26.
Existen cuatro conjuntos que tienen una importancia especial, tanto para la
informtica como para las matemticas:
N
Z
R
{O, 1, 2, 3, ... }
{... , -3, -2, -1, 0,1,2,3, oo.}
{xl- infinito < x < +infinito}
{O, 1, 2, ..., n - 1}
nmero naturales
los enteros
los nmeros reales
los enteros mdulos n
4 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
Los tres primeros son infinitos, mientras que el ltimo es finito y tiene cardina-
lidad n. Por ejemplo, el conjunto Z2 = {O, 1} tiene cardinalidad 2; el conjunto
Z10 = {O, 1, ..., 9} tiene cardinalidad 10.
2.1.1. Relaciones entre conjuntos: los diagramas de Venn
El orden en 'que aparecen enumerados los elementos de un conjunto no tiene
especial relevancia; adems, la duplicidad de elementos es redundante. Es decir,
{a, b, e} y {b, a, e, a} representan el mismo conjunto.
Es bastante habitual que los elementos de un conjunto sean tambin miem-
bros de otro diferentes. Por ejemplo, todos los elementos del conjunto V =
= {a, e, i, o, u} son tambin elementos del conjunto L = {a, b, '00' z}. La
definicin siguiente sirve para formalizar estos conceptos:
Definicin. Si dos conjuntos A y B contienen los mismos elementos, se dice
que son iguales y se simboliza escribiendo A = B. Si todos y cada uno de
los elementos de A tambin lo son de B, y se simboliza por A e B. Si A es
un subconjunto de B, decimos que B es un superconjunto de A y se simboliza
por A ::J B. Si se verifica que A i= B, Yadems A e B, entonces se dice que
A es un subconjunto propio de B. Si todos los elementos de un conjunto o de
una coleccin de conjuntos se obtienen de un conjunto comn, a este con-
junto se le denomina conjunto universal.
Obsrvese la diferencia que existe entre elemento y subconjunto. Por ejemplo,
sea A = {O, 1, 2, 3, 4, 5, 6, 7}. Entonces el dgito O es un elemento de A
(simbolizado por OE A), yel conjunto {O} es un subconjunto de A (y se denota
por {O} e A). Sera incorrecto decir que Oes un subconjunto de A, puesto que
no es un conjunto. De forma anloga, sera incorrecto decir que {O} es un
elemento de A.
Frecuentemente, se representan los conjuntos utilizando diagramas de
Venn (vase Fig. 2.1). Un diagrama de Venn es un dibujo en el que los conjun-
tos se representan como crculos etiquetados, dentro de una caja rectangular,
que representa el conjunto universal del que se dibujan los elementos.
2.1.2. Variables tipos y estados
Dos nociones fundamentales de la informtica son las de variable y estado.
Una variable es un mecanismo de notacin que se toma prestado de las mate-
mticas, que permite representar ideas complejas mediante un simple smbolo,
y que aporta concisin y precisin. Frecuentemente, leemos frases como: Re-
presentemos mediante x una letra del alfabeto. A continuacin, podemos
utilizar el smbolo x y entender de forma precisa lo que significa, puesto que se
ha definido anteriormente el smbolo, para representar la nocin de cualquier
elemento del conjunto L = {a, b, oo., z}. Cuando se utiliza de esta forma, x
recibe el nombre de variable, puesto que su valor puede variar entre diversas
alternativas (26 para ser exactos).
Conjuntos y funciones 5
al
bl
Figura 2.1. Diagramas de Venn. a) Dos conjuntos A y B que pueden
tener varios elementos comunes. b) La relacin A e B.
Definicin. Una variable es un smbolo que se asocia con un valor simple,
que de hecho puede ser un elemento de un conjunto bien definido. A lo
largo de los pasos que implican un clculo, el valor de una variable puede
cambiar de ser uno de los miembros del conjunto a ser otro distinto. El
conjunto sobre el que se define una variable recibe el nombre de tipo de la
variable.
Por ejemplo, la variable x que se ha definido anteriormente es del tipo L (o de
manera informal, del tipo letra).
Otra nocin fundamental en la informtica es la de estado. Por ejemplo, un
programa que juegue al ajedrez tiene muchos estados posibles -uno por cada
posible colocacin de las piezas sobre el tablero-o Un programa grfico debe
controlar millones de pixels [puntos de una pantalla de un monitor, cada
uno de los cuales puede estar iluminado (on) o no iluminado (ofl)]. Su estado,
en cada momento, es el valor on u off que tienen el milln de pixels. La nocin
de estado se puede definir ms formalmente de la forma siguiente:
Definicin. Supongamos que tenemos una lista de variables Xl' X
2
' .oo, X
n
cuyos tipos estn definidos por los conjuntos 51' 52' oo., Sm respectivamente.
6 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Supngase que el valor de Xl es SI E SI' el valor de X
2
es S2 E S2' y as
sucesivamente. Entonces se dice que la expresin
representa el estado de las variables xl' X
2
, ... , X
w
El conjunto de todos los
estados postbles de Xl' X
2
, ... , X
n
recibe el nombre espacio de estados de esas
variables.
Esta importante nocin se ilustra en los Ejemplos del 2.1 al 2.3:
Ejemplo 2.1. Supongamos que un programa de computadora tiene dos
variables i y j, utilizadas como contadores. Ambas tienen como tipo el
conjunto de los nmeros naturales. El estado inicial del programa podra
ser:
i=O y j=O
Un estado posterior podra ser
i=5 Y j=6
Ejemplo 2.2. Si los pixels controlados por un programa son Xl' X
2
' ...,
XIOOOOOO, un estado de ese programa tendra 1 milln de entradas, una por
cada variable. Por ejemplo, la expresin
Xl = on y X
2
= off y
describe un posible estado del programa.
y XIOOOOOO
on
Ejemplo 2.3. Considrese un programa con tres variables, las tres del tipo
rea l (la analoga en programacin al conjunto R). Tres posibles estados
de este programa son:
X O e y 0, junto con z =

X
-3,1 e
y J2 junto con z = 1
-1
n.
1789
X = e y "2 Junto con z
Frecuentemente, es de gran ayuda visualizar el estado de un programa,
como puntos del espacio. Por ejemplo, los puntos de la Figura 2.2 estn repre-
sentados los dos estados del Ejemplo 2.1. La grfica tridimensional de la Figu-
ra 2.2b representa el espacio estado del Ejemplo 2.3, donde se ha marcado el
punto correspondiente a uno de los estados del programa. Cuando en un
programa las variables cambian de estado, el efecto que se produce es como si
nos desplazramos de un punto a otro del espacio de estados.
2 3 4 5 6
a)
7

51--+--+......,f-+--+-+--I
41--t--+-+-+-+-+--;
31--+--+""",'--+--+-+--1
21-+--+---1'--+--+-+--1
o t-Jf-+-+-+--+-t-+--
- 1 L..-.J----L_.1.--L---J,_.L---.J
-1 O
z
Conjuntos y funciones 7
y
.;.- x
b)
Figura 2.2. Representacin grfica del estado de un programa.
al Dos estados del espacio de estados del Ejemplo 2.1. bl Un
estado del espacio de estados del Ejemplo 2.3.
Considrese un programa con tres variables reales z, x e y (variable rea l
significa lo mismo que variable del tipo rea l). Supngase que el programa
contiene una instruccin de la forma
x:= 1.0
Esta instruccin asigna el valor de 1.0 a la variable x. Si no se ha realizado
ninguna restriccin sobre las otras dos variables z e y, todo el plano x = 1 es el
conjunto de posibles estados de este programa, despus de que se ejecute la
asignacin (vase la Figura 2.3).
y
/1
/ I
I
I
I
I
;-+----x
z
Figura 2.3. El estado x = 1 en un programa
con tres variables reales z, x e y.
8 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
2.1.3. Operaciones entre conjuntos
Considrense los conjuntos siguientes:
s {O, 1, 01, 10, 11, OO}
T {l, 10, 100, 1000, 10000}
\
Los nmeros 1 y 10 son los nicos elementos que pertenecen a ambos conjun-
tos, pero existen entre S y T otros nueve elementos diferentes. Los conceptos de
interseccin, unin y diferencia de conjuntos nos ayudan a describir en diferen-
tes maneras la existencia de elementos comunes entre conjuntos.
Definicin. Sean A y B dos conjuntos. La unin de A y B simbolizada por
A u B, es aquel conjunto cuyos elementos pertenecen como mnimo a uno
de los dos conjuntos, A o B. La interseccin de A y B, simbolizada por A (\ B,
es el conjunto que incluye aquellos elementos que pertenecen tanto a A como
a B. La diferencia (o complemento relativo) de A y B, simbolizado por A \ B, es
el conjunto que contiene aquellos elementos que estn en A, pero no en B.
La Figura 2.4 representa tres diagramas de Venn, en los que las reas
sombreadas representan la unin, la interseccin y la diferencia.
b)
e)
Figura 2.4. Diagramas de Venn: a) Unin. b) Interseccin. e) Diferencia de dos
conjuntos A y 8.
Conjuntos V funciones 9
Es posible escribir algunos ejemplos adicionales, utilizando la notacin de
conjuntos. Sean a = {1, 3, 5, 7, 9}, YB = {- 3, - 1, 1, 3, 5}. Las relaciones
siguientes son ciertas:
AnB
A u B
A \ B
{1, 3, 5}
{-3, -1,1,3,5,7, 9}
p, 9}
Como ejemplo adicional, supngase que
A = {plp es un polinomio de la forma n2 + bn, donde b es una constante real}
B = {plp es un polinomio de la forma n
2
+ e, donde e es una constante real}
Dos posibles elementos del conjunto A seran n
2
+ n y n
2
+ 4,5n, mientras que
del B seran n
2
- 3 Yn
2
+ 7. Las siguientes relaciones son ciertas:
AnB
AuB
A \ B
{n
2
}
{plp es un polinomio de la forma n
2
+ bn + e,
donde b = O o e = O}
{plp es un polinomio de la forma n
2
+ bn, donde b "# O}
El conjunto vaco <p es extremadamente til. Por ejemplo, si e es el conjun-
to de consonantes (excluida la y), y V el conjunto de vocales (incluida la y),
entonces e n V no contiene elementos.
Definicin. Decimos que dos conjuntos son disjuntos si su interseccin es
el conjunto vaco.
Definicin. El complementario de un conjunto S es aquel conjunto Si al
que pertenecen todos los elementos del conjunto universal U, que no per-
tenecen aS.
Por ejemplo, si e y S representan el conjunto de consonantes y vocales, respec-
tivamente, y U es el alfabeto completo, entonces C' = V YV' = C. Es decir,
todas las letras que no son consonantes son vocales y viceversa. (Se ha supues-
to que la letra y es una vocal). La Figura 2.5 ilustra los conceptos de conjuntos
disjuntos y complementarios utilizando diagramas de Venn.
Ejemplo 2.4. Supongamos que x e y son enteros. Sea S el espacio de
estados compuesto por todos los posibles pares de enteros (x, y). Si defini-
mos los conjuntos A = {(x, y)lx ;?; Oe y ;?; O}, YB = {(x, y)lx < Oe y < O},
entonces A y B son disjuntos. Esto se ilustra en la Figura 2.6, donde las
reas sombreadas representan los conjuntos A y B. Obsrvese que B "# A'
puesto que A' = {(x, y Jlx < Oo y < O}.
10 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
al bl
Figura 2.5. Representacin mediante diagramas de Venn de:
al Conjuntos disjuntos. bl Conjuntos complementarios.
x
Figura 2.6. Conjuntos disjuntos.
2.1.4. Propiedades de las operaciones entre conjuntos
Las operaciones aritmticas entre nmeros tienen determinadas propiedades,
como asociatividad, conmutatividad, inversa, y as sucesivamente. Hacemos
uso de estas propiedades, de forma casi automtica, cuando simplificamos
ecuaciones algebraicas. Los conjuntos y sus operaciones tienen propiedades
similares, y las podemos utilizar para simplificar operaciones complejas entre
conjuntos. Las principales propiedades de las operaciones entre conjuntos se
resumen en la Tabla 2.1.
Conjuntos y funciones 11
Tabla 2.1. Propiedades y operaciones de los conjuntos. (A y B son conjuntos;
U es el conjunto universal sobre el que estn definidos A y B)
Conmutatividad
AnB==BnA
AuB==BuA
\ Asociatividad
A n (B n C) == (A n B) n C
A u (B u C) == (A u B) u C
Distributividad
A n (B u C) == (A n B) u (A n C)
A u (B n C) == (A u B) n (A u C)
Leyes de Morgan
(A n B)' == A' u B'
(A u B)' == A' n B'
Propiedad de la negacin
(A')' == A
Ley de exclusin del trmino medio
A u A' == U
Ley de la contradiccin
A n A' == <p
u -simplificacin
A uA == A
Au<p==A
AuV==V
n-simplificacin
A nA == A
AnV==A
An<p==<p
Complementariedad
V' <p
<P' == V
2.1.5. Conjuntos de cadenas de caracteres
El tipo s tri ng (cadena de caracteres) * es muy importante en informtica.
Informalmente, puede definirse una cadena como una secuencia de elemen-
tos contiguos, pertenecientes todos a un conjunto universal conocido como
alfabeto. A continuacin, se pueden ver algunos ejemplos de conjuntos cuyos
elementos son cadenas de caracteres.
Ejemplo 2.5. El conjunto {aa, ab, ba, bb} es el conjunto de todas
las posibles cadenas de dos elementos, construidas a partir del alfabeto
{a, b}.
* N. del T.: El tipo string es un tipo caracterstico de la mayora de los lenguajes de
programacin modernos. Sin embargo, al tratarse de un captulo dedicado a los conjuntos, tradu-
ciremos el trmino string al castellano. En captulos posteriores, en los que aparece el tipo como
perteneciente a un lenguaje de programacin, dejaremos el trmino sin traducir.
12 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Ejemplo 2.6. M = {abe, acb, bae, bca, eab, eba} es el conjunto
formado por todas las posibles colocaciones o permutaciones de las tres
letras a, b Y e. Obsrvese que existen seis permutaciones distintas.
Ejemplo 2.7. S = {O, 1,01,001, 100, 0100} es un conjunto de cadenas del
alfabeto {O, 1}. Existen otras muchas cadenas obtenidas de este alfabeto,
tales como {l, 10, 100, 1000, 10000}, Ylos propios {O, 1}. Es posible estable-
cer restricc'iones a las cadenas. Por ejemplo, el conjunto {O, 1,01, 10, 11, OO}
es el conjunto de todas las cadenas del alfabeto {O, 1} que tienen longitud
1 2.
Ejemplo 2.8. F = {abed, abdc, aebd, aedb, adbe, adeb, baed,
bade, bead, beda, bdae, bdea, eabd, eadb, ebad, ebda,
edab, edba, dabe, daeb, dbae, dbea, deab, deba} es el conjun-
to de todas las permutaciones de las letras a, b y c. Esto puede escribirse
alternativamente como F = {plp es una permutacin de abed}. Obsrvese
que existen 24 permutaciones distintas.
Ejemplo 2.9. Si A = {sls es una cadena sobre {O, 1} que comienza por 1},
entonces A' = {E} U {sls es una cadena sobre {O, 1} que comienza por 1}.
En este caso, el smbolo E simboliza la cadena vaca que no contiene ningn
carcter. La notacin {E} significa el conjunto que tiene un solo elemen-
to, que es la cadena vaca. El conjunto vaco <p, por el contrario, no
contiene ninguna cadena.
Ejemplo 2.10. Sea D el conjunto formado por todas las permutaciones de
abed, que terminan en d. Entonces D = { abed, aebd, bacd, bead,
cabd, ebad}. Si N = {plp es una permutacin de abed}, entonces D es
un subconjunto propio de N, por lo que la interseccin de D y N es el
propio conjunto D y la unin entre D y N es N.
Ejemplo 2.11. Sea U = {ulu es cualquier cadena sobre el alfabeto {O, 1},
incluida la cadena vaca E}. Entonces U es el conjunto universal de varios
conjuntos definidos sobre el mismo alfabeto, tales como S = {E, 0,1,00,01,
10, 11} YT = {O, 01, 001, 0001, oO.}. Obsrvese que ni S es subconjunto de T,
ni T lo es de S. En la mayora de los casos, el conjunto universal sobre el
que se definen conjuntos de cadenas particulares es tan evidente que no
suele mencionarse explcitamente.
Ejemplo 2.12. Supngase que tenemos los dos conjuntos de cadenas si-
guientes:
A {plp es una permutacin de la cadena abed,
que comienza por a}
{abed, abdc, acbd, aedb,adbe, adcb}
Conjuntos y funciones 13
D {plp es una permutacin de la cadena abcd que termina en d}
{abcd, acbd, bacd, bcad, cabd, cbad}
Entonces las operaciones interseccin, unin y complemento relativo dan
origen a las cadenas siguientes:
AnD
AuD
A \ D
{abcd, acbd}
{abcd, abdc, acbd, acdb, adbc, adcb, bacd,
bcad, cabd, cbad}
{abdc, acdb, adbc, adcb}
Obsrvese que tanto A como D tienen seis miembros, mientras que A u B
tiene diez miembros, puesto que abcd y acbd son elementos de ambos
conjuntos.
Ejercicios
2.1. Supongamos que i = 1 Yj = 1 es el estado inicial. Describir el estado al
que se llega despus de realizar cada una de las asignaciones de los
apartados a) al e). Hacer una representacin bidimensional del plano
xy, y dibujar el punto que corresponde al estado inicial y a los distintos
estados a que conducen las asignaciones de los apartados a) al e).
a)
;
:= 2;
j
.-
; ;
b)
;
.-
;
+ 1;
j .- j + 2;
e) j .- j +
1 .
r
;
.- i +
1 .
r
j .- j +
; .
r
2.2. Expresar en notacin de conjunto los descritos mediante las frases si-
guientes:
a) Las cadenas sobre el alfabeto {O, 1} de longitud menor o igual que
5, que contengan uno o dos ceros.
b) Los enteros pares.
e) El conjunto de todas las cadenas sobre el alfabeto {a, b, e} que
no contengan smbolos duplicados.
d) El conjunto de todas las permutaciones de la cadena 012.
e) El conjunto de todos los polinomios de grado 3 menor que ten-
gan a x como un factor.
14 Computacin /. Lgica, resolucin de problemas, algoritmos y programas
2.3. SeaA = {(x, y)lx ~ e y ~ O} YB = {(x, y)lx ~ 1 e y ~ 1}. Identificar
cada uno de los conjuntos siguientes sobre el plano xy, sombreando el
rea apropiada.
a) A n B
b) A u B
e) A \ B
d) B ~ A
e) A'
2.4. Supngase que s y t son cadenas sobre el alfabeto {a, b, ..., z}. Es posible
definir eoneat (s, t> como la cadena que resulta de poner t a conti-
nuacin de s (concatenar). Por ejemplo, si s = abe y t = xy, entonces
eoneat(s,t) = abexy. Del mismo modo, si S y Tson conjuntos de
este tipo de cadenas, podemos definir eoneat (S, T) como el conjunto
de todas las cadenas, que resultan de concatenar una cadena arbitraria s
de S, y otra t de T. Supongamos, por ejemplo, que S = {e, x, xy,
xyy}, y T = {e, y, yx, yxx}. Se pide encontrar cada uno de los
conjuntos siguientes:
a) eoneat (S, T>
b) eoneat(T,S)
e) S u T
d) S n T
e) S \ T
f) T \ S
2.5. Supongamos que S y T son conjuntos de cadenas. Encontrar dos ejem-
plos de parejas S y T, tales que eoneat(S, T> = S u T.
2.6. Dibujar un diagrama de Venn para los conjuntos A y B, Ysombrear las
partes correspondientes a los conjuntos siguientes:
a) (A' n B') u (A n B)
b) (A u BY u (A \ B)
2.7. Cuntas cadenas de longitud 2 menor existen sobre el alfabeto (O, I)?
2.8. Decir cules de las afirmaciones siguientes son verdaderas y cules
falsas.
a) {2, 3, 4} u {2, 4, 5, 6} = {2, 3,4, 5, 6}
b) {2, 3, 5} n {2, 4, 5, 6} e {2, 3, 6}
e) {3, 4, 6, 8} \ {2, 4, 7, 8} ::J {3}
d) (<(> n {3, 5, 7, 8}) u {3, 7} = {3, 5, 7, 8}
e) {2, 3, 5} = {5, 2, 3, 2}
f) {2, 4, 5} e {I, 2, 4, 5, 6}
g) {3, 4, 5} e {I, 2,4, 5, 6}
h) {I, 2, 6} ::J {I, 2,4,5, 6}
i) > e {2, 5}
Conjuntos y funciones 15
2.9. Supngase que:
S {1, 2, 3, 4, 5}
T {xlO < x < 10 Y x es impar}
U Z16
\ Escribir el conjunto de elementos de los conjuntos siguientes:
a) S n T
b) (S u T)'
e) (S u T) \ S
2.10. Los conjuntos siguientes se han definido en forma de reglas. Reescribir
las definiciones en forma de lista de elementos.
a) {xix E N, x ::::; 10, Yx es par}
b) {plp es una permutacin de la cadena 012}
2.2. FUNCIONES
Un concepto fundamental para la informtica es el de funcin. En su forma
ms simple, unafunein es una tabla con dos columnas que indican una corres-
pondencia entre los valores de la primera columna y los de la segunda.
Ejemplo 2.13. Considrese la tabla siguiente.
1 2
2 5
3 10
4 17
Esta es una funcin que relaciona los enteros de la primera columna con
los correspondientes de la segunda. Si quisiramos extender la funcin, no
sera dificil deducir que la quinta fila constara de los pares 5 y 26. Es decir,
existe un criterio, sugerido por las cuatro filas de la funcin, que permite
generalizarla para cualquier nmero de valores.
Ejemplo 2.14. La tabla siguiente es ligeramente diferente:
1 2
2 5
1 7
3 2
2 6
16 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
Puesto que en la columna de la derecha aparecen nmeros duplicados, esta
tabla no parece representar una relacin estable y fiable. Parece no ajustar-
se a ninguna regla gracias a la cual, a partir de un valor de la izquierda,
pueda calcularse el de la derecha.
Los valores no-ambiguos -es decir, que a cada valor de la primera columna lc
correspondA uno de la segunda-, son bsicos para la idea de funcin.
La Figura 2.7 muestra dos funciones ms, en este caso utilizando un grfico
en lugar de una tabla. Obsrvese que en la Figura 2.7a cada valor de x se
corresponde con uno de y, y de la misma forma, cada uno de y se corresponde
con uno de x. En la Figura 2.7b cada x se corresponde con uno de y; sin
embargo, para un mismo y existen ms de un valor de x. Para poder trabajar
con funciones es necesario definir el concepto de forma ms precisa. Clarifique-
mos algunas de las ideas acerca de la correspondencia presentadas en los
ejemplos.
y
a)
y
b)
x
Figura 2.7. Dos representaciones grficas de funciones: al Cada x se corres-
ponde con un y. bl Cada x se corresponde con una y, pero una misma y se
corresponde con varias x.
2.2.1. Conceptos bsicos
Una funcin siempre se define utilizando dos conjuntos.
Definicin. Sean X e Y conjuntos. La notacin (x, y) donde x E X e y E Y,
recibe el nombre de par ordenado. El producto cartesiano de X e Y, simboli-
zado por X x Y, es el conjunto {(x, y)lx E X e y E Y}. Es decir, X x Yes el
conjunto de todos los pares ordenados (x, y) que verifican que x E Xe y E Y.
Conjuntos y funciones 17
Ejemplo 2.15. Sea X = Y = R. Entonces, X x Yes el sistema y coordena-
das xy que se muestra en la Figura 2.8a. Si 1 = J = Z, entonces 1 x J es el
conjunto de todos los puntos del plano cartesiano, cuyas coordenadas son
enteras. Los puntos de 1 x J son las intersecciones de las lneas verticales y
horizontales de la Figura 2.8b.
y
al
7
6
5
4
3
x
2
O
-1
-1 O 2 3 4 5 6
b)
Figura 2.8. Representacin grfica de: a) El producto cartesiano
de reales. b) El producto cartesiano de enteros.
Una funcin es un caso particular de producto cartesiano, es un conjunto de
pares en el que dos elementos distintos no pueden tener igual el primer elemen-
to del par. De una manera formal, una funcin puede definirse.
Definicin. Sean X e Y dos conjuntos. Una funcin es un subconjunto f de
X x Y, tal que cada x E X se encuentra emparejado con uno, y slo un
elemento y E Y. El conjunto X recibe el nombre de dominio de la funcin!, e
y el de rango de f
En el contexto de una representacin tabular de las funciones podemos pensar
en el dominio como en la primera columna de la tabla, y en el rango como en
la segunda. La propia funcin es la correspondencia que existe entre los nme-
ros de las dos columnas. De una forma similar, cuando observamos una repre-
sentacin grfica de una funcin, se puede identificar el eje x como el dominio
y el y como el rango, y la funcin con el conjunto de pares (x, y) que constitu-
yen la grfica (por ejemplo, como se muestra en la Figura 2.7). En cualquier
caso, la nocin de que cada valor x slo puede tener un y asociado, resalta el
concepto de dependencia o estabilidad de la correspondencia.
18 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Ejemplo 2.16. Supongamos que X = {l, 2, 3, 4} e Y = {2, 4, 6, 8}.
Supongamos tambin que tenemos el conjunto de pares f = {(l, 2),
(2,4), (3, 6), (4, 8)}. Entonces f es una funcin; el conjunto {l, 2, 3, 4} es el
dominio; y {2, 4, 6, 8} su rango. Obsrvese que para cada x E X existe un
nico y E Y emparejado con l. Obsrvese tambin que esta corresponden-
cia particular puede representarse mediante la regla y = 2x.
\
Supongamos de nuevo que X = {l, 2, 3, 4}, Yconsidrese el conjunto g = {(1,2),
(2, 4), (3, 6)}. En este caso, g no es una funcin con dominio X, puesto que
existen elementos de X para los que g no est definida. Aquellos conjuntos que
tienen todas las propiedades de las funciones, pero que no estn definidas
sobre todo el dominio, reciben el nombre de funciones parciales. Las funciones
parciales se utilizan a menudo en la informtica.
Aunque una funcin exige que cada x del dominio tenga un valor del
rango, y asociado con l, no es necesario que cada valor y del rango correspon-
da a un x. Por ejemplo, si X = Y = {l, 2, 3, 4}, Ydefinimos la funcin y = 4
para todo valor de X, entonces los valores 1, 2 Y 3 no se corresponden con
ninguno de X. Finalmente, sea h = {(l, 2), (2, 4), (3, 6), (1, 8), (4, lO)}. El
conjunto h no es tampoco una funcin, puesto que existe un valor de x que se
corresponde con dos valores distintos de y.
Los trminos siguientes suelen utilizarse al referirnos a funciones.
Definicin. Seafuna funcin con dominio X y rango Y. Se suele simbolizar
esta relacin como f: X ~ Y. Cuando se han especificado el dominio y el
rango, escribimos y = f(x) para simbolizar la relacin que f representa
entre cada elemento del dominio X, y el correspondiente del rango Y. En
esta notacin, x recibe el nombre de variable independiente. El conjunto de
pares {(x, f(x))lx E X Yf(x) E Y) se utiliza para definir la grfica de la
funcin!
Ejemplo 2.17. Si X = Y = R e y = f(x) = 2x - 1, x es la variable inde-
pendiente, e y es la dependiente. La grfica def se muestra en la Figura 2.9.
2.2.2. Funciones continuas y discretas
Las funciones suelen caracterizarse dependiendo de si pueden visualizarse me-
diante una linea continua o no. Si no es posible, la funcin tiene huecos en
su representacin en el plano xy, y recibe el nombre de funcin discreta.
Ejemplo 2.18. Sea X = Y = R. La funcin valor absoluto, dada por y = Ixl
puede definirse mediante la regla
Ixl x cuando x ? O
- x cuando x < O
Conjuntos y funciones 19
________.......,.... x
Figura 2.9. Grfica de la funcin ((x) 2x - 1.
La Figura 2.10a muestra la grfica de y = Ixl cuando el dominio y el rango
de la funcin es R (dando origen a una funcin continua). Si X = Y = Z, la
funcin es ligeramente diferente, como se muestra en la Figura 2.10b (una
funcin discreta).
(0,0)
------+------x
y
-----IlI'-----x
(0,0)
(-3,3)
(-2,2).
(-1,1)
y
.(3,3)
(2,2)
(1,1)
a) b)
Figura 2.10. Grfica de y = IxI. a) Una funcin continua. b) Funcin discreta.
Ejemplo 2.19. Lafuncin suelo l_x_lse define como el mayor entero menor
o igual que x. Esta funcin tiene como dominio a R y como rango a Z. Por
tanto, si x = n.dd
1
d
3
... (donde n es un entero y di cualquier dgito), enton-
ces l_x_1 = n cuando x ~ 0, o x es un entero, y l_x_1 = n - 1 en caso
contrario. Por tanto, para nmeros reales positivos, la funcin l_x_1 es el
20 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
resultado de eliminar la parte decimal de x, y para nmeros reales negati-
vos que no sean ya enteros, l_x_1 es el resultado de eliminar la parte deci-
mal y restarle uno. La grfica de esta funcin se muestra en la Figura 2.11.
Una funcin muy relacionada es la funcin techo I-x-j que se define como el
menor entero mayor o igual que x. Se calcula eliminando la parte decimal
de x, yIsi x no fuera entero, sumndole uno. Las funciones suelo y techo
tambin se conocen como funciones mayor entero y menor entero, respecti-
vamente.
La funcin valor absoluto puede calcularse en Pascal, directamente, utili-
zando la expresin abs (x), donde x puede ser una variable o expresin del
tipo rea lo; ntege r. Sin embargo, las funciones suelo y techo no tienen una
analoga exacta en Pascal. La funcin ms prxima es la funcin t runC< x)
que convierte cualquier variable o expresin de tipo rea l en integer eliminan-
do los decimales. Por tanto, trunc(3.14) = 3,ytrunC<-3.14) = -3.
2.2.3. Formas alternativas de definir funciones
Hemos visto cmo se pueden definir funciones utilizando una frmula, una
grfica xy, una tabla de dos columnas y un conjunto de pares ordenados. Las
funciones pueden definirse de varias formas alternativas.
Definicin recursiva de funciones. Algunas veces es conveniente definir las
funciones en trminos de s mismas. Esta capacidad de autorreferenciarse reci-
be el nombre de recursin, y las funciones as definidas reciben el nombre de
funciones recursivas.
y

,
I
, ,
:-2 '-1 O
,
1 '2 :3
x
Figura 2.11. La funcin suelo I_x_l.
Conjuntos y funciones 21
Ejemplo 2.20. Supongamos X = Y = N, Yque la funcinf(n) se define de
la forma siguiente:
f(n) 1
3 + f(n - 1)
cuando
cuando
n-O
n > O
\ Con la definicin conocemos un valor inicial para la funcin; es decir, su
valor cuando x = o. Mientras conozcamos cmo se puede calcular cada
valor de f a partir del anterior, no es necesario que conozcamos una regla
explcita para calcular f(n) directamente. Es decir, el valor de f(n) pue-
de calcularse aplicando reiteradas veces la relacin de recurrencia a valo-
res crecientes de n, comenzando por n = o. Por tanto, primero calculamos
f(O) = 1, despus lo utilizamos para calcular f(l) = 3 + f(O). Esto puede
hacerse repetidas veces, obtenindose la tabla siguiente:
n f(n)
~ _ . _ ~
O 1
1 4
2 7
3 10
En algunas ocasiones es fcil deducir una frmula no-recursiva para calcu-
lar f(n) a partir de la recursiva, y en otros casos es muy dificil. Por ejemplo,
el caso del Ejemplo 2.20 es relativamente senciJIo, extrayendo el criterio de
la tabla para obtener la frmula equivalente f(n) = 3n + 1.
Ejemplo 2.21. Considrese la funcin recursiva:
f(n) = O
= 1
= f(n - 1) + f(n - 2)
cuando
cuando
cuando
n-O
n - 1
n > 1
Aplicando reiteradas veces la relacin de recurrencia se puede obtener la tabla:
n f(n)
O O
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
22 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
Esta funcin recibe el nombre de serie de Fibonacci. Es una funcin de gran
utilidad en diversas reas de las matemticas aplicadas. Sin embargo, es
dificil, sin un conocimiento ms profundo de las matemticas, encontrar
una forma de la funcin que la calcule directamente para cualquier valor
de n.
\
Utilizacin de un programa para definir una funcin. Las funciones pueden
definirse tambin utilizando un programa de computadora en el cual se descri-
ba cmo puede calcularse un valor de rango, utilizando un valor predetermi-
nado del dominio. Formalmente, un programa de estas caractersticas recibe el
nombre de algoritmo. La construccin de algoritmos computacionales para
una gran variedad de funciones es el objetivo de los Captulos 4 al 6.
Ejemplo 2.22. Podemos definir un algoritmo como un conjunto bien defi-
nido de pasos, que transforman una entrada (de un conjunto de entradas
disponibles) en la salida correspondiente. Es decir, describe cmo calcular
el valor de una funcinf(x) para cada valor particular x del dominio. Por
ejemplo, la secuencia siguiente es un algoritmo (escrito en lenguaje Pascal)
que calcula los valores de la funcin n = Hog2n-l, donde x es un nmero
real arbitrario, mayor o igual que 1. En este caso, el valor de x es la entrada
del algoritmo, y el de n la salida de la funcin.
read(x);
n := o;
whi le x >= 1.0 do
begin
x:=x/2.0;
n := n + 1
end;
Cuando se utiliza un algoritmo para calcular una funcin, el conjunto de
entradas permitidas (en este caso R) se corresponde con el dominio de la
funcin; el conjunto de salidas (en este caso N) se corresponde con el rango; y
los pasos de que consta definen procedimentalmente la correspondencia exis-
tente entre cada valor del dominio y el correspondiente del rango. Otras for-
mas de definir funciones (vase Ejemplo 1.11) no describen ningn proceso
particular, mediante el cual pueda calcularse la funcin. Los programas con-
trolan el proceso.
Ejercicios
2.11. Cules de los conjuntos de pares ordenadores siguientes son funciones?
a) {(1, 1), (1, n), (1, lOO)}
b) {el, 1),(3,7),(5,13),(4, 19)}
e) {( - 1, 1), (O, 1), (1, 1), (1, 1), (3, l)}
Conjuntos y funciones 23
d) {(x, y)lx ~ e y = x}
e) {(l, a), (2, b), (3, a), (4, b), (5, e)}
f) {(l, a), (2, b), (1, e), (2, d), (3, e)}
g) {(l, e), (2, d), (3, e), (4, b), (5, a)}
2.12. Determinar el dominio y el rango de cada una de las funciones siguien-
tes:
a) h(x) = x mod 17, para x = 0, 16, 17, 32 Y 69. (La funcin mod
calcula el resto entero que resulta de la divisin del primer argu-
mento por el segundo.)
b) b(x) = (-1:::;; x :::;; 10), para x = -2, -1,0,10 Y15.
e) l_x_1 para x = 10, n, y -1,5.
n
d) Ixl para x = -1,0,1, -49,5 Y6".
2.13. Definir las funciones que cumplan lo siguiente:
a) Tome un entero positivo y calcule el resto despus de dividirlo
por 67.
b) Trunque un nmero real a la mitad de la dcima ms prxima (por
ejemplo, 19.567 quedara 19,5).
e) Asigne verdadero si el nmero es positivo, y falso si es cero
o negativo.
d) Crear una secuencia de valores para cada uno de los cuales es el
doble del anterior ms uno. El primero es 1.
2.14. Tabular unos pocos valores de las siguientes ecuaciones de recurrencia,
y deducir una expresin compacta para f
a) f(n) 3 para n 0, y f(n) = f(n - 1) + 5 para n > O.
b) f(n) = 1 para n = 0, y f(n) = 2f(n - 1) para n > O.
2.15. Marcar un punto en la grfica (i, j) de la Figura 2.8b, para cada uno de
los estados marcados con A y B, en el segmento de programa siguiente.
; := 1;
j := 1;
(estado A}
;:=;+1;
j:=j+1;
{estado B}
2.16. Considrese la funcin f(x) = (x mod 2 = O).
a) Cul es el dominio de esta funcin?
b) Cul es el rango?
e) Es una funcin parcial o total?
24 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
2.17. La funcin Ancestros tiene como entrada un nmero de generacin, y
devuelve el nmero de ancestros que tuvo en todas las generaciones
precedentes, suponiendo que cada persona de cada generacin tiene
exactamente dos padres. Es decir, Ancestros(l) = 2, Ancentros(2) = 4, Y
as sucesivamente. En particular, Ancestros(O) = 1, suponiendo que cada
persona es ancestro de s mismo o s misma. Enunciar una definicin
para la funcin Ancestros.
2.2.4. Funciones uno-a-uno y funciones inversas
Supongamos quef es una funcin con dominio Xy rango Y. Entonces, como se
vio en la Figura 2.7b, a cada x le corresponde uno y slo un valor de y. Sin
embargo, cada valor de y puede corresponder a ms de un valor de x. Una
funcin de este tipo se representa en la Figura 2.12. Sin embargo, si quisira-
mos invertir el proceso, comenzando por y, el resultado obtenido no sera una
funcin correcta. Es decir, alguna y se correspondera con ms de un valor de
x, mientras que algunas de ellas no se corresponderan con ningn x. La
funcin de la Figura 2.12b es diferente ---en este caso podemos invertir el
proceso y seguimos obteniendo una funcin-o Esto es debido a que a cada x
le corresponde una y distinta. La definicin siguiente formaliza estas ideas.
Definicin. Sea f: X -+ y una funcin. La funcin f es una funcin uno-
a-uno si a cada x diferente le corresponde un y diferente para cada x E X e
y E Y. Se dice que dos conjuntos x e Y estn en una correspondencia uno-
a-uno si existe una funcin f: X -+ y que es uno-a-uno.
Ejemplo 2.23. Las funciones resultantes de permutaciones son ejemplos
clarificadores de las correspondencias uno-a-uno. Por ejemplo, considrese
y
.... "",__..., x
al
y
x
bl
Figura 2.12. a) Funcin no-uno-a-uno. b) Funcin uno-a-uno.
Conjuntos y funciones 25
la cadena abcd y su permutacin bdac. Si hacemos X = Y = {a, b, e,
d} esta permutacin puede considerarse como una funcin definida como:
p(a) e
p(b) a
p(c) d
p(d) b
Es decir, p indica en qu posicin se deben colocar los diferentes elementos de
una cadena arbitraria de a, b, e y d. La funcin p es tambin una funcin
uno-a-uno, puesto que x diferentes se corresponden con y's distintos, y el rango
de p = {a, b, e, d} = y.
Definicin. Sea f : X --. Y una funcin uno-a-uno. Entonces f - 1 es una
funcin con dominio Y y rango X, que verifica que si y = f(x), entonces
x = f - 1(y). La funcin f - 1 recibe el nombre de funcin inversa de f
No todas las funciones tienen inversa. Por ejemplo, supongamos X = Y =
= {a, b, c,d},yf(a) = b,f(b) = c,yf(c) =f(d) = d,como se muestra en
la Figura 2.13.
x
a . ~
b
~
c . ~
y
a
b
e
d - - - - - - + ~ d
f
Figura 2.13. Una funcin f que no es uno-a-uno, por lo que no tiene inversa.
Entonces, si la inversa def existiera,f - 1 (d) tendra como valores asociados e y
d, lo que invalidara af -1 como una funcin legtima. Por tanto, para que una
funcin pueda tener inversa ha de ser una relacin uno-a-uno.
26 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
Ejemplo 2.24. El Ejemplo 2.23, puesto que p es una funcin uno-a-uno,
tiene inversa. Esta inversa, p- 1, puede definirse de la forma siguiente:
p-l(a) b
p-l(b) d
p-l(e) a
p- l(d) e
Obsrvese que p-l(p(a)) = p-l(e) = a. De forma general, para cubrir
cualquier funcin invertible p : X -+ Y, y cada x E X, P- 1(p(x) = x. Anlo-
gamente, para cada y E Y, p(p-l(y)) = y.
Ejemplo 2.25. Las funciones uno-a-uno se emplean habitualmente en la
codificacin. El American Standard Code for Information Interchange (AS-
CII) define una equivalencia numrica entre O y 127 para cada carcter
regular o de control que puede ser pulsado en un teclado estndar de una
computadora. Esta funcin es uno-a-uno, y est incluida en lenguaje de
programacin Pascal con el nombre de ord (por valor orddinal). Es decir,
para cada carcter que encontramos en el teclado, o rd(x) es un nmero
entero entre Oy 127. Los valores ordinales de algunos caracteres familiares
del teclado se pueden ver debajo:
ord ( , O' ) = 48
ord('A') =-65
ord( '=') = 61
ord ( , a') = 97
Una lista completa de los caracteres ASCII y sus ordinales correspondien-
tes puede encontarse en el Apndice A.
El propsito de la funcin ord es definir un esquema de codificacin uni-
forme para representar los caracteres del teclado. Este esquema lo utilizan
todos los constructores de software y hardware de computadoras. La existen-
cia de este estndar permite el intercambio fcil de informacin entre distintos
tipos de computadoras.
Obsrvese que, para ser eficaz, la funcin o rd tiene que ser uno-a-uno; si
un cdigo estuviera asignado a dos caracteres distintos, no existira una forma
consistente de descodificar el cdigo. Puesto que es una funcin uno-a-uno, la
funcin ord tiene en Pascal su inversa, denominada eh r (por Character). Si n
es un entero en el intervalo 0-127, entonces eh r (n) es el carcter del teclado
correspondiente del entero. Por ejemplo:
ehr(48) = 'O'
ehr(65) = 'A'
ehr(61) = '='
eh r (97) = 'a'
Conjuntos V funciones 27
Obsrvese que, puesto que ord y chr son inversas, una de la otra, se verifica:
chr<ord<x = x y ord<chr<n = n
Para cualquier entero entre O y 127, Ycualquier carcter del teclado.
\ Ejemplo 2.26. La criptografia (codificacin de mensajes secretos) es un
rea de la informtica que utiliza muchos de los principios que hemos
discutido. Por ejemplo, el cifrado de Csar, un esquema de codificacin en
el que cada letra de un mensaje es reemplazada por otra letra diferente del
alfabeto, la tercera letra detrs de ella. Entonces el mensaje:
SERGEANT PEPPERS LONELy HEARTS CLUB BAND
se codifica en el cifrado de Csar como:
VHUJHDGW SHSSHUV ORGHOB KHDUWV FOXE EDGG
El cifrado de Csar es una permutacin de las letras del alfabeto, y por
tanto una funcin uno-a-uno, cuyos dominio y rango son el alfabeto de
letras maysculas. La descodificacin del lenguaje implica el descubrimien-
to de la funcin inversa a la que fue utilizada al cifrarlo.
La gran desventaja del cifrado de Csar es lo relativamente fcil que es
descodificarlo. Podemos construir un mtodo ms dificil de descodificar, utili-
zando una permutacin aleatoria y haciendo sustituciones en base a ella. Utili-
zando la tabla de sustitucin:
ABCDEFGHIJKLMNOPGRSTUVWXYZ
JSATERNICFHPLUGWVYDZOMXGBK
Permite codificar el mensaje:
SERGEANT PEPPERS LONELY HEARTS CLUB BAND como
DEYNEJUZ WEWWEYD PGUEPB IEJYZD APOS SJUT
Si el mensaje cifrado es lo suficientemente largo, incluso un cifrado aleatorio
puede descodificarse contando el nmero de veces que aparece cada letra,
comparndola con el nmero de veces que aparece cada letra en un prrafo en
castellano. Algunos esquemas de encriptacin ms sofisticados emplean funcio-
nes de descodificacin que encriptan bloques de letras. La criptografa es un
campo de estudio excitante y que encierra grandes desafos. El concepto de
funcin uno-a-uno aporta un criterio preciso para definir la nocin de conjun-
tos que tienen el mismo nmero de elementos, y la nocin de tamao de un
conjunto.
28 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Definicin. Dos conjuntos A y B tienen el mismo nmero de elementos, si
estn en una correspondencia uno-a-uno. Un conjunto que est en una
correspondencia uno-a-uno con Zn para algn valor n natural, se dice que
tiene cardinalidad * n. Dicho conjunto tiene n elementos y recibe el nombre
de conjunto finito. Los conjuntos que no tienen cardinalidad n para ningn
valor de n, reciben el nombre de conjuntos infinitos.
\
La mayora de los conjuntos que nos encontraremos en la informtica son
finitos. Por ejemplo, el conjunto de caracteres ASCII del Ejemplo 2.25 tiene
cardinalidad 128. Incluso el conjunto de enteros que se utiliza en la informtica
es finito -para muchas computadoras, su cardinalidad es 2
16
; es decir, 65.536.
Este es el tipo; nteger que utiliza el lenguaje de programacin Pascal, y que
difiere de la nocin matemtica del conjunto Z por razones evidentes. En
resumen, el rango de los enteros en matemticas es infinito, mientras que el
rango de los; ntege r en programacin es finito. Nociones complementarias
sobre el tipo; nteger se introducen en el manual de laboratorio.
2.2.5. Funciones booleanas enteras, exponenciales
y logartmicas
Existen un conjunto de funciones especiales que aparecen con la suficiente
frecuencia en la informtica como para justificar un breve estudio.
Ejemplo 2.27. Supongamos que X = Z e Y = {verdadero, fa l so}.
Sea f(x) = (O ~ x ~ 100). Entonces, f(l) = verdadero, f(102) =
fa l so, f( - 1) = fa l so, y as sucesivamente. El dominio de f es el de los
enteros y el rango el conjunto {verdadero, falso}.
Este es un ejemplo de un importante conjunto de funciones, conocidas como
booleanas en honor del matemtico ingls George Boole (1815-1864), que sen-
t las bases y comenz el desarrollo de la lgica simblica. Esta funciones
reciben tambin el nombre de predicados. Estudiaremos detenidamente los
predicados y la lgica en el Captulo 3.
Ejemplo 2.28. Sea b mod p el resto entero resultante de dividir el entero b
por el entero p. As, por ejemplo, 8 mod 3 = 2, 15 mod 5 = O, Y as
sucesivamente. Obsrvese que O ~ b mod p ~ p - 1. Si X = N, Y = Z23 y
h(b) = b mod 23, entonces h(46) = O, h(70) = 1, Yas sucesivamente.
* N. del T.: En castellano se suele utilizar el trmino cardinalidad o simplemente cardinal
de un conjunto.
Conjuntos y funciones 29
La funcin h es un ejemplo sencillo de una clase de funciones conocidas como
funciones hash*, que se suelen utilizar en programas de computadoras que
almacenan y recuperan informacin de archivos muy grandes.
Ejemplo 2.29. Otro tipo de funciones que aparecen frecuentemente en
informtica es la clase de funciones polinmicas, tales como x
Z
, 2x
3
+ 1,
, x
5
. - 5x, y as sucesivamente. La forma general de una funcin polin-
mIca es:
p(x) = a x
n
+ a x
n
- l + '" + a x + a
n n-l l o
As, si n = 3, a
3
= 2, a
z
= al = O, ya
o
= 1, entonces p(x) = 2x
3
+ 1.
Las funciones exponenciales y logartmicas son dos clases de funciones con una
importancia tal en la informtica, que es necesario estudiarlas cuidadosamente.
Comencemos por la funcin exponencial.
Definicin. Sean X = Y = R, Yseanf(x) 2
x
La funcin f(x) recibe el
nombre de funcin exponencial con base 2.
Puesto que 2
0
= 1 Y 2-x = 1/2
x
, es posible tabular algunos valores de la
funcin exponencial y perfilar su grfica, que se muestra en la Figura 2.14.
y
x Z'
-2 1/4
-1 1/2
O 1
1 2
x
2 4
3 8
4 16
Figura 2.14. La funcin exponencial y su representacin grfica.
* N. del T.: Es extraordinariamente dificil traducir al castellano el trmino hash. Su
traduccin literal sera picadillo. Ms en consonancia con el concepto sera traducir hashtable
por tabla asociativa, hash functiom> por funcin asociativa, hashing por asodatividad, aunque
aqu no lo hemos hecho.
30 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
La principal caractersticas de la funcin exponencial es su crecimiento
rpido. Si la x se incrementa en 1, f(x) se dobla, puesto que 2
x
+ 1 = 2 x 2
x
.
Los dos acertijos siguientes ilustran esta propiedad; el primero se debe a los
franceses y el segundo a los persas.
Ejemplo 2.30. Supongamos que tenemos un estanque en nuestra propie-
dad. En el estanque crecen nenfares, y hemos observado que la superficie
del estanque que recubren stos se dobla cada dia. Al principio, el creci-
miento era pequeo, puesto que el rea que cubran era escaso. Sin embar-
go, si llegasen a cubrir todo el estanque, eliminaran todos los dems tipos
de vida en l. Despus de 29 das observamos que la mitad del estanque
est totalmente cubierto. Cuntos das nos quedan para poder salvar el
estanque? (La respuesta, por supuesto, es 1 da).
Ejemplo 2.31. Cierto individuo ofreci regalar al rey un precioso tablero
de ajedrez si el rey le daba a l un grano de trigo en la primera casilla, dos
granos sobre la segunda, cuatro sobre la tercera, y as sucesivamente hasta
que el tablero estuviera cubierto completamente. Pensando de forma super-
ficial sobre lo que le pedan, el rey acept. El rey no tard mucho en caer en
la bancarrota.
Estimemos cunto arroz deba dar el rey al individuo. Antes de ello, recorde-
mos algunas propiedades algebraicas de las funciones exponenciales. Las cua-
tro funciones que necesitamos son las siguientes:
2
m
2
m
2
m
+"
(2.8)
2
m
/2"
2
m
-"
(2.9)
(2
m
)" 2
m
" (2.10)
2
m
!"
= .::12
m
(2.11 )
donde m y n son nmeros naturales (estas propiedades se verifican incluso si n
y m son reales, aunque nuestras aplicaciones slo requerirn el caso ms sim-
ple).
No es dificil verificar esas propiedades. En la Ecuacin (2.8), el lado izquier-
do es el producto de m doses seguido del de n doses. El resultado es el produc-
to de m + n doses. La verificacin de la Ecuacin (2.9) se obtiene de forma
anloga. La parte izquierda de la Ecuacin (2.10) es el producto de n copias de
2
m
; es decir, el producto de n copias de un producto de m doses. Por tanto, es el
producto de mn doses. Para verificar la Ecuacin (2.11), utilizamos la propie-
dad de que la Ecuacin (2.10) puede extenderse al caso en que m y n sean
nmeros racionales. Es decir, 2
m
!" puede escribirse como (2
m
)l!", por lo que se
obtiene directamente la Ecuacin (2.11) utilizando el hecho de que 2
1
!" =.::12.
Podemos ahora estimar la cantidad de granos de trigo que el donante del
tablero de ajedrez habra recibido si el rey hubiera sido capaz de cumplir el
Conjuntos y funciones 31
compromiso. Consideremos los primeros cuadrados. En la casilla 1 habra que
depositar 1 (= 2) granos de trigo; en la casilla 2, 2 ( = 2
1
) granos; en la casilla 3,
4 (= 2
2
) granos; y as sucesivamente. As, el da 64 el individuo tendra que
recibir 2
63
granos de trigo del rey. Pero:
Por tanto:
2
63
260 X 2
3
= (2
1
)6 X 2
3
210 1024 ~ 1000 = 10
3
2
63
~ (10
3
)6 X 8 = 8 X 10
18
Si hacemos una estimacin de 50 granos de trigo por cada gramo, esto es
aproximadamente igual a 1,6 x 10
11
toneladas mtricas de trigo, que excede
con creces la produccin de arroz de todo el mundo.
La funcin exponencial es una funcin uno-a-uno; as, si Xl =f. x
2
, entonces
2" =f. 2". Su rango es el conjunto de nmeros reales no negativos. Por tanto, si
restringimos el dominio al conjunto {x E Rlx > O}, entonces el dominio de la
funcin exponencial ser igual al rango (vase de nuevo la Figura 2.14). En este
caso, la funcin es invertible. La funcin inversa de una exponencial recibe el
nombre de funcin logartmica.
Definicin. Sea X = R e Y = {x E Rlx > O}. Seaf(x) = 2
x
Entonces'-l
recibe el nombre de funcin logartmica en base 2 y se representa por
log2(x).
Recurdese que una funcin y su inversa cumplen fU- 1(x = x y
f-IU(x = x. Esta relacin nos conduce a las ecuaciones siguientes, que
relacionan entre s ambas funciones:
(2.12)
(2.13)
Ejemplo 2.32. Puesto que 2
3
= 8,log
2
8 = 3. Es decir, 2
3
= 8 responde a
la pregunta: Qu obtendremos cuando elevamos el nmero 2 al cubo?.
Por el contrario, log2 8 = 3 responde a la pregunta: A qu potencia hay
que elevar 2 para obtener 8?. Del mismo modo, tendremos que log2 16 = 4,
Ylog2 1024 = 10.
En la Figura 2.15 se muestra la grfica de la funcin logartmica. La principal
caracterstica de la funcin exponencial es su rpido crecimiento. Por el con-
trario, la principal caracterstica de la funcin logartmica es su crecimiento
lento. Obsrvese que log2 8 = 3 Ylog2 16 = 4. Es decir, aadiendo 1 a x se
dobla 2
x
, mientras que al doblar x slo se le aade 1 a log2 x.
Otra forma de comparar las funciones exponencial y logartmica es la si-
guiente: y = 2
X
significa que el nmero 1 debe ser doblado x veces para
32
Computacin l. Lgica, resolucin de problemas, algoritmos y programas
y
x
Figura 2.15. La funcin logartmica.
obtener y. Si x es una potencia de 2, y = log2 x significa que x debe ser
dividido por 2 y veces, para obtener 1. Por ejemplo, log2 16 = 4 significa que
16 debe ser dividido por 2 cuatro veces para obtener 1. Las Ecuaciones (2.14) a
(2.18) describen algunas propiedades adicionales de la [uncin logartmica.
log2 1
O
(2.14)
log2 2
1
(2.15)
log2 mn log2 m + log2 n
(2.16)
log2 (m/n)
log2 m - log2 n
(2.17)
log2 (m
n
) n log2 m
(2.18)
La verificacin de esas expresiones depende del hecho de que la funcin loga-
rtmica es la inversa de la exponencial. Abajo verificamos las Ecuaciones (2.14)
a (2.16), dejando para el lector la verificacin de las restantes.
Para verificar la Ecuacin (2.14) supongamos que log2 1 = x. Entonces
2
x
= 1, por lo que x = O. Para verificar la Ecuacin (2.15), sea log2 x = x.
Entonces 2
X
= 2, resultando x = 1. Para verificar la Ecuacin (2.16), sea
x = log2 me y = log2 n. Entonces m = 2
x
y n = 2
Y
Por tanto, nm = 2
x
+
y
, y
por tanto, x + y = log2 (mn). Combinando ambas, obtenemos log2 mn = log2
m + log2 n.
Conjuntos y funciones 33
Ejemplo 2.33. logz 3 = 1,585 Y logz 5 = 2,322. Podemos utilizar esta
informacin para calcular las expresiones siguientes:
a) logz 6 = logz (2 x 3) = logz 2 + logz 3 = 1 + 1,585 = 2,585
b) logz 1,6 = logz (8/5) = logz 8 - logz 5 = 3 - 2,322 = 0,678
e) logz 0,5 = logz (1/2) = logz 1 - 1 = - 1
Pascal incorpora las funciones exponencial y logartmica, pero en base e en
lugar de en base 2. Se simbolizan mediante exp y l n respectivamente. Es
decir, dado x para calcular en Pascal eX escribiremos la expresin exp(x).
Conocido x para calcular en Pascal loge x, escribiremos l n ( x). Para ms
detalles vase el manual de laboratorio.
Ejercicios
2.18. Una alternativa en criptografia para el cifrado de Csar es la utilizacin
de una clave de codificacin, que consiste en un patrn que se repite e
indica al descodificador a qu distancia a la derecha en el alfabeto se
encuentra la letra correcta. Por ejemplo, A significa desplaza letras;
B significa desplaza 1 letra, y as sucesvamente. Por tanto, si la clave
de codificacin es ABCDABC..., el mensaje (en ingls) FOURSCO-
REANDSEVEN se codificara FPWRTEOSGAOFSFXEO. Invertir el
proceso para el mensaje codificado (tambin en ingls) OIVOCGIO-
PASPIB. Es este esquema una funcin de caracteres uno-a-uno? Es
una funcin uno-a-uno de cadenas de caracteres?
2.19. Dibjense las grficas de las funciones siguientes. Supngase que el
dominio es R (excepto para el apartado e que es N).
a)
12xl
b) lx/3J
e) logz (2x)
x
d) 2>+
e) x mod 7
f)
Ilogz xl
g)
rIxll
2.20. Simplificar las expresiones siguientes:
a)
3
a
x
3-a
b)
(2
Z
)3
e) 27"/
3
d) 2
3
/2
4
e) logz 4
f) log3 (1/27)
g) logz 2"
h) 3 log3 (x + 1)
34 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
2.2.6. Series finitas y funciones relacionadas
Los procesos acumulativos son frecuentes en la informtica. Por ejemplo, al-
gunos programas repiten un determinado clculo. Cada repeticin consume
una cierta cantidad de tiempo y memoria. El programador tiene que ser ca-
paz de esmar la cantidad de tiempo y espacio que consumir el programa,
sin necesidad de ejecutarlo. Tales clculos suelen implicar la suma de lar-
gas listas de nmeros o expresiones. Para facilitar todo ello, y otras expresio-
nes relacionadas, se ha desarrollado la denominada notacin sigma. Esta nota-
cin utiliza la letra griega L (sigma) para simbolizar la suma, un ndice que
define el intervalo de valores para los que se realiza la suma, y la funcin que
hay que sumar. Supongamos que se quiere escribir la suma de los 20 primeros
enteros, 1 + 2 + 3 + ... + 20, utilizando notacin sigma. Escribiremos
entonces:
Esto se lee, calcular la suma de los i enteros comprendidos entre 1 y 20,
ambos inclusive. El nmero 20 es el lmite superior y el 1 el lmite inferior,
siendo la variable i la variable ndice de la sumatoria.
Ejemplo 2.34. A continuacin, se muestran varios ejemplos de notacin
sigma:
n
a) i ~ l i 1 + 2 + 3 + ... + (n - 1) + n.
n
b) i ~ 3i O + 3 + 6 + 9 + '" + 3(n - 1) + 3n.
n
e) L (3i + 2)
i= 1
5 + 8 + 11 + .. , + (3n - 1) + (3n + 2).
n
e) i ~ i
1 + 2 + 3 + ." + (n - 2) + (n - 1).
2 + 3 + 4 + ... + (n - 1) + n.
n
f) i ~ i(3i + 2) = 5 + 16 + 33 + ... + (n - 1)(3n - 1) + n(3n + 2).
Conjuntos y funciones 35
De hecho, cualquier funcin de una variable ndice i, puede sumarse de esta
forma. Considrense las relaciones generales siguientes:
n
I f(i) = f(m) + f(m + 1) + ... + f(n)
i=m
n
)' a = a + a + .,. + a
L....J I 1 2 n
j= l
(2.19)
(2.20)
Obsrvese la utilizacin de subndices en la Ecuacin (2.20). Este tipo de nota-
cin suele utilizarse para diferenciar los elementos de una lista, siendo al el
primero, a
z
el segundo, y as sucesivamente. Utilizaremos a menudo esta idea
de lista en el diseo de programas.
Propiedades de las series finitas. Las Ecuaciones (2.21) a (2.24) reflejan algunas
propiedades bsicas de las sumas utilizando la notacin sigma.
1
I a al
(2.21)
=1
n n
I a al +
~ a
(2.22)
= 1
n
n ~ l
I a
a
n
+
I a
(2.23)
= 1 = 1
n m n
I a I a
+
I a
SI 1 ~ m < n (2.24)
= 1 = 1 =m+l
Que se pueden justificar de la forma siguiente: En la Ecuacin (2.21) los lmites
inferior y superior son iguales, por lo que existir un nico trmino, el corres-
pondiente al valor comn de los lmites. En la Ecuacin (2.22) el lado derecho
de la expresin es simplemente igual al izquierdo, con el primer trmino escrito
por separado. En la Ecuacin (2.23), el lado derecho es igual al izquierdo, pero
con el ltimo trmino escrito por separado. En la Ecuacin (2.24), el lado
derecho es igual al izquierdo separado en dos sumas -una hasta m, y otra
desde m + 1 hasta n.
Las Ecuaciones (2.25) a (2.29) resumen otras importantes propiedades adi-
cionales de las sumas en series finitas.
n
I e
j= 1
en donde e es una constante (2.25)
n
I (f(i)
= 1
n
e I f(i)
i= l
(2.26)
36 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
n n n
I (f(0 +
g(i))
i ~ f(O
+
j ~ g(i)
(2.27)
j= 1
n n n
I (fU) - g(i)) I f(i) I g(i) (2.28)
j= 1 j= 1 j=l
n
i ~ (f(i + 1) - f(i)) = f(n + 1) - f(l) (2.29)
Es posible justificar estas ecuaciones haciendo las consideraciones siguientes:
En la Ecuacin (2.25), dIado izquierdo es el propio valor c sumado a s mismo
n veces. En la Ecuacin (2.26), dIado derecho es igual al izquierdo, tras sacar c
factor comn de la suma. En la Ecuacin (2.27), el lado derecho es igual al
izquierdo, pero con los trminos reagrupados. La Ecuacin (2.28) se deja como
ejercicio. La Ecuacin (2.29) se conoce como las series telescpicas. El lado
izquierdo puede escribirse como:
(f(2) - f(l)) + (f(3) - f(2)) + ... + (f(n + 1) - f(n))
donde podemos ver que todos los trminos entre f(n + 1) y f(l) se cancelan
mutuamente, por lo que el resultado serf(n + 1) - f(l).
Algunas series importantes para la informtica. No suele ser habitual la mode-
lizacin de procesos acumulativos, como sumas finitas, utilizando notacin
sigma. Generalmente, es deseable encontrar una frmula que nos calcule el
resultado en funcin de los lmites inferior y superior. Se han obtenido estas
frmulas para algunas de las series ms comunes, y es conveniente memorizarlas.
Una de tales series, que se utiliza frecuentemente en la informtica, es la
serie aritmtica (tambin conocida como progresin aritmtica):
1 + 2 + 3 + ... + (n - 1) + n
Existe una ancdota interesante sobre esta serie. Cad Friedrich Gaus (1777-
1855) fue uno de los matemticos ms destacados del siglo XIX. Cuando era
joven le enviaron a un internado, ms conocido por su estricta disciplina que
por su calidad acadmica. Como castigo, l y sus compaeros deberan realizar
el ejercicio de sumar los 100 primeros enteros. Apenas el profesor haba enun-
ciado el problema, Gauss levant su mano dando la respuesta correcta. Gauss
haba descubierto una forma sencilla de sumar la serie aritmtica para n =
100. Gauss escribi la suma horizontalmente en orden creciente, y debajo
escribi la misma suma, pero en orden decreciente, haciendo despus la suma
trmino a trmino:
1 + 2 + 3 +
+ 100 + 99 + 98 +
101 + 101 + 101 +
+ 99 + 100
+ 2 + 1
+ 101 + 101
Conjuntos y funciones 37
Gauss pudo observar que el resultado era la mitad de 101 x 100, o 5050. El
profesor de Gauss reconoci que el muchacho tena un gran talento para las
matemticas, y recomend a su padre que lo enviara a un colegio en el que
pudiera sacar mejor partido de su capacidad. De hecho, podemos utilizar el
mtodo abreviado de Gauss para sumar series en general:
1 + 2 + 3 +
+ n + (n 1) + (n 2) +
(n + 1) + (n + 1) + (n + 1) +
+ (n 1) + n
+ 2 + 1
+ (n + 1) + (n + 1)
Puesto que hay n trminos en la suma, el resultado de la suma anterior pue-
de escribirse n(n + 1). Por tanto, la suma de la serie aritmtica original es
n(n + 1)/2, puesto que se ha sumado consigo misma para obtener la ltima
lnea. La forma compacta de la suma de esta serie, junto con la de otras tam-
bin importantes, se muestran en las Ecuaciones (2.30) a (2.33).
n
n(n + 1)
i ~ l 2
(2.30)
n
n(n + 1)(2n
+
1)
i ~ 1
i
2
6
(2.31 )
n
n
2
(n +
1)2
I i
3
(2.32)
i= 1
4
n
I 2i
2n+ 1 _
1 (2.33)
i= 1
Las Ecuaciones (2.30) a (2.32) se las conoce con el nombre de p-series por ser de
la forma:
n
I i
P
i= 1
para algn valor de p. La Ecuacin (2.32) es un ejemplo de la que se conoce
como serie geomtrica o progresin geomtrica.
Ejemplo 2.35. A continuacin, se estudian dos ejemplos en los que se ve
cmo pueden utilizarse esas propiedades para calcular sumas de series.
15
15(15
+ 0_
i ~ 1 i
2
120
20 20 6
20(21) 6(7)
i ~ i
i ~ 1 JI
-2-
2
210 - 21 189
38 Computacin ,. Lgica, resolucin de problemas, algoritmos Vprogramas
Ejemplo 2.36. Considrese el problema discutido en el Ejemplo 2.31. Es
posible utilizar la Ecuacin (2.33) para calcular el nmero total de granos
de arroz que se acumularan en 64 das, de la forma siguiente:
Obsrvese que 2
64
= 2 X 2
63
= 2
63
+ 2
63
, luego 2
64
- 1 = 2
63
+ 2
63
- 1.
Recurdese que el nmero de granos de trgo recibidos el da 64 fue 2
63
.
Por tanto, el nmero de granos recibidos el da 64 era de uno ms que la
suma de los recibidos en todos los das anteriores! En general, las series
geomtricas tienen esta caracterstica. Es decir,
1 + 2 + 4 7, que es 1 menos que 8
1 + 2 + 4 + 8 = 15, que es 1 menos que 16
y as sucesivamente. Esto aporta otro punto de vista sobre el rpido creci-
miento de las funciones exponenciales.
2.3. SUMARIO
En este captulo se han introducido algunas ideas fundamentales sobre conjun-
tos y funciones. Como se sugiri, la mayora de estas nociones tienen directas e
importantes aplicaciones en la informtica. En este libro utilizaremos los con-
ceptos de conjunto y funcin siempre que sea necesario. Veremos que esta
notacin matemtica, concisa y exacta, produce grandes beneficios en la solu-
cin de problemas informticos, sean los propios problemas de naturaleza
matemtica o no. Las propiedades de los conjuntos y las funciones tienen un
gran paralelismo con las de la lgica, como veremos en el Captulo 3, y en el
diseo de computadoras, como se ver en el Captulo 7. Por tanto, un conoci-
miento profundo de los conjunto y las funciones es de vital importancia en el
estudio de la disciplina informtica.
Ejercicios
2.21. Desarrollar cada una de las sumatorias siguientes:
Conjuntos y funciones 39
o
d) i ~ a
2.22. Expresar las series siguientes en notacin sigma:
a) 17 + 21 + 25 + ... + 65.
b) 2 + 5 + 10 + 17 + .. , + 101.
e) La suma de los nmeros impares de Oa 1000, inclusive.
d) La suma de los enteros positivos menores que 300 y que sean divisi-
bles por 3.
e) La suma de las raices cuadradas de todos los enteros positivos
menores que 1000.
2.23. a) Justificar la Ecuacin (2.28).
b) Justificar que la suma de los n primeros nmeros impares es n
2

2.24. Calcular la suma de las expresiones desarrolladas en el Ejercicio 2.22.


2.25. Calcular las sumas siguientes:
25 n
a)
i
e)
~ 1 2
13 5
b)
i ~ 2i(i + 1)
f)
~ (2 + 1)
12 5
e)
32
g)
i ~ 2
=6
10 O
d)
k ~ 5
2
k
h) a
i= 1
2.26. Un programa de computadora ordena una lista L = (al' a
2
, ..., a
n
) en la
forma siguiente. Examina cada elemento de la lista, selecciona el mayor,
y lo intercambia con an0 A continuacin, repite el mismo proceso para la
sublista (a l' a
2
, ... , a
n
_ 1)' El programa termina cuando slo quede a 1 en
la sublista.
a) Utilizar notacin sigma para escribir una expresin que refleje el
nmero de exmenes realizados por el proceso.
b) Sumar la expresin.
2.27. En Nepal, el arroz se cultiva a menudo en terrazas formadas en las
laderas de las colinas. Una coleccin de estas terrazas, observadas a
40 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
vista de pjaro, se puede ver en la Figura 2.16. El cuarto de crculo
interior, correspondiente a la cima, no est cultivado. Movindonos
hacia abajo por la colina, los parterres se alternan con zonas escarpadas
no cultivadas. Supongamos que, para una determinada colina, el radio
del crculo de la cima es de 75 metros, y cada crculo concntrico de ah
hacia abajo tiene 50 metros. Supongamos que hay 10 parterres planta-
dos.'
a) Utilizar la notacin sigma para escribir una expresin que refleje el
rea total cubierta por los parterres de arroz.
b) Calcular el rea total cubierta por parterres.
75 125 175 225 275 325
Metros
Figura 2.16. Panormica a vista de pjaro
de los parterres de Nepa!.
2.28. Si comenzamos con una clula de levadura el da O, y al final de cada
da cada clula se divde en dos, cmo de grande ser la colona des-
pus de n das?
CAPTULO 3
LGICA
La lgica est adquiriendo un papel cada vez ms preponderante en la infor-
mtica. De hecho, algunas personas llegan tan lejos como para afirmar que la
informtica no es ms que lgica aplicada. En este texto, la lgica tiene tres
distintas e importantes aplicaciones: se utiliza la lgica en programacin para
construir expresiones lgicas (Captulo 4); se utiliza la lgica para escribir pre y
poscondiciones y otros asertos que describen el comportamiento de los progra-
mas (Captulos 5 y 6); Yse utiliza la lgica como fundamento para el diseo de
las computadoras mismas (Captulo 7).
En las Secciones 3.1 y 3.2 se introduce la lgica proposicional, que es un
sistema para razonar y hacer clculos con proposiciones. La lgica proposicio-
nal naci entre los aos 1847 y 1854, fruto de los trabajos de George Boole.
Boole observ que exista una gran similitud entre las operaciones lgicas and
y or, y las operaciones aritmticas producto y suma. Boole desarroll un siste-
ma para la manipulacin de expresiones lgicas, que era tan preciso para
manipular esas expresiones como la aritmtica para manipular nmeros.
En la Seccin 3.3 se extiende la nocin de lgica proposicional a otra ms
amplia, conocida como lgica de predicados. Esta extensin nos permite utili-
zar la lgica en informtica de una forma muy constructiva. Por ejemplo, la
utilizacin de los denominados cuantificadores lgicos est estrechamente rela-
cionada con la idea de bucles en los programas.
Tambin se introducen las ideas de tautologa y demostracin. Estos con-
ceptos sern revisados en el Captulo 6, en yuxtaposicin con los conceptos
paralelos de prueba y verificacin. Lgica y demostracin son tan fundamenta-
les para la informtica como para otras disciplinas, tanto artsticas como cien-
tficas; por tanto, este captulo ser til en otras reas diferentes.
3.1. LGICA PROPOSICIONAL
La idea bsica de Boole fue la de analizar patrones de argumentaciones lgi-
cas, utilizando smbolos para representar tanto aseveraciones simples como los
42
Computacin l. Lgica, resolucin de problemas, algoritmos y programas
propios patrones. Esta parte de la lgica se conoce por el nombre de lgica
proposicional (o en algunos casos lgica simblica). En lgica proposicional,
una frase (o proposicin) puede tener slo dos valores verdadero (true) o falso
(false). Las oraciones siguientes son ejemplos tpicos de proposiciones:
I
El rea de un tringulo rectngulo issceles, que tiene una hipotenusa de
longitud 2 es 1/2.
Todos los elementos de la lista (1 3 5 7 6 4) son menores que 10.
3 + 5 = 7.
En la frase The quick brown fox jumps over the lazy dog estn presen-
tes, al menos una vez, todas las letras del alfabeto ingls.
Ningn alumno de informtica del Calvin College, alcanz la calificacin
de B+ en el curso de 1990.
Con objeto de expresar frases como las anteriores, de una forma ms preci-
sa, utilizamos un estilo formal para escribir proposiciones. En la Tabla 3.1 se
presenta una lista de los operadores lgicos que se utilizan al escribir proposi-
ciones.
Definicin. Una proposicin es una expresin que se construye siguiendo
las reglas siguientes:
Regla 1:
Regla 2:
Regla 3:
Regla 4:
Verdadero (true) y falso (false) son proposiciones.
Cualquier variable cuyo tipo sea {verdadero, falso} (conocido
como tipo booleano) es una proposicin.
Si p es una proposicin, tambin lo es ('" p).
Si p Y q son proposiciones, tambin lo son (p v q), (p /\ q),
(p => q), (p <=> q).
Obsrvese que la definicin anterior es recursiva, segn se vio en el Captu-
lo 2. Es decir, las reglas 3 y 4 definen una proposicin en trminos de una o
ms proposiciones ya existentes, las cuales pueden haber sido construidas utili-
zando las reglas 3 y 4, Yas sucesivamente. Sin embargo, debido a que existen
proposiciones elementales formadas utilizando las reglas 1 y 2, que no utilizan
la palabra proposicin en la definicin, el proceso para determinar si algo es
una proposicin, utilizando estas reglas, no es infinito; es decir, la definicin no
es circular.
Por el momento, cuando trabajemos con el clculo proposicional, manipu-
laremos slo variables y no intentaremos simbolizar ninguna proposicin en
particular. Ms adelante introduciremos formas de interpretacin de las varia-
bles, que son de gran utilidad en el mundo de la programacin y del diseo de
las computadoras.
Lgica 43
Tabla 3.1. Los operadores lgicos
Smbolo
V
/\
=>
-=
Equivalente
en castellano
no
o
y
implica
si y solo si
Significado
Negacin
Disyuncin
Conjuncin
Implicacin
Equi valencia
i
I
Despus de ver algunos ejemplos de la aplicacin de estos operadores, estudia-
remos otras interpretaciones.
Ejemplo 3.1. Si p, q y r son variables booleanas, entonces las siguientes
expresiones son proposiciones vlidas:
p
q
c- p)
(p v q)
(p v (q v r
(p =o> (q v (r =o> (p ~ q
De las Reglas 2 y 3 puede deducirse, de forma inmediata, que las cuatro
primeras son expresiones. Para la quinta expresin puede aplicarse reitera-
damente la cuarta regla, siguiendo los siguientes pasos:
p, q y r son proposiciones por la segunda regla.
(q v r) es una proposicin segn la regla 4.
(p v (q v r es una proposicin segn la regla 4.
Una lnea de razonamiento similar sirve para demostrar que el sexto ejem-
plo es una proposicin:
p, q y r son proposiciones por la segunda regla.
(p ~ q) es una proposicin segn la regla 4.
(r =o> (p ~ q es una proposicin segn la regla 4.
(q v (r =o> (p ~ q))) es una proposicin segn la regla 4.
(p =o> (q v (r =o> (p ~ q))) es una proposicin segn la regla 4.
Ejemplo 3.2. Las expresiones siguientes no son proposiciones:
(p)
(p q) p)
~ (p)
44 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
Observando el Ejemplo 3.2, si somos estrictos en la aplicacin de las reglas,
los parntesis juegan un papel crucial en la determinacin de si una expresin es
una proposicin. Sin embargo, podemos prescindir de ellos siempre que el signi-
ficado de la expresin est claro. Por ejemplo, podemos escribir '" p en lugar de
('" p), p v q en lugar de (p v q), y as sucesivamente.
Sin embargo, la eliminacin descuidada de los parntesis puede conducir-
nos a Por ejemplo, no est claro si p v q /\ r significa
((p v p) /\ r)
(p v (q /\ r))
o bien,
Para evitar estas ambigedades, se asignan prioridades a los operadores:
'" tiene la prioridad ms alta; /\ tiene la siguiente ms elevada; y v, =:> y
tienen sus prioridades por este mismo orden. De esta forma, la expresin
p v q /\ r siempre se debe interpretar como (p v (q /\ r)).
3.1.1. Representacin de frases en castellano
utilizando la lgica proposicional
No siempre es posible representar cualquier frase arbitraria, de forma simbli-
ca, utilizando proposiciones o predicados. Es decir, muchas frases no son de-
clarativas y, por tanto, no puede afirmarse que sean verdaderas o falsas. Por
ejemplo, cierra la puerta! es una orden, y fuiste a la clase de anatoma de
ayer, del profesor Davidson? es una pregunta. Sin embargo, existen gran canti-
dad de frases que pueden representarse como proposiciones y, ms an, que
pueden representarse como predicados. En informtica, la mayora de las cosas
que solemos querer representar simblicamente, no son ambiguas, tienen un
valor verdadero o falso, tambin no ambiguo y son expresables en forma de
proposicin o de predicado.
Obsrvese que en la lgica proposicional existen cinco operadores. De he-
cho, solamente es necesario uno; el resto pueden obtenerse a partir de ste
(vanse los ejercicios de la Seccin 3.2). La lengua castellana ofrece una gran
cantidad de formas para expresar la misma idea; as, al representar frases
mediante proposiciones evitaremos muchos matices del significado, centrando
nuestra atencin en la estructura lgica de las oraciones. Del mismo modo,
utilizaremos la misma estructura lgica para expresar diferentes giros en caste-
llano. Por ejemplo, si representamos la frase Phogbound quiere ser senador
mediante la variable p, las oraciones siguientes pueden representarse ambas
mediante la proposicin '" p:
Phogbound no quiere ser senador.
No es verdad que Phogbound pretenda ser senador.
De forma similar es posible simbolizar las frases siguientes, como p /\ q si
realizamos una asignacin apopiada a las variables p y q:
Lgica 45
El nmero n es un nmero primo menor que 100.
10 ~ x ~ 100
Henry Higgins era un soltero recalcitrante, pero El iza Doolitte conquist
su corazn.
Aunque haba sido un traficante de esclavos, John Newton termin siendo
un decidido oponente a la esclavitud.
I
La primera de las oraciones anteriores puede descomponerse en dos frases
-n es un nmero primo y n es menor que 100- aunque estn condensa-
das en una utilizando, segn es costumbre en el lenguaje coloquial. La segunda
tambin contiene dos frases ocultas, aunque en este caso el mtodo de sntesis
corresponde a las matemticas. En la tercera, el adverbio pero tiene en lgica
significado de la operacin y; introduce un matiz en la frase que no es necesa-
rio para la construccin de las proposiciones. En la cuarta frase, la proposicin
aunque indica la presencia de una y, a la vez que sirve para remarcar el con-
traste.
Podemos simbolizar la frase:
Algunos han nacido para la grandeza, algunos alcanzan la grandeza y
algunos soportan sobre s la grandeza
tanto por ((p 1\ q) 1\ r) como mediante (p 1\ (q 1\ r)). En la Seccin 3.2 se ver que
ambas expresiones lgicas son equivalentes, y que pueden eliminarse los parn-
tesis, quedando, por tanto, la expresin p 1\ q 1\ r. En la frase anterior, la prime-
ra coma equivale al operador 1\.
El operador v puede tener en castellano dos significados ligeramente dife-
rentes, por 10 que es necesario distinguirlo. En la frase:
Este banco proporcionar crdito a todo el que mantenga un saldo medio de
500 dlares o que tenga un certificado de depsito de ms de 5000 dlares.
El banco, evidentemente, no intenta excluir a aquellas personas que cumplan
simultneamente ambos requisitos. Por el contrario, podemos imaginar a un
padre diciendo: Puedes ir a la piscina o a la pista de patinaje, que quiere
decir que puede ir a uno u otro lugar, pero no a ambos. Mientras el banco
utiliza la o inclusiva que significa que ambas posibilidades son aceptables, el
padre utiliza la o exclusiva que significa que una de las dos posibilidades es
aceptable, pero no ambas a la vez.
En proposiciones como p => q, p recibe el nombre de antecedente y q el de
consecuente. Un ejemplo en castellano de una implicacin lgica es:
Si Phogbound resulta elegido, entonces estaremos apaados.
Aunque el adverbio entonces no suele incluirse en el lenguaje coloquial. Si
simbolizamos mediante p la frase Phogbound resulta elegido, y mediante q a
estaremos apaados, podemos representar toda la frase como p => q (que
IGIL.JIUIJIM... i.IISIIISlIILllj!IJ"".!lI!C,;aIllJIII ..lI!I!d!ll!lll .. \IIl,
46 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
significa p implica q). De forma alternativa, es posible reescribir esa frase en
la forma
Estaremos apaados si Phogbound resulta elegido,
aunque la frase anterior puede seguir representndose de forma simblica
como p => q.
Obsrvense las distintas utilizaciones que se hacen de la proposicin si, en
las siguientes frases:
Comprar entradas si representan Nuestro barrio.
Comprar entradas slo si representan Nuestro barrio.
Si representamos mediante r la proposicin representan Nuestro barrio y
mediante s la proposicin comprar entradas, la primera frase puede repre-
sentarse en la forma r =::> s. Cualquier persona que pronuncie esta frase no est
afirmando nada acerca de lo que hara si se representase Maebeth. En cambio,
la ltima frase tiene un significado ligeramente diferente, y que se simboliza
mediante s => r. Esta frase puede rehacerse de la forma si compro entradas,
entonces es que se representa Nuestro barrio; en definitiva, que la nica cir-
cunstancia que har que compre entradas es que se est representando Nuestro
barrio; En estas circunstancias, se dice que la proposicin s =::> r es la proposi-
cin recproca de r =::> s.
Otra propiedad importante de la implicacin p =::> q es que no es necesario
suponer la existencia de causalidad entre p y q. Por ejemplo, cuando decimos:
Si George toca bien la viola, entonces le seleccionarn para la orquesta,
implcitamente asumimos que si George es elegido para tocar en la orquesta, es
porque toca bien. La frase:
Si 1 + 1 = 2, entonces el sol es el centro del sistema solar.
Tambin se simboliza por p => q que, desde el punto de vista de la lgica, es
tan vlida como la afirmacin de George y la orquesta.
La causalidad es otra de las cosas que podemos expresar en lenguaje natu-
ral, pero que no podemos expresar en el clculo proposicional.
La expresin p q se utiliza para indicar que dos proposiciones son
lgicamente equivalentes; es decir, que una implica la otra y viceversa. Un
ejemplo tpico es el siguiente:
Sea T un tringulo de lados a, b y e. Entonces a
2
+ b
2
= e
2
slo si T es un
tringulo rectngulo.
Si representamos por p a
2
+ b
2
= e
2
, y por q T es un tringulo rec-
tngulo, la frase a
2
+ b
2
= e
2
si y slo si T es un tringulo rectngulo
Lgica 47
se representa mediante P ~ q. Es decir, que son ciertas simultneamente
tanto P => q como q => p.
Ejemplo 3.3. Se pueden representar como proposiciones oraciones en-
teras. Veamos un ejemplo relativamente complicado: Si conseguimos
los contratos de Dynamic Systems o de Metadyne, van Alstyne o Liu
realizarn tanto el anlisis como el diseo; a Frederick no se le asignar
el diseo, y Thompson ser despedido. Para poder escribir la proposi-
cin equivalente a esta frase, primero tenemos que asociar variables a
cada parte de la oracin.
DS
MD
VAA
L/VA
VAD
L/VD
FRA
TF
Conseguir el contrato de Dynamic Systems.
Conseguir el contrato de Metadyne.
Se le asigna el anlisis a van Alstyne.
Se le asigna el anlisis a van Liu.
Se le asigna el diseo a van Alstyne.
Se le asigna el diseo a Liu.
Se le asigna el anlisis a Frederick.
Thompson es despedido.
Con estas definiciones de variables, la oracin anterior puede represen-
tarse:
(DSvMD) =>
(((VAA 1\ VAD) v (L/VA 1\ L/VD 1\ "" FRA 1\ TF)
3.1.2. Evaluacin de proposiciones: Tablas de verdad
Recurdese que en el Captulo 2 definamos el concepto de estado de una
variable. Esta nocin puede aplicarse tambin a las proposiciones.
Definicin. Sean PI' ..., Pn las variables de una proposicin. El estado de
esas variables PI' ..., P
n
es el resultado de asignar los valores booleanos
verdadero o falso a cada una de ellas.
Por ejemplo, supongamos que tenemos la proposicin P v q. Puesto que la
proposicin consta slo de dos variables, cada una de las cuales puede tomar
slo dos valores posibles (verdadero o falso), existen slo cuatro posibles esta-
dos para las variables de la proposicin P v q. De forma alternativa, podemos
considerar la proposicin Pv q como una funcin en dos variables P y q, con
dominio {verdadero, falso} x {verdadero, falso} y con rango {verdadero, falso}.
As, al contrario que las funciones con dominios infinitos (tales como N o R), la
funcin Pv q tiene un dominio tan reducido que pueden tabularse sus valores
para todos los estados posibles de sus variables. Estas tablas reciben el nombre
48 Computacin /. Lgica, resolucin de problemas, algoritmos y programas
de tablas de verdad. La tabla de verdad de la funcin p v q se muestra en la
Figura 3.1.
p q pvq
verdadero verdadero verdadero
verdadero falso verdadero
falso verdadero verdadero
falso falso falso
Figura 3.1. Tabla de verdad para la funcin pv q.
En la tabla, se puede apreciar que el valor de la funcin es verdadero siempre
que cualquiera de las variables, o ambas, valga verdadero; en caso contrario
valdr falso. Esta definicin de la funcin es consistente con nuestra idea intui-
tiva acerca de la disyuncin, que se ilustr en la Seccin 3.1.1. Supongamos
que las variables p y q representan las proposiciones siguientes:
p Tenemos un saldo medio mayor de 500 $.
q Tenemos un certificado de depsito de ms de 5000 $.
Entonces, la proposicin p v q vale verdadero, siempre que p y q, o ambas a la
vez, sean verdaderas; en otro caso (p v q) valdr falso.
Las tablas de verdad de las otras operaciones de la lgica proposicional,
pueden construirse de forma anloga. Estas tablas se muestran en la Figura 3.2.
La mayora de los valores de estas operaciones son consistentes con las ideas
intuitivas introducidas en la Seccin 3.1.1. Asi, la negacin siempre devuelve el
valor contrario al de la variable, y la conjuncin lgica slo se evala a verda-
dero cuando ambas variables valen verdadero simultneamente.
El operador implicacin precisa una discusin ms cuidadosa, sobre todo
en el caso en que p vale falso. Lo anterior, no es dificil de entender si considera-
mos el ejemplo siguiente:
Si representan Nuestro barrio, entonces comprar entradas.
La frase anterior se representa por p ~ q. De hecho, si no se representa
Nuestro barrio, la variable p vale falso. Sin embargo, no est garantizado que
no queramos comprar entradas aunque no se represente Nuestro barrio; en su
lugar, podemos comprar entradas para Lnea de coros. Puesto que la falsedad
de p no garantiza la falsedad de q, podemos permitir que la proposicin resul-
tante sea, en este caso, verdadera. (Otra justificacin para esta decisin se
presentar en la Seccin 3.2.4.)
La tablas de verdad se pueden construir para proposiciones de complejidad
arbitraria. Cuando una proposicin involucra a ms de un operador, la evalua-
cin de su valor se realiza siguiendo el orden de prioridad de los operadores.
Esto se ilustra en el Ejemplo 3.4.
Lgica 49
P
q pAq
P
~ p
verdadero verdadero verdadero
verdadero falso verdadero falso falso
falso verdadero falso verdadero falso
falso falso falso
a) b)
p q p=q p q p<:o>q
verdadero verdadero verdadero verdadero verdadero verdadero
verdadero falso falso verdadero falso falso
falso verdadero verdadero falso verdadero falso
falso falso verdadero falso falso verdadero
e) d)
Figura 3.2. Tablas de verdad para proposICiones: (a) Negacin; (b) conjun-
cin; (e) implicacin; (d) equivalencia.
Ejemplo 3.4. Para construir la tabla de verdad de (p v q) = '" p comenza-
mos por p y q; a continuacin, se deriva la tabla para cada subproposicin
(p v q) y ~ p, combinando finalmente los resultados utilizando la tabla de
verdad de la operacin =. Habitualmente se trabaja siempre de izquierda a
derecha, tal y como se muestra abajo:
p q pvq ~ p
(p v q) =
~ p
verdadero verdadero verdadero falso falso
verdadero falso verdadero falso falso
falso verdadero verdadero verdadero verdadero
falso falso falso verdadero verdadero
Una forma alternativa de construir tablas de verdad es la de escribir la opera-
cin una nica vez y colocar el resultado de la evaluacin de cada subproposi-
cin debajo del operador correspondiente. Si lo hacemos as, debemos tener
cuidado de rellenar las columnas en el orden adecuado, como se muestra en la
tabla de verdad siguiente:
p q (p v q)
=
~ p
verdadero verdadero verdadero falso falso
verdadero falso verdadero falso falso
falso verdadero verdadero verdadero verdadero
falso falso falso verdadero verdadero
50 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
En este caso, comenzamos rellenando las columnas de p y q; a continua-
cin, rellenamos la columna de (p v q); a continuacin, la de "-' p, y finalmente
la columna correspondiente a =>. La tabla de verdad de la proposicin comple-
ta se corresponde con los valores de la ltima columna obtenida, que no se
corresponde forzosamente con la columna de ms a la derecha.
El nmero de filas de una tabla de verdad crece exponencialmente con el
nmero de variables presentes en la proposicin. Es decir, si una proposicin
tiene una variable como, por ejemplo, "-' p, su tabla de verdad tiene dos filas.
Proposiciones con dos variables como p v q tienen tablas de verdad de cuatro
filas. Proposiciones de tres variables tendrn ocho filas, puesto que existen
2
3
= 8 formas diferentes de asignar los valores verdadero y falso a las tres
variables. En general, el tamao de una tabla de verdad con n variables ser de
2
n
filas. Por este motivo, si trabajamos con ms de cuatro o cinco variables, el
tamao de las tablas de verdad resulta inmanejable.
Una forma de acortar la longitud de las tablas de verdad es mediante la
bsqueda de condiciones da igual. Por ejemplo, cuando evaluamos la propo-
sicin (p v p), si p vale falso, no importa lo que valga q; la proposicin se
evaluar a verdadero en cualquiera de los casos. Es decir, el valor de q es una
entrada da igual, y 10 denotaremos mediante un guin (-) en la columna
correspondiente de la tabla de verdad. Con esto, podemos reducir en uno el
nmero de filas de la tabla de verdad para p v q:
p
verdadero
falso
falso
q
verdadero
falso
pvq
verdadero
verdadero
falso
Utilizando esta tcnica, se pueden reducir de forma significativa el nmero de
lneas de las tablas de verdad de expresiones complejas, como se muestra en la
Figura 3.5.
Ejemplo 3.5. La proposicin (p /\ q) => (r v (p => s)) podra tener una tabla
de verdad completa de 16 lneas. Sin embargo, utilizando condiciones da
igual podemos reducir su tamao a cinco lineas, tal y como se muestra
debajo:
p q r s (p 1\ q) => (r v (p => s))
falso falso verdadero
falso falso verdadero
verdadero verdadero verdadero verdadero verdadero verdadero verdadero
verdadero verdadero falso verdadero verdadero verdadero verdadero verdadero
verdadero verdadero falso falso verdadero falso falso falso
Lgica 51
El proceso de construccin de tablas de verdad con entradas da igual
puede ser bastante complejo, tal y como sugiere el ejemplo. Cursos avanzados
en lgica yen diseo de circuitos tratan este tema ms cuidadosamente. Intuiti-
vamente podemos ver que, si reducimos el nmero de filas en una tabla de
verdad, reduciremos tambin la complejidad de cualquier circuito representa-
do por la proposicin. Esta es una de las actividades cruciales en el diseo de
l(ls computadoras modernas: un objetivo primordial es la minimizacin del
nmero de circuitos y, por tanto, la reduccin del costo de fabricacin de la
computadora. Estas ideas sern abordadas en el Captulo 7.
3.1.3. Tautologas
Algunas proposciones se distinguen por el hecho de que son siempre verdaderas.
Es decir, cualquiera que sea la asignacin de valores a sus variables, siempre se
obtendr el valor verdadero en la ltima columna de la evaluacin de la propo-
sicin. Formalmente, estas proposiciones reciben el nombre de tautologas.
Definicin. Una tautologa es una proposicin que se evala a verdadero
en cualquier estado; una contradiccin es una proposicin que se evala a
falso en cualquier estado.
Podemos comprobar si una proposicin es una tautologa sin ms que escribir
su tabla de verdad. Tambin existen otros mtodos para comprobar si una
proposicin compleja es o no una tautologa. Estos mtodos implican el desa-
rrollo de demostraciones, y se estudiarn en la Seccin 3.2.3. Las demostracio-
nes de la lgica juegan un papel trascendental en la informtica, por lo que les
dedicaremos un inters especial en este captulo.
Ejemplo 3.6. Para verificar que la proposicin (p 0= q) /\ p) 0= q es una
tautologa, podemos desarrollar su tabla de verdad y examinar la columna
ms a la derecha para comprobar que todas las entradas son verdadero.
p q ((p =;. q) /\ p) =;. q
verdadero verdadero verdadero verdadero verdadero
verdadero falso falso falso verdadero
falso verdadero verdadero falso verdadero
falso falso verdadero falso verdadero
Ejemplo 3.7. La proposlcIOn' p /\ "V P es una contradiccin. Esto puede
verse en la tabla de verdad siguiente:
p
verdadero
falso
falso
verdadero
falso
falso
52 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Esto confirma algo intuitivo: es imposible para una proposicin ser simul-
tneamente verdadera y falsa. Igualmente, p v '" p es una tautologa.
p
verdadero
falso
falso
verdadero
pv
verdadero
verdadero
La aseveracin de que p v '" p es una tautologa recbe el nombre de ley del
exclusin del caso intermedio. Es decir, para cualquier proporcin, ella misma o
su negacin deben ser cierta; no existe una tercera posibilidad. Esto significa que
algunas frases que son comunes en el lenguaje coloquial, como la frase que est
leyendo ahora es falsa, estn excluidas del clculo proposicional. Se han desa-
rrollado otros modelos lgicos que no incluyen la ley de exclusin del caso
intermedio; estos modelos son de gran utilidad en el estudio de las bases de
datos. La ley de exclusin del trmino medio, junto con el hecho de que la
proposicin p 1\ "-' P es una contradiccin, nos indica que cualquier proposicin,
o es una tautologa o no lo es; no puede ser ambas cosas al mismo tiempo.
Ejemplo 3.8. La proposicin '" (p 1\ q) Y('" Pv '" q) tienen la misma tabla
de verdad.
p q

verdadero verdadero falso falso falso falso
verdadero falso falso verdadero verdadero verdadero
falso verdadero verdadero falso verdadero verdadero
falso falso verdadero verdadero verdadero verdadero
La aseveracin de que "-' (p 1\ q) Y ('" Pv '" q) tienen la misma tabla de
verdad, constituye una de las tres aseveraciones que conjuntamente constitu-
yen las denominadas Leyes de Margan. Estas leyes son muy tiles en la simplifi-
cacin de proposiciones compuestas, especialmente si contienen negaciones. La
segunda Ley de Morgan se analiza en el ejercicio 3.6.
Ejercicios
3.1. Razonar cules de las frases siguientes constituyen una proposicin:
a) En esta pgina hay 512 palabras exactamente.
b) 314159 es un nmero primo.
e) Xl + 2x + 1 = 13.
d) La edad del universo es de unos 17 billones de aos, aproximada-
mente.
e) Disparad al pianista.
Lgica 53
f) x - y = o.
g) Por qu es azul el cielo?
h) La hipotenusa es el lado ms corto de un tringulo rectngulo.
3.2. Construir las proposiciones siguientes a partir de variables, aplicando
una regla de la definicin en cada paso.
u) (p => (p /\ q))
h) ((( "-' p) -= q) /\ ( "-' r))
e) (p v ( "-' q)) /\ (p V q)) => p)
3.3. Representar las frases siguientes, de forma simblica, utilizando proposi-
ciones. Definir claramente qu significa cada variable.
a)
b) Aunque Manderson tena una mente fina y analtica y grandes rique-
zas, estaba incomprensiblemente loco.
e) Bien Trent estaba en Pars mientras Mabel estaba en Londres, bien
Trent estaba en Venecia mientras Mabel estaba en Pars.
d) Una definicin es recursiva slo si incluye un paso de inicializacin y
otro de induccin.
e) Siempre que Thomas y Dumars disparen bien, los Pistons ganarn, a
no ser que Rodman est lesionado y Laimber batee mal, en cuyo
caso los Pistons perdern.
f) Si el grupo de diseo cometiera un error, seran los principales res-
ponsables, y los dems tendran una responsabilidad secundaria; si el
grupo de programadores cometiera un error de codificacin, enton-
ces el grupo de Ted o el de Louis sera el principal responsable; si el
error fuera de prueba, tanto el grupo de FouSen como el de Rita
seran los principales responsables.
3.4. De acuerdo con la definicin, cules de las siguientes son proposiciones
vlidas?
verdadero
(verdadero)

p => "-'q)
(p V "-' p) /\ q))
(p => p) /\ "-' q) => q)
3.5. Construir las tablas de verdad de las proposiciones siguientes, utilizando
condiciones da igual siempre que resulte apropiado. Identificar las tau-
tologas.
a) p => q) /\ p) => q
b) pp => r) /\ (q => => (p /\ q)
e) p /\ (q V r) => S
d) (p =>q) /\ (q => r)) => (p => r))
54 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
e) ((p => (q /\ "-'q)) => p)
f) (p => q) V (p <o:> '" q)
3.6. Demostrar que '" (p v q) y ("-' P/\ "-' q) tienen la misma tabla de verdad.
3.2. RAZONAMIENTO CON PROPOSICIONES
1
En esta seccin se analizan algunos aspectos fundamentales del razonamiento
con proposiciones. En este contexto, razonamiento significa desarrollo de nueva
informacin a partir de otra dada, expresada en forma de proposiciones (y
como predicados).
Es necesario desarrollar mtodos que permitan determinar cundo dos
proposiciones son equivalentes, de forma que una pueda ser sustituida por la
otra. Es tambin necesario encontrar una forma alternativa a las tablas de
verdad, para determinar cundo una proposicin arbitraria es una tautologa.
Finalmente, es necesario explorar cmo los mtodos de razonamiento pueden
ayudarnos a resolver problemas lgicos que estn planteados en castellano.
Todas estas tcnicas constituyen una preparacin necesaria para una fase pos-
terior, en la que utilizaremos tcnicas de razonamiento para analizar varias
caractersticas de programas escritos en Pascal (Captulo 6) y en el diseo de
computadoras (Captulo 7).
3.2.1. Equivalencia
Considrese la proposicin (p /\ q) V (p /\ "-' q), cuya tabla de verdad se mues-
tra abajo:
p q (p /\ q) V (p /\ ~ q )
verdadero verdadero verdadero
verdadero falso verdadero
falso verdadero falso
falso falso falso
Los valores de la ltima columna de la tabla son exactamente los mismos que
los de la columna de la p; por tanto, podemos decir que (p /\ q) V (p /\ '" q) es en
cierta manera equivalente a p. Por tanto, si en alguna situacin nos encontra-
mos con (p /\ q) V (p /\ '" q) podemos sencillamente reemplazarla por p.
En cuanto empezamos a razonar con proposiciones, se ve la necesidad de
simplificar proposiciones complejas. Nuestro propsito ahora ser el de definir
qu significa que dos proposiciones sean equivalentes, y el ver cmo esta equi-
valencia permite simplificar expresiones complejas.
Definicin. Se dice que dos proposiciones p y q son equivalentes si tienen
el mismo valor para cada estado. En otras palabras, p y q son equivalentes
si tienen la misma tabla de verdad.
Lgica 55
Por tanto, una forma de comprobar si dos proposiciones son equivalentes es
escribiendo su tabla de verdad. Existe otro mtodo que generalmente es ms
eficaz, basado en el siguiente teorema.
Teorema. Dos proposiciones p y q son equivalentes y lo simbolizamos
como p == q, si y slo si la proposicin p <:o> q es una tautologa.
El teorema no es dificil de probar. Primero, supongamos que p y q son
equivalentes. Entonces en cualquier estado ambas son bien verdaderas bien
falsas. Por tanto, en cualquier estado p <:o> q es bien (verdadero <:o> verdadero)
bien (falso <:o> falso) haciendo de p <:o> q una tautologa. Por el contrario,
supongamos ahora que p <:o> q es una tautologa, y que S es un estado en que p
es falso. Puesto que p <:o> q es una tautologa, q tiene que ser tambin falso.
Igualmente, si S es Un estado en que p es verdadero, entonces q tambin debe
serlo en ese estado.
3.2.2. Propiedades de la equivalencia
La equivalencia tiene una serie de propiedades que se verifican para todas las
proposiciones, y que son de gran utilidad en varias aplicaciones de la lgica.
En la Tabla 3.2 se resumen las ms importantes.
Tabla 3.2. Propiedades de la equivalencia
Conmutatividad' Asociatividad
p A q == q A P PA (q A r) == (p A q) A r
p v q == q v p p v (q v r) == (p v q) v r
Distributividad
p A (q V r) == (p A q) V (p A r)
p v (q A r) == (p v q) A (p V r)
Ley de la implicacin
p =q == ~ p v q
Propiedad de la negacin
~ ( ~ p ) == p
Ley de la exclusin del trmino medio
p v ~ p == verdadero
v -simplificacin
pvp == p
p v verdadero == verdadero
p v falso == p
pV(pAq) == P
Leyes de Morgan
~ ( p v q ) == ~ p A ~ q
~ ( p A q ) == ~ p v ~ q
Ley de la bicondicionalidad
p<o>q==(q=q)A(q=p)
Identidad
p == p
Ley de la contradiccin
pA ~ p == falso
A -simplificacin
pAp == P
PA verdadero == p
p A falso == falso
p A(p V q) == p
56 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
Obsrvese que muchas de estas expresiones tienen una paralela en las que
fueron estudiadas para los conjuntos (vase Tabla 2.1). Adems, muchas de
estas propiedades tienen tambin una anloga en la aritmtica. As, las propie-
dades conmutativa, asociativa y distributiva permiten la simplificacin de ex-
presiones aritmticas. De una forma similar la asociatividad, conmutatividad y
distributividad introducidas en la Tabla 3.2 permiten la simplificacin de pro-
posiciones lgicas.
Estas propiedades se utilizan de diversas maneras. Por ejemplo, la conmu-
tatividad se utiliza para reordenar las proposiciones y as poder realizar otras
simplificaciones. La asociatividad permite la eliminacin de parntesis. Por
ejemplo, puesto que p /\ (q /\ r) == (p /\ q) /\ r, de forma equivalente es posible
escribir p /\ q /\ r. Las leyes de la distributividad permiten la factorizacin de las
proposiciones. Esta leyes totalmente equivalente a la ley aritmtica que permi-
te escribir 3 x 5 + 3 x 7 = 3 x (5 + 7). Las leyes de Morgan son de gran
utilidad cuando se trabaja con expresiones que incluyen negaciones. La ley de
la implicacin permite escribir expresiones equivalentes a la implicacin, pero
utilizando slo v, /\ Y "'.
Antes de utilizar las leyes de la equivalencia es necesario convencerse de
que son correctas. Para ello es suficiente construir una tabla de verdad para
cada lado de la equivalencia y verificar que ambas tablas son idnticas. De-
mostraremos lo anterior para la ley de la implicacin, dejando el resto como
ejercicio.
Ejemplo 3.9. Para demostrar que (p ~ q) == ('" p v q), podemos construir
sus tablas de verdad de la forma siguiente:
p q p=q -pvq (p = q ) ~ ( - p v q )
verdadero verdadero verdadero verdadero verdadero
verdadero falso falso falso verdadero
falso verdadero verdadero verdadero verdadero
falso falso verdadero verdadero verdadero
Simplificacin de proposiciones mediante la utilizacin de las propiedades de la
equivalencia. Centremos nuestra atencin en la simplificacin de proposicio-
nes. Entendemos por simpllfzcacin el proceso de modificar una proposicin
para que resulte ms til a un determinado propsito, como el conseguir que
contenga menos variables y/o operadores que la proposicin original.
Para simplificar una proposicin, escribimos una serie de pasos numerados.
Cada paso se compone de una proposicin en la parte izquierda, y de una
referencia a una ley particular en la parte derecha. La proposicin de la iz-
quierda es siempre equivalente a la del paso inmediatamente anterior, en vir-
tud de la propiedad escrita en la derecha. Por ejemplo, supongamos que se
desea reducir la proposicin (p ~ q) v (p ~ r). En el paso 1 se escribe la
proposicin, y los pasos 2 al 4 contienen las proposiciones equivalentes.
1. (p => q) /\ (p => r)
2. (- p v q) /\ ( - Pv r)
3. '" p v (q /\ r)
4. p => (q /\ r)
Ley de implicacin
Distributividad
Ley de la implicacin
Lgica 57
Donde puede observarse que la proposicin del paso 2 resulta de la del paso 1,
tras la aplicacin de la ley de la implicacin. La del paso 3 se obtiene de la
del '2 aplicando la distributividad, y la del 4 se obtiene de la del 3 por la ley de
la implicacin. El Ejemplo 3.10 es ms complicado:
Ejemplo 3.10. En el Ejercicio 3.5a se utiliz una tabla de verdad para
demostrar que la proposicin ((p => q) /\ p) => q es una tautologa. Pueden
utilizarse las propiedades de la equivalencia para demostrar de nuevo que
lo es. En este caso demostraremos que la proposicn anterior es equivalen-
te a la proposicin simple verdadero.
1. ((p => q)/\p) => q
2. ((-pvq)/\p) => q
3. (( - P/\ p) V (q /\ p)) => q
4. (falso v (q /\ p)) => q
5. (q /\ p) => q
6. - ((q /\ p) /\ - q)
7. - ((p /\ q) /\ - q)
8. - (p /\ (q /\ - q))
9. -(p/\falso)
10. - falso
11. verdadero
Ley de implicacin
Distriti butividad
Contradiccin
v -simplificacin
Ley de la implicacin
Conmutatividad
Asociatividad
Ley de la contradiccn
/\ -simplificacin
Negacin
El ejemplo 3.10 se ha desarrollado con excesivo detalle; cada propiedad se
ha aplicado en un paso separado. Cuando nos familiaricemos ms con estas
propiedades, ser posible abreviar los clculos. De hecho, es lo mismo que en
el caso del lgebra, donde nuestra familiaridad y costumbre en la manipulacin
de expresiones complejas nos permite la simplificacin mediante la aplicacin
de varias reglas a la vez. Como ejemplo, obsrvense las dos simplificaciones
siguientes:
1. 5x + 1 = 3x + 2
2.2x=1
3. x = 1/2
1. 5x + 1 = 3x + 2
2. (5x + 1) - 1 = (3x + 2) - 1
3. 5x + (1 - 1) = 3x + (2 - 1)
4. 5x + O = 3x + 1
5. 5x = 3x + 1
6. 5x - 3x = (3x + 1) - 3x
7. (5 - 3)x = (1 + 3x) - 3x
8. 2x = 1 + (3x - 3x)
9. 2x = 1 + (3 - 3)x
10. 2x = 1 + Ox
58 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
11. 2x=1
12. (1/2)2x = 1/2
13. ((1/2)2)x = 1/2
14. Ix = 1/2
15. x = 1/2
La simplificacin en tres pasos de la izquierda es lo habitual cuando se
conocen bien las propiedades de la aritmtica, mientras que la simplificacin
en 15 pasos es lo habitual en los aprendices del lgebra. Con este libro se
pretende alcanzar un conocimiento suficiente de la lgica, de manera que las
simplificaciones se parezcan ms a la de la izquierda, es decir, que se realicen
aplicando varias leyes en cada paso. Sin embargo, el conocimiento de las
propiedades en que se basan estos argumentos, es fundamental para entender
claramente el proceso realizado.
El ejemplo 3.11 muestra una serie de pasos ms corta, en la simplificacin
de la proposicin (p => (q /\ r)) /\ ( ~ p => (q /\ s)). En ella q aparece como parte
del consecuente de dos condiciones diferentes, que estn conectados con el
operador /\. En la simplificacin se extrae q de ambas, de forma que la propo-
sicin puede escribirs como la conjuncin de q con dos implicaciones.
Ejemplo 3.11. Simplificar la proposicin (p => (q /\ r)) /\ ( ~ p => (q /\ s)):
1. (p => (q /\ r)) /\ ( ~ p => (q /\ s))
2. ( ~ p v (q /\ r)) /\ (p V (q /\ s))
3. ( ~ p v q) /\ ( ~ Pv r) /\ (p V q) /\ (p V s)
4. (( ~ P/\ p) V q) /\ ( ~ Pv r) /\ (p V s)
Ley de la implicacin, negacin
Distributividad, asociatividad
Conmutatividad,
distributividad
Ley de la contradiccin
v -simplificacin
Ley de la implicacin
3.2.3. Reglas de inferencia: La idea de demostracin
Cuando se estudia la lgica, el primer objetivo es el de conseguir patrones de
razonamiento. Sera deseable encontrar una metodologa que nos permitiera
afirmar cundo una determinada conclusin es vlida -es decir, si es o no una
tautologa-o Sabemos que las tablas de verdad son un buen instrumento
cuando trabajamos con proposiciones sencillas, pero que resultan tediosas
cuando las proposiciones contienen ms de tres o cuatro variables u operado-
res.
Por tanto, pretendemos encontrar una metodologa alternativa que nos
permita llegar a conclusiones vlidas de una forma legtima. En dicha metodo-
loga, denominada demostracin, el criterio de razonamiento consiste en el
encadenamiento de una serie de pasos o inferencias, cada una de las cuales es
encadenable con la siguiente de una manera justificable formalmente. El proceso
Lgica 59
de demostracin es una extensin de la metodologa desarrollada para simpli-
ficar proposiciones. Sin embargo, las demostraciones contienen un ingrediente
adicional de gran importancia: se realiza una inferencia a partir de una suposi-
cin. Las inferencias de una demostracin se realizan aplicando un reducido
conjunto de reglas de inferencia. Es decir, las reglas de inferencia permiten
obtener proposiciones a partir de otras, de las que se conocen si son verdade-
ras o se supone que lo son. Estas reglas se resumen en la Tabla 3.3.
Definicin. En el clculo proposicional, una demostracin es una secuen-
cia de pasos que sirven para demostrar que una determinada proposicin p
es una tautologa. Cada paso de la demostracin es bien una proposicin
ya demostrada, bien una proposicin que se ha obtenido de otra anterior
utilizando una regla de inferencia, o bien una proposicin que se introduce
como suposicin para preparar un paso posterior. Este ltimo tipo de
proposiciones (suposicin) lo simbolizamos ponindolo entre corchetes
cuadrados [y]; todos los dems pasos se acompaan de una justificacin; y
el ltimo paso de la demostracin debe ser la propia p.
La sencilla prueba del ejemplo 3.12 muestra que p => p es una tautologa.
Podramos demostrar esto utilizando una tabla de verdad, pero representa una
buena oportunidad para introducir la notacin y estilo de las demostraciones.
Ejemplo 3.12. Demostrar p => p:
1. [p]
2. p
3. p => p
1
=>-introduccin, 1, 2
La primera lnea contiene la suposicin [p]. Al comienzo de la demostracin,
podemos suponer cualquier cosa que creamos que puede llevarnos a la con-
clusin.
La suposicin, junto con los pasos subsiguientes que se obtienen de ellas,
suealen presentarse sangrados, de forma que la lgica de pasos subsiguientes
pueda distinguirse del resto de la prueba. Puesto que suponemos que p es
verdadero, se puede deducir que p es verdadero, luego el paso 2 se obtiene del 1
directamente. Colocamos un 1 en la columna de la derecha de la demostra-
cin como justificacin del paso realizado. A continuacin utilizamos la regla
de inferencia de la =>-introduccin (sustituyendo p por q en la frmula general
de la Tabla 3.3) con lo que se concluye en el paso 3 que p => p es una
tautologa.
La Tabla 3.3 fue desarrollada por el matemtico alemn Gerhard Gentzen.
En ella se reflejan las reglas de inferencia que se utilizan en el razonamiento
normal, y que constituyen las bases de la mayora de los estudios y aplicacio-
nes de la lgica formal. Cada regla de la tabla tiene la forma:
p
q
60 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
P/\q
-q-
Tabla 3.3.
=-introduccin
[p]
-q--
p=q
=-eliminacin
(modus ponens)
p=p
-p-
q
(modus tollens)
p=q
::!L

/\ -introduccin
p
-q-
P/\q
/\ -eliminacin
P/\q
-p-
Reglas de inferencia

p=q
q=p



p=q q=p
-introduccin
[p]
falso

-eliminacin
falso
p
v -introduccin
-p- -q-
pvq pvq
v -eliminacin
[p] [q]
pv q r r
r
La propoSlclOn p que aparece encima de la lnea indica un paso anterior
(suposiciq u otro) que ya aparece en la demostracin. La proposicin q que
aparece debajo de la lnea puede obtenerse o ser iriferida en el siguiente paso de
la demostracin. Asi, la regla denominada =>-introduccin en las tablas permite
realizar la inferencia p => q en cualquier paso de la demostracin, en la que p
aparece como suposicin y q como conclusin en un paso subsiguiente.
Una comparacin cuidadosa entre estas reglas y algunas de las propiedades
de la equivalencia que se muestran en la Tabla 3.2, pone de manifiesto algunas
similitudes interesantes. Por ejemplo, la ley de la bicondicionalidad dada en
la tabla, conduce directamente a las dos reglas de inferencia denominadas
<=>-introduccin y <=>-eliminacin de la Tabla 3.3. De forma similar, la ley de la
contradiccin de la Tabla 3.2 conduce directamente a la regla de inferencia de
la eliminacin. Sin embargo, muchas de las reglas de inferencia no tienen
ningn precedente, entre las propiedades de la equivalencia.
Las reglas de inferencia pueden utilizarse como alternativa a las tablas de
verdad en la demostracin de que una determinada proposicin es una tauto-
loga. Sin embargo, como veremos ms adelante, las demostraciones son ms
Lgica 61
verstiles que las tablas de verdad, puesto que las tablas de verdad son inmane-
jables cuando analizamos las proposiciones de ms de tres o cuatro variables, y
adems no aportan ninguna base para razonar con proposiciones de forma
deductiva.
Podemos autoconvencernos, de forma intuitiva, de que las reglas de infe-
rencia tienen sentido. Por ejemplo, la regla de la 1\ -introduccin nos dice que si
hllmos demostrado que p y q son tautologas en dos pasos anteriores cuales-
quiera de la demostracin, en el paso actual podemos concluir que p 1\ q es una
tautologa. De forma similar, la regla de la ==>-eliminacin (conocida familiar-
mente como modus ponens), simplemente establece que, si en un paso anterior
hemos demostrado que p ==> q y que p es una tautologa, en el paso actual
podemos concluir que q es una tautologa.
En las demostraciones procederemos paso a paso para conseguir, en cada
uno de ellos, una nueva tautologa que nos acerque ms a nuestra meta -la
ltma proposicin de la prueba--. Justificaremos cada paso realizado, bien en
la utilizacin de una regla de equivalencia (mediante la sustitucin de una
parte derecha de una expresin de la Tabla 2.3, por una parte izquierda, o vi-
ceversa), bien mediante la utilizacin de una regla de inferencia. Adicionalmen-
te a lo anterior, es preciso desarrollar estrategias de demostracin; es decir, m-
todos de realizar demostraciones que puedan ser de utilidad en diferentes
situaciones. Estas situaciones se dan no slo en la lgica, sino tambin en
varias aplicaciones de la informtica, las matemticas y la ciencia en general.
3.2.4. Estrategias de demostracin
En esta seccin se estudian algunas estrategias bsicas para demostrar que una
proposicin es una tautologa, mediante la utilizacin de las propiedades de la
equivalencia y las reglas de inferencia.
Demostracin deductiva. Una demostracin deductiva es aquella en que se
utilizan las reglas de inferencia para deducir las conclusiones, despus de haber
realizado una o ms suposiciones para comenzar el proceso de demostracin.
El ejemplo 3.13 es un ejemplo sencillo.
Ejemplo 3.13. Demostrar que p ==> (q ==> p)
1. [p]
2. [q]
3. p
4. q => p
5. p ==> (q => p)
Suposicin
Suposicin
1
=>-introduccin, 2, 3
=>-introduccin, 1, 4
Si se intenta demostrar que una proposicin de la forma p ==> q es una tautolo-
ga, es aconsejable comenzar suponiendo p y tratar de encontrar una serie de
pasos que nos conduzcan a q. Si lo conseguimos, el ltimo paso de la demos-
62 Computacin J. Lgica, resolucin de problemas, algoritmos y programas
tracin ser la propia p q. Esta estrategia fue utilizada en los Ejemplos 3.12
y 3.13.
Utilizacin del modus ponens. Supongamos que alguien dice: Si abres la
jaula, se escapar el tigre y supongamos que yo abro la jaula. La conclusin
seguramente ser, por modus ponens, que el tigre escapar. Anlogamente, si
oimos a alguien decir: Si representan Nuestra Ciudad, comprar entradas, y
descubrimos que estn representando Nuestra Ciudad, podemos concluir que
esa persona comprar entradas. En el Ejemplo 3.14 podemos ver cmo se
utiliza el modus ponens en una demostracin.
Ejemplo 3.14. Demostrar que ((p q) 1\ (r p) 1\ r) q:
1. ((p q) 1\ (r p) 1\ r)
2. r p
3. r
4. p
5. p q
6. q
7. ((p q) 1\ (r p) 1\ r) q
Suposicin
1\ -eliminacin, 1
1\ -eliminacin, 1
Modus ponens, 2, 3
1\ -eliminacin, 1
Modus ponens, 4, 5
1,6
Utilizacin de la I\-eliminacin y modus tollens. En el Ejemplo 3.15 se desa-
rrolla una demostracin utilizando una combinacin de las reglas de inferencia
I\-eliminacin y modus ponens. Como en casos anteriores, se parte de suposi-
ciones cuidadosamente elegidas y trabajamos deductivamente a partir de ellas.
Ejemplo 3.15. Demostrar ((p q) 1\ '" q) '" p:
1. [(p q) 1\ '" q]
2. p q
3. '" P
4. '" P
5. ((p q) 1\ '" q) '" p
Suposicin
1\ -eliminacin, 1
1\ -eliminacin, 1
Modus tollens, 2, 3
1, 4
Utilizacin de la '" -eliminacin y de la '" -introduccin. La segunda regla de
'" -eliminacin dice que cuando partimos de una suposicin falsa cualquier
conclusin p es una tautologa. As, podemos realizar una argumentacin lgi-
ca muy sofisticada en la que una suposicin no vlida (no importa cmo de
nimia pueda ser sta) hace que todos nuestros razonamientos sean errneos.
Muchas argumentaciones pueden ser vlidas, tanto en cuanto no dependan de
suposiciones falsas.
Ejemplo 3.16. Demostrar, sm utilizar modus tollens, la proposicin
((p q) 1\ "'q) p:
Lgica 63
[p]
q
"'q
falso
1.
2.
3.
4.
5.
6.
1-
8. '" P
9. ((p "'q) ",p
Suposicin
A -eliminacin, 1
A -eliminacin, 1
Suposicin
Modus ponens, 2
3
'" -eliminacin 5, 6
'" -introduccin, 4
1, 8
El ejemplo 3.17 es algo ms complicado.
Ejemplo 3.17. Demostrar (p (q r)) ((p q) (p r)):
[p (q r)]
[p q]
[p]
q

r
1.
2.
3.
4.
5.
6.
7. P r
8. (p q) (p r)
9. (p (q r)) ((p q) (p r))
(La justificacin de los distintos pasos de la demostracin se dejan al lector
como ejercicio.)
Utilizacin de la bicondicionalidad en las demostraciones. Para demostracio-
nes de proposiciones de la forma p q, una estrategia que suele ser eficaz es
demostrar primero que p q y despus que q p, utilizando posteriormente
la regla de la como ltimo paso de la demostracin.
Suposicin
Suposicion
Suposicin
A-introduccin, 2, 3
'" -introduccin, 4
'" -eliminacin, 5
3, 6
Suposicin
['" p v q]
["'p]
[p]
pA ",p
falso
q

[q]
Ejemplo 3.18. Para demostrar que (p q) ('" p v q), primero se de-
muestra que (p q) ('" p q) es una tautologa (pasos 1-13), y poste-
riormente se demuestra que ('" p v q) (p q) es una tautologa (pasos
14-22). Finalmente, se aplica la regla de la como ltimo
paso de la demostracin. La estrategia seguida en los pasos 1-11 para
demostrar que p q puede realizarse suponiendo '" p (paso 2) o bien q
(paso 8).
1.
2.
3.
4.
5.
6.
7.
8.
64
Computacin l. Lgica, resolucin de problemas, algoritmos y programas
9.
[p]
In
q
11.
p=>q
12.
p => q
13. ( '" Pv q) => (p => q)
14.
.[p => q]
15.
pv"'p
16.
[p]
17.
q
18.
"'pvq
19.
["'p]
20.
'" p v q
21.
"'pvq
22. (p => q) => ('" p v q)
23. (p => q) ('" p v q)
Suposicin
8
=>-introduccin, 9, 10
v-eliminacin, 1, 2
=>-introduccin
Suposicin
Ley de exclusin del caso intermedio
Suposicin
Modus ponens, 14, 16
v -introduccin, 17
Suposicin
v -introduccin, 19
v -eliminacin, 15, 16, 18, 19, 20
=>-introduccin, 14, 21
13, 22
Demostracin por contradiccin (reduccin al absurdo). La regla de inferencia
de la '" -introduccin es la base de una importante estrategia de demostracin
conocida como demostracin por contradiccin. Una aplicacin tpica de esta
tcnica en las matemticas podra ser la siguiente: Sea T un tringulo de lados
2, 3 Y 4. Supongamos que queremos demostrar que T no es un trngulo
rectngulo. Si suponemos lo contrario, que T es un tringulo rectngulo, pode-
mos concluir por el teorema de Pitgoras que la longitud de la hipotenusa,
elevada al cuadrado, es igual a la suma de los cuadrados de los otros dos lados;
esto es, 2
2
+ 3
2
= 4
2
Sin embargo, 4 + 9 i= 16. Esto conduce, utilizando la
eliminacin, al valor falso. Entonces, por la '" -induccin, la hiptesis original
-Tes un tringulo rectngulo- es tambin falsa.
Supongamos que queremos demostrar que p => q) /\ p) => q es una tauto-
loga. Supongamos que es falsa en cualquier caso -es decir, que la negacin es
una tautologa- y analicemos si esta suposicin nos conduce a una contradic-
cin. Esta es la estrategia seguida en el ejemplo 3.19.
Ejemplo 3.19. Demostrar p => q) /\ p) => q:
1. ['" (p => q) /\ p) => q)]
2. ",(",p => q)/\p)vq)
3. '" q
4. p => q) /\ p)
5. (p => q)
6. p
7. q
8. Falso
9. p => q) /\ p) => q
Suposicin
=>-eliminacin, 1
Ley de Morgan, /\-eliminacin, 2
/\-eliminacin, 2
/\ -eliminacin, 4
/\-eliminacin, 4
Modus ponens, 5, 6
'" -eliminacin, 3, 7
'" -introduccin, 1, 8
Lgica 65
3.2.5. Resolucin de problemas de la vida real
La lgica y los mtodos de demostracin pueden utilizarse en una gran
variedad de problemas lgicos o problemas de la vida real, en los que puede
obtenerse informacin nueva, a partir de una pequea cantidad de informa-
cin inicial. En los Ejemplos 3.20 y 3.21 se utilizan las propiedades de la
las reglas de inferencia y las tcnicas de demostracin:
Ejemplo 3.20. Los deseos son caballos, a condicin de que los caballos
no vuelen. Tambin, los mendigos no cabalgan, a condicin de que los
deseos no sean caballos. Si se da el caso de que los mendigos cabalgan y
los deseos no sean equinos, entonces los caballos vuelan. Si la imposibi-
lidad de los caballos para volar y la imposibilidad de los mendigos para
cabalgar no son alternativas, entonces los mendigos no son ricos. Pero
los mendigos cabalgan, son ricos los mendigos?
El primer paso para resolver problemas como este, es el de introdu-
cir variables que representen cada una de las proposiciones bsicas que
contiene. Como suele ser habitual en problemas de la vida real, como es
este, las frases constituyen un pequeo jeroglfico que hay que descifrar.
En cualquier caso, supongamos que introducimos las variables siguientes:
W
HF
BRD
BRCH
Los deseos son caballos
Los caballos vuelan
Los mendigos cabalgan
Los mendigos son ricos
Es posible representar las cinco frases de que consta el problema origi-
nal mediante las proposiciones siguientes, respectivamente:
1. -HF W
2. - W - BRD
3. - (BRD /\ - W) HF
4. - ( - HF v - BRD) - BRCH
5. BRD
Utilizndolas igual que utilizaramos suposiciones en una demostracin
ordinaria, es posible escribir la serie de inferencias siguiente, haciendo
referencia la ltima a la variable BRCH que es la que nos interesa:
6. W
7. -BRDv W HF
8. -BRDv W
9. HF
10. BRD/\HF
11. (HF /\ BRD) - BRCH
12. -BRCH
Modus tollens, 2, 5
Leyes de Morgan, 3
v-introduccin, 6
Modus ponens, 7, 8
/\-introduccin, 5, 9
Leyes de Morgan, 4
Modus ponens, 10, 11
Con lo que se demuestra que los mendigos no son ricos.
66 Computacin /. Lgica, resolucin de problemas, algoritmos y programas
Ejemplo 3.2.1. Los martes, o Timson est en el cementerio o Agnes
est en la sacrista. No es posible encontrar a Timson en el cementerio
sin Stanley. Stanley slo abandona los martes el cementerio, cuando va
a pasear con Agnes. Si Hutchinson cometi el robo, Stanley no estaba
en el cementerio. El robo se produjo en martes. Pudo ser Hutchinson
el ladrn?
Utilicemos las variables siguientes:
p Timson estaba en el cementerio
q Agnes estaba en la sacrista
s Stanley estaba en el cementerio
h Hutchinson fue el ladrn
u El robo fue en martes
Ahora es posible simbolizar el prrafo problema de la forma siguiente:
1. u => (p V q)
2. p => S
3.
4.
5.
S
q=>s
S

Para poder deducir algo sobre la variable h, que es la que nos interesa,
podemos razonar de la manera siguiente:
Modus ponens, 1, 5
Suposicin
Modus Tollens, 3, 7
=>-introduccin, 7, 8
v-eliminacin, 2, 6, 9
Modus tollens, 4, 10
6. pvq
7. [q]
8.
9.
10.
11.
Por 10 que Hutchinson no fue el ladrn.
Ejercicios
3.7. Utilizar tablas de verdad para demostrar que las expresiones siguientes
son equivalencias.
a) p v (q /\ r) == (p v q) /\ (p V r)
b) ==
c) p => q == /\ "'-'q)
d) p v falso == p
e) p /\ verdadero == p
f) P/\ (p V q) == p
3.8. Encontrar todas las correspondencias entre las propiedades de la equiva-
lencia entre proposiciones (Tabla 3.2), y las propiedades de la equivalen-
cia entre conjuntos (Tabla 2.1).
Lgica 67
3.9. Simplificar las proposiciones siguientes, encontrando otra equivalente
con menos operadores y/o variables:
a) (pvq)/\("'pv"'q)
b) (p /\ q) V (p /\ '" q) V ( '" P/\ q) V ( '" P/\ '" q)
e) p v ( '" P/\ q)
d) '" p p
e) p '" p
f) ((p /\ q) p) (p v q)
g) "'p
3.10. La funcin nand se define mediante la tabla de verdad siguiente:
p q p nand q
verdadero verdadero falso
verdadero falso verdadero
falso verdadero verdadero
falso falso verdadero
Demostrar que los operadores "', /\, V Y pueden definirse utilizando
la funcin nand. Es decir, encontrar proposiciones construidas slo con
p's, q's y operadores nand cuyas tablas de verdad sean iguales a las de
'" p, p v q, P/\ q YP q, respectivamente.
3.11. Justificar los pasos realizados en cada una de las demostraciones si-
guientes:
a) ((p q) /\ (q r)) (p r)
(( '" p v q) /\ ( '" q v r)) ('" p v r)
'" (( '" p v q) /\ ('" q v r)) v ('" p v r)
( '" ( '" p v q) v '" ( '" q v r)) v ( '" p v r)
(p /\ '" q) V (q /\ '" r) v ( '" p v r)
((p /\ '" q) V '" p) v ((q /\ '" r) v r)
( '" p v (p /\ '" q)) v (r v (q /\ '" r))
(",pvp)/\("'pv ",q))v(rvq)/\(rv "'r))
verdadero /\ ( '" Pv '" q) v (r v q) /\ verdadero
( '" p v '" q) v (r v q)
'" p v (q v '" q) v r
'" p v verdadero v r
verdadero
b) "'p
(p falso) '" p
'" (p /\ '" falso) '" p
'" (p /\ verdadero) '" p
"'p
"'pvp
verdadero
68 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
3.12. Demostrar que las proposiciones siguientes son tautologas, utilizando
reglas de equivalencia que las hagan equivalentes al valor verdadero:
a) (-pvq)=>(qv-p)
b) (p => q) ~ (-q => -p)
e) (p => - p) => - p
d) p v q) 1\ ""' p) => q
e) (p v q) 1\ (p => s) 1\ (q => s)) => S
f) p => q) 1\ (p => r)) => (p => q 1\ r)
g) p => q) 1\ (r => s)) => p v r) => (q V s))
h) p => q) 1\ (r => s) 1\ ( - q v s)) => ""' PV - r
313. Utilizando reglas de inferencia, demostrar cada una de las tautologas
del Ejercicio 3.12.
3.14. Dada la proposicin p v q) 1\ ""' p) => q.
a) Demostrar que es una tautologa, utilizando una tabla de verdad.
b) Demostrar que es equivalente a la oracin siguiente, si se realiza
una asignacin apropiada de variables a cada frase.
O los Red Sox son mejores que los A-es o los Piratas son
mejores que los Red. Los Red Sox no son mejores que los A-es. Por
tanto, los Piratas son mejores que los Red.
e) Demostrar que la proposicin es una tautologa, utilizando las
equivalencias y reglas de inferencia apropiadas. Ayuda: comenzar la
demostracin suponiendo que el lado derecho de la implicacin es
verdadero y concluirla utilizando la regla de la =>-introduccin.
3.15. Desarrollar una demostracin para cada una de las tautologas siguien-
tes, utilizando reglas de inferencia.
a) p => r) 1\ (r => q)) => (p => q)
b) p v q) 1\ (p => s) 1\ (q => s)) => S
3.16. En la isla Paradoja, todos sus residentes pertenecen a uno de dos clanes.
Los miembros de uno de los dos clanes siempre dicen la verdad, mien-
tras que los del otro siempre mienten. Un visitante de la isla Paradoja se
encuentra con tres nativos. Einstein, Planck y Bohr. Einstein dice: o
bien Bohr o bien yo pertenecemos a un clan distinto de los otros dos.
A qu clan pertenece Bohr? *
3.17. Abigail, Bridget y Claudia cenan a menudo juntas. Despus de cenar
toman caf o t. Si Abigail pide caf, entonces Bridget pide lo mismo
que Claudia. Si Bridget pide caf, entonces Abigail pide lo contrario de
lo que pida Claudia. Si Claudia pide t, entonces Abigail pide lo mismo
* Adaptado del libro de GEORGE J. SUMMERS, titulado The Great Book C?f Mind Teasers and
Mind Puzzles, Ed. Sterling Publishing Co., Nueva York, 1986.
Lgica 69
que Bridget. Cul de las tres (si es que existe) pide siempre lo mismo
despus de cenar?
3.3. LGICA DE PREDICADOS
La programacin puede considerarse como una actividad dirigida por un objeti-
vo. ~ s decir, el propsito de un programa puede describirse como la consecucin
de una tarea, que genera una salida de un determinado tipo. Por tanto, el punto
de partida en la construccin de un programa es la definicin de la salida que se
espera que produzca. Otra tarea a completar en la construccin de programas
est estrechamente relacionada con la anterior. Definir un conjunto de condicio-
nes que describan todas las entradas posibles para las que el programa produzca
la salida deseada. Suele definirse primero la salida, porque describe el objetivo
del programa. Para entender esto, considrese el problema de encontrar todas
las posibles rutas para viajar en automvil desde Cleveland a Dretoit. Para
resolver este problema, no solemos analizar todas las carreteras que salen de
Cleveland y ver cules llegan a Detroit; lo normal es localizar Detroit y desde
ah ver slo cules son las posibles carreteras que llegan desde Cleveland.
Para el diseo de problemas, necesitamos un lenguaje muy preciso para
describir entradas y salidas. Por ejemplo, supongamos que queremos construir
un programa que reorganice una lista de 30 enteros, de forma que los deje en
orden descendente (a este proceso se le conoce vulgarmente como ordenacin).
Podemos describir, informalmente, las entradas y salidas de la forma siguiente:
Entrada = Cualquier lista de treinta enteros
Salida = Los 30 enteros originales, en orden descendente
Sin embargo, esta forma de descripcin suele no ser lo suficientemente precisa
para definir un problema. Por ejemplo, no se da un criterio para determinar
que los enteros estn en orden descendente. Esto puede parecer trivial, puesto
qe todos tenemos una idea clara de lo que esto significa. Esto es debido a que,
por la experiencia que compartimos, damos por hecho que conocemos esta
informacin. Sin embargo, una computadora no tiene estas ventajas, y en
algn punto del proceso de programacin tenemos que indicarle un mtodo
con el que determinar si la lista de enteros est ordenada en orden descendente
o no. Por tanto, una descripcin ms precisa es la siguiente:
Entrada
Salida
Cualquier lista A = (el' el' ..., e
30
) de enteros.
Una lista B = (e', e ~ , ..., e30) permutacin de A para la que se
verifica que e+ 1 ~ e para cada entero i en el intervalo 1 al 29,
ambos inclusive.
Esta descripcin alternativa clarifica la relacin entre la entrada y la salida, y
aporta una definicin no ambigua de lo que significa en orden descendente.
Aunque nuestra segunda definicin es ms precisa que la primera, tambin
es ms prolija. Es, por tanto, necesario encontrar una notacin ms sinttica
para expresar los estados de entrada, salida y otros intermedios del programa.
70 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Esta notacin puede ser la denominada lgica de predicados, que no es ms
que una extensin de la lgica proposicional presentada en las Secciones 3.1
y 3.2. En esta seccin se introduce la notacin bsica de la lgica de predica-
dos, junto con las nociones necesarias para trabajar con ella y utilizarla en la
descripcin de los estados de los programas.
Las descripciones de entrada y salida anteriores no son ms que formas
relajadas 'de predicados. De forma intuitiva, podemos considerar un predicado
como una frase que incluye variables, las cuales, al tener un determinado valor,
convierten la frase en una proposicin.
Definicin. Un predicado es un aserto constituido por constantes aritmti-
cas y booleanas (nmeros enteros, reales y los valores lgicos verdadero y
falso); variables aritmticas y booleanas, operaciones aritmticas (=, *, etc.);
operaciones relacionales ( <, >, =, i=, E, etc.) y operadores lgicos
(1\, v, etc.), que tiene el valor verdadero o falso dependiendo de los
estados de sus variables.
En Pascal, este tipo de predicados se conocen con el nombre de expresiones
booleanas, y tienen gran cantidad de usos en programacin.
En la Seccin 3.1 se defini la sintaxis de las proposiciones de forma preci-
sa. Podramos hacer lo mismo con los predicados; sin embargo, en su lugar,
utilizaremos nuestros conocimientos y experiencia con ese tipo de expresiones
en otros campos de las lgebra y programa-
cin- junto con los conocimientos adquiridos sobre proposiciones. Comence-
mos destacando que cualquier proposicin es tambin un predicado.
Ejemplo 3.22. Las proposiciones siguientes son tambin predicados. Las
expresiones equivalentes en Pascal se muestran a la derecha.
x < 10
x < 10
i
2
+ / = 25
i*i + j*j = 25
al < a
2
1\a
2
< a
3
(a[1] < a([2]) and (a[2] < a[3])
Obsrvese en el tercer predicado del Ejemplo 3.22 que, aunque no es necesario
utilizar parntesis para representar el predicado, si 10 es en la expresin en
Pascal equivalente. Esto es debido a que los operadores 1\ y v tienen menor
prioridad que los operadores relacionales , >, etc.). Sin embargo, en
Pascal, los operadores and y or tienen una prioridad mayor que los operadores
relacionales , >, etc.) en una expresin booleana. Por ello, para conse-
guir una interpretacin equivalente, es necesaria la utilizacin de parntesis *.
Las expresiones siguientes no son predicados:
i + 1
y2 < 10 i=
x := x + 1
* Para una mayor informacin sobre las expresiones booleanas en Pascal, consltese el
manual de laboratorio.
Lgica 71
i + 1 no es un predicado, puesto que no tiene un valor lgico; simplemente es
una expresin aritmtica que tiene un valor numrico. y2 < 10 :1: podra serlo,
si hubiera otra expresin a la derecha del smbolo :1:; pero, tal y como est
escrita, carece de significado. La expresin x := x + 1 es una instruccin vlida
en Pascal, pero no es una expresin que tenga un valor lgico.
Es posible evaluar un predicado reemplazando todas sus variables por sus
valpres, en un determinado estado, y calcular el resultado utilizando las leyes
de la aritmtica. As, x < 10 se evala a verdadero en el estado x = 1, Ya falso
en el estado x = 11. Decimos que x = 1 es un estado que satisface el predica-
do x < 10. A un predicado que posee estado en el que puede ser satisfecho, se
le denomina satisfactible. Por ejemplo, el predicado x < 10 es satisfactible,
mientras que el predicado 11 < 10 no es satisfactible.
Definicin. Un predicado que se satisface en cada estado se dice que es
vlido.
Por ejemplo, si i es un entero, el predicado i ~ Ov i ~ 1 es vlido, puesto que
es verdadero para cualquier valor de i. Por tanto, el concepto de validez para
los predicados es como la nocin de tautologa para las proposiciones.
Ejemplo 3.23. Los predicados se utilizan frecuentemente en la definicin
de conjuntos. Por ejemplo, en cada una de las definiciones siguientes, el
conjunto definido contiene todos los estados que satsfacen el predicado
que haya la derecha de la barra vertical. El apartado d utiliza cadenas de
caracteres como dominio; el dominio del resto de las variables es el conjun-
to de los nmeros naturales N.
a) {(i, j) I i < j}
b) {(i,j) I i
2
+ / = 25)}
c) {(a
o
, al' a
2
) I a
o
= mx(a
1
, a2)}
d) {(Si' S2) / Sl es un prefijo para S2}
e) {(i, j) I i < j v j = O}
f) {(i, j) I i
2
+ / = 25 1\ j > 2}
3.3.1. Los cuantificadores universal y existencial
Recurdese de un ejemplo anterior, que es posible describir la salida de un
programa como una lista de la forma
B = (e', e, ..., e30)
que es una permutacin de otra lista A, y que tiene la propiedad de que para i
entre 1 y 29, ambos inclusive, ej+ 1 ~ ej. Esta frase es la conjuncin de dos
72 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
predicados. El primero, B es una permutacin de A, es un predicado con
treinta variables. El segundo, para cada i entre 1 y 29, ambos inclusive, ei+ 1
~ ~ ei, contiene 29 predicados de la forma ei + 1 ~ e, uno por cada entero
entre el 1 y el 29. Es decir, sirve como abreviatura para el predicado
Debido a que expresiones como para cada, para todo, para cada
uno aparecen con frecuencia en matemticas y lgica, todos ellos se s i m b o l i ~
zan de forma abreviada con el smbolo V, denominado cuantificador universal.
En el ejemplo, podemos escribir la frase:
para cada i entre 1 y 29, ambos inclusive, ei+ 1 ~ ei
Vi E {1, 2, ..., 29}: e+ l ~ e;
como
donde, a continuacin del smbolo V, aparece un predicado que indica el domi-
nio de la variable i, y a continuacin de este otro predicado que indica 10 que
es verdadero cuando la variable toma valores en ese dominio.
De forma general, el predicado siguiente puede construirse con los predica-
dos R(i) y P(i):
V R(i) : P(i)
Donde R(i) se utiliza para describir el dominio de i, y el predicado P(i) debe
satisfacer para todos los valores de i pertenecientes a su dominio, para que el
predicado VP(i) : R(i) resultante sea vlido -es decir, valga verdadero en todos
los casos-o Este tipo de predicados puede utilizarse para sintetizar conjuncio-
nes como P(i
1
) 1\ P(i
2
) 1\ ... , donde i
l
, i
2
. , simbolizan todos los valores de i que
satisfacen R.
Ejemplo 3.24. Cada una de las frases de abajo va seguida de su represen-
tacin como predicado, que utiliza el cuantificador universal:
a) Cada elemento e de la lista desde el hasta e
21
es distinto de 9.
Vi E{l, 2, oo., 21}: e =1= 9
b) Todos los e
j
entre e
m
y en son nmeros positivos.
Vj E {m, m + 1, ..., n}: e
j
> O
c) El punto (a, b) est arriba y a la derecha de cada punto (i, j) de alguna
regin rectangular R del plano xy (vase Figura 3.3).
V (j, j) E R: i < a 1\ j < b
Lgica 73
y
'(a, bl
R
--r-----------
x
Figura 3.3. Representacin grfica del
predicado V (j, j) E R: i < a /\ j < b.
d) En una lista A = (el' e
2
, 000' en) los elementos hasta elj-simo, excluido
l mismo, estn colocados en orden creciente (vase Figura 3.4)0
Vi E {l, 2, ..o,j - 2}: e ~ e+l
(1 3 5 6 7
I
e,
9 2 8 4)
I
e
j
Figura 3.4. Ejemplo de predicado.
e) La proposicin P(p, q, r ) es una tautologa.
Vp, q, r E {verdadero, falso}: P(p, q, r)
Obsrvese que no se realiza ninguna exigencia de. que las proposiciones
sean siempre verdaderas. El apartado e requiere algn comentario adicional:
P(p, q, r) es una proposicin; sin embargo, la frase la proposicin P(p, q, r) es
una tautologa puede reescribirse para todos y cada uno de los estados de
las variables p, q y r, P(p, q, r) es verdadera. Por tanto, con el cuantificador
universal, el aserto P(p, q, r) del apartado e vale verdadero en todos sus ocho
posibles estados.
Hay veces en que el cuantificador del predicado puede omitirse, si est
claro por el contexto -es decir, cuando el conjunto universal ha sido expresa-
do con claridad-o Por ejemplo, si sabemos que i es un entero (como suele
ocurrir frecuentemente), es posible escribir:
Vi:i<i+l
74 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
De forma similar, siempre es posible escribir
V R(i) : P(i)
como Vi : R(i) ~ P(i). Por ejemplo
(Vi E {l, ..., 2l}: e "1= 9)
es lo mismo que (Vi: 1 ~ i ~ 21 ~ e "1= 9).
El otro cuantificador de inters es el cuantificador existencial, simbolizado
por 3. Su significado es existe, o bien existe al menos o para algo. Se
utiliza para abreviar mltiples ocurrencias de disyunciones cuando varios pre-
dicados similares estn relacionados con este operador.
Ejemplo 3.25. Las frases siguientes se acompaan con su representacin
abreviada utilizando el cuantificador existencial:
a) Existe un elemento de la lista (el' e
2
, , en) que es cero.
3iE {l, ...,n - l}:e = O
b) Los elementos de (el' e
2
, ., en) no estn todos en orden ascendente.
3j E {l, ..., n - l}: ej + 1 > ej
e) Algn punto del conjunto del plano R, se encuentra en el tercer cua-
drante.
3 (i, j) E R : i < O/\ j < O
d) Existen enteros a b y e, distintos de cero, que verifican a
3
+ b
3
c
3

e) Existe alguna fila del tablero que no tiene ninguna pieza.


3 una fila R en el tablero: R no tiene piezas
f) Existe una frase en este texto con al menos una falta de ortografa.
3 una frase S en este texto: S tiene al menos una falta de ortografa.
El cuantificador universal, al igual que el existencial, representa una notacin
abreviada. Por ejemplo, 3 i E {l, ..., n}: e = Oes la notacin abreviada de (el =
= O) v (e
2
= O) v ... v (en = O). Es decir, al igual que el cuantificador universal
representa una forma abreviada de una secuencia de operaciones and, el cuan-
tificador existencial representa una forma abreviada de secuencias de oro
Lgica 75
La relacin entre ambos cuantificadores podemos encontrarla en la genera-
lizacin de las leyes de Morgan siguiente:
- V R{i) : P(i) = 3 R{i): - P(i)
- 3 R(i) : P(i) = V R(i): - P(i)
(3.1)
(3.2)
La Ecuacin (3.1) dice que la frase no es cierto que todos los es en el dominio
satisfacen p es equivalente a para algn i del dominio, P es falso. La Ecua-
cin (3.2) tiene una interpretacin similar: la frase no es cierto que algn i en
el dominio satisfate P es equivalente a la frase para cada i en el dominio, P
es falso.
Estas son generalizaciones de la versin simple de las leyes de Morgan, que
fueron introducidas anteriormente en este captulo. Tngase en cuenta que los
cuantificadores utilizados ahora representan abreviaturas de conjunciones y
disyunciones. Por ejemplo, las equivalencias siguientes son interpretacio-
nes vlidas de las Ecuaciones (3.1) y (3.2), cuando el rango de i es el conjun-
to {1, 2}:
-(P(l) /\ P(2)) - -P(I) v -P(2)
-(P(I) v P(2)) -P(I) /\ -P(2)
Ejemplo 3.26. A continuacin, se muestran dos ejemplos concretos:
a) - 3i E {1, oo., n}: e = Oes equivalente a
Vi E {l, .oo, n}: e :f. O.
b) - 3i E {1, oo., 21}: e :f. 9 es equivalente a
Vi E {1, oo., 21}: e = 9.
(3.3)
(3.4)
A menudo son necesarios ambos cuantificadores para expresar un nico
predicado. Por ejemplo, supongamos que queremos expresar que, simblica-
mente, B = {e'}, e, OO" e ~ o } es una permutacin de A = {el' e
2
, .. , e
30
}.
Supongamos tambin que todos los a son distintos. Es posible expresar todo
lo anterior como:
perm (B, A) = Vi E {l, oo., 30} 3j E {1, oo., 30}: ei = ej'
Dicho en castellano, B es una permutacin de A, si para cada elemento ei de B
existe un elemento idntico e
j
en A, aunque no necesariamente en la misma
posicin (es decir, los ndices i y j no necesitan ser idnticos para que e; = e
j
sea verdadero).
76 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
3.3.2. Otros cuantificadores
En informtica suelen utilizarse otros cuantificadores junto con los dos ante-
riores, 3 y V. Estos cuantificadores pueden verse a continuacin:
Num R(i): P(i)
Mio R(i): P(i)
Max R(i): P(i)
Sum R(i): f(i)
Prod R(i): f(i)
Num R(i): P(i) da el nmero de valores de i en el rango determinado por R, que
satisfacen el predicado P. Mio devuelve el valor mnimo de la funcin f(i),
donde i est restringida al rango especificado por R. Max es similar a Mio,
pero devuelve el valor mximo. Tambin se ha visto la funcin Sum, que se
utiliz en la Seccin 2.4 (donde se simboliz mediante la letra griega L). Prod
es similar a Sum, pero simboliza el producto en lugar de la suma. (En matem-
ticas suele simbolizarse el producto mediante la letra griega n.)
Ejemplo 3.27. Las expresiones siguientes muestran la utilizacin de estos
cuantificadores. El valor que resulta de evaluarlas aparece a la derecha:
a) Num i E {O, oo., 3}: i
2
> i 2
b) Mio i E {O, ..., 3}: i
2
> i 2
e) Max i E {O, oo., 3}: i
2
> i 3
d) Sum i E {O, ..., 3}: i
2
- i

+
2
+
6 = 8
e) Prod i E {l, .oo, 4}: i
2
> i 1
x 4
x
9
x
16 = 576
3.3.3. Variables libres y ligadas
Comprese
con la expresin cuantificada
Vi E {l, oo., 29}: ei+l ~ e;
En la primera expresin, i est irrestringida; puede tomar cualquier valor en el
dominio que deseamos definir. En este caso, i recibe el nombre de variable
libre. Sin embargo, en el segundo caso, la variable i est restringida por el
cuantificador universal a tomar valores en un intervalo especfico. En este caso,
se dice que i es una variable ligada.
En general, todas las variables cuyos valores estn restringidos a un deter-
minado dominio, por la aplicacin de un cuantificador, son ligadas; variables
Lgica 77
que no estn ligadas son libres. (Veremos que la misma distincin entre varia-
bles libres y ligadas existe entre variables globales y locales, respectivamente,
cuando definamos procedimientos y funciones en programacin.)
Considrese la expresin
Vi E {m, ..., n}: e :::;; K
En esta expresin, i es una variable ligada, mientras que m, n y K son libres.
Suele ser habitual la coexistencia de variables libres y ligadas.
3.4. PREDICADOS V PROGRAMAS
En el Captulo 5, se utilizarn con frecuencia predicados para discutir sobre
programas y resolucin de problemas. La idea de predicado, que define exacta-
mente las condiciones bajo las que debe ejecutarse un programa, es fundamen-
tal para los objetivos descritos en la frase anterior. Es tambin fundamental la
correspondencia entre predicados cuantificados y bucles de un programa. En
la seccin siguiente se introducen ambas ideas.
3.4.1. El estado de un clculo
Supngase que en un programa de una computadora se tiene una instruccin
como la siguiente:
; := O
que asigna el valor O a la variable ;. Supngase tambin que el programa es
tan simple que slo utiliza las variables; y j. Es posible utilizar un predicado
para describir el estado del programa despus de la ejecucin de la instruccin
; := O
Tal predicado recibe el nombre de poscondicin de la instruccin ; : = O.
Supngase que conocemos que, antes de la ejecucin de esta instruccin, las
variables cumplen i > j 1\ j > 10. El predicado anterior recibe el nombre de
precondicin, debido a que describe el conjunto de todos los estados que pue-
den darse antes de ejecutar la instruccin.
Definicin. Una poscondicin de una instruccin o grupo de instrucciones
de un programa, es un predicado que describe el conjunto de todos los
estados en que estas instrucciones pueden terminar, despus de que sean
ejecutadas. Una precondicin para esa instruccin o grupo de instrucciones,
es un predicado que describe el conjunto de estados en los que pueden estar
todas las variables del programa, inmediatamente antes de ejecutarse la
instruccin o grupo de instrucciones.
78 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
Podemos pensar en la poscondicin como un predicado que describe el
conjunto objetivo o el propsito de nuestro programa. Obsrvese que, si se
considera una instruccin o conjunto de instrucciones como una funcin, la
precondicin representa su dominio, y la poscondicin su recorrido. Ms ade-
lante, se ver cmo la precondicin y la poscondicin sirven de ayuda en la
construccin y verificacin de programas.
3.4.2. Cuantificadores y programacin: bucles
Existe una estrecha correspondencia entre la utilizacin de cuantificadores en
lgica y la de bucles en programacin. Es decir, al igual que los cuantificadores
universal y de existencia permiten en la lgica abreviar una serie de tediosas
secuencias de operaciones /\ y v, los bucles sirven en programacin para
abreviar largas secuencias de instrucciones. Tendremos muchas ocasiones de
hacer traducciones entre esas dos formas de expresarse.
Es habitual tener que escribir instrucciones de programas que comprueben
si los predicados cuantificados VR(i): P(i) y 3R(i): P(i) son vlidos. Cuando el
rango de la variable i, expresada en R(i) es finito, esta prueba puede realizarse
utilizando un bucle for de Pascal. Supongamos que tenemos la lista A =(el'
e
2
, ... , e
30
) Yqueremos conocer si todos los miembros de esta lista son positivos;
es decir, se quiere establecer si el predicado siguiente es vlido:
V i E {l, ..., 30}: e
i
> O
Una forma posible de comprobar esto sera escribir una largusima instruccin
condicional, asignando a la variable booleana v l ; do el valor verdadero o
falso:
if (e[1]>O and (e[2]>0> and .. and (e[30]>O>
then vlido:=true
eLse vlido:=false;
De forma alternativa, tras aplicar la ley de Morgan, podramos escribir:
vlido:=true;
if e[1] <= O
then vlido:=false;
if e[2] <= O
then vlido:=false;
if e[30] <= O
then vlido:=false;
Es decir, el predicado original no es vlido, SI es posible que uno o ms
elementos de la lista cumplan e
i
~ O.
Lgica 79
Para evitar problemas de escritura, en esta y en similares situaciones, es
posible utilizar la instruccin for para expresar la misma idea. Es posible
sustituir la serie de instrucciones if-then por el bucle siguiente:
vlido:=true;
for i :=1 to 30 do
jf e[i] <= O
then v l i do :=fa lse;
Sencillamente, se ha utilizado un truco bastante comn en programacin: se ha
supuesto que el predicado es vlido para todos los valores del rango de i, y se
intenta demostrar lo contrario examinando los 30 casos de forma individual.
Puede seguirse una estrategia de programacin similar, cuando se imple-
menten predicados como instrucciones, que involucren otros cuantificadores.
Ejemplos de esto pueden verse en los Ejemplos 3.28 y 3.29:
Ejemplo 3.28. El predicado Existe un nmero en la lista A = (e l' e2' ... ,
e
30
) cuyo valor es cero, puede reescribirse como :Ji E {l, ..., 30}: e = O. Un
bucle para probar la validez del predicado sera:
vl ido:=false;
for i :=1 to 30 do
ife[i]=O
then vlido:=true;
Ejemplo 3.29. La frase El nmero de elementos de la lista A = (el' ez' ...,
e
30
) cuyo valor es cero, puede reescribirse como Num i E {l, ..., 30}: e = O.
El programa siguiente comienza con la suposicin de que no existen en A
elementos que cumplan esta condicin. Posteriormente, se corrige metdi-
camente la suposicin (aadiendo 1 a la variable contador numero), cada
vez que se encuentre un cero en la lista.
nmero:=O
for i :=1 to 30 do
ife[i]=O
then nmero:=nmero+1;
Una discusin ms detallada sobre el bucle for, puede encontrarse en el
manual de laboratorio.
Ejercicios
3.18. Evaluar los predicados siguientes, en cada uno de los estados 1 y 11:
(1) i = O1\ j = 1 1\ k = - 1 (JI) i = - 1 1\ j = 1 1\ k = O
80 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
a) i< lO/\j< 10
b) -1 < j :::; i
e) i + j > k
d) i
3
= / = p
3.19. Evaluar cada uno de los predicados siguientes. Supngase, en todos los
casos, que el dominio es N.
a) Vi: i < i + 1
b) Vi: i
2
< i
e) Vi, j : i
2
+ / > O
d) 3i: i
2
= 5i - 6
e) 3i, j : i
2
+ j2 :::; 25
f) Vi 3j : j = O
g) Max i E {l, ..., lOO} : i
h) Vi 3j : i - j = O
i) 3i Vj : i - j = O
j) Mio i E {1, ..., 6} : (i2 - 6i) = 3
k) Vi 3j : i x j = O
l) Sum i E {l, , lO} : i - 5
m) Prod i E {l, , n} : i
+ 2 = 101
3.20. Supngase que se define un tablero de ajedrez como {(i, j)ll :::; i :::;
:::; 8 /\ 1 :::; j :::; 8}. Supongamos que el par (1, 1) define el cuadrado de
la esquina inferior izquierda del tablero, la casilla es negra, y las blancas
ocupan inicialmente las dos filas inferiores del tablero. Sea p una fun-
cin que asigna a cada casilla del tablero el nombre de la pieza que est
sobre ella. As, si la casilla (4, 7) est vaca, escribiremos p(4, 7) = vaca;
si la casilla (1, 5) contiene el rey blanco, escribiremos p(l, 5) = RB.
Escribir predicados para describir las frases siguientes:
a) La reina blanca ha sido capturada.
b) Las negras conservan sus alfiles.
e) Una torre blanca est en la misma fila que la reina negra.
d) Un pen blanco est atacando al rey blanco.
e) Una torre blanca est atacando a la reina negra.
f) Un alfil negro est atacando al rey negro.
3.21. Identificar las variables libres y ligadas de las expresiones siguientes:
a) Vi E {O, oo., n} : i
3
- i
2
< 100
b) 3i E N : "In E {1, .oo, i} : n
2
= i
e) (O:::; m :::; p) /\ (Vw E R : w < m /\ w
2
< p)
3.22. Considrese la situacin del juego de las tres-en-raya descrita en el
dibujo. Supngase que la notacin s(i, j) = v significa que la cuadrcula
de la fila i y la columna j contienen el valor v (donde v puede ser una X,
una O o estar vaca).
a) Escribir un predicado que describa la situacin concreta del dibujo.
b) Escribir un predicado que describa el mejor movimiento que pue-
dan realizar las O, a continuacin.
Lgica 81
columna
fila 1 2 3
2
3
x
O
X
e) Escribir un predicado que describa todos los estados en que las X
pueden ganar, en la columna de enmedio; es decir, todos los estados en
que las X ocupan dos casillas de la segunda columna y la otra casilla
est vaca.
d) Escribir un predicado cuantificado, que describa la imposibilidad de
que las X ganen en la segunda columna.
e) Escribir otro que describa la imposibilidad de las X de ganar en cada
columna.
f) Escribir un predicado que describa la imposibilidad de que ganen las X.
3.23. Describir las situaciones siguientes, utilizando predicados y cuantificado-
res. Supngase que A = (el' e
2
, ..., e,,) es una lista de caracteres ASCII.
a) Todos los caracteres de la lista son idnticos.
b) La letra x no est en la lista.
e) Algn carcter de la lista es la z.
d) La lista est ordenada alfabticamente, de menor a mayor.
e) No existen en la lista dos caracteres iguales.
f) Algn par de caracteres de la lista son iguales.
g) La letra y aparece exactamente dos veces en la lista.
h) La lista B = (b
l
, b
2
, .., b,,) es una sublista de A.
i) La variable cont almacena el nmero de puntos y comas de la lista.
j) La lista B es idntica a la A.
k) La lista B es idntica a la A, excepto que algn cero de la lista ha sido
reemplazado por una letra o.
l) El nmero 3621 no es primo.
3.5. RAZONAMIENTO CON PREDICADOS:
PRUEBA POR INDUCCION
El razonamiento con predicados es similar al razonamiento con proposiciones,
puesto que existen tambin reglas de inferencia que gobiernan los pasos a seguir.
Frecuentemente, se asignan valores representativos a las variables de un predica-
do (convirtindolo en una proposicin) y se utilizan las reglas de inferencia para
82 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
proposiciones. Sin embargo, el razonamiento con predicados implica algunas
reglas adicionales que se resumen en la Tabla 3.4.
Como sugiere la Tabla 3.4, las reglas de la 3-introduccin y de a 3-elimina-
cin recuerdan a las leyes de Morgan (vanse Ecuaciones (3.1) y (3.2)). Las reglas
de la V-introduccin y de la V-eliminacin tambin son ampliamente utilizadas
en las demostraciones. La primera indica que si es posible establecer que R => P
es vlida, es posible afirmar, en un paso posterior de la demostracin, que
tambin es' vlido V R(i): P(i). La segunda indica que si V R(i): P(i) es vlida,
entonces para cada valor particular i
o
de i, tambin es vlida R(io) => P(i
o
)'
Tabla 3.4. Reglas de inferencia para predicados cuantificados
V-introduccin
R-=P
V R(i): P(i)
3-introduccin
V R(i): P(i)
~ 3 R(i): ~ P ( i )
V-eliminacin
V R(i): P(i)
R(i
o
) -= P(i
o
)
3-eliminacin
3 R(O: P(i)
~ V R(i): ~ P(i)
Supongamos que se quiere demostrar que todos los enteros pares mayores
que 2 no son primos. En este caso, R es el predicado:
i no un entero /\ (i > 2) /\ i es par
y P es el predicado:
i no es primo
Es necesario ver que R => P es vlido. Esto se suele hacer seleccionando un i
o
representativo, que satisfaga R, y demostrando que tambin satisface P. As, la
prueba podra comenzarse:
Sea i
o
cualquier entero par que verifique i
o
> 2.
De la suposicin anterior concluimos que i no es primo (puesto que para que un
nmero sea par, es necesario que sea divisible por 2). Por tanto, concluimos que
todos los enteros pares mayores que 2 no son primos.
Prueba por induccin. La validez de predicados que contienen cuantificadores,
puede muchas veces establecerse mediante el mtodo conocido por prueba por
induccin (o induccin). Este es un concepto tan importante para la programa-
cin como para las matemticas. Es decir, los mtodos de demostracin inducti-
vos se utilizan en la verificacin formal de programas (vase Captulo 6). La
Lgica 83
induccin tiene tambin una relacin muy estrecha con el concepto matemtico
de funciones recursivas (como se vio en el Captulo 2) y una gran aplicacin en la
resolucin de problemas y en programacin (vase Captulo 5).
Para demostrar la validez del predicado VR(n): P(n) en el caso especial en que
R(n) tiene la forma n E {l, 2, "'}' podemos considerar dos casos por separado.
Oaso base: Demostracin de P(l).
Paso de induccin: Demostracin de P(i) ::::- P(i + 1) para todo i ~ 1.
El caso base, simplemente establece la validez de P para el valor inicial, i = 1. El
paso de induccin establece que, si podemos demostrar que P(i) ::::- P(i + 1), para
cualquier i, entonces se demuestra la validez de P(l) ::::- P(2) ::::- oo Puesto que
P(l) es vlido, tambin lo ser P(2) [puesto que P(l) ::::- P(2)] y tambin lo ser
P(3) [puesto que P(2) ::::- P(3)], y as sucesivamente. .
La idea de la induccin puede ilustrarse mediante una analoga. Suponga-
mos que alguien quiere subir una escalinata. Slo sern necesarias dos fases para
describir el proceso -la fase de alcanzar el primer peldao y la de subir desde
un peldao hasta el siguiente-. Utilizando estas dos instrucciones es posible
subir cualquier escalinata, sin tener en cuenta cmo tenemos que situarnos en un
escaln determinado. Adems, estas dos acciones hacen irrelevante, para com-
pletar el proceso de induccin, lo larga que sea la escalera. El hecho de alcanzar
el primer escaln es equivalente a probar el caso base P(1). El hecho de saltar del
i-simo escaln al i + 1, es anlogo a probar el paso de induccin P(i) ~ P(i +
+ 1) para cada i ~ 1. La expresin Vn E {l, 2, oo.}: P(n) establece que P(n) es
verdadero para todo n, y es anlogo a la posibiliad de saltar de uno a otro
escaln de todas las escaleras.
Mientras no podamos utilizar una tabla de verdad para justificar el proceso
de induccin, podemos justificarlo utilizando el modus ponens y basndonos en
algunas propiedades de los nmeros naturales. Es decir, si sabemos que P(l) es
verdadero y que Vi E {l, 2, oo.}: P(i) ::::- P(i + 1) es posible escribir las expresiones
siguientes, sin ms que sustituir i por diferentes nmeros enteros:
P(l)
P(l) ~ P(2)
P(2) ::::- P(3)
Combinando las dos primeras lneas es posible concluir, utilizando modus po-
nens, que P(2) es vlido. Combinando la veracidad de P(2) con la tercera lnea, es
de nuevo posible concluir que P(3) es verdadero. Es posible continuar de esta
forma indefinidamente hasta demostrar que Vi E {l, 2, oo.}: P(n) es vlido.
Ejemplo 3.30. Supongamos que St; desea probar por induccin que Vn > o:
n n(n + 1)
j ~ l j = 2 . Consideremos los dos casos:
84 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
n
Caso base. Demostrar que L j
j= 1
Paso de induccin: Demostrar que
n(n + 1)
2
" i( i + 1) i ~ 1 .
j= ~ J
j=l 2 j=l
(i + 1)((i + 1) + 1)
2
El caso base es evidente si utilizamos la aritmtica. Es decir, 1 = 2/2. El paso
de induccin tampoco es muy dificil de probar, si se utilizan las propiedades
de las sumatorias finitas, introducidas en la Seccin 2.2.6.
i+ 1 i
j
L j + (i + 1) Propiedad de L
j= 1 j=l
i(i + 1)
i
i(i + 1)
+ (i + 1) Suponiendo L j =
2 2
j= 1
i(i + 1) 2(i + 1)
2
+ 2
Aritmtica
(i + 1)((i + 1) + 1)
Aritmtica
2
A primera vista, puede parecer que la induccin matemtica es una forma circu-
lar de razonamiento. Sin embargo, lo que est realizndose es, en alguna medida,
un razonamiento hipottico. Lo que decimos es Supongamos que P(n) es
cierto. Podemos deducir de ello que P(n + 1) tambin lo es?. Esto no demues-
tra la validez de P(n + 1), sino slo que P(n) implica P(n + 1). Considrese de
nuevo la analoga con la ascensin de la escalinata. En realidad, lo que estamos
diciendo es Supongamos que nos encontramos en el n-simo escaln, puedo
desde aqu ir al siguiente?. Esto no supone afirmar que sepamos llegar al
n-simo escaln, sino que estando en l somos capaces de alcanzar el n + l-simo.
Es la combinacin de las capacidades de saltar de uno al siguiente, y la de
alcanzar el primer escaln (es decir, probar P(I)), lo que permite alcanzar el n-
simo.
Ejemplo 3.31. Demostrar que si O < 1 r < 1, entonces
n 1 - r
n
+ 1
r
i
= ---
i=O 1 - r
Comencemos con n = O. Los lados izquierdo y derecho (LHS y RHS) de la
ecuacin anterior se convierten en:
LHS
i=O
rO = 1, para r =1= O
Lgica 85
1 r
RHS = = 1, para r =1= 1
1 - r
E&to completara la demostracin del caso base. Supongamos ahora que
n 1 - r
n
+ 1
I r
i
= ----
i=O 1 - r
Demostraremos que esto implica
n+1 1 _ r
n
+
2
I r
i
=
i=O 1 - r
Sumando r
n
+ 1 a ambos lados de la ecuacin (3.5), obtenemos
(3.5)
RHS
n+1
LHS = I r
i
+ r
n
+ 1 =
i=O
1 - r
n
+ 1
+ r
n
+
1
1 - r
1 - r
n
+ 2
1 - r
n+1
I r
i
i=O
Ejemplo 3.32. Supongamos que S es un conjunto finito que tiene n ele-
mentos. Demostrar mediante induccin que S tiene 2
n
subconjuntos.
Solucin. Denotemos por P(S) la coleccin de subconjuntos de S. Supon-
gamos que n = O. Entonces, S = <j>. Por tanto, P(S) = {<j>} y S tiene 1 (= 2)
subconjuntos. Este es el caso base para la prueba inductiva.
Supongamos ahora que cualquier conjunto S de n elementos tiene 2
n
subconjuntos. Para probar el paso de induccin, sea T un conjunto arbitra-
rio con n + 1 elementos.
Los subconjuntos de T pueden dividirse en dos grupos ~ a q u e l l o s que in-
cluyen a t
n
+
1
Ylos que no-o Cada subconjunto {t
1
, t
2
, , t
n
} es tambin un
subconjunto de T. Por tanto, por hiptesis de la induccin 2
n
subconjuntos
de T no incluyen a t
n
+ l' Cada subconjunto que incluye t
n
+ 1 puede conside-
rarse como la unin de un subconjunto de {t l' t2' ... , t
n
} con {t
n
+ 1}' Luego
existen 2
n
subconjuntos que incluyen t
n
+ l' Por tanto, existen 2
n
+ 2
n
= 2 x
x 2
n
= 2
n
+ 1 subconjuntos.
86 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
Una forma de visualizar la demostracin es escribiendo la lista de subcon-
juntos siguiente:
Sin incluir t
n
+
4J
{td
{t
2
}
{ti' .t
2
}
{ti' t
2
, oo., t
n
}
Incluyendo t
n
+
{tn+d
{ti' t
n
+ }
{t 2' t
n
+ }
{t l' .t
2
, t
n
+ }
{t,"t
2
, .., t
n
, t
n
+ }
La lista de la izquierda est construida con todos los subconjuntos de {tl' t
2
,
..., t
n
). La lista de la derecha se ha construido haciendo la unin de cada uno
de los elementos de la lista de la derecha con {t
n
+ }. Luego hay exactamente
2
n
elementos en cada lista.
Obsrvese que, en contradiccin con su nombre, la demostracin por induc-
cin implica razonamiento deductivo, en lugar de inductivo. El razonamiento
inductivo hace referencia a una tcnica habitual en la ciencia, denominada mto-
do cientfico; este mtodo consiste en inferir principios generales a partir de casos
particulares. Por ejemplo, el astrnomo Kepler utiliz el razonamiento inductivo
para inferir las leyes del movimiento planetario a partir de un voluminoso con-
junto de datos experimentales que haba recogido. Sin embargo, la induccin
matemtica sigue un tpico proceso deductivo -partiendo de axiomas, teoremas
previamente demostrados define nuevos teoremas utilizando reglas de inferencia.
3.6. RESUMEN
En este captulo hemos estudiado los fundamentos de la lgica, prestando espe-
cial atencin a su utilizacin en la informtica. La lgica proposicional, la equi-
valencia y las demostraciones se han revelado como inestimables herramientas
en la resolucin de problemas. El clculo de predicados tiene una utilizacin
directa en Pascal, en forma de expresiones booleanas. Se han introducido mto-
dos deductivos de demostracin, incluida la induccin, tiles para el estudio del
diseo de programas y la verificacin, que se vern en captulos posteriores.
Ejercicios
3.24. Demostrar que la suma de los n primeros nmeros impares es n
2

n > 1 para
3.25. Supongamos que la funcin Factorial: N ~ N se define recursivamente de
la forma siguiente:
Factorial (1)
Factorial (n) = n x Factorial (n - 1)
Lgica 87
Demostrar por induccin, sobre n, que esta definicin es equivalente a la
definicin no recursiva:
Factorial (n) = 1 x 2 x ... x (n - 1) x n
3.26. Supongamos que la funcin f(n) se define mediante la siguiente regla:
f(O) = 1
f(n + 1) = 2f(n) para todo n > O
Demostrar por induccin que f(n) = 2
n

3.27. Demostrar la generalizacin de la ley de Margan, siguiente:


n
(Nota: UA significa A
o
u Al U ... U A
n
)
;=0
n
(Nota: nA
i
significa A
o
n Al n ... n A
n
)
i=O
3.28. Verificar las relaciones siguientes utilizando la induccin matemtica:
n
n(n + 1)(n + 2)
a) L (i(i + 1)
3
i=O
n
n(n + 1)(2n
+
1)
b)
L 2
6
i=O
n
n
2
(n
+ 1?
c)
L 3
4
i=O
CAPTULO 4
PROBLEMAS ALGORTMICOS
V SU SOLUCiN
El conjunto de problemas que son resolubles utilizando una computadora es,
indudablemente, muy extenso. Muchos de estos problemas son de ndole mate-
mtica, y requieren la utilizacin de nmeros y la aplicacin de principios
matemticos. Otros tienen naturaleza grfica, e implican la manipulacin de
objetos grficos, tales como puntos, lneas, rectngulos y crculos. El otro gran
grupo implica la manipulacin de textos en lengua castellana y, por tanto,
implica la manipulacin de caracteres alfabticos y palabras como unidades de
informacin bsicas.
Muchos de los problemas que debemos resolver con computadoras, autn-
ticamenteimportantes, fuerzan a la manipulacin conjunta de dos o tres de los
dominios anteriores -matemticas, grficos y texto--. Por ejemplo, si utiliza-
mos una computadora para resolver un problema que simula el juego de las
tres en raya, no querremos slo visualizar la secuencia de movimientos (descri-
bible como texto), sino que queremos ver en qu situacin se encuentra el
tablero en cada momento (descripcin grfica). Un estudio cuidadoso de pro-
blemas algoritmicos debe incluir elementos de esos tres dominios, bien por
separado, bien en combinacin con otro.
Existe una ventaja adicional si se estudian los problemas computacionales
de las matemticas, los grficos y los textos de forma conjunta: muchos de los
principios que se aprenden al estudiar una de estas reas, por ejemplo las
matemticas, son tambin de aplicacin en las dems. Esto sugiere la existencia
de una serie subyacente y nica de principios, que gobiernan el comportamien-
to de computadoras y programas. De hecho, estos principios dirigen nuestra
forma de abordar un problema cuando tratamos de resolverlo con una compu-
tadora. Este conjunto de principios recibe el nombre de resolucin de problemas
algortmicos. En este capitulo se introducen las ideas1undamentales de la reso-
lucin de problemas algortmicos, y se presentan una gran variedad de proble-
mas matemticos, grficos y de procesamiento de textos, que ilustran estas
ideas.
90 Computacin /. Lgica, resolucin de problemas, algoritmos y programas
4.1. ALGORITMOS Y PROBLEMAS
Los conceptos de problemas algortmicos, algoritmos, lenguajes algortmicos y
comportamiento algortmico son fundamentales para la actividad de resolver
problemas con computadoras y, por tanto, para la disciplina de la informtica.
f En consecuencia, necesitamos adquirir un conocimiento firme sobre lo que es
un algoritmo (y sobre lo que no es), y lo que es un problema algortmico, con
objeto de llevar a cabo de forma eficaz la actividad de resolver problemas. La
definicin siguiente sirve como punto de partida para esta discusin.
Definicin. Un algoritmo es una lista de instrucciones que realizan una
descripcin paso a paso y precisa de un proceso que garantiza que resuelve
cualquier problema que pertenezca a un tipo determinado, y que termina
despus de que se hayan llevado a cabo un nmero finito de pasos.
Los algoritmos se escriben o disean con el propsito de resolver problemas, o
ms exactamente, problemas algortmicos.
Definicin. Un problema algortmico es cualquier problema, conceptual o
prctico, cya solucin puede expresarse mediante un algoritmo.
En la vida cotidiana encontramos muchos problemas algoritmicos, tanto den-
tro como fuera del campo altamente especializado de la informtica. Por ejem-
plo, una determinada receta para preparar pollo a la cazadora constituye un
algoritmo, mientras que el problema general de preparar pollo a la cazadora es
el problema algoitmico asociado. En la Tabla 4.1 se presentan algunos ejem-
plos comunes de algoritmos y de problemas algortmicos.
Tabla 4.1. Algunos algoritmos y problemas algortmicos
Algoritmo
Problema algortmico
Conjunto de instrucciones para tejer un jersey
Un itinerario particular para recorrer el mundo
Un plan de trabajo para cursar una licenciatura
Tejer un jersey.
Dar la vuelta al mundo.
Cursar una licenciatura.
Para cada problema algortmico como cursar una licenciatura, existen
varios algoritmos alternativos que pueden utilizarse como solucin. Por ejem-
plo, un alumno que desee cursar una ingeniera en informtica, seguir un
algoritmo muy diferente que en el que desee licenciarse en ciencias medioam-
bientales o en filosofa.
En cualquier caso, los algoritmos de la Tabla 4.1 exhiben las principalcs
caractersticas sealadas en la definicin: exactitud, efectividad y terminacin
garantizada. Cuando se ejecutan determinados algoritmos pueden completarse
en un pequeo intervalo de tiempo, mientras que otroS' pueden llevar mucho
Problemas algortmicos y su solucin 91
tiempo. Sin embargo, la ejecucin de todos los algoritmos debe terminar. Por
ello, cualquier descripcin paso a paso de un proceso que no termine, no es un
algoritmo. Por ejemplo, el proceso de escribir todos los nmeros enteros posi-
tivos, uno a uno, no es un algoritmo, puesto que no terminara nunca.
En la informtica se asocia la nocin de algoritmo con la de un proceso
que debe ser ejecutado por una computadora, en lugar de por una persona. En
princjpio, cualquier algoritmo que diseemos para una computadora puede ser
realizado a mano (suponiendo que disponemos del tiempo necesario, una piza-
rra o suficiente papel). En realidad, encargamos a la computadora la ejecucin
de los pasos que componen un algoritmo, porque es capaz de completarlo en
un tiempo mucho menor del que nosotros emplearamos, y porque es menos
proclive a cometer errores que nosotros.
Sin embargo, no todos los algoritmos pueden ser ejecutados por computa-
doras. Las computadoras slo pueden ejecutar algoritmos que se componen de
acciones individuales que pueden entender y realizar. Por ejemplo, la prepara-
cin de pollo a la cazadora implica acciones como encender el horno o
deshuesar el pollo, tareas para las que una computadora est bastante mal
preparada. Por tanto, es necesario conocer bien cules son las tareas que puede
realizar una computadora, de forma que diseemos algoritmos que contengan
slo ese tipo de tareas.
Como punto de partida, considrese el sencillo modelo computacional de la
Figura 4.1.
ENTRADA I - - - - ~ . I PROCESO - - - - ~ . I SALIDA
Figura 4.1. El modelo de computacin entrada-procesa-salida.
En este modelo, un proceso de clculo se compone de tres partes: una entrada,
un proceso y una salida. La entrada la constituyen un conjunto de informacio-
nes que necesitan los pasos de que se compone el algoritmo para llevar a cabo
la tarea; el proceso contiene (una descripcin de) los pasos del algoritmo; final-
mente, la salida la constituye el resultado que se obtiene ejecutando los pasos,
con los datos de entrada.
Por ejemplo, el procedimiento para calcular la calificacin media (CM) es
un algoritmo. En este caso, la entrada puede ser cualquier lista de valores
numricos dentro del rango Oa 4. (O = suspenso, 1 = aprobado, 2 = notable,
3 = sobresaliente, y 4 = matrcula de honor); la salida ser la media de esos
valores (es decir, el cociente entre la suma de todos y el nmero de valores); yel
proceso es (una descripcin de) el conjunto de pasos individuales que deben
seguirse para obtener el resultado. Ese conjunto de pasos puede resumirse en
un lenguaje-castellano descriptor de procesos, en la forma siguiente:
92 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Paso 1. Obtener la lista de calificaciones.
Paso 2. Calcular n = nmero de notas de la lista.
Paso 3. Calcular Sum = la suma de las calificaciones de la lista.
Paso 4. Calcular CM = Sumn.
Paso 5. Mostrar CM.
Cuando se escriben este tipo de descripciones de procesos, se realizan algu-
nas' suposiciones tcitas sobre el comportamiento del modelo entrada-proceso-
salida de la Figura 4.1. La primera hiptesis es que el nmero de calificaciones
es indeterminado, aunque nunca infinito. La segunda hiptesis es que para
poder calcular cualquier cosa sobre las calificaciones, el algoritmo necesita
obtenerlas primero ---es decir, trasladarlas fisicamente a la parte proceso del
modelo, desde la parte entrada del mismo.
Cuando se utiliza una computadora en la resolucin de este problema
algortmico, las instrucciones que contienen los pasos individuales, junto con
los valores numricos de Sum, n y CM se almacenan fisicamente en un lugar
llamado memoria, que se encuentra unido a la unidad central de procesamiento
(CPU o procesador) de la computadora. Toda la informacin de entrada o
salida, se encuentra fsicamente separada del procesador en dispositivos como
el teclado, el monitor o un archivo en disquete. Un diagrama de las unidades
de una computadora que se corresponde con el modelo entrada-proceso-salida
puede verse en la Figura 4.2.
[
I
Procesador/
Teclado/Ratn ----'--_M_em_o_ri_a_--..JI--- Pantalla de monitor
Figura 4.2. Computadora correspondiente al modelo.
La tercera suposicin que realizaremos es que los pasos de la descripcin
del proceso se realizarn en el orden en que estn escritos. Por ejemplo, difcil-
mente podramos realizar el Paso 5 sin haber realizado antes los pasos 1 al 4,
adems de ser improbable que hubiramos podido calcular la CM.
Nuestra cuarta suposicin es que cada uno de los pasos es eficaz ---es decir,
que contiene slo acciones del repertorio de las realizables por la computado-
ra-. Por ejemplo, hemos asumido que la orden Mostrar (Paso 5) est en el
repertorio de instrucciones de la computadora. Por tanto, siempre que se eje-
cute alguna instruccin que contenga la palabra Mostrar, la informacin de
salida aparecer en el monitor, independientemente de cul sea el paso que la
contiene. (En este caso, mostrar aparece muy tarde. No existe ninguna restric-
cin del nmero de veces que mostrar puede estar en un proceso.)
Las cuatro suposiciones son ciertas, de hecho, para todos los algoritmos
que construimos para las computadoras. Las computadoras ejecutan las ins-
trucciones de una forma obediente, comenzando por la primera y ejecutando
slo aquellas que le son inteligibles; es decir, instrucciones que describen tareas
dentro de su propio repertorio.
Problemas algortmicos y su solucin 93
Ejercicio
4.1. Describir un problema algortmico que nos encontremos en la vida dia-
ria, similar a los discutidos en la Seccin 4.1. Dar dos algoritmos alterna-
tivos para solucionar el problema.
,
4.2. DEFINICiN DE PROBLEMAS Y DESCRIPCiN
DE ALGORITMOS
En la resolucin de problemas algortmicos, el nivel de precisin -tanto en la
descripcin del propio problema como en la solucin algortmica al mismo-
debe ser detallada y rigurosa. Por ejemplo, nuestra descripcin del algoritmo
de CM, de la Seccin 4.1, puede no ser lo suficientemente rigurosa para incor-
porarlo a una computadora. Es necesario un mayor nivel de detalle por dos
razones fundamentales:
El problema, sus limitaciones y su solucin deben describirse de forma
clara para el lector humano.
La solucin debe resolver completamente el problema -es decir, debe
aportar a la computadora toda la informacin necesaria para que pro-
duzca una salida correcta para todas las posibles variaciones de la en-
trada.
En el problema CM, la impresin en el proceso de descripcin deja sin respon-
der la pregunta de cuntas puntuaciones constituirn la entrada. Existe un
nmero mximo de puntuaciones? Es posible suponer que siempre habr un
nmero de puntuaciones distinto de cero? Si no est permitida una entrada
consistente en cero puntuaciones, esto debera expresarse explcitamente. Sin
embargo, si se permite una entrada de cero puntuaciones, es necesario modifi-
car la descripcin del proceso, de forma que evitemos la divisin por cero
(Paso 4), y que sea posible escribir el mensaje adecuado.
Esta breve discusin enfatiza sobre la necesidad de encontrar una manera
ms sinttica y formal de describir un problema algortmico y sus soluciones.
En el resto de esta seccin se introducen los rudimentos de un lenguaje de
descripcin de algoritmos. En la Seccin 4.3 se introducirn los rudimentos de
un lenguaje de descripcin de soluciones a problemas, y se demostrar que estos
dos tipos de lenguajes estn relacionados mutuamente.
4.2.1. Los estados inicial y final de un algoritmo:
entrada y salida
Para formalizar el modelo de clculo entrada-procesa-salida, introduciremos
primero la nocin de estado de un algoritmo. Intuitivamente, podemos enten-
der la idea de estado de un algoritmo como una especie de instantnea que
describe cmo estn las cosas inmediatamente despus (o antes) de que se haya
94 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
ejecutado un paso de un algoritmo. Por ejemplo, el estado del proceso descrito
en la Seccin 4.1 podria ser una instantnea de sus entradas, sus salidas y cada
una de sus variables Sum, n y CM en el instante particular en que cada uno de
los pasos, del 1 al 5, ha sido ejecutado.
Existen dos pasos de inters especial: el estado inicial y el fina!. El estado
inicial lo constituye una descripcin de la entrada, antes de que se ejecute el
primer paso del algoritmo y, por tanto, recibe el nombre de precondiein del
algoritmo (o pre). El estado final es una descripcin de las entradas y las salidas
despus de que se haya ejecutado el algoritmo, y reciben el nombre de poseon-
dicin del algoritmo (o post). Ambas suelen escribirse utilizando la notacin
convencional de la lgica, introducida en el Capitulo 3:
{pre: ent rada = una expresin que describe todas las posibles entradas
del problema}
{post ent rada =0/\ sa l i da = una descripcin de todas las salidas que
pueden darse para cada entrada}
Si denotamos por Notas! la primera calificacin de la lista, por Notas
z
la
segunda, y as sucesivamente, la descripcin siguiente es una descripcin preci-
sa del problema de la calificacin media, en forma de precondicin y poscondi-
cin:
{pre: entrada = (Notas" Notas" .. "' Notas,> /\ n> O /\
\ti E {1, .. , n} :Notas, E (O, ... , 4))
{pos t: ent rada = 0 /\
salida = Sum i E {1, ... , n}:Notas,ln}
Obsrvese cmo se utiliza en la precondicin y la poscondicin el lenguaje de
la lgica de predicados, estudiado en el Captulo 3. Cuando utilizamos la
lgica de predicados de esta forma, se dice que realizamos asertos acerca de los
estados inicial y final del proceso.
El lenguaje de la lgica permite, en la expresin del estado de un clculo,
una concisin y precisin que no podemos alcanzar con el lenguaje castellano.
En el ejemplo, el estilo de descripcin no deja duda sobre la exclusin del caso
de que existan cero entradas en el problema de la CM. Por tanto, la solucin
algortmica a este problema no tiene que ocuparse de este caso.
El haber escrto entrada = 0 en la poscondicin significa que, al final del
proceso, la entrada estar vaca. Es decir, todas las entradas habrn sido ledas
por el proceso, pero no pueden ser ledas de nuevo. Esta peculiaridad de los
estados incial y final reflejan una forma peculiar de procesar la entrada y la
salida en una ejecucin del algoritmo. Es decir, el acto de obtener las entradas
consiste en una serie de pasos discretos, en los cuales: 1) un valor no puede ser
obtenido de nuevo despus de haberse obtenido una vez; y 2) los valores
individuales de la entrada se obtienen exactamente en el orden en el que se
introducen por el teclado.
Problemas algortmicos y su solucin 95
Con objeto de enfatizar la estrecha relacin existente entre la especificacin
de un algoritmo y la descripcin del proceso correspondiente, encerramos la
descripcin del proceso entre la precondicin y la poscondicin, como se
muestra en la Figura 4.3.
(pre: entrada = <Notas" Notas" .. "' Notas") 1\ n> O
1\ \fi,E (1, ... , n) :Notas, E (O, ... ,4))
Paso 1. Obtener La Lista de caLificaciones
Paso 2. CaLcuLar n = nmero de notas de La Lista
Paso 3. CaLcuLar Sum= La suma de Las caLificaciones de La
Paso 4. CaLcuLar CM ~ Sum/n
Paso 5. Mostrar CM
{post: entrada ~ 0 1 \
saL ida = Sum i E (1, ... , n} :Notas,ln}
}
\ Descrip-
Lista \ cin del
Jproceso
Especificaciones
Figura 4.3. Unificacin de la descripcin de un proceso y su especificacin.
4.2.2. los estados intermedios de un clculo:
introduccin de variables
Los estados intermedios resultantes de cada paso intermedio de un clculo
pueden describirse tambin mediante asertos. Contrariamente al caso de la
precondicin y la poscondicin, en este caso es necesario considerar valores
intermedios que es necesario calcular para obtener los resultados finales, as
como los cambios que se producen en las propias entradas al incorporar valo-
res individuales al proceso de clculo. Por ejemplo, en el algoritmo de CM, los
valores intermedios se identifican por n (el nmero de calificaciones); Sum (la
suma de calificaciones individuales, Notas;, donde i = 1, oo., n); y CM (el prome-
dio de notas resultante).
Estos valores intermedios se identifican simblicamente, puesto que es im-
posible predecirlos previamente a una ejecucin concreta del algoritmo. Por
ejemplo, una ejecucin puede calcular el promedio de tres calificaciones (y por
tanto, n = 3), Yotra diferente puede calcular el promedio de 24 puntuaciones
(n = 24). La misma situacin es esperable para las propias puntuaciones o
para su suma, para diferentes ejecuciones. Por ello, capturamos esta nocin de
valor variable de la suma utilizando un nombre apropiado, como Sumo
Definicin. Una variable es un nombre simblico que se asocia con un
valor o serie de valores particulares, durante una ejecucin concreta de un
algoritmo, pero cuyo valor no puede predeterminarse en el momento en
que se construye el proceso del algoritmo.
96 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Por tanto, n, Sum y CM son variables del problema de la CM.
Podemos utilizar variables siempre que deseemos describir un estado inter-
medio de un clculo. Por ejemplo, es posible describir el aserto:
{ent rada ~ 0/\ Sum = Sum i E {1, .. , n l : Notas;
Para describir el estado de los clculos, despus de que se hayan completado
los pasos 1, 2 Y3. Esto es una abreviatura de Se ha obtenido la entrada, el
tamao de la entrada (n) ha sido determinado, y se ha calculado la suma de los
n valores de entrada y se ha identificado este valor con la variable Sum.
Con objeto de localizar con precisin dentro del proceso dnde es cierto el
aserto, lo colocamos justo inmediatamente detrs del paso del algoritmo que lo
hace verdadero. Una versin aumentada de la descripcin del algoritmo del
proceso CM podria ser la siguiente:
Paso 1. Obtener la lista de cal i fi caciones
Paso 2. Calcular n ~ nmero de notas de la lista
Paso 3. Calcular Sum = la suma de las calificaciones de la lista
{entrada =0/\ Sum = Sum i E {1, .. , n} :Notas;}
Paso 4. Calcular CM = Sum/n
Paso 5. Mostrar CM
En general, se puede colocar un aserto entre dos pasos cualquiera de un clcu-
lo, y ste puede decir mucho o poco sobre el estado de los clculos en ese
momento del clculo. Lgicamente, si se colocan asertos antes del primer paso
y despus del ltimo, ambos deben ser consistentes con la precondicin y la
poscondicin, respectivamente. Por tanto, es posible colocar junto con la pre-
condicin y la poscondicin un conjunto completo de asertos, con objeto de
clarificar la descripcin de los pasos de un algoritmo, tal y como se muestra en
la Figura 4.4.
En la prctica, el nivel de detalle que se muestra en la Figura 4.4 en los
asertos intermedios es excesivo, puesto que la mayora de la informacin puede
deducirse de un aserto prximo. Es decir, existe mucha informacin redundan-
te en esta descripcin, lo que la hace intil. Por ejemplo, cada aparicin de
entrada = 0 en los asertos despus de los pasos del 2 al 4, puede eliminarse,
puesto que es redundante con la informacin que aparece en el aserto de detrs
del paso 1. De forma ms general, cualquier aserto intermedio puede eliminar-
se si su contenido es directamente deducible de un aserto vecino.
Una especificacin, descripcin de proceso y anotaciones intermedias ms
tiles se muestran en la Figura 4.5. El propsito para el que se utilizan los
asertos intermedios para ilustrar los pasos de un proceso es doble. Primero, los
asertos aportan informacin para cualquiera que necesite comprender el efecto
de los pasos individuales del proceso de clculo. Segundo, son un vehculo
eficaz en el proceso de verificacin de que ese conjunto de pasos resuelve
verdaderamente el problema original que se plante en forma de precondicin
Problemas algortmicos y su solucin 97
{pre: entrada = (Notas" Notas., . , Notas,) /\ n > O
/\ Vi E {1, ... , n} :Notas; E {O, " .. , 4}}
Paso 1. Obtener la lista de calificaciones
{entrada =0} ---------------------------,
Paso 2. Calcular n ~ nmero de notas de la lista
{entrada =0/\ n > O}
Paso 3. Calcular Sum = la suma de las calificaciones de la lista
{entrada =0/\ Sum = Sum i E {1, ... , n} :Notas;}
Paso 4. Calcular CM = Sum/n
(entrada =0/\ Sum = Sum i E (1, .. "' n) :Notas, /\ CM = Sum/n} _
Paso 5. Mostrar CM
{post: entrada =0/\
sal ida = Sum i E {1, " .. , n} :Notas,!n}
As e r los i n I e rme dio S _--'-----'-.-JL-'
Figura 4.4. Introduccin de asertos intermedios en la descripcin
del algoritmo del problema CM.
y poscondicin. Obsrvese que existe una estrecha correspondencia entre esta
forma de describir los pasos de un algoritmo y el modelo original de entrada-
proceso-salida descrito en la Figura 4.1. Es decir, la precondicin se correspon-
de con la entrada, el paso del algoritmo describe el proceso, y la poscondicin
caracteriza la salida.
Ahora que podemos describir con ms precisin las transiciones entre esta-
dos en un proceso algortmico, en la Seccin 4.3 y posteriores trataremos de
conseguir un nivel de precisin comparable en el proceso de descripcin de los
pasos de que consta el propio algoritmo.
(pre: entrada = (Notas" Notas., , Notas,) /\ n > O
/\ Vi E (1, .. "' n) :Notas, E {O, , 4}}
Paso 1. Obtener la lista de calificaciones
Paso 2. Calcular n = nmero de notas de la lista
(entrada =0/\ n > O)
Paso 3. Calcular Sum = la suma de las calificaciones de la lista
Paso 4. Calcular CM = Sum/n
(entrada =0/\ Sum ~ Sum i E (1, ... , n) :Notas; /\ CM = Sum/n}
Paso 5. Mostrar CM
(pos t: ent rada = 0 /\
salida = Su.. i E (1, ... , n) :Notas,!n}
Figura 4.5. Una versin del problema del clculo del promedio
anotada parcialmente.
Ejercicios
4.2. Describir en castellano el conjunto de pasos de un proceso algortmico
que calcule y muestre el conjunto de calificaciones que estn por encima
98 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
del promedio para una lista de calificaciones arbitraria. Considrese este
problema como una extensin del problema CM. Ser muy general al
describir los pasos del proceso. Que variable adicional es necesaria?
4.3. Cules seran la precondicin y poscondicin del proceso del Ejercicio
4.2? Definir una lista sencilla y la salida correspondiente que dara el
algoritmo construido.

4.3. LENGUAJE ALGORTMICO


El conjunto de pasos individuales que, combinados, forman la descripcin
completa de un proceso o algoritmo, deben escribirse con un estilo lingstico
muy preciso. El castellano, por su propia naturaleza, es un medio inadecuado
para conseguir la precisin adecuada. El algoritmo de cinco pasos, mostrado
en la Seccin 4.2 para calcular la calificacin media, es demasiado vago para
ser til.
El tipo de lenguajes que tienen la suficiente precisin para ser tiles en la
descripcin de algoritmos, reciben el nombre de lenguajes algortmicos o len-
guajes de programacin. Los lenguajes de programacin difieren del castellano
en tres puntos esenciales:
1. Los lenguajes de programacin tienen un vocabulario y una sintaxis
muy limitados. Por tanto, los programas slo pueden describir algorit-
mos, y son inadecuados para describir otros tipos (no algortmicos) de
prosa.
2. El vocabulario de un lenguaje de programacin contiene slo aquellos
tipos de acciones bsicas que una computadora puede entender y reali-
zar, y no otras. Por ejemplo, un lenguaje de programacin soporta las
operaciones aritmticas habituales (suma, resta, multiplicacin, divi-
sin, comparacin); acciones propias del procesamiento de texto, accio-
nes de procesamiento de grficos y acciones de entrada/salida. Las
acciones que una computadora no puede realizar son muchas y varia-
das -correr, sacar de banda, recibir, sentir, hacer quiche y crear pintu-
ras al leo- son algunas de las acciones que no se encuentran dentro
de vocabulario de una computadora.
3. La sintaxis de un lenguaje de programacin es muy rgida, y no permite
muchas variaciones de estilo. Por ejemplo, el clculo del cociente entre
Sum y n se expresa como Sum/n y no existe forma alternativa.
La descripcin de un proceso o algoritmo en un lenguaje de programacin que
difiere del castellano recibe el nombre de programa. Los programas son ejecu-
tables por las computadoras, mientras que los algoritmos descritos en castella-
no no. (Algunos lenguajes de programacin estn diseados para parecerse al
ingls, por lo que los programas escritos en l parecen estarlo en este idioma.
El COBOL es uno de estos lenguajes. Sin embargo, la capacidad de expresin
en ingls no es posible alcanzarla en ningn lenguaje de programacin.)
Problemas algortmicos y su solucin 99
Existen varios lenguajes de programacin entre los que podemos elegir
para describir algoritmos. Algunos estn diseados especialmente para la ense-
anza y el aprendizaje de los algoritmos, las computadoras y la resolucin de
problemas algortmicos. Pascal es un lenguaje de este tipo, y lo utilizaremos en
los ejemplos que pondremos a lo largo de este texto. Otros lenguajes de pro-
gramacin populares son C, Modula-2, Ada, FORTRAN, COBOL, LISP,
ScheQ1e y ensambladores a nivel mquina. Introduciremos los lenguajes en-
sambladores en el Captulo 7. Algunos de los lenguajes mencionados antes son
bien conocidos por los programadores profesionales (como FORTRAN y CO-
BOL), pero no son adecuados para el aprendizaje y la enseanza del proceso
de resolucin de problemas algortmicos.
Hasta el momento, nos hemos familiarizado con la sintaxis del Pascal,
gracias al manual de laboratorio adjunto. Por ello, no es difcil comprender
que el programa de la Figura 4.6 es una implementacin en este lenguaje del
problema CM, que habiamos descrito informalmente en castellano.
program caLcuLaCM;
{Esto es un programa que caLcuLa La CM de una serie de una o ms
caLificaciones numricas, cada una de eLLas en eL rango O.. 4,
que se introducirn por eL teclado}
uses
Listas;
val'
Notas: Li stas;
i,n:integer;
Sum, CM: rea L;
begin
{pre: entrada = (Notas" Notas" .. "' Notas") 1\ n > O
1\ \1 i E {1, ... , n} : No t a s; E {O, ... , 4} }
(Paso 1. Obtenemos La Lis ta de ca Lif i cac iones}
WriteLn ('Introducir La Lista de calificaciones: ');
ReadLista (Notas);
{Paso 2. CalcuLar n o nmero de caLificaciones en La lista)
n := LongLi sta(Notas);
if n > O then
begin
{entrada ~ 0 1 \ n > O}
{Paso 3. CalcuLamos Sum = La suma de Las caLificaciones de la Lista}
Sum := O:
i := 1;
whi le i <= n do
begin
Sum : ~ Sum + Notas[i];
i : ~ i + 1
end
end;
{Paso 4. CaLcuLamos CM = Sum/n)
CM = Sum/n;
(Sum ~ SUII iE (1, ... , n) :Notas; 1\ CM = Sum/n}
100 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
{Paso 5. Se muestra CM}
WriteLn( 'La CM de esas calificaciones es =', CM : 5 : 2)
end [if]
{post entrada =01\
salida ~ SUIl i E {1, ... , n}:Notas,ln}
end. {CalculaCM}
Figurp 4.6. Programa Pascal que se corresponde con la descripcin
de proceso de la Figura 4.5.
Los cinco pasos originales de la descripcin del proceso se incluyen aqui
como comentarios entre corchetes, de forma que la correspondencia entre estos
casos y el grupo de instrucciones Pascal sea fcilmente identificable. La pre-
condicin, la poscondicin y los asertos intermedios tambin se ponen de
relieve mediante comentarios entre corchetes. Puesto que se han escrito como
comentarios de Pascal, el programa puede ser ejecutado en una computadora
directamente, sin necesidad de hacer ninguna modificacin.
El programa introduce algunos elementos nuevos que no se han tratado en
el manual de laboratorio. Los introduciremos en la seccin siguiente (para una
descripcin ms detallada, vase el manual de laboratorio). Para el propsito
de la discusin que nos ocupa, pondremos un nfasis especial en la correspon-
dencia entre el lenguaje de programacin (como vehiculo para describir de
forma precisa el proceso algortmico) y la especificacin (como vehiculo para
describir de forma precisa el problema lingstico a resolver).
4.3.1. Sintaxis y semntica
El conjunto de instrucciones Pascal de la Figura 4.6 representa una implemen-
tacin del problema CM, en un lenguaje de programacin concreto. El signifi-
cado de cada instruccin est definido de forma estricta, y trata de expresar de
una forma ms rigurosa el conjunto de pasos que componen el algoritmo,
originalmente expresado en castellano. Por ejemplo, la frase
Obtenemos la lista de calificaciones
que constituye el primer paso de la descripcin de la Figura 4.3, se convierte en
dos instrucciones de Pascal:
WriteLn ('Introducir la lista de calificaciones:');
ReadLista (Notas);
La instruccin Wr; te Ln indica al usuario qu tipo de entrada se pretende
obtener, y la instruccin ReadL; sta cumple la tarea de conseguir la lista de
enteros.
Listas. Este programa hace us\> del tipo L; s ta y sus operaciones relaciona-
das, que se resumen en la Figura 4.7. Los programadores pueden utilizar el
Problemas algortmicos y su solucin 101
B ~
;::1:7.: : ~ " g 3 l
Entrada
RadLi sta
,,----..@
e List0 InserLista
DeleteLista
) oo.b.."", ["di ,,]
salida I GV
Figura 4.7. Resumen de las operaciones de Lista.
tipo Lis ta y sus operaciones, sin ms que hacer la declaracin uses Lis ta;
despus de la cabecera del programa. (Las definiciones estn ocultas al progra-
ma, aunque su utilizacin se ha descrito cuidadosamente en el manual de
laboratorio.)
Un programa Pascal que incluye la unidad Lista est capacitado para
obtener, procesar y escribir listas completas de enteros, en lugar de trabajar con
un nmero cada vez. Esto supone una ayuda inestimable para la resolucin de
muchos problemas algortmicos, y la utilizaremos extensivamente en este texto.
Una variable que se declare como de tipo Lista, contendr una lista de
valores completa, como ocurre con la variable Notas declarada en el proble-
ma CM, con el objetivo de almacenar una lista de calificaciones completa:
var Notas: Li sta;
El procedimiento ReadLi sta (Notas) obtiene del dispositivo de entra-
da una lista de enteros, suponiendo que la lista est encerrada entre parntesis,
y se asigna su valor a la variable Notas. As, por ejemplo, si se teclea la
entrada:
(3 2 1 3)
El procedimiento ReadLi st (Notas) dejar la variable Notas en el estado
Notas = (3 213)
La funcin LenghtLista (Notas) devuelve el nmero de elementos
que componen la lista, mientras que la expresin Nota s [i ] devuelve el valor
del i-simo elemento de la lista Notas. El entero i recibe el nombre de ndice
102 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
del elemento devuelto. As, por ejemplo, un caso posible podra ser que Leng-
htLista (Notas) devuelva el valor integer 4, y Notas[3] devuelva el
valor real 1. Una dscusin ms completa de las operacones sobre Lis ta
mostradas en la Fgura 4.7, puede encontrarse en el manual de laboratorio. Es
conveniente repasar esta discusin antes de construir programas que utilicen
listas.
Limitaciones del conjunto de caracteres ASCn. Cuando se incorporan asertos
y otros comentarios dentro del texto de un programa, es necesario recordar las
limitaciones del conjunto de caracteres ASCn, que es el estndar de los carac-
teres que se pueden codificar y que utilizan la mayora de los constructores de
computadoras. (ASCII es un acrnimo de American Standard Code for Infor-
mation lnterchange)*. Utilizando un conjunto de caracteres estndar, es posi-
ble la transferencia de informacin entre computadoras diferentes. (Como entre
Macintosh y PCs de IBM, por ejemplo). La lista completa de caracteres ASCII
y su. codifcacin se incluye en el Apndice A.
Los cientficos suelen utilizar letras gregas y otros smbolos especiales,
subndices, superndices, al escribir expresiones lgicas y matemticas o al
escribir asertos. En el problema de CM se utilizaron, por ejemplo, No t a Si' 0
y ~ estilo matemtico, continuando con la notacin convencional de los Cap-
tulos 2 y 3. Desgraciadamente, esos caracteres no pueden aparecer dentro de
un programa Pascal, por no estar incluidos dentro del conjunto de caracteres
ASCII. Por ello, cuando convertimos un algoritmo en un programa Pascal,
utilizamos un convenio de sustitucin ASCn para la sustitucin de los smbolos
ms comunes, como el de la Tabla 4.2.
Tabla 4.2. Sustitutos ASCII para los smbolos matemticos
Smbolo
matemtco
Nota Si
o
LO Sum
~
V
3

V
E
Significado
Seleccin del i-simo elemento de la lista
Conjunto vaco
Sumatoria
Menor o igual
Cuantificador universal
Cuantificador existencial
Conjuncin
Disyuncin
Pertenencia a conjunto
Sustituto
ASCII
Notas[;]
vaco
Sum
~
para todo
exste

or
n
N. del T.: Estndar Americano de Codificacin para el Intercambio de Informacin.
Problemas algortmicos y su solucin 103
Utilizando las equivalencia de la tabla anterior, algunas de las expresiones
matemticas de la Figura 4.6, podran escribirse utilizando sustitutos ASCII
aceptables de la forma siguiente:
entrada =01\ n > O
8u.; E (1, ... , n): Notas,
entrada = vac;o 1\ n > O
8um; ;n {1, .. "' n}: Notas[i]
4.3.2. Repeticin y bucles: inicializacin, invarianza
y terminacin
Un nuevo e importante concepto que encontramos en la solucin al problema
CM es el de bucle.
Definicin. Un bucle es una secuencia de instrucciones que pueden ejecu-
tarse O, I un nmero finito de veces n.
El concepto de bucle es uno de los ms importantes de todos los que se utilizan
en el diseo de algoritmos. Por qu necesitan bucles los programas? Existen
dos razones fundamentales:
1. Economa de las expresiones.
2. Impredecibilidad del tamao de la entrada.
Ambas razones para la existencia de bucles se pueden comprender si analiza-
mos la situacin siguiente: Supongamos que es necesario disear un algoritmo
que calcule S como la suma de seis calificaciones, dadas por las variables 91 a
96. Una forma de calcularlo sera realizando la declaracin y secuencia de
instrucciones Pascal siguiente:
val" 91,92,93,94,95,96: real;
S := O;
8:=8+91;
8 := 8 + 92;
8 := 8 + 93;
8:=8+94;
8:=8+95;
8 := 8 + 96;
Esta alternativa es absolutamente torpe. Si tuviramos que extender el proble-
ma mnimamente, y necesitsemos sumar 100 calificaciones, la eleccin realiza-
da sera bastante poco brillante.
Bastante ms dificil, e incluso bordeando lo imposible, sera extender el
algoritmo para el caso en que el nmero de calificaciones fuera impredecible
(aunque finito); por ejemplo, n. Naturalmente, el valor de n no puede predecirse
104 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
en el momento en que se escribe el programa, de forma que el programa pueda
calcular el valor de Sum para cada valor particular de n, en el momento en que
el programa es ejecutado o, como dicen algunos, corrido. Es decir, en una
ejecucin del programa, n puede valer 6, y en la siguiente ejecucin del mismo
programa 100, en otra quiz 1000.
Lo que ,necesitaremos es que el lenguaje aporte facilidades que permitan
generalizaciones de dos tipos:
1. La posibilidad de asignar un nico nombre a una lista de nmeros
arbitrariamente larga.
2. La posibilidad de escribir instrucciones o grupos de instrucciones que
puedan ser ejecutados reiteradas veces, pero que sean susceptibles de
ser interpretados de una forma diferente en cada repeticin.
La primera posibilidad la aporta el tipo Lis ta, tal y como se describi en la
seccin anterior. La segunda capacidad la aporta la instruccin de Pascal
wh i l e, que permite ejecutar reiteradas veces una instruccin, o grupo de
instrucciones, pero con interpretaciones diferentes en cada repeticin. Esto es
lo que necesitamos para simplificar la torpe construccin que nos calculaba la
suma de n valores.
Ilustremos estas capacidades por separado. Supongamos que se declara
slo una variable 9, del tipo Lis ta, en lugar de las seis variables de 91 a 96.
Entonces, es posible cambiar el programa original en la forma siguiente, sin
cambiar su significado:
varg: Lista;
5 := O;
5 :=5+g[1];
5 := 5 + g[2];
5 := 5 + g[3];
5:=5+g[4];
5 := 5 + g[5];
5 :=5+g[6];
Es decir, la poscondicin de la secuencia anterior seguir siendo:
5 = Sum i E {1, ... , 6}: g[ i]
haciendo una nica declaracin, en lugar de seis.
Pero las seis instrucciones ltimas son idnticas, a excepcin del valor del
ndice de la referencia a la lista 9 [i ]; es decir, i varia entre 1 y 6 a lo largo de
las instrucciones. Con objeto de generalizar esas instrucciones de forma que
sean idnticas, necesitaremos introducir una variable, por ejemplo i, que reco-
rra la secuencia de valores que se muestra en la Figura 4.8:
Problemas algortmicos y su solucn 105
8 := O;
i := 1;
8:=8+g[i];
i :=i+1;
8:=8+g[i];
i := i + 1 ;
8:=8+g[i];
i:=i+1;
'8 := 8 + g[i];
i:=i+1;
8:=8+g[i];
i:=i+1;
8 ;= 8 + 9 [i];
i:=i+1;
Figura 4.8. Suma de seis elementos: un paso hacia la generalizacin.
Parece como si estuviramos retrocediendo, puesto que ahora tenemos que
escribir el doble de instrucciones, por lo que el nuevo mtodo parece una
locura. Sin embargo, cada pareja de instrucciones a partir de las dos primeras
es idntica:
whi le b do
begin
5; s; ... ; s
end
Figura 4.9. Forma general de la instruccin wh i le: b es una expresin boo-
leana; s; s; . ; s es cualquier secuencia de instrucciones en Pascal.
8:=8+g[i];
i:=i+1;
y la secuencia entera sigue satisfaciendo la poscondicin.
La instruccin whi l e permite repetir el par de instrucciones seis veces. Su
forma general se presenta en la Figura 4.9, y una descripcin ms detallada
puede encontrarse en el manual de laboratorio.
Cuando se ejecuta una instruccin wh i l e, primero se evala la condicin b.
Si el resultado de la evaluacin es verdadero, se ejecuta la secuencia s; s;
.. ; s una vez. La condicin b se vuelve a evaluar, y si el resultado es
de nuevo verdadero, se vuelve a ejecutar la sentencia. Esta pareja de acciones
se ejecutan reiteradamente, hasta que la condicin resulta evaluada a falso,
momento en que se concluye la repeticin de las instrucciones y se termina
la ejecucin del wh; le.
Sin embargo, cuando utilizamos un bucle wh ; l e, debemos tomar una serie
de precauciones inicia/espara que ste se ejecute bajo control. Es decir, la ejecu-
cin del bucle debe terminar despus de un nmero finito de repeticiones, y
una vez terminado, debe satisfacerse la poscondicin. Por esta razn, a los
bucles suele denominrse!es bucles controlados. La estructura de un bucle con-
trolado, que incluye tanto la inicializacin como la instruccin wh i l e, se
muestra en la Figura 4.10:
106 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Instrucciones de inicializacin
while b do
begin
s;s; ... ;5
end;
Figura 4.10. Estructura general de un bucle controlado en Pascal.
Por tanto, los requisitos para que un bucle sea controlado son que las instruc-
ciones de inicializacin, la expresin booleana b y las instrucciones s; Si
... i s estn escritas de tal forma que: 1) se garantice la terminacin del bucle;
y 2) se satisfaga la poscondicin del bucle.
En nuestro ejemplo, las instrucciones de inicializacin S : = Oe ; : = 1, la
expresin booleana ; <= 6, Ylas instrucciones S : = S + 9 [ i] e ; : = ; + 1,
combinan y satisfacen estos requisitos. Es decir, nuestro ejemplo puede reescri-
birse como el bucle controlado de la Figura 4.11.
5 := O;
i := 1;
while i < ~ 6 do
begin
5:=5+g[i];
i := i + 1
end
Figura 4.11. Suma de los seis elementos de una lista. Generalizacin.
Obsrvese que en la Figura 4.11 la condicin; <= 6 describe con exactitud la
condicin bajo la cual el bucle debe seguir repitindose, con objeto de conse
guir el equivalente a los seis pares de instrucciones como las que aparecen en la
versin original de la Figura 4.8.
Utilizando el mtodo de los bucles controlados, se ha conseguido una
generalidad y economia en las expresiones, que en otro caso habra sido dificil
de conseguir. Obsrvese que el paso 3 de la solucin al problema CM ( el bucle
whi le de la Figura 4.6) es prcticamente idntico al bucle whi le de la Figura
4.11. Los dos bucles difieren slo en la forma de las expresiones booleanas que
gobiernan el nmero de repeticiones del bucle, y en el nombre de las variables.
En la Figura 4.11, el bucle se repetir exactamente seis veces; mientras que en
el bucle original, el nmero de iteraciones viene determinado por n, o nmero
de calificaciones en la lista Notas. Gracias a la generalidad que nos aporta la
introduccin de la variable n, es posible resolver el problema CM. Sin n, la
solucin estara limitada a la que calcula el promedio de un nmero predeter-
minado de calificaciones. La permanencia de esta restrccin supondra una
situacin bastante insatisfactoria no slo para este problema, sino que no
satisfara los requisitos de generalidad exigidos a las soluciones algortmicas.
Invarianza de bucles. Un aspecto importante en el diseo de soluciones a
problemas mediante la utilizacin de bucles, es el poder garantizar que el bucle
Problemas algortmicos y su solucin 107
termina, y que despus de esto se satisface exactamente la poscondicin para la
que fue diseado. Para conseguir este propsito se utiliza un tipo especial de
aserto, llamado invariante del bucle (o simplemente invariante).
Informalmente, podemos pensar en el bucle como en un aserto sobre el
estado de los clculos, que vale verdadero (es decir, que no vara) antes y
despus de cada iteracin del bucle, mientras se est ejecutando. Es habitual
diferenciar los invariantes de otro tipo de asertos de los programas, porque
guardan una relacin especial con los fragmentos de programas en los que
estn incluidos. El aserto siguiente es un invariante del bucle del progra-
maCM.
(inv: Sum = Su. j in (1, """' i - 1}: Notas[j] /\ 1 <= i <= n + 1}
Para demostrar que esto es, sin duda, el invariante del bucle, debemos
comprobar que cada valor de ; durante la ejecucin del bucle:
1. Sum es la suma de las i - 1 primeras calificaciones en la lista Not as; y
2. El valor de ; est comprendido siempre entre 1 y el valor que causa la
terminacin del bucle.
Considrese el ejemplo en el que Notas = (3 2 1 3), por lo que n = 4. El
estado antes de cada iteracin del bucle, y la comprobacin correspondiente
del valor del invariante, puede sintetizarse de la forma siguiente:
Antes
de la
Estado
iteracin
1 S=O/\;=1J\n=4
2 S=3/\;=2J\n=4
3 S=5J\;=3/\n=4
4 S=6/\i=4J\n=4
5 S=9J\i=5J\n=4
Comprobacin del invariante
Sum = Sum j ; n {1, ""., O}: No t a s [j]
J\1<=1<=5
Sum= Sum j in {1, .. , 1}: Notas[j]
/\1<=2<=5
Sum= Sum j in {1, . , 2}: Notas[j]
J\1<=3<=5
Sum = Sum j ; n {1, .. , 3}: No t a s [j]
J\1<=4<=5
Sum = Sum j in {1, .. , 4}: Notas [j]
J\1<=5<=5
Puesto que la quinta iteracin no tiene lugar (se produce la salida del wh i Le,
puesto que; <= n cambia a falso), el invariante conduce al cumplimiento de la
poscondicin al salir del bucle. Esto es,
Sum = Su.. j in (1, "."' i - 1}: Notas [j] /\ 1 <= i < ~ n + 1
108
Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
que por s mismo acaba siendo:
Suro = Sum j ; n {1, ... , n}: Nota s [j]
Cuando el valor de ; alcanza n + 1.
Cuill es la relacin entre el invariante del bucle y la secuencia de instruc-
ciones s; s; ... ; s que constituyen el cuerpo del bucle? Es necesario que
estudiemos en nuestro ejemplo la relacin entre las instrucciones
Suro := Suro + Notas[;]i
; := ; + 1
y el invariante
Suro = SUII j ; n {1, ... , ; - 1}: Notas [j] 1\ 1 <= ; <= n + 1
El cuerpo del bucle se ha diseado de forma intencionada con dos objetvos en
mente:
1. El cuerpo preserve el invariante (valga verdadero).
2. El cuerpo produzca una progresin hacia la terminacin del bucle.
En general, los bucles no tienen que hacer ni ms n menos que esto -todo lo
dems es irrelevante.
4.3.3. Tres v i s i o n ~ s de la misma solucin al problema
",.
El programa de la Figura 4.6 resulta de la composicin de tres niveles de
lenguaje distintos: el cdigo en Pascal; la descripcin del proceso, que describe
en castellano qu ocurre en cada paso del proceso que describe el programa; y
la especificacin formal que aparece antes y despus de cada paso del proceso.
Los tres niveles juntos suponen un nivel elevado de redundancia; es decir,
expresan los mismos conceptos en tres estilos diferentes -algortmico formal
(Pascal), algortmico informal (castellano) y declarativo formal (especificacio-
nes).
Esta redundancia enfatiza el hecho de que una solucin programada a un
algoritmo se escribe simultneamente para tres tipos de audiencias:
1. La computadora.
2. La gente que disea y lee el programa.
3. La gente que verifica la correccin del programa.
La computadora slo tiene en cuenta el cdigo en Pascal: la computadora
seguir con exactitud el cdigo al realizar el proceso. Los programadores hu-
manos se interesarn por el cdigo en Pascal, los comentarios escritos en
castellano, y las pre y poscondiciones si quieren entender y desarrollar correc-
Problemas algortmicos y su solucin 109
tamente el cdigo y, posteriormente, ampliar o mejorar el programa. Los veri-
ficadores humanos del programa estarn interesados en el cdigo de Pascal, la
precondicin, la poscondicin y en los asertos intermedios mediante los cuales
obtendrn una demostracin rigurosa de la correccin del programa.
En la Figura 4.12 se muestra lo que considerara la computadora de la
parte en Pascal del programa que soluciona el problema CM.
prograll ca l cu laCM;
uses
Listas;
var
Notas: Listas;
i, n : integer;
Sum, CM: real;
begin
WriteLn ('Introducir la lista de calificaciones:');
ReadLista (Notas);
n := LongLista(Notas);
if n > O then
begin
Sum := O;
i := 1;
while i <= n do
begin
Sum :=Sum+Notas[i];
i := i + 1
end;
CM := Sum/n;
WriteLn( 'La CM de esas cal ificaciones es = " CM : 5 2)
end
end. (CalculaCM}
Figura 4.12. El programa CM, desde el punto de vista de la computadora.
Los programadores noveles suelen confundir el punto de vista de la com-
putadora con el del lector. Es decir, suelen presentar slo el programa como
solucin a un problema algortmico. Sin embargo, esta representacin, por si
misma, no es suficiente para la construccin y presentacin de programas
fiables.
Cuando nos comprometemos en el proceso de resolver problemas algort-
micos, nuestra intencin debe ser la de desarrollar programas comentados
completamente, de forma que estas anotaciones nos muestren la definicin del
problema original, y los sucesivos pasos que hemos seguido en su solucin.
Para el problema de CM, el programa completo es, ms o menos, como la
versin mostrada en la Figura 4.13.
program calculaCM;
{esto es un programa que calcula la CM de una serie de una o ms
110 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
calificaciones numricas, cada una de ellas en el rango O.. 4, que
se introducirn por el teclado}
uses
Listas;
var
Notas: Listas;
i, n : integer;
Sum, CM : real;
begin '
{pre: entrada = (Notas" Notas" , Notas
n
) /\ n > O
/\ Vi E {1, ... , n}:Notas; E {O, ... , 4}}
{Paso 1. Obtenemos la lista de calificaciones}
WriteLn('Introducir la lista de calificaciones');
ReadLista(Notas);
{Paso 2. Calcular n o nmero de calificaciones en la lista}
n := LongLista(Notas);
if n > O then
begin
{Paso 3. Calculamos Sum= la suma de las calificaciones de la lista}
Sum := O;
i := 1;
while i <= n do
begin
Sum := Sum + Notas[i J;
i := i + 1
end;
{Paso 4. Calculamos CM = Sum/n}
CM = Sum/n;
{Paso 5. Se muestra CM}
WriteLn('La CMde esas calificaciones es= " CM 5 2)
end {if}
{post: entrada =0/\
salida = Su.. i E {1, ... , n}: Notas;!n}
end. {CalculaCM}
Figura 4.13. El mismo programa, desde el punto de vista del lector
y del desarrollador.
La versin de la Figura 4.13 difiere de la versin de la Figura 4.6, en que
excluye los asertos intermedios. Estos asertos son tiles cuando el programa es
probado y verificado. La prueba y verificacin de programas se introduce
separadamente en el Captulo 6.
Problemas algortmicos y su solucin 111
Ejercicios
4.4. La lista siguiente contiene la lectura de las temperaturas diarias de una
semana de verano.
Temps = (78 62 71 73748584) *
a) Cul es el ndice de la lista Tems, de la temperatura mxima de la
semana?
b) Cul es el valor de la temperatura mxima?
e) Cuntas temperaturas estuvieron por debajo del promedio sema-
nal?
4.5. Supongamos que necesitamos escribir un programa que calcule, para
una lista de siete temperaturas como la del ejemplo anterior, todas las
respuestas a las cuestiones de dicho ejemplo.
a) Escribir una precondicin que describa el conjunto de todas las
listas de entrada vlidas para el programa.
b) Dar una poscondicin que describa, para las entradas vlidas, las
salidas que debe mostrar el programa.
e) Cul de todas las cuestiones precisa la utilizacin de un bucle para
que el programa pueda contestarla?
4.6. Debajo, se muestra un bucle controlado que calcula la temperatura
mxima de una semana, y la deja en la variable Max.
Max := Temps[1]
i := 2;
while i <= LenghtLi sta (Temps) do
if Temps [i] > Max then
Max := Temps[i]
a) Trazar una ejecucin de los pasos de bucle, utilizando los valores de
Temp s del Ejercicio 4.4. Trazar significa escribir los valores que
toman las variables ; y Max, en relacin a los valores de
Temps [; ], al comienzo de cada iteracin.
b) Despus de examinar esos valores y examinar el comportamiento
del bucle para cualquier lista de valores, escribir un invariante para
el bucle.
4.7. Escribir un bucle controlado que satisfaga las especificaciones siguien-
tes:
{pre: L ~ (e" e" . , en) /\ n > O)
N. del T.: Expresadas en grados Farenheith.
112 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
{post: SumPares = La suma de todos Los eLementos de L con ndce par 1\
Sumlmpar = La suma de todos Los eLementos de L con subndice mpar}
4.8. Escribir las instrucciones de Pascal que calculen el promedio de las siete
temperaturas de la lista del Ejercicio 4.4, asignando el valor a la varia-
ble TemProm. Dar las precondiciones y postcondiciones de esas instruc-
ciones, as como el invariante del bucle controlado que contienen.
4.9. Escribir las instrucciones en Pascal que cuenten el nmero de tempera-
turas de la lista del Ejercicio 4.4, que estn por debajo de valor medio
(TemProm) y dejen este valor en la variable entera ndebajo. Escribir
la precondicin y la poscondicin para esas instrucciones, asi como el
invariante del bucle que contienen. Estn esas precondiciones relacio-
nadas con las poscondiciones del Ejercicio 4.8? Qu sugiere esto sobre
el orden en que esos dos grupos de instrucciones deberan escribirse si
las ussemos para resolver el Ejercicio 4.4c?
4.10. Qu mostraria el siguiente fragmento de programa?:
var x, y: reaL;
m, n, p: nteger;
begin
readln (x, m);
read (y);
read (n, p);
wrte (n, x);
wrteln (p);
wrteln (y, m);
end.
si se le suministrase la entrada siguiente:
13.215
23.7
236575
354679
4.4. MS PROBLEMAS ALGORTMICOS
En esta seccin nos alejamos del ya familiar problema de CM, e introducimos
otros problemas algortmicos junto con sus soluciones. Estos nuevos ejemplos
ilustran el conjunto de problemas que son susceptibles de solucionarse utili-
zando una computadora. Tambin nos servirn para ilustrar cmo los tres
estilos diferentes (descripcin en castellano de los pasos individuales, especifi-
caciones y otras aserciones, y codificacin en lenguaje Pascal) se utilizan para
realizar una descripcin y resolucin completa del problema.
Problemas algortmicos y su solucin 113
4.4.1. Clculo de el
Desarrollemos un programa llamado Pot en c i a que calcule la b-sima poten-
cia de a, o a
b
, donde a y b son enteros y el resultado un nmero real. Por
ejemplo, escrito como una funcin de Pascal Potencia(2,3) calcularia el
valor 2
3
= 8.
El\ la construccin de una solucin, debemos precisar previamente no slo
el resultado esperado, sino tambin el rango de enteros para los que el progra-
ma est bien definido; es decir, sus precondiciones. En particular, debemos
especificar que ciertas parejas de valores de a y b, tales como a = OYb = - 1,
deben ser excluidas, puesto que podrian conducirnos a errores computaciona-
les. (En este caso, Potenci a (0,1) representara 0-
1
1/0, que representa
una divisin con resultado indefinido). Tambin debemos tener en cuenta las
limitaciones del lenguaje de programacin en el que expresamos el algoritmo.
Por ejemplo, muchas versiones de Pascal restringen el rango de valores de los
enteros al rango - 2
15
... 2
15
- 1. Si identificamos estos valores con Mi nlnt y
Maxlnt, respectivamente, entonces las precondiciones de Potencia pueden
descartar todos aquellos valores de a o b que conduzcan un resultado que
exceda a Minlnt o Maxlnt. Por ejemplo, a = 2 Y b = 16 daran como
resultado 2
16
, que sera un valor mayor que Maxlnt para muchas versiones
Pascal.
Teniendo presentes estas condiciones, las precondiciones y poscondiciones
siguiente podran ser apropiadas para disear el programa de la potencia.
{pre: a y b son enteros A (a", O v a = O A b '" O)
A Minlnt '" a
b
'" Maxlnt}
{Pos t: resu l t = a
b
}
Para los valores de a y b que satisfagan esta precondicin, el resultado a
b
podra definirse como:
Definicin a
b
= 1 if b O
: ' : / ~ a v ' ~ ~ ' . : ~ I
if b > O
if b < O
Lb-a es
En la construccin de una solucin al problema, debemos tener en cuenta que
el valor de b, que gobierna el nmero de veces que se calcula a por a, es una
variable. Por tanto, cualquer solucin que calcule el producto de las bases
debe contener un bucle.
El diseo del bucle se ve facilitado si analizamos el caso en que b es
pequeo, y la varable P = ab resultante se calcula en la forma de la Tabla 4.3.
De los casos de esta tabla podemos hacer las observaciones siguientes:
1. El nmero de iteraciones del bucle es b - 1.
114 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
2. La inicializacin del bucle se realiza mediante la asignacin P : = a.
3. La instruccin que debe repetirse b -1 veces es la asignacin P := P * a.
Este ejemplo nos sugiere nuevas ideas sobre la naturaleza del invariante del
bucle. Esto es, de la i -sima iteracin del bucle, donde 1 ~ i ~ b, el valor de P
viene dado por
,
{; nv: P = ai A 1 <= ; <= b}
La salida del bucle se producir inmediatamente antes de la b-sima iteracin
(que nunca tendr lugar). Ahora i = b Yel invariante se convierte por s mismo
en P = ab, que est bastante prximo de la poscondicin del problema.
Tabla 4.3. Resultados intermedios para el problema de la potencia
VaLor de b CLcuLo de a
b
1 P := a
2 P := a;
P := P * a
3 P := B;
P := P * a;
P := P * a
4 P := B;
P := P * a;
P :=P*a;
P := P * a
Poscond;c;n
{P = a}
{P=a*a}
{P=a*a*a}
{P=a*a*a*a}
Entonces, si utilizamos la variable i para controlar el nmero de iteracio-
nes del bucle, tomar todos los valores del rango de enteros comprendidos
entre 1 y b ~ 1, para que el clculo de P sea correcto. Estas consideraciones
nos conducen al programa Pascal comentado, que se muestra en la Figura 4.14.
Quin comprueba las precondiciones? Cuando observamos la solucin a al-
gn problema algoritmico, tales como el de la Potencia o el de la CM,
es normal preguntarse: de quin es responsabilidad comprobar el cumpli-
miento de las precondiciones?, del programa o del usuario del programa?
Nos gustara tener algn tipo de garanta operativa de que ninguna entrada
diferente de aquellas para las que fue diseado el programa se producir y
tendremos as garantizado que no se nos contaminar ni peligrar la inte-
gridad del programa.
Consideremos el programa Potencia, para el que la precondicin esta-
blece que, para algunos valores de a y b, el resultado a
b
puede estar fuera del
conjunto de valores enteros que la computadora puede reconocer. Desgracia-
damente, esta precondicin del programa Potenc i a no puede ser comproba-
da explicitamente por el propio programa, puesto que la accin de calcular a
b
Problemas algortmicos y su solucin 115
para valores inadecuados provoca un error en tiempo de ejecucin; un mensaje
similar a ; nteger overf Low aparecer en el monitor, y la ejecucin con-
cluir repentinamente.
progra. Potencia;
{Este programa calcula la b-sima potencia de a)
varP: real;
1I, b, i: i nteger;
begin
{Pre : ent rada = a b A (a <> Oor a ~ O A b <> O)
A Mi nlnt <= a
b
<= Maxlnt}
WriteLn( 'lntroduci r dos enteros a y b: ');
ReadLn(a,b);
if b = O then
P := 1
else
begin
P := a;
i := 1;
while i <= abs(b) - 1 do
{i nv: P = a; A 1 <= i <= b)
begin
P := P * a;
i := i + 1
end;
if b < O then
P := 1/P
end;
WriteLn('Potencia(a,b) =',P);
{post: entrada = vacio A salida = a
b
)
end. {Potencia)
Figura 4.14. Un programa que calcula abo
La precondicin (a <> Ov a = O b <> O) podra haberla comproba-
do explcitamente el programa Potenc; a, y emitido un mensaje de error
en el caso de ser violada. Sin embargo, esto no es as en el programa de la
Figura 4.14.
En general, debemos elegir entre dos extremos cuando tenemos que decidir
quin debe comprobar las precondiciones:
Estrategia 1. Disear el programa sin comprobar ninguna de las precon-
diciones; construir el programa conforme a las precondiciones y poscon-
diciones, pero de forma que resuelva un problema ms general (es decir,
de forma que haga algo incluso si alguien introduce entradas fuera del
rango de las precondiciones), en este caso, el usuario no se ofender si el
programa se utiliza para los propsitos especificados por las precondicio-
nes.
Estrategia 2. Disear el programa de forma que compruebe todas aque-
llas precondiciones que sea posible comprobar, sin provocar una termi-
116 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
nacin anmala del mismo. Adoptar un convenio para devolver esta
informacin al usuario, si las entradas estn en desacuerdo con las pre-
condiciones.
La estrategia 1 podria denominarse programacin pasiva, mientras que la se-
gunda podra denominarse programacin defensiva. En un curso de programa-
cin lVanzado o de desarrollo profesional de software, siempre se prefiere la
estrategia 2 sobre la 1. Sin embargo, en un curso introductorio, donde se estu-
dian por primera vez otros conceptos fundamentales, suele aceptarse temporal-
mente la estrategia 1. Este punto es importante y trascendente. Lo analizare-
mos de nuevo en el Captulo 6, cuando discutamos las diferencias entre la
nocin de correccin de un programa, robustez y facilidad de uso.
No importa cul de las dos estrategias decidamos seguir, siempre debemos
introducir las precondiciones y poscondiciones como comentarios al principio
y al final del programa, respectivamente. Es decir, el lector humano no debe
tener nunca dudas de lo que hace el programa, aunque la propia computadora
no est totalmente informada de l.
4.4.2. Contar palabras de un texto
Los tipos numricos integer y real se utilizan en casi todos los problemas
algortmicos. Sin embargo, un gran nmero de problemas no se resolvera
adecuadamente con slo esos dos tipos. Muchos problemas involucran a cade-
nas de caracteres ASCII, como datos, y su solucin precisa la utilizacin de un
conjunto de operaciones caractersticas de este tipo de datos. La nocin de
cadena en Pascal puede definirse de la forma siguiente:
Definicin. Una cadena es una secuencia finita de cero o ms caracteres
ASCII. Cuando se escribe una cadena en un programa Pascal, se encierra
entre comillas simples ( , ) para distinguirla de las instrucciones del progra-
ma que la rodean.
En la Figura 4.1 hemos visto ejemplos de cadenas. Por ejemplo, todos los
mensajes como:
'Introducir la lista de calificaciones'
son cadenas. Extendiendo el concepto, podemos declarar variables del tipo
cadena (stri ng) * cuando queramos manipular valores de tipo cadena, en
lugar de valores numricos. Acompaando a la idea de cadena de caracteres,
estn una serie de funciones y procedimientos que sirven para manipularlas y
transformarlas. Esas funciones se resumen en la Figura 4.15.
N. del T.: Algunas implementaciones de Pascal incluyen entre los tipos incorporados el
tipo string. Por ello, cuando nos refiramos al concepto seguiremos hablando de cadenas" de
caracteres y utilizaremos la palabra slring" cuando hablemos del tipo.
Problemas algortmicos y su solucin 117
Figura 4.15. Resumen de las operaciones sobre cadenas
y tipos involucrados*.
En el manual de laboratorio se realiza una discusin completa de estas
operaciones. Aqu slo daremos unos pocos ejemplos que sirvan de ayuda para
comprender cmo se utilizan las cadenas de caracteres en la resolucin de
algunos problemas algortmicos de manipulacin de textos.
Para declarar una variable cadena, por ejemplo s, basta con escribir la
declaracin siguiente:
va .. s: st .. ing;
Ahora podemos asignar valores a la variable utilizando la asignacin o los
procedimientos Read o ReadLn, de la misma forma en que lo hacamos con
los enteros o los reales. Por tanto, podemos escribir instrucciones como:
5:= 'Hello World!'; o Read(s);
Para conseguir el efecto que se muestra en el centro de la Figura 4.16.
La Figura 4.16 muestra el efecto de la utilizacn de varias de las operacio-
nes de las cadenas, tales como Lenght, Pos, Copy, Insert, Delete y
Wri te. Obsrvese que sus nombres son similares a los de las funciones que
manipulaban listas (vase Fig. 4.7). Ms detalles pueden encontrarse en el
manual de laboratorio.
La longitud de una cadena (valor de la funcin Lengh t) es, simplemente,
el nmero de caracteres de que se compone, incluidos los blancos, signos de
puntuacin y otros caracteres especiales del conjunto ASCII.
N. del T.: En las Figuras 4.15 y 4.16 na se han traducido los nombres de las funciones.
pues son los mismos que suelen tener esas funciones en las implementaciones de Pascal. que
incluyen el tipo string.
118 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
Input I
'Hello World!'
'Hello World!'
1Output 1
12
va.. s: St,;ng;
(
s := 'Hello World! ';
lnsert(', Ciao', s, 12)
"
'Hello World, Ciao!'
7
Figura 4.16. Utilizacin de algunas operaciones de cadenas de caracteres.
La funcin Pos realiza una bsqueda en la cadena, de izquierda a derecha,
tratando de encontrar la primera ocurrencia de otra cadena. As, si escribimos
Pos (s, I W' ) preguntamos por el ndice o posicin de la primera ocurrencia
empezando por la izquierda, de la cadena 'W'. Si la cadena no estuviera dentro
de s, la {uncin devolver el valor O.
La funcin Copy selecciona una subcadena de la cadena argumento, defini-
da por el valor de la posicin inicial y la longitud. As, Copy( s, 1,1) selec-
ciona la subcadena de s que comienza en la posicin 1 y que tiene una longi-
tud 1. Como se trata de una funcin, Copy devuelve un resultado de tipo
string, aunque no altera para nada la cadena original s. La nica forma en que
s podra quedar modificada, sera mediante una subsiguiente asignacin a s,
del resultado de la funcin Copy, como ocurre en la instruccin siguiente:
s := Copy(', adis' ,12);
Finalmente, la funcin Insert crea una cadena ms larga mediante la
insercin o incrustracin, de una cadena dentro de otra, a partir de una deter-
minada posicin. As, Inserte I , adi s ,s, 12), literalmente indica que se
debe crear un valor nuevo de tipo string para la variable s incrustrando el
valor " adis' en la cadena I Hello world! " que es el antiguo valor de s.
Para ilustrar estas ideas, considrese el problema de construir un programa
que tenga como entrada una cadena s, y que cuente el nmero de palabras de
la entrada.
Por simplicidad, supongamos que una palabra es una secuencia de caracte-
res distintos del blanco, tengan o no significado dentro de la lengua castel1ana
comn. Los signos de puntuacin, tales como puntos y comas, y as sucesiva-
Problemas algortmicos y su solucin 119
mente, se consideran elementos de la palabra a la que se aaden. Por ello, cada
una de las cadenas siguientes son palabras:
esos
conocer.
IMundo! I
Podemo$ escribir las precondiciones y poscondiciones que describen el proble-
ma, como sIgue:
{pre: entrada 'c[1J c[2J .,. c[nJ' /\ n >= O1-. cada c[iJ es
un carcter ASCII}
{post: entrada vacia /\ sal ida = nmero de palabras de la entrada}
Un programa que resuelve este problema, utilizando la mayoria de las funcio-
nes de la Figura 4.16, se muestra en la Figura 4.17.
program ContadorPalabras;
(El programa cuenta el nmero de palabras de una linea de texto, y
muestra el cmputo resul tanteo Se entiende por palabra cualquier
secuencia de caracteres distintos del blanco, que est precedido por
el comienzo del texto o un blanco, y que termina con el final del texto
o un blanco)
var s: string;
i, npalabras: integer;
begin
{pre: entrada = 'c[1J c[2J ... c[nJ' 1-. n >= O1-. cada c[iJ es
un carcter ASCII}
{Paso 1. Obtenemos el texto de entrada}
writln(' introduci runa linea de texto seguida de <RET>'}
Read(s);
Writeln;
Insert(" ,s,Lenght<s) + 1);
(s = 'c[1J c[2J '" c[nJ c[n + 1J' 1-. c[n + 1J = " /\ n O)
{Paso 2. Contamos las palabras del texto}
npalabras := O;
i := 1;
while i <+ Lengh(s) - 1 do
{inv: ... i-1JI-.1<=i<=n+1)
begin
if (Copy(s, i, 1) <>' ') and (Copy(s, i + 1,1) =' ') then
npalabras npalabras + 1;
i:=i+1;
end;
(npalabras = palabras contadas en s[1 ... n + 1J)
(Paso 3. Se muestra el resultado de la cuenta)
writeln('el nmero de palabras es', npalabras)
{post: entrada = vacia 1-. sal ida = nmero de palabras de la entrada}
end. (ContadorPalabras)
Figura 4.17. Programa que cuenta el nmero de palabras
de una cadena de texto.
120 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
En el programa anterior, la variable npa Lab r as indica el nmero de palabras
en el texto de entrada, mientras que n simboliza su longitud.
El corazn del programa es el bucle whi Le, donde se realiza una compro-
bacin sobre el final del texto de s. Es decir, el final del texto ser slo cuando
el carcter i -simo sea un blanco, y el i + 1-simo tambin. Este convenio se
verifica para la palabra ms a la derecha de s; es decir, la instruccin:
1
Insert<' " s, Length<s) + 1);
Introduce un carcter adicional a la derecha de s. Los casos en los que el valor
de entrada de s termine con un carcter distinto del blanco, son eliminados
previamente a la entrada del bucle que cuenta.
Consideremos la cadena de entrada:
'Whose woods these are 1 thi nk 1 know .
Tras completarse el paso 1 del programa ContadorPa Labras, la variable s
queda con el valor:
5= 'Whose woods these are 1 think 1 know. '
Obsrvese que el blanco adicional se ha insertado dentro de la palabra I know I
de s. Ahora, el bucle de bsqueda del paso 2 comienza con la variable ndice
i = 1:
s IWhose woods these are 1 thi nk 1 know.1
i
Utilizamos la expresin Copy(s, i, 1) para seleccionar el ;-simo ca-
rcter de s y Copy(s, i + 1, 1) para seleccionar el i + 1-simo. As, la
expresin combinada:
<CoPY<s, i, 1) <>' ') and <copy<s, i + 1,1) =' ')
que busca si dentro de s el i -simo carcter es distinto de blanco, a la vez que
el i + 1-simo s lo es. Obsrvese que esta condicin es exactamente verdadera
cuando se alcanza el final de una palabra, como en el caso en que i = 5:
s IWhose woods these are 1 think 1 know.1
i
Puesto que el contador npaLabras se incrementa slo al final de cada pala-
bra, registra apropiadamente el nmero de palabras de s en el devenir de i
desde la primera posicin del texto hasta el siguiente carcter al final del tex-
to s. Esta posicin se establece utilizando la expresin Lenght (s) - 1.
Problemas algortmicos y su solucin 121
As, el nvarante del bucle se preserva. A la salida del bucle, el invariante se
converte en una expresn sobre el valor final de npa labras, necesara para
que se satisfaga la poscondicn. Nngn otro valor nos satisfara!
Fnalmente, obsrvese la similitud entre las operaciones de las cadenas y las
correspondientes de las listas, viendo las Figuras 4.15 y 4.17, respectivamente.
Por ejemplo, la funcin de cadenas Lenght devuelve el nmero de caracteres
de Uljla cadena, mientras que la LenghtL; sta devuelve el nmero de elemen-
tos de una lista. Esta similitud es de gran ayuda cuando queremos recordar el
nombre de las funciones, cuando queremos resolver otros problemas algortmi-
cos que utilizan listas y cadenas de caracteres.
4.4.3. Representacin del problema de Las Tres-en-Raya
Aunque los tipos numricos y cadena de caracteres son la base de gran canti-
dad de problemas algortmicos, no sirven para caracterizar aquellos problemas
que implican la representacin de informacin grfica. Este tipo de problemas
incluye la visualizacin y anlisis de imgenes de rayos X, fotografas desde
satlites, tableros de ajedrez y otros tipos de tableros de juego, y otros tipos de
grficos utilizados habitualmente en gestin comercial y en el clculo cientfico.
Para ilustrar este tipo de problemas, consideremos el conocido juego de las
tres-en-raya. Supongamos que se nos pide que construyamos un algoritmo que
muestre los movimientos individuales del juego de las tres en raya, reflejando
cada movimiento (X o O) en un entramado rectangular de la pantalla de la
computadora.
Para poder resolver este tipo de problemas necesitamos un nuevo tipo de
datos y el correspondiente conjunto de operaciones asociadas, que permitan a
un programa dibujar y realizar transformaciones sobre un array* rectangular,
denominado ent ramado de celdas individuales. Cada celda puede rellenarse
de una de las cuatro formas siguientes: No (sin rellenar); S (rellena en gris); Xo
O. En la Figura 4.18 se muestra un entramado de 3 x 3 celdas, las cuales
tienen valores particulares en la que las filas y columnas del entramado se han
numerado de la forma convencional. La celda de la fila 1, columna 2 es una X;
la celda en la fila 2, columna 1 es S; la celda de la fila 3, columna 3 es O; y las
seis celdas restantes son No.
El nmero de filas y columnas, as como el tamao de cada celda, se
establece en el momento en que el programa lo crea. El tamao de la celda se
mide en pixels, que son unidades grficas de la pantalla de la computadora y
que no son divisibles en unidades ms pequeas. Cada celda del entramado de
la Figura 4.18 es de 20 pixels de ancha y otros 20 de larga. El anclaje de un
entramado es la posicin en la pantalla de su esquina superior izquierda,
cuando se visualiza el entramado. La localizacin viene dada por un par de
N. del T.: Aparece aqui por primera vez la palabra inglesa ARRAY. Como ocurriera con
string, esta palabra se ha traducido de muchas formas, en mi opinin todas ellas insatisfactorias.
Por ello prefiero, tanto en este punto como en ocurrencias posteriores, respetar el trmino ingls.
122 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Anclaje
3
} Tamao de la celda ~ 20 pixels
~ ~ - - i
o
Figura 4.18. Un entramado de 3 x 3 celdas y las situaciones de las mismas.
coordenadas xy, teniendo la esquina superior izquierda dc la pantalla las coor-
denadas (O, O).
La Figura 4.19 muestra las distintas operaciones que pueden utilizarse para
crcar entramados de varios tamaos y para modificar cl estado de sus celdas.
Si declaramos una-variable dc tipo Grid*, podemos utilizar esas opcraciones
para realizar transformaciones sobre la variable.
CellOn ~ o l e ~
CellOff
CellX
Ce llO
TurnCellOn
TurnCellOff
TurnCellX
TurnCellO
Figura 4.19. Resumen de las operaciones ms importantes.
N. del T.: Seguiremos aqu el msmo convenio entre tipo y objeto que utilizamos entre
cadena y slring.
Problemas algortmicos y su solucin 123
Sin embargo, al contrario de las listas y cadenas, necesitamos comenzar los
programas que utilizan estas facilidades grficas con la instruccin
StartGrids;
y finalizar el programa con la instruccin
StopGrids;
La primera de ellas borra la pantalla y crea dos ventanas, una ventana grfica a
la izquierda y una de texto a la derecha. Todos los entramados que se creen en
el programa aparecern en la ventana grfica, mientras que los textos, entradas
y salidas lo harn en la ventana de texto. Los detalles sobre esas y otras
operaciones grficas se explican extensivamente en el manual de laboratorio.
Al contrario que las variables de tipo Lista o string, las variables del tipo
Gr ; d se deben crear y dibujarse en la ventana grfica antes de asignar valores
a las celdas. Por ejemplo, si queremos crear el entramado d para que tenga 3
filas y columnas, con celdas de 20 pixels y anclado en la posicin (10, 10) de la
ventana grfica, escribiremos:
MakeGrid(d, 3,10,10,20);
Esta instruccin crea el entramado d con la forma y tamao idnticos al
entramado de la Figura 4.18, pero teniendo todas sus celdas en blanco. El
resultado se muestra en la Figura 4.20.
Si queremos cambiar de aspecto alguna celda de d, utilizaremos las opera-
ciones TurnCeLLOn, TurnCellX o TurnCeL LO. Por ejemplo,
TurnCellX(d, 1, 2)
coloca una X en la celda de la fila 1, columna 2. El resultado de esta accin
aparecer inmediatamente en la ventana grfica. Si queremos extender lo ante-
(O, O)
(10, ro;
Ventana grfica Ventana de texto
( 2 0 0 , 2 ~
Figura 4.20. Aspecto de la pantalla para salida grfica.
124 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
rior de forma que todas las celdas de la columna 2 contengan X, podemos
escribir el bucle siguiente:
for i := 1 to GridSize(d) do
TurnCeLLX(d, i, 2);
Donde se ha utilizado la variable integer i para recorrer todas las filas del
entrainado d, y se ha utilizado la funcin GridSize para obtener el nmero
total de filas y columnas del entramado d.
Finalmente, el grupo de operaciones CeLLOnCd, i, j), CeLLOffCd,
i, j), Ce LLX Cd, i, j) y Ce LLO Cd, i, j) pueden utilizarse para cono-
cer el estado de la celda de la fila i, columna j del entramado d. Por ejemplo,
si nuestro entramado d tuviera el aspecto del de la Figura 4.18, la funcin
CeLLOnCd, 1, 3) devolvera el valor faLse mentras que la operacn
Ce LLX Cd, 1, 2) devolvera el valor t rue.
Con estas operaciones presentes podemos resolver el problema propuesto
al princpio de la seccin. El programa de la Figura 4.21 controla el juego de
Las Tres-en-Raya, solicitando una alternancia de movmientos a dos jugado-
res, y redibuja la situacin del juego en la parte grfica de la pantalla.
program TresEnRaya;
uses Grids;
const ancLajex = 20; {coordenadas x e y}
ancLajey = 20; {deL tabLero en La pantaLLa}
var tabLero: Grid;
movimiento: integer; {movimiento que se debe mostrar}
i, j: integer; {fila y columna del movimiento}
begin
{pre: una serie de movimientos de las Tres en Raya}
{Paso 1. Inicializamos eL tabLero y eL juego}
StartGrids;
MakeGrid(tablero, 3, ancLajex, anclajey, 40)
movimiento : ~ 1;
{Paso 2. Alternancia de movimientos entre x e y}
repeat
writeLn(' introduci r fila y columna del siguiente movimiento');
writeLn('(O Osignifica eL finaL deL juego): ');
read(i); read(j);
i f i > j then
begin
if movi mi ento mod 2 ~ 1 then
TurnCeLLX(tabLero, i, j) {Los movimientos impares son de X}
else
TurnCe LLO( tabLero, i, j) {Los movimi entos pares son de O}
end;
movimiento := movimiento + 1;
unti l i = O;
Problemas algortmicos Vsu solucin 125
{post: entrada ~ vaca /\
sa l da = una representaci 6n gr f i ca de estos movi mi entos sobre
un tablero de las Tres-en-Raya}
end. {TresEnRaya}
Figura 4.21. Programa que controla Las Tres-en-Raya.
En el programa, dos jugadores alternan sus movimientos. Cada movimien-
to viene dado por un nmero de fila ;, y uno en columna j, donde los
jugadores desean colocar una Xo un O. La primera persona que juega es X. El
control del juego y la determinacin del ganador se encuentra totalmente en
manos de los jugadores. Cuando un jugador introduce O O (dos ceros), el
programa terminar el juego. Un ejemplo de una secuencia de movimientos y
de los tableros resultantes se muestra en la Figura 4.22.
La variable mov; mi ento juega un papel trascendental en la simulacin.
Almacena el nmero de jugada que est a punto de realizarse, en cada repeti-
cin del bucle del paso 2. Movimientos de nmeros impares (siempre que
mov; mi ento mod 2 = 1) el programa coloca una Xen la posicin (;, j)
del tablero. Un nmero impar de movimiento coloca un O en la posicin del
tablero.
Introducir fi la y columna del siguiente movimiento
(O Osignifica el final del juego):
1 2
Introducir fi la y columna del siguiente movimiento
(O Osignifica el final del juego):
1 3
Introducir fila y columna del siguiente movimiento
(O Osignifica el final del juego):
3 2
Figura 4.22. Serie de tres movimientos de Las Tres-en-Raya.
Aunque el programa anterior no sea una implementacin excesivamente
satisfactoria del juego de las tres-en-raya, sirve para ilustrar alguna de las
operaciones grficas bsicas que acompaan al tipo Gr; d, Y su utilizacin
como ayuda en la visualizacin de la salida de cierto tipo de problemas algorit-
micos.
Existen varias razones por las que este programa no representa una simula-
cin totalmente satisfactoria del juego de las tres-en-raya. En primer lugar,
obsrvese que el programa permite a un jugador borrar el movimiento del
otro, sin ms que especificar la misma casilla. Segundo, el programa no analiza
si un jugador accidentalmente introduce un nmero de fila o de columna
errneo, tal como 4 7. Tercero, el programa no tiene ningn conocimiento de
la situacin del juego. Es decir, no puede reconocer un movimiento tras el que
126 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
gane X o gane Y, o queden empatados (lo que es bastante habitual en este
juego). Cuarto, el programa no est preparado para ser uno de los dos jugado-
res, realizando movimientos inteligentes en respuesta a los que realice una
persona jugando con la pieza opuesta.
La primera y segunda de las carencias son fciles de solucionar. Sin embar-
go, la tercera y la cuarta requieren la introduccin de fragmentos de algoritmos
ms sofisticados, que corresponderan al rea de la informtica conocida como
inteligencia artificial. Es decir, cdigo que permitiera a la computadora simular
la inteligencia humana, aunque fuera de forma muy limitada.
Hemos investigado un pequeo nmero de algoritmos, y las herramientas
del lenguaje Pascal que sirven para su realizacin en una computadora. Hemos
utilizado varios tipos de datos, tales como el integer, real, string, lista y grids; y
varios tipos de instrucciones que incluyen la asignacin, la seleccin condicio-
nal, los bucles y la E/S. Tras estudiar estas herramientas y ejemplos, y tras
haber trabajado con el manual de laboratorio, el lector habr conseguido
desarrollar una cierta facilidad en el diseo y escritura de programas pequeos
en Pascal. Con los Ejemplos 4.11 a 4.27 conseguir algo ms de prctica.
Recuerde que el aprendizaje del diseo de programas, como el aprender a tocar
un instrumento, requiere no slo estudio terico, sino mucha prctica. Cuando
ejecute sus programas en una computadora, sea paciente e intntelo de nuevo;
recuerde que pocos programas funcionan bien la primera vez. Conseguir
mayores xitos si lo tiene en cuenta!
Ejercicios
4.11. Escribir un programa en Pascal que escriba S1, si la variable Kes un
entero positivo impar (como 1, 3, 5, ...) Y NO en caso contrario.
4.12. Escribir un programa que asigne a mel valor absoluto de n, sin utilizar
la funcin de Pascal que da el valor absoluto.
4.13. Escribir un programa Pascal que escriba la secuencia de n nmeros, en
la que cada trmino se obtiene de doblar el valor del anterior, siendo n
la entrada. (Es decir, cada nmero en la secuencia es el doble del ante-
rior.)
4.14. Repetir el Ejercicio 4.13, pero cambiando el programa para que escriba
los n nmeros en orden inverso. (Es decir, cada nmero es la mitad del
anterior.)
4.15. Escribir un programa que lea 25 enteros y que cuente cuntos de ellos
son negativos.
4.16. Escribir un programa que lea 100 enteros y que determine y escriba
cuntos de ellos son divisibles por 5.
Problemas algortmicos Vsu solucin 127
4.17. Escribir un fragmento de programa que realice lo siguiente:
Poner x a x + A si x es negativo;
Poner x a x + A+ B si x es cero; o
Poner x a x + A+ B + e si x es positivo.
Cuidado!
,
4.18. Qu hacen los fragmentos de programa siguientes? Es decir, si in-
trodujera y ejecutase en la computadora este programa, cul seria la
salida?
a) var
k, j, m: integer;
n: real;
begin
k := 4;
j := 8;
m := 9;
n := mdiv j + k * 1.0 - mdiv j;
writeln ('n= " n)
end;
b) var
m, j: integer;
begin
m : ~ 4;
j := 1;
whi le (j < m) do
begin
j:=j+2;
m:= m+ 1
end;
writeln ('m= ',m, Ij= " j)
end;
e) var
k, j: integer;
begin
for k : = 1 to 10 do
begin
j := 10 - k;
if (j <= 4) then
j := j - 1
end;
writeln ('j = " j, 'k= " k)
end;
ti) var
n, m: integer;
begin
n := O;
m := 1;
128 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
whi le (m <= 101) do
begin
n := n + 1;
m := m+ 5
end;
writeln ('n= " n)
end;
e) var
j, k, m: integer;
begin
k := O;
for j : = 1 to 3 do
for m := 1 to 4 do
k :=k+1;
writeln ('k= " k)
end;
f) uses
Lista;
var
k: Lista;
j: integer;
begin
k[1] 1;
for j := 2 to 4 do
k[j]
wri teLi sta (k)
end;
g) uses
Lista;
var
m: Lista;
j: integer;
begin
j := 1;
while (j <= 2) do
begin
m[j + 2] j;
m[3-j] :=j;
j
end
WriteLi sta (m)
end;
4.19. Trazar la ejecucin del programa Po t ene i a para las entradas 5 y - 4,
escribiendo los valores de las variables a, b, P e i, antes de que se
ejecute cada iteracin.
4.20. Escribir un programa que cambie a cero todos los valores de una lista
que ocupen una posicin impar y que sean impares. Es decir, si llama-
mos L a la lista, el programa debe examinar L[1 J, y si contiene un
Problemas algoritmicos y su solucin 129
valor impar, poner L [1] a O. Lo mismo debe hacer para L [3] ,
L[S], , mientras que deben descartarse los elementos L[2],
L[4], .
4.21. Escribir un programa que escriba los 11 primeros nmeros de Fibonac-
ci. Los nmeros de Fibonacci son 1, 1, 2, 3, 5, 8, 13, ...
4.22. Escribir un programa que calcule el factorial de un entero n (denotado
por ni). Recurdese que la definicin de n! es:
O! 1
n! n x (n - 1)1
4.23. Disear y escribir un programa en Pascal que lea un determinado texto,
y calcule y escriba el nmero de ocurrencias de la subcadena I and' .
4.24. Trazar la ejecucin del programa ContadorPa Labras de la Figura
4.17, mostrando los valores de las variables i y npa Labras durante su
ejecucin, con el texto de entrada siguiente:
'Able was 1 ere 1 saw Elba .
4.25. Comprobar que el invariante del bucle del programa ContadorPa La-
bras es vlido para la entrada del Ejercicio 4.24, analizndolo para
cada valor de i que provoca un cambio en npa Labras. Por ejemplo,
la primera interpretacin del bucle ocurrir cuando i = 6, Yse leera de
la forma siguiente:
{npalabras = 1 para 'Able' /\ 1 <= 6 < ~ 26)
4.26. Escribir un programa en Pascal que lea un texto y lo invierta y escriba.
Es decir, si la entrada del programa es:
'mayo 1992'
la salida del programa debe ser:
'2991 oyam'
4.27. Refinar el programa de las Tres-en-Raya, de forma que prevea el
que un jugador coloque una X o una O en una casilla ya ocupada.
Cuando esto ocurra, el programa debe avisar al jugador, de forma cor-
ts, que debe hacer un movimiento alternativo y registrar un nuevo
movimiento.
130 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
4.28. Escribir un programa que calcule el coste total del franqueo postal de
una serie de envos. Debe contener un bucle que lea la cantidad y precio
de cada envo y lo acumule al total. Despus de que se haya introducido
el ltimo elemento, el programa mostrar el coste total de la operacin
y el nmero total de envos realizados. El coste total deber reflejar un
5 por 100 de impuestos. Asegrese de incluir en el propio programa las
pre y. poscondiciones.
4.5. RESUMEN
En este captulo se han introducido las ideas de problema algoritmico y de su
solucin correspondiente. Se ha hecho especial hincapi en la importancia de
especificar con precisin el problema en forma de precondicin y poscondi-
cin. Tambin se ha introducido la idea de invariante de un bucle y su utiliza-
cin en un programa. Se comenz con algunos sencillos problemas matemti-
cos, para seguir con problemas de procesamiento de textos y manipulacin de
grficos, proponiendo y discutiendo su solucin en Pascal.
Este captulo es una base importante para los Captulos 5 y 6. En el Cap-
tulo 5 se introduce la metodologa MAPS, que es una metodologa sistemtica
para la resolucin de problemas algortmicos, y que puede utilizarse en la
resolucin de una amplia gama de problemas dentro de esas tres reas. La
metodologa MAPS incide especialmente en la utilizacin de las ideas funda-
mentales introducidas en el Captulo 4 -precondiciones, poscondiciones, bu-
cles, invariantes, listas, cadenas, entramados y sus operaciones asociadas. En el
Captulo 6 se introduce una tcnica que permite asegurar la correccin de los
programas en Pascal que construimos al solucionar problemas algortmicos.
CAPTULO 5
RESOLUCiN
DE PROBLEMAS ALGORTMICOS
El conocimiento puede ser de dos tipos. Conocemos algo por nosotros mismos,
o conocemos dnde podemos encontrar informacin sobre ello.
SAMUEL JOHNSON, 1775
En el Captulo 4 nos concentramos en la construccin de programas relativa-
mente cortos, que resolvan problemas bastante sencillos. Enfatizamos en la
necesidad de realizar especificaciones claras, estableciendo los principales pa-
sos del algoritmo y trasladando esos pasos a instrucciones Pascal ejecutables.
En este proceso nos familiarizamos con los tipos de datos bsicos (i nteger,
reaL y booLean) y con otros algo ms complejos (Listas, strings y
gri ds), junto con sus operaciones asociadas. Tambin desarrollamos algunos
programas sencillos para ilustrar el gran nmero de problemas con una solu-
cin algoritmica. Estos programas son una muestra de la denominada pro-
gramacin en pequea escala.
Sin embargo, para poder resolver problemas algoritmicos ms extensos y
complejos, necesitamos proveernos de un conjunto de tcnicas de resolucin de
problemas ms robustas. Es decir, la programacin en gran escala requiere
la utilizacin de una metodologa unificada y robusta que pueda utilizarse de
manera fiable en una variada rea de aplicaciones. Una Metodologa de Reso-
lucin de Problemas Algortmicos *, MAPS, se desarrollar e ilustrar en este
capitulo.
5.1. NECESITAMOS UNA METODOLOGA
Los problemas de la programacn en gran escala difieren de los de la pequea
escala en tres aspectos. Primero, un programa que representa una solucin a
* N. del T.: En el texto se respelar el acrnimo ingls MAPS (Methodology for Algorith-
mic Problem Solvng), debido a que el autor pretende enfatizar la semejanza de la metodologa con
el trmino Map o Mapping, que podra traducirse por correspondencia y que se utiliza amplia-
mente en la terminologia informtica. Debido a que al traducirlo es imposible capturar este
concepto, respetamos el acrnimo original.
132 Computacin l. Lgica, resolucin de problemas, algoritmos Vprogramas
problemas grandes ocupa generalmente ms de una pgina de cdigo en Pas-
cal. Segundo, los programas largos tienen, adems de su longitud, alguna otra
caracterstica que los hace ms complejos. Tercero, las soluciones para proble-
mas ms complicados se expresa mejor si se utiliza una sistemtica que si se
escribe directamente el cdigo que se nos ocurre. Es necesario que los primeros
pasos describan el problema y que el algoritmo resultante sea fruto de un
diseo, fruto de una sistemtica paso a paso. De hecho, en muchos casos, la
solucin a un problema grande es el resultado del trabajo de un grupo de
trabajo numeroso ms que de una sola persona.
Las soluciones a los problemas grandes comparten con las de los pequeos
tres caracteristicas: legibilidad, eficiencia y correccin. Legibilidad significa que
cualquiera que conozca el lenguaje Pascal y el dominio al que pertenece el
problema, es capaz de entender el problema y el programa sin ms que leer
cuidadosamente el programa y los comentarios que le acompaan, indepen-
dientemente de lo largo que sea el programa o lo complejo que sea el pro-
blema. La eficiencia es deseable porque los recursos informticos son rela-
tivamente costosos, y las aplicaciones deben intentar minimizarlos. La
correccin significa que todas las ejecuciones del programa deben conducir
a resultados vlidos para cualquier entrada permitida por las especificaciones
del programa.
Estas tres caractersticas de los problemas complejos tienden a dotarlos de
una identidad dual. En un extremo, la legibilidad de los programas permite
que stos constituyan una explicacin de la solucin a problemas algortmicos
para un lector interesado. En el otro extremo, la eficiencia y fiabilidad de los
programas les permite ser un mecanismo a travs del cual la computadora
puede ser utilizada para resolver problemas. En la construccin de programas
utilizando la metodologa MAPS, siempre tendremos en mente esta doble
identidad de los programas. i El proceso de codificacin de un programa en
Pascal es slo una parte de la complicada tarea de resolver un problema
algoritmico!
5.1.1. Generalidades sobre el mtodo MAPS
En qu consiste esta metodologa de resolucin de problemas algortmicos?
La metodologa MAPS puede resumrse como la sucesn de las etapas si-
guientes:
Etapa 1: El dilogo. Comprender el problema. Leer el enunciado del
problema. Hacer preguntas sobre las caractersticas de la entrada y la
salida y sus limitaciones, hasta tener completamente claro el problema.
Etapa 2: Las especificaciones. Construir las especificaciones a partir de
nuestro conocimiento del enunciado del problema. Escribir pre y poscon-
diciones que sean completas y consistentes. Es decir, asegurarse de que
las precondiciones cubren todas (y slo esas) las posibles entradas, que
las poscondiciones definen la salida para todas las posibles entradas, y
Resolucin de problemas algortmcos 133
que tanto las precondiciones como las poscondiciones son interna y mu-
tuamente consistentes.
Etapa 3: La divisin. Subdividir, de forma sistemtica, el proceso en una
coleccin de pasos diferentes. Repetir este proceso para cada paso hasta
que la subdivisin no tenga sentido. Identificar las relaciones de control
entre los distintos pasos. Es decir, qu paso debe preceder a cul?, qu
pasos son parte de otro ms complejo?, qu pasos deben repetirse den-
tro de un bucle?, y asi sucesivamente. Documentar cada paso escribiendo
una breve descripcin de sus objetivos. Asignar un nombre apropiado a
cada nueva variable que incorporemos en cada paso, en funcin de cul
es su cometido.
Etapa 4: Definicin de abstracciones. Determinar cules de los pasos que
hemos utilizado habian sido, a su vez, usados en otra situacin, recolectar
las rutinas que se utilizaron en esa situacin y adaptarlas para reutilizar-
las en la situacin presente. En muchos casos, esta tarea implica la cons-
truccin de una rutina nueva a partir de otras dos, o incluso construir
una nueva para una utilizacin ms especializada.
Etapa 5: Codificacin. Trasladar a Pascal cada paso individual de nuestra
solucin, identificando rutinas nuevas y reutilizando aquellas que resul-
ten apropiadas para realizar cada paso individual. Conectar cada paso
utilizando la estructura de control apropiada (bucles, invocaciones a pro-
cedimientos, secuencias de instrucciones, selecciones condicionales, etc.)
de una forma compatible con lo diseado en el paso 3. Respetar como
comentarios toda la informacin generada durante el paso 3 para cada
paso individual y las variables correspondientes.
Etapa 6: Prueba y verificacin. Probar o validar de forma sistemtica el
programa Pascal, hacindolo ejecutarse para un conjunto de valores de
entradas, que permita explorar todo el rango de valores permitido por las
precondiciones. Para cada ejecucin, comprobar que las salidas satisfacen
las poscondiciones. De forma alternativa, verificar cuando sea apropiado
alguno o todos los pasos del programa, utilizando tcnicas de demostra-
cin formal.
Etapa 7: Presentacin. Aadir un comentario al comienzo del programa
para clarificar su propsito, escribir el nombre de los autores y la fecha, e
identificar la utilizacin de rutinas que fueron desarrolladas con otro
propsito (e incluso por otros programadores). Preparar un listado del
programa, junto con un listado de algunas ejecuciones de prueba.
En este captulo se ilustran cada una de las etapas de la metodologa MAPS.
Definamos previamente la idea de rutina, tal y como se considera en la resolu-
cin de problemas algortmicos, junto con el mtodo de Pascal para empaque-
tarlas, de forma que stas sean reutilizables convenientemente.
134 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
5.2. CONSTRUCCiN DE SOFTWARE PARA
SU REUTILIZACiN: LA RUTINA
En el Captulo 4, y en el manual de laboratorio, se han presentado algunos
procedimientos y programas cortos que realizan tareas especificas. Por ejem-
plo, un programa calcula el valor promedio de una lista de enteros, otro
calcula una potencia entera de un nmero, un tercero localiza el mximo de
una lista, y otros cuentan las palabras de un texto o visualizan una secuencia
de jugadas del juego de Las Tres-en-Raya.
Tuvimos que realizar un gran esfuerzo, porque desarrollamos esos proble-
mas partiendo de la nada. Es evidente que, para problemas ms complejos,
tendremos que hacer un esfuerzo mayor si los resolvemos tambin partiendo
de la nada. Existe alguna alternativa? Seguramente no queremos seguir resol-
viendo problemas si no podemos beneficiarnos de la experiencia adquirida al
resolver otros problemas.
Si encontramos un problema que para solucionarlo podemos utilizar partes
de otros previamente resueltos, el no hacerlo y desarrollar una solucin desde
el principio seria un gran despilfarro de tiempo. Nuestro tiempo y energa
estarn utilizados de una forma ms eficaz si somos capaces de reutilizar solu-
ciones ya conocidas cuando sean necesarias. La correccin de la solucin nuc-
va ser ms fcil de establecer, puesto que la de uno de sus componentes ya lo
fue anteriormente.
Un algoritmo o parte de l, que parcialmente puede ser rcutilizado, recibe
el nombre de rutina. Una buena parte del tiempo empleado en resolver proble-
mas se utiliza en identificar rutinas y en reutilizarlas en forma apropiada.
Definicin. Una rutina es una parte de un algoritmo que puede reutilizarse
en otros contextos de resolucin de problemas algortmicos.
Algunas rutinas son tan comunes que estn incluidas en el lenguaje de progra-
macin Pascal para utilizarlas en los programas. Estas rutinas incluyen los
operadores numricos (+, -, *, /, di v y mod); las expresiones aritmticas,
las estructuras de control (i f, whi Le y f o r); los operadores de entrada,
salida y asignacin (read, wri te y :=) y los operadores de cadenas (copy,
pos y Length). Se pucden aadir al lenguaje otras rutinas para manipular
listas (ReadLi s t a, Wri teLi s tal y entramados (Ma keGr i d, Gr i dS i ze y
TurnCeLLOn).
Existe una gran variedad de rutinas para diferentes dominios de la resolu-
cin de problemas. Varios de ellos se introducirn en este capitulo.
5.2.1. Encapsulamiento de rutinas para la reutilizacin.
Abstraccin procedimental
Cmo podemos almacenar o encapsular rutinas de forma que puedan ser
reutilizadas con posterioridad en la resolucin de otros problemas? Un mtodo
Resolucin de problemas algoritmicos 135
fundamental para construir rutinas en Pascal es la denominada abstraccin
procedimental. Siempre que hacemos que una parte de un programa ya existen-
te se convierta en una rutina, primero encontramos (y definimos) su generaliza-
cin ms apropiada, y despus la convertimos, de forma sistemtica, en un
procedimiento o funcin de Pascal. Estdiese en el manual de laboratorio los
detalles de cmo utilizar y crear los procedimientos y funciones de Pascal antes
de continuar con el captulo.
La 'abstraccin procedimental es un proceso que consta de tres etapas:
1. Nombrar la abstraccin. Asignar un nombre que identifique claramen-
te el algoritmo que representar el algoritmo resultante.
2. Redefinir las precondiciones y poscondiciones del problema, de forma
que su solucin pueda implementarse como un procedimiento o funcin.
a) Parametrizar la entrada y la salida. Reemplazar (partes de) entra-
da = y salida = en las especificaciones por el o los parmetros
apropiados, que jueguen el mismo papel que las especificaciones a
las que sustituyen en el problema original.
b) Generalizar los tipos. Examinar las entradas, las salidas y los pa-
rmetros para determinar si es posible extenderlos o generalizarlos,
de forma que la solucin construida pueda servir para un conjunto
ms amplio de problemas.
3. Implementar la abstraccin como un procedimiento o funcin, bien
partiendo de cero, bien convirtiendo un programa existente para el
problema original.
Los pasos 1 y 2 reciben el nombre de especificacin de la rutina. Su resultado se
muestra en la forma encapsulada siguiente:
Nombre(parmetros>
(pre: expresin con las precondiciones de la rutina)
(post: expresin con las poscondiciones de la rutina)
El paso 3 unifica las especificaciones con el propio procedimiento o funcin de
Pascal, convirtindola en una unidad de programa reutilizable.
Para ilustrar lo anterior, considrese el problema de la CM que se resolvi
en el Captulo 4. Sus especificaciones se definieron, originalmente, en la Figu-
ra 4.3 de la forma siguiente:
(pre: entrada = (Notas" Notas" "."' Notas
n
> 1\ n > O1\
'Vi E {1, .""' n} :Notas E (O, "."' 4})
(post: entrada =0/\ salida = Sum i E (1, .. , n):NotasJn}
Supongamos ahora que este programa es lo suficientemente importante para
asignarle la categora de rutina. Quiz porque estemos trabajando en un pro-
blema ms complejo que tiene por objetivo calcular qu mes del ao tiene el
mayor promedio de lluvia cada por da. La entrada de este problema podra
ser una serie de listas, una por cada uno de los 12 meses del ao, que conten-
gan la cantidad de lluvia cada cada da. Cuando nos ponemos a resolver el
136 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
problema observamos que parte de nuestro viejo programa CM puede utilizar-
se para encontrar la solucin. Nuestra solucin de promediado acaba de
alcanzar el rango de rutina!
Pero, antes de reutilizar nuestro programa debemos convertirlo en un pro-
cedimiento o funcin equivalente; es decir, debemos aplicar los tres pasos de la
abstraccin procedimental a su definicin. Para el paso 1, la eleccin del nom-
bre Promed; al,; sta es una buena eleccin, pues indica con claridad lo que
har la rutina. Para el paso 2a, parametrizacin de la entrada y la salida,
incluimos el parmetro l, en lugar de la entrada, para simbolizar la lista de
valores de la que deseamos calcular el promedio, y el parmetro resuL tado
en lugar de la salida, indicando as que el promedio resultante se devolver al
contexto del programa en que se utilice, en lugar de visualizarse por la panta-
lla. Para el paso 3, generalizacin del tipo, cambiamos nuestra rutina de pro-
mediado para que trabaje sobre nmeros en un intervalo apropiado, y no slo
en el rango de Oa 4 original.
Por tanto, los pasos 1 y 2 de la abstraccin procedimental del problema
CM conducen a las especificaciones revisadas siguientes:
PromedioLista(L):
{pre: L= (e" e" """' en) 1\ n:i'a 1\ Vi E {1, """' n}:: e, es un nmero}
{post: n > a 1\ resultado = Sum i E {1, .""' n}: eJn
v n ~ a 1\ resul tado = a}
En el paso 3, en la abstraccin procedimental, convertimos el programa CM
original en un procedimiento o funcin de Pascal que satisfaga las especifica-
ciones revisadas. La eleccin entre un procedimiento y una funcin depender
de la forma en que se vaya a utilizar la rutina, asi como de ciertas restricciones
que plantea el lenguaje Pascal en la codificacin de procedimientos y funcio-
nes. Por ejemplo, debe devolver la rutina un nico resultado o debe devolver
varios? Si slo tiene que devolver un resultado se suele preferir una funcin; si
los resultados a devolver son varios, entonces se utilizar un procedimiento. En
otras palabras, invocaremos a la abstraccin resultante como si de una ins-
truccin separada se tratase (lo que sugiere la codificacin de un procedimien-
to) o, por el contrario, la invocaremos como una funcin utilizndola dentro
de una expresin aritmtica ms larga (lo que requiere la codificacin de una
funcin)?
Consideremos la abstraccin Promed; al; s ta que estamos construyen-
do. Si la vamos a invocar como una instruccin, debemos codificarla como un
procedimiento Pascal, con todos los parmetros de salida de la cabecera iden-
tificados con el prefijo varo (Para ms detalles sobre la sintaxis de los procedi-
mientos de Pascal, y sobre los parmetros var, consltese el manual de labora-
torio.) Por el contrario, si se va a invocar como una funcin Promed; ol; sta,
debe implementarse como una funcin de Pascal. En este caso, todos los par-
metros deben incluirse en la cabecera de la definicin, excepto el resultado, que
se identifica con el propio nombre de la funcin. En las Figuras 5.1 y 5.2 se
muestran ambas alternativas.
Resolucin de problemas algortmicos 137
p..ocedu.. e P.. omediolista (l: Lista; va.. resultado: reaL);
uses
Listas;
va ..
i, n: integer;
sum: rea l;
begin
(pre: l= (e" e" o , e
o
) A n;'O A Vi E (1, ... , ni:: e
i
es un nme .. o}
n lengh\;l i sta(L);
if n > O then
begin
Sum O;
i := 1;
while i <= n do
begin
Sum := Sum + l[i];
i := i + 1
end;
.. esul tado := Sum/n;
end {if}
else
.. esul tado := O
(post: n>OA E {1, "0' nI: eJn
v n = O/\ resu l tado = O}
end; (P.. omediolista)
Figura 5.1. Abstraccin de Promedi ol; sta como un procedimiento.
En ambas abstracciones hay que destacar algunas caracteristicas. Si con-
frontamos ambas con el programa original (vase Figura 4.6), a partir del cual
han sido construidas, podemos ver que todas las instrucciones de entrada y
salida han sido sustituidas por referencias a los parmetros l y resultado. Es
decir, la abstraccin procedimental delega la tarea de hacer la entrada y la
salida al programa que utiliza la abstraccin resultante. De hecho, el programa
debe suministrar los argumentos apropiados para que sirvan de entrada al
procedimiento o funcin, y debe interpretar de forma apropiada la informacin
de salida que ste le proporcione.
Podemos observar tambin que el fundamento lgico del programa origi-
nal se ha preservado. En el procedimiento Promediolista (Figura 5.1), el
resultado se asocia con un parmetro varo En el caso de la funcin Prome-
di ol i st a (Figura 5.2), el resultado se asocia con el propio nombre de la
funcin. Otras variables declaradas en el programa original (Sum, i y n)
adquieren la categoria de variables locales dentro de la abstraccin, puesto que
ahora slo tienen un inters local exclusivo para el clculo del promedio.
En la Figura 5.2 se puede observar que el parmetro de salida resultado se
ha reemplazado por la asignacin del promedio resultante al propio nombre
de la funcin. Esta es la forma en que Pascal permite especificar el resultado
que debe devolver una funcin. En otras palabras, el procedimiento Prome-
diolista de la Figura 5.1 y la funcin Promediolista de la Figura 5.2
son idnticos.
138 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
function PromedioLista (L: Lista): real;
uses
Listas;
var
i, n: integer;
sum: rea l;
begin
{pre: L ~ (e" e" .. , en) /\ n '" O /\ Vi E {1, . , n}: /\ n '" 0/\
Vi E {1, ... , ni:: e, es un nmero}
n := LenghtLista(L);
if n > O then
begin
Sum := O;
i := 1;
while i <= n do
begin
Sum:=Sum+L[i];
i := i + 1
end;
PromedioLista := Sum/n;
end {if}
else
PromedioLista := O
{post: n > O /\ resultado = SUII i E {1, .. , ni: eJn
v n = O /\ resultado = O}
end; {PromediLista}
Figura 5.2. Abstraccin de Promedi ol i sta como una funcin.
Comprobacin de la integridad de una abstraccin. Antes de utilizar una rutina
que ha sido abstrada en forma de procedimiento o funcin, debemos asegurar-
nos de que hemos realizado correctamente el proceso de abstraccin. Como
mnimo, esto requiere reestructurar el programa original del que hemos parti-
do para realizar la abstraccin, y comprobar que el programa sigue satisfacien-
do las especificaciones originales con la abstraccin realizada. Para el programa
de la calificacin media, esto puede realizarse como se muestra en la Figura 5.3.
prograll calculacM;
{esto es un programa que ca lcu la la CM de una seri e de una o ms
calificaciones numricas, cada una de ellas en el rango O.. 4,
que se introducirn por el teclado}
uses
Listas;
var
Notas: Listas;
CM: real;
function PromedioLista (L: Lista): real;
{Esta funcin calcula la media de los valores de una lista)
uses
Listas;
var
i, n: integer;
sum: real;
Resolucin de problemas algortmicos 139
begin
{pre: L = (e" e" ... , en) /\ n :;" O/\ Vi E {1, , n}: /\ n :;" O/\
Vi E {1, ... , n}:: e; es un nmero}
n := LenghtLista(L};
i1 n > O then
begin
Sum := O;
i := 1;
ilhile i <= n do
begin
Sum : ~ Sum + L[i];
i := i + 1
end;
PromedioLista := Sum/n;
end {;t}
else
PromedioLista := O
{post: n > O /\ resu l tado = Su. i E {1, ... , n}: e;!n
v n = O /\ resu l tado = O}
end; {PromediLista}
begin
pre: entrada = (Notas" Notas" .. , Notas
n
) /\ n > O /\
Vi E {1, ... , n} :Notas; E {O, ... , 4}}
{Paso 1 . Obtenemos la lista de ca l ;ti cac iones}
WriteLn ('Introducir la lista de calificaciones:');
ReadLista (Notas);
{Nota: Los pasos del 2 al 4 del programa CM original se realizan ahora
invocando a la funcin PromedioLista}
CM : ~ PromedioLista (Notas);
{Paso 5. Se muestra CM}
WriteLn ('La CM de esas cal ificaciones es =', CM : 5 : 2)
end{if}
{post: entrada ~ 0 1 \ salida ~ Sum i E {1, .. "' n}: Notas;!n}
end. {CalculaCM}
Figura 5.3. Revisin del programa CM utilizando la funcin Promedi ol i sta.
La revisin de la Figura 5.3 podr perfectamente haber utilizado el proce-
dimiento en lugar de la funcin. En este caso, la instruccin
CM := PromedioLista (Notas);
debe sustituirse por la invocacin equivalente al procedimiento
PromedioLista (Notas, CM)
Lo importante aqui no es si se utiliza un procedimiento o una funcin, sino la
estructura del programa resultante. En concreto, obsrvese que el programa ha
reducido su responsabilidad a la de obtener la lista de entrada Notas, y a
visualizar el promedio de notas (pasos 1 y 5, respectivamente, del diseo origi-
140 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
nal de la Seccin 4.1). A su vez, el programa ha transferido la responsabilidad
de calcular el promedio a la rutina Promedi oLi s ta recin creada. Para
poder hacer esto, el programa necesita suministrar a la rutina una lista de
nmeros (en este caso la variable Notas). El programa tiene que asignar el
resultado devuelto por Promedi oLi sta a la variable CM, de forma que su
responsabilidad frente a la salida est cubierta. El proceso completo puede
observarse "en la Figura 4.5, donde se ha supuesto que la lista de entrada es
<32 1 3).
5.2.2. Identificacin de rutinas nuevas y definicin
de sus abstracciones
Una destreza importante que se debe adquirir al resolver problemas algoritmi-
cos es la de reconocer rutinas cuando aparecen en contextos de resolucin de
problemas diferentes. Una vez identificada la rutina, puede ser abstrada con
facilidad en forma de procedimiento o funcin -lo mportante es reconocer la
rutina, no su abstraccin!
En el Captulo 4 introdujimos algoritmos para resolver el problema CM,
para calcular a
b
, y para contar el nmero de palabras de una cadena de texto.
Trate de identificar las rutinas que incluyen. Algunas de ellas saltan a la vista.
Por ejemplo, consideremos el clculo de la suma de los elementos de una lista
de enteros arbitraria, que est incluido dentro del programa CaLcuLaCM (y
tambin dentro de Promedi oLi sta). Calcular la suma de los elementos de
una lista es seguramente una rutina, puesto que puede ser til en una gran
variedad de problemas, tales como el de calcular el balance de un libro de
contabilidad o totalizar la recaudacin obtenida en un evento deportivo.
Cmo sera el aspecto de una rutina que realice este proceso? Podramos
Entrada
(32 1 3)
Salida
2.25
Figura 5.4. Utilizacin de la funcin Pramedi al i sta
en el programa CaLcuLaCM.
Resolucin de problemas algortmicos 141
llamarla Suma Lis t a y escribir sus especificaciones para una lista arbitraria L,
como las siguientes:
Suma Lis t a CLl :
{pre: L= Ce" e" ... , e,) /\ n;:,O /\ Vi E {1, ... , n):: e, es un nmero)
{post: result = Sum i E {1, ... , n): ed
Figur 5.5. Especificacin de la abstraccin que suma los elementos
de una lista.
El programa Pot ene i a es otro candidato a convertirse en rutina, y pode-
mos convertirlo de programa a funcin con facilidad. De las especificaciones
de la Seccin 4.4.1, la abstraccin procedimental de Potene i a puede definirse
como en la Figura 5.6:
PotenciaCa, b):
{Pre: a y b son enteros /\ Ca '1' Ov a = 0/\ b '1' O) /\ Minlnt '" a
b
'" Maxlnt)
{Post: resultado = a
b
)
Figura 5.6. Especificacin de la abstraccin de la funcin Potencia.
Considrese tambin la posibilidad de encapsular como una rutina el progra-
ma CuentaPalabras. De las especificaciones del Capitulo 4, la abstraccin
de la Figura 5.7 resulta evidente:
CuentaPalabrasCs):
{pre: s ~ 'c[1] c[2] .. c[n]' /\ n >= O/\ cada c[i] es un carcter ASCII)
{post: resultado = nmero de palabras en s)
Figura 5.7. Especificaciones de la abstraccin CuentaPaLabras.
Existen otros muchos fragmentos de programas que tienen gran utilidad y
que pueden ser convertidos con facilidad en rutinas. Otras cuatro abstraccio-
nes simples pueden ser de utilidad en una gran variedad de problemas algorit-
micos que procesan listas. Los dos primeros (Figura 5.8) encuentran el lugar
que ocupa (ndice) el mayor y el menor elemento de los mprimeros elementos
de una lista L.
MaxListaCL, m):
{pre: L = Ce" e" ... , e,) n;:' O/\ cada e
i
es un nmero)
{pos t: n > O/\ Vi E {1, ... , n): e j ;:, e, /\ resu l tado = j v n = O/\
resul tado = O)
MinListaCL, m):
{pre: L = (e
1
, el' .. _, en) n ~ O 1\ cada e, es un nmero}
{pos t: n > O/\ Vi E {1, .. , n}: ej '" e
i
/\ resu l t ado = j v n ~ O/\
resul tado = O)
Figura 5.8. Especificacin para las abstracciones de MaxLi sta y Mi nLi sta.
142 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
La tercera abstraccin intercambia o permuta dos elementos de una lista L La
cuarta busca en una lista L y determina si un determinado valor x est o no
dentro de la lista, devolviendo su posicin (si es Hue existe). Las especificacio-
nes para ambos se pueden ver en la Figura 5.9:
Intercambiar<L, j, k):
{pre: L = fe" e
2
, _, e
j
, _, e
k
, _, en) 1\ 1 j, k n}
{post: L = (e" e" ""., e., "."' e
j
, , en)}
PosLista(x, Ll:
{pre: L = (e" e" ... , en) 1\ X es un nmero 1\ n O}
{post: 3i E {1, .""' n}: X = e, 1\ resultado = i v Vi E {1, ... , n}:
X"" e, 1\ resul tado = O}
Figura 5.9. Especificacin de las abstracciones Intercambi a r y PostLi sta.
Estas abstracciones precisan algunos comentarios. Consideremos la lista de
la Figura 5.10. Aqu podemos ver que L contiene 12 nmeros, representando
cada uno un valor pluviomtrico mensual expresado en litros por m
2
Por
ejemplo, L[1] representa 2,5 litros por m
2
en el mes de enero. L[2] represen-
ta 4,4 litros por m
2
en el mes de febrero, y as sucesivamente.
As, la rutina Mi nLis t a ( L, 7) busca el valor pluviomtrico mnmo de
los siete primeros meses del ao, y devuelve el ndce 3. La rutina MaxLi s-
ta (L, 12) busca el valor mxmo de los doce de la lista L, devolviendo el
valor 9. PostLista(O.O, L) busca la existencia en L del valor especfico
0.0, y devuelve el valor 10, que indica su posicin en la lista. Finalmente, la
rutina Intercambiar(L, 2, 9) intercambia o permuta los elementos se-
gundo y noveno de la lista L, como se indica mediante los valores subrayados
en la parte baja de la Figura 5.10.
9
12l

( PosLista(O.O,Ll
2, 9l
L = (2.5 6.00.3 5.7 2.1 1.3 1.0 5.9 4.40.0 0.3 2.2)
Figura 5.10. Ilustracin de las rutinas MaxLi sta, Mi nLi sta,
Intercambiar y PosLista.
Resolucin de problemas algortmicos 143
Veamos la implementacin de una de esas rutinas, Ma xLi s t a ( L, m)
como un ejercicio adicional de la abstraccin procedimental. La Figura 5.11
contiene algunas observaciones adicionales sobre una lista arbitraria:
al ir incrementando los valores del indice k entre 1 y m. Para una lista de
longitud 1, su valor mximo slo puede ser el valor e,. Para k = 2, MaxLis-
ta (L, 2) es el ndice del mayor de los valores e, o e
2
, Ysi k = 3, MaxLi s-
ta(L, 3) es el ndice del mayor entre e
3
Y eM.xList.(L, 2) --es decir, el ndice
del mayor de e
3
Y(el mayor de e, Ye
2
). Este razonamiento puede continuarse
hasta llegar finalmente a que Ma xLi s t a (L, m) es el ndice del mayor de e
m
,
e
m
-" , e" Y por tanto de toda la lista e
m
, e
m
_" , e
2
Y e,. (Los
lectores observadores se habrn percatado de que esta expresin es un ejemplo
de relacin de recurrencia, como las que se introdujeron en el Captulo 2.)
MaxLista(L, k)
=1 si k = 1

si k> 1 y
ek > eMaxListaCL, k - 1)
= MaxLi sta(L, k - 1) si k> 1
y
ek ::::;: eJIIIUListaCL, k - 1)
Figura 5.11. Valores de MaxLi sta (L, k) al variar el ndice k.
Las consideraciones anteriores sugieren la estrategia de implementacin
iterativa siguiente, para calcular el ndice j del valor mximo de la sublista de
L que contiene melementos:
j := 1;
fOI" k := 2 to mdo
{invVi E {1, """' k-1}: e[j] >=e[i]
if L[k] > L[j] then
j := k;
Max :=j;
Obsrvese que el invariante refleja nuestro razonamiento informal sobre cmo
debe calcularse el valor de MaxLista(L, i) para cada valor de i en el
intervalo i, ... , m. Cuando finaliza el bucle, el ndice j sealar el elemento
mayor de la sublista L[1, ... , m]. Esto se deduce de la interpretacin del
valor final del invariante
{inv: Vi E {1, ... , m}: e[j] >= e[i]}
puesto que k = m+ 1 al terminar.
Hemos terminado prcticamente la codificacin del cuerpo de la funcin
MaxLi sta, si exceptuamos la instruccin condicional, o guarda, que debe
144 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
aadirse para comprobar que se satisfacen las precondiciones. Esto se muestra
en la Figura 5.12, donde se presenta una abstraccin procedimental completa
de la funcin MaxLi s tao Obsrvese que la implementacin elegida devuelve el
valor O siempre que no se satisface la precondicin. Para esta funcin, este
valor es el equivalente a resultado <<indefinido.
5.2.3. Funciones recursivas: Una alternativa a la repeticin
En el Captulo 2 vimos que las funciones matemticas pueden definirse utili-
zando una relacin de recurrencia, o recursivamente. Esta idea ha sido trasla-
dada al lenguaje Pascal, de forma que ste nos permite definir funciones recur-
sivas. El hecho de que la funcin MaxLi sta fuera originalmente concebida de
forma recursiva no es, por tanto, ninguna traba para su traslacin a una
funcin de Pascal. Es decir, podemos escribir una funcin Pascal que incluya la
relacin de recurrencia original. Este tipo de funciones de Pascal reciben el
nombre de funciones recursivas. En la Figura 5.13 puede verse una implementa-
cin recursiva de la funcin MaxLista. La funcin refleja directamente la
relacin de recurrencia de la Figura 5.11.
Podemos ver que la relacin de recurrencia original se ha codificado en
Pascal utilizando una serie de instrucciones i f anidadas. El efecto de la itera-
cin se consigue en la tercera instruccin i f de la serie, donde los aspectos
recursivos de la funcin han sido subrayados. La funcin Ma xLi s ta se invoca
a s misma de forma recurrente, con los argumentos L y m- 1. As se activan
una serie completa de invocaciones a Ma xLi s t a, para poder determinar:
function MaxLista(L: Lista; m: integer): integer;
var j, k: integer;
begin
{pre: L = (e" ez, .. _, e
lll
, _, en) 1\ n ~ O /\ cada e
i
es un nmero}
if (O < n) and (m <= LengthLista(L then
begin
j : ~ 1;
for k := 2 to mdo
{i nv: \li E {1, ... , k - 1}: e [j] >= e [i] 1\ 2 <= k < ~ m+ 1 }
if L[k] > L[j] then
j := k;
end
else
j := O;
MaxLi sta := j;
{pos t: n > O1\ \1 i E {1, ... , n}: e j ? e, 1\ resu l tado = j v
n = O1\ resul tado = O}
end;
Figura 5.12. Abstraccin procedimental de MaxLi sta (L, m).
Resolucin de problemas algortmicos 145
el ndice del elemento mayor de la sublista de L.
function MaxLista(L: Lista; m: integer): integer;
begin
{pre: L ~ (e" e" ... , e., ""., e
o
) /\ n;, O/\ cada e, es un nmero}
if (O<n) and (m<=LengthLista(L then
if m= 1 then
MaxLi sta := 1
else if L[m] > L[MaxLista(L, m- 1 )] then
MaxLi sta := m
else
MaxLi sta : ~ MaxLi sta (L, m- 1)
else
MaxLi sta : ~ O;
{post: n > O/\ Vi E {1, .""' n}: e
j
;, e, /\ resul tado = j v
n = O /\ resul tado = O)
end;
Figura 5.13. Implementacin recursiva de la funcin MaxLista(L, m).
Para ilustrar la semntica (el signfcado) de las funciones recursivas, su-
pongamos que se nvoca a la funcn con Ma xLi S t a ( L, 4), siendo L = (2 5
4 3 8 6). La secuencia de eventos que se producen en el proceso de clculo
para calcular el resultado (que es el ndce 2), se muestra en la Tabla 5.1.
Tabla 5.1. Clculo de MaxLista(L, 4)
Invocacin
Sublista Invocacin Comparacin
Devuelve
de
de L activa e
m
> MaxLista(L, m- 1)
el re-
MaxLi sta m sultado
1 4 (2 5 4 3)
2 3>MaxLista(L,3) 2
2 3 (2 5 4)
3 4> MaxLista(L, 2) 2
3 2
(2 5)
4 5>MaxLista(L,1) 2
4 1
(2)
ninguno ninguno 1
Cada nvocacin sucesiva a MaxLi sta, comenzando por la primera, reali-
za una comparacin entre e
m
y el valor mxmo de la sublista que contiene un
elemento menos, hasta que se realza una invocacin para la que la longitud de
la lista es 1. (En este caso, esto ocurre en la cuarta invocacin). En ese momen-
to se devuelve el resultado, que confirma que e, es siempre el mximo valor de
la lista de longitud 1. El resultado se pasa a la invocacin 3, por lo que
MaxLi s ta compara los valores de e, Yez. Puesto que e
z
es mayor, la invoca-
cin 3 devuelve el ndce 2 a la llamada 2. La invocacin 2 compara los valores
de e
z
Ye
3
, determinando que e
z
es mayor, por lo que pasa a la nvocacin 1 el
ndce 2. Aqu se realiza finalmente la comparacin e
4
> ez' devolvindose el
valor 2 al programa que nvoc la funcin.
Una forma grfica de ver el proceso de recursn es dibujando una estruc-
146 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
tura arborescente que muestre los caminos de invocacin, argumentos pasados
y resultados devueltos. En la Figura 5.14 se muestra una estructura de este
tipo.
5.2.4. Aprendizaje de rutinas ya existentes: Bibliotecas
y caractersticas de los lenguajes
Muchas de las rutinas que nos sirven de ayuda en el proceso de resolucin de
problemas, o estn incluidas en el lenguaje de programacin, o han sido desa-
rrolladas por otros programadores y son suministradas en forma de bibliotecas
y rutinas utilizables. Por ejemplo, hemos utilizado los tipos elementales; nt e-
ger y rea L de Pascal, junto con sus operaciones aritmticas y booleanas,
como +, -, <, =, y as sucesivamente. Tambin hemos utilizado el tipo
string y algunas de las rutinas de utilidad (Length, Pos, Insert, De-
Lete, y as sucesivamente). Otras caractersticas del lenguaje, como Read o
ReadLn, tienen una utilidad ms general, puesto que pueden aplicarse a un
gran variedad de tipos como el integer, reaL y string.
Tambin hemos aprendido cosas sobre los tipos Li s ta y Gr id, conteni-
dos en bibliotecas, junto con algunas de sus operaciones (ReadLista,
L[i], MakeGrid, y as sucesivamente). Si no se nos hubieran suministrado
esas rutinas, tendramos que haberlas construido de la nada, antes de ponernos
a resolver muchos problemas algortmicos interesantes.
Figura 5.14. Estructura de la invocacin recursiva de MaxLista(L, 4>-
El nmero de la invocacin est dentro de un crculo; las flechas
descendentes simbolizan argumentos y las ascendentes resultados.
Resolucin de problemas algortmicos 147
En el manual de laboratorio puede encontrarse una discusin ms detalla-
da sobre esos tipos y otros de Pascal igualmente tiles, junto con sus rutinas
relacionadas. Las definiciones siguientes de algunas de estas rutinas estn escri-
tas en el ya familiar estilo de definicin procedimental que se introdujo en la
Seccin 5.2.1.
ReadLista(L):
{pre: entrada = (e" e
u
.. , en) cualquier secuencia A n;. D}
{post: ent rada = cua lqui er secuenci a A L = (e" e
u
... , en)}
L[ i] :
{pre: L= (e" e
u
.. , en) A 1 ~ i ~ n }
{post: e, es un nmero A resul tado = e
i
v e, no es un nmero A
resul tado = D}
Writeln(s" Su . , sn):
{pre: entrada = cualquier secuencia A Vi E {1, . , ni: Si es un nmero
o una cadena}
{post: salida = cualquier secuencia s" s" .... , sn}
poses, t):
{pre: t = 't
1
, t
z
, __ , t
n
l
A S = '$" 52' _, Srw
l
/\ n ~ O}
{post: 5= t,t<+, ... t' ...._1 (1 ~ i ~ i + m- 1 ~ n) es la ocurrencia ms a la
izquierda de s en t A resultado = i v s no est en t A resultado = D}
Aqu, la nocin cua lqui er secuenci a asociada a las rutinas Read-
Lis t a y Wr i te l n significan, literalmente, cualquier secuencia de valores de
entrada o salida existentes en el momento en que las rutinas son ejecutadas. En
el caso de ReadLi sta, la notacin entrada = (e" el' . , en) cua l-
quier secuencia, significa que existe una lista al principio de la secuencia
de entrada, seguida de una secuencia arbitraria de otros posibles valores (que
puede no incluir ninguno). La utilizacin de cualquier secuencia en la especifi-
cacin de wr i te l n, significa que coloca la salida a la cola de todas las salidas
que se hayan generado antes de la ejecucin de la instruccin wr i te l n.
5.2.5. Seleccin y reutilizacin de tipos de datos y estructuras
Sabemos ya que es importante para su reutilizacin la identificacin y encap-
sulamiento de rutinas. Tambin debemos ejercitarnos en ser cuidadosos cuan-
do seleccionamos tipos de datos y estructuras para diferentes problemas con
los que estamos familiarizados.
Hemos trabajado ya con los tipos numricos bsicos (rea le i nteger), el
tipo string y con los tipos Lista y Array, que se utilizan para definir
estructuras lineales simples. Sabemos, por la experiencia adquirida, que las
operaciones para el tipo rea l tambin pueden aplicarse, aunque con algunas
restricciones, al i nteger. Sabemos tambin que rutinas con nombre similares
para los tipos Lis ta y s tri ng, tienen significados similares. Por ejemplo, la
rutina Pos (s, t), que devuelve la posicin donde aparece por primera vez la
148 Computacin l. Lgica, resolucin de problemas, algoritmos V programas
cadena t en la s, es totalmente anloga PosL;sta(x, U, que localiza el
elemento x en L. De forma similar, la referencia L[; J, que selecciona el ele-
mento ; -simo de la lista L, se utiliza en la misma forma para seleccionar el
;-simo elemento de un array.
Sin embargo, existen sutiles diferencias entre esas alternativas. Por ejemplo,
no podemos aplicar operadores aritmticos a valores tipo s t r; ng, aunque
stos teng;m connotaciones numricas; instrucciones tales como:
5:=5+'1.5'
(donde s simboliza una variable cadena) son incorrectas. Del mismo modo,
podemos leer y almacenar en una lista una coleccin completa de nmeros
reales, tanto de un archivo externo como desde el teclado, utilizando la opera-
cin ReadL; sta. Sin embargo, no podemos hacer lo mismo si queremos leer
y almacenar una coleccin de cadenas. Podemos utilizar un a r rayen lugar de
una lista para almacenar una coleccin de cadenas, pero carecemos de la
flexibilidad para leerlas y almacenarlas si no inventamos y construimos las
rutinas que tengan la capacidad funcional de ReadL; sta. Estas diferencias
estn resumidas en la Figura 5.15, que muestra, en una especie de diagrama de
Venn, el solapamiento funcional que existe entre a r rays y Listas. El men-
saje bsico de estos prrafos es que ninguna estructura de datos ofrece todas
las ventajas de otra sin acarrear algunas desventajas. Esta situacin es tpica en
la informtica; los profesionales de la informtica se refieren a ella como el
compromiso y las consecuencias de tomar una decisin.
Figura 5.15. Diferencias entre l; stas, arrays, cadenas y nmeros.
Resolucin de problemas algoritmicos 149
El tipo cadena es el ms bsico de los tipos construidos con valores elemen-
tales, puesto que puede contener cualquier nmero de caracteres separados por
blancos u otros caracteres ASCII no imprimibles (caracteres de control, tales
como saltos de lnea y tabuladores). As, cualquier carcter es una cadena, pero
no cualquier cadena es un carcter; por ejemplo, el carcter a es una cadena,
pero la cadena Pepe no es un carcter. Continuando con esta lnea de razona-
miento, c'lda dgito numrico es un carcter, pero un carcter individual no
tiene por qu ser un dgito numrico. Por ejemplo, el dgito 3 es un carcter,
pero el carcter x no es dgito numrico. Igualmente, si colocamos un nmero
entre comillas simples tendremos una cadena, pero no toda cadena es un
nmero. As, I 3 . 5 I es una cadena, pero I 1v n I no es un nmero.
5.2.6. Arrays de cadenas de caracteres
Nos gustara extender la potencia y utilidad del tipo st r; ng incorporndolo
dentro de la idea de l; sta. Esto nos permitira aplicar todas las rutinas de
l; s ta s, que nos son tan familiares, a listas de cadena s de caracteres en la
misma forma en que lo hicimos en el Captulo 4 con las listas de rea les.
Puesto que el tipo string es ms general que el de integer o real, es
esperable que el tipo lista de s tri ng sea de utilidad en una gama de proble-
mas algortmicos ms amplia que el de las listas de rea les.
Desgraciadamente, no podemos extender la idea de lis ta de esta forma.
Tenemos que implementar las listas de cadenas utilizando arrays. El tipo
de elementos de un array puede ser establecido arbitrariamente por el pro-
gramador. Supongamos que escribimos una frase como una lista de palabras,
separadas entre s por saltos de lnea. La frase:
Ivn camin 3 ki Lmetros hasta eL coLegio a una veLocidad de
2,5 ki Lmetros por hora
Podra introducirse por el teclado en la forma siguiente:
Ivn RET
cami n RET
3 RET
ki Lmetros RET
hasta RET
eL RET
coLegio RET
a RET
una RET
veLocidad RET
de RET
2,5 RET
ki Lmetros RET
por RET
hora RET
RET
150 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Es posible declarar el tipo de array siguiente, y una variable del mismo que
permite almacenar cada palabra del texto:
type palabra = string[16];
ListaStrings = a ....ay[1 .. 100] of palab.. a;
va.. Frase: ListaSt .. ings;
LongitudFrase: integer;
A p a l a ~ r a : palab.. a;
La definicin anterior permite manipular frases de 100 palabras o menos,
conteniendo cada palabra 16 caracteres o menos (lo que es una suposicin
bastante razonable para el lenguaje cotidiano). La terminacin de la frase se
sealiza con dos saltos de lnea sucesivos (RET RET).
Si queremos leer una serie de cadenas en la variable f rase e identificar el
nmero de palabras con la variable Long; tudPa labra, debemos disear el
cdigo que realice esta operacin. Es decir, el cdigo siguiente podra ser la
base de una abstraccin procedimental:
LongitudFrase := o;
ReadLn(APalabra)
whi le APa lab..a <> ' , do
begin
LongitudFrase := LongitudFrase + 1;
Frase[LongitudFrase] := APalabra;
ReadLn(APalabra)
end
De forma anloga, es posible implementar inserciones, eliminaciones y bsque-
das de palabras aisladas utilzando abstracciones procedurales. De esta forma,
podemos manipular listas de palabras de la misma forma que manipulamos
l; s tas de rea l es, posibilidad que es de gran utilidad en gran cantidad de
aplcaciones.
5.2.7. Tipificacin fuerte y coercin
Es complcado cambiar de tipos dentro del lenguaje Pascal, porque el lenguaje
obliga a los programadores a hacer distinciones explcitas entre los valores del
tipo string, char, real e integer, dependiendo de la rutina concreta
(procedimiento o funcin) utilizada y del contexto sintctico en el que se utili-
za. Esta caracterstica de los lenguajes de programacin recibe el nombre de
tipificacin fuerte.
Definicin. Un lenguaje de programaclOn es fuertemente-tipificado si el
tipo de cada variable y constante que interviene en cada instruccin indivi-
dual est restringida explcitamente al tipo de clculo en el que se utiliza.
Los ejemplos de tipificacin fuerte pueden encontrarse en los programas del
Captulo 4:
Resolucin de problemas algortmicos 151
1. La instruccin i : = i + 1, del programa Pot enc i a de la Figura 4.14,
necesita que i sea una variable numrica --es decir, rea lo i nteger.
Si i hubiera sido declarada como un string, la idea de utilizar su
valor en una operacin aritmtica, como una suma, sera incorrecta,
incluso si su valor pudiera ser interpretable como un nmero (por
ejemplo, la cadena '2.2 ').
2. La expresin Copy(s, i, 1) <> ", del programa ContarPaLa-
bra s de la Figura 4.17, precisa que s sea una cadena y que i sea un
entero. La propia Copy debe devolver un valor de tipo s t ri ng, pues-
to que el resultado debe ser comparado (utilizando el operador < con
la cadena ' '.
3. La instruccin Tu r n Ce LL( t a b Le ro, i, j), del programa de
las Tres-en-Raya de la Figura 4.21, necesita que sus argumentos
sean de los tipos grid, integer e integer, respectivamente.
Supongamos que queremos reinterpretar un valor de un tipo como valor
de otro diferente -por ejemplo, interpretar la cadena '2.5 I como el nmero
real 2,5--. Para hacer esto en un lenguaje fuertemente tipificado como Pascal,
necesitamos utilizar una rutina especifica que convierta el valor de tipo string
en uno de tipo real. Este es el papel de la rutina de Pascal Val (vase Seccin
5.2.6). La utilizacin de una rutina de este tipo recibe el nombre de coercin. La
coercin en la direccin opuesta le permite la funcin s t r. Las rutinas siguien-
tes estn definidas en Turbo Pascal para permitir la coercin entre reales y
cadenas:
valCs, r, cdigo)
{pre: s es una cadena)
{post: r = valor real equivalente a s 1\ cdigo = Osi la coercin
se rea liza con x ito
strCr, s);
{pre: r es un nmero real J
{post: s es la cadena equivalente a r)
Pascal realiza la coercin directa entre reales y enteros. Los enteros no
necesitan ser convertidos explcitamente a los reales equivalentes, puesto que se
pueden considerar un subconjunto de ellos. Por ejemplo, el entero 1 se inter-
preta siempre que sea necesario como el real 1 O. Las rutinas siguientes con-
vierten un nmero real en entero, bien redondendolo al entero ms prximo,
bien truncndolo, respectivamente.
roundCx);
{pre: x es un nmero rea l )
{post: resultado=lx+O.5J}
trunc(x) :
{pre: x es un nmero rea l)
(post: resultado = lxJ}
152 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Por tanto, si queremos tratar el i-simo elemento de una lista L como un entero,
debemos convertirlo explcitamente utilizando una de las rutinas round o
trunco Por ejemplo, la instruccin siguiente asigna la parte entera (ignorando
la parte decimal) del i -simo elemento de L a la variable int ege r j.
j : ~ truncCL[i]);
,
Por qu son tan necesarias y tiles la tipificacin fuerte y la coercin?
Existen varias razones. Primero, los lenguajes fuertemente tipificados suelen ser
ms efectivos que los dbilmente tipificados como vehculos de enseanza de
los principios de la programacin, por el simple hecho de que sus compiladores
detectan un rango de errores ms amplio, y sugieren la forma de corregirlos
antes de que se produzca la ejecucin del programa. En algunas ocasiones, las
listas incluyen elementos de distintos tipos, por lo que el programa debe identi-
ficar tanto los tipos como los valores de cada elemento. La lista siguiente
incluye algunos datos en los que cadenas y reales se alternan en una serie no
ordenada cronolgicamente de valores pluviomtricos de los meses del ao.
Las listas como esta, en que cada valor numrico est precedido inmediata-
mente por un nombre descriptivo, reciben el nombre de listas con atributos.
L = (Enero 2,5
Septi embre 6,0
Febrero 4,4
Mayo 2,1
Junio 1,3
Novi embre 0,3
Diciembre 2,2
Julio 5,9
Marzo 0,3
Abril 5,7
Agosto 1,0
Octubre 0,0)
Ejercicios
5.1. Describir qu es lo que hacen los programas siguientes:
a) function nooz (L: lista) : integer;
val'
i: i nteger;
begin
nooz := O;
for i := 1 to LengthLista(L) do
if L[i] =0,0 then
nooz := nooz + 1;
end;
Resolucin de problemas algortmicos 153
b) program fn;
var
k: integer;
function nd (m: integer>: integer;
var
n: integer;
begin
nd := O;
n := m;
while n >= 1 do
begin
n := n div 10;
nd := nd + 1
end
end;
begin
whi le not eof do
begin
readln (k>;
writeln ('ans = " nd(k
end
end.
5.2. Implementar la rutina SumL; s ta, definida en la Figura 5.5, como una
funcin de Pascal. Probar que la funcin puede reutilizarse para conse-
guir una implementacin alternativa del procedimiento Promed i 0-
Lis t a, diferente a la de la Figura 5.1.
5.3. Construir una funcin, a la que llamaremos MaxFactor, que calcule
el mximo factor de un entero n, que sea menor que el propio n (por
ejemplo, MaxFactor(100) = 50, MaxFactor(15) = 5, Y Max-
Factor(13) = 1).
5.4. Supongamos que A, B YC representan la longitud de los lados de un
tringulo. Construir una funcin que devuelva t rue si A, B YC son los
lados de un tringulo rectngulo.
5.5. En qu condiciones puede convertirse un procedimiento en una fun-
cin equivalente? En qu condiciones puede realizarse la operacin
inversa? Razonar la respuesta.
5.6. Convertir el programa factorial del Ejercicio 4.22 en una funcin.
5.7. Implementar como un procedimiento de Pascal la abstraccin Con-
tarPalabraCs) de la Figura 5.7. Comprobar su integridad reutili-
zndola para resolver el programa original que contaba palabras del
Captulo 4 (vase Figura 4.17).
154 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
5.8. Ilustrar el comportamiento de la implementacin recursiva de Max-
Lista(L, m) (Figura 5.8), mostrando la secuencia de invocaciones y
resultados devueltos, cuando L = (6 5 4 3 2 1) Y m = 6. Existe
alguna reduccin en el nmero de invocaciones que son precisas cuando
el mximo valor ocupar el primer lugar de la lista? Razonarlo.
5.9. Reesdribir la funcin siguiente, pero reemplazando el bucle far por
uno whi Le equivalente; es decir, quc conduzca al mismo resultado.
Escribir pre y poscondiciones que describan el resultado. En qu medi-
da es esta funcin similar a la operacin Mi nLi sta (Figura 5.8)?
type ArrayLista = array[1 .. 255] of real;
function IndiceDelMenor<UnArray: ArrayLista; n: integer):
integer;
(devuelve el indice del menor de los elementos de un array de
longi tud n}
var IndiceDelMenorPorAhora: integer;
begin
Indi ceDelMenorPorAhora := 1;
for i ;= 2 to n do
i f UnArray[i] < UnArray[Indi ceDelMenorPorAhora] then
Indi ceDe lMenorPorAhora : ~ i;
Indi ceDe lMenor := Indi ceDe lMenorPorAhora;
end;
5.10. Escribir una funcin recursiva SumLi sta (L, n) que devuelva la suma
de los n primeros elementos de la lista L.
5.11. a) Escribir la funcin recursiva Fib(n) que calcule para el entero n el
n-simo nmero de Fibonacci, que se define de la forma siguiente:
Fib(n) o
1
Fib(n - 1) + Fib(n
para
para
2) para
n O
n 1
n > 1
b) Dibujar la representacin grfica de la cadena de invocaciones
cuando se invoca con Fi b (4).
e) Reescribir la funcin, pero sin utilizar recurrencias; es decir, utili-
zando un bucle en lugar de llamadas recursivas.
5.12. a) Describir en castellano qu hace la funcin siguiente.
function MyFun (n: integer): integer;
begin
i f n ~ O then
MyFun := O
else if n mod 2 = O then
Resolucin de problemas algortmicos 155
MyFun := n + MyFun<n - 1)
else
MyFun : ~ MyFun<n - 1)
end;
b) Escribir las pre y poscondiciones de la funcin My Fun.
5.13. Utillzando una linea de razonamiento similar a la utilizada para imple-
mentar MaxLi sta (L, m), desarrollar una implementacin de la fun-
cin Mi nLis t a definida en la Seccin 5.2.2. Si la implementacin con-
tiene un bucle, incluir la descripcin del invariante del bucle.
5.14. Realizar la abstraccin procedimental de la rutina PosLista(x, U,
definida en la Seccin 5.2.2, y escribir en Pascal una funcin no recursi-
va de la abstraccin.
5.15. La rutina PosLi sta (x, U es muy til cuando queremos determinar
si una lista tiene elementos repetidos. Escribir un programa en Pascal
que, para una lista arbitraria de nmcros L, utilice PosLi s ta para
ayudarnos a descubrir y escribir los nmeros que aparezcan ms de una
vez. Por ejemplo, la lista L = (1 2 3 5 4 1 5 1 ) har que el programa
escriba las duplicidades siguientes:
1
5
Describir un problema algortmico de la vida cotidiana en que sea de
utilidad una rutina que localice duplicidades.
5.16. Escribir una implementacin recursiva de la funcin PosLi sta.
5.17. Escribir la funcin Primos Re La t i vos que tenga dos enteros n y m
como argumentos, y devuelva el valor booleano t rue, si y slo si my n
no tienen ningn divisor comn ms que 1. Por ejemplo,
PrimosRelativos<B, 9) = true
PrimosRelativos<B, 10) ~ false
puesto que 8 y 10 tiene un divisor comn que es 2.
5.18. Escribir una funcin que devuelva el valor t r ue si el primer elemento
de una Lis ta es mayor que el resto de elementos. La funcin se llama-
r EsMayor y tendr un solo parmetro, que designar a la lista. Escri-
bir un programa de prueba que invoque a la funcin para establecer si
trabaja correctamente.
156 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
5.19. Disear y escribir en Pascal una funcin que examine los n elementos
de una lista y devuelva t rue si los elementos estn ordenados en orden
decreciente, y fa l se en caso contrario. La funcin se llamar Prueba
y tiene que tener un parmetro para el nombre de la lis ta, y otros
para el nmero de elementos n que deben examinarse. Escribir un pro-
grama de prueba que invoque a la funcin para establecer si trabaja
correctamente.
5.3. RESOLUCIN DE UN PROBLEMA UTILIZANDO
LA METODOLOGA MAPS
Ya estamos en condiciones de utilizar nuestro mtodo de resolucin de proble-
mas (MAPS) y utilizarlo en un caso concreto, desde el principio hasta el final.
Durante todo el proceso enfatizaremos la importacia de identificar y reutilizar
rutinas en una forma creativa. Una de las caractersticas destacables de MAPS
es que no slo sirve como gua en la resolucin de problemas particulares, sino
que en este proceso se van creando rutinas que el programador podr reutili-
zar en la resolucin de otros problemas ms complejos.
5.3.1. El dilogo
El problema que vamos a resolver es el de construr un algoritmo que tenga
como entrada una lista de valores pluviomtricos, y escriba los meses cuyos
valores pluviomtricos estn por debajo de la media, el valor pluviomtrico
ms alto y ms bajo de cada mes, y el mes que dio el valor pluviomtrico ms
alto.
Nuestra primera reaccin ante la explicacin anterior es que es muy vaga.
Es decir, se han omitido muchos detalles. Necesitamos mucha ms informacin
antes de pasar a la etapa siguiente en la resolucin del problema. Esto es muy
tpico en la resolucin de problemas; no es buen proceder el admitir especifica-
ciones ambiguas y realizar preguntas que dejen sin clarificar algunos detalles.
Los resolutores de problemas inteligentes preguntan primero sobre las cuestio-
nes que necesiten ser clarificadas, antes de proceder a la bsqueda de una
solucin. Asi, debemos tener un dilogo con la persona que nos presenta el
problema, hasta que consigamos tener un conocimiento preciso del mismo.
Para el problema que nos ocupa, algunas cosas que deberamos preguntar
podran ser las siguientes:
1. Cmo se nos presentar la entrada? Cronolgicamente por meses?
Por valores pluviomtricos? Consistir la entrada en una o dos lis-
tas? Estarn los meses explcitamente representados en la entrada, o se
presentar las lecturas nicamente organizadas en orden cronolgico?
2. Cul es un valor vlido de pluviometra? Es decir, un valor pluviom-
trico puede ser cualquier nmero real no negativo?, existe un valor
mximo para las lecturas?
Resolucin de problemas algortmicos 157
3. En la salida, deben aparecer los meses con pluviometria inferior al
promedio, en orden cronolgico, en orden de indices pluviomtricos
relativos o, simplemente, en el mismo orden en que aparecieron las
lecturas en la entrada? Es necesario escribir el valor medio del indice
pluviomtrico?
4. Puede ocurrir que ms de un mes tengan el valor pluviomtrico ms
alto? En ese caso, debe mostrar el algoritmo el nombre de todos esos
rbeses?
Tratando de clarificar lo anterior, suele ser conveniente dar una muestra de la
entrada y de la salida correspondiente del problema; una imagen vale ms que
mil palabras! Los ejemplos sirven para resolver de forma visual muchas de las
preguntas anteriores, e incluso nos proporcionan pistas sobre cmo debemos
resolver el problema. En la Figura 5.16, la entrada se presenta en una lista
sencilla, y el programa debe distinguir entre nombre de meses (entradas de la
lista con ndices impares 1, 3, 5, ...) Yvalores pluviomtricos (entradas de la lista
con ndices pares 2, 4, 6, ...).
ENTRADA
(Enero 2,5
Febrero 4,4
Marzo 0,3
Abril 5,7
Mayo 2,1
Junio 1,3
Julio 5,9
Agosto 1,0
Septiembre 6,0
Octubre 0,0
Novi embre 0,3
Di c i embre 2,2)
SALIDA
ESTADISTICAS PLUVIOMETRICAS
medi a = 2,64
mxima = 6,0
minima = 0,0
Meses por debajo de la media:
Enero
Marzo
Mayo
Junio
Agosto
Octubre
Noviembre
Diciembre
Mes(es) mxima:
Septiembre
Figura 5.16. Ejemplo de entrada y salida para el problema
de la pluviometra.
Sin embargo, la entrada y salida para este problema pueden presentarse
perfectamente de otras maneras. Dos alternativas razonables se muestran en la
Figura 5.17. En una de las alternativas, la entrada se suministra en dos listas en
lugar de en una; en la otra, la entrada se presenta sin los nombres de los meses.
En este caso, el programa debe generar los nombres de los doce meses y
suponer que los valores de pluviometra estn suministrados en orden cronol-
gico --es decir, la primera entrada es el valor de enero, la segunda el de
febrero, y as sucesivamente.
158 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
CEnero, Febrero
Marzo, Abri L
Mayo, Junio
JuL i o, Agosto
Septiembre, Octubre
Noviembre, Diciembre)
2.5 ~ . 4
0.3 5.7
2.1 1.3
5.9 1.0
6.0 0.0
0.3 2.2)
a)
C2.5 4.4
0.3 5.7
2.1 1.3
5.9 1.0
6.0 0.0
0.3 2.2)
b)
Figura 5.17. Dos representaciones alternativas de la entrada para el problema
de la pluviometra. al Dos listas de entrada. b) La lista de los valores pluviom-
tricos como nica entrada.
5.3.2. Las especificaciones
Supongamos que la Figura 5.17b muestra la organizacin de la entrada que
espera el programa, y la Figura 5.16 la de la salida. Podemos entonces cons-
truir de una forma ms precisa las especificaciones del programa, es decir, las
precondiciones y postcondiciones. Estas especificaciones servirn para clarifi-
car los detalles de la solucin al problema, que desarrollaremos en pasos si-
guientes. La precondicin para el problema de la pluviometra puede expresar-
se de la forma siguente:
{pre: entrada = Ce" e" .. , e
,2
) /\ Vi E {1, ... ,12) e
i
es eL vaLor
pLuviomtrico deL i-simo mes deL ao)
As, si se suministrase al programa la entrada particular de la Figura 5.l7b, se
satisfara esta precondicin; el programa asignara a e
z
el valor 4.4 Its/m
2
(el
valor pluviomtrco de febrero), y as sucesivamente. Sin embargo, el lector se
percatar de que, si la entrada se suministrase en una de las otras formas
alternativas, no se satisfaria la precondicin.
La poscondicin para este problema puede definirse de la forma siguiente:
{post: entrada =0/\ saLida = ESTADIsnCAS PLUVIOMETRICAS
media = Sum i E {1, ,12): e
i
/12
m xi ma ~ Max i E {1, , 12): e i
minima = Min i E {1, ,12): e
i
Meses por debajo de La media:
{m;: e; < Su.i E {1, ... ,12): e,l12)
MesCes) ma><ima:
[mi: e
j
= Max iE (1, ... ,12): e
i
/\ 1o;;jo;;12))
Resolucin de problemas algoritmicos 159
En este caso, la especificacin de entrada describe la forma general y la esencia
de la misma, y la especificacin de salida la relacin que deben guardar entra-
da y salida. Por ejemplo, podemos ver que son necesarias dos listas -una lista
(mi' ml' ..., miz) con los doce meses del ao y una lista con los doce valores
pluviomtricos. A la vista de esto, debe existir algn tipo de paralelismo entre
ambas listas. (Obsrvese que, aunque la lista de meses no se suministra como
entrada, d e b ~ ser generada de alguna forma por el programa en forma de un
array de doce posiciones). Es decir, el hecho de que m
2
= Febrero y que e
2
=
4,4 significa que el valor pluviomtrico de febrero es 4,4 lts/m
2
.
Por tanto, la solucin al problema puede describirse en trminos de aque-
llos meses cuyo valor pluviomtrico guarda alguna relacin con el mximo,
mnimo y valor pluviomtrico medio. En este caso, la notacin de la lgica es
especialmente til, pues permite expresar las especificaciones de forma breve y
precisa. Una descripcin en castellano de las mismas entradas y salidas podria
no estar escrita con la misma precisin y brevedad.
5.3.3. La particin
Muchos objetivos o pasos de este problema son evidentes, si nos ponemos
a pensar sobre el problema y sus especificaciones. Inicialmente, nuestra so-
lucin debe generar la lista con los nombres de los meses y obtener de la
entrada la lista de valores pluviomtricos. Tambin nuestra solucin necesita
calcular el valor medio, el mximo y mnimo de los valores pluviomtricos.
Necesitar escribir Jos nombres de aquellos meses cuyo valor pluviomtrico
est por debajo de la media, as como el(los) mes(es) que tengan el mximo
de valor pluviomtrico.
La solucin a este problema puede ser dividida, inicialmente, en las cuatro
rutinas y cinco elementos de datos que se muestran en la Figura 5.18. Hemos
hecho dos cosas importantes en esta etapa inicial del proceso de particin;
hemos identificado las principales rutinas que sern necesarias, y hemos asig-
nado nombre a las listas principales (meses y pLuv;ometr;as) y a las
variables principales PLuv;ometr;aProm, MaxPLuv;ometr;a y M;n-
PLuv;ometria) que precisa la solucin.
Recapacitemos ahora acerca de dos nuevos elementos del proceso de reso-
lucin de problemas -la relacin secuencial entre rutinas y la posibilidad de
utilizar rutinas ya conocidas como ayuda para la construccin de la solucin al
problema que nos ocupa-o Podemos determinar informalmente el secuencia-
miento de los eventos descritos en la Figura 5.18 (simplemente pensando en
qu debe ocurrir primero, qu segundo, etc.), o formalmente (escribiendo pre
y poscondiciones para cada rutina que hayamos identificado, u ordenarlas
lgicamente segn el contexto que imponen las especificaciones del proble-
ma principal). Un anlisis informal conduce al orden inicial descrito en la
Figura 5.19, junto con las especificaciones del programa original, ocupando su
lugar.
160 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Rutinas
Inicializar
lista de meses
y pluviometras
Mostrar pluviometra
promedio. mxima
y mnima
Elementos de datos
Mostrar meses
por debajo
del promedio
Mostrar mes(es)
con pluviometra
ms alta
Meses
Pluviometrias
PluviometriaPorm
MaxPluviometria
MinPluviometria
Un array de doce nombre de meses.
Una lista de doce lecturas de valores pluviomtricos.
El valor medio de las lecturas.
El valor mximo de pluviometra de los doce meses.
El valor mnimo de pluviometra de los doce meses.
Figura 5.18. Particin en rutinas y elementos de datos para el problema
de la pluviometra.
{pre: entrada = (e" e" " .. , e,.) /\ Vi E {1, """' 12) e, es el valor
pluviomtrico del i-simo mes del ao}
Paso 1. Inicializar lista de meses y pluviometras
Paso 2. Mostrar pluviometra promedio, mxima y mnima
Paso 3. Mostrar meses por debajo del promedio
Paso 4. Mostrar el(los) mes(es) con pluviometra ms alta
{post: entrada =0/\ salida = ESTAOfSnCAS PLUVIOMIOTRICAS
media = Sum i E {1, , 12): e;l12
mxima = Max i E {1, , 12): e,
minima = Min i E {1, , 12): e,
Meses por debajo de la media:
{m
j
: ej < SUII i E {1, ... , 12): e ;l12}
Mes(es) mxima:
(m;: e; ~ Sum i E (1, """' 12): e;l12}
Figura 5.19. Orden inicial y especificaciones para el problema
de los valores pluviomtricos.
Resolucin de problemas algortmicos 161
Podemos observar que las cuatro rutinas deben colocarse en este orden
para que la poscondicin quede satisfecha. En concreto, la lectura de los valo-
res pluviomtricos debe preceder a todos los dems pasos. Por si mismo, el
primer paso provoca la satisfaccin de la especificacin entrada = 0 de la
poscondicin. Del mismo modo, a continuacin debe calcularse y escribirse el
valor promedio por dos razones: Primero, el promedio es necesario como
entrada (calilla precondicin) del paso 3, donde necesitamos calcular y visuali-
zar los meses cuya pluviomtria est por debajo del promedio, y del paso 4,
donde encontramos y visualizamos el(los) mes(es) con mximo valor pluviom-
trico. Segundo, la poscondicin del problema exige que los valores promedio,
mximo y mnimo de pluviometra deben mostrarse antes de que se produzcan
las salidas de los pasos 3 y 4. Finalmente, el paso 3 debe preceder al 4, puesto
que sus salidas respectivas deben realizarse en este orden segn las poscondi-
ciones del problema.
Ejercicios
5.20. Supngase que se utiliza la metodologa MAPS para disear un progra-
ma que lea un nmero expresado en cifras romanas, y que muestre su
valor en nmeros arbigos. En las etapas de dilogo y especificacin, se
ha establecido que la entrada ser una cadena de letras maysculas del
conjunto (1, V, X, L, C, D, M). Recuerde que los valores de esos digitos
romanos son 1, S, 10, SO, 100, SOO, 1000, respectivamente. Se ha decidido
tambin que los digitos en la entrada estarn en orden no creciente de
valores; es decir, el nmero arbigo 4 se escribir como el numeral UU
(en lugar de IV). Con estas hiptesis, escribir detalladamente las especifi-
caciones y realizar la fase de particin de la metodologa MAPS.
5.21. Escribir la salida que aparecera si mezclamos los dos bucles for de los
pasos 3 y 4, del problema de la pluviometra, en un solo bucle for que
contenga las dos selecciones ; f, ante la entrada ejemplo de la Figu-
ra S.17. Es decir, suponer que se mezclan los pasos 3 y 4 de la forma
siguiente:
WriteLn('Meses por debajo de La media');
WriteLn( 'Mes(es) mxima:');
for i := 1 to LenghtLista(Pluviometras) then
begin
if Pluviometrias[i] < PLuvometriaProm then
WriteLn(' " Meses[i]);
if Pluvometras[i] = PluviometraProm then
WriteLn(' " Meses[i]);
end;
5.22. Escribir un invariante para el bucle del paso 3 del problema de la
pluviometra.
162 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
5.4. DEFINICiN DE ABSTRACCIONES: UNIFICACiN
DE RUTINAS VIEJAS CON IDEAS NUEVAS
Hemos definido y desarrollado la solucin al problema de la pluviometra,
hasta un punto en que es posible evaluar el esfuerzo necesario para solucionar
cada una de sus partes. Es decir, debemos decidir qu pasos deben ser subdivi-
didos en subpasQs. En nuestro ejemplo, los pasos 1 y 2 pueden ser subdivididos
nuevamente para clarificar sus objetivos individuales.
Estas nuevas subdivisiones pueden verse en la Figura 5.20. En la figura
podemos ver que se ha subdividido el paso 1 en dos subpasos 1.1 y 1.2, que
asignan la lista de nombre de meses y leen la lista de pluviometras, respectiva-
mente. El paso 3 tiene tres componentes: el paso 2.1 calcula y escribe el valor
pluviomtrico medio; el paso 2.2 calcula y escribe el valor pluviomtrico mxi-
mo; y el paso 2.3 calcula y escribe el valor pluviomtrico mnimo. Obsrvese
que los subpasos diseados se han secuenciado apropiadamente, con objeto de
satisfacer el orden de las dos listas, y el que especifica la poscondicin para las
salidas. Este cuidado, que puede parecer excesivo para un problema tan simple,
se hace ms importante cuanto ms complejo es el problema a resolver.
Paso 1. Inicializar lista de meses y pluviometra
I Paso 1.1. Asignar lista de meses I
L
Paso 1.2. Leer lista de valores pluviomtricos
Paso 2. Mostrar pluviometra promedio, mxima y minima
Paso 2.1. Calcular y mostrar pluviometria media
Paso 2.2. Calcular y mostrar pluviometra mxima
Paso 2.3. Calcular y mostrar pluviometra mnima
Figura 5.20. Particin adicional de los pasos 1 y 2 del problema
de la pluviometra.
Hemos de continuar subdividiendo y secuenciando los pasos individuales
hasta que cada subpaso sea reconocible con claridad como una rutina, sea
resoluble mediante la combinacin de otras existentes (conocidas), o pueda ser
resuelto directamente creando una rutina nueva. Podemos ver que es necesario
desarrollar una rutina nueva para el paso 1.1. Podemos utilizar la rutina
Resolucin de problemas algortmicos 163
ReadLista para el paso 1.2. Podemos combinar dos rutinas, Promed;o-
Lista y WriteLn para resolver el paso 2.1 (el clculo del promedio y la
visualizacin del resultado son dos acciones separadas, y por tanto deben
realizarlas rutinas diferentes). De forma similar, podemos combinar las rutinas
MaxL; sta y Wri teLn para el paso 2.2, y las rutinas Mi nL i sta y Wr; teLn
para el paso 2.3.
Ni el paso 3 ni el 4 parecen resolubles mediante la aplicacin directa ni la
combinacin de rutinas. No hemos visto hasta ahora ninguna rutina que re-
suelva directamente problemas como ste, y tenemos que crear una solucin
nueva para cada uno de los casos. Sin embargo, en la mayora de las situaciones
de resolucin de problemas algoritmicos, los diseadores de software emplean
ms tiempo combinando o reutilizando rutinas que crendolas nuevas desde el
principio. Es decir, el proceso de resolucin de problemas algortmicos tiende a
cumplir la regla 90 por 100 de transpiracin y 10 por 100 de inspiracin.
Apliquemos la <<transpiracin (Seccin 5.4.1) y la inspiracin (Seccin 5.4.2).
5.4.1. Reutilizacin de rutinas
Como hemos dividido suficientemente el problema original, de forma que po-
demos tratar cada parte de forma independiente, debemos explorar la presen-
cia de rutinas conocidas o viejas entre los pasos individuales. Por cierto,
algunas rutinas que son conocidas para unos resolutores de problemas, son
desconocidas para otros. Por ello, no debe descorazonarse si desconoce algu-
nas rutinas con las que otros parecen estar muy familiarizados. Estamos apren-
diendo un lenguaje nuevo, y nuestro vocabulario crecer con la experiencia.
Existen cuatro mecanismos que podemos utilizar para adaptar o reutilizar
rutinas ya existentes para propsitos nuevos: empalmndolas, anidndolas,
adaptndolas y mezclndolas *.
Empalmado. Es el mtodo ms sencillo de crear rutinas nuevas. Si Rl YR2
son dos rutinas ya existentes, el empalmado de ambas crea una rutina nueva R,
que se compone de R1 seguida secuencialmente de R2. Por ejemplo, en el
problema de la pluviometra. Las cuatro rutinas (pasos del 1 al 4) son empal-
madas para formar una rutina nueva como es la solucin al problema. De la
misma forma, las rutinas PromedioLista y WriteLn se empalman para
construir la solucin al paso 2.1, como se ilustra en la Figura 5.21.
Anidamiento. Tambin se puede construir una rutina nueva anidando una
rutina R1 ya existente de otra R2. El anidamiento se produce cuando utiliza-
mos una rutina como argumento de la invocacin a un procedimiento, o
cuando la colocamos dentro de una instruccin condicional o dentro de un
bucle. Esto sc ilustra en la figura 5.22, donde el clculo del promedio de
pluviometra, ha sido anidado dentro del propio proceso de visualizacin del
* E. SOLOWAv: {<Lcarning to program: Learning to construct rncchanisms and cxplana-
tions". Curnrnunicatians al the ACM (septiembre 1986), 29(9): 850.
164 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
mismo. Obsrvese que se pierde la asignacin del valor promedio a la variable
PluviometraProm, que se realiz en el empalmamiento mostrado en la figu-
ra 2.21.
Rl PluviometriaProm:= PromedioLista(Pluviometrias>
R
R2 WriteLn( 'media = " PluviometriaProm>
Figura 5.21. Creacin de una rutina nueva R empalmando
las rutinas R1 y R2.
R
R2 WriteLn( 'media = "
R11 PromedioLista(Pluviometrias>!
Figura 5.22. Creacin de una rutina nueva R por anidamiento
de R1 y R2.
Adaptacin. Es posible crear una rutina nueva R adaptando otra R1 ya exis-
tente. Es decir, el propsito original de Rl puede ser ligeramente modificado,
generalizado o particularizado de forma que realice la funcin requerida por R.
Supongamos que adaptamos la rutina MaxLi s ta (que encuentra la posicin
que ocupa el elemento mximo de una lista) para utilizarla como una rutina
Mi nList a (que encuentra la posicin que ocupa el elemento mnimo de una
lista). Qu necesitamos modificar en rutina MaxLi sta de forma que cumpla
las especificaciones de Mi nLi sta? Es casi evidente que es necesario realizar
unas modficaciones mnimas, y el resultado se obtiene mucho ms rpda y
fcilmente que si la construyramos de cero. Las modificacones se resumen en
la Figura 5.23.
Mezcla. Se puede construir una rutina nueva R mediante la mezcla o entrela-
zamiento de los pasos individuales de otras Rl y R2 ya exstentes. Esto se
muestra de forma ablitracta en la Figura 5.24, donde se han mezclado los pasos
de la rutina MaxL i sta con los de la Mi nLi sta, para obtener una nueva que
obtiene el valor mximo y mnimo en una nica pasada (bucle f o r) por la
lista, en lugar de dos.
Obsrvese que, en la Figura 5.24, hemos alterado la sintaxs y renombrado
algunas de las variables de las rutinas MaxLi sta y Mi nLi sta originales, con
objeto de que la nueva rutina MaxMi nLi s ta devuelva dos valores en lugar de
uno. En una implementacin completa, la cabecera podra ser:
Resolucin de problemas algortmicos 165
pl"ocedul"e MaxMinLista(L: Lista; val" Max, Min: reaL);
R
Rl if <O < m) and (m <= LengthLi sta(L then
begin
j := 1
fOI" k := 2 to mdo
if L[k](2:)L[j] then
j := k;
end
else
j := O;
:y
::J>
Figura 5.23. Creacin de una rutina R por la adaptacin de otra R1.
Donde los parmetros por referencia Max y Mi n se utilizan directamente en la
obtencin de los resultados; la variable j utilizada para este propsito en la
Figura 5.23 no es necesaria en esta versin.
R Rl
if (O < m) and (m <= LengthLi sta( L then
begin
Max := 1 ; R2
IMin:=1;
for k 2 to mdo
begin
if L[k] > L[Max] then
Max := k;
Iif then
end
end
else
begin
Max:=O;
I Min :=0
end;
I
Figura 5.24. Creacin de una rutina nueva R por mezcla de otras dos R1 y R2.
166 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Obsrvese, en la Figura 5.24, que las instrucciones fa r e i f sirven tanto
para el caso de la funcin MaxLi sta que para el de Mi nLi sta. Esto es asi
porque la forma lgica de implementar ambas rutinas es la misma. En la
Figura 5.24 se han marcado esas instrucciones como originarias de la rutina
Rl (en lugar de por R2), pero esto es indiferente en la ilustracin de la mezcla.
5.4.2. Utilizacin de la creatividad para disear nuevas rutinas
En los casos en los que no existe ninguna rutina disponible, debemos emplear
nuestra creatividad para construir las abstracciones procedimentales apropia-
das. En el problema de la pluviometra tenemos que utilizar nuestra creativi-
dad para encontrar una solucin a los pasos 3, que debe escribir los meses
cuya pluviometria est por debajo de la media, y el 4, que debe mostrar el(los)
mes(es) cuya pluviometria es la mxima.
Aparentemente, ambos pasos requieren utilizar el mismo tipo de estrategia
-una bsqueda dentro de la lista de pluviometrias para encontrar los valores
que cumplen una determinada propiedad-. El ndice de la lista PLuv i ome-
tri a puede utilizarse para encontrar el nombre del mes correspondiente, en el
array Meses. Considerando el ejemplo de entrada de la Figura 5.17b, el pro-
medio de lecturas pluviomtricas de esta entrada es de 2,64 lts/m
2
. El valor
pluviomtrico para PLuviometria[1] es 2,5, que se encuentra por debajo
de la media. Por tanto, el paso 3 debe mostrar el valor de Me ses [1] o Enero
como una de las salidas. Para encontrar todos los meses que satisfacen la
misma condicin, es necesario explorar los doce valores pluviomtricos. Esto
se consigue con el bucle siguiente:
{Paso 3. Mostrar meses que estn por debajo deL promedio}
WriteLn('Meses por debajo de La media: '};
for i := 1 to LengthLista(PLuviometrias) do
if PLuviometrias[i] < PLuviometriaProm then
WriteLn(' " Meses[i]);
Obsrvese que, a pesar de haber utilizado la creatividad, la solucin al paso 3
combina algunas rutinas ya familiares mediante el empalmado y el anidamien-
to. Por ejemplo, una referencia a un elemento del array Meses se ha anidado
dentro de una rutina Wri teLn que, a su vez, est anidada dentro de una
rutina que incluye un bucle foro La propia rutina del for est, a su vez,
empalmada con otra rutina Wr i teLn, para completar el paso 3.
Tras haber completado el paso 3, podemos intentar utilizar la misma estra-
tegia para resolver el 4, del que sospechamos que se puede resolver en la misma
forma. Obsrvese que el valor mximo de pluviometra puede darse para ms
de un mes. En el caso peor, los 12 meses pueden tener el mismo valor pluvio-
mtrico, por lo que la salida debe mostrarlos todos como salida del paso 4!
{Paso 4. Muestra eL(Los) mes(es) con vaLor mximo de PLuviometria)
WriteLn( 'Mes(es) Mxima:'};
Resolucin de problemas algortmicos 167
for i := 1 to LengthListaCPluviometrias) do
if PLuviometrias[i] = Maxpluviometria then
WriteLnC' " MesCes)[i]);
Obsrvese que la solucin se ha conseguido adaptando la solucin del paso 3.
Esta prctica es habitual en la resolucin de problemas algortmicos, y debe
utilizarse siempre que parezca, intuitivamente, que dos pasos necesiten el mis-
mo tipo de 'proceso. Pueden mezclarse los pasos 3 y 4 en un bucle for nico
que resuelva el problema? No es el caso. Piense sobre lo que ocurrira si un
nico bucle f or tuviera las dos instrucciones ; f de los pasos 3 y 4 dentro
de l.
5.4.3. Utilizacin del conocimiento de dominio en el diseo
de rutinas nuevas
A lo largo de nuestra discusin sobre la resolucin de problemas algoritmicos,
hemos supuesto que se posee un cierto conocimiento sobre el dominio al que
pertenece el problema. En problemas sencillos, como los que hemos visto hasta
el momento, el nico conocimiento del dominio que se precisa es el de la
familiaridad con los rudimentos del lgebra y de la Lgica. Para poder cons-
truir soluciones a problemas ms avanzados, es necesario tener unos conoci-
mientos ms profundos dentro del campo de la alta Matemtica, Informtica,
Ciencias Naturales, Ciencias Sociales, Lingstica, Economa o Comercio.
El Pascal estndar no incluye una rutina que calcule la raz cuadrada de un
nmero. Supongamos que estamos trabajando con un problema que requiere
esta rutina. Por ejemplo, necesitamos calcular, adems del valor medio de unas
lecturas pluviomtricas, su desviacin estndar. Este clculo precisa la utiliza-
cin de una rutina que calcule la raz cuadrada de x, siendo x un valor no
negativo. La construccin de esa rutina puede comenzarse con la especificacin
siguiente:
sqrtCx):
(pre: x>=O)
(post: result ~ y 1\ y2 ~ x)
Donde se ha utilizado el simbolo ~ para resaltar el hecho de que la raiz
cuadrada de algunos nmeros slo se puede calcular de forma aproximada.
Por ejemplo, la raz cuadrada de 2 es aproximadamente, con una precisin de
tres decimales, 1,414.
Un conocido mtodo de las matemticas para calcular races cuadradas de
forma aproximada es el mtodo de Newton. De hecho, el mtodo de Newton
es un mtodo general para calcular las races de ecuaciones, entre las que la
ecuacin y = x
2
es tan slo un caso particular. El mtodo de Newton es un
mtodo iterativo que trabaja de la forma siguiente. Comenzamos con una
primera aproximacin al valor esperado; por ejemplo, y = 1. La eleccin
particular de este valor inicial es habitualmente indiferente para la efectividad
168 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
del mtodo. A partir de y calculamos un nuevo valor ms aproximado, y',
mediante la frmula:
y'
y + x/y
2
La apliqcin reiterada de esta frmula crea una serie de valores candidatos
que converge rpidamente hacia el valor de la raz cuadrada de x. Por ejemplo,
en la Tabla 5.2 se muestran los valores obtenidos, suponiendo x = 2 Y asu-
miendo un valor inicial de y = 1. As, utilizando el mtodo de Newton, pode-
mos construir una rutina que calcule el valor aproximado de una raiz cuadra-
da, simplemente escribiendo un bucle que realice las aproximaciones sucesivas
de y' a y, y que termine cuando se haya alcanzado un grado de precisin
adecuado (por ejemplo, una diferencia de 0,0001).
Tabla 5.2. Primeros pasos del clculo aproximado de )2 por el mtodo
de Newton
Estimacin (y)
1
1,5
1,41667
1,41422
x/y
2/1 = 2
2/1,5 = 1,33333
2/1,41667 = 1,41176
Clculo de y'
(1 + 2)/2 = 1,5
(1,5 + 1,33333)/2 = 1,41667
(1,41176 + 1,41667)/2 = 1,41422
Existe una forma alternativa de calcular races cuadradas que nos permite
esquivar el necesario conocimiento del dominio que supone el mtodo de New-
ton. Sin embargo, esta alternativa nos obliga a conocer el dominio de las ca-
ractersticas ms avanzadas de las bibliotecas de funciones estndar de Pascal.
En concreto, Pascal incorpora las funciones exp(x) y ln(x) que calcu-
lan las funciones eX y el logaritmo neperiano de x, respectivamente. Combinan-
do esta informacin con los conocimientos adquiridos en el Captulo 2, pode-
mos obtener:
b In (a)
a
Por lo que tenemos una forma simplificada de calcular la raiz cuadrada de x.
Recurdese que es posible escribir la raz cuadrada de un nmero como X
1
/
2
.
Por lo que utilizando logaritmos:
In (x 1/2) = 1/2 In x
Ahora, aplicando eX, que excribimos como exp (x), obtendremos:
exp (In (X
1
/
2
) = exp (1/2 In x)
Resolucin de problemas algortmicos 169
o bien:
X'f2 = e1f2 In (xl
Que puede escribirse en Pascal como:
y : ~ exp(O,5 * ln(x
Por lo que 1<1 solucin que demos al problema algoritmico estar fuertemente
influida por nuestro conocimiento de la relacin del mismo y sus disciplinas
relacionadas.
5.5. TERMINACiN DEL CASO DE ESTUDIO
Volviendo al caso de estudio, nos quedan por aplicar tres pasos de la metodo-
loga MAPS propuesta: codficacin, verificacin y prueba, y presentacin.
5.5.1. Codificacin
En pocas palabras, la codificacin es la traslacin de la solucin de un proble-
ma algortmico a un programa, junto con su documentacin. En la resolucin
de un problema algortmico, la mayora del cdigo se obtiene durante las
etapas de particin y abstraccin. Por ejemplo, hemos completado la codifica-
cin de los pasos 3 y 4, del problema de la pluviometria, en la bsqueda de
nuevas rutinas que sean apropiadas para ellos. Tambin los pasos 1 y 2 estn
prcticamente codificados; sabemos que pueden implementarse reutilizando y
combinando rutinas de otros problemas ya existentes.
El proceso de codificacin implica el juntar las partes de la solucin al
problema, asegurndonos de que el resultado conjunto es coherente, inteligi-
ble, y satisface las pre y poscondiciones originales. Cuando codificamos en
Pascal suele ser til utilizar una plantilla como la siguiente:
program <nombre>;
{Breve comentario que describa el problema, la estructura general de
la soluci n, el autor y la fecha}
uses <Bibliotecas de las que se tomarn algunas rutinas>;
<Declaracin de las variables identificadas en el proceso de parti-
cin>
begin
{pre: <Precondicin del problema>}
{Paso 1. <Descripcin del primer paso de la particin>}
{Paso 2. <Descripcin del segundo paso de la particin}
{post: <Poscondiciones del problema>}
end.
Figura 5.25. Plantilla de un programa escrito en Pascal.
170 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Podemos codificar el programa de la pluviometra que hemos desarrollado,
utilizando como gua la plantilla de la Figura 5.26. En este programa se ha
supuesto que las rutinas PromedioLista, MaxLista y MinLista estn
almacenadas separadamente en la biblioteca denominada Herramientas-
Lis t a s, y otras operaciones diversas para manipulacin de listas de reales en
la biblioteca Listas. Una vez que se ha construido el esqueleto del programa,
el cdigo de lbS pasos individuales puede completarse mediante su insercin en
los lugares apropiados.
program Pluviometrias;
{El programa calcula algunas caracteristicas Pluviomtricas
a partir de datos mensuales. Diseador: Allen Tucker, 30 de marzo
de 1990. Reutiliza las rutinas MaxLista, MinLista y PromedioLista.}
uses Listas, Herrami entasLi stas;
type NombreMeses = array [1 . 12] of string[10];
val' Meses: NombreMeses;
Pluviometrias: Lista;
PluviometriaProm: real;
MaxPluviometria: real;
MinPluviometria: real;
{Los nombres de los 12 meses}
{Las 12 lecturas pluviomtricas}
{La medi a de las lecturas}
{Valor mximo de las lecturas}
{Valor minimo de las lecturas}
begin
{pre: entrada = (e" e" .. "' e,,) /\ Vi E {1, .. , 12} e, es el valor
pluviomtrico del i-simo mes del ao}
{Paso 1. Inicializar lista de meses y pluviometrias}
{Paso 2. Mostrar pluviometria promedio, mxima y minima}
{Paso 3. Mostrar meses por debajo del promedio}
{Paso 4. Mostrar mes(es) con pluviometria ms alta.}
{post: entrada =0/\ salida = ESTADISTICAS PLUVIOMETRICAS
media = Sum i E {1, .. "' 12}: e,/12
m xi ma = Max i E {1, , 12}: e,
minima = Min i E {1, , 12}: e,
Meses por debajo de la media:
{m;: e
J
< Su. i E {1, ... , 12}: e,l12}
Mes(es) mxima:
{m;: e
j
~ Max i E {1, ... , 12}: e, /\ 1,; j,; 12})
end.
Figura 5.26. Plantilla en Pascal para el problema de la pluviometria.
Para completar la codificacin de los pasos de entrada de datos, es necesa-
rio que el programa emita los mensajes necesarios para que el usuario intro
Resolucin de problemas algoritmicos 171
duzca los datos correctamente. Lo que hay que hacer se refleja en el esquema
del paso 1 siguiente:
{Paso 1. Inicializar lista de meses y pluviometrias}
InicializarMesesCMeses);
WritelnC'Introducir la lista de los 12 valores pluviomtricos men-
suales:' );
Readlista(pluviometrias);
Donde es necesario disear la rutina In; c; aL; za rMeses de forma que el
array Meses se inicialice adecuadamente con los nombre de los doce meses del
ao. Podemos aadir entradas protegidas (para el caso en que las prccondicio-
nes deban ser comprobadas explcitamente por el programa). Por ejemplo, en
vez de reducir el paso 1 a las instrucciones:
WritelnC'Introducir la lista de los 12 valores pluviomtricos
mensuales:');
ReadlistaCPluviometrias);
Es posible comprobar que se introduce exactamente una lista de doce elemen-
tos con las instrucciones:
repeat
WritelnC'introducir la lista de los 12 valores pluviomtricos
mensuales: 1);
ReadlistaCpluviometrias);
until lengthlistaCPluviometrias) = 12;
El cdigo de los pasos 2 a 4 se ha completado en el programa de la Figu-
ra 5.27. Obsrvese que se ha omitido el cuerpo del procedimiento In; c; aL;-
za rMeses, que se deja como ejercicio.
5.5.2. Prueba y verificacin
El objetivo de la prueba y la verificacin es garantizar lo ms posible que la
solucin diseada es correcta y completa en todos sus extremos. Es decir, se
trata de poder asegurar que la ejecucin del programa, utilizando unos datos
de entrada permitidos por las precondiciones, producir un resultado consis-
tente con las poscondiciones. Debido a que la prueba y verificacin son funda-
mentales en el proceso de resolucin de problemas algortmicos, se analizarn
en profundidad en el Captulo 6.
5.5.3. Presentacin
Cuando la solucin a un problema algortmico ha sido desarrollada completa-
mente, el programa debe ser suficientemente autodocumentado, para cuando
172 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
sea ledo por alguien no familiarizado con la solucin obtenida, pero s con la
metodologa y el dominio al que pertenece el problema. Es decir, el texto del
programa ---con su documentacin, estructura paso a paso, y pre y poscondi-
ciones- debe ser fcilmente legible por un colega profesional, como lo sera un
artculo del ABe para cualquier persona bien educada.
La presentacin de una solucin completa de un problema algortmico
debe incluir, adems del propio texto del programa, los elementos siguientes:
1. Una introduccin escrita en castellano identificando el(1os) autor(es) y
que descrba el problema, la solucin y algn aspecto inusual o innova-
dor de la solucin.
2. Un ejemplo de las entradas y las respectivas salidas obtenidas en una o
varias ejecuciones del programa.
3. Un resumen de los resultados de la verificacin y/o prueba del progra-
ma, en los casos en que sea adecuada.
program Pluviometrias;
(El programa calcula algunas caracteristicas Pluviomtricas
a partir de datos mensuales. Diseador: Allen Tucker, 30 de marzo
de 1990. Reutiliza las rutinas MaxLista, MinLista y PromedioLista.)
uses Listas, HerramientasLi stas;
type NombreMeses = array[1 .. 12] of string[10];
var Meses: NombreMeses;
Pluviometrias: Lista;
PluviometriaProm: real;
MaxPluviometria: real;
MinPluviometria: real;
(Los nombres de los 12 meses)
(Las 12 lecturas pluviomtricas)
{La media de las lecturas}
(Valor mximo de las lecturas)
(Valor minimo de las lecturas)
begin
{pre: entrada = (e" e" . , en) /\ Vi E {1, . ",12) e, es el valor
pluviomtrico del i-simo mes del ao)
{Paso 1. Inicializar lista de meses y pluviometrias)
InicializarMeses(Meses)
WriteLn('Introducir la lista de los 12 valores pluviomtricos
mensuales:');
ReadLista(Pluviometrias);
(Paso 2. Mostrar pluviometria promedio, mxima y minima)
WriteLn('ESTADISTICAS PLUVIOMETRICAS');
PluviometriaProm := PromedioLista(Pluviometrias);
WriteLn(' media = " PluviometriaProm:5:2);
MaxPluviometria :=MaxLista(Pluviometrias, LengthLista(Pluviome-
trias;
WriteLn(' mxima = " MaxPluviometria:5:2);
MinPluviometria : ~ MinLista(Pluviometrias, LengthLista(Pluviome-
trias;
WriteLn(' minima = " MinPluviometria:5:2);
Resolucin de problemas algortmicos 173
(Paso 3. Mostrar meses por debajo deL promedio)
WriteLn( 'Meses por debajo de La media:');
for i 1 to LengthLista(PLuviometrias) do
if PLuviometrias[i] < PLuviometriaProm then
WriteLn('Meses[i]);
{Paso 4. Mostrar mes(es) con pLuviometria ms aLta.)
WriteLn( 'Mes(es) mxima:');
fQr i := 1 to LengthLista(PLuviometrias) do
if PLuviometrias[i] = MaxPLuviometria then
WriteLn(' " Meses[i]);
{post: entrada saLida = ESTADISnCAS PLUVIOMETRICAS
media = Sum i E {1, , . ,12): e,l12
mxima = "ax i E (1, .. ",12): e
i
minima = "in i E (1, ." ,,12): e
i
Meses por debajo de La media:
{mj: e j < Sum i E {1, .. "' 12): e,l 12 )
Mes(es) mxima:
(m
j
: e
j
"ax i E (1, """,12):
end.
Figura 5.27. El programa Pascal PLuviometras, compLeto.
En pocas palabras, la presentacin de la solucin a un problema debe hacese
de forma que un lector interesado sea capaz de comprenderla. El lector ser,
por el momento, su profesor, pero en un futuro podra ser cualquier otro
resolutor de problemas profesional (programador o analista) al que se le asigne
la tarea de revisar o extender la solucin al problema en cuestin.
5.6. RESUMEN
En el Captulo 4 introdujimos las tcnicas y herramientas bsicas para cons-
truir programas sencillos en Pascal a partir de sus especificaciones. En este
captulo hemos aprendido cmo analizar un problema y a desarrollar su solu-
cin, identificando elementos del programa ms pequeos (rutinas) y combi-
nndolas todas en un programa completo.
Aprendimos algo del proceso de abstraccin y de su realizacin en Pascal.
La creacin de rutinas que puedan ser reutilizadas, es una de las tareas funda-
mentales del proceso de resolucin de problemas algoritmicos. Podemos reuti-
lizar rutinas y recombinarlas en cuatro formas fundamentales --empalmndo-
las, anidndolas, adaptndolas y mezclndolas durante el proceso de creacin
de una solucin a un problema nuevo. Fuera de estos limites, es preciso utilizar
la creatividad y el conocimiento del dominio. Los otros aspectos de la resolu-
cin de problemas algortmicos son evidentes en la metodologa MAPS --el
dilogo, la especificacin, la particin, definicin de abstracciones, codificacin,
verificacin y prueba, y presentacin.
Pero entender no es lo mismo que hacer. Antes de proseguir con el libro,
tmese algn tiempo para disear y escribir programas para los problemas
174 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
propuestos en los ejercicios siguientes. Asegrese de aplicar correctamente las
tcnicas del mtodo MAPS.
Ejercicios
5.23. Implementar una rutina del mtodo de Newton para calcular raices
cuadradas en forma de funcin de Pascal, y que tenga Z + como domi-
nio y R como rango. Probar el resultado para diversos valores de x, y
compararlos con los resultados de utilizar la rutina de clculo de races
cuadradas de la Seccin 5.4.
5.24. Escribir el cuerpo del procedimiento In; e; al; za rMeses del progra-
ma de la Pluv;ometr;a.
5.25. Continuar con el diseo MAPS sobre los nmeros romanos esbozado
en el Ejercicio 5.20; definir las abstracciones y codficar el programa
completo. Es posible utilizar abstracciones vistas previamente? Qu
abstracciones nuevas es necesario introducir, y qu tipo de creatividad y
conocimiento del dominio es necesario utilizar para completarlo?
5.26. Disear e implementar un sistema de manipulacin de informacin de
una pequea compaa. El programa deber leer un archivo del perso-
nal, en el que cada empleado tiene su nmero y sueldo anual. Disear
un programa que realice un informe. Disear el formato del informe
cuidadosamente; cada elemento debe estar etiquetado cuidadosamente.
Para poder probar el programa, suponer que la compaia tiene 25 em-
pleados y disear un archivo de empleados sencillo, consistente en nme-
ros de empleados y su sueldo anual. En el informe, mostrar lo siguiente:
a) La nmina anual de la empresa, los sueldos anuales mximo, mini-
mo y medio.
b) Un apartado de la misma informacin para los rangos de salarios
siguientes (en dlares):
< sueldo < 15.000
15.000 < sueldo < 20.000
20.000 < sueldo < 30.000
30.000 < sueldo < 45.000
45.000 < sue ldo
(Es decir, el nmero de trabajadores de cada intervalo, junto con los
sueldos mximo, mnimo y medio de cada intervalo.)
5.27. Desarrollar un diseo basado en la metodologa MAPS, para un gestor
de apuestas mltiples en las carreras de caballos. Antes de cada carrera,
el usuario debe introducir la apuesta que realice, dando el nmero del
Resolucin de problemas algortmicos 175
caballo y el valor de la apuesta. Tras la campana de ltima apuesta, el
programa debe calcular y visualizar la relacin de las apuestas sobre
cada caballo, que se calcula dividiendo el valor total de las apuestas
sobre todos los caballos por la cantidad total apostada a cada caballo.
Por ejemplo, en una carrera con tres caballos, el total de apuestas para
el nmero 1 fueron 100 dlares; para el nmero 2, 150 dlares; y 250
dlares Pllra el nmero 3. Las relaciones para el ejemplo anterior sern
5 a 1 para el primero, 5 a 3,33 para cl segundo, y 2 a 1 para el tercero.
No es necesario implementar todo el programa, sino slo el diseo
(pasos de MAPS del 1 al 4).
CAPTULO 6
ROBUSTEZ Y PRUEBA
DE LOS ALGORITMOS
Todo lo que pueda funcionar mal, lo har.
MURPHY
La disciplina de resolver problemas algortmicos puede resultar cruel. El dise-
ador no slo debe cuidar que el programa funcione correctamente para las
entradas que se ajustan a las especificaciones, sino que debe cuidar que el
programa responda adecuadamente cuando se encuentre entradas incorrectas
o inesperadas. Asi, el resolutor de problemas se convierte rpidamente en un
escptico sobre la infalibilidad de los programas que pretenden resolver un
problema. Invariablemente, siempre que oimos en el laboratorio he encon-
trado el ltimo error!, sabemos que despus comprobar que slo era el
penltimo.
Es posible resolver problemas complejos y disear un software que tenga
una fiabilidad alta? Es decir, cmo podemos asegurar que nuestros progra-
mas, que son el producto final de nuestra metodologia de resolucin de proble-
mas algoritmicos (MAPS), detecten combinaciones de entradas inesperadas, y
aun as trabajen de forma correcta y predecible?
En este captulo analizamos estas cuestiones de diferentes formas. Primero,
definimos las nociones complementarias de correccin, robustez y amigabili-
dad. Segundo, ilustramos la aplicacin de estas ideas en dos situaciones dife-
rentes: una que involucra el procesamiento de textos, y otra que involucra el
tratamiento de grficos. En ambos casos utilizamos la metodologa de resolu-
cin de problemas MAPS, lo que nos servir para afianzarnos en su conoci-
miento para utilizarla en otro tipo de problemas algortmicos. Tercero, intro-
ducimos una estrategia para disear datos de prueba, y una metodologa de
prueba sistemtica que aporta un grado de confianza sobre la correccin y
robustez del programa mayor que si se utilizan pruebas aleatorias. Cuarto,
introducimos la nocin complementaria de verificacin formal y mostramos
que est estrechamente relacionada con el lenguaje de la lgica y los procesos
de demostracin que fueron presentados en el Capitulo 3. Como veremos, las
tcnicas de verificacin y prueba pueden combinarse para crear una serie de
mtodos que aseguren la calidad y fiabilidad del software.
178 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
6.1. CORRECCiN V ROBUSTEZ
Qu significa que un programa sea correcto?
Definicin. Un programa es correcto si, para cualquier entrada que satisfa-
ga la precondicin, termina generando una salida que satisface sus poscon-
diciones. De forma anloga, un procedimiento (o funcin) es correcto si,
para todos los posibles valores de los parmetros de entrada que satisfacen
las precondiciones, termina y, adems, los parmetros de salida (resultados)
satisfacen las poscondiciones.
Por ejemplo, el programa que calcula la calificacin media CaLcuLaCM, del
Capitulo 4, es correcto en este sentido. Es decir, para todas las entradas del
tipo (Notas!' Notas
2
, .. , Notas
n
), donde n > Oy cada Notas, es un nmero en
el intervalo {O, ..., 4} el programa calcula y escribe la calificacin media y
termina. A continuacin, se demuestran algunas entradas y sus correspondien-
tes salidas, para diferentes ejecuciones del programa.
Entrada
(3 1 2 4)
(2 )
(2 3 3 3 3 3 3 2)
Salida
2,50
2,00
2,75
Un estudio cuidadoso del programa de la Figura 4.6 hace que nos plantee-
mos algunas dudas sobre lo que ocurre cuando las entradas no satisfacen las
especificaciones de las precondiciones. Por ejemplo, qu ocurre si la entrada
es la lista vacia( )? Qu ocurre si la lista de entrada contiene valores fuera del
intervalo {O, ..., 4}, como la lista de pluviometras mensuales utilizadas en la
Figura 5.17b, utilizadas para un problema completamente distinto? Qu ocu-
rre si la lista contiene algo distinto de nmeros, como la lista de los doce
nombres de meses de la Figura 5.17a?
Una posible alternativa para responder a esas preguntas es correr el pro-
grama con varias entradas alternativas que no satisfacen las precondiciones, y
ver qu ocurre en cada caso. Observemos el cuerpo del programa Ca Lcu LaCM
y analicemos cmo tratar cada uno de los distintos casos (vase Figura 6.1).
Este es un programa tan sencillo que resulta conveniente un anlisis tan
directo. En el caso en que la lista de entrada est vacia, no se satisface la
condicin n > O, por lo que el programa no genera ninguna salida. Sin embar-
go, en el caso en que los valores de la entrada no estn en el intervalo {O, ..., 4},
el programa calcula sin problemas el promedio y escribe (errneamente) el
valor de la CM, aunque algunas entradas numricas no sean calificaciones
vlidas, segn las especificaciones.
Robustez y prueba de los algoritmos 179
begin
{pre: entrada ~ (Notas" Notas" . o., Notas,) 1\ n > O1\
\;Ii E {1, o , ni: Notas, E {O, .. , 4}}
{Paso 1. Obtenemos la lista de calificaciones}
WriteLn( 'Introducir la lista de calificaciones:');
ReadLista(Notas);
{Pas6 2. Calcular n o nmero de calificaciones en la lista}
n : ~ LengthLista(Notas);
i f n > O then
begin
{ent rada =0 A n>O}
{Paso 3. Calculamos Sum = la suma de las calificaciones de la lista}
Sum := O;
i : ~ 1;
while i <= n do
begin
Sum := Sum + Notas[i];
i := i + 1
end
end;
{Paso 4. Calculamos CM = Sum/n}
CM = Sum/n;
{Sum = Su. i E {1, ... , n}: Notas, 1\ CM ~ Sum/nj
{Paso 5. Se muestra CM}
WriteLn('La CM de esas calificaciones es ~ ' , CM 5: 2)
end {if}
{pos t: ent rada = 0 1\
salida = SUII i E {1, o , n}: Notas,!n}
end. {CalculaCM}
Figura 6.1. Cuerpo del programa CalculaCM.
Finalmente, consideremos el caso en que la entrada no es completamente
numrica:
(31 hello 2)
Cmo trate el programa esta entrada depender de cmo manipule la rutina
ReadLi s ta las entradas no numricas. Es decir, los valores obtenidos por
ReadLista<Notas) parai = 1,2y4sonlosnmeros3,1 y2,respectiva-
mente. Para el caso de i = 3 (donde la entrada es Notas = heL Lo) se
producir un error?, debe devolver la rutina algn valor especial, por ejemplo
0, cuando se introduzca un valor no numrico? Obsrvese que simplemente
analizando las pre y poscondiciones de la rutina ReadLi s ta (vase Apn-
dice C), no se contesta a esta pregunta, puesto que stas estn enunciadas para
entradas vlidas. Sin embargo, ejecutando el programa podemos descubrir que
180 Computacin l. Lgica, resolucin de problemas, algoritmos Vprogramas
la referencia a Notas[3] devuelve el valor para esta lista en concreto, por
lo que el valor promedio es, por tanto, 1,50.
Tenemos que destacar, por tanto, que el programa Ca Lcu LaCM es correcto
en el sentido de la definicin anterior. Sin embargo, no es robusto.
Definicin, Se dice que un programa es robusto si rene las dos condicio-
nes siguientes:
1. Es correcto.
2. Para todas las entradas que no satisfacen las precondiciones, el
programa termina y produce una salida que refleja el hecho de que
ha ocurrido un error en la entrada.
Seguramente, el programa Ca Lcu LaCM no es robusto, aunque seguramente es
correcto. En general, la creacin de software robusto es ms complicada que la
creacin de software correcto. Ms an, la robustez es una caracterstica desea-
ble para el software de computadoras, sobre todo si va a ser manipulado por
gente no familiarizada con los detalles del diseo, o que son proclives a come-
ter ocasionalmente errores cuando escriben la entrada.
Cmo es posible robustecer el programa de la Figura 6.1? Es necesario
hacer dos cambios bsicos. Primero, es preciso revisar el procedimiento
ReadL; s ta de forma que ponga L; s tError a t rue siempre que aparezca
un dato no numrico en la lista de entrada. El paso 1 del programa debe
explorar especficamente la correccin de cada calificacin (es decir, que sea un
valor numrico dentro del conjunto {O, ..., 4}). Segundo, es necesario completar
la instruccin condiciorral que compruebe si n > 0, con una clusula e Lse, de
forma que el programa escriba el mensaje de error apropiado cuando se pre-
sente como entrada una lista vaca. Podemos revisar el paso l de la forma
siguiente:
(Paso 1. Obtenemos la lista de calificaciones}
WriteLn( 'Introducir la lista de calificaciones:');
ReadLista(Notas);
n := LengthLista(Notas);
if Li stError o.. (n = O) then
entradavlida := false
else
begin
entradavl ida : ~ true;
for i : = 1 to n do
if Notas[i] < O) o.. (Notas[i] > 4) then
entradavlida := false;
end;
i f not ent radav l i da then
WriteLn('Entrada no vlida. Programa terminado')
else begin
Robustez y prueba de los algoritmos 181
Donde la nueva variable booleana ent radav L; da indica si la entrada se
ajusta o no a los requisitos de la precondicin. El resto del programa quedaria
de la forma original, salvo que la comprobacin de si n > Opuede ser elimina-
da (puesto que se ha incorporado el paso 1 de esta nueva versin).
Una tercera caracteristica que es valorable en un programa es la de la
amigabilidad. Es decir, es deseable un programa que no slo identifique los
errores de entrada, sino que, a ser posible, realice avisos constructivos al
usuario sobre cmo tiene que escribir sta para que se ajuste a las especifica-
ciones.
Definicin. Se dice que un programa es amigable si rene los requisitos
siguientes:
1. Es correcto.
2. Para todas las entradas que no se ajusten a las precondiciones, el
programa indica el tipo de error de entrada y concede al usuario la
oportunidad de corregirlo y continuar.
Cmo podemos convertir el programa CaLcuLaCM en un programa amiga-
ble? Podemos revisar el paso 1 en la forma siguiente:
{Paso 1. Obtenemos la lista de calificaciones}
repeat
WriteLn('Introducir La lista de calificaciones:');
ReadLista(Notas);
n := LengthLista(Notas);
if ListError 01' (n = O) then
entradavl ida ;= false
else
begin
entradavl ida := true;
for i : ~ 1 to n do
if Notas[i] <O) 01' (Notas[i] > 4) then
entradavlida := false;
end;
until entradavlida;
Esta entrada es ms constructiva que la anterior, porque permite al usuario
mltiples oportunidades de reintroducir la lista de calificaciones. Es decir, el
programa contina en el bucle del paso 1 hasta que se introducen las califica-
ciones apropiadas, tras lo cual pueden ser ejecutados los pasos del 2 al 5.
Asegurarse de que un programa es correcto, robusto y amigable es una
tarea dura. Ello implica la aplicacin cuidadosa de tcnicas de prueba de
programas intrnsecas a la metodologa MAPS. Puesto que esta actividad es
tan crucial en la resolucin de problemas algortmicos, hacemos hincapi en
ella en las Secciones 6.2 y 6.3, donde resolvemos dos problemas muy diferentes
utilizando la metodologa MAPS.
182 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Ejercicios
6.1. Es correcto el programa de las Tres-en-Raya de la Figura 4.21? Es
robusto? Justificar la respuesta.
6.2. Mostrar cmo puede modificarse el problema de las Tres-en-Raya
para que sea m ~ amigable.
6.3. a) Revisar la precondicin del programa de las Tres-en-Raya, de
forma que describa exactamente cul movimiento es legal y cul no.
b) Considerando esta revisin, qu cambios adicionales pueden reali-
zarse para hacer el programa ms robusto?
6.4. Es correcto el programa ContarPalabras de la Figura 4.17? Es
robusto? Justificarlo.
6.5. Mostrar la forma en que se puede alterar el programa ContarPala-
bras para hacerlo amigable.
6.2. RESOLUCiN DE PROBLEMAS DE PROCESAMIENTO
DE TEXTO UTILIZANDO MAPS: CRIPTOGRAFA
Las computadoras se han utilizado desde la Segunda Guerra Mundial para
ayudarnos en la resolucin de problemas criptogrficos, que requieren descu-
brir el esquema de codificacin, o cifrado, que subyace en un mensaje codifica-
do. En el Captulo 2 presentamos un ejemplo del conocido mtodo Csar de
cifrado que convirti el mensaje
SERGEANT PEPPERS LONEL y HEARTS CLUB BANO
en el mensaje codificado
VHUJHOQW SHSSHUV ORQHOB KHOUWV FOXE EOQG
Aqu, el esquema de codificacin subyacente consiste en reemplazar cada letra
por la que ocupa tres posiciones posteriores en el alfabeto. En la prctica,
se utilizan otros esquemas de codificacin ms elaborados, y el descubrimiento
tanto del cifrado como del mensaje original puede ser una tarea bastante
complicada.
En nuestro caso, el problema es mucho ms sencillo: dada una serie de
mensajes codificados segn el mtodo Csar, descodificar cada uno y escribir el
texto del mensaje ya descodificado. Por tanto, para el mensaje codificado que
se muestra arriba, la salida debera ser SERGEANT PEPPERS LONELy
HEARTS CLUB BAND.
Robustez V prueba de 105 algoritmos 183
Etapa 1: El dilogo. Existen tan pocas dudas acerca de este problema, que
podemos estar tentados de abordar directamente el diseo. Sin embargo, es
necesario apuntar y resolver algunas cuestiones de detalle. Por ejemplo, puede
contener el texto tanto letras maysculas como minsculas, e incluso caracte-
res no alfabticos? Presumiblemente la respuesta es si, y tales caracteres deben
aparecer en el mensaje descodificado tal y como aparecan en el mensaje origi-
nal. Por ejemplo, el blanco del mensaje codificado permanece igual en el men-
saje descodificado.
Etapa 2: Las especificaciones. Las especificaciones para este problema pueden
establecerse de la forma siguiente:
[pre: entrada = una serie de mensajes, siendo cada uno una secuencia
de caracteres c" ... , c
n
representando una codi fi cacin uti Lizando
eL mtodo de Csar
"post: saLida = una serie de textos descodificados de La forma
d" ... , d
n
en La que cada d, satisface La reLacin c, ~ Csar(d,) /\c,
es un carcter aLfabtico v para todo i en {1, ... , n): c, = di}
Donde Csa r (di) representa la codificacn Csar del; -simo carcter di
en el texto de salida. Esta codificacin se describe en la Tabla 6.1.
Tabla 6.1. El cifrado de Csar
Letra (1) Csar (1) Letra (1) Csar (1)
a d A D
b e B E
x a X A
Y
b Y B
z e Z C
Etapa 3: La particin. El programa necesita ejecutar tres pasos principales
para cada mensaje que descodifica. En el paso dc entrada se obtendr el men-
saje descodificado, a continuacin se har un paso de descodificacin y, final-
mente, se realizar el paso de salida que escribe el programa ya descodificado.
Estos pasos se resumen de la forma siguiente:
repeat
{Paso 1. Obtener eL mensaje. J
{Paso 2. Descodificar eL mensaje.)
{Paso 3. Escribir eL mensaje descodificado.)
until no existan ms mensajes para descodificar
184 Computacin ,. Lgica, resolucin de problemas, algoritmos y programas
Si acordamos que la longitud mxima de un mensaje est limitada a la
longitud mxima de un string de Pascal (255 caracteres en la mayora de las
implementaciones), entonces existe una pequea dificultad al implementar los
pasos de entrada y salida para este programa. Sin embargo, si pretendemos
ms generalidad, es necesario realizar algunas cuidadosas consideraciones so-
bre el almacenamiento y los requerimientos de codificacin de cada mensaje.
En esta solucin vamos a atenernos a la versin ms simple.
As, el programa tendr dos variables del tipo s tri n9 principales, la va-
riable mensaje y la variable deseodi fi cado. La propia descodificacin
puede hacerse de dos maneras. Una forma es la de almacenar las letras del
alfabeto en un array, por ejemplo el array Csar, de forma que la descodifica-
cin de una letra concreta Csa r [i] puede obtenerse directamente buscando
en Csar[i-3]. Si utilizamos esta estrategia, tendremos que tener cuidado
con las tres primeras letras del alfabeto. (Por qu?)
Otra forma de descodificar las letras del alfabeto es la de hacer operar
sobre el ordinal que corresponde a cada carcter en la tabla ASCII (vase el
Apndice A). Por ejemplo, el ordinal de la letra Aes el 65, que se diferencia del
ordinal de la letra D (68) en tres unidades. As, si e es una letra del mensaje de
entrada, la funcin de Pascal ehr(ord(e)-3) devolver la letra codificada,
suponiendo de nuevo que e no es una de las tres primeras letras del alfabeto.
(Por qu?)
Etapa 4: Definicin de abstracciones. El paso 2 de este programa, la descodifi-
cacin del mensaje, puede considerarse como el anidamiento de dos rutinas. Es
decir, la funcin que calcula la inversa de la funcin de cifra de Csar (vase
Tabla 6.1) para una sola letra del alfabeto, puede anidarse dentro de otra que
analice uno a uno los caracteres que componen el mensaje codificado. La
ltima puede implementarse como un bucle for, mientras que la primera
puede implementarse como una funcin de Pascal a la que denominaremos
Csarlnversa(e), que toma un solo carcter como argumento y devuelve
como resultado el carcter descodificado. El anidamiento debe tener lugar,
puesto que esta operacin se realiza para todos los caracteres del mensaje.
Podemos definir las especificaciones de esas dos rutinas en la forma siguiente:
Descodificar(mensaje)
{pre: mensaje = C
1
, e
2
, _, en}
{post: resultado = d" d" . "' d
n
1\ para todo i in (1, "."' n):
di = Csarlnversa(c)
Csarlnversa(c)
(pre: c es un carcter)
(post: resultado = d, Ybien d es alfabtico 1\ CsarCd) = c or d no
es alfabtico 1\ d = c)
Etapa 5. Codificacin. Las especificaciones anteriores pueden codificarse
como rutinas Pascal de la forma siguiente:
Robustez y prueba de los algoritmos 185
function Descodificar (mensaje: string): string;
yar
i: integer;
descodificado: string;
begin
{pre: mensaje = C
1
, C
2
, "' en}
descodificado := mensaje;
for i := 1 to Length(mensaje) do
descodifi cado[i] := CsarInyersa (mensa j e[i]);
Descodif i ca r : = descodi f i cado
{post: resultado=d" d" ... , do 1\ para todo i in {1, ... , ni:
di = CsarInversa(c
i
)}
end;
function Csar Inversa (c: char): char;
yar
d: char;
j: integer;
alpha: string;
begin
{pre: c es un carcter}
alpha := concat('abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
j := pos(c, alpha); {busca c en el al fabeto}
case j of
O:
d := c; {no es alfabtico}
1 .. 3:
d := alpha[23 + n; {descodifica a, b, c}
4 .. 26:
d := alpha[j - 3]; {descodifica d, e, .. "' z}
27 .. 29:
d := alpha[23 + n; (descodifica A, B, C)
30" .52:
d : ~ alpha[j - 3J; {descodifica D, E, ... , Z}
end;
Csar Inversa := d;
(post: resultado = d, Ybien d es alfabtico /\ Csar(d) = c
or d no es al fabtico 1\ d = c}
end;
Teniendo todo lo anterior en mente, podemos escribir el esbozo de programa
siguiente:
program Criptografia;
{El programa descodifica una serie de mensajes y escribe cada uno
descodi fi cado; se supone que cada mensaje se ha codi fi cado
util izando la cifra de Csar.}
function CsarInversa
function Descodificar
Yar
mensaje, descodificado: string;
186 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
begin
{pre: entrada una serie de lineas, conteniendo cada una un mensaje
codifi cado}
repeat
{Paso 1. Obtener el mensaje}
WriteLn('Introducir en una sola linea un mensaje codificado, y');
WriteLn,( 'pulsar <RET> para terminar:');
ReadLn(mensaje);
{Paso 2. Descodificar el mensaje.}
Descodificar(mensaje);
{Paso 3. Escribir el mensaje descodificado.)
WriteLn('El mensaje descodificado es:');
WriteLn(descodificado);
unti l mensaje = "
{post: entrada vacia 1\ salida el correspondiente mensaje
descodificado}
Etapa 6: Prueba. Es til probar este tipo de programas utilizando como entra-
da un texto almacenado en un archivo separado. De esta forma, no es necesa-
rio reescribir de forma tediosa el mensaje de entrada cada vez que se ejecute el
programa. Una sencilla alternativa al programa anterior, que permita utilizar
una variable archivo (tipo file), en el que se escribira la entrada, y que condi-
ciona la terminacn del programa a que se lea la marca de fin de fichero, se
obtendra con las modificaciones siguentes. Previas al paso 1 habra que escri-
bir:
var Archi voTexto: text
reset(ArchivoTexto, 'codificado,txt');
El paso 1 debera alterarse para que tome la entrada del archivo, en lugar de
tomarla desde el teclado, en la forma siguiente:
ReadLn(ArchivoTexto, mensaje);
WriteLn(mensaje);
Finalmente, la condicin de terminacin del bucle repea t debe explorar el
final del archivo de entrada en la forma siguiente:
until not eof(Archi voTexto);
Es evidente que, separadamente, se debe preparar en la forma adecuada el
archivo cod i f i cado. t xt para que incluya los textos codificados antes de
ejecutar esta nueva versin del programa.
Robustez y prueba de los algoritmos 187
Etapa 7: Presentacin. La presentacin de la solucin a este problema requie-
re la realizacin de varias ejecuciones del programa, imprimiendo la salida
correspondiente a cada ejecucin. La combinacin de estas salidas con el texto
del programa, una breve exposicin escrita con el propsito del mismo, y una
explicacin con alguna caracterstica inusual (si la tiene), completarn la pre-
sentacin.
6.3. RESOLUCiN DE PROBLEMAS GRFICOS UTILIZANDO
MAPS: EL JUEGO DE LA VIDA
El Juego de la Vda lo invent John H. Conway en 1970. Su propsito es
proporcionar una simulacin grfica sencilla de la variacin de poblacin a lo
largo de varias generaciones. El juego se juega en un entramado rectangular
que representa el mundo para una especie particular de organismo viviente
(personas, amebas, pollos u otros). En el entramado, cada celda sombreada
representa un organismo vivo, y la coleccn completa de celdas sombreadas la
poblacin viva en una generacin concreta. Por ejemplo, la Figura 6.2 muestra
una poblacin de seis pollos vivos en un mundo que puede albergar un total
de 64 en una generacin.
Figura 6.2. Una generacin de seis pollos en el Juego de la Vida.
Cada nueva generacin de pollos se obtiene de la anterior siguiendo cuatro
reglas muy simples que regulan la supervivencia, muerte o nacimiento de cada
individuo. Estas reglas estn relacionadas solamente con el entorno fisico en
que vive el pollo -es decir, las condiciones de superpoblacin o la baja densi-
dad de poblacin en la que se incluye el pollo-o Se define el entorno de una
celda del entramado, como el conjunto de celdas contiguas a ella. Las cuatro
reglas mencionadas son:
1. Supervivencia. Un pollo sobrevive hasta la siguiente generacin, si tie-
ne dos o tres vecinos vivos en la generacin actual.
2. Nacimiento. Un pollo nacer en la generacin siguiente, si: a) no existe
en la generacin actual; y b) tiene exactamente tres vecinos vivos en la
generacin actual.
188 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
3. Muerte por soledad. Un pollo morir en la generacin siguiente, si en
la actual tiene cero o un solo vecino.
4. Muerte por superpoblacin. Un pollo morir en la siguiente genera-
cin, si en la actual tiene 4 o ms vecinos vivos.
Asi, si extendemos el ejemplo de la Figura 6.2 hasta la generacin siguiente,
nuestra poblacin de ppllos se transformar en la de la Figura 6.3.
Observamos, en la Figura 6.3b, que el pollo de abajo, a la izquierda, ha
muerto por soledad, mientras que dos pollos en la cruz han muerto por
superpoblacin. Los otros tres pollos de la cruz han sobrevivido porque tenan
tres vecinos en la generacin anterior. Finalmente, nacieron tres nuevos pollos
en celdas que estaban sin ocupar, y tenian exactamente tres vecinos en la
generacin anterior.
a) b)
Figura 6.3. Dos primeras generaciones en el Juego de la Vida.
a) Seis pollos en la primera generacin. b) Seis en la segunda.
Despus de algunas pruebas, podemos concluir que la configuracin de po-
llos en cada generacin puede diferir de la precedente. El Juego de la Vida y
algunas derivaciones que presentan pequeas diferencas, han fascinado a mate-
mticos y cientficos que los han estudiado detenidamente. Los cientficos han
estudiado la forma de aplicar este tipo de simulacones o tcnicas de modeliza-
cin, como ayuda para comprender los cambios de poblacin en la vida real.
Sin embargo, el problema al que nos enfrentamos aqu es simplemente el de
construir un programa que, para una configuracin inicial sobre un entramado
de 8 x 8 celdas, muestre la secuencia de generaciones que siguen las reglas
sobre supervivencia, vida y muerte anteriores.
Etapa 1: El dilogo. Seguramente, nuestro programa debe proporcionar al
usuario una forma sencilla de describir la configuracin inicial de los pollos en
el entramado. Mientras no sea dificil generalizar el programa para que pueda
manipular entramados de cualquier tamao, esto no parece ser importante
para el programa, por lo que lo ignoraremos por el momento. Sin embargo, es
necesario incorporar algn mecanismo por el cual el usuario pueda controlar
el paso de las generaciones, e incluso parar el proceso.
Robustez y prueba de los algoritmos 189
Podemos considerar la entrada en dos etapas. Primero, el usuario introdu-
ce las filas y columnas de cada celda que estarn ocupadas por la primera
generacin de pollos. Segundo, el usuario introducir una serie de rdenes que
indicarn al programa si debe avanzar a la siguiente generacin, o bien termi-
nar el juego.
La salida la constituyen una sucesin de grficos como los de la Figura 6.3.
La configuracin inicial se compone de un entramado, colocado a la izquierda,
con la distribucin inicial, y otro entramado vaco a la derecha. La segunda
imagen, que se visualiza ante la entrada por el usuario de la orden de progre-
sar, estar constituida por un entramado a la izquierda con la configuracin
inicial, y el de la derecha con la distribucin obtenida en la segunda genera-
cin. La tercera imagen, si se ordena, presentar a la segunda generacin a la
izquierda, y la tercera a la derecha, y asi sucesivamente.
Etapa 2: Las especificaciones. Despus del dilogo, podemos escribir las si-
guientes especificaciones para este problema:
{pre: entrada =n, X
1
, y" XZ' Y2' _, X
n
, Y
n
, C" e
Z
' , C
m
/\ C
m
= I q ' /\
n > O 1\ m> Opa ra todo i in {1, ... , n}: 1 ,;; Xii y; ,;; 8}
{post: salida = una serie de m- 1 imgenes del Juego de la Vida,
donde la pri mera imagen est determi nada por las n celdas
(x" y,>, (x" y,> , (X
n
, Yn>' y cada imagen sucesiva presenta
la i-sima generacin que se obtiene de la (i -1)-sima al aplicar
las reglas de nacimiento, supervivencia y muerte. El final del
juego lo provoca el usuario pulsando' 'q" (de' 'quit' '>')
Donde las pulsaciones de teclas C" Cl' , Cm-' sirve para proporcionar al
usuario el control de las transiciones entre una generacin y la siguiente. Es
decir, el carcter (incluida la barra espaciadora) que se simboliza por c; indica
al programa que tiene que calcular la i -sima generacin, a partir de la
(i -1)-sima y dibujarlas una alIado de la otra. Por tanto, en cada momento, el
programa debe mostrar las dos ltimas generaciones calculadas, siendo la de la
derecha la ms reciente. La primera generacin, dada por las coordenadas x"
y" x
2
' Yl' , x
n
, Yn' se identifica con el nombre de generacin 1 de la
secuenCia.
La Figura 6.3 muestra una generacin 1 inicial (en el entramado del lado
izquierdo) y la generacin 2, que se obtendra si se pulsa la tecla de continua-
cin (lee las celdas sombreadas, fila a fila, suponiendo que las filas y las colum-
nas estn numeradas del 1 al 8):
6364546475456
Etapa 3: La particin. Inmediatamente nos vienen a la cabeza varias ideas para
resolver este problema. Primero, ser til usar las facilidades de la abstraccin
Gri d. Segundo, ser til declarar dos variables del tipo Gri d; por ejemplo,
Gen1 (para el entramado de la izquierda) y Gen2 (para el de la derecha).
190 Computacin l. Lgica, resolucin de problemas, algoritmos Vprogramas
El programa deber incorporar tres pasos principales para simular el Juego
de la Vida. El primer paso debe inicializar los dos entramados Gen1 y Gen2,
leyendo la primera parte de la entrada, y sombreando las celdas de Gen1
apropiadas. El paso 2, simplemente leer del teclado la orden de si se debe
continuar a la siguiente generacin o terminar el juego. El paso 3 se encargar
de calcular la generacin actual a partir de la anterior, y de mostrar el re-
sultado.
El secuenciamiento de esos tres pasos puede ser gobernado por la estructu-
ra iterativa que se muestra ms adelante. En ella, una instruccin wh i Le
controla el bucle, y cada repeticin de ste provoca el clculo de una nueva
generacin que resulta visualizada.
{Paso 1. Inicializar Gen1 y Gen2}
{Paso 2. Leer una orden de cont ro l}
while control <> 'q' do
begin
{Paso 3. Obtener y mostrar la generacin siguiente}
{Paso 4. Leer una orden de control}
end
Donde la variable de control se utiliza para almacenar el carcter que el
usuario pulsa en el teclado para indicar si se debe calcular y mostrar la prxi-
ma generacin. Por esta razn, el paso 4 es una repeticin del paso 2; es decir,
se necesita una orden distinta para iniciar el proceso y para cada repeticin
sucesIva.
El paso 1 primero crea los dos entramados con un tamao de celda apro-
piado, por ejemplo, 10 pixels, y coloca los entramados Gen1 y Gen2 en las
coordenadas apropiadas para que aparezcan uno al lado del otro. Este paso
tambin necesita inicializar la variable entera n seguida de n pares de enteros i
y j, en el rango 1 al 8 que designe la posicin inicial de la poblacin de la
generacin 1. A diferencia de la primera parte del paso 1, esta segunda parte
necesitar ser abstraida como un procedimiento -que podramos llamar
Ini ciaL izar.
El paso 2 es prcticamente inmediato. Puede construirse simplemente in-
cluyendo una instruccin Read que asigne el carcter de la tecla pulsada a la
variable control. El paso 3 es el ms complejo del programa, por lo que se debe
subdividir en varias partes. Es decir, para el clculo y visualizacin de una
nueva generacin, primero debemos borrar el entramado que contendr la
generacin siguiente (Gen2 o Gen1, dependiendo de cul de los dos contiene
la generacin actual), y a continuacin determinar para cada celda en esa
generacin cul est viva y cul no. El acto de borrar un entramado puede
abstraerse bajo el nombre de Bor ra rG r i d. La determinacin de la configura-
cin de la prxima generacin puede abstraerse bajo el nombre Si gui ente-
Generacin.
Robustez y prueba de los algoritmos 191
El procedimiento SiguienteGeneracin puede subdividirse a su vez
en partes, puesto que para cada celda debe contarse el nmero de vecinos vivos
que tiene. Abstraeremos esa tarea con la funcin Vec i nos. El procedure
NuevaGene ra c in puede construirse anidando la funcin Vec i nos dentro
de un bucle que examine por separado cada celda de la generacin actual.
Puede utilizarse una instruccin case (vase el manual de laboratorio para
ms detalles sobre esta funcin) para discriminar entre si las cuatro reglas del
nacimiento, supervivencia y muerte. Por tanto, el paso 3 tendr la estructura
de control siguiente, suponiendo que Gen1 es la generacin actual, y Gen2 la
siguiente:
{Paso 3. Obtener y mostrar la generacin siguiente}
BorrarGrid<Gen2);
SiguienteGeneracin<Gen1, Gen2);
El procedimiento S; gui enteGenerac i n tiene la siguiente estructura
cuando se aplica al clculo de Gen 2 a partir de Gen1:
for i := 1 to 8 do
for j : = 1 to 8 do
case Vecinos<Gen1, i, j) of
{sobrevivir: poner a on la celda i, j de Gen2}
{nacimiento: poner a on la celda i, j de Gen2}
{muerte: poner a off la celda i, j de Gen2}
end
Donde se han establecido informalmente las distintas alternativas para evitar
detalles innecesarios para este paso.
Obsrvese que los papeles de Gen1 y Gen2 sern los opuestos cuando se
produzca el cambio de poblacin siguiente de la generacin 2 a la 3. Es decir,
para la generacin 3 habr que borrar el entramado Gen1 y recalcular sus
celdas a partir de los valores actuales de Gen2. Por tanto, para valores impa-
res del nmero de generacin (1, 3, 5, Yasi sucesivamente), el entramado Gen1
mostrar la nueva generacin, y para valores pares (2, 4, 6, ..., etc.). Este papel
lo jugar Gen2. Debido a esta alternancia de papeles, Gen1 y Gen2 deben ser
parmetros en la implementacin de las rutinas BorrarGri d, Si gui ente-
Generacin y Vecinos.
Paso 4: Definicin de abstracciones. A continuacin, resumimos las abstrac-
ciones nuevas ms importantes que son necesarias para este programa:
procedure Inicializar<var G: Grid);
{pre: entrada = n, x" y" X
2
, Y2' -, x
n
, Y
n
}
{post: todas las celdas de Gque corresponden a los pares de enteros
Xi' Yi se ponen a on, para todo i in 1, .. "' n, A entrada = vacia}
procedure BorrarGrid<var A: Grid);
{post: todas las celdas del Grid A se ponen a off}
192 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
function Vecinos(G: Grid: i, j: integer): integer;
{post: resultado ~ el nmero de vecinos vivos de la celda i, j
del grid G}
procedure SiguienteGeneracin(A: Grid; var B: Grid);
{post: entramado B= nueva generacin de celdas vivas, calculadas
del entramado A uti l izando las cuatro reglas de nacimiento,
supervivenci a,Y muerte}
El resto de las abstracciones pueden implementarse directamente a partir de
los procedimientos y funciones generales disponibles para los entramados.
Etapa 5: Codificacin. El cdigo de este programa se muestra en varios frag-
mentos. El cuerpo principal del programa puede verse en la Figura 6.4. Es
bastante autoexplicativo, puesto que se ha obtenido a partir de las etapas
previas de la metodologa MAPS.
program vi da;
uses
Grids;
var
Gen1, Gen2: Grid;
control: char;
Gennumero: integer;
begin
{pre: entrada = n, X
1
, y" x
2
' Y2' , x
n
, Y
n
, C
1
, e
2
, .... , Cm 1\ C
lII
= Iql A
n > O 1\ m> Opa ra todo i in {1, . , n}: 1 <:; x;, y; <:; 8}
{Paso 1. Inicializar Gen1 y Gen2}
WriteLn( 'El juego de la Vida');
StarsGrids;
SetUpGrid(Gen1, 8,10,10, 10};
SetUpGrid(Gen2, 8, 120, 10, 10};
Inicializar(Gen1);
{Paso 2. Leer una orden de control}
gennmero:= 1; {lleva el control del nmero de generacin}
WriteLn( 'pulsar <RET> para ver la generacin', gennumero + 1 :3);
WriteLn( 'pulsar "q" para terminar');
Read(control);
while control <> 'q' do
begin
{Paso 3. Calcula y visualiza la generacin siguiente}
if gennumero IIOd 2 = 1 then
begin
BorrarGrid(Gen2); {las generaciones pares en el grid derecho}
SiguienteGeneracin(Gen1, Gen2);
end
else
begin
BorrarGrid (Gen1 ); {las generaciones impares en el gri d i zqui erdo}
SiguienteGeneracin(Gen2, Gen1);
end;
Robustez y prueba de los algoritmos 193
{Paso 4. Leer una orden de cont ro l )
gennmero + 1;
WriteLn( 'pulsar <RET> para ver la generacin', gennumero + 1 :3);
WriteLn( 'pulsar' 'q" para terminar');
Read(controL> ;
end
{post: salida = una serie de m-1 imgenes del Juego de la Vida,
donde la primera imagen est determinada por las n celdas
(x" y,), (x" y,) , (x
n
, Yn)' y cada imagen sucesiva presenta
la i-sima generacin que se obtiene de la (i - 1)-sima al aplicar
las reglas de nacimiento, supervivencia y muerte. El final del
juego lo provoca el usuario pulsando 'q' (de 'quit').)
end
Figura 6.4. Cuerpo del programa principal del programa Vi da.
Obsrvese que el paso 3 tiene dos partes alternativas. Una que se ejecuta al
calcular una generacin par, y la otra al calcular una impar. Esto se obtiene
directamente de la idea de los papeles invertibles de los entramados Gen1 y
Gen2. La variable gennumero lleva la cuenta de la generacin que se est
calculando y visualizando.
Las rutinas nuevas que se utilizan en este programa se muestran a conti-
nuacin. La primera es la rutina 1ni e; aL; za r, que se muestra en la Figu-
ra 6.5. Simplemente pone a on cada celda del entramado Gque se indica por la
fila y columna.
procedure Ini c i a l i zar (val' G: Gr i d);
val'
k, n, i, j: integer;
begin
{pre: entrada =0, x" y" X
Z
, Y2' a , X
n
, Y
n
}
Writeln('Introducir el nmero n de celdas inicialmente vivas:');
Read(n);
Writeln(' Introducir una serie n de pares de enteros');
Writeln('indicando cada uno las coordenadas x, y de una celda
vi va. ' );
for k : ~ 1 to n do
begin
repeat
read(i, P;
until (1 <= i) and (i <= GridSize(G and
(1 <= j) and (j <= GridSize(G;
TurnCellOn(G, i, j);
end;
{post: todas las celdas de Gque corresponden a los pares de enteros
Xi' Yi se ponen a on para todo i in 1, .. , n /\ entrada = vaca)
Figura 6.5. La ruti na 1ni e i a l iza r.
194 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Adems, obsrvese que el procedimiento IniciaLizar lee reiteradamente
pares de enteros i, j hasta que el par represente una celda vlida del entra-
mado G. Es decir, si i o j estuvieran fuera de rango de filas y columnas de G, el
par se vuelve a leer. Esto es un ejemplo de la construccin de programas
robustos y amigables.
'
La segunda rutina, 80 r ra rG r id, realiza la sencilla tarea de poner a off
todas y cada una de las celdas del entramado G. Esto se muestra en la Figu-
ra 6.6.
p..ocedu..e Bo.... a .. Gr-id (va.. A: Grid);
(post: todas las celdas del Gr-id A se ponen a off}
va"
i,j:intege.. ;
begin
fa.. i := 1 to Gr-idSize(A) do
fo.. j := 1 to GridSize(A) do
Tu.. nCellOfHA, i, j)
end;
Figura 6.6. La rutina BorrarGrid.
La rutina Vec i nos, de la Figura 6.7, cuenta el nmero de vecinos vivos
para la celda i, j del entramado G. Obsrvese que se considera vecina a
cualquier celda viva a la que se acceda directamente desde la celda i, j por
uno de sus cuatro lados, o por una de sus cuatro esquinas. Por tanto, cada
celda puede tener como mximo ocho vecinas. Sin embargo, las celdas que se
encuentran en los bordes del entramado Gtienen menos de ocho vecinos. Por
ejemplo, la celda 1,1 no tiene ms que tres vecinos, y la celda 1,2 no tiene
ms que cinco. Para asegurarnos de que la rutina calcula valores correctos
para esos casos, debemos saber que la rutina Ce LLOn (k, L>, que se suminis-
tra con el tipo Grid, devuelve el valor faLse siempre que el par k, L no se
corresponda con una celda de G. Por ejemplo, si k = O o L= O Ce LLOn (k,
L) = fa Ls e. Podemos cerciorarnos de esto viendo la especificacin de la
rutina CeL LOn (vase Apndice D).
function Vecinos(G: grid; i, j: integer): integer;
var
k, l, con t: i nt ege r;
begin
cont := O;
for k : = i - 1 to i + 1 do
for l := j - 1 to j + 1 do
if CellOn(G, k, l) and not ((k ~ i) and (L = j then
cont := cont + 1;
Vecinos := cont
: post: resul tado = eL nmero de vecinos vivos de la celda i, j del grid G:
Figura 6.7. La rutina Vecinos.
Robustez Vprueba de los algoritmos 195
Finalmente, la rutina Si gui enteGeneraci n (vase Fig. 6.8) calcula las
celdas vivas para la siguiente generacin del entramado B, a partir de la gene-
racin actual del entramado A. Incluye una interpretacin detallada de las
cuatro reglas de supervivencia, nacimiento y muerte.
Etapa 6: Prueba. Para probar este programa suficientemente, necesitamos
disear una serie de asos de prueba, que no slo prueben el Juego de la Vida
para unas configuraciones iniciales inusuales, sino tambin otras que suminis-
tren datos de entrada no vlidos. Queremos asegurar que nuestro programa es
tan robusto como correcto. Un paso inicial es ejecutar el programa para una
entrada conocida, tal como la de la Figura 6.2. Producir el programa la
salida correcta para la generacin 2?, y para la 3 y sucesivas?
A continuacin, debemos probar el programa con otras entradas, especial-
mente aquellas que representan poblaciones con una evolucin fcil de prede-
cir, tal como la que se muestra en la Figura 6.9. Esta configuracin es intere-
sante porque prueba la correccin del programa cuando las celdas vivas
ocupan los bordes.
procedure SiguienteGeneracin (A: Grid; var B: Grid);
var
i, j, cont: integer;
begin
for i := 1 to GridSize(A) do
for j : ~ 1 to GridSize(A) do
case Vecinos(A, i, j) of
{RegLa 1. Supervivencia}
2, 3:
if CeLLOn(A, i, j) then
TurnCeLLOn(B, i, j)
{RegLa 2. Nacimiento)
else if (Nacimiento(A, i, j) = 3) and
(CeLlOff(A, i, j))
then TurnCellOn(B, i, j);
{Regla 3. Muerte por soLedad)
O, 1 :
if CellOn(A, i, j) then
TurnCellOff<B, i, j);
{Regla 4. Muerte por superpobLacin}
4,5,6,7,8:
if CeLLOn(A, i, j) then
TurnCeLLOff(B, i, j);
end
{post: entramado B =nueva generacin de ceLdas vivas, caLcuLadas
del entramado A utiLizando Las cuatro regLas de nacimiento,
supervi venci a y muerte}
end;
Figura 6.8. La rutina SiguienteGeneracin.
Etapa 7: Presentacin. La presentacin del programa est completa cuando se
ha preparado un esbozo de su propsito general, junto con un listado del
196 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
propio programa y con las salidas de algunas ejecuciones como ejemplo. El
esbozo debe contener no slo un resumen de lo que hace el programa, sino
tambin de cmo trata las situaciones excepcionales, junto con otras limitacio-
nes que el usuario se pueda encontrar.
a) b)
Figura 6.9. Un caso de prueba diferente para el Juego de la Vida.
a) Primera generacin. b) Segunda generacin.
Ejercicio
6.6. Obtener a mano las generaciones 2 y 3 para las generaciones iniciales
siguientes.
a) b) e)
6.4. GARANTA DE LA ROBUSTEZ: DISEO DE CASOS
DE PRUEBA
La metodologa de resolucin de problemas MAPS proporciona una estructu-
ra que, si se manipula cuidadosamente, puede conducirnos a la obtencin de
programas robustos -programas que no slo funcionan ben para entradas
correctas, sino que tambin se comportan elegantemente para un amplio
Robustez y prueba de los algoritmos 197
rango de entradas incorrectas-o Una etapa fundamental de la metodologa
MAPS es la etapa 6, o etapa de prueba y verificacin. Esta es una etapa que, en
nuestro camino, puede que sea la ms critica de todo el proceso. Si un progra-
ma resulta no ser correcto como resultado de la aplicacin sistemtica de
mtodos de prueba y/o verificacin, todas las etapas anteriores de la metodolo-
ga MAPS habrn sido intiles. En las Secciones 6.4 y 6.5 introduciremos
mtodos esp::cificos para llevar a cabo en esta importante etapa de prueba y
verificacin. La discusin de estos temas concluye con una evaluacin compa-
rativa de la utilizacin de ambos mtodos en la construccin del software.
Un conjunto ya clsico de tcnicas para asegurar la correccin, robustez y
amigabilidad de los programas, se incluye bajo el nombre genrico de prueba.
Las tcnicas de prueba han sido desarrolladas por diseadores e ingenieros del
software durante las ltimas dcadas.
Definicin. La prueba de un programa es la aplicacin sistemtica de casos
de prueba al programa, procedimiento o funcin, con el objetivo de detec-
tar y corregir los errores (o fallos) del programa. Los casos de prueba
consisten en distintos conjuntos de valores de entrada, elegidos intenciona-
damente para analizar el comportamiento del programa bajo unas condi-
ciones que pueden o no haber sido sugeridas por el diseador del progra-
ma. Conjuntamente, todos los datos que estn incluidos en esas pruebas
reciben el nombre de juego de pruebas.
El resultado de la prueba ofrece menores garantas que la de la verificacin. Es
decir, la prueba, por su naturaleza limitada, no asegura la ausencia de errores
-slo puede poner de manifiesto los errores presentes.
Para que sea eficaz, la prueba debe realizarse por una persona distinta a la
que construy el programa. Esto es importante, porque una persona ajena
puede ser bastante ms objetiva sobre el comportamiento del programa que la
persona que lo ha desarrollado.
Existen varias formas de disear juegos de prueba y de aplicarlas a un
programa o a un procedimiento concreto. Son necesarias estrategias de prueba
ms largas cuando se trata de probar programas construidos con extensos
conjuntos de instrucciones, que cuando tratamos de probar casos de estudio.
En esta seccin nos concentraremos en el diseo y aplicacin de mtodos de
prueba rigurosos para programas relativamente pequeos, dejando para el
Volumen II de esta serie los mtodos de prueba del software de gran escala.
6.4.1. Ejemplo: Prueba de un procedimiento o funcin
completos
Cuando desarrollamos una abstraccin procedimental para un problema bien
definido, o para una rutina, es necesario probarla ejecutando el procedimiento
suministrndole una amplia gama de valores a los parmetros de entrada, y
198 Computacin l. Lgica, resolucin de problemas, algoritmos V programas
asegurndonos de que, en cada caso. el resultado del procedimicnto es consis-
tente con sus poscondiciones.
Puesto que es imposible probar (odos los posibles valores de entrada. ten-
dremos que seleccionar un subconjunto de ellos que sea significativo, y ejecutar
el programa e imprimir el resultado con cada uno de los elementos de ese
subconjunto. Una forma bastante til de realizar este proceso es construir un
programa cO/lductor. Se denomina as porque, literalmente. guia la ejecucin
e impresin de resultados del procedimiento o funcin con los valores seleccio-
nados para la prueba.
Ilustremos estas ideas construyendo un juego de pruebas para la funcin
MaxL i sta (vase Figura 5.12). Cul seria un conjunto de pruebas apropiado
para esta funcin, y cmo podemos disear un conductor para estudiar el
comportamiento de MaxLi sta frente a estos datos?
Los juegos de prueba pueden crecer rpidamente. Consideremos el nmero
total de posibles entradas vlidas que podramos construir para la funcin
MaxLi sta, utilizando O ms elementos. Supongamos que cada elemento es
un entcro en el rango - 2':; al 2':; - 1, habrn 2\6 = 65.536 listas diferentes
de un solo elemento. El nmero de posibles listas diferentes de /l elementos
resulta astronmico --seguramente excesivo para incluirlas en un juego de
pruebas.
Pensemos un momento sobre algunas posibles listas que pueden ser pasa-
das a MaxLista. y a lo que esperamos que MaxLista produzca como res-
puesta. En la Tabla 6.2 se ofrecen algunas ejemplos obvios.
Tabla 6.2
Parmetros de entrada L
(3 1 2 8)
(8 1 2 3)
(3 8 1 2)
(-1 23 -8)
(3 1 2 8)
(3 1 2 8)
(3 2 8)
m
4
4
4
4
3
2
Resultado esperado
4
2
Los dos primeros datos de pruebas son importantes porque el valor mximo
ocupa la ltima y primera posicin de la lista. respectivamente. El tercer caso
tambin es importante. pues representa el caso tpico que puede ocurrir---es
Robustez y prueba de 105 algoritmos 199
decir, el valor mximo ocupa una posicin cualquiera entre el primero y el
ltimo elemento de la lista--. El cuarto comprueba si MaxLi s ta trabaja
correctamente con valores negativos. Los tres ltimos son importantes, puesto
que restringen el valor de mforzando a la funcin a buscar el mximo en una
sublista.
Pero, qu otras cosas deben introducirse en un juego de p r u e b a s ~ Eviden-
temente, debem9s asegurarnos de que la lista vaca ( ) devuelva el valor O.
Qu hacer con los otros incontables casos que se nos pueden presentar?
Cmo presentar a MaxLi sta un subconjunto de esos casos que nos asegure
que el procedimiento hace lo que debe? As mismo, cmo podcmos probar la
robustez y amigabilidad de Ma xLi s ta? Es decir, cmo se comportar Ma x-
Lista con entradas como la lista (-1, -2, hoLa, -8)? ante un valor
de L, como I hoLa I o I asrtfadesr I o 3332123442 que no sean una
lista? Debemos aadir todos esos casos a nuestro juego de pruebas para deter-
minar cmo responde MaxLi sta.
Por tanto, debemos ser muy selectivos al disear los juegos de prueba
para un procedimiento. Slo debemos incluir en los juegos de pruebas aquellas
entradas que representen a un gran nmero de casos posibles. Es conveniente
almacenar aparte nuestro juego de pruebas en un archivo de disco, de forma
que no necesitemos reescribirlo cada vez que queramos probar el procedi-
miento.
En la Figura 6.10 se muestra la estructura general dc un conductor de
pruebas. En la notacin utilizada <p (x, y) > simboliza a un procedimiento p
con parmetros de entrada x y parmetros de salida y; <archivo juegos
prueba> simboliza al archivo del que se pueden obtener los juegos de prueba.
Esta estructura es fcilmente adaptable para el caso en que lo que deseemos
sca probar una funcin f (x) en lugar de un procedimiento p (x, y); en este
caso la variable y se identifica con la salida de la funcin, la instruccin <p (x,
y se sustituye por y := f(x) en el conductor de la Figura 6.10, y los
comentarios se modifican para indicar que se prueba una funcin en lugar de
un procedimiento.
program conductor;
(Este programa conductor prueba eL procedimiento <p(x, y}
{ut i Lizando un juego de pruebas como datos de ent rada}
(deL archivo <archivo juego pruebas>}
procedure <p(x, y;
begin
end;
var <variabLes correspondientes a Los parmetros>;
<archivo juego pruebas>: text;
begin
WriteLn(' Comi enza La prueba deL procedimi ento <p(x, y');
readarchivo juego pruebas, <x;
while not eofarchivo juego pruebas do
200 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
beg;n
WrHeLn('Parmetros de entrada = " <x;
<p(x, y;
Wr; teLn(' Resul tado de p(x, y) =' , <y;
readarch;vo juego pruebas>, <x;
end;
WrHeLn( 'F;nal de la prueba del proced;m;ento <p(x, y')
end.
Figura 6.10. Estructura general de un conductor de pruebas.
Supongamos que se quiere probar la funcin MaxL; sta utilizando un
programa conductor y el archivo de juegopruebasmax que contiene las
listas siguientes:
(3 1 2 8) 4
(8 1 2 3) 4
(3 8 1 2)
4
(-1 -2 -3 -8) 4
(3 1 2 8) 3
(3 1 2 8)
2
(3 1 2 8) 1
(-1 -2 hello -8) 4
()
O
Los enteros que aparecen a la derecha no estn almacenados en el archivo,
sino que son escritos por el usuario cuando el conductor se lo solicita. El
programa conductor siguiente podra ser eficaz:
program Conductor;
{Este prog rama conductor prueba la fune; n MaxU sta ut H ; zando un
juego de pruebas como datos de entrada del arch;vo juegopruebasmax}
function MaxUsta(L: Usta; m: integer): integer;
val' j, k: ;nteger;
begin
{pre: L = (e
1
, e
2
, _, e
m
, _, en) A n ~ O1\ cada e
i
es un nmero}
if (O < n) and (m <= LengthUsta(L then
begin
j := 1;
for k := 2 to mdo
{; nv: v; E {1, ... , k - 1 }: e [j] >= e [;] /\ 2 <= k <= m+ 1 }
if L[k] > L[j] then
j := k;
end
else
j := O;
MaxUsta := j;
( pos t: n > O /\ v; E {1, ... , n}: e j ;;O e, /\ re su l tado = j v
n = 0/\ resul tado = O}
end;
Robustez y prueba de los algoritmos 201
varL: Lista;
m, j: integer;
juegopruebasmax: text;
begin
WriteLn( 'Comienza la prueba de la funcin MaxLista(L, m)');
WriteLn('Introducir el nombre del archivo del juego de pruebas: ');
ReadLista(U;
while not eof(juegopruebasmax) do
begin
WriteLn( 'Lista de entrada L ='); WriteLista(U;
Write(Introducir valor de m: '); ReadLn(m);
j := MaxLista(L, m);
WriteLn('Resultado de MaxLista(L, m) ~ " j);
ReadLista(U;
end;
WriteLn('Final de la prueba de la funcin MaxLista(L, m)
end.
La salida que produce este conductor cuando se le suministra el archivo j ue-
gopruebasmax se muestra en la Figura 6.11.
Comienza la prueba de la funcin MaxLista(L, m)
Introducir el nombre del archivo del juego de pruebas:
milista
Lista de entrada L =
(3 1 2 8)
Introducir valor de m: 4
Resultado de MaxLista(L, m) = 4
Lista de entrada L =
(8 1 2 3)
Introducir valor de m: 4
Resul tado de MaxLista(L, ro) = 1
i.. i sta de entrada L =
O
Int roduci r va lar de ro: O
Resultado de MaxLista(L, ro) = O
Final de la prueba de la funcin MaxLista(L, ro)
Figura 6.11. Resultado de ejecutar el conductor de pruebas para
la funcin MaxLista, con el archivo de entrada juegopruebasmax.
Como puede verse, la construccin y utilizacin de un conductor de prue-
bas es casi un proceso mecnico. Sin embargo, cuando se utiliza con cuidado,
no slo nos permite descubrir errores ocultos, sino que nos sugiere formas de
conseguir que el programa sea ms robusto y amigable. j Utilizar el procesa-
miento con un juego de datos desconocido puede conducirnos a resutados
sorprendentes! Sin embargo, es preferible realizar esos descubrimientos en el
momento de la prueba, que no despus, cuando se ha entregado el procedi-
miento a una persona desconocida para cualquier utilizacin.
202 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
6.4.2. Ejemplo: Prueba de un programa completo
Debemos probar los programas de abajo a arriba. Es decir, debemos probar
todos los procedimientos y funciones antes de probar el programa que los
utiliza. Despus de realizar esto, podemos proceder a la prueba del programa
completo en la misma forma en que probamos un procedimiento. Para cllo,
convertimos e' programa en una especie de autoconductor de si mismo, aa-
dindole un bucle externo que lea sistemticamente datos de entrada alternati-
vos desde un archivo externo que contenga un juego de pruebas, y despus
prosiga con su ejecucin normal, produciendo las salidas a todas las entradas
del juego de pruebas, en lugar de la salida de un nico juego de datos.
Por ejemplo, considrese el programa Ca Lcu La CM, de la Figura 4.6, el cual
modificamos para ser ms amigable (vase Seccin 6.1). Para probar este pro-
grama, podemos convertirlo en el autoconductor que se muestra ms abajo, y
ejecutarlo con los datos de el archivo que contiene varias listas de calificacio-
nes alternativas, en lugar de slo una. El resultado de convertir este programa
en amigable y en un autoconductor, se muestra en la Figura 6.12. Para conver-
tirlo en autoconductor, basta con aadirle un bucle repea t abarcando las pre
y poscondiciones del programa. Esta modificacin hace que el programa lea y
procese entradas hasta que lea una lista vacia 0, lo que seala el fin de las
ejecuciones de prueba.
program caLcuLaCM;
uses
Listas;
var
Notas: Listas;
i, n: integer;
Sum, CM: reaL;
entradavLida: BooLean;
beyin
repeat
{pre: entrada = (Notas" Notas" ... , Notas") 1\ n > O
1\ \1'i E {1, .""' n}: Notas, E (O, .. "' 4}}
repeat
WriteLn ('Introducir La Lista de caLificaciones:');
ReadLista(Notas);
n : ~ LongLista(Notas);
entradavL ida : ~ true;
for i : ~ 1 to n do
if not isNumeric(Notas[i] or Notas[i] < O) or (Notas[i] > 4) then
entradavLida := faLse;
until entradavLida;
if n > Othen
beyin
Sum : ~ O:
i := 1;
whi le i <= n do
begin
Sum := Sum + Notas[i];
Robustez y prueba de los algoritmos 203
i := i + 1
end
CM = Sum/n;
WriteLn('La CM de esas caLificaciones es=', CM: 5: 2)
end {i f}
{post entrada =0"
saLida=Sumi E {1, ... ,n}:Notas;ln}
untiL n ~ O;
end.
Figura 6.12. Un autoconductor para la versin amigable del CaLcuLaCM.
6.5. GARANTA DE CORRECCiN: VERIFICACiN
DE PROGRAMAS
Como metodologa general, la verficacn de programas tene como objetvo
la aplcacn de la lgca matemtica, para demostrar formalmente que el
programa incluido entre la precondicn y la poscondicin cumple esas especi-
ficaciones bajo cualquier circunstanca de ejecucin posible. En este sentido, la
verificacn formal es un logro relativamente nuevo en el rea del software.
Pienso que es importante tener unos conocimientos bsicos de la verificacin
formal, sus mtodos y sus objetivos. De todas formas, esta materia est en un
punto de corte de la investigacn en informtica. La verificacin de progra-
mas proporciona a los lectores un punto de vista alternativo sobre la correc-
cin de los programas, que pone de manifiesto uno de los mayores defectos de
las tcnicas de prueba clsicas: stas nunca garantizan la correccin.
El estilo de verificacin que utilizaremos es informal, resaltando los funda-
mentos ms que explicando el proceso de demostracn con mucho detalle.
Partimos de la hiptesis de que las propiedades algebraicas de los nmeros,
con las que estamos familiarizados, se preservan cuando se utilizan los nme-
ros en programacin. Sabemos que es una restriccin bastante fuerte. Sabe-
mos, por ejemplo, que en los nmeros -reales o enteros- no tiene una repre-
sentacin exacta en los programas Pascal. Sabemos tambin que, en
matemticas, las operaciones entre reales y enteros siempre producen resulta-
dos exactos, mientras que en computacin se introducen a veces pequeos
errores. Para el propsito de esta introduccin, ignoraremos estas pequeas
desviacones, con objeto de simplificar la presentacin de la verificacin y
centrarnos en los principios y en la metodologa.
6.5.1. Tableau de demostracin
Para verificar un programa, desarrollamos una prueba del tableau. Un comien-
zo de prueba del tableau, o tableau vaco, es un listado del programa con sus
precondiciones, poscondiciones y comentarios vacios antes y despus de cada
204 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
instruccin, tal y como se muestra en la Figura 6.13. El objetivo de la verifica-
cin es rellenar este tableau con asertos vlidos. Cada instruccin del progra-
ma debe preceder y seguir a un aserto, y debemos demostrar, siguiendo una
lnea sistemtica de razonamiento, que la instruccin conduce de una situacin
que satisface el aserto que le precede al que le sigue, partiendo de otros cuya
validez ya ha sido demostrada. As, la verificacin de un programa es un
proceso en el que se desarrollan una serie de asertos (y razonamientos que les
acompaan) en una forma similar al de las demostraciones de la lgica (como
vimos en el Captulo 3). El resultado de este proceso se denomina demostracin
de la correccin del programa, o simplemente demostracin.
El proceso por el que descubrimos sistemticamente la validez de los aser-
tos que componen una prueba, se le denomina razonamiento sobre programas.
Podemos definir esas ideas ms formalmente como sigue:
Definicin. Una demostracin es un conjunto de asertos P
1
, P
u
... ,
Pr>+1' que, cuando se insertan sucesivamente entre las instrucciones 51' Su
, sn en un tableau vaco, dan origen a la siguiente prueba de tableau:
begin
(precondiciones}
{P,}, 5,; {P
2
}, 52; ; {Pn}' Sn; {P
n
+,}
(poscondiciones}
end
Donde los asertos siguientes son vlidos (es decir, tautologas):
1. precondi ciones =<> P,
2. {P;}, s,, (P'+1} para todo i en (1, . , n}
3. P0+' =<>poscondi ciones
La notacin {P;} s; {PH1} quiere decir que, respecto de la ; -sima ins-
truccin del programa, si P; es vlido antes de la ejecucin de S;, el aserto
P
H1
ser vlido despus de la ejecucin de s;. En otras palabras, Pi y P
H1
son, respectivamente, precondicin y poscondicin de la instruccin s;.
Supongamos que tenemos el programa y el tableau vaco de la Figura 6.14. Es
decir, queremos demostrar la correccin del programa que se ha diseado para
calcular y escribir el resultado del producto de dos nmeros cualquiera n
1
Yn
2
.
Para completar la demostracin, necesitamos descubrir y justificar los aser-
tos p1 al P4 del tableau, uno a uno, hasta rellenarlo. El resultado se muestra en
la Figura 6.15. Las justificaciones que aparecen en la columna de la derecha de
la Figura 6.15 son el resultado de aplicar equivalencias lgicas y reglas de
inferencia a la secuencia de instrucciones de Pascal. Algunas de esas justifica-
ciones (por ejemplo, aritmticas) se basan en las hiptesis comunes que se
suelen realizar en la aritmtica. Otras (por ejemplo, A -introduccin) se han
tomado de las reglas de inferencia de la lgica (vase Captulo 3). Otras (por
Robustez y prueba de los algoritmos 205
begin
(pre: precondicin)
5,;
(post: poscondicin);
Figura 6.13. Aspecto inicial de una prueba de tableau: el tableau vaco.
ejemplo, la regla de la asignacin) reflejan las propiedades de algunas instruc-
ciones de Pascal (vanse Secciones 6.5.2 a 6.5.5), y las estudiaremos en este
captulo.
La demostracin completa del tableau refleja el estilo de las demostraciones
de la lgica, tal como se vio en el Captulo 3.
begin
{pre: entrada = n1, n2 /\ salida =0l
( @)
Read (x, y);---
{ @
z:=x*y; ~
{ @Y
Write (z) ----
( )
{post: entrada =0/\ salida = n1 * n2
end.
Figura 6.14. Tableau vaco para un sencillo programa de tres instrucciones.
206 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
6.5.2. La regla de inferencia de la asignacin
Al igual que otros mtodos de demostracin, la verificacin de programas
utiliza los axiomas y las reglas de inferencia. Las reglas de inferencia son
generalizaciones sobre el comportamiento de determinados tipos especificos de
instrucciones de los programas en Pascal. Estas reglas aportan mtodos con
los que derivar asertos nuevos, a partir de otros existentes, para algunas ins-
trucciones especficas.
begin
{pre: entrada n1, n2 /\ salida =0}
n2 }
QY Read (x, y);.. @
[entrada =0/\ x = n1 /\ y = n2 /\ x*y = n1*n2)
@
{x = n1 /\ y = n2 /\ z = n1 *n2 /\ sa l i da = 0
Write (z) .. @
{z = n1 *n2 /\ sa l i da = n1 *n2 }
{post: entrada =0/\ salida n1 * n2 }
Jus! Cica! iuus
{A-eLiminacin
i regla de la asignacin,
aritmtica,
/\-introduccin}
{regla de la asignacin,
A-eliminacin,
/\-introduccin}
{regla de la asignacin,
/\-el iminacin}
{/\-eliminacin,
/\-introduccin}
Figura 6.15. Prueba del tableau completa
para un programa sencillo.
En la verificacin formal de programas, el sistema de inferencias, y concre-
tamente las reglas de inferencia, son mucho ms complicadas que las que se
han presentado aqu. Consideremos cuatro reglas de inferencia bsicas para los
programas: la regla de la asignacin, la regla de los procedimientos, la regla de
las condicionales y la regla de los bucles.
Definicin. La regla de inferencia de la asignacin.
a) {P(e)} v := e { }
{P(e)} v := e {P(v)}
b) {entrada n} Read(v) { }
[entrada n} Read(v) {entrada = 0 /\ V = n}
e) [salida=0/\e=n} Write(e):}
[salida /\ e = n) Write(e) {salida = e}
Robustez y prueba de los algoritmos 207
El apartado a) de esta regla dice que si una proposicin es vlida para el
estado de una expresin e (la satisface) antes de que la instruccin de
asignacin v : = e sea ejecutada. Podemos inferir que la misma proposi-
cin es vlida para la variable y despus de la ejecucin de la asignacin.
Los apartados b) y e) simplemente destacan el hecho de que las instruc-
ciones Read y Wr; te producen el mismo efecto que la asignacin. En la
instruccin .Read, el origen del valor para la asignacin es el flujo de
entrada, y el receptor la variable v. En la instruccin Wr; te, el origen del
valor es la expresin e, y el destino el propio flujo de salida. Ms concreta-
mente, el apartado b) significa que la instruccin Read retira un valor n del
flujo de entrada, y se lo asigna a la variable v. El apartado e) indica que la
instruccin Wri te(e) aade una copia del valor n, que actualmente es el
resultado de evaluar la expresin e, al flujo de salida. Esto no es ms que
una formalizacin directa de lo que ya conociamos de la actuacin de
Read y Wr; te en nuestros programas.
Por ejemplo, en el programa de la Figura 6.14, supongamos que lo nico
que conocemos antes de la ejecucin de la instruccin de asignacin z : = x * y,
es que los valores de x e y son dos nmeros n1 y n2. Por las reglas de la
aritmtica, tambin sabemos que x * y = n1 * n2. Podemos utilizar estos
conocimientos en la forma siguiente:

z:=x*y;
{z=n1 *n2} {regLa de La asignacin}
Lo nico que hemos hecho, al realizar esta inferencia, ha sido poner z en todas
las ocurrencias de x * y en la proposicin ya conocida P(x * y) para poder
obtener P(z >. Obsrvese que se ha marcado esta inferencia de la demostra-
cin, con una justificacin situada a la derecha, para clarificar las razones de la
inferencia realizada. Esto es consistente con el estilo de las demostraciones de
la lgica.
Est claro que esta regla es fcilmente extensible para instrucciones Read y
Wr; te, con ms de una variable, para las instrucciones ReadLn, Wr; tLn,
ReadL; sta y Wr; teL; sta, y as sucesivamente. Por simplicidad, no re-
cargaremos esta regla tratando de formalizarla para todas esas situaciones,
aunque la utilizaremos en nuestras demostraciones como si lo hubiramos
hecho.
Como ejemplo adicional, consideremos la primera instruccin del progra-
ma de la Figura 6.14, para la que se cumple lo siguiente cuando razonamos
sobre ella:
{ent rada n1, n2)
Read(x, y);
{ }
20S Computacin l. Lgica, resolucin de problemas, algoritmos y programas
La parte b) de la regla de la asignacin nos permite escribir la inferencia
siguiente:
(entrada = n1, n2]
Read(x, y);
{entrada =0/\ x = n1 /\ y ~ n2} {regla de la asignacin}
Lo que justifica formalmente que se les asignan valores a x e y, utilizando la
instruccin Read, y los valores son eliminados, simultneamente, del flujo de
entrada.
De forma similar, podemos razonar sobre la instruccin Wr i te, de la
Figura 6.14, utilizando el apartado e) de la regla de asignacin. Comencemos
con:
{z = n1 * n2 /\ sal ida =0}
Wr ite (z);
{
Lo ms importante de esta inferencia es que z debe tener el valor n1 * n2,
para que dicho valor pueda aparecer en el flujo de salida. Podemos escribir
esta conclusin formalmente utilizando la regla de la asignacin de la forma
siguiente:
{z = n1 * n2 /\ sal ida =0}
Write(z);
{salida=n1 *n2} {regla de la asignacin}
El razonamiento sobre programas siempre requiere que utilicemos activa-
mente nuestros conocimientos sobre aritmtica, aunque no reflejemos los deta-
Hes de este conocimiento durante el proceso de la demostracin. Aqui presen-
tamos otro ejemplo. Supongamos que sabemos que el valor de la variable i es
no negativo, inmediatamente antes de que se ejecute la asignacin i := i + 1
en un programa. Cmo nos puede ayudar la regla de la asignacin a razonar
acerca de esto? Formalmente comenzamos con:
{i ~ O]
i:=i+1;
{i > Ol {Regla de la asignacin, aritmtica}
Si analizamos detenidamente los detaHes de esta asignacin, descubriremos
que si i ?> O, antes de la asignacin, entonces ; + 1 ?> 1. As, para utlizar la
regla de la asignacin identificamos las variables v e i + 1 con la expresin e,
y el aserto P(e) con i + 1 ?> 1. Por todo ello, podemos inferir P(v) o i ?> O.
Aplicando de nuevo las reglas de la aritmtica, podemos reescribir el aserto
slo en trminos de la variable i, lo que nos conduce a i > O.
Robustez y prueba de los algoritmos 209
6.5.3. Reutilizacin de las reglas de inferencia de la lgica
Cuando escribimos la demostracin de un programa, adems de las reglas que
definen el comportamiento del programa y la aritmtica, utilizamos las reglas
de inferencia de la lgica que estudiamos en el Capitulo 3. Esas reglas nos
permiten mover los asertos a lo largo del programa, lo que permite utilizar-
los para escribir nuevas inferencias en otros puntos del programa. Por tanto,
podemos conseguir una lnea de razonamiento coherente que incluya a todo el
programa, desde el principio hasta el final.
Para ilustrarlo, consideremos el programa de la Figura 6.15. Obsrvese
cmo se utiliza la regla de la asignacin para construir ciertas partes de los
asertos del P1 al P4' Pero, qu ocurre con sus interconexiones? Por ejemplo,
cmo justificar la migracin del aserto ent rada = 0 desde P
2
, donde se
origina, saltndose P
3
y P4' Yapareciendo finalmente en la poscondicin donde
se necesita para que la prueba est completa? Aunque la regla de la asignacin
no nos permite realizar esta migracin, las reglas de inferencia de la lgica, s.
El primer paso de la demostracin de la Figura 6.15 contiene el aserto P
1
{ent rada = n1, n2}
que se infiere de la precondicin, utilizando la /\ -eliminacin
{ent rada = n1, n2 " sa l i da =0}
La derivacin de P
2
es el resultado de la combinacin de tres pasos diferentes:
la regla de la asignacin, las propiedades de la aritmtica, y la regla de in-
ferencia de la 1\ -introduccin. En concreto, la proposicin x*y = n1 *n2
aparece en P
2
como preparacin para la derivacin de los asertos P
3
de P
2
y S2'
Las reglas de la /\ -introduccin y de la /\ -eliminacin se utilizan tambin
a lo largo de la prueba. Sin embargo, esas reglas de inferencia deben aplicarse
con cuidado cuando el predicado que se va a aadir viene de una posicin
distante del programa. Por ejemplo, considrese la reintroduccin del aserto
sa l i da =0 en la proposicin P3 despus de haber desaparecido de las propo-
siciones P
1
y P
2
. Esto es posible hacerlo si en el programa no se han ejecutado
instrucciones que invaliden este predicado: es decir, alguna instruccin Wr i te
(o, de forma equivalente, alguna aplicacin del apartado e) de la regla de
asignacin) entre la ltima posicin en que el predicado era vlido y la instruc-
cin donde se reintroduce.
6.5.4. Reglas para las condicionales
Los programas incluyen otros tipos de instrucciones, aparte de las que asignan
valores a las variables. Cuando se pretenden escribir demostraciones sobre los
programas, es necesario conocer axiomas para poder razonar sobre selecciones
210 Computacin l. Lgica, resolucin de problemas, algoritmos Vprogramas
condicionales (instrucciones i f), invocaciones a procedimientos y funciones
sobre bucles. Existen reglas de inferencia que son aplicables a estas instruccio-
nes.
Definicin. La regla de inferencia de la seleccin condicional.
a) ;P 1\ 6} 5 {Q)
PI\-6o>Q
{Pi if 6 then 5 {Q)
b) {P 1\ 6) 5, {Q }
{P 1\ -6) 5, {Q )
{Pi if 6 then 5, el5e 5, {Q}
El apartado a) permite inferir la validez de Q tras la ejecucin de la selec-
cin condicional, si podemos inferirla independientemente de cul alterna-
tiva se haya seguido -en una tanto, P como B son verdaderas, y se ejecuta
la instruccin s; y en la otra, B es falso, y P =Q es tambin vlido-o El
apartado b) es simplemente una extensin del a), en la que se establece la
validez de q, independientemente de cul de los dos caminos alternativos se
haya seguido -ejecucin de S1 (cuando B es ve rdade ro), o la de S2
(cuando B es fa Lso).
Consideremos las asignaciones y seleccin condicional siguientes, que se
han diseado para asignar a la variable z el mayor de los valores x o y:
z := x;
if x < ~ y then
z : ~ y
Para verificar esto, tenemos que establecer la validez del aserto Q:
Q = {z = X 1\ X > y v z ~ y 1\ X < ~ y)
Que es una manera ms formal de describir la salida que deseamos para z. Las
inslrucciones de asignacin y la seleccin condicional estn en secuencia, por
lo que necesitamos utilizar, en el proceso de verificacin, tanto la regla de la
asignacin como la de la seleccin condicional. Por tanto, podemos comenzar
con lo siguiente:
I 1
, J
Z := x;
{z = x}
if x < ~ y then
z := y
{x > y 1\ Z = X v X <= Y 1\ Z = y)
Utilizando la regla de la asignacin, podemos identificar P como z = x (la
validez de P se deduce de la linea anterior a l y de la regla de la asignacin), y
B como x <= y. Por tanto, tendremos que demostrar ahora la validez del
Robustez y prueba de los algoritmos 211
aserto Q para completar la demostracin. Sustituyendo por B, P Y Q sus
valores en la regla de la seleccin, obtendremos:
{z ~ X /\ X <= y} z : = y (z ~ X /\ X > y v z = y /\ X <= y) /\
{z = X /\ ~ ( x <= y) "'" z ~ X /\ X > y v z = y /\ X <= YJ
Para demostrar la validez del aserto anterior, consideramos los dos casos
x <= y Y~ ( x <= y) que, como sabemos por aritmtica, son los nicos posibles.
Cuando x <= y la linea 1 es vlida, puesto que se realizar la asignacin
x : = y, y la regla de la asignacin garantiza que z = y. La regla de la
/\ -introduccin nos permite inferir z = y /\ X <= y, Yfinalmente, la regla de la
v -introduccin nos permite inferir z = x /\ x > y v z = Y/\ X <= y. La lnea 2
tambin es trivialmente vlida, puesto que ~ ( x <= y) es fa Lso y fa Lso =o> p
es siempre vlido para cualquier proposicin p.
En el segundo caso, x > y, la segunda lnea de la disyuncin de arriba es
vlida. Es decir, tanto ~ ( x <= y) (o equivalentemente, x> y) y z = x son
vlidos, por lo que lo es su conjuncin por la /\ -introduccin. Pero
z = X /\ ~ ( x : = y)
es equivalente a
z=x/\x>y
por lo que la lnea 2 completa tiene la forma de un aserto de tipo p =o> P V q,
que es vlido por la v -introduccin. La lnea 1 tambin es trivialmente vlida,
puesto que x <= y es fa Lso. Esto completa la justificacin para el aserto Q.
Considrese la alternativa siguiente para asignar a z el mayor de los valo-
res de x e y:
if x > y then
z := x
else
z := y
Para demostrar esto, es necesario establecer de nuevo la validez del aserto Q:
Q = {z = X /\ X > y v z = y /\ X <= y}
Utilizaremos de nuevo la regla de inferencia de la seleccin condicional, junto
con otras reglas de inferencia apropiadas, la aritmtica e identidades. Comen-
zamos con un tableau de prueba parcial:
{verdadero}
if x ) y then
z := x
else
z : ~ y
: z = x /\ x > y v z ~ y /\ X <= y}
212 Computacin l. Lgica, resolucin de problemas, algoritmos Vprogramas
Identificamos B como x> y, 5, como z := x, 52 como z := y, y P como
verdadero (esto es lo mismo que decir que no nos importa cul era el valor
que tenian esas variables antes de ejecutar la seleccin condicional). Asi, la
parte b) de la regla de la seleccin tomaria la forma siguiente, de la que debe-
mos demostrar su validez para establecer la propia validez de Q:
{verdadero A x y} z := x{z = X A X > y v z = y A X <= y} A
{verdadero A > y)} z := y{ z = X A X > y v z = y A X <= y}
Analicemos por separado cada una de las lineas de la disyuncin, como hici-
mos en el ejemplo anterior. La lnea 1 se corresponde con el caso en que x > y.
Utilizando la regla de la asignacin, la propiedad de la identidad para el valor
verdadero y la 1\ -introduccin, podemos poner lo siguiente:
{X>Y} z
Por lo que, utilizando la v -introduccin, es posible validar la lnea I con la
hiptesis de que x > y. La linea 2 cubre el caso alternativo en el que supone-
mos que x <= y. Es posible establecer la validez de la lnea 2 siguiendo
razonamientos similares a los que se utilizaron con la 1.
6.5.5. Verificacin de bucles
Para verificar un bucle de un programa es necesario realizar dos operaciones
independientes: debemos encontrar y justificar sus asertos asociados, y debe-
mos verificar por induccin su invariante.
Recurdese, del Captulo 4, que es posible explicar lo que hace un bucle
desplegndolo. Es decir, si reescribimos el bucle como una secuencia de
ocurrencias del cuerpo del bucle, podemos deducir con exactitud qu clase de
generalizacin representa el bucle. Considrese el bucle whi l e de la Figu-
ra 6.16, que suma los enteros del 1 al 5.
sum := o;
i 1;
while i <= 5 do
begin
5um := sum + i;
i:=i+1;
end
Figura 6.16. Un bucle wh i Le sencillo.
Las cinco ejecuciones del cuerpo del bucle pueden ser desplegadas de la mane-
ra siguiente:
sum := sum + i;
i:=i+1;
Robustez y prueba de los algoritmos 213
sum : = sum + i;
i:=i+1;
suro : = sum + i;
i:=i+1;
sum : = sum + i;
i:=i+1;
sum := sum + i;
i:=i+1;
,
Recurdese tambin de! Capitulo 4, que el invariante del bucle es un aserto
que es vlido antes y despus de cada repeticin del bucle, incluidas la primera
y la ltima. El invariante para e! bucle de arriba es:
{inv: sum=Su. j E {1, .. , i -1}: j 1\ 1 <= i <=6)
Es posible comprobar que este invariante es verdadero, tanto antes como
despus de cada repeticin del bucle wh; Le. En particular, el bucle explica
cada uno de los pasos individuales de la expansin del bucle siguiente:
{sum = O1\ i = 1}
sum := sum + i;
i:=i+1;
{sum = O+ 1 1\ i = 2}
sum := sum + i;
i:=i+1;
{sum = O+ 1 + 2 1\ i = 3}
sum : = sum + i;
i:=i+1;
{sum = O+ 1 + 2 + 3 1\ i = 4}
sum := sum + i;
i:=i+1;
{sum = O+ 1 + 2 + 3 + 4 1\ i ~ 5}
sum := sum + i;
i:=i+1;
( sum = O+ 1 + 2 + 3 + 4 + 5 1\ i = 6 }
Otro aspecto importante de la verificacin de bucles es demostrar que termi-
nan. Es decir, estamos interesados slo en bucles controlados, bucles que termi-
nan despus de un nmero de pasos finito, independientemente del estado de
las variables en el momento en que empieza su ejecucin. Existen tres reglas de
inferencia diferentes para describir la condicin de terminacin de un bucle,
una por cada tipo de bucle existente. Cada una de estas variantes utiliza el
invariante y la presuncin de terminacin de forma diferente.
Definicin. La regla de inferencia de los bucles.
a) { i nv 1\ e} s {i nv}
{inv} while e do s {inv 1\ -e}
214 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
b) (inv) s {inv}
{inv) repeat s until B {inv A B)
e) (inv A 1 i n} s {inv}
[ i nv) for i : = 1 to n do s {i nv A i = n + 1)
La parte a) de la regla dice que si {i nv !\ B} s {i nv} es vlido para una
nica ejecucin del cuerpo del bucle s, entonces {i nv} whi le B do s
{; nv !\ es vlido para el bucle completo. Obsrvese que la condicin
de terminacin del bucle est incluida en la expresin de forma
explicita. Los apartados b) y e) son similares, aunque se aplican a los otros
dos tipos de bucles de Pascal.
Reconsideremos el bucle whi le de la Figura 6.16. La regla del bucle nos
permite inferir los asertos siguientes, en los que B es la expresin i <= 5.
5Uro := o;
i 1;
while i <= 5 do
{i nv: sum = Sum i E (1, ... , i - 1 ): i A 1 i <= 6)
begin
sum := suro + i;

end
{sum = Sum i E {1, ... , i - 1 ): i A 1 i <= 6 A -( i <= 5) )
Este ltimo aserto puede simplificarse a
{sum = Sum i E {1, o o ., 5}: i A i = 6)
utilizando reglas elementales de la aritmtica.
Observando las formas de la regla de los apartados b) y e), podemos ver
que la relacin entre el invariante y la condicin de terminacin son ligeramen-
te diferentes, y reflejan con exactitud el significado de los bucles repeat y
foro Por ejemplo, si reescribimos el bucle de la Figura 6.16 en forma de bucle
repeat, la regla del bucle nos dar lo siguiente:
sum O;
i := 1;
repeat
(inv: sum= Sumi E [1, o , i -1): i A 1 <= i
sum := suro + i;

until i > 5
{sum = SUII j E {1, .. o, i - 1 }: j A 1 i <= 6 A i > 5 }
Donde la condicin B es ahora; > 5, que especifica la condicin para que el
bucle termine (en lugar de la condicin para que contine, como pasaba en el
Robustez V prueba de los algoritmos 215
bucle wh; Le). De nuevo, podemos simplificar utilizando las reglas de la arit-
mtica:
{ s um = SUI! j E {1, ... , S}: j /\ ; = 6 }
Finalmente, reescribiremos el bucle de la Figura 6.16 como un bucle for.
Podemos ver de nuevo que la regla para este bucle alternativo genera los
asertos siguientes:
sum : ~ o ;
for ; := 1 to 5 do
{ ; nv: sum ~ Sumj E {1, ... , ; - 1 }: j /\ 1 < ~ ; <= 6}
sum := sum + i;
{sum = Su. j E {1, .. , ; - 1 }: j /\ 1 <= ; <= 6 /\ ; = 6}
donde el ltimo aserto se simplifica de nuevo a
{ sum = Sum j E {1, ... , S}: j /\ ; = 6}
Utilizacin de la induccin en la verificacin del invariante. Hasta ahora, he-
mos admitido la validez del invariante del bucle muy informalmente. Es decir,
hemos supuesto que el invariante es, sin ninguna duda, vlido para el bucle
que describe. Sin embargo, cuando verificamos un programa, debemos escrutar
la correccin de todos los invariantes del bucle. Cmo podemos hacer esto?
Puesto que cada iteracin del bucle sigue a una iteracin anterior, podemos
utilizar el mtodo de la induccin que se introdujo en el Capitulo 3.
Aqui, la base de la induccin es el nmero ;, de la iteracin del bucle
que se va a ejecutar. Concretamente, es necesario demostrar: 1) Que el in-
variante se satisface antes de la primera interacin; y 2) Que la satisfaccin
del bucle despus de las ; - 1 primeras iteraciones (es decir, antes de la
; -sima iteracin) garantizan la satisfaccin del invariante despus de la ite-
racin; -sima (es decir, antes de la iteracin ; + 1). Consideremos de nuevo
el bucle siguiente:
sum := o;
for ; := 1 to 5 do
{; nv: SUm = Su", j E {1, ... , ; - 1}: j /\ 1 <= ; <= 6}
sum : ~ sum + 1;
Antes de la primera iteracin del bucle; = 1 Y sum = O, por lo que se ve
fcilmente que el invariante se satisface en este caso. Supongamos ahora que el
invariante se satisface despus de ; - 1 iteraciones, para algn ; = 2, 3,
... , 6. Es decir, supongamos que:
sum ~ Sum j E {1, ... , ; - 1 }: j /\ 1 <= ; <= 6
216 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Ahora tendremos que demostrar por, induccin, que tras una ejecucin de
todo el cuerpo del bucle, se garantiza que:
sum = SUII j E (1, ... , ;' - 1): j 1\ 1 <= ; , <= 6
donde ; , = ; + 1.
Podemos hacer esto examinando el efecto de las instrucciones sobre el
invariante original. Es decir, una simple ejecucin de la instruccin sum :=
sum + 1 conduce a
sum = ; + Sum j E (1, ... , ; - 1 ): j
= Sum j E (1, , ;): j
= Sum j E (1, , (; + 1 ) - 1 }:
= SUII j E (1, , ; , - 1 ): j
por reglas algebraicas sencillas. La instruccin; :=; + 1 conduce a
1 <= ; + 1 <= 6 '" 1 <= ;' < ~ 6
puesto que el valor limitador de ; = 5 en el bucle for limita a 6 el valor de
; , . Luego, por induccin, se deduce que el invariante del bucle es vlido, lo
que completa la verificacin del bucle.
6.5.6. Verificacin formal frente a verificacin informal
de programas
Las tcnicas que se han introducido en este captulo reciben habitualmente el
nombre de tcnicas de verificacin formal. Como es fcil imaginar, la aplicacin
de las tcnicas de verificacin formal a un programa razonablemente largo se
convierte rpidamente en algo inabarcable. Adicionalmente, existe una amplia
gama de problemas de programacin para los que no se han desarrollado
suficientemente las tcnicas de verificacin. El proceso de verificacin formal
de programas est todava en la infancia -hace falta hacer mucho todava
para que pueda utilizarse como una herramienta que garantice la robustez de
los programas.
Sin embargo, existen diferentes niveles de granularidad de programas, en
los que se puede aplicar las tcnicas de verificacin de programas. El proceso
de la verificacin i'!formal parece aportar medios de argumentar, de forma
convincente, sobre la correccin de los programas, evitando muchos de los
inconvenientes de la demostracin lnea-a-linea de los mtodos formales. Este
proceso es similar al que se sigue en Matemticas, en la demostracin de un
teorema, o en una simplificacin algebraica, tal como se vio en el Captulo 3.
Es decir, cuando simplificamos una expresin algebraica, no solemos enumerar
todos los pasos que se siguen ni su justificacin formal en trminos de propie-
Robustez y prueba de los algoritmos 217
dades algebraicas bsicas (asociatividad, conmutatividd, etc.). En su lugar, sole-
mos saltarnos los pasos que son evidentes para el lector, concentrndonos slo
en aquellos esenciales y dificiles de comprender.
Este es el caso de la verificacin informal. En lugar de construir una demos-
tracin completa mediante una prueba tableau, nos centramos en los aspectos
ms complejos del programa, y argumentamos en castellano sobre la forma en
que esas partes complejas satisfacen las especificaciones. As, las nociones de
precondicin, poscondicin e invariante juegan an un papel esencial en este
proceso, pero las argumentaciones sobre la correccin del programa se realizan
ms informalmente.
6.6. RESUMEN
En este captulo se han presentado las nociones de correCClOn, robustez y
amigabilidad de los programas. En el captulo se ha incidido sobre la utiliza-
cin de la estrategia de resolucin de problemas MAPS, ilustrando su utiliza-
cin en la resolucin de un problema de tratamiento de textos, y otro gr-
fico.
Hemos presentado y desarrollado dos metodologas complementarias para
asegurar la correccin y robustez de nuestros programas: prueba y verificacin.
stas permiten desarrollar buenos programas, aun a los ms escpticos, si
tienen una mentalidad positiva. Es evidente que tendremos que realizar un
anlisis activo de nuestros propios diseos y los programas que resultan a
medida que sean ms complejos los problemas que queremos resolver.
El mtodo de prueba que se ha estudiado en este captulo aporta herra-
mientas que nos permiten adquirir una mayor confianza sobre la correccin de
los programas. Aunque el proceso de prueba no garantiza la inexistencia de
errores, nos ayuda a adquirir confianza en la validez de nuestras soluciones. La
prueba es uno de los fundamentos pragmticos en el campo de la garantiza-
cin de la calidad del software.
Cuando es posible aplicar los mtodos de verificacin estudiados en este
capitulo, garantizan la ausencia de errores. A su vez, inciden en la importancia
de la lgica para la informtica. Es decir, los principios de la lgica y las
demostraciones que se introdujeron en el Captulo 3, son la base notacional y
metodolgica para la combinacin de precondiciones y poscondiciones en la
especificacin de problemas, con las reglas de inferencia en la verificacin de
programas. Sin embargo, la verificacin tiene limitaciones prcticas, y es nece-
sario que las conozcamos bien cuando tengamos que decidirnos entre prueba o
verificacin de programas. En el Volumen JI de esta serie, veremos tcnicas de
prueba y verificacin adicionales.
218 Computacin l. Lgica, resolucin de problemas, algoritmos y programas
Ejercicios
6.7. Verificar los siguientes grupos de instrucciones, rellenando la precondi-
cin o poscondicin que falta, utilizando la regla de inferencia de la
asignacin:
a) { } e) { }
i := i + 1 Write(x>
{i > O} {saLida ~ 12)
b) {i ~ O} J) {i ~ 10}
i : ~ i + 1 j : ~ 25
{ } { }
e) {i+j=O} g) { }
i := i + 1;
s : ~ s + t ~ 1
j
: ~ j ~ 1
{O <= s)
{ }
d) {entrada ~ 4 7 5)
Read(x>
{ }
6.8. Verificar el bucle siguiente, utilizando la regla de inferencia para bucles,
incluyendo una demostracin (por induccin) del invariante.
{ L ~ (e[1], e[2], .. " e[m], . , e[n]>)
j := 1;
k := 2;
whi le k <= mdo
{inv: para todo i in {1, ... , k ~ 1): e[j] <= e[i] /\ 2 < ~ k <= m+ 1}
if L[k] < L[j] then
j := k;
Min := j
}
6.9. Escribir un bucle controlado utilizando una instruccin for o una
repeat y que sea equivalente al bucle del Ejercicio 6.8. Encontrar el
invariante y verificar el bucle resultante.
6.10. En cada una de las instrucciones siguientes, escribir el aserto que falta
(utilizando la regla de inferencia de la seleccin condicional) de forma
que ste sea vlido.
a) { }
if a = 1 then b : ~ a else b := a + 1
{b ~ 1}
Robustez y prueba de los algoritmos 219
b) {i=nAj=m}
H i = O then j := O else j := 1
{ }
e) {i = n A j = m}
if i = O then j O
{ }
6.11. Confrontar los procesos de prueba y verificacin como garantes de la
correccin, robustez y amigabilidad de los programas. Qu ventajas
tiene cada uno? Cules son las desventajas? Para el problema de la
Pluviometria del Captulo 5, cul de los dos procesos parece ser
ms adecuado y por qu?
6.12. Verificar el invariante del segmento de programa siguiente, suponiendo
que s = R2D2 I . Escribir los valores de las variables Count y Loe en
cada iteracin de bucle.
Count := o;
Loe := O;
whi le Loe < Length(S) do
{inv: O <= Loe <= Length(S) A
Count = Num i E {1, ... , Lo e}: 'O' <= S[ i] <= '9')
begin
Loe
if (S[Loe] >= 'O') and (S[Loe] '9') then
Count := Count + 1
end
6.13. Encontrar el invariante del bucle de la funcin siguiente:
function EstaOrdenada (A: Lista): Soolean;
var i: i nteger
begin
EstaOrdenada := true;
for i := 1 to LengthLista(A) -1 do
i f A[ i] > A[i + 1] t hen
EstaOrdenada := false
end

Вам также может понравиться