Documente Academic
Documente Profesional
Documente Cultură
Programacion
para la carrera de
Licenciatura en Artes y Tecnologas
Indice de contenidos
Introduccion
Unidad
Unidad
Unidad
Unidad
Unidad
Version digital de la
Carpeta de trabajo Unidad
Unidad
Unidad
Unidad
Pagina siguiente
2
ISBN 978-987-1856-39-8
ISBN: 978-987-1856-39-8
Iconos
Ejemplo. Se utiliza para ilustrar una definicion o una afirmacion del texto
principal, con el objetivo de que se puedan fijar mejor los conceptos.
Recurso Web. Liks a sitios o paginas web que resulten una referencia
dentro del campo disciplinario.
Los autores
Indice general
1. La disciplina de la programacion 17
1.1. Que es la programacion? . . . . . . . . . . . . . . . . . . . . . . 17
1.2. Que son los lenguajes de programacion? . . . . . . . . . . . . . 19
1.3. Breve historia de la programacion . . . . . . . . . . . . . . . . . . 21
1.3.1. Surgimiento de las computadoras . . . . . . . . . . . . . . 21
1.3.2. Los primeros lenguajes de alto nivel . . . . . . . . . . . . . 23
1.3.3. Los paradigmas de programacion . . . . . . . . . . . . . . 24
1.3.4. Consolidacion y expansion del software . . . . . . . . . . . 26
1.3.5. La era de internet . . . . . . . . . . . . . . . . . . . . . . . 26
1.3.6. Tendencias actuales . . . . . . . . . . . . . . . . . . . . . . 27
1.4. Lenguajes para dominios especficos . . . . . . . . . . . . . . . . 28
5. Modularizacion 153
5.1. Modulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
5.2. P YTHON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
5.2.1. Como trabajaremos con P YTHON . . . . . . . . . . . . . . . 156
5.2.2. Herramientas abstractas en P YTHON . . . . . . . . . . . . . 158
5.3. Tipos abstractos de datos . . . . . . . . . . . . . . . . . . . . . . . 160
5.4. Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
5.4.1. Ejercicios con listas . . . . . . . . . . . . . . . . . . . . . . 162
5.5. Diccionarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
5.5.1. Ejercicios con diccionarios . . . . . . . . . . . . . . . . . . 163
5.6. Iteracion sobre estructuras de datos . . . . . . . . . . . . . . . . . 163
5.7. Biblioteca P YGAME . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
5.8. Ejercicio integrador . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
5.8.1. Organizacion del proyecto . . . . . . . . . . . . . . . . . . . 167
5.8.2. Implementacion del juego . . . . . . . . . . . . . . . . . . . 168
7. Bases de datos
por Carlos A. Lombardi 189
7.1. Persistencia de informacion . . . . . . . . . . . . . . . . . . . . . . 189
7.1.1. La necesidad de persistir . . . . . . . . . . . . . . . . . . . 189
7.1.2. Persistencia de datos, mecanismos de persistencia . . . . 190
7.1.3. Actualizacion, consulta, busqueda . . . . . . . . . . . . . . 191
7.1.4. Persistencia en archivos . . . . . . . . . . . . . . . . . . . . 191
7.2. Concepto de base de datos . . . . . . . . . . . . . . . . . . . . . . 192
7.2.1. Cualidades de los datos persistidos . . . . . . . . . . . . . 193
7.2.2. Desventajas de la persistencia en archivos . . . . . . . . . 194
7.2.3. Un problema de consistencia . . . . . . . . . . . . . . . . . 194
7.2.4. Que son las bases de datos? . . . . . . . . . . . . . . . . 195
7.3. Bases de datos relacionales . . . . . . . . . . . . . . . . . . . . . . 197
7.3.1. Tablas, campos y filas . . . . . . . . . . . . . . . . . . . . . 197
8. Redes 225
8.1. Redes de computadoras . . . . . . . . . . . . . . . . . . . . . . . . 225
8.1.1. Clasificacion de las redes . . . . . . . . . . . . . . . . . . . 226
8.1.2. Redes cliente-servidor y redes punto a punto . . . . . . . . 227
8.2. Modelo de capas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
8.2.1. Modelo OSI . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
8.2.2. Modelo TCP/IP . . . . . . . . . . . . . . . . . . . . . . . . . 232
8.2.3. Modelo hbrido . . . . . . . . . . . . . . . . . . . . . . . . . 232
8.2.4. Protocolos . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
8.2.5. Tipos de servicios . . . . . . . . . . . . . . . . . . . . . . . 234
8.3. Capas del Modelo OSI . . . . . . . . . . . . . . . . . . . . . . . . . 234
8.3.1. Capa de aplicacion . . . . . . . . . . . . . . . . . . . . . . . 234
8.3.2. Capa de transporte . . . . . . . . . . . . . . . . . . . . . . 239
8.3.3. Capa de red . . . . . . . . . . . . . . . . . . . . . . . . . . 240
8.3.4. Capa de enlace y capa fsica . . . . . . . . . . . . . . . . . 241
8.4. Introduccion al HTML . . . . . . . . . . . . . . . . . . . . . . . . . 242
8.4.1. Descripcion basica de una pagina web . . . . . . . . . . . 244
9. Aplicaciones 247
9.1. Interpretes y compiladores . . . . . . . . . . . . . . . . . . . . . . 247
9.2. IDEs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
9.3. Ejercicio integrador . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
9.3.1. Codificacion del modelo . . . . . . . . . . . . . . . . . . . . 250
9.3.2. Base de datos y consultas . . . . . . . . . . . . . . . . . . 251
9.3.3. Consultas a la base de datos . . . . . . . . . . . . . . . . . 254
Introduccion
Mapa conceptual
El mapa conceptual de esta carpeta se presenta en el grafico G.1.
La disciplina de la programacion
Actividad 1
http://lifedev.net/2008/07/programmer-creativity-boost/
.
http://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/
EWD1036.html
Para Ampliar
Entre las historias que se cuentan sobre Edsger Dijkstra hay una carac-
terstica de su personalidad que se reflejo en todos sus trabajos. Intente
descubrir cual es.
tareas que la computadora requiere realizar para que el programa cumpla con
sus objetos. Pero existen tambien lenguajes de bajo nivel, que nos hacen definir
en mayor o menor medida cada paso que el programa seguira, y por ende, estan
ligados a la naturaleza operacional de la maquina. Esta denominacion surge de
la idea de imaginar que la computadora es la base fundacional sobre la que los
programas ejecutan, y que las ideas abstractas se van construyendo sobre ellas.
Hablaremos entonces de un nivel alto de abstraccion cuando nos estemos refi-
riendo a abstracciones mas cercanas a las ideas del problema a ser solucionado,
a la mente de los programadores; y de nivel bajo de abstraccion cuando nos re-
firamos a abstracciones mas cercanas a las ideas relacionadas a las formas de
funcionamiento de las maquinas que ejecutan los programas.
Definicion 1.2.2. Un lenguaje de programacion de alto nivel es uno que expre-
sa mejor las ideas en las que debe pensar el programador, y en alguna forma
esta mas alejado (y menos dependiente) de la maquina especfica que ejecu-
tara cada programa escrito en dicho lenguaje.
Definicion 1.2.3. Un lenguaje de programacion de bajo nivel es uno que expresa
mejor las ideas propias de los mecanismos de ejecucion, por lo que es mas
dependiente de la maquina especfica que ejecutara cada programa escrito en
dicho lenguaje.
El desarrollo de los lenguajes de programacion es guiado fundamentalmente por
la busqueda del nivel de abstraccion adecuado para poder expresar con facilidad
cierto tipo de soluciones a los problemas a resolver. Podra decirse que los len-
guajes de progamacion surgieron y se desarrollaron a partir de la necesidad de
reconciliar dos mundos: el mundo operacional o fsico, relativo a la ejecucion de
bajo nivel de las computadoras; y el mundo denotacional o abstracto, definido por
las ideas que manejan los programadores. Esto impactara tambien en la forma
en que pensamos programas. Por eso conviene revisar un poco la historia de la
programacion.
A partir de los trabajos de Turing, John von Neumann desarrollo una arqui-
Se pronuncia yon fon tectura de maquinas que usaban la misma memoria para almacenar los datos
noiman. Matematico y los programas. La arquitectura von Neumann, o alguna variante de la mis-
hungaro-americano,
que vivio entre 1903 y
ma, es aun hoy utilizada por, practicamente, todas las formas de computadoras
1957. Realizo nume- existentes.
rosas contribuciones Estos dos descubrimientos permitieron, durante la Segunda Guerra Mundial
en matematicas, pero
su nombre se conoce
el desarrollo practico de las primeras computadoras: los trabajos del aleman Zu-
por su aporte a la arquitectura de se, los trabajos ingleses en la lnea Colossus y los trabajos americanos en la
las computadoras. lnea ENIAC.
Recien en la decada de 1950 se comenzaron a producir computadoras a nivel
comercial. Estaban basadas en tubos de vaco llamados valvulas y eran enor-
mes y costosas, y su poder de computo era menor que el de un telefono digital
moderno. Sin embargo significaron una revolucion en terminos de calculo para
la epoca. Fueron la llamada primer generacion de computadoras. La segunda
generacion aparece a fines de esa decada, cuando las valvulas son reemplaza-
das por transistores, y permiten iniciar la carrera para disminuir el tamano de las
computadoras. Las computadoras de la segunda generacion son mas pequenas
y consumen menos electricidad que las anteriores.
Durante la decada de 1960 se invento el circuito integrado, que fue la clave
para el desarrollo del microprocesador, que dio lugar a la tercera generacion.
Los circuitos integrados son pastillas de silicio en las que se colocan miles de
componentes electronicos en una integracion en miniatura.
Para Ampliar
Para saber mas sobre el desarrollo del hardware, especialmente las pri-
meras computadoras, consultar:
to que haba que atender todos y cada uno de los aspectos de las maquinas que
se programaban, los cuales no eran pocos ni simples. Ademas, al querer reali-
zar un programa para otra computadora deba aprenderse todo el lenguaje de
nuevo desde el comienzo. El problema es que el lenguaje assembler se acerca
mas a la forma de operar de las computadoras y no a la forma de pensar de los
programadores; o sea, en los terminos que manejamos en esta Unidad, es un
lenguaje de muy bajo nivel. En ese momento era necesario este tipo de manejo
de bajo nivel, puesto que los recursos de los que dispona una computadora eran John Warner Backus
extremadamente escasos y deban, por lo tanto, ser administrados con precision fue un cientfico
americano de la
y sumo cuidado. computacion que
vivio entre 1924 y
2007. Gano diversos
premios por sus con-
tribuciones, entre las
que se encuentran
1.3.2. Los primeros lenguajes de alto nivel la creacion del primer lenguaje de
programacion de alto nivel, y de
un mecanismo de descripcion de
La situacion con los lenguajes ensambladores era bastante preocupante para lenguajes de programacion conoci-
los programadores de aquella epoca pues les restaba productividad, les res- do hoy como forma Backus-Naur
tringa la creatividad y el espectro de soluciones imaginables. Por esa razon, (Backus-Naur Form, o BNF).
en 1955, John Backus y sus colegas de IBM desarrollaron, en el campus de
esta compana en California en Estados Unidos, el lenguaje FORTRAN, por
FORmula TRANslator (o mas detalladamente, the IBM Mathematical F ORmula
T RANslating System), que es tpicamente considerado por toda la comunidad in-
formatica como el primer lenguaje de programacion independiente de la maqui-
na. FORTRAN introdujo muchas ventajas sobre los lenguajes ensambladores, e Tecnicamente el primer lengua-
hizo mas claras las operaciones basicas. je de programacion de este esti-
lo fue P LANKALK UL (pronunciado
La idea rectora en esos das era hacer la programacion mas cercana al len- plankalkil), desarrollado por Kon-
guaje natural humano; o dicho de otro modo, aumentar el nivel de abstraccion. rad Zuse en 1943 en Alemania. Sin
embargo, debido a la Guerra, este
Por esa razon, estos lenguajes que empezaron a surgir fueron denominados len-
lenguaje no fue hecho publico has-
guajes de alto nivel. Hoy en da se los suele entender como lenguajes de mas ta 1972.
bajo nivel, puesto que existen otros lenguajes (como los lenguajes funcionales o
los orientados a objetos) que son de mayor nivel de abstraccion que los aqu men-
cionados. En esta epoca el motor que llevaba adelante las investigaciones y el
desarrollo de software eran las aplicaciones de defensa y las de administracion a
gran escala.
Al poco tiempo de la aparicion de FORTRAN surgieron otros dos lengua-
jes: LISP (por LISt Processor, procesador de listas), antecesor de los modernos
lenguajes funcionales y COBOL (por COmmon Business Oriented Language,
lenguaje orientado a los negocios comunes) que fuera adoptado en bancos, com-
panas y dependencias oficiales. En menos de una decada florecieron otra do-
cena o mas de lenguajes diferentes. Cada uno de estos lenguajes se enfocaba
en cierta forma de resolver problemas, siendo la mayora orientados a establecer Entre los mas notorios que die-
una secuencia de instrucciones con foco en diferentes aspectos de como esta- ron origen a ideas modernas estan
blecer la comunicacion entre las diferentes partes que componan el programa. CPL (antecesor de C), S IMU -
LA (precursor de la progamacion
Un lenguaje que resulto un hito por la consolidacion de muchas ideas al res- orientada a objetos), y BASIC (ori-
pecto de como deban definirse los lenguajes de programacion fue ALGOL (por ginalmente disenado para la en-
senanza).
ALGOrithmic Language, lenguaje de algoritmos). Este lenguaje fue de gran in-
fluencia en muchsimos lenguajes modernos, puesto que sus ideas siguen usando-
se en el diseno actual de lenguajes de programacion (por ejemplo, la forma de
describir sus reglas de sintaxis, la Backus-Naur Form o BNF, se sigue usando
en la especificacion de la sintaxis de todos los lenguajes de programacion mo-
dernos). Tambien fue el primer lenguaje para el que se estudio como asignar
significado (semantica) de manera independiente a la ejecucion.
Para 1970 ya se pueden identificar cuatro grandes paradigmas, que estan vi-
gentes hoy da y que son claramente reconocidos por todos los miembros de la
comunidad informatica. Mucho despues se intento identificar paradigmas adicio-
nales a estos cuatro originales, pero no hay consenso sobre si alguno de ellos
llega o no a poder ser considerado un paradigma y merece ese nombre; por esa
razon nos limitaremos a hablar de los cuatro paradigmas principales.
El foco del desarrollo de software se fue desplazando hacia la educacion,
para poder formar a los futuros programadores. La administracion a gran escala
siguio teniendo fuerte presencia, pero las aplicaciones orientadas a la defensa
fueron disminuyendo.
Los cuatro paradigmas de programacion que surgieron a fines de los sesenta
y principios de los 1970, y que resultaron de fundamental influencia en la forma
de hacer programacion, son:
el paradigma imperativo,
el paradigma orientado a objetos,
el paradigma funcional, y
el paradigma logico.
Los dos primeros estan mas orientados a la forma de manejar estado y podran
ser denominados procedurales, mientras que los dos ultimos estan mas orienta-
No es usual asociar el termino pro- dos a expresar conceptos o nociones independientes del estado, y podran ser
cedural con los lenguajes orienta- denominados declarativos. El paradigma que se desarrollo con mayor mpetu al
dos a objetos, pero es una forma
de indicar que los mismos se con-
principio fue el imperativo, debido a su cercana con los lenguajes de bajo nivel.
centran mas en el estado que en la Los otros tardaron mas tiempo en adoptar un estado de madurez, y no fue hasta
descripcion de informacion. mediados de la decada de 1980 que tanto el paradigma funcional como el logico
y el orientado a objetos empezaron a ser foco de atencion masiva.
Dentro del paradigma imperativo se clasifican lenguajes mas vinculados con
la secuencia de instrucciones y cercanos al assembler. Algunos nombres nota-
bles que surgieron en esa epoca dentro del paradigma imperativa, y aun cono-
cidos hoy en da, son: BASIC, desarrollado en 1965 por John Kemey y Tho-
mas Kurtz con la intencion de que se conviertiese en un lenguaje de ensenan-
za; PASCAL, creado, tambien con fines didacticos, por Niklaus Wirth en 1970
a partir del ALGOL; y C, disenado por Dennis Ritchie y Ken Thompson en los
laboratorios Bell (Bell Labs) entre 1969 y 1973, con el proposito proveer una tra-
duccion eficiente a assembler y permitir la administracion eficaz de los recursos
de computo de las maquinas con arquitectura von Neumann a traves de abs-
tracciones cercanas al bajo nivel, que brinda una forma comoda e independiente
http://griffsgraphs.com/2012/07/01/
programming-languages-influences/
Cerramos este apartado con la certeza de que la proxima decada nos depa-
rara nuevas sorpresas en el desarrollo de sistemas de computacion.
esto parte del proceso propuesto para la solucion de problemas; este estilo se
suele denominar programacion orientada a lenguajes. Existen numerosas inves-
tigaciones sobre la manera mas eficiente y efectiva de definir nuevos lenguajes
rapidamente y se han desarrollado numerosas herramientas para ello.
En este apartado mencionaremos dos o tres de los dominios mas populariza-
dos, y relevantes para el publico general, pues una cobertura exhaustiva resulta
Puede resultar interesante investi- practicamente imposible e innecesaria para los objetivos aqu propuestos.
gar mas en el tema, eligiendo un El primero de los dominios que consideraremos es el de consulta y administra-
dominio de su interes y comproban-
do si existen DSLs para dicho domi-
cion de bases de datos. El modelo tradicional utiliza bases de datos relacionales,
nio. que son agrupaciones de datos en vnculos (o relaciones) dadas por el proble-
ma a modelar. Para describir las consultas a este tipo de bases de datos, IBM
en 1970 desarrollo un DSL denominado SQL (por su denominacion en ingles,
Structured Query Language). Es uno de los DSLs mas conocidos hoy da. Este
Son lenguajes textuales que permi-
lenguaje evoluciono con el tiempo, y dio lugar a diversos lenguajes de proposito
ten anotar un documento con tags general como F OX, C LIPPER, RBASE y los lenguajes asociados a los motores
que sirven para especificar estruc- de bases de datos Oracle e INFORMIX. Todos los lenguajes de esta familia se
tura, agregar significados asocia- denominan grupalemente como 4GL (Lenguajes de Cuarta Generacion).
dos a diferentes elementos, asociar
informacion de autora, revisiones, Otro dominio muy conocido es el de diseno y especificacion de contenidos pa-
etcetera. ra la Web. En este dominio el lenguaje mas conocido es HTML, un lenguaje de
marcado (markup language) que permite especificar los elementos de una pagi-
na web de manera tal que diferentes herramientas puedan elegir como mostrar-
los. Como otros lenguajes de marcado especifica informacion a traves de etique-
tas, mas conocidas por su denominacion en ingles, tags. Los tags son utilizados
Esta palabra tambien se utiliza en para describir estructura, informacion visual, comportamiento u otras nociones,
castellano como anglicismo aun no y son interpretados por las diferentes herramientas que analizan un programa
aceptado por la Real Academia Es-
panola.
en uno de estos lenguajes para decidir diferentes cursos de accion. Por ejem-
plo, en el caso de HTML, los diferentes navegadores pueden elegir mostrar los
elementos de diferentes maneras dependiendo de factores tales como el tipo de
dispositivo (pantalla de PC, telefono, etc.), las opciones elegidas (ver el codigo
fuente o mostrar el resultado) y otros. Por eso se dice que HTML es un lenguaje
de marcado presentacional. Otro DSL asociado al dominio de presentacion web
es el CSS, por el ingles Cascading Style Sheets (hojas de estilo en cascada),
utilizado para especificar el estilo de presentacion de una familia de documentos
de manera generica.
Otro DSL que se clasifica dentro de los lenguajes de marcado es el XML,
por eXtensible Markup Language (lenguaje de marcado extensible), que se uti-
liza para definir un conjunto de reglas de codificacion de documentos en un for-
mato que es simultaneamente legible por las personas y por las computadoras.
Aqu los tags se utilizan para expresar la estructura del documento, sus partes
y dependencias, y en ese sentido se puede considerar como un lenguaje de
marcado descriptivo. Los documentos descritos con XML estan correctamente
formados por definicion, siendo imposible la especificacion de documentos con
partes faltantes o incompletos. El lenguaje es extremadamente flexible, pudiendo
utilizarse para describir metadatos, o sea, documentos que describen, de mane-
ra completamente formal y susceptible de ser analizada por las computadoras,
la forma de los datos o documentos a definir con el mismo lenguaje XML. Una
de las formas mas conocidas de este tipo de descripciones es llamada DTD,
por Document Type Definition (definicion de tipo de documento), un conjunto de
tags XML especficamente disenado para describir formatos de documentos. Del
XML evolucionaron otros lenguajes tales como RSS, ATOM, SOAP, and XHTML
(una version de HTML basada en las definiciones de XML).
Un tercer dominio, aunque por el momento solo difundido en la comunidad
cientfica (mas especficamente entre matematicos, fsicos e informaticos), es el
de composicion tipografica (en ingles, typesetting). En este dominio existe un len-
Para Ampliar
http://programandoenc.over-blog.es/article-28741792.html
Primeros elementos de
programacion
Observar que las expresiones pueden tener formas basicas, atomicas (como
5), o pueden estar formadas por partes (como 4+1), y sin embargo se refieren al
mismo valor. En ese caso, se suele decir que las expresiones son equivalentes,
y por ende pueden ser intercambiadas a eleccion.
Para Reflexionar
diferentes formas (conos, texto, etc.). En el grafico G.2.1 podemos visualizar dis-
tintos valores, y la forma en que aparecen graficados en un programa (el editor
de textos de Open Office). En el ejemplo, los valores son el tipo de la fuente, el
tamano de la fuente, el color de la fuente, y un texto con la palabra Texto. Todos Es un programa libre, de fun-
estos valores aparecen de una forma u otra en el codigo que los programadores cionalidad similar a otras herra-
mientas no libres, como Word.
de dichas herramientas escriben. Para conocer esta herramien-
Actividad 1 ta en mayor profundidad, ver
De la misma forma que los valores, las acciones tambien se encuentran gra-
ficadas en los programas tradicionales. En el grafico G.2.2 podemos visualizar
distintas acciones encontradas en el programa Open Office.
La mayora de los lenguajes de programacion trabajan con comandos. Al igual
que con las expresiones, la forma exacta en que se construyen comandos co-
rresponde a la sintaxis del lenguaje, y se rige por las mismas reglas rgidas, que
como se menciono, son una de las cosas a aprender al estudiar un lenguaje
de programacion. En el caso de los comandos, su significado (su semantica) es
normalmente entendida a traves de la forma en que la maquina que ejecuta el
programa lleva a cabo las acciones correspondientes. Esto se conoce como com-
portamiento operacional del comando, y es comun no distinguir entre el comando
como descripcion de la accion y la accion en s. Sin embargo, en algunos casos
es fundamental hacer esta distincion, y por ello es importante conocerla.
Para Reflexionar
Los valores son parte de distintos conjuntos. Por ejemplo, el numero dos for-
ma parte de los numeros naturales, las palabras forman parte del conjunto de
todas las palabras y los colores forman parte del conjunto total de colores. De-
nominaremos tipo de una expresion a un conjunto de expresiones determinado,
y lo denotaremos mediante algun nombre especial. Diremos, por ejemplo, que la
expresion 2 posee tipo Numero, y el color Rojo posee tipo Color.
Expresion Tipo
Rojo Color
"Casa" Palabra
2+4 Numero
Norte Direccion
Actividad 2
Para Reflexionar
Para Ampliar
www.haskell.org
Para conocer mas de Python, ver
www.python.org
2.2.2. El cabezal
Tanto el tablero como las bolitas son componentes inanimados. El factor de mo-
vimiento en G OBSTONES viene dado por una maquina que puede operar sobre
el tablero y las bolitas. Esta maquina puede realizar diversas acciones (siempre
sobre una unica celda por vez). Las acciones incluyen desplazarse a una celda
vecina, poner y sacar bolitas en la celda sobre la que se encuentra, y consultar
si hay bolitas en una celda, y cuantas hay.
La maquina, que sera denominada cabezal para remarcar el hecho de que opera
sobre una celda por vez, puede recibir instrucciones relativas a la celda sobre la
que se encuentra el mismo, y a la que se denomina celda actual.
En los graficos G.2.6 y G.2.7 se observa el tablero presentado antes con una
representacion del cabezal y la celda actual.
Definicion 2.2.2. El cabezal es una maquina que opera sobre una celda por vez,
la celda actual.
Para Reflexionar
Otra caracterstica importante del cabezal, ademas de que puede operar sobre
una celda por vez, es que dispone de una cantidad ilimitada de bolitas de cada
color. Esto, al igual que las caractersticas del tablero y las celdas, determinara al-
gunas de las formas de hacer cosas en G OBSTONES.
Todo el objetivo de un programa G OBSTONES es servir para indicar al cabe-
zal que lleve a cabo determinada serie de modificaciones al tablero, con algun
proposito determinado. Para ello, precisamos los elementos del lenguaje.
Poner(Verde),
Poner(Rojo),
Poner(Azul) y
Poner(Negro).
Definicion 2.2.5. Los valores posibles para un < color > son Verde, Rojo, Azul
o Negro.
Que debe hacerse para describir la indicacion al cabezal que debe poner mas
de una bolita en la celda actual? Dicha descripcion debe contener dos comandos
seguidos. La manera de colocar seguidos comandos en G OBSTONES es ponerlos
uno a continuacion del otro; por ejemplo
Poner(Verde)
Poner(Verde)
Poner(Verde); Poner(Verde)
Poner(Verde); Poner(Verde);
{
Poner(Verde); Poner(Verde)
Poner(Rojo); Poner(Rojo)
Poner(Azul); Poner(Azul)
Poner(Negro); Poner(Negro)
}
que describe una accion, cuyo efecto al ejecutarse sera colocar dos bolitas de
cada color en la celda actual. Los bloques tendran importancia en la definicion
de comandos compuestos a traves de ciertas estructuras de control.
Poner(Verde)
Poner(Verde)
{ Poner(Rojo); Poner(Rojo) }
{
Poner(Azul); Poner(Azul)
Poner(Negro); Poner(Negro)
}
es un grupo de comandos que tendra el mismo efecto que el bloque dado previa-
mente, o sea, sera equivalente. Y dado que un bloque tambien es un comando,
Recordemos que un comando es podra a su vez ser colocado en otro bloque. Entonces, el comando
equivalente a otro cuando describe
la misma accion. {
{ Poner(Verde);Poner(Verde) }
}
es valido, y denota la accion de poner dos bolitas de color Verde. Sin embargo,
estas dos formas de usar bloques son poco comunes, reservandose el uso de
bloques para estructuras de control mas complejas.
Para Reflexionar
En este punto somos capaces de construir comandos cuyo unico efecto es po-
ner muchas bolitas de muchos colores. Pero todava no podemos construir un
programa. Para ello debemos presentar un par mas de conceptos.
1. x
2. sumar
3. Dibujar
4. identificadormuylargoymuyconfuso
5. UnIdentificadorMasEntendible
6. UnIdentificadorTanLargoQueNoValeLaPenaNiPensarEnEscribirlo
Los ejemplos 1, 2 y 4 comienzan con minuscula. Los ejemplos 3, 5 y 6 co-
mienzan con mayusculas. Por otra parte, los ejemplos 4 y 5 estan escritos en una
forma mixta conocida como camelCase, que es la que vamos a utilizar en esta
carpeta. Existen otras formas de escribir identificadores, y cada programador tie- De Wikipedia: CamelCase es un
ne su propio estilo. Vamos a hablar de cuestiones de estilo en el apartado 2.3. estilo de escritura que se apli-
ca a frases o palabras compues-
Actividad 3 tas. El nombre se debe a que las
mayusculas a lo largo de una pa-
labra en CamelCase se asemejan
Escribir al menos otros diez identificadores, que sirvan para describir a las jorobas de un camello. El
valores complejos y acciones cotidianas. Por ejemplo, sumarDosYTres, nombre CamelCase se podra tra-
FreirUnHuevo, etcetera. ducir como Mayusculas/Minusculas
en Camello.
El procedimiento Main
De que manera el cabezal sabe cuales son las acciones que debe realizar an-
tes de detenerse al ejecutar un programa? En todo programa G OBSTONES existe
un procedimiento especial con nombre fijo, con el unico proposito de ser clara-
mente identificable por el cabezal. Este procedimiento debe ser el ultimo definido Significa Principal en ingles.
y su nombre debe ser Main. Es el procedimiento mas importante de un programa
procedure Main()
{
Poner(Verde)
Poner(Verde)
}
Al escribir el programa en papel, lo mas importante es validar que las ideas son
las correctas, y que estan seleccionadas y ordenadas adecuadamente para resol-
ver la tarea encomendada. Sin embargo, el codigo en papel puede considerarse
como un borrador, y puede por lo tanto contener pequenos errores, detalles que
pueden dejarse para un mejoramiento posterior porque no hacen a la estructura
de la solucion.
Leer con Atencion
Antes de pasar a realizar ejercicios donde usted escriba sus propios programas
para solucionar tareas sencillas, veremos un ejercicio mas, con el fin de trabajar
sobre la nocion de error.
Actividad de Programacion 5
prosedure main()
{ poner(Roja) }
Observar el mensaje de error que se produce, y corregir los errores hasta que el
programa resulte ejecutable.
G.2.9. Texto correcto del programa G OBSTONES del ejercicio 2.2.2, al comenzar
el ejercicio
Actividad de Programacion 6
Realizar el ejercicio 2.2.3. Recuerde que para poder realizarlo, debe pri-
mero escribirlo en papel, y luego pasarlo en la computadora y ejecutarlo.
Ejercicio 2.2.3. Escribir un programa G OBSTONES que deposite una bolita ver-
de, dos rojas, tres azules y cuatro negras en la celda actual, y ejecutarlo.
Revise todo lo ledo hasta el momento, e intente identificar cuales son las
actividades importantes al pensar sobre el papel, y cuales al escribir el
codigo en la computadora para ejecutarlo. Relacione esto con la defini-
cion de programa dada, y observe que cosas tienen que ver con la parte
de los programas en cuanto descripciones y que cosas con la parte en
cuanto descripciones ejecutables. La tarea del programador comienza
por pensar lo que quiere describir, y luego darle forma ejecutable. . .
procedure PonerDosVerdes()
{
Poner(Verde); Poner(Verde)
}
procedure PonerDosVerdes()
{
Poner(Verde); Poner(Verde)
}
procedure Main()
{
PonerDosVerdes(); PonerDosVerdes()
}
Observar como ahora la tarea de poner dos bolitas verdes ya no queda expre-
sada unicamente por una secuenciacion, sino que a traves del uso de proce-
dimientos hemos podido darle un nombre significativo a esa tarea. Cada vez
que precisemos poner dos bolitas verdes podemos recurrir al nuevo comando
Para que sea realmente un nue- PonerDosVerdes().
vo comando, su definicion debe en-
contrarse entre las definiciones de Leer con Atencion
procedimientos del programa.
Podramos decir que las tareas son situaciones complejas a resolver, y
los procedimientos, la forma de describir tareas (de la misma forma que
las acciones son la manera de producir efectos, y los comandos, la forma
de describir acciones).
Esta habilidad es fundamental para poder encarar tareas complejas. Uno de los
errores mas tradicionales en los cursos basicos de programacion consiste en
mantener el pensamiento operacional demasiado tiempo, pues resulta mas sen-
cillo pensar los primeros ejemplos de manera operacional. Sin embargo, esto
complica y dificulta luego el aprendizaje posterior. Pero antes de trabajar sobre
esta manera de pensar con tareas y procedimientos, vamos a enriquecer el re-
pertorio de comandos basicos.
La forma general del comando Sacar es similar a la de Poner, y esta dada por
la siguiente definicion.
Definicion 2.2.13. El comando Sacar(< color >) indica al cabezal que quite una
bolita del color < color > de la celda actual, si hay alguna.
No olvidar que esto siginifica un co-
Debe observarse que el cabezal solo puede realizar una accion de Sacar si se lor en particular, y no la palabra
cumplen ciertos requisitos. Dado que el cabezal no es mas que una maquina, y color. . .
bastante limitada, no tiene ninguna manera de saber que hacer cuando la des-
cripcion para la accion a realizar no incluya alguna situacion. Si bien las personas,
antes tal situacion, podemos tomar decisiones, las computadoras no pueden.
Cuando el cabezal recibe una orden que no puede ejecutar, toma una accion
drastica: se autodestruye, y con el al tablero y todas las bolitas. Esto puede pa-
recer exagerado para una persona, que siempre tiene otros cursos de accion para
considerar, pero no lo es para una maquina, al menos no para una tan simple.
Cuando un comando describe una accion que puede provocar la autodestruccion
del cabezal en caso de que ciertos requisitos no se cumplan, se dice que tal co-
mando describe una operacion parcial, pues solo describe parcialmente la accion
a realizar. Si en cambio la descripcion conlleva una accion que siempre puede
realizarse, se dice que es una operacion total. Al requisito que debe cumplirse
antes de intentar ejecutar una operacion parcial para estar seguro que la misma
no falla se la denomina precondicion de la operacion. De esta manera, Poner es
una operacion total, y Sacar es una operacion parcial y su precondicion es que
haya una bolita del color indicado en la celda actual.
Definicion 2.2.14. Una operacion total es la descripcion de una accion que, al
no tener requisitos para que el cabezal pueda llevarla a cabo, siempre puede ser
realizada.
Definicion 2.2.15. Una operacion parcial es la descripcion de una accion que
precisa que ciertos requisitos se cumplan para que el cabezal pueda llevarla a
cabo, y que en caso de que los mismos no se cumplan, provoca la autodestruc-
cion del cabezal y todos los elementos.
Definicion 2.2.16. La precondicion de una operacion parcial expresa los requi-
sitos que deben cumplirse para que la ejecucion de la accion indicada por la
operacion pueda ser llevada a cabo sin provocar la autodestruccion del cabezal.
De aqu en mas, al presentar nuevos comandos, se establecera si los mismos
describen operaciones totales o parciales, y en caso de que sean parciales,
cuales son sus precondiciones. En el caso de operaciones parciales, normalmen-
te se indicara solamente la accion descrita por el comando en el caso en que la
precondicion sea verdadera. Por ejemplo, diremos que Sacar saca una bolita de
la celda actual; si la bolita no existiese, la precondicion sera falsa y por lo tanto tal Recordar que los comandos des-
situacion no se indica. En algunos casos, podremos hacer la salvedad aclarando criben acciones y no que hacen
acciones. Tener en cuenta este
la precondicion en la accion: Sacar saca una bolita de la celda actual, si existe. abuso del lenguaje al leer el resto
Actividad de Programacion 7 del cuadernillo.
Ejercicio 2.2.4. Escribir un programa Gobstones que saque una bolita de la cel-
da actual sin que haya ninguna, y comprobar la forma en que se manifiesta la
autodestruccion del cabezal, el tablero y los otros elementos.
Ejercicio 2.2.5. Escribir un programa Gobstones que saque una bolita de la cel-
da actual, pero que no produzca la autodestruccion del cabezal. Como se puede
asegurar que la precondicion del comando Sacar se cumpla? Piense solo en los
elementos presentados hasta el momento. . .
Toda vez que se utiliza una operacion parcial, hay que tomar una de dos medidas:
o bien se busca garantizar la precondicion de la misma de alguna manera (como
en el ejercicio 2.2.5) o bien se trasladan los requerimientos de dicha operacion a
la operacion que se esta definiendo. Veremos esto con cuidado mas adelante.
Para Reflexionar
Otro comando que describe una operacion parcial es el que permite al cabezal
moverse por el tablero. Esta operacion es basica para poder operar en mas de
una celda. El comando Mover(Norte) describe la accion de que el cabezal se
debe desplazar una celda hacia el norte, si hay alguna celda en esa direccion. El
formato general esta dado por esta definicion
Definicion 2.2.17. El comando Mover(< dir >) indica al cabezal que debe mo-
verse una celda en la direccion < dir >, si es posible.
Las direcciones posibles (los valores que puede tomar < dir >) son Norte, Sur,
Este y Oeste.
Definicion 2.2.18. Los valores posibles para una direccion son Norte, Sur, Este
y Oeste.
Poner(< color >) Ninguna Pone una bolita del color indica-
(operacion total) do en la celda actual
Que exista una boli-
Sacar(< color >) Saca una bolita del color indica-
ta del color indicado
do de la celda actual
en la celda actual
Que exista una cel- Mueve el cabezal una celda en
Mover(< dir >) da en la direccion la direccion indicada respecto
indicada de la celda actual
procedure Main()
{
Mover(Norte); Poner(Negro)
Mover(Este); Poner(Negro)
Mover(Sur); Poner(Negro)
Mover(Oeste); Poner(Negro) Recordar que en realidad sera co-
} rrecto decir que el programa descri-
be la tarea de dibujar un cuadrado
negro.
Actividad de Programacion 8
procedure DibujarLineaHaciaElNorte()
{
Mover(Norte); Poner(Negro)
Mover(Norte); Poner(Negro)
}
procedure DibujarLineaHaciaElEste()
{
Mover(Este); Poner(Negro)
Mover(Este); Poner(Negro)
}
procedure DibujarLineaHaciaElSur()
{
Mover(Sur); Poner(Negro)
Mover(Sur); Poner(Negro)
}
procedure DibujarLineaHaciaElOeste()
{
Mover(Oeste); Poner(Negro)
Mover(Oeste); Poner(Negro)
}
Para Reflexionar
procedure TrasformarLineaHaciaElNorte()
{
Mover(Norte); Sacar(Negro); Poner(Rojo)
Mover(Norte); Sacar(Negro); Poner(Rojo)
}
procedure TrasformarLineaHaciaElEste()
{
Mover(Este); Sacar(Negro); Poner(Rojo)
Mover(Este); Sacar(Negro); Poner(Rojo)
}
procedure TrasformarLineaHaciaElSur()
{
Mover(Sur); Sacar(Negro); Poner(Rojo)
Mover(Sur); Sacar(Negro); Poner(Rojo)
}
procedure TrasformarLineaHaciaElOeste()
{
Mover(Oeste); Sacar(Negro); Poner(Rojo)
Mover(Oeste); Sacar(Negro); Poner(Rojo)
}
procedure CuadradoNegroARojo()
{
TrasformarLineaHaciaElNorte()
TrasformarLineaHaciaElEste()
TrasformarLineaHaciaElSur()
TrasformarLineaHaciaElOeste()
}
El primer detalle a observar es que si bien el procedimiento solicitado es sola-
mente CuadradoNegroARojo, la solucion involucra la definicion de cinco procedi-
mientos diferentes. Esto no es parte del requerimiento original explcito, pero una
buena practica de programacion se consigue eligiendo convenientemente las ta-
reas a describir, y nombrandolas adecuadamente (volveremos sobre este punto
en el apartado 2.3).
Otro detalle a observar tiene que ver con como probar este procedimiento.
Puesto que la precondicion de CuadradoNegroARojo es que exista un cuadrado
negro de lado tres ya dibujado en el tablero, no tendra sentido utilizar como
programa Main
procedure Main()
{
VaciarTablero()
IrAlOrigen()
CuadradoNegroARojo()
}
pues este programa siempre fallara. Se requiere, en cambio, asegurar primero la
precondicion de CuadradoNegroARojo, utilizando alguna otra forma. Una de ellas,
por ejemplo, es utilizar algun otro procedimiento para preparar el tablero antes de
llamar al procedimiento a probar, como en
procedure Main()
{
VaciarTablero()
IrAlOrigen()
DibujarCuadradoNegro()
CuadradoNegroARojo()
}
Otra de las formas, si la herramienta lo permite, es tener un tablero predefinido
donde el cuadrado negro ya ha sido dibujado a partir del origen, y entonces usar
como procedimiento principal simplemente
procedure Main()
{
IrAlOrigen()
CuadradoNegroARojo()
}
Pero como esto es dependiente de cada herramienta, no nos extenderemos en
estas alternativas. Sera tarea del estudiante buscar la forma de probar los proce-
dimientos que se solicitan en las actividades de programacion.
Actividad de Programacion 10
otros para indicar que los primeros estan subordinados a los segundos. Por ejem-
plo, al bloque nombrado por la definicion de un procedimiento simple lo hemos
puesto hasta ahora siempre debajo de la lnea que indica que se esta definiendo
el mismo.
Desde el punto de vista de la herramienta que ejecuta los programas, es lo
mismo un caracter de espaciado que quinientos, ya que lo que importa es po-
der distinguir que hay mas de un elemento uno a continuacion del otro, y no a
que distancia estan. Los caracteres de espaciado estan dados por los espacios
en blanco, los fines de lnea y los tabuladores. Entonces, son equivalentes el
codigo
procedure PintarCelda()
{
Poner(Rojo)
Poner(Rojo)
}
y el codigo
y tambien el codigo
procedure
PintarCelda()
{
Poner(Rojo)
Poner(Rojo)
A la forma exacta en que el codigo es mostrado en dos dimensiones, en funcion Indent tambien significa dejar mar-
de variar el numero de caracteres de espacio que se utilizan, se lo denomina cas en una superficie, ademas de
indentar el codigo. El termino indentar es un neologismo basado en el termino sangrar.
ingles indent, que significa sangrar, como en el castellano sangra. Entonces, in-
dentar un codigo es sangrarlo, o sea, comenzar ciertas lneas mas adentro que
otras, como se hace en el primer parrafo de los textos en castellano; en otros
terminos, es agregarle sangras al texto del codigo. Dado que el termino caste-
llano sangrar es sinonimo tambien de, y mas comunmente reconocido como, per-
der sangre, muchos programadores de habla castellana (pero no los espanoles)
Los espanoles son extremadamen- preferimos usar el termino indentar.
te recelosos de los neologismos
o anglicismos, y traducen todo de Para Ampliar
manera literal. Esto resulta confu-
so, pues hablan de sangrado de
codigo, lo cual a nosotros nos hace Buscar en la web discusiones sobre indentacion (o sangrado)
pensar en codigo al que se le saca de codigo. El primer sitio que sale en Google es la Wikipedia:
sangre. . .
http://es.wikipedia.org/wiki/Indentacion
que dice
Indentacion es un anglicismo (de la palabra inglesa indentation)
de uso comun en informatica que significa mover un bloque de
texto hacia la derecha insertando espacios o tabuladores para
separarlo del texto adyacente, lo que en el ambito de la impren-
ta se ha denominado siempre como sangrado o sangra. En los
lenguajes de programacion de computadoras la indentacion es
un tipo de notacion secundaria utilizado para mejorar la legi-
bilidad del codigo fuente por parte de los programadores, te-
niendo en cuenta que los compiladores o interpretes raramente
consideran los espacios en blanco entre las sentencias de un
programa. Sin embargo, en ciertos lenguajes de programacion
como Haskell, Occaml y Python, la indentacion se utiliza pa-
ra delimitar la estructura del programa permitiendo establecer
bloques de codigo. Son frecuentes discusiones entre progra-
madores sobre como o donde usar la indentacion, si es mejor
usar espacios en blanco o tabuladores, ya que cada programa-
dor tiene su propio estilo.
Como con todas las cuestiones de estilo, la percepcion sobre lo que es adecua-
do y lo que no vara con las personas, e incluso con el contexto. Algunas formas
son claramente incorrectas (como la tercer variante que vimos antes), pero otras
son solo cuestion de costumbre. Por ejemplo, en este cuadernillo hemos elegido
colocar el bloque nombrado por un procedimiento en una lnea independiente al
encabezado de su declaracion, y en el caso que el bloque ocupe mas de una
lnea, con las llaves en sus propias lneas, y uno o dos caracteres mas adentro
que la palabra procedure; los comandos del bloque van entre medio de ambas
llaves, otros dos caracteres mas adentro. El resultado, que ya hemos visto nume-
rosas veces, es el siguiente
procedure DibujarLinea()
{
Poner(Negro); Mover(Norte)
Poner(Negro); Mover(Norte)
}
Sin embargo, otros estilos son posibles. El mismo codigo, indentado por un pro-
gramador de la comunidad Java, habra sido
Java es uno de los principa-
procedure DibujarLinea() { les lenguajes de programacion de
Poner(Negro); Mover(Norte) hoy da. Para conocer mas so-
Poner(Negro); Mover(Norte) bre el lenguaje Java, ver el sitio
}
Observe como la llave de apertura se coloca en la misma lnea que el encabeza- www.java.com/es
do, y la correspondiente de cierre a la misma altura que la palabra procedure.
Otra variacion de estilo, que usaremos en ocasiones, consiste en que, cuando
el codigo del procedimiento es breve, se muestra en una unica lnea, como en
o a veces
procedure DibujarLineaCorta()
{ Poner(Negro); Mover(Norte) }
El aspecto de como escribir nombres complejos tiene varias opciones mas o me-
nos estandarizadas en la comunidad de programadores. Por ejemplo, en este
cuadernillo hemos elegido usar CamelCase, que como vimos, es un estilo de es-
critura para identificadores compuestos de varias palabras, y donde cada palabra
se escribe con mayusculas.
Otro estilo muy difundido es utilizar guiones bajos (underscores en ingles)
para separar las palabras, en lugar de poner en mayusculas cada una de las
letras. Comparemos, por ejemplo,
UnIdentificadorEnCamelCase con
http://whathecode.wordpress.com/2011/02/10/
camelcase-vs-underscores-scientific-showdown/
Como dijimos antes, ningun nombre que se elija esta realmente mal, pues
no es importante para la ejecucion del programa, sino que es mas adecuado o
mas inadecuado para la lectura; y el grado de adecuacion depende mucho del
gusto del que lo lee. Sin embargo, al evaluar un programa, existen elecciones
claramente incorrectas pues no solo no contribuyen a la legibilidad, sino que
confunden. Por ejemplo, observe el siguiente codigo
procedure PonerBolitaRoja() { Sacar(Verde) }
procedure Main() { Poner(Verde); PonerBolitaRoja() }
Que hace este programa? Es correcto? Se da cuenta que la eleccion del
nombre PonerBolitaRoja es terriblemente inadecuada, porque lleva a pensar
en otra idea? Pero sin embargo el codigo funciona! Entonces diremos que este
codigo esta mal, porque su eleccion de nombres es enganosa, aunque el codigo
funcione.
Leer con Atencion
brindar informacion diversa acerca del codigo, como ser el autor del mismo,
la fecha de creacion, etcetera.
{-
Autor: Fidel
Fecha: 08-08-08
-}
procedure DibujarLineaHaciaElNorte()
{-
PRECONDICION:
Debe haber al menos dos celdas al Norte de la actual.
(O sea, el cabezal no puede encontrarse ni en la ultima
ni en la anteultima fila)
-}
{
-- No se dibuja en la celda incial
Mover(Norte); Poner(Negro) -- Dibuja en la celda
-- al Norte de la inicial
Mover(Norte); Poner(Negro) -- Dibuja en la celda dos
-- lugares al Norte de la
-- inicial
Observar que el codigo efectivo (aquel que no sera ignorado durante la ejecucion)
es identico al ofrecido antes. Sin embargo, los comentarios ayudan a entender el
proposito de cada parte.
Es importante destacar que, puesto que los comentarios son ignorados en la
ejecucion, debe verificarse al leer un programa que los comentarios sean validos
respecto de los comandos. Es una practica mala, pero demasiado comun, el de-
jar comentarios desactualizados al modificar codigo. Por ejemplo, supongamos
que utilizamos este ultimo procedimiento comentado como base para un proce-
dimiento similar utilizado en la solucion del ejercicio 2.2.7. Para ello, copiamos el
programa en otro archivo, y realizamos algunas modificaciones, para obtener:
{-
Autor: Fidel
Fecha: 08-08-08
-}
procedure DibujarLineaHaciaElNorte()
{-
PRECONDICION:
Debe haber al menos dos celdas al Norte de la actual.
(O sea, el cabezal no puede encontrarse ni en la ultima
ni en la anteultima fila)
-}
{
-- No se dibuja en la celda incial
Mover(Norte); Poner(Negro) -- Dibuja en la celda
-- al Norte de la inicial
Mover(Norte); Poner(Negro) -- Dibuja en la celda dos
-- lugares al Norte de la
-- inicial
Mover(Norte); Poner(Negro) -- Dibuja en la celda dos
-- lugares al Norte de la
-- inicial
Observar que el codigo fue obtenido copiando y pegando (suele decirse, con
cut&paste), y luego alterando algunas partes
Para Reflexionar
Estas alteraciones llevan a que haya por lo menos tres comentarios desactualiza-
dos en este codigo. El primero es la precondicion, puesto que al agregar coman-
dos de movimiento, la precondicion cambio, y sin embargo el comentario no fue
alterado. El segundo es el comentario de lnea que se asocia al tercer grupo de
comandos: como fue obtenido por cut&paste y no fue modificado, indica lo mismo
que el anterior, pero su efecto es diferente. El tercero es el comentario de cierre, La forma en que la mayora lo lee-
sobre la posicion final del cabezal. Si ademas este codigo hubiera sido modifi- mos es catan peist.
cado por otra persona diferente de Fidel, o en otra fecha, el comentario sobre
el autor y la fecha tambien estaran desactualizados. Puede verse en el grafi-
co G.2.10 las indicaciones de que comentarios estan desactualizados. Puesto
que los comentarios estan en lenguaje natural, y el proposito de un programador
no es analizable automaticamente, este tipo de situaciones no se pueden detec-
tar en ninguna herramienta. Es absoluta responsabilidad del programador que
sus comentarios esten actualizados, sean pertinentes y utiles.
La practica de comentar el codigo de manera adecuada es extremadamen-
te importante cuando varias personas trabajan sobre un programa, ya sea si-
multaneamente, o a lo largo de algun perodo de tiempo. Es recomendable co-
mentar todo codigo que se escriba de manera correcta. Por otra parte, los comen-
tarios desactualizados son mas daninos que la ausencia de comentarios, puesto
que pueden inducir a ideas incorrectas. Es por ello recomendable no desestimar
2.4. Ejercitacion
En este apartado se enuncian una serie de ejercicios de practica adicionales a
los ya dados durante la Unidad. Para su correcta resolucion son necesarios todos
los elementos aprendidos en los apartados anteriores. A traves de su resolucion
iremos repasando algunos de los conceptos principales, e incorporando pregun-
tas que prepararan el material de unidades posteriores.
Actividad de Programacion 12
El primer ejercicio es simplemente una gua para recordar como definir un pro-
cedimiento, para experimentar como probarlo en un Main, y para preparar ideas
que luego se utilizaran en ejercicios posteriores.
Ejercicio 2.4.1.
Ejercicio 2.4.2.
Para Reflexionar
Recuerde que una vez que definio la forma de realizar una tarea, siempre
puede reutilizar dicha definicion en ejercicios posteriores. Al probar su
programa no olvide incluir todas las definiciones necesarias en el mismo.
Ejercicio 2.4.3.
La celda lindante en direccion < dir > es la primera celda en la direccion dada,
a partir de la celda actual. Por ejemplo la celda lindante al Norte es la primera
celda al Norte de la celda actual.
Escribir el procedimiento PonerAzulAlNorteYMoverse que ponga una bolita
de color azul en la celda lindante al Norte y se quede en esa posicion. Este pro-
cedimiento siempre funciona? Que requerimientos debe cumplir? Cual sera
su precondicion?
Ejercicio 2.4.4.
Para Reflexionar
Ejercicio 2.4.5.
Para Reflexionar
Para Reflexionar
Para Reflexionar
Para Reflexionar
Ejercicio 2.4.10.
Escribir un procedimiento LetraE, que pinte una letra E con acuarela marron,
Para Reflexionar
Ejercicio 2.4.12.
Para Reflexionar
Ejercicio 2.4.13.
Para Reflexionar
Ejercicio 2.4.14.
Supongamos que cada celda del tablero representa una seccion del cantero de 1
metro de longitud. Ademas, representaremos flores con combinaciones de boli-
tas. Las rosas se representan con 1 bolita de color rojo, las violetas se represen-
tan con 1 bolita de color azul, y los girasoles se representan con 1 bolita de color
negro. Se desea armar un cantero de flores de 3 metros de longitud, donde cada
metro del cantero posee 5 rosas, 8 violetas y 3 girasoles.
Escribir el procedimiento ArmarCantero que cumpla con esta representacion.
Para Reflexionar
Ejercicio 2.4.15.
Modificar el programa del ejercicio 2.4.14 para que ahora las flores se represen-
ten utilizando el siguiente esquema. Las rosas se representan con 3 bolitas de
color rojo y 1 de color negro, las violetas se representan con 2 bolitas de color
azul y 1 de color rojo, y los girasoles se representan con 3 bolitas de color negro
y 2 de color verde.
Para Reflexionar
El ultimo ejercicio busca combinar todos los elementos vistos hasta ahora. Por un
lado, usted debe decidir acerca de la representacion de los elementos. Por otro,
debera utilizar adecuadamente procedimientos para representar cada parte, no
solo la representacion de los elementos, sino tambien las acciones involucradas.
Finalmente, debe establecer las precondiciones necesarias, y al probarlo, ga-
rantizar que las mismas se cumplen de alguna manera. No olvide comentar el
codigo!
Ejercicio 2.4.16.
bolitas de color negro, la forma de eliminarlos debera ser quitar esa cantidad de
bolitas de ese color.
Para Reflexionar
Procedimientos, funciones y
parametrizacion
3.1. Procedimientos
En la Unidad anterior aprendimos como escribir procedimientos simples (defini-
cion 2.2.9), y trabajamos con ellos, aprendiendo como utilizarlos adecuadamen-
te. Vimos que los procedimientos simples eran una forma de nombrar coman-
dos compuestos para identificarlos como tareas de nuestro problema. Y tambien
vimos que ademas de los comandos, los lenguajes posean expresiones para
describir valores, entidades para representar informacion.
En este apartado vamos a agregar la idea de parametro a los procedimientos,
y comenzaremos a estudiar su potencial.
G.3.1. Programa que dibuja un cuadrado negro, con 4 procedimientos para las
lneas
G.3.3. Programa que dibuja un cuadrado negro con un unico procedimiento pa-
rametrizado para dibujar lneas
procedure CuadradoNegro()
{- PROPOSITO:
* dibuja un cuadrado Negro de lado 2
PRECONDICION:
* el cabezal no se encuentra ni en la ultima fila
ni en la ultima columna
-}
{
DibujarLineaHaciaEl(Norte)
DibujarLineaHaciaEl(Este)
DibujarLineaHaciaEl(Sur)
DibujarLineaHaciaEl(Oeste)
}
que es mucho mas conciso, ya que evita la repeticion del codigo de dibujar lneas
solo para tener diferentes direcciones. Observar que dir es el parametro en la
definicion de DibujarLineaHaciaEl y se lo utiliza en el comando Mover(dir);
el nombre utilizado no es importante, pero debe indicar de alguna manera la
intencion de para que se utilizara el parametro. Al invocar el procedimiento pa-
rametrico DibujarLineaHaciaEl se utiliza un valor especfico de direccion como
argumento en cada caso. El codigo final es equivalente al codigo original, pero
que define solo dos procedimientos, en lugar de cinco!
El mecanismo utilizado para esta definicion, llamado abstraccion, consiste en
concentrarse en las similaridades entre diferentes elementos, reconociendolos
como casos particulares de una misma idea. El uso de parametros permite iden-
tificar en que partes son diferentes los elementos, y el proceso de invocacion
de un procedimiento con argumentos (valores especficos para los parametros)
permite obtener los elementos particulares a partir de la definicion general. Este
caso particular de abstraccion se conoce con el nombre de parametrizacion, por
el uso de parametros para representar las variaciones de una misma idea.
Que otras nociones son generalizables en el caso de dibujar un cuadrado?
La mas sencilla de todas es el color del cuadrado. El programa definido dibu-
ja un cuadrado negro. Si quisieramos un cuadrado rojo o uno azul, tendramos
que definir otro procedimiento que utilice a su vez un procedimiento que dibu-
je una lnea con la instruccion Poner(Rojo) o Poner(Azul), en lugar de la ac-
tual Poner(Negro). Sin embargo, la unica diferencia entre estos procedimientos,
que dibujan cuadrados de distintos colores, es el color elegido para pintar cada
cuadrado, lo que nos permite parametrizar su color y disenar un procedimiento
general que dibuje un cuadrado de un color que elijamos al invocarlo.
Volviendo al codigo original con cinco procedimientos para dibujar el cuadra-
do, el codigo para generalizar el cuadrado de diferentes colores podra definirse
utilizando procedimientos como los siguientes:
procedure DibujarLineaHaciaNorteDeColor(color)
{- PROPOSITO:
* dibuja una lnea del color indicado de longitud
1 hacia el Norte
PRECONDICION:
* el parametro color es un color
* existe al menos una celda en al Norte
-}
{
Mover(Norte); Poner(color)
procedure DibujarCuadrado()
{- PROPOSITO:
* dibuja un cuadrado Negro de lado 2
PRECONDICION:
* el cabezal no se encuentra ni en la ultima fila
ni en la ultima columna
-}
{
DibujarLineaHaciaNorteDeColor(Negro)
DibujarLineaHaciaEsteDeColor(Negro)
DibujarLineaHaciaSurDeColor(Negro)
DibujarLineaHaciaOesteDeColor(Negro)
}
Otra nocion generalizable es el tamano del cuadrado. Sin embargo, para poder
generalizarla son necesarios comandos mas complejos, por lo cual esta idea se
tratara luego de presentar dichos comandos, en el Apartado siguiente.
Un detalle importante a observar en el uso de parametros es la correspon-
dencia entre el numero de parametros declarados en un procedimiento, y el
numero de argumentos usados para invocarlo. Por ejemplo, el procedimiento
DibujarLineaHacia tiene un unico parametro dir y cuando se invoca dicho pro-
cedimiento se debe suministrar un unico valor; es valido invocar al procedimiento
como DibujarLineaHacia(Norte), as como tambien con el resto de las direc-
ciones. La misma correspondencia debe existir si se usan varios parametros en la
definicion del procedimiento: al invocarlo deben usarse la misma cantidad de ar-
gumentos. Si tomamos el procedimiento de dibujar lneas utilizado en la solucion
al ejercicio 3.1.1
procedure DibujarLineaDeHacia(color,dir)
{- PROPOSITO:
* dibuja una lnea de longitud 1 del color indicado
y en la direccion indicada
PRECONDICION:
* el parametro dir es una direccion y color es un color
Una nocion mas a tener en cuenta es donde tiene sentido utilizar un parametro.
Un parametro permite definir un esquema de procedimiento, nombrando un valor
que sera diferente en cada llamado de dicho procedimiento.
Leer con Atencion
Es por tanto razonable esperar que la validez del parametro sea solo
dentro del cuerpo del procedimiento que lo define. Esta nocion de va-
lidez se conoce con el nombre de alcance (en ingles scope), y es ex-
tremadamente importante, pues es usual intentar utilizar un parametro
fuera de su alcance, provocando errores extranos.
{
repeatWith i in 1..cantidad
{ Poner(Rojo) }
}
Entonces, el comando PonerNRojas(3) pondra 3 bolitas en la celda actual, y el
comando PonerNRojas(10) pondra 10 bolitas.
Actividad de Programacion 3
Para Reflexionar
(a). Tablero a producir como resultado. (b). Tablero a producir como variante.
Actividad de Programacion 5
Actividad de Programacion 6
3.1.3. Ejercitacion
En este subapartado revisamos algunos de los ejercicios de practica de la Unidad
anterior, con el fin de incorporar las nociones de parametros y repeticion.
Actividad de Programacion 7
Actividad de Programacion 8
Al presentar la operacion Poner se haba establecido que era una operacion total,
y ahora resulta que la misma es en realidad parcial. Como debe entenderse este
hecho? Lo que sucede es que los errores producidos por utilizar valores de tipo
distinto al esperado (llamados errores de tipo) pueden ser controlados antes de
la ejecucion del programa. De este control se suele decir que impone el uso de
tipos, pues en el caso de que un programa contenga combinaciones erroneas
de tipos en las expresiones es rechazado sin ejecutarlo.
Leer con Atencion
Para Ampliar
La idea de tipos tambien se aplica a las expresiones. Por ejemplo, la suma solo
es posible realizarla entre numeros. Que sucede si se intenta armar una suma
utilizando un color? Consideremos, por ejemplo, la expresion Verde+1. La misma
no describe a ningun valor. Si se intenta determinar que valor representa esta
expresion, tambien se obtendra la autodestruccion del cabezal.
Para Reflexionar
la suma, +
la resta, -
la multiplicacion, *
la exponenciacion, ^
Actividad 9
Ejercicio 3.2.3. Escribir una expresion sobre numeros que represente la suma
de cuatro veces diez, mas dos. Escribir una expresion sobre numeros que re-
presente la suma de cuatro veces el numero resultante de sumar diez mas dos.
Que diferencias se pueden observar en las expresiones? Y en los resultados?
Las unicas operaciones especiales de los colores son el calculo de los valores
mnimo y maximo.
Las operaciones de mnimo y maximo sobre un tipo dado permiten armar repeti-
ciones indexadas que recorren todos los valores del tipo, sin tener que recordar
el orden particular. Por otra parte, dichos programas expresan con mayor ade-
cuacion el hecho de que se pretende recorrer todos los valores del tipo y no solo
los que posea la version actual del lenguaje. Y siempre es una buena idea que
los programas expresen con mayor precision el proposito del programador.
Actividad de Programacion 10
Ejercicio 3.2.8. Escribir una expresion que determine si dos parametros de ti-
po direccion, llamados por ejemplo direccionOriginal y direccionNueva, son
diferentes.
Ejercicio 3.2.9. Escribir una expresion que determine si un numero esta entre 0
y 100. Para ello, combinar dos expresiones relacionales mediante una conjuncion
booleana.
Por ejemplo, hayBolitas(Rojo) puede ser True o False, dependiendo del es-
tado de la celda actual: si en la celda hay alguna bolita de color Rojo, enton-
ces esta expresion valdra True; si por el contrario, no hay ninguna, esta expre-
sion valdra False. Si hayBolitas(Rojo) vale False, entonces nroBolitas(Rojo)
valdra 0, y si nroBolitas(Rojo) es distinto de 0, entonces hayBolitas(Rojo)
valdra True. De manera similar a hayBolitas, puedeMover(Sur) valdra True si el
cabezal no se encuentra en la fila de mas abajo, y False si se encuentra en dicha
fila, y de manera analoga para las restantes direcciones. Ejercitaremos el uso
de estas expresiones luego de ver una herramienta nueva para armar comandos
complejos.
Esto completa el repertorio de expresiones de G OBSTONES, con las cuales
se pueden realizar una serie importante de programas.
Actividad 12
Actividad de Programacion 13
Realice los ejercicios 3.2.12 y 3.2.13 y utilcelos para quitar todas las
bolitas rojas y negras de la celda actual, y la totalidad de las bolitas de
la celda lindante al Norte.
Para Reflexionar
alternativa con base en una condicion. Por ejemplo, en este caso, el comando se
leera si no hay una bolita roja (flor) en la celda actual, entonces poner una bolita
roja (flor) y una negra (fertilizante), y si ya hay flores, poner solo una bolita negra
(fertilizante).
La forma general del comando if-then-else esta dada por la siguiente defi-
nicion:
Definicion 3.2.2. El comando de alternativa condicional (o simplemente condi-
cional) if-then-else tiene la siguiente forma:
if (< bool >)
< unBloque >
else
< otroBloque >
siendo < bool > una expresion que describe un valor de verdad (booleano), y
donde los bloques < unBloque > y < otroBloque > son bloques de codigo cua-
lesquiera (que normalmente son diferentes, aunque podran ser iguales). Al blo-
que < unBloque > se lo denomina rama verdadera (o rama del then) y al bloque
< otroBloque > se lo denomina rama falsa (o rama del else).
El comando if-then-else describe la decision de realizar la accion descrita por
el bloque < unBloque >, en caso que la condicion sea True, o de realizar la accion
descrita por < otroBloque > en caso que la condicion sea False. Observar que
los parentesis son necesarios siempre alrededor de la condicion.
Actividad de Programacion 14
Una variante util del comando if-then-else es cuando no existe una accion
alternativa para la rama del else. En ese caso, la alternativa se transforma real-
mente en un comando condicional (o sea, un comando que solo se ejecuta si se
cumple cierta condicion). Esto es extremadamente util para evitar que una opera-
cion parcial provoque la autodestruccion del cabezal. Para ello, basta con utilizar
como condicion del if-then-else una expresion < condicion > que valga True
cuando la precondicion de la operacion dada en la rama del then sea valida. Por
ejemplo, si se quiere sacar una bolita, puede preguntarse primero si la misma
existe, de la siguiente manera:
if (hayBolitas(Rojo)) { Sacar(Rojo) }
Notar que la precondicion de Sacar(Rojo) es que haya bolitas rojas, y la condi-
cion del if-then es una expresion que vale True siempre que haya bolitas rojas;
Definicion 3.2.4. Una funcion simple puede ser usada como una expresion. La
forma de invocarla es escribir su nombre seguida por parentesis, de la siguiente
manera
< funcName >()
donde < funcName > es el nombre de alguna funcion declarada en el programa.
-- como argumento
}
Condiciones booleanas
donde < expBooleana > es cualquier expresion cuyo resultado sea True o False.
Con esta operacion, por ejemplo, podra escribirse una condicion que verifique
si en la celda actual no hay bolitas rojas como: not hayBolitas(Rojo). Esta
expresion valdra True cuando el numero de bolitas rojas en la celda actual sea
0, y False en caso contrario, extactamente lo opuesto a hayBolitas(Rojo).
La expresion True && True tendra como resultado True, y las expresiones True
&& False, False && True y False && False tendran como resultado False. De
esta manera se pueden construir condiciones complejas, como preguntar si en
la celda actual hay bolitas rojas y verdes al mismo tiempo: hayBolitas(Rojo) &&
hayBolitas(Verde).
Ejercicio 3.2.20. Escribir una funcion hayFlores() que retorne verdadero si en
la celda actual hay alguna flor, y falso en caso de que no haya ninguna. Una flor se
representa mediante una bolita de color Rojo y una de color Verde. La condicion
de que haya flores puede verificarse, por tanto, verificando que haya bolitas de
ambos colores en la celda. Observar que no se pide verificar que la cantidad de
bolitas verdes y rojas coincida, sino solo que haya de ambas! Y tambien que no
molesta que haya bolitas de otros colores.
Las expresiones True || True, True || False y False || True tendran como
resultado True, y la expresion False || False tendra como resultado False.
Con la disyuncion se puede pregunta si en la celda actual hay bolitas rojas o
hay bolitas verdes (puede faltar cualquiera de las dos): hayBolitas(Azul) ||
hayBolitas(Negro).
Actividad 16
Ejercicio 3.2.23. Escribir una funcion hayBolitas que retorne verdadero si hay
alguna bolita en la celda actual (no importa su color). Considerar la utilizacion de
una combinacion mas complicada de hayBolitas y ||, y que involucre a los 4
colores. Puede expresar la condicion de alguna otra forma?
Ejercicio 3.2.24. Escribir un procedimiento PintarCeldaMarron que pinte una
celda de color marron (agregando bolitas de los cuatro colores en la celda actual)
solo si no hay bolitas de ningun color. Considerar la utilizacion de la funcion del
ejercicio anterior y una alternativa condicional.
Para Reflexionar
Actividad 17
siendo < funName > un identificador que comienza con minuscula, < params >,
una lista de identificadores que comienzan con minusculas y < expresion >, una
expresion de cualquier tipo basico.
Las funciones con parametros se pueden invocar de manera similar a la vista
para procedimientos con parametros, mediante el uso de argumentos, con la
diferencia, ya mencionada, de que por ser expresiones solo se pueden utilizar en
lugares donde se espera una expresion.
Definicion 3.3.2. Una funcion con parametros puede ser usada como una ex-
presion. La forma de invocarla es escribir su nombre seguida por argumentos, de
la siguiente manera
< funcName >(< args >)
donde < args > es una lista de valores especficos (los argumentos) para los
parametros de la funcion.
Las nociones de concordancia de tipos entre cada argumento y los usos que se
les da a los parametros correspondientes es similar a la vista para los procedi-
mientos.
Por ejemplo, podemos ver si hay mas bolitas de un color que de otro, pero
usando parametros para indicar que colores queremos.
function hayMasQue(color1, color2)
{-
PROPOSITO:
* retorna verdadero si hay mas bolitas del color1
que bolitas del color2 en la celda actual
PRECONDICION:
* Ninguna (es una funcion total)
-}
{
return (nroBolitas(color1) > nroBolitas(color2))
}
Con esta funcion podra verificarse que hubiera mas bolitas rojas que verdes
y mas negras que azules mediante la expresion hayMasQue(Rojo,Verde) &&
hayMasQue(Azul,Negro).
Actividad de Programacion 18
Actividad de Programacion 19
Ejercicio 3.3.2. Escribir una funcion enIntervalo que dados un numero n y dos
numeros inf y sup, retorne verdadero si n esta dentro del intervalo [inf,sup] (o
sea, es mayor o igual a inf y menor o igual a sup).
Definicion 3.3.3. Una funcion con procesamiento es una forma de funcion que
ademas de nombrar a una expresion, realiza previamente algun procesamiento.
La forma de definir una funcion con procesamiento en G OBSTONES es
siendo < funName >, < params > y < expresion > como antes, y < comando >
un comando (que puede ser un comando compuesto como una secuencia de
comandos.
function nroEnemigosAl(dir)
{-
PROPOSITO:
* retorna la cantidad de enemigos en la celda lindante a la
actual en la direccion dir
PRECONDICION:
* hay una celda lindante en direccion dir
-}
{
Mover(dir)
return(nroBolitas(colorEnemigo()))
}
permite utilizar las funciones con procesamiento para retornar informacion, pero
sin tener que preocuparse por las consecuencias del procesamiento.
Leer con Atencion
Por ejemplo, imaginemos una situacion donde queremos agregar en la celda ac-
tual un numero de aliados igual a la cantidad de enemigos en la celda al Norte,
mas uno (por ejemplo, como parte de un programa que expresa nuestra estrate-
gia de defensa en un juego), suponiendo la misma codificacion que vimos antes
(un enemigo se representa con una bolita roja y un aliado con una bolita verde).
El procedimiento podra ser:
procedure EstrategiaDeDefensa()
{-
PROPOSITO:
* agregar tantos aliados en la celda actual como
enemigos hay en la celda lindante al Norte,
mas uno (si hay enemigos)
PRECONDICION:
* hay una celda lindante al Norte
-}
{
if (hayEnemigosAl(Norte))
{ AgregarAliados(nroEnemigosAl(Norte)+1) }
}
Observar que si bien la funcion nroEnemigosAl realiza un movimiento para retor-
nar la cantidad de enemigos en la direccion dada, este movimiento no es refleja-
do por el procedimiento EstrategiaDeDefensa, que solo agrega los aliados en la
celda actual.
Actividad de Programacion 20
function hayEnemigosCercaAlNorte()
{-
PROPOSITO:
* retorna verdadero si hay algun enemigo en las
proximas 3 celdas al Norte de la actual
PRECONDICION:
* hay 3 celdas lindantes al Norte
-}
{
SacarTodas(Azul) -- Elimina todas las bolitas azules,
-- para estar seguro que no hay ninguna
repeatWith i in 1..3
{ if(hayEnemigosAlEnRango(Norte, i))
{ Poner(Azul) } -- Agrega una azul si hay enemigos
}
return(hayBolitas(Azul)) -- Si hay azules, es porque
-- uno de los rangos dio verdadero
}
Observar que se utilizan bolitas azules para indicar el exito de la busqueda. Pues-
to que el procesamiento realizado por la funcion es solo simulado y no real, esta
modificacion de las bolitas azules no sera reflejada en el procedimiento que uti-
lice a hayEnemigosCercaAlNorte. En este ejemplo particular, la funcion podra
haberse escrito simplemente como
function hayEnemigosCercaAl()
{-
PROPOSITO:
* retorna verdadero si hay algun enemigo en las
proximas 3 celdas al Norte de la actual
PRECONDICION:
* hay 3 celdas lindantes al Norte
-}
{
return(hayEnemigosAlEnRango(Norte,1) ||
hayEnemigosAlEnRango(Norte,2) ||
hayEnemigosAlEnRango(Norte,3)
}
Actividad de Programacion 21
3.4. Ejercitacion
En este apartado se enuncia una serie de ejercicios adicionales a los ya dados.
Al igual que en ejercitaciones previas, para su correcta resolucion son necesarios
todos los elementos aprendidos en los apartados y unidades anteriores.
Actividad de Programacion 22
(a). Tablero inicial representando el dis- (b). Tablero final representando el ecuali-
play de un ecualizador. zador con intensidades.
Las torres se mueven en lnea recta cualquier numero de casillas, pero solo
en direccion ortogonal. Las torres no pueden saltar las propias piezas ni
las piezas enemigas.
Ademas, si una pieza se mueve sobre una casilla ocupada por una pieza del opo-
nente, captura a dicha pieza, que se retira permanentemente del tablero, exacta-
mente como en ajedrez.
Tambien como en el ajedrez, se dice que el rey de un jugador esta en jaque
si puede ser capturado por una pieza del oponente. El objetivo del juego es dar
jaque mate, que consiste en dar jaque al rey del oponente, de tal manera que le
resulte imposible evitar el jaque.
El tablero del juego se representara con el tablero de G OBSTONES. Las piezas
del primer jugador se representaran con bolitas de color Rojo y las del segundo
con Negro; el numero de bolitas dependera de la clase de pieza en cuestion
(1 = visir, 2 = torre, 3 = rey). Las bolitas de color Verde y Azul se reservaran para
marcar posiciones del tablero.
Ejercicio 3.4.3. Implementar las siguientes funciones auxiliares que se usaran
en el resto de los ejercicios del Procedrez.
visir() que devuelve 1.
torre() que devuelve 2.
rey() que devuelve 3.
hayPieza() que devuelve True si hay una pieza en la casilla actual.
clasePieza() que devuelve la clase de la pieza en la casilla actual, asu-
miendo que hay una.
colorPieza() que devuelve el color de la pieza en la casilla actual, asu-
miendo que hay una.
marcadaComoDestino() que devuelve True si la casilla actual esta marcada
como destino (con una bolita Azul).
marcadaComoMovimiento() que devuelve True si la casilla actual esta mar-
cada como movimiento (con alguna bolita Verde).
G.3.9. El rey negro puede capturar a la torre roja pero no puede pasar sobre su
propia torre
if (not hayEnemigosAca())
{
Mover(Este) -- No hay enemigos, y puede avanzar
if (not hayEnemigosAca())
-- El nuevo Aca habla de la celda al
-- Este de la original!!
{ ArmarTrinchera() }
else
{ Atacar() }
}
else
{ -- Hay enemigos, y debe huir o esconderse
if (elCaminoEstaDespejado(Norte)))
{ Mover(Norte) }
else
{ Esconderse() }
}
procedure InvadirPosicionAlEste()
{- PROPOSITO:
* avanza 1 celda al Este y al llegar, decide si arma
una trinchera (si no hay enemigos) o ataca al enemigo.
PRECONDICION:
* hay una celda al Este
-}
{
Mover(Este)
if (not hayEnemigosAca())
{ ArmarTrinchera() }
else
{ Atacar() }
}
procedure HuirOEsconderse()
{- PROPOSITO:
* decide si huir hacia el Norte o esconderse, en base
a las condiciones del camino
PRECONDICION:
* hay una celda al Norte
-}
{
if (elCaminoEstaDespejado(Norte)))
{ Mover(Norte) }
else
{ Esconderse() }
}
y luego construir el condicional como
if (not hayEnemigosAca())
{ InvadirPosicionAlEste() }
else
{ HuirOEsconderse() }
Actividad de Programacion 1
4 -> { MinimizarVentana() }
_ -> { NoHacerNada() }
En este caso, la funcion decodificarCelda devolvera 1 si en la celda actual
hay bolitas verdes, 2 si hay bolitas azules pero no verdes, 3 si hay bolitas ne-
gras pero no azules ni verdes, 4 si hay solo bolitas rojas, y cualquier otro nume-
ro (por ejemplo, 0) si no hay bolitas en la celda actual (para definir la funcion
decodificarCelda en G OBSTONES hace falta alguna forma de recordar valores,
por lo que volveremos a ella despues de presentar la idea de memoria.) Final-
mente, el procedimiento NoHacerNada no tiene ningun efecto.
En G OBSTONES existe un coman-
do predefinido que no hace nada. Definicion 4.1.1. El comando de alternativa indexada (tambien conocido como
Por razones historicas, el mismo se sentencia case) tiene la siguiente forma:
denomina Skip. Tambien puede im-
plementarse con otros comandos, case (< indexExp >)
por ejemplo, poniendo y sacando < val1 > -> < bloque1 >
una bolita de cierto color de la celda
actual.
..
.
< valn > -> < bloquen >
-> < bloqueDefault >
siendo < indexExp > una expresion que describe un valor de alguno de los ti-
pos basicos, < val1 > a < valn >, una serie de valores de ese tipo, y < bloque1 >,
< bloquen > y < bloquedefult >, una serie de bloques de codigo cualesquiera (que
normalmente son diferentes, aunque podran ser iguales). Al bloque < vari > se
lo denomina rama i-esima (o rama del valor < vali >), para cada i entre 1 y n, y
al bloque < bloqueDefault > se lo denomina rama por defecto (o rama default).
el case debera contener igualmente la rama default, pero con codigo que jamas
se ejecutara:
procedure CodificarDirAlternativo(dir)
{
case (dir) of
Norte -> { PonerN(Verde,1) }
Sur -> { PonerN(Verde,2) }
Este -> { PonerN(Verde,3) }
Oeste -> { PonerN(Verde,4) }
_ -> { BOOM("Es imposible que suceda esto!") }
}
Sin embargo, es mucho mas comodo escribir esta construccion mediante el co-
mando case. En algunos lenguajes donde no existe el comando case, existe una
forma de alternativa condicional que permite varias ramas en el if mediante la P YTHON por ejemplo.
palabra clave elif (abreviatura de else if; ver unidad 5).
Para Reflexionar
Actividad de Programacion 2
procedure CodificarDireccionDelEnemigo()
{- PRECOND:
* no hay bolitas verdes en la celda actual
* solo una de las celdas contiguas tiene enemigos
-}
{
repeatWith dir in minDir()..maxDir()
{
if (puedeMover(dir))
{
if (hayEnemigosAl(dir))
{ Codificar(dir) }
}
}
}
Se puede observar que hay una repeticion sobre las 4 direcciones, para verificar
por turnos en las 4 celdas contiguas. Pero que sucede si la celda actual no tiene
Actividad de Programacion 3
Actividad de Programacion 4
Para Reflexionar
Actividad de Programacion 5
Realice los ejercicios 4.2.2 y 4.2.3, y verifique que obtienen los mismos
resultados que los originales que mejoran.
En el caso del triangulo, segun la solucion que uno adopte, al invocar el proce-
donde < condicion > es una expresion booleana y < bloque > un bloque cualquie-
ra al que se denomina cuerpo de la repeticion.
El efecto del comando while es la repeticion del comando descrito por el < bloque >
mientras la < condicion > sea verdadera. Para obtener este efecto, la ejecucion
del comando comienza evaluando la < condicion > en el estado actual. Si esta
evaluacion resulta verdadera (o sea, la expresion < condicion > evalua a True),
se realiza una iteracion del comando descrito por el < bloque >, y a continuacion
se vuelve a evaluar la condicion. Esto ultimo se repite hasta tanto la condicion
resulte falsa, en cuyo caso termina la ejecucion del comando. Observar que es
necesario que el bloque del cuerpo altere el estado de tal manera que la condi-
cion llegue a resultar falsa en algun momento.
La repeticion condicional es util cuando se trata de realizar una tarea repetitiva
de la que no se sabe a priori cuantas veces debe repetirse (o sea, no se puede
generar un rango sobre el cual realizar la iteracion). El ejemplo mas sencillo de
uso de repeticion condicional es llevar el cabezal hasta un borde del tablero. El
siguiente codigo lleva el cabezal hasta el borde superior:
procedure CabezalAlTopeDeLaColumna()
{- PROPOSITO:
* ilustrar el uso de while
* llevar el cabezal a la ultima fila de la columna actual
PRECONDICION:
* es una operacion total
-}
{
while (puedeMover(Norte))
{ Mover(Norte) }
}
Observar que no hay manera de realizar esta tarea con una repeticion indexa-
da pues no se conoce de antemano el numero de celdas que debera moverse
el cabezal. Asimismo, el cuerpo del while modifica el estado, y en determinado
momento esa modificacion hace que la condicion pase a ser falsa, dando por fi-
Esto es as porque el tablero es fi- nalizada la ejecucion del comando. Esta tarea no podra hacerse con repeticion
nito. indexada, pues no se conoce el tamano del tablero, ni hay forma de determinar
la posicion de la celda actual. Pero s podra parametrizarse, lo cual se evidencia
en el proximo ejercicio.
Actividad de Programacion 6
procedure LaBuenaPipa()
{- PROPOSITO:
* ilustrar una repeticion cuya ejecucion no termina
PRECONDICION:
* Falsa: el programa jamas termina, por lo que nunca
produce ningun resultado
-}
{
QueresQueTeCuenteElCuentoDeLaBuenaPipa()
while (True)
{
YoNoDije_True_Dije_QueresQueTeCuenteElCuentoDeLaBuenaPipa()
}
}
Donde los dos procedimientos internos son cualesquiera que definan operacio-
nes totales. Es claro que como la respuesta es siempre la misma, este cuento
seguira para siempre. Esta capacidad de ejecutar infinitamente es equiparable a
la autodestruccion del cabezal, en tanto y en cuanto no produce un tablero deter-
minado. Sin embargo, su manifestacion es diferente, pues se limita a mantener
una apariencia de trabajo cuando en realidad no hay ningun trabajo que termine
dando beneficios. A pesar de tener esta manifestacion diferente, la precondicion
de un procedimiento debe incluir las condiciones para asegurar que todas las
repeticiones condicionales terminan. Por ejemplo, considerar el siguiente codigo:
Observar que la condicion establece que el valor de los parametros debe ser tal
que no sean direcciones opuestas. Si las direcciones son opuestas (por ejemplo,
una es Norte y la otra es Sur), los efectos de ambos Mover se anularan, y la
repeticion no terminara nunca, provocando la ejecucion infinita. En cualquier otro
caso los efectos se iran acumulando haciendo que a la larga se alcance el borde
del tablero, por lo que el procedimiento se dentendra.
Para controlar este poder de la repeticion condicional, presentamos a conti-
nuacion la idea de recorrido.
Es usual que muchas veces al pensar una tarea que involucra repeticion, ten-
gamos en mente alguna secuencia de elementos. Por ejemplo, si buscamos pro-
cesar todas las celdas de una columna pintando cada una de ellas de un color
determinado, la secuencia en cuestion es la secuencia de celdas de la columna
actual. En ese caso, el programa podra escribirse como:
procedure PintarColumna(color)
{- PROPOSITO:
* pinta una columna entera con bolitas de color
PRECONDICION:
* ninguna, es una operacion total
-}
{
-- empieza arriba de todo para estar seguro
-- que las procesa todas
CabezalAlTopeDeLaColumna()
Actividad de Programacion 7
Actividad de Programacion 8
Ejercicio 4.2.6. Completar el codigo anterior. Para ello, debe escribir la funcion
llegoALaUltimaFila, que establece si el cabezal se encuentra en la fila mas al
Este (o sea, no puede moverse mas hacia el este) y tambien el procedimiento
CabezalALaPrimeraColumna que lleva el cabezal a la primera columna del tablero
(similar al procedimiento CabezalATopeDeLaColumna).
Este esquema de repeticion donde se realiza una tarea para cada uno de una
serie de elementos se denomina recorrido, pues recorre la secuencia de elemen-
tos de a uno, procesando de alguna forma cada uno de ellos. El esquema que
siguen todos los recorridos es el siguiente:
procedure RecorridoGenerico()
{- PROPOSITO:
* recorre una secuencia de elementos genericos, segun
las definiciones que se den a las partes
PRECONDICION:
* depende de las definiciones que se den a las partes
-}
{
IniciarRecorrido()
-- todo lo necesario para recorrer los elementos:
-- ubicarse en el primero de ellos,
-- preparar lo que haga falta, etc.
FinalizarRecorrido()
-- termina el recorrido, cerrando lo necesario
-- y completando el trabajo
}
Los procedimientos utilizados en este codigo son operaciones genericas (al igual
que sus nombres), y deben reemplazarse por las operaciones correspondientes
a la secuencia de elementos que quiere recorrerse. Por ejemplo, en el caso de
PintarColumna, la correspondencia entre las operaciones genericas y las reales
es la siguiente:
Actividad 9
El recorrido tampoco tiene por que procesar todos los elementos. Por ejemplo, si
consideramos que una columna es un cantero, y queremos recorrer cada sector
del cantero (representado cada uno con una celda), colocando fertilizante (bolitas
negras) solo en aquellos sectores donde haya flores (bolitas rojas), el codigo
podra ser el siguiente
procedure FertilizarFlores()
{- PROPOSITO:
* Poner fertilizante en las celdas de la
columna que contengan flores
PRECONDICION:
* ninguna, es una operacion total
-}
{
-- va al tope para saber que las hace todas
IrAlExtremo(Norte)
while (puedeMover(Sur))
-- la condicion dice "no llego a la base"
{
if (hayFlor()) -- solo se agrega en las celdas
{ Fertilizar() } -- que cumplen la condicion
Mover(Sur) -- pasar a la siguiente celda
}
Actividad de Programacion 10
numero de bolitas negras de la celda actual. Las operaciones dadas por los pro-
cedimientos BuscarInicioSendero y VolverAlInicioDelSendero son, en esta
forma simplificada de senderos, nada mas que IrAlOrigen. Entonces, la ope-
racion interesante esMoverASiguienteSector, que es una busqueda por las 4
celdas contiguas de aquella que tenga bolitas negras pero no tenga flores y lue-
go moverse all. Se puede realizar con dos subtareas, de la siguiente manera
procedure MoverASiguienteSector()
{-
PRECOND:
* La celda actual no tiene bolitas verdes
* La celda actual es parte de un camino simple
* Una de los dos sectores contiguos ya fue visitado
y tiene una flor
-}
{
-- Elegir la direccion para seguir y codificarla
repeatWith dir in minDir()..maxDir()
{
if (puedeMover(dir))
{
if (haySectorNoVisitadoAl(dir))
{ CodificarDireccion(dir) }
}
}
DecodificarDireccion()
}
procedure PonerFloresEnSenderoSimple()
{
BuscarInicioSendero() -- iniciar recorrido
while (not esFinDelSendero())
-- no termino el recorrido
{
ColocarRosa() -- procesar elemento
MoverASiguienteSector() -- pasar al siguiente
}
ColocarRosa() -- finalizar recorrido
VolverAlInicio() -- "
}
Actividad de Programacion 11
ColocarRosa,
esFinDelSendero,
BuscarInicioSendero,
VolverAlInicioDelSendero y
procedure BuscarInicioSendero()
{-
PRECOND:
* hay una unica celda que es el inicio del sendero
(indicada con 2 bolitas negras)
-}
{
IrAlOrigen()
while(not esInicioDelSendero())
{
PasarASiguienteCelda()
}
}
procedure PasarASiguienteCelda()
{
if (puedeMover(Norte))
{ Mover(Norte) }
else
{ IrAlExtremo(Sur); Mover(Este) }
}
Actividad de Programacion 12
Volveremos a revisar la idea de recorrido una vez que hayamos presentado una
de las herramientas mas poderosas (y mas complejas de utilizar) que tienen los
lenguajes de programacion: la memoria.
4.3.1. Variables
La palabra variable sufre de un pro-
Para conseguir que el cabezal recuerde cosas mediante una memoria, se puede
blema: en distintos contextos tiene
utilizar la misma idea de dar nombres a expresiones que ya fueron utilizadas en distintos significados. As, un ma-
los parametros de un procedimiento y en el ndice de una repeticion indexada. En tematico entendera una cosa por
ambos casos usamos una forma limitada de memoria, donde el cabezal recuerda variable, mientras que un progra-
mador puede entender otra. Por
un valor dado por cierto tiempo (por ejemplo un argumento, mediante el nombre eso debemos ser cuidadosos en
del parametro, mientras dura la ejecucion de un procedimiento). Esta misma idea respetar las formas de entender un
de nombrar valores puede utilizarse de manera independiente y controlada por termino de cada disciplina.
el progamador. Para ello, se define la nocion de variable, que no es mas que
un identificador que se utiliza para denotar algun valor en cierto momento de
la ejecucion de un programa. O sea, la forma de proveer memoria es mediante
la capacidad de nombrar valores y sabiendo que nombre le dimos, recordar
el valor; o sea, establecemos una correspondencia entre un nombre y un valor
dado. Para establecer la correspondencia entre una variable y el valor que la
misma denota se utiliza un comando particular, conocido como asignacion.
Definicion 4.3.1. Una variable es un identificador que comienza con minusculas
y que se utiliza para denotar un valor en cierto momento de la ejecucion de un
programa.
cantidadRojas := nroBolitas(Rojo)
siendo < variable > un identificador con minusculas, y < expresion > una expre-
sion cualquiera que describe (o denota) al valor que se quiere asociar (asignar)
al nombre de la variable.
procedure CopiarVerdesAlNorte()
{- PROPOSITO:
* ilustra el uso de variables y el hecho de que la
correspondencia no cambia aunque la expresion usada
para definirla s lo haga
PRECONDICION:
* debe haber una celda al Norte
SUPOSICION:
* la celda al Norte se encuentra vaca
-}
{
cantVerdes := nroBolitas(Verde)
-- Recuerda el nro de bolitas de la celda inicial
Mover(Norte)
-- Se mueve al Norte
PonerN(Verde, cantVerdes)
-- Pone en la nueva celda la cantidad recordada
-- (observar que se supone que esta celda no
-- tiene bolitas)
Mover(Sur)
}
El valor que se asocia a cantVerdes es el numero de bolitas que hay en la celda
inicial, e incluso despues de que el cabezal se mueva, la variable seguira tenien-
do el valor de la celda inicial, aunque la nueva celda no tenga dicha cantidad. La celda inicial es la celda actual
En este ejemplo, suponemos que la celda al Norte no tiene bolitas, y que la cuando inicia el procedimiento.
inicial s las tiene. Podemos observar el efecto de este procedimiento en el grafi-
co G.4.4.
Actividad de Programacion 13
Las variables son utiles para recordar ciertos valores al moverse por el table-
ro. Por ejemplo, en el siguiente ejercicio deberan usarse variables cantRojas,
Actividad de Programacion 14
Realice el ejercicio 4.3.1 y pruebelo con varias celdas con distinto nume-
ro de bolitas de diversos colores.
Las variables pueden nombrar valores de cualquier tipo. Por ejemplo, suponga-
mos que las bolitas en una celda cuentan votos, y que queremos indicar en la
celda del origen el ganador de la votacion con una bolita del color correspon-
diente (suponemos ademas que en caso de empate, gana el color mas chico, o
sea, el que este mas cerca del inicio del alfabeto). Podra, entonces, usarse el
procedimiento que se presenta a continuacion
procedure RecuentoDeVotos()
{- PROPOSITO:
* colocar en la celda del origen, una bolita del color
de las que haya mas en la celda actual
-}
{
colorAPoner := colorConMasCantidad()
IrAlOrigen()
Poner(colorAPoner)
}
donde la funcion colorConMasCantidad retorna el color del que hay mas bolitas
en la celda actual (y si hay mas de uno, retorna el menor de todos); esta fun-
cion sera definida mas adelante. Se observa que el valor descrito por la variable
colorAPoner es un color (pues se usa como argumento del comando Poner).
Tambien pueden guardarse direcciones y booleanos en variables, ademas de
numeros y colores.
Un caso muy simple de cometer este error es realizar una asignacion en alguna
de las ramas de un condicional, y olvidarlo en la otra.
Por ejemplo, supongamos que queremos enviar al cabezal a que encienda
una luz roja en la celda de origen (representando la luz con una bolita de ese
color) si el cultivo en la celda actual (representado tambien con distintas bolitas)
ha comenzado a ponerse negro y que encienda una luz verde en aquella celda,
si el cultivo se conserva azul. El codigo propuesto para esta tarea es
procedure AvisarEstadoDelCultivo()
{-
PRECOND:
* debe haber bolitas negras o azules
en la celda actual
-}
{
if (hayBolitas(Negro))
-- El cultivo se empezo a poner Negro
{ colorAEncender := Rojo }
else
{ if (hayBolitas(Azul))
-- El cultivo conserva su color Azul
{ colorAEncender := Verde }
}
IrAlOrigen()
Poner(colorAEncender)
-- Encender la luz correspondiente
}
Sin embargo, el codigo del ejemplo contiene un error potencial. En el caso de
que el cultivo se haya muerto (o sea no haya bolitas de ningun color), la variable
colorAEncender no tendra valor, pues no se habra ejecutado ninguna de las
asignaciones en las ramas de los condicionales. Puesto que la variable no tiene
valor, el llamado a Poner de la ultima lnea producira la destruccion del cabezal.
Actividad de Programacion 15
Una forma de corregir el error es darnos cuenta de que la accion de prender la luz
no siempre debe ejecutarse. En caso de que el cultivo no este ni azul ni negro,
no debe encenderse ninguna luz. Entonces podemos indicar la necesidad de
prender la luz con una nueva variable, esta vez de valor booleano. Esta variable
debe contener verdadero si la luz debe encenderse y falso en caso contrario.
procedure AvisarEstadoDelCultivo()
{-
PRECOND: ninguna, es una operacion total
-}
{
if (hayBolitas(Negro))
-- El cultivo se empezo a poner Negro
{
colorAEncender := Rojo
encenderLuz := True
-- Indicamos que hay que encender la luz de color rojo
}
else
{ if (hayBolitas(Azul))
-- El cultivo conserva su color Azul
{
colorAEncender := Verde
encenderLuz := True
-- Indicamos que hay que encender
-- la luz de color verde
}
else
{
encenderLuz := False
-- Indicamos que no hay que encender
-- la luz
}
}
IrAlOrigen()
if (encenderLuz)
{ Poner(colorAEncender) }
-- Encender la luz correspondiente,
-- si fue indicado
}
Podemos ver que el comando de encender la luz (el Poner del final) es ahora
condicional, y la condicion es el valor de la variable, que habra cambiado segun
el color del cultivo. Este codigo no produce la destruccion del cabezal (o sea, es
una operacion total).
Otra forma de provocar la autodestruccion mediante el uso de una variable
que no fue definida es utilizar dicha variable cuando la misma no tiene sentido,
por no corresponder con ningun valor. En G OBSTONES, la correspondencia en-
tre una variable y un valor sirve solamente dentro del procedimiento donde se
realiza la asignacion; o sea, cada procedimiento tiene sus propios recuerdos
que no comparte con ningun otro. La parte del codigo donde tal correspondencia
tiene sentido para una variable determinada se denomina alcance de la variable.
As, en G OBSTONES, las variables tienen alcance dentro de un procedimiento
exclusivamente.
procedimiento DuplicarRojasAlNorteMal()
{- PROPOSITO:
* ilustrar el uso INCORRECTO de variables
PRECONDICION:
* falla siempre, por invocar un procedimiento que
no puede tener exito
OBSERVACION:
* pretende mostrar lo que NO DEBE hacerse
-}
{
cantRojas := nroBolitas(Rojo)
Mover(Norte)
CompletarDuplicarRojasAlNorte()
}
procedimiento CompletarDuplicarRojasAlNorteMal()
{- PROPOSITO:
* ilustrar el uso INCORRECTO de variables
PRECONDICION:
* falla siempre, pues cant no es una variable definida,
ni un parametro
OBSERVACION:
* pretende mostrar lo que NO DEBE hacerse
-}
{
PonerN(cantRojas,Rojo)
-- cantRojas ES UNA VARIABLE SIN ASIGNAR!
-- (La asignacion de cantRojas en el otro
-- procedimiento no tiene validez en este)
}
La variable cantRojas asiganada con el numero de bolitas rojas en el procedi-
miento DuplicarRojasAlNorteMal, solo tiene alcance dentro del cuerpo de ese
procedimiento (o sea, solo tiene sentido utilizar dicha variable en ese procedi-
miento, y en ningun lugar mas). Por otra parte, el uso de cantRojas que se hace
en el procedimiento CompletarDuplicarRojasAlNorteMal es incorrecto, puesto
que no fue asignada ninguna variable con ese nombre. La forma correcta de co-
municar ambos procedimientos es utilizar un parametro, de la siguiente manera:
procedimiento DuplicarRojasAlNorteBien()
{- PROPOSITO:
* ilustrar el uso correcto de variables y parametros
PRECONDICION:
* debe haber una celda al norte
-}
{
cantRojas := nroBolitas(Rojo)
Mover(Norte)
CompletarDuplicarRojasAlNorteBien(cantRojas)
}
procedimiento CompletarDuplicarRojasAlNorteBien(cant)
{- PROPOSITO:
* ilustrar el uso correcto de variables y parametros
PRECONDICION:
* siempre funciona
-}
{
PonerN(cant,Rojo)
-- cant ES UN PARAMETRO!
}
procedure VariosErrores(color)
{- PROPOSITO:
* ilustrar la combinacion incorrecta de
parametros y variables y de ndices y variables
PRECONDICION:
* este codigo siempre produce la autodestruccion
-}
{
color := Negro -- color no puede ser una variable,
-- pues es un parametro
cantidad := 1
repeatWith cantidad in 1..5
-- cantidad no puede ser un ndice,
-- pues es una variable
{
PonerN(cantidad, color)
-- hace referencia a un ndice o a una variable?
}
}
Actividad de Programacion 16
Utilizando variables hay ciertas operaciones que son mas sencillas. En los proxi-
Actividad de Programacion 17
function valorTotalDeLaCompra()
{
-- Iniciar el recorrido
libreta := 0 -- Preparar algo para llevar la cuenta
IrAlPrimerProducto() -- Ubicarse en el primer elemento
Actividad de Programacion 18
Actividad de Programacion 19
function colorConMasCantidad()
{-
PROPOSITO:
* retorna el color del que hay mas bolitas.
Si hay igual cantidad de mas de un color,
retorna el menor color posible
PRECOND:
* ninguna, es una operacion total
-}
{
-- Inicializar el recorrido
maxColor := minColor()
maxCant := nroBolitas(minColor())
movimientosAlMax := cantMovimientos
}
-- Y marcamos la celda que corresponde
IrAlExtremo(Norte)
MoverN(Sur, movimientosAlMax)
Poner(Azul)
}
En este codigo podemos observar como se utilizan 3 variables para recordar, por
un lado, la maxima cantidad de bolitas vistas hasta el momento (maxCantidad),
por otra parte, la cantidad de movimientos necesarios hasta donde fue vista di-
cha cantidad (movimientosAlMax, que es similar a recordar que color es el que
tena mas bolitas en el primer ejemplo), y finalmente, la cantidad de movimientos
hechos hasta el momento (cantMovimientos, necesaria para saber cuanto nos
movimos y poder recordarlo si es el maximo). Al finalizar el recorrido, en lugar de
informar la cantidad de movimientos, se realiza el marcado de la celda corres-
pondiente, con base en la cantidad calculada. Se debe observar que a diferencia
de un recorrido de busqueda, que finaliza apenas encuentra lo buscado, en este
caso deben procesarse todos los elementos, pues no se sabe de antemano cual
es el maximo.
Un recorrido para calcular el mnimo elemento de una secuencia es exac-
tamente igual en estructura a uno de calcular el maximo, solo que en lugar de
recordar el mayor, se recuerda el menor. Tener esto en cuenta al realizar los
siguientes ejercicios.
Actividad de Programacion 20
Actividad de Programacion 21
bolitas negras por bolitas verdes, para indicar que ya fue visitado. Si hiciese falta
volver a ponerlas negras, al finalizar el recorrido habra que hacer una subtarea
que vuelva a recorrer el sendero cambiando bolitas verdes por negras.
Actividad de Programacion 22
Actividad de Programacion 23
4.4. Ejercitacion
Este apartado culmina la introduccion al lenguaje G OBSTONES, con algunos ejer-
cicios avanzados que utilizan todas las herramientas vistas hasta el momento.
Actividad de Programacion 24
Igual que en el caso del visir, deben marcarse las casillas ocupadas por piezas
del oponente, pero no las casillas ocupadas por piezas del mismo color. No se
deben marcar casillas saltando por sobre piezas propias ni del oponente.
El cabezal debe quedar ubicado en la casilla en la que estaba originalmente.
El ultimo tema para presentar ejercicios se basa en una idea de Pablo Baren-
baum. Nuevamente agradecemos a Pablo por su generosidad.
La Piedra Rosetta es una losa del Antiguo Egipto que contiene inscripciones
del mismo texto en tres sistemas de escritura distintos: griego, egipcio demotico y
jeroglficos egipcios. En el siglo XIX, Jean-Francois Champollion se valio de esta
informacion para descifrar la escritura jeroglfica. Para auxiliarnos en el analisis
de lenguas muertas, haremos una version simplificada de este modelo.
El tablero de G OBSTONES se dividira en dos mitades, separadas por una co-
lumna marcada con bolitas negras en todas sus celdas. Las columnas de la mitad
izquierda representaran un texto de referencia. Las columnas de la mitad dere-
cha representaran un texto a descifrar. Notar que las mitades no necesariamente
tienen el mismo ancho.
Este ejercicio puede realizarse de tres maneras diferentes, cada una con su pro-
pia complejidad.
1. Recorrer primero el texto de referencia, recordando la traduccion de cada
smbolo (digamos, armando un diccionario), y despues recorrer el texto a
traducir, usando el diccionario ya armado.
Esta solucion es conceptualmente correcta, y en la siguiente Unidad se pre-
sentaran herramientas que permitiran estructurar la solucion de esta mane-
ra. Pero en G OBSTONES, con las herramientas vistas, esto no es factible,
porque solo se dispone de un numero finito de variables que recuerdan un
unico valor, y no se pueden usar para recordar un numero desconocido
de smbolos del alfabeto.
2. Recorrer el texto de referencia y, a medida que se encuentra un par cla-
ve/valor, traducir todas las ocurrencias de ese smbolo.
Esta solucion tiene la dificultad de que una vez visitado el texto a traducir,
hay que volver a la posicion del texto de referencia de donde haba par-
tido el cabezal. Esto puede hacerse dejando marcas sobre el tablero. Sin
embargo, esta solucion es compleja.
3. Esta posibilidad es la mas simple de programar (y quizas la mas natural en
algun sentido). La idea consiste en hacer una funcion traduccion que dado
un smbolo representado como un parametro de tipo numero que sera el
codigo del jeroglfico correspondiente, busque en el texto de referencia su
traduccion, devolviendo el codigo de la letra conocida correspondiente.
Hecho esto, el problema se puede resolver haciendo un unico recorrido
sobre el texto a traducir, traduciendo smbolo a smbolo mediante la funcion
recien definida. La ventaja es que no hay que preocuparse por dejar marcas
para volver, aprovechando que las funciones deshacen todos sus efectos.
La solucion mas simple del problema de la Piedra Rosetta muestra el poder que
tiene la division de un problema complejo en subtareas mas sencillas, siempre
que la descomposicion se haga pensando en simplificar el proceso completo.
Este, mas que ningun otro concepto, es el que deben llevarse de esta primera
parte de la introduccion a la programacion.
Modularizacion
5.1. Modulos
Hasta ahora, hemos aprendido que al programar es conveniente separar las
ideas en diversas tareas a resolver. Entonces, los programas en general estan
compuestos de distintas tareas que juntas dan lugar a un programa completo.
Ahora bien, cuando el numero de tareas y subtareas crece es importante man-
tener cierto orden, agrupando aquellas funciones o procedimientos que contribu-
yen a una tarea especfica, de manera tal de estructurar mejor a los programas
de forma global, para facilitar su comprension, su correccion y su modificacion.
Es facil observar que las aplicaciones tienen asociadas distintos objetivos que
deben cumplir, muchos de ellos independientes entre s. Por ejemplo, un proce-
sador de textos posee una region en la que podemos escribir y editar texto, pero
tambien tiene opciones para imprimir documentos, guardarlos en el disco duro,
enviarlos por mail, etcetera. Cada una de estas tareas podra ser codificada por
separado (por ejemplo, la opcion de imprimir y la de enviar mails seguramente no
dependan la una de la otra), por lo que comunmente en programacion se agru-
pa a estas distintas porciones de programas de cierta manera. Denominamos
modulo a un grupo de funciones y procedimientos que contribuyen a expresar la
solucion a determinada tarea.
De esta manera, podemos razonar a los programas como la union de varias par-
tes que interactuan entre s, los modulos, y que trabajan juntas para alcanzar
un objetivo comun, realizando cada una alguna de las tareas necesarias para la
consecucion de los objetivos finales del programa. Como dijimos, en esta Uni-
dad denominaremos modulo a cada una de esas partes en las que se encuentre
dividido un sistema. Cada modulo debera tener tareas bien definidas a cumplir
e idealmente sera independiente de otros modulos, o al menos debera comu-
nicarse de forma controlada con el resto. Observar que uno podra agrupar las
funciones y procedimientos de diversas maneras, pero no todas las divisiones
posibles daran como resultado una buena modularizacion, puesto que se espera
que cada modulo capture una tarea o idea general, y no que sean simples agru-
paciones de procedimientos. Por ejemplo, agrupar todos los procedimientos que
empiezan con la letra A en un modulo ModuloA, todos los que empiezan con B en
un modulo ModuloB, etc., no sera considerado una buena modularizacion, ya que
esta agrupacion no esta vinculada al problema a resolver, sino a los nombres de
los procedimientos. En cambio, una agrupacion de todos los procedimientos que
tengan que ver con imprimir en un modulo Impresion, y todos las de enviar mail
en un modulo Correo.
Para Reflexionar
Actividad 1
La tarea del disenador es de las tareas mas difciles y los ejercicios de esta Uni-
dad siempre especificaran que operaciones deberan implementarse en determi-
nado modulo. El conjunto de operaciones que el disenador define para un modulo O sea, no se pedira que el estu-
se denomina interfaz del modulo. Por consiguiente, dicha interfaz tambien define diante asuma el rol de disenador.
la forma con la que podemos comunicarnos con dicho modulo. En esta Unidad,
usaremos la siguiente definicion de interfaz.
Definicion 5.1.2. Una interfaz es una lista de los nombres y tipos de las opera-
ciones provistas por un modulo.
Para Reflexionar
5.2. P YTHON
Para programar utilizando los conceptos de esta Unidad dejaremos de utilizar
el lenguaje G OBSTONES, y utilizaremos un lenguaje de programacion llamado
P YTHON. A diferencia de G OBSTONES, que es un lenguaje pequeno, disenado
exclusivamente con la idea de presentar las primeras ideas de programacion,
P YTHON es un lenguaje de proposito general, lo que significa que es utilizado en
la vida real para resolver problemas de todo tipo, incluyendo aplicaciones como
las que utilizamos a diario. Esta es la razon por la que utilizaremos este lenguaje
en reemplazo de G OBSTONES. Si instalaron la herramienta P Y G OBSTONES, ya
tendran que tener instalado P YTHON. Utilizaremos la version en Windows de este
lenguaje, el cual trae un editor denominado IDLE. Para el resto de las unidades
siguientes tambien utilizaremos este lenguaje y este editor.
Lectura Obligatoria
.
https://hkn.eecs.berkeley.edu/~dyoo/python/idle_intro/IDLE_
spanish.html
Realice los ejercicios 5.2.1 y 5.2.2, que seran descrito paso a paso a
continuacion. Preste atencion a cada paso porque esta sera la forma de
trabajar con P YTHON en futuros ejercicios.
Ejercicio 5.2.1. Seguir las instrucciones dadas en los parrafos subsiguientes pa-
ra crear un programa Calculadora con visor.
Para ilustrar la explicacion anterior presentaremos un ejemplo que describa paso
por paso lo pedido para cada ejercicio. Este ejercicio de ejemplo consistira en
definir un modulo con las operaciones elementales de suma, resta y multiplica-
cion, que seran utilizadas por un modulo que imprimira una serie de resultados
por pantalla. Al programa completo lo denominaremos Calculadora con visor y
as tambien se nombrara a la carpeta que contenga a los modulos del programa
(como puede verse en el grafico G.5.1). Dentro de dicha carpeta crearemos dos
archivos, que se corresponden con los dos modulos requeridos para el programa:
Operaciones y Main (nunca olvidar a este ultimo). Puede observa2rse el conte-
nido resultante de la carpeta al crear estos archivos en el grafico G.5.2. Ambos
archivos tendran extension .py, la cual poseen todos los archivos fuente de un
Para esto debemos utilizar la he- programa P YTHON. No se alarme si P YTHON genera varios archivos mas dentro
rramienta IDLE que viene con P YT- de esa carpeta, adicionales a los del codigo fuente, ya que son creados cuando
HON . Se puede abrir desde el
menu de inicio, o utilizando el el programa se ejecuta por primera vez. Generalmente estos archivos poseen ex-
menu contextual. tension .pyc, pero tambien puede haber otros. Dentro del modulo Operaciones,
o sea, dentro del archivo Operaciones.py, colocaremos las siguientes definicio-
nes:
def sumar(x,y):
return x + y
def restar(x,y):
return x - y
def multiplicar(x,y):
return x * y
La regla de los cuatro espacios es
muy importante en P YTHON ya que
De estas tres funciones de P YTHON podemos comentar algunas diferencias con la indentacion es obligatoria (forma
la sintaxis que utilizabamos en G OBSTONES. Las palabras function y procedure parte de la sintaxis), siendo esta la
son reemplazadas por def. En P YTHON no hay distincion entre procedimientos forma de definir bloques en el len-
y funciones: todos los procedimientos pueden devolver valores a traves del co- guaje. Por dicho motivo debe res-
petarse esa cantidad exacta de es-
mando return. Una de las mayores diferencias con G OBSTONES es que en este pacios o se producira un error de
lenguaje los bloques de codigo no son encerrados entre llaves, sino que empie- sintaxis.
zan con : (dos puntos), y se indenta el codigo exactamente cuatro espacios
para indicar que el bloque pertenece a dicha definicion.
Si realizo correctamente lo indicado, debera tener una ventana como la que
se muestra en el grafico G.5.3.
A su vez, dentro del modulo Main, o sea dentro del archivo llamado Main.py,
colocaremos el siguiente codigo:
Si ya esta abierta la herramienta ID-
import Operaciones LE puede utilizar la opcion Nuevo
(New ) del menu Archivo (File ).
if __name__ == __main__:
resultado = Operaciones.sumar(4, 5)
print "4 + 5 =", resultado
Herramienta
G OBSTONES P YTHON
abstracta
if(puedeMover(Norte)) if puedeMover(Norte):
Alternativa { Mover(Norte) } Mover(Norte)
condicional else else:
{ Mover(Sur) } Mover(Sur)
case color of
if color == Rojo:
Rojo ->
FlorRosa()
{ FlorRosa() }
Alternativa elif color == Azul:
Azul ->
indexada FlorAzul()
{ FlorAzul() }
else:
_ ->
FlorComun()
{ FlorComun() }
procedure PintarColumna(color)
{
IrAlExtremo(Sur)
Poner(color)
while(puedeMover(Norte))
{ Mover(Norte); Poner(color) }
}
procedure PonerTodosLosColores()
{
colorActual := minColor()
Poner(colorActual)
colorActual := siguiente(colorActual)
while(colorActual == minColor())
{
Poner(colorActual)
colorActual := siguiente(colorActual)
}
}
Interfaz
5.4. Listas
Continuaremos el entendimiento de interfaces y tipos de datos con un tipo de
datos que ya viene definido en P YTHON; este tipo se denomina Lista. Este nuevo
tipo es distinto los que hemos utilizado con anterioridad ya que constituye lo que
se denomina una estructura de datos, que es una forma de organizar grupos de
datos de manera de garantizar formas de acceso eficientes a los mismos. Este concepto sera explorado so-
Las listas no son otra cosa que una coleccion o secuencia ordenada de ele- lo superficialmente en esta carpe-
ta de trabajo ya que generalmente
mentos de determinado tipo. Decimos que es una coleccion porque agrupa ele- existen asignaturas especializadas
mentos y los compone en un unico valor (por dicha razon las listas tambien son en cubrirlo en profundidad.
conocidas como un tipo compuesto de datos); y decimos secuencia ordenada
porque dicha composicion de datos posee un orden determinado, es decir, existe
un primer elemento seguido de un segundo, un tercero, un cuarto, etc., hasta lle-
gar al ultimo de la lista. A diferencia de otras estructuras, las listas pueden variar
la cantidad de elementos que poseen durante el transcurso del programa.
Para ilustrar esta idea, podemos imaginarnos una lista de numeros, o una
lista de colores, o una lista de personas, etcetera. P YTHON posee una notacion
comoda para describir listas. Utilizando numeros, un ejemplo es [1,2,3,4,5,6].
El siguiente procedimiento asigna la lista del ejemplo anterior a una variable y la
imprime por pantalla:
def imprimirListaEjemplo():
listaEjemplo = [1,2,3,4,5,6]
print listaEjemplo
Los tipos abstractos de datos se presentan dando el nombre del tipo de dato
y sus operaciones (su interfaz). Para cada tipo de datos, debe investigarse su
interfaz en la bibliografa correspondiente a cada lenguaje.
Lectura Obligatoria
.
http://docs.python.org.ar/tutorial/datastructures.html#
mas-sobre-listas
Realice cada uno de los siguientes ejercicios. Recuerde crear una carpe-
ta por cada ejercicio a resolver. Cada una de ellas contendra un archivo
Main sobre el que codificara la solucion.
5.5. Diccionarios
Ademas de las listas, otra estructura de datos muy utilizada es lo que se conoce
como diccionario o mapping en ingles. Un diccionario es tambien una coleccion
de valores, pero en este caso de pares clave-valor (o sea, no habra un orden
preestablecido entre los elementos de la coleccion). Para cada clave existira un
valor asociado. Un ejemplo tradicional es el de asociar personas y numeros te-
lefonicos. En este caso el conjunto de claves son las personas que tiene cada
una asociada un numero telefono o una lista de todos sus numeros de telefonos.
Lectura Obligatoria
.
http://docs.python.org.ar/tutorial/datastructures.html#
diccionarios
Actividad de Programacion 5
Realice cada uno de los siguientes ejercicios. Recuerde crear una carpe-
ta por cada ejercicio a resolver. Cada una de ellas contendra un archivo
Main sobre el que codificara la solucion.
if __name__ == __main__:
agenda = {}
agenda["Jorge"] = 5552125
agenda["Pepe"] = 8885555
print "Mi agenda telefonica es", agenda
Ejercicio 5.5.3. Sobre el ejercicio 5.5.2 agregar lo necesario para imprimir por
pantalla solo el numero telefonico de "Fidel".
En P YTHON tambien es posible realizar una repeticion sobre todos los elemen-
tos de listas o diccionarios. Esta repeticion tambien es llamada iteracion sobre la
estructura. No es objetivo de esta carpeta profundizar sobre iteraciones en es-
te lenguaje, pero las veremos brevemente, porque sera requisito para resolver
algunos ejercicios que veremos mas adelante.
Lectura Obligatoria
.
http://docs.python.org.ar/tutorial/controlflow.html#
la-sentencia-for
.
http://docs.python.org.ar/tutorial/datastructures.html#
tecnicas-de-iteracion
.
http://pygame.org/ftp/pygame-1.9.1.win32-py2.7.msi
import pygame
import sys
def screenSize():
return (320,240)
def Game():
pygame.init()
screen = pygame.display.set_mode(screenSize())
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.fill((255,255,255))
drawGame(screen)
pygame.display.flip()
tick = clock.tick(60)
if __name__ == "__main__":
Game()
def drawGame(surface):
(x,y) = screenSize()
pygame.draw.circle(surface, (0,255,0), (x/2,y/2), 100, 2)
Lectura Obligatoria
www.pygame.org/docs/ref/draw.html
Actividad de Programacion 7
Ejercicio 5.7.2. Con base en lo aprendido hasta ahora sobre procedimientos pa-
ra dibujar crculos, colecciones e iteradores, definir un procedimiento denomina-
do DibujarCirculosEn que reciba una lista de pares de coordenadas y dibuje
crculos de radio 3 con centro en cada una de dichas coordenadas.
http://en.wikipedia.org/wiki/Separation_of_concerns
Incumbencia Modulos
Level
Logica del juego
SokobanLogic
Aplicacion Main
Common
Auxiliares
Constants
Ejercicio 5.8.8. Implementar la funcion winGame que verifica si el juego fue ga-
nado.
Para esto, winGame verifica que la lista de cajas a colocar (que no estan sobre
objetivos) no se encuentre vaca, recibiendo por parametro dicha lista de coorde-
nadas. Para verificar si una lista posee o no elementos puede preguntar si posee
exactamente cero elementos.
Modulos Objetos
Para ejecutar un procedimiento de Los objetos deben ser instanciados
un modulo basta con saber el nom- para poder recibir mensajes.
bre del modulo y el nombre del pro-
cedimiento.
Para Ampliar
http://www.cs.virginia.edu/~evans/cs655/readings/
smalltalk.html
Ejemplo
Por ultimo debemos presentar una idea que, si bien no forma parte de todos
los lenguajes orientados a objetos, forma parte de la mayora de ellos, y en es-
pecial de P YTHON, que es el lenguaje que utilizaremos en esta Unidad. Esta idea
es la de clase, que es la definicion de la estructura sobre la que se creara un gru-
po de objetos particulares. Por ejemplo, para poder crear muchos objetos con las
mismas caractersticas definiremos la clase de un automovil, que definira que ca-
ractersticas tendra cada automovil particular, es decir, sus atributos y metodos
(pero no los valores especficos de cada atributo, los cuales dependeran de cada
objeto en s y de su identidad).
En las primeras unidades hemos visto que cada expresion tena un tipo. En
el paradigma de objetos utilizamos de manera similar la idea de clase. Particular-
mente (al menos en los lenguajes orientados a objetos que poseen clases, que
son mayora) nos interesa saber a que clase pertence cada objeto. Por ello, una
nocion adicional al comportamiento, identidad y estado interno de un objeto, es
la clase del mismo.
Leer con Atencion
Para Ampliar
tro especial, llamado self, que es (la referencia a) el objeto para el que estamos
definiendo este metodo. Es decir, todo metodo recibe por parametro al objeto que En algunos otros lenguajes la re-
posee dicho metodo. Esta capacidad de autoreferenciacion nos permite denotar cepcion de este parametro se en-
cuentra implcita y no debe expre-
caractersticas del mismo objeto dentro del metodo. Por ejemplo, si deseamos sarlo el usuario
implementar un metodo que llena el tanque del objeto auto por completo, debe-
mos poder referenciar al combustible que posee el auto actualmente para poder
as modificarla. De esta forma expresaremos, por ejemplo self.combustible =
100, lo cual indica que combustible es un atributo del objeto actual, y que el mis-
mo debe asociarse con el valor 100, indicando que el tanque posee el 100 % del
combustible.
La segunda idea especfica de P YTHON es que toda definicion de clase debe
implementar un metodo especial, llamado init . A este metodo se lo denomi-
na metodo de inicializacion de un objeto de esa clase, dado que define el estado
interno inicial que posee el objeto al crearse.
Ilustraremos lo expresado hasta el momento implementando el objeto auto:
class Auto():
def __init__(self):
self.combustible = 100
def moverse(self,km):
self.combustible = self.combustible - (km/40)
# Suponemos un tanque de 40 litros, y un consumo
# de 100 km por litro.
def llenarTanque(self):
self.combustible = 100
Podemos observar que el metodo init tambien recibe por parametro a self.
En este caso lo utilizamos para definir para el mismo objeto que atributos po-
seera y que valor inicial tendran. Es decir, la primera asignacion de un valor a un
atributo se considera su declaracion, como ocurre con variables dentro de un pro-
cedimiento en G OBSTONES. La diferencia entre la declaracion del atributo de un
objeto y una variable de un procedimiento radica en que el atributo puede ser re-
ferenciado desde cualquier metodo del objeto, mientras que las variables que de-
fina un procedimiento solo pueden ser utilizadas dentro de este ultimo. Ademas,
los objetos de clase Auto poseen dos metodos: moverse y llenarTanque.
Actividad de Programacion 1
if __name__ == __main__:
# Creacion de un objeto de clase Auto
unAuto = Auto()
# Primera verificacion
print "El combustible del auto es ", unAuto.combustible
Un nombre mas adecuado para el mensaje crecer podra haber sido cumplirA~
nos,
pero en P YTHON no se puede utilizar la ~
n como letra de un identificador.
class Persona():
def __init__(self, nombre):
self.nombre = nombre
self.edad = 0
def crecer(self):
self.edad = self.edad + 1
def esJoven(self):
return self.edad < 20
if __name__ == "__main__":
# Instanciamos un objeto de clase persona
unaPersona = Persona("Juan Carlos")
print "Hola! Me llamo", unaPersona.nombre
unaPersona.crecer()
unaPersona.crecer()
class CajaDeAhorro():
def __init__(self):
self.saldo = 0
class Cliente():
def __init__(self, unaPersona, unaCajaDeAhorro):
self.persona = unaPersona
self.efectivo = 0
self.cajaDeAhorro = unaCajaDeAhorro
def tieneDinero(self):
return self.efectivo > 0 or self.cajaDeAhorro.saldo > 0
if __name__ == "__main__":
# Instanciamos los objetos
unaPersona = Persona("Juan Carlos")
unaCajaDeAhorro = CajaDeAhorro()
unCliente = Cliente(unaPersona, unaCajaDeAhorro)
unaCajaDeAhorro.extraer(100)
print "Tengo dinero si extraje?", unCliente.tieneDinero()
unCliente.incrementarEfectivo(100)
print "Recibi efectivo; tengo dinero?", unCliente.tieneDinero()
Nuevamente hay particularidades que nos interesa observar. Un objeto de clase
Cliente recibe en su instanciacion un objeto de clase Persona y un objeto de
clase CajaDeAhorro. Esto es as porque los objetos son como cualquier otro va-
lor que hayamos manejado hasta el momento, solo que tienen la particularidad
de poder recibir mensajes, llevando parte del programa junto con ellos. Otra co-
sa a notar es que un cliente es la asociacion entre una persona (con nombre y
edad) y los restantes atributos. Esto se relaciona con lo que en otras unidades
llamamos cuestiones de representacion de informacion. Si para el programa ne-
cesitamos que el cliente posea solamente una referencia a su caja de ahorro y no
necesitamos distinguirla de ninguna manera ni obtener ninguna otra informacion,
entonces es adecuado que otras caractersticas adicionales que se nos puedan
ocurrir para que personas de la vida real no formen parte de la representacion de
una persona en forma de objeto para este sistema.
Actividad de Programacion 2
Ejercicio 6.2.1. Modelar los objetos propietario y auto, de tal manera que de un
auto se conoce su patente (que puede ser representada con un numero). Del pro-
pietario nos interesa que pueda responder al mensaje tieneUnAutoConLaPatente
que dado un numero de patante dice si un propietario posee o no un auto con
esa patente.
Ejercicio 6.2.2. Modelar un banco con clientes. El banco comienza sin clien-
tes y a traves del mensaje ingresarCliente anade uno a su lista. Tambien nos
interesa saber cuantos clientes posee y si determinado numero de documento
pertenece a alguno de sus clientes.
Ayuda: considerar la utilizacion de listas, segun se estudio en la Unidad an-
terior.
Ejercicio 6.2.3. En un mundo medieval existen guerreros. De cada guerrero se
sabe su nombre de batalla y cuanta fuerza tiene (magnitud numerica). En un
duelo entre guerreros el guerrero mas fuerte segun su nivel de fuerza ganara, y
ademas como resultado del duelo, ambos guerreros incrementan su fuerza en 1
unidad.
Porcentaje(15).aplicarA(2000)
6.3.1. Polimorfismo
Una situacion recurrente al utilizar objetos es la de enviar el mismo mensaje a
muchos objetos diferentes. Pero puesto que estos objetos pueden ser instancia
de clases diferentes, entonces es necesario que todos ellos puedan entender
el mismo mensaje, aunque sea de diferentes maneras. A la caracterstica que
permite que objetos de clases diferentes respondan a un mismo mensaje se la
conoce en el paradigma orientado a objetos con el nombre de polimorfismo.
Decimos entonces que esos objetos son polimorficos respecto de dicho mensaje.
Para ilustrar que significa precisamente la definicion anterior, imaginemos que
tenemos dos clases de objetos: perros y gatos. Ambos objetos pueden realizar
acciones similares, como son correr, respirar, dormir, comer. Consideremos, en-
tonces, el siguiente codigo:
def comer(self):
self.energiaDePerro = self.energiaDePerro + 15
def correr(self):
self.energiaDePerro = self.energiaDePerro - 8
def ladrar(self):
self.energiaDePerro = self.energiaDePerro - 2
def comer(self):
self.energiaDeGato = self.energiaDeGato + 10
def correr(self):
self.energiaDeGato = self.energiaDeGato - 2
def maullar(self):
self.energiaDeGato = self.energiaDeGato - 1
Ambas clases, tanto Perro como Gato, poseen dos mensajes en comun: comer
y correr. Las clases se diferencian en la forma en que perros y gatos comen y
corren, y tambien en que los perros pueden ladrar y los gatos maullar.
Diremos al enviar a un objeto el mensaje comer, por ejemplo, que dicho objeto
es tratado de manera polimorfica respecto del mensaje comer. Esto quiere decir
que no importa si quien recibe el mensaje es un Perro o un Gato; solo importa
que cualquiera de ellos puede recibir este mensaje, aunque lo implementen de
manera diferente. Esto se hace evidente con el siguiente ejemplo:
def entrenarMascota(unGatoOPerro):
unGatoOPerro.comer()
unGatoOPerro.correr()
unGatoOPerro.correr()
unGatoOPerro.correr()
unGatoOPerro.correr()
unGatoOPerro.comer()
class Estocada():
def realizarAtaque(self, unGuerrero):
unGuerrero.fuerza = unGuerrero.fuerza - 2
class Garrotazo():
def realizarAtaque(self, unGuerrero):
unGuerrero.fuerza = unGuerrero.fuerza - 5
class Guerrero():
def __init__(self):
self.fuerza = 100
self.tipoDeAtaque = None
def atacar(self):
self.tipoDeAtaque.realizarAtaque(self)
Actividad 4
Actividad de Programacion 5
if __name__ == "__main__":
# Instancia al guerrero
unGuerrero = Guerrero()
print "Mi fuerza esta en un", unGuerrero.fuerza, "%!"
unGuerrero.cambiarDeAtaque(Garrotazo())
print "Ahora dare un garrotazo!"
unGuerrero.atacar()
Ejercicio 6.3.1. Se desea modelar una aplicacion para guardar informacion so-
bre discos de musica (CD) y pelculas (DVD). De los CDs nos interesa conocer
el ttulo y la cantidad de temas que posee, y de los DVDs nos interesa el ttulo de
la pelcula y el tiempo total que dura.
Modelar tambien un local de venta, que conoce una serie de tems (CDs y/o
DVDs) que estan a la venta en dicho local; puede utilizarse una lista que los
contenga para modelar esta caracterstica. Para un local se tiene que poder saber
la cantidad de tems que posee y la cantidad de tems largos.
Un CD se considera largo si tiene mas de 15 canciones; en cambio un DVD
se considera largo si dura mas de 140 minutos. Notar que ambos podran res-
ponder al mensaje esLargo, cada uno implementandolo en su respectiva clase
con distinto comportamiento.
class Restaurante():
def __init__(self):
self.nroDeClientes = 0
def ingresarPersona(self):
self.nroDeClientes = self.nroDeClientes + 1
class Agenda():
def __init__(self):
self.numeros = {}
class Alcancia():
def __init__(self):
self.monedas = []
Ejercicio 6.3.3. Una maquina de una fabrica de autos posee cuatro fases, donde
cada una le agrega una pieza particular al auto. La primera fase le agrega el
motor; la segunda, el radiador; la tercera, el tanque de combustible y la ultima, la
caja de cambios. El programa, parcialmente implementado, es el siguiente:
class AutoPorArmar():
def __init__(self):
self.piezas = []
6.3.2. Herencia
Con el concepto de polimorfismo hemos estado modelando entidades que po-
sean un mensaje en comun, aunque distinta implementacion, es decir, no se
comportaban de la misma manera pese a poseer exactamente el mismo nombre
y recibir exactamente el mismo tipo y numero de parametros. Pero la pregunta
es, que sucede cuando tenemos un conjunto de entidades que son diferentes
pero que poseen en comun un mismo mensaje con identico comportamiento?. El
polimorfismo, por lo expresado anteriormente, no es una solucion a este proble-
ma.
Ilustraremos este concepto con un ejemplo, retomando el ejemplo de perros
y gatos. Ambos comen y corren, pero los primeros ladran y los ultimos maullan.
Supongamos que deseamos agregar ademas la posibilidad de representar tanto
animales vivos como animales muertos. O sea, queremos que tanto perros como
gatos puedan tener en su estado el atributo estaVivo. La propiedad de estar vivo
es identica a ambos seres vivos. Es un estado que es verdadero o falso. Veamos
esto en codigo:
class Perro():
def __init__(self):
self.energiaDePerro = 200
self.estaVivo = True
def seMurio(self):
return not self.estaVivo
def morir(self):
self.estaVivo = False
def comer(self):
self.energiaDePerro = self.energiaDePerro + 15
def correr(self):
self.energiaDePerro = self.energiaDePerro - 8
class Gato():
def __init__(self,):
self.energiaDeGato = 100
self.estaVivo = True
def seMurio(self):
return not self.estaVivo
def morir(self):
self.estaVivo = False
def comer(self):
self.energiaDeGato = self.energiaDeGato + 10
def correr(self):
self.energiaDeGato = self.energiaDeGato - 2
Tanto el atributo estaVivo como los mensajes seMurio y morir se codifican exac-
tamente de la misma manera (hay repeticion de codigo). La diferencia entre pe-
rros y gatos esta en que responden de diferente manera a los mensajes comer y
correr, y porque poseen un mensaje mas cada uno, que no comparten (ladrar
para Perro y maullar para Gato).
Como podemos evitar repetir el codigo identico en diferentes clases? Es
claro que la propiedad de estar vivo es algo comun, no solo a perros y gatos,
sino a todos los seres vivos. Entonces, queremos poder modelar esta idea, y
simplemente decir que tanto perros como gatos son seres vivos.
La forma de resolver esto en P YTHON, y en general en cualquier lenguaje
de programacion con objetos que nos permita programar con clases, es utilizar
Existen lenguajes que no poseen el herencia entre clases. Esta caracterstica del paradigma permite modelar una
concepto de clase, aunque no son clase que contiene exactamente las propiedades y mensajes que comparten cla-
la mayora
ses mas especializadas. En otras palabras, perros y gatos si bien son clases
distintas, podramos pensar que son de la clase SerVivo, porque poseer esa
caracterstica de poseer o no vida. En P YTHON podemos codificar lo siguiente:
class SerVivo():
def __init__(self):
self.estaVivo = True
def seMurio(self):
return not self.estaVivo
def morir(self):
self.estaVivo = False
Esta clase modela exactamente lo que tanto gatos como perros comparten. Aho-
ra lo que resta hacer es indicar que las clases Perro y Gato heredan las carac-
tersticas que provean los objetos de la clase SerVivo. O sea, debemos indicar
que tanto perros como gatos poseen todas las caractersticas y mensajes de
los seres vivos, y que ademas van a agregar algunas caractertsticas propias.
En P YTHON podemos hacer:
En realidad esta no es la forma que
class Perro(SerVivo): actualmente se utiliza en el lengua-
def __init__(self): je, pero la elegimos para esta car-
peta por su simplicidad
SerVivo.__init__(self)
self.energiaDePerro = 200
def comer(self):
self.energiaDePerro = self.energiaDePerro + 15
def correr(self):
self.energiaDePerro = self.energiaDePerro - 8
class Gato(SerVivo):
def __init__(self):
SerVivo.__init__(self)
self.energiaDeGato = 100
def comer(self):
self.energiaDeGato = self.energiaDeGato + 10
def correr(self):
self.energiaDeGato = self.energiaDeGato - 2
Observar las modificaciones que debemos realizar para que las clases Perro y
Gato, dadas previamente, para que hereden de SerVivo. La primera es indicar
en la primera lnea que declara a cada una de las clases que la clase que se
declara debe poseer las caractersticas y comportamiento de alguna ya definida,
ubicando el nombre de la clase de la cual queremos heredar entre los parente-
sis siguientes al nombre de la clase particular. La segunda es que al ejecutar la
inicializacion, debemos agregar un llamado de inicializacion a la clase de la cual
heredamos, en este caso pasando self como parametro (este es el unico caso
donde self no es implcito como parametro). Esta segunda modificacion es im-
portante dado que la clase de la cual heredamos puede poseer comportamiento
inicial que debe ser ejecutado, y self debe ser pasado como parametro porque
es a las clases particulares a las que debe hacer referencia dicha inicializacion.
Esta relacion indica que una clase es subclase de una superclase, siendo la
subclase quien hereda de la clase que es superclase. En nuestro ejemplo, Perro
es subclase de SerVivo, y SerVivo es superclase de Perro.
Actividad de Programacion 7
if __name__ == "__main__":
# Instanciamos algunos seres vivos particulares
unPerro = Perro()
unGato = Gato()
unPerro.morir()
print "Ahora esta vivo el perro?", unPerro.estaVivo
unGato.morir()
print "Ahroa se murio el gato?", unGato.seMurio()
Puede observarse que los mensajes seMurio y morir pueden enviarse tanto a
perros como a gatos, y su comportamiento sera exactamente el mismo en ambos.
Ademas, ambas subclases ahora poseen como atributo estaVivo, aunque no lo
declaran explcitamente, sino a traves de la herencia de la clase SerVivo.
Actividad de Programacion 8
Ejercicio 6.3.4. Se desea modelar un sistema para una universidad que posee
estudiantes y profesores. De toda persona se sabe su nombre y edad. Pero par-
ticularmente de los estudiantes se conoce el promedio y de los profesores, la
materia que dictan. Modelar esta herencia de atributos a traves de las clases
correspondientes.
Las relaciones de subclasificacion pueden darse varias veces, dando lugar a una
jerarqua de clases, donde existen clases que no heredan de ninguna otra, pero
donde todas pueden tener subclases, incluso aunque ellas mismas sean subcla-
ses de otras. En este ultimo ejercicio veremos un ejemplo de jerarqua de clases
simple pero no trivial, donde habra una unica clase que no hereda de nadie, y
otras que, heredando de esta, a su vez, poseen subclases.
Bases de datos
por Carlos A. Lombardi
cada ticket que se hace en cada caja le llega al sistema de stock del super ;
al sitio del pronostico del tiempo le llegan los datos de los satelites.
Ejemplo
Con todas las otras aplicaciones que mencionamos, tambien vemos informacion
que fue incorporada anteriormente. En el procesador de texto puedo abrir un
documento que guarde la semana pasada; en el campus virtual veo los apuntes
que el profesor cargo antes; en el sistema de legajos de alumnos se tienen que
poder consultar todas las materias que aprobe; el pronostico para La Plata para
los proximos 10 das entro al sitio de pronostico del tiempo hace dos horas.
Antes de seguir, veamos que esto es cierto incluso para una aplicacion que aso-
ciamos con lo inmediato, como el chat. La mayor parte de la informacion que se
ingresa en una aplicacion de chat son los mensajes que escribimos, y la intencion
es que sean ledos en el momento en que los escribimos. Hasta ah la persisten-
cia de datos no tiene ningun rol. Pero al poco tiempo de usar una aplicacion de
chat, descubrimos que queremos que la aplicacion se acuerde de nuestros con-
tactos, para no tener que cargarlos cada vez que queremos hablar con ellos. La
informacion sobre contactos s debe almacenarse para uso posterior, por lo tanto
s aplica la idea de persistencia de datos. Mas adelante, descubrimos la con-
veniencia de guardar al menos algunas conversaciones que tuve por chat, para
rescatar esa direccion que me dieron y que no encuentro por ningun lado. La per-
sistencia de datos juega entonces un papel relevante, incluso en una aplicacion
inmediata como un chat.
minar esos problemas y a presentar una solucion a los mismos: las bases de
datos.
del autor, y en columnas adicionales, los datos del autor (nacionalidad, ano de
nacimiento).
En esta forma de organizar los datos estamos generando una duplicacion de
los datos de cada autor. En el grafico se ve que el dato que Ana Menseguez es
Argentina esta dos veces, y lo mismo con la fecha de nacimiento. Esta duplica-
cion puede generar inconsistencias en los datos almacenados; el grafico G.7.4
muestra un ejemplo. Se agrego otro libro de Ana Menseguez a nuestra planilla,
pero se indico para la autora un pas y un ano de nacimiento distintos. Al mirar la
planilla, no podemos determinar donde y cuando nacio Ana.
Una forma de evitar la duplicacion es separar los datos de los autores, poniendo-
los en una hoja separada. Es lo que se propone en el grafico G.7.5. Pero lo que
ganamos en consistencia, lo perdimos en practicidad. Ahora, si estoy mirando, la
hoja con la informacion de los libros, y me da curiosidad de saber en que pas
nacio la autora de Las aventuras de Carozo, tengo que cambiar a la hoja donde
estan los escritores y buscar los datos de Ana Menseguez.
Para Ampliar
Para hablar de bases de datos se usan las siglas BD, y tambien DB que son
las iniciales en ingles. La forma en la que los datos estan organizados en una
base de datos da herramientas para evitar la duplicacion de informacion. Esta
organizacion tambien esta pensada para facilitar la forma de definir consultas,
incluyendo consultas que usen informacion desparramada por distintos sectores
dentro de la base de datos.
Definicion 7.2.1. Una base de datos (BD) es un conjunto especfico de informa-
cion que esta almacenada de acuerdo a una organizacion conocida e indepen-
diente de cualquier programa que la utilice.
Para persistir informacion en una BD, antes de empezar con las actualizaciones y
consultas, hay un paso previo, que es definir la organizacion de la BD. Los datos
que se agreguen despues tienen que estar de acuerdo con esta organizacion, si
no, la BD los rechaza.
Una tabla tiene por un lado, una estructura que define la forma que van a tener
los datos, y por otro, un conjunto de datos persisitidos. Una BD incluye un conjun-
to de tablas. En el grafico G.7.7 se muestra una posible tabla en la que se incluyen
los datos de los libros que deben persistirse en nuestra base de datos de ejemplo.
Leer con Atencion
En cada fila se indica un dato que corresponde a cada una de las columnas,
este sera el valor de la fila para cada columna. En nuestra tabla Libro, cada
fila tendra entonces cuatro datos: un ttulo, un ano, un idioma y un autor. En el
grafico G.7.7, una de las filas corresponde a los datos persistidos para el libro
Las aventuras de Carozo, los valores de esta fila para las columnas ttulo, ano,
idioma y nomAutor son: Las aventuras de Carozo, 2004, Espanol y Ana
Menseguez respectivamente.
Los nombres de las columnas son muy utiles para acceder a la informacion
almacenada en una tabla especfica. Sirven fundamentalmente para especificar
las actualizaciones y consultas que queramos hacer sobre una tabla.
Para agregar una nueva fila a la tabla Libro, debemos indicar los valores
para cada columna.
Una consulta posible sobre los datos de esta tabla puede ser obtener las
filas de la tabla Libro cuyo valor para la columna nomAutor sea Ana Men-
seguez. De esta forma obtenemos los libros de esta autora cuyos datos
estan persistidos en nuestra BD.
Fechas.
En nuestra tabla Libro, los tipos de dato para las columnas ttulo, idioma y
nomAutor podran ser texto libre hasta 120 caracteres, mientras que para ano
resulta mas adecuado un tipo numerico sin decimales.
Veremos como especificar el tipo de dato de cada columna al describir la
creacion de una tabla con MySQL.
7.3.3. Claves
Un elemento adicional en la definicion de la estructura de una tabla es su clave
primaria, que es una columna incluida en la definicion de la tabla. Las claves pri-
La clave primaria de una tabla pue- marias son conocidas comunmente como PK, por las iniciales del ingles primary
de constar de varias columnas; no key.
estudiaremos esta posibilidad en la
rapida introduccion a las bases de
datos relacionales que estamos ha-
Definicion 7.3.1. Una clave primaria (del ingles primary key) es un atributo (una
ciendo. columna) de una entidad que la identifica de manera unvoca.
Definicion 7.3.3. Una clave de negocio es una clave primaria que corresponde
a datos propios de las entidades que estan siendo representadas.
Definicion 7.3.4. Una clave tecnica es una clave primaria que se agrega a la
entidad para identificarla, cuando ninguno de sus atributos originales es unico.
Ejemplo
Para Ampliar
http://dev.mysql.com/doc/refman/5.0/es/
Cada expresion SQL incluye el nombre de un comando que indica el tipo de ope-
racion que deseamos realizar (agregar filas, hacer una consulta, etc.), parame-
tros que indican sobre que objeto (base de datos, tabla, columna, etc.) debe apli-
carse esta operacion, y muchas veces informacion adicional que es necesaria
para definir la operacion.
Las expresiones SQL deben terminar con punto y coma para poder ser
comprendidas adecuadamente por el SGBD.
Ejemplo
insert into < tabla >(< col-1 >,< col-2 >,... < col-n >)
values (< val-1 >, < val-2 >, ... < val-n >);
donde las listas de nombres de columnas y valores deben tener la misma canti-
dad de elementos, y la nueva fila tendra a < val-i > como valor de cada columna
< col-i > incluida en la lista de columnas.
Para Ampliar
Actividad 1
La definicion del comando select en SQL incluye una gran cantidad de variantes
para especificar < columnas >, < tabla > y < condicion >. De esta forma, per-
mite describir una amplia variedad de consultas sobre una BD. A continuacion
describimos algunas de estas variantes.
Respecto de las columnas, en los ejemplos vistos hasta ahora se utilizaron
tres variantes: *, < col-1 >, < col-2 >, ... y count(*).
Utilizando la forma < col-1 >, < col-2 >, ... se indica explcitamente
que columnas se quiere obtener como resultado de la consulta. Es la op-
cion utilizada en la consulta
select titulo, anio
from libro
where nomAutor = Ana Menseguez;
Utilizando count(*) se obtiene un resultado que incluye una sola fila y una
sola columna, o sea, un solo valor. Este valor es la cantidad de filas de la
consulta. Notar que la cantidad de filas que aparecen en una consulta pue-
de ser distinta a la cantidad de filas que hay en la tabla correspondiente. Por
ejemplo, si los datos de la tabla libro se corresponden con el grafico G.7.11,
entonces el resultado de
select count(*) from libro;
es 5, mientras que el de
select count(*)
from libro
where nomAutor = Ana Menseguez;
es 2.
Respecto de la tabla, hasta ahora hemos incluido siempre el nombre de una unica
tabla. Veremos ejemplos de consultas que involucran varias tablas mas adelante,
en el apartado 7.5.3.
Respecto de la condicion, ademas del comparador por igualdad = se pueden
usar, entre otros, la comparacion por desigualdad !=, y las comparaciones <=, >=,
< y >. Todos son validos tanto para valores numericos como para texto; en este
ultimo caso se considera el orden de diccionario, por ejemplo alfa < beto
< betun.
Puede compararse el valor de una columna contra un valor fijo, como en la
comparacion nomAutor = Ana Menseguez, o tambien los valores de dos co-
lumnas entre ellos. Por ejemplo, la consulta
select * from libro where titulo < nomAutor;
incluira al libro El cachalote contento, pues este ttulo esta antes en el diccio-
nario que Eva Condal, que es el nombre de la autora. Por su parte, el libro
Pigmallion no sera incluido, porque segun el orden del diccionario el nombre de
su autor, George Shaw, esta antes que el ttulo del libro, por lo tanto la condicion
Al juntarse nombre y apellido del titulo < nomAutor resulta falsa en este caso.
autor en una unica columna, el va- Tambien pueden incluirse varias condiciones, usando los operadores logicos
lor con que se compara es George
Shaw y no solamente Shaw, por
and, or y not, entre otros. Por ejemplo, el resultado de la consulta
eso resulta estar antes que Pigma- select *
llion. from libro
where nomAutor = Ana Menseguez and anio >= 2006;
seran los datos correspondientes a los libros escritos por Ana Menseguez de
2006 en adelante, mientras que el resultado de
select *
from libro
where nomAutor = Ana Menseguez or nomAutor = Eva Condal;
seran los datos correspondientes a los libros que hayan sido escritos por alguna
de las dos autoras mencionadas en la consulta.
Finalmente, observamos que si no se coloca ninguna condicion, como por
ejemplo en:
select titulo, anio from libro;
no se esta estableciendo ninguna restriccion sobre las filas a incluir en el resul-
tado de la consulta, que por lo tanto incluira informacion de todas las filas de la
tabla libro. En este caso, se omite la palabra where.
Como ya hemos hecho en algunos ejemplos es posible utilizar solamente la
restriccion de filas dada por la condicion, solamente la restriccion de columnas
dada por una lista explcita de columnas, o ambas a la vez en la misma consulta.
Actividad 2
Escribir consultas para obtener cada uno de los conjuntos de datos pe-
didos en el siguiente ejercicio.
Todos los datos de los libros escritos entre los anos 1900 y 1999.
Todos los datos de los libros que o bien se han escrito en frances o bien
fueron escritos despues del ano 2000.
Por ejemplo, para obtener todos los datos de la tabla libro, ordenando
las filas segun el ano de cada libro, se puede ejecutar esta consulta:
select * from libro order by anio;
Tambien se puede indicar que las filas aparezcan en el orden inverso al que
corresponde a una columna, para eso se agrega la palabra desc a continuacion
del nombre de la columna. Por ejemplo en el resultado
select * from libro order by anio desc;
la primera fila sera la del libro mas reciente. En el grafico G.7.13 se muestra el
resultado correspondiente a estas consultas.
La indicacion de orden puede combinarse con las restricciones de filas y/o
columnas. Puede verse un ejemplo en el grafico G.7.14. Observar que no es
necesario que las columnas involucradas en la condicion o el orden aparezcan en
Escribir una consulta para obtener todos los datos de los libros escritos
a partir de 1900, ordenados segun el nombre del autor.
Actividad 4
Escribir una consulta para obtener ttulo e idioma de los libros escritos
en espanol, en orden inverso respecto del ttulo.
Ejemplo
Ademas de las cuatro operaciones aritmeticas basicas, los distintos SGBD ofre-
cen una gran cantidad de funciones matematicas, de tratamiento de texto, y otras
que pueden ser utilizadas para definir columnas calculadas dentro de una con-
sulta. Destacamos algunas funciones provistas por MySQL:
la parte entera de < numero >.
floor(< numero >)
Por ejemplo: floor(3.8) es 3.
el valor absoluto de < numero >.
abs(< numero >)
Por ejemplo: abs(-3.8) es 3.8.
los primeros n caracteres del texto especificado.
left(< texto >,< n >)
Por ejemplo: left(Orqudea.4) es Orqu.
right(< texto >,< n >) analogo a left pero tomando los ultimos caracte-
res, en lugar de los primeros.
char length(< texto >) la cantidad de caracteres del texto especificado.
para cada libro en idioma espanol, la inicial del ttulo y la ultima cifra del ano.
select titulo, anio,
left(titulo,1) as inicial,
anio - (floor(anio / 10) * 10) as ultCifraAnio
from libro
where idioma = Espa~ nol;
Aunque no es imprescindible, resulta siempre conveniente asignar un nombre
a cada columna calculada que se incluye en una consulta. En el ejemplo, los
nombres asignados a las dos columnas calculadas son inicial y ultCifraAnio.
Las operaciones y funciones tambien pueden ser utilizadas dentro de la con-
dicion al definir una consulta. En el siguiente ejemplo solo se incluyen las filas
correspondientes a libros cuyo ttulo empieza, con E o bien con P.
select titulo, anio, left(idioma,2) as idiomaResumido
from libro
where left(titulo,1) = E or left(titulo,1) = P;
En esta consulta se incluyeron calculos tanto en las columnas como en la condi-
cion. El grafico G.7.16 muestra los resultados de las dos ultimas consultas des-
critas.
Actividad 5
El ttulo entero, la ultima letra del ttulo, el ano y el autor de los libros de los
cuales el nombre del autor empieza con A.
Esta expresion tiene una diferencia respecto de las que estudiamos en el apar-
tado 7.4.3: no se especifican valores para todas las columnas. Observamos
que no se especifica el valor para la columna idioma.
En el apartado 7.3.1 vimos que cada fila de una tabla tiene un valor para
cada una de las columnas. Cual sera el valor de la nueva fila para idioma?
Podemos averiguarlo haciendo la consulta que mostramos en el grafico G.7.17.
Observamos que en idioma aparece una leyenda especial que dice NULL.
Leer con Atencion
Se considera que si el valor para una columna en una fila es null, enton-
ces la fila no tiene valor asignado para esa columna. En el ejemplo,
podemos decir que la fila agregada no tiene valor asignado para idioma,
o lo que es lo mismo, que no tiene idioma asignado.
Actividad 6
remos como hacer algunas consultas que integran datos que estan en distintas
tablas. En los ejemplos consideraremos que las tablas escritor, lector y tiene-
Libro incluyen las filas que se muestran en el grafico G.7.10. Respecto de libro,
supondremos que tiene las filas que se muestran en el grafico G.7.19.
Supongamos que queremos saber, para el libro El cachalote contento, el
ano de edicion, idioma y autora que estan en la tabla libro, y ademas, el pas y
ano de nacimiento de su autora, que estan en la tabla escritor. Para ello vamos
a realizar una consulta que reune datos que, en la BD, estan separados en dos
tablas distintas. Esta consulta debe seleccionar una fila en cada una de las tablas.
La situacion se describe en el grafico G.7.20.
La fila de libro que incluye los datos que buscamos es la que corresponde
al libro sobre el que queremos consultar datos; puede seleccionarse facilmente
por el valor de la columna titulo. Una vez seleccionada la fila en libro, tambien
es intuitivamente sencillo determinar en que fila de la tabla escritor estan los
datos que debemos tener en cuenta: se trata de la fila correspondiente a Eva
Condal, la autora del libro en cuestion. Para elegir las filas de libro y de escritor
que corresponde reunir, nos basamos en que hay un dato, el nombre del autor,
que esta presente en ambas tablas. Al reunir informacion que en la BD esta se-
parada en dos tablas, obtenemos un mayor detalle de informacion acerca del
libro: reunimos los datos presentes en libro con la informacion de su autor, que
esta presente en escritor.
La existencia de un dato en comun entre las tablas libro y escritor puede
observarse en su estructura. El nombre de columna nomAutor aparece en las
dos tablas. Mas aun, es el unico nombre de columna que se repite: ningun otro
nombre de columna de libro aparece en escritor y viceversa. El criterio usado
para reunir una fila de libro con una de escritor es la coincidencia en el valor de
la columna que aparece en ambas filas. En el ejemplo, las dos filas reunidas
coinciden en el valor de nomAutor, que es Eva Condal.
Definicion 7.5.2. Se dice que dos filas de distintas tablas estan en reunion natural
Frecuentemente este concepto si y solo si, tienen los mismos valores para todas las columnas que aparecen en
aparece bajo el nombre natural ambas tablas. Para que dos filas de distintas tablas esten en reunion natural, la
join, su denominacion en ingles.
estructura de las tablas debe coincidir en al menos un nombre de columna.
El lenguaje SQL provee una forma sencilla de generar consultas que, en su resul-
tado, reunan filas de distintas tablas que estan en reunion natural. Recordemos la
forma general de las consultas segun lo descripto en los apartado 7.4.4 y 7.4.5,
o sea:
select < columnas > from < tabla > where < condicion >
order by < orden >;
Para incluir en la consulta filas en reunion natural que estan en distintas tablas,
debemos modificar la especificacion de la < tabla >. En lugar de incluir un so-
lo nombre de tabla, incluimos las dos tablas involucradas en la reunion natural,
poniendo las palabras natural join entre los nombres de tabla.
Para obtener, en una misma consulta, los datos sobre El cachalote contento
que estan separados en las tablas libro y escritor podemos ejecutar la siguiente
select titulo, anio, idioma, nomAutor, paisNacim, anioNacim
consulta from libro natural join escritor
where titulo = El cachalote contento;
En el grafico G.7.21 se muestra el resultado de esta consulta. La reunion natural
entre dos filas genera una sola fila en el resultado de la consulta, que reune los
datos que en la BD estan separados en las filas que se reunieran en la consulta.
Para Ampliar
El resultado de la consulta
al no tener condicion sobre las filas de libro a incluir, realizara para cada fila de
libro la reunion natural con la fila correspondiente de escritor, obteniendose el
resultado que se muestra en el grafico G.7.23.
El uso de la reunion natural en una consulta puede combinarse con las va-
riantes de definicion de columnas y condiciones estudiadas hasta ahora.
Ejemplo
Por ejemplo, podemos usar una columna calculada para incluir la edad
que tena el autor de cada libro de autor argentino cuando se edito el
libro:
select titulo, nomAutor, anio - anioNacim as edad
from libro natural join escritor
where paisNacim = Argentina;
o ttulo, autor y edad que tena el escritor, para los libros cuyo autor tena
menos de 40 anos al momento de ser editados:
select titulo, nomAutor, anio - anioNacim as edad
from libro natural join escritor
where anio - anioNacim <40;
tablas.
Considerando la informacion que se esta modelando en la BD, hay tres lecto-
res que tienen ejemplares de La dama de las camelias, mientras que ninguno
tiene Cuarteles de invierno. Como cada fila en el resultado de la consulta co-
rresponde a un lector que tiene un libro, es correcto que un libro se repita tres
veces, mientras que el otro no aparezca.
Actividad 8
Terminemos este apartado observando que, dado que cada fila de la tabla
libro incluye una referencia a una fila de la tabla autor, tal como se describe en
el apartado 7.5.3, pueden armarse consultas en las que se hace una reunion na-
tural de las cuatro tablas incluidas en la BD que estamos usando como ejemplo.
Considerar la siguiente consulta:
select titulo, idioma, nomAutor, paisNacim
nombreYApe, desde
from libro natural join tieneLibro
natural join lector natural join escritor
order by titulo;
Actividad 10
Para Ampliar
Si se utiliza una condicion mas abarcativa, pueden eliminarse varias filas con
una sola expresion. Por ejemplo
delete from libro where idioma = Espa~ nol;
elimina, si los datos de la tabla libro corresponden al grafico G.7.19, todas las
filas excepto las correspondientes a La dama de las camelias y Pigmallion.
Observamos que si hacemos referencia a un valor especfico sobre la clave
primaria, es seguro que no se eliminara mas de una fila ejecutando una expre-
sion. Podra tambien darse el caso en el que ninguna fila sea eliminada, porque
ninguna cumple con la condicion explicitada. Por ejemplo, considerando los libros
descritos en el grafico G.7.19,
delete from libro where titulo = Ulyses;
no eliminara ninguna fila, porque no hay ningun libro registrado cuyo ttulo sea
Ulyses.
El comando update permite actualizar filas de una tabla. La estructura gene-
ral de las expresiones correspondientes a este comando es
update < tabla > set < col > = < valor > where < condicion >;
donde corresponden para < tabla > y < condicion > las mismas consideracio-
nes que para delete. Por ejemplo, la siguiente expresion:
update libro set anio = 1992
modifica el ano de edicion
where titulo = El cachalote contento;
en la fila de libro correspondiente al libro El cachalote contento.
Al especificar el nuevo valor puede referenciarse al valor anterior. Por ejem-
plo, si queremos sumar dos anos al ano de edicion de un libro, podemos escribir
una expresion como la siguiente
update libro set anio = anio + 2
where titulo = El cachalote contento;
Para Ampliar
Actividad 11
Redes
Redes de area local o LAN (Local Area Network), disenadas desde el prin-
cipio para transportar datos en areas no tan extensas.
Redes de area extensa o WAN (Wide Area Network), disenadas para trans-
portar datos entre areas.
Para Reflexionar
Para Ampliar
Las redes WAN fueron disenadas en principio para transportar voz. De esto se
desprende que usualmente son servicios contratados a operadoras importantes.
Dado que los datos recorren grandes distancias se suele optimizar el diseno de
estas redes para reducir costos. Hay que tener en cuenta que muchas de ellas
se realizan va satelite. Por el contrario, las redes LAN son simplemente redes
implementadas para un ambito mas reducido, como puede ser una red domestica
o la red interna de una empresa.
Por otra parte, podemos separar las redes por la forma en que se comunican:
Actividad 1
Estas dos nociones de tipo de comunicacion son bien sabidas en la vida cotidia-
na. Por ejemplo, una red broadcast es la television por cable, y una red punto a
punto es una llamada telefonica convencional. En las redes broadcast la informa-
cion es enviada a todos los nodos de la red, aunque solo interese a unos pocos;
Cabe destacar que los tipos de clasificaciones que realicemos sobre redes no
son excluyentes entre s, por lo que podemos tener redes broadcast LAN, redes
punto a punto WAN, por dar algunos ejemplos.
Ejemplo
Actividad 2
Sin embargo, aunque los servicios sean mayormente de tipo cliente-servidor, las
comunicaciones entre computadoras son punto a punto, en donde la red no fun-
ciona con clientes y servidores fijos, sino que cada computadora que la compo-
ne actua simultaneamente como cliente y servidor. Esto permite el intercambio
Contraste las caractersticas que poseen las redes punto a punto y las
de arquitectura cliente-servidor.
Topologas de redes
Por ultimo, las redes ademas pueden estar dispuestas de diversas maneras. To-
das pueden estar conectadas a una central y esa central distribuir la informacion,
pueden estar conetactadas a un medio comun (un cable que atraviesa a todas),
etcetera. No cubriremos en esta unidad las ventajas o desventajas de las distin-
tas topologas de redes de computadoras; en el grafico G.8.1 pueden observarse
algunas.
No obstante, en la mayora de los casos se escoge una topologa jerarquica
en distintos niveles (sobre esto avanzaremos mas adelante).
4 Presidente Presidente
3 Traductor Traductor
3
2 Secretaria Secretaria
Comunicacin Real
1 Fax Fax
Modularidad Puesto que permite realizar cambios con relativa facilidad a una
de sus partes sin afectar al resto.
Actividad 4
Con base en lo explicado hasta aqu intente describir por que un modelo
de capas posee los beneficios mencionados. Puede relacionarlo con lo
que sabe de unidades anteriores.
Teclado Teclado
E-Mail
Computadora Computadora
7
Capa de aplicacin
6
Capa de presentacin
5
Capa de sesin
4
Capa de transporte
3
Capa de red
2
Capa de enlace
1
Capa Fsica
8.2.4. Protocolos
Como dijimos, un protocolo es un conjunto de reglas que prescriben la comunica-
cion entre dos pares de componentes en dos extremos de la red. Los protocolos
definen diversas caractersticas de la comunicacion entre dos capas de un mismo
nivel:
5
Capa de aplicacin
4
Capa de transporte
3
Capa de red
2
Capa de enlace
1
Capa Fsica
HTTP
Aplicacin Aplicacin
Interfaz
Sockets Sockets
TCP
Transporte Transporte
IP
Red Red
Winsock Winsock
IEEE 802.3
Enlace Enlace
IEEE 802.3
Fsica Fsica
un usuario no manda una peticion con el comando GET propio del protocolo HTTP
para conseguir una pagina web, ni lee directamente el codigo que define a una de
estas paginas, que es codigo en lenguaje HTML (que sera visto en subapartados
siguientes). El usuario interactua con un navegador web, un cliente de correo o
una aplicacion de chat, y estos programas son los que utilizan los protocolos de
esta capa con el fin de comunicarse entre s.
En suma, protocolos de esta capa son:
Protocolo HTTP
El protocolo HTTP es uno de los mas importantes de esta capa dado que los usua-
rios de internet lo utilizan constantemente. Significa Hypertext Transfer Protocol,
y define un grupo de comandos para pedir paginas web y enviar datos hacia las
mismas. Actualmente tambien existe un protocolo llamado HTTPS, que imple-
menta una version mas segura, donde los datos que viajan estan encriptados.
Algunos comandos del protocolo son GET, POST, HEAD, CONNECT. Cuando un
cliente establece el inicio de una comunicacion con un servidor HTTP, el primero
enva estos comandos al segundo, de tal manera que se establece un dialogo
entre ambos: cliente pidiendo recursos y el servidor otorgandolos. Todo recurso
transmitido por este protocolo se identifica por una URL. Estos recursos pueden
ser archivos, imagenes, paginas web, entre otros.
Actividad 5
Para Reflexionar
Las cookies son utilizadas tambien para almacenar datos de los usua-
rios con respecto a publicidades. Esto es as porque contienen muchas
veces informacion clave sobre el comportamiento de la persona mien-
tras navega. Considere las implicaciones que pueden tener las cookies
para su seguridad ahora que sabe para que son utilizadas.
http://web-sniffer.net/
Introduzca la URL del buscador (www.google.com.ar) en la parte de
HTTP(S)-URL. Presione submit y se completara la informacion relativa
al servicio. Podemos ver que cuando realizamos un pedido HTTP
debemos indicar que version del protocolo utilizaremos y que comando
deseamos enviar. En este caso se encuentra configurado por defecto el
comando GET.
Podemos ver la informacion de Request (pedido del cliente) y de
Response (respuesta del servidor). Dentro del pedido podemos ver el
navegador con el que realizamos la consulta, el destino (Host) y diver-
sas configuraciones de idioma y codificacion de la informacion. Dentro
de la respuesta el servidor nos retorna un mensaje de estado. Si el ser-
vidor de Google nos responde correctamente el estado debera ser OK.
Existen otros estados que detallan solicitudes incorrectas, problemas con el ser-
vidor, etcetera. Todos se encuentran numerados. Ademas del estado el servidor
nos retorna contenido, indicando que tipo de contenido posee la informacion que
requiere el cliente. En este caso es una pagina web por lo que el contenido es
texto HTML. El servidor que sirve al cliente tambien enva informacion adicional
Este protocolo de descripcion de para poder visualizarla correctamente, que a nuestros fines no analizaremos. To-
paginas sera tratado en subaparta- da esta informacion que acabamos de nombrar forma parte del encabezado de
dos siguientes.
la respuesta del servidor, y el cuerpo de dicha respuesta, que es la pagina web
que nos entrega, forma parte del cuerpo del mensaje. En el cliente que utilizamos
para hacer el pedido podemos ver el contenido principal en el apartado content.
Ese contenido cuando se realiza un pedido de forma tradicional con un navega-
dor es interpretado para ser presentado de la forma que habituamos a diario.
Los protocolos SMTP, POP e IMAP son utilizados para el manejo de correo electroni-
co. El protocolo SMTP es un protocolo de transferencia de correos, tanto para
envo desde el cliente al servidor de correo, como entre servidores de correos
que distribuyen entre s la informacion. Pero no provee forma de acceder luego
a la casilla de correo para poder acceder a los mails. Esto ultimo lo permiten los
protocolos POP e IMAP, que funcionan de distinta manera.
Todos estos protocolos al igual que HTTP tambien poseen diversos coman-
dos. Particularmente SMTP posee comandos que permiten ir definiendo un correo
propiamente dicho, y uno para finalizar y que el servidor procese la consulta.
El siguiente ejemplo constituye un dialogo tpico entre una maquina cliente (c)
y un servidor (s):
Protocolo DNS
Si bien cada recurso de la web es identificado por una URL, la direccion del servi-
dor al que nuestra computadora realiza el pedido se identifica en realidad por una
direccion de IP. Una IP es una identificacion de una maquina, pero numerica. El
protocolo DNS es el encargado de traducir nombres, llamados nombres de domi- Si bien este concepto no es propio
nios (URLs) para obtener la IP correspondiente del servidor al que el navegador de la capa de aplicacion sino de la
capa de red del modelo OSI, el pro-
debe realizar el pedido. Nosotros, los humanos, no utilizamos directamente estas tocolo DNS se vale de este concepto
IP (aunque podramos) porque nos es mas facil recordar nombres significativos para operar.
que numeros sin ningun significado aparente. Por otra parte, la direccion numeri-
ca podra cambiar por muchas razones, sin que tenga que cambiar el nombre.
Como todo protocolo de esta capa, existen clientes que realizan peticiones,
y servidores que ofrecen respuestas a dichas peticiones. El cliente basicamen-
te pregunta Que direccion IP corresponde a nombre.dominio? Esta pregunta
se deriva al servidor de DNS que opera en la zona del cliente. Cada zona de
autoridad abarca al menos un dominio y posiblemente sus subdominios, si es-
tos ultimos no son delegados a otras zonas de autoridad. Para resolver estos
pedidos los servidores de DNS poseen una base de datos en donde registran
todas estas traducciones y delegaciones a otros servidores.
Ejemplo
solo las URL de tipo www son las unicas traducidas, y por el contrario cualquier tipo
de nombre de dominio es traducido por este protocolo.
Por ultimo debemos destacar que muchas veces la consulta no viaja hasta
el servidor mas especfico sino que es respondida por un servidor mas general
que posee guardada la respuesta. Esto se debe a que todo el viaje de informa-
cion y delegacion entre servidores es costosa, y en muchos casos para consul-
tas realizadas frecuentemente al servidor le conviene mantener guardadas estas
respuestas de manera local.
Enrutables, que son aquellos que viajan junto con la informacion. Dentro de
estos podemos encontrar al protoclo IP.
De enrutamiendo, que son los que permiten seleccionar que ruta tomara la
informacion. Cada protocolo en este caso elige una forma distinta de resol-
ver este problema, y entre ellos podemos nombrar RIP, IGRP, OSPF, BGP.
Como podemos observar es la capa mas concreta de todas, dado que se encarga
de los medios fsicos propiamente dichos.
Para Reflexionar
Actividad 9
Lectura Obligatoria
http://es.wikipedia.org/wiki/HTML
Por otra parte, cada tag a su vez puede contener atributos. Los atributos son ca-
ractersticas diferentes que puede tener cada tag. Por ejemplo, el tag de image-
nes posee como atributo la URL de la imagen a mostrar, lo cual se escribe como
<img src="./imagenes/mifoto.jpg/>.
Por ultimo, si bien HTML provee tags que permiten describir cuestiones de
estilo y estetica de las paginas, por ejemplo estilo de la fuente de un texto, se
elige no utilizar estos tags dado que existe otro lenguaje que permite describir
solo el estilo de las paginas HTML. Este otro lenguaje es CSS, de las siglas en
ingles Cascading Style Sheets. Dado el alcance de esta carpeta no ahondaremos
demasiado en la estetica de las paginas.
Para Ampliar
www.w3schools.com/css/
Para Reflexionar
<head>
<style type="text/css">
body {background-color:yellow}
</style>
</head>
<body>
<h1>Biografa de Miguel de Cervantes</h1>
<p>
Consulte:
<a href="http://es.wikipedia.org/wiki/Miguel_de_Cervantes">
Cervantes
</a>
</p>
</body>
<div>
<div style="text-align:center;"><embed
height="315" width="560"
type="application/x-shockwave-flash"
src="http://www.youtube.com/v/HEheh1BH34Q?version=3&hl=es_ES&rel=0"
allowfullscreen="true"
allowscriptaccess="always" /><p></p></div>
</div>
Aplicaciones
En esta ultima unidad mencionaremos dos de las principales formas con las que
se implementa la ejecucion de programas para un lenguaje de programacion: in-
troduciremos la idea de IDE, herramienta que usan los programadores para pro-
gramar a escala industrial, y realizaremos un ultimo programa final, con el fin de
integrar la mayora de los conocimientos adquiridos en las unidades anteriores.
9.2. IDEs
A medida que los programas se hacen cada vez mas grandes se vuelve poco
viable codificarlos en un simple editor de textos. Por esta razon surgieron los
entornos de desarrollo integrados, mas comunmente conocidos como IDEs, por
sus siglas en ingles.
Integrated Develpment Environ- Estas herramientas suelen estar compuestas de distintos elementos, entre las
ments. que podemos mencionar:
Un editor de texto.
Un compilador o interprete.
Los editores de texto que suelen venir incorporados en los IDEs ayudan enorme-
mente a la tarea del programador. Suelen tener iluminacion de la sintaxis, auto-
completado de palabras segun el lenguaje en el que se codifica, e informacion
adicional sobre procedimientos, funciones, tipos y objetos codificados. Proveen
un marco para agilizar y facilitar la tarea del programador de mantener y codificar
programas, y ocuparse de detalles importantes mientras que el editor se encar-
ga de rellenar los que son mas mecanicos. A estos editores se anaden formas
comodas de correr los programas, trayendo consigo generalmente un interprete
para correrlos o una forma de comunicacion con el compilador del lenguaje en el
que se este codificando.
Actividad 2
Actividad de Programacion 3
if __name__ == __main__:
leonardoDiCaprio = Actor("Leonardo Di Caprio", 37, 3)
kateWinslet = Actor("Kate Winslet", 37, 1)
jamesCameron = Director("James Cameron", 58,
["drama", "ciencia ficcion"])
unaPeli = Pelicula("Titanic", jamesCameron,
[leonardoDiCaprio, kateWinslet],
1997, 187000)
Impresor().mostrar([unaPeli,
jamesCameron,
kateWinslet,
leonardoDiCaprio])
se debera mostrar como resultado:
Pelicula: Titanic
Director: James Cameron
Actor: Kate Winslet
Actor: Leonardo Di Caprio
if __name__ == __main__:
conn = sqlite3.connect(":memory:", isolation_level=None)
Este procedimiento nos retornara una conexion a la base de datos, que de-
beremos asignar a una variable para utilizar de forma posterior, tal como sucede
en el ejemplo anterior.
La conexion por s sola no nos sirve de mucho. A cada conexion puede pedir-
se un objeto de tipo cursor que nos permitira realizar consultas sql mediante el
procedimiento execute, que recibe por parameto la consulta sql a ejecutar.
Actividad de Programacion 5
El siguiente ejemplo muestra como podemos crear una tabla, como insertar una
fila y como realizar una consulta a la tabla creada:
import sqlite3
if __name__ == __main__:
conn = sqlite3.connect(":memory:")
c = conn.cursor()
Podemos observar que con el mensaje fetchone pedimos un dato de los tantos
que podra traer la consulta. Para obternerlos todos en forma de lista podemos
utilizar el mensaje fetchmany.
Lectura Obligatoria
http://docs.python.org/library/sqlite3.html
Actividad de Programacion 6
Serie, con columnas nombre, nombre de director (foreign key), fecha y can-
tidad de temporadas.
Como ayuda, puede utilizar el hecho de que estos metodos seran utilizados como
en el siguiente ejemplo:
def insertarTitanic(cursor):
leonardoDiCaprio = Actor("Leonardo Di Caprio", 37, 3)
kateWinslet = Actor("Kate Winslet", 37, 1)
jamesCameron = Director("James Cameron", 58,
["drama", "ciencia ficcion"])
titanic = Pelicula("Titanic", jamesCameron,
[leonardoDiCaprio, kateWinslet],
1997, 187000)
Tambien puede tener en cuenta que en P YTHON es posible asignar una tupla
a una tupla de variables como suceda en G OBSTONES. En otras palabras, es
posible escribir algo como:
(nombre, edad, cantidadDePremios) = ("Robert De Niro", 69, 51)
Ejercicio 9.3.5. Utilizando lo definido en ejercicios anteriores definir el procedi-
miento habitarBaseDeDatos que reciba por parametro un cursor a una base de
datos e inserte informacion en la misma. Debe agregar a la base al menos 3
pelculas y 2 series de su preferencia, cada una con al menos 2 actores.
Ejercicio 9.3.6. Definir procedimientos para insertar cada tipo de elemento del
sistema a las tablas correspondientes.
Nota: para el caso de pelculas, series y directores tener en cuenta que para
cada fila deberemos obtener de las tablas de elencos y estilos las filas corres-
pondientes a cada uno de estos objetos.
Recuerde utilizar los procedimientos de transformacion de tuplas en objetos
definidos anteriormente.
Tenga en cuenta que el resultado de una consulta puede ser tomado como se-
cuencia a iterar. Para ilustrar esto le proveemos ya codificado el procedimiento
todosLosActores, para que observe una posible forma de resolver los procedi-
mientos pedidos.
def todosLosActores(cursor):
resultList = []
for fila_actor in cursor.execute(SELECT * FROM Actor):
newActor = transformarEnActor(fila_actor)
resultList.append(newActor)
return resultList
Ejercicio 9.3.8. Definir el procedimiento mostrarTodaLaBase que utilizando los
anteriores procedimientos y el mensaje mostrarse de cada objeto del sistema,
muestra todos los objetos existenes en el sistema.
La herramienta P Y G OBSTONES
Instalacion
El primer paso es obtener los scripts que conforman el entorno de programacion
P Y G OBSTONES 0.9.6. Se encuentran en un archivo zip que esta disponible para
descargar desde el sitio de SourceForge. La direccion del sitio es:
http://gobstones.sourceforge.net/
Usuarios de Windows
Para los usuarios de Windows, el siguiente paso es conseguir e instalar una
version de P YTHON. El interprete tradicional de P YTHON para Windows se puede
descargar desde:
http://python.org/ftp/python/2.7.3/python-2.7.3.msi
Usuarios de GNU/Linux
Las distribuciones de Linux generalmente ya traen el interprete de P YTHON ins-
talado. Ademas de esto, para ejecutar P Y G OBSTONES se requiere instalar el pa-
quete python-tk. Para instalar los paquetes que falten, se deben buscar utili-
Uso
La interfaz de P Y G OBSTONES es similar a la de un editor de textos comun y
corriente. El editor permite crear y modificar programas de G OBSTONES, que se
guardan en archivos de texto con extension .gbs.
La funcionalidad provista por la herramienta es mnima. Una vez escrito el
programa, la opcion de menu Gobstones Ejecutar permite ejecutarlo (lo cual
se puede hacer mas comodamente con la tecla F5). Una vez que termino de
Ademas, el menu Tablero permite abrir y guardar tableros en archivos con ex-
tension .gbb.
Sokoban en P YTHON
Main.py
from Common import quitGame
from Constants import SCREEN_WIDTH, SCREEN_HEIGHT, BOX
from Game.SokobanLogic import playerMove
from Level import newLevel
from Resources import loadResources
from SokobanDrawing import drawAllObjects, drawWinTitle
from SokobanLogic import winGame
import pygame
def main():
pygame.mixer.pre_init(44100, -16, 2, 512)
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH(), SCREEN_HEIGHT()))
pygame.display.set_caption("Sokoban")
clock = pygame.time.Clock()
resources = loadResources()
coordMap = newLevel(1)
win = False
while True:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quitGame()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
quitGame()
elif event.key == pygame.K_1:
coordMap = newLevel(1)
elif event.key == pygame.K_2:
coordMap = newLevel(2)
else:
playerMove(coordMap, event.key, win)
win = winGame(coordMap[BOX()])
paint(screen, resources, coordMap, win)
if __name__ == __main__:
main()
Common.py
import pygame
import sys
def quitGame():
pygame.quit()
sys.exit()
def quitGameWithError():
pygame.quit()
sys.exit(1)
Constants.py
#===============================================================================
# CONSTANTS
#===============================================================================
def SCREEN_WIDTH():
return 256
def SCREEN_HEIGHT():
return 288
def WALL():
return wall
def BOX():
return box
def DARKBOX():
return darkbox
def GOAL():
return goal
def PLAYER():
return player
def EMPTY():
return empty
def RES_SIZE_X():
return 32
def RES_SIZE_Y():
return 32
def MIN_POS_X():
return 0
def MAX_POS_X():
return 7
def MIN_POS_Y():
return 0
def MAX_POS_Y():
return 8
def DOWN():
return 0
def UP():
return 1
def LEFT():
return 2
def RIGHT():
return 3
Level.py
from Constants import EMPTY, WALL, GOAL, PLAYER, BOX
from Constants import DARKBOX
from Resources import resourceNames
from SokobanLogic import collideWith
def level1():
return [[W],[W],[W],[W],[W],[E],[E],
[W],[E],[E],[E],[W],[E],[E],
[W],[E],[W],[E,B],[W],[W],[W],
[W],[E],[E,P],[E],[G],[G,B],[W],
[W],[W],[W],[W],[W],[W],[W]
]
def level1Size():
return (7,5)
def level2():
return [[E],[E],[W],[W],[W],[W],[W],[E],
[W],[W],[W],[E],[E],[E],[W],[E],
[W],[G],[E,P],[E,B],[E],[E],[W],[E],
[W],[W],[W],[E],[E,B],[G],[W],[E],
[W],[G],[W],[W],[E,B],[E],[W],[E],
[W],[E],[W],[E],[G],[E],[W],[W],
[W],[E,B],[E],[B,G],[E,B],[E,B],[G],[W],
[W],[E],[E],[E],[G],[E],[E],[W],
[W],[W],[W],[W],[W],[W],[W],[W]
]
def level2Size():
return (8,9)
def parseCode(code):
if code == E:
return EMPTY()
elif code == W:
return WALL()
elif code == G:
return GOAL()
elif code == P:
return PLAYER()
elif code == B:
return BOX()
def initializeCoordMap(coordMap):
for objName in resourceNames():
coordMap[objName] = []
return coordMap
def reAddBoxesToVerifyDarkBoxes(coordMap):
boxes = coordMap[BOX()]
coordMap[BOX()] = []
for box in boxes:
if collideWith(coordMap, GOAL(), box):
coordMap[DARKBOX()].append(box)
else:
coordMap[BOX()].append(box)
return coordMap
def newLevel(levelNumber):
if levelNumber == 1:
return mkCoordMap(level1(), level1Size())
elif levelNumber == 2:
return mkCoordMap(level2(), level2Size())
Resources.py
from Common import quitGameWithError
from Constants import EMPTY, WALL, GOAL, BOX, PLAYER, DARKBOX
import os
import pygame
IMG_DIR = "resources/img"
SONIDO_DIR = "resources/snd"
#===============================================================================
# BASIC LOAD RESOURCES
#===============================================================================
#===============================================================================
# LOAD RESOURCES
#===============================================================================
SokobanDrawing.py
from Constants import RES_SIZE_X, RES_SIZE_Y, SCREEN_WIDTH, SCREEN_HEIGHT
from Resources import resourceNames
import pygame
#===============================================================================
# DRAWING OBJECTS
#===============================================================================
#===============================================================================
# DRAWING TITLES
#===============================================================================
def drawWinTitle(screen):
drawTitleWithShadow(screen, "YOU WIN!",
(SCREEN_WIDTH()/2 - 56, SCREEN_HEIGHT()/2 - 20), 32)
drawTitleWithShadow(screen, "CHOOSE ANOTHER LEVEL",
(SCREEN_WIDTH()/2 - 110, SCREEN_HEIGHT()/2 + 20), 24)
drawTitleWithShadow(screen, "(PRESS 1 or 2)",
(SCREEN_WIDTH()/2 - 60, SCREEN_HEIGHT()/2 + 40), 24)
SokobanLogic.py
from Constants import WALL, BOX, DARKBOX, DOWN, UP, LEFT, RIGHT, GOAL, \
PLAYER, MAX_POS_Y, MIN_POS_Y, MIN_POS_X, MAX_POS_X
import pygame
#===============================================================================
# COLLISION DETECTION
#===============================================================================
#===============================================================================
# MAIN LOGIC
#===============================================================================
def updateGame(coordMap,aDir):
oldCoord = coordMap[PLAYER()][0]
newCoord = moveWorker(oldCoord,aDir)
if not collideWith(coordMap, WALL(), newCoord):
if collideWith(coordMap, BOX(), newCoord) or
collideWith(coordMap, DARKBOX(), newCoord):
wasChanged = changeBoxPos(coordMap, aDir, newCoord)
if(wasChanged):
changeWorker(coordMap, newCoord)
else:
changeWorker(coordMap, newCoord)
return coordMap
def winGame(boxes):
# completar
#===============================================================================
# BOXES
#===============================================================================
def moveBox((x,y),aDir):
if aDir == DOWN():
return (x,y+1)
elif aDir == UP():
return (x,y-1)
elif aDir == LEFT():
return (x-1,y)
elif aDir == RIGHT():
return (x+1,y)
#===============================================================================
# WORKER
#===============================================================================
def moveWorker(oldCoord,aDir):
# completar
def moveWorkerDown((x,y)):
if(y < MAX_POS_Y()):
return (x,y+1)
else:
return (x,y)
def moveWorkerUp((x,y)):
if(y > MIN_POS_Y()):
return (x,y-1)
else:
return (x,y)
def moveWorkerLeft((x,y)):
if(x > MIN_POS_X()):
return (x-1,y)
else:
return (x,y)
def moveWorkerRight((x,y)):
if(x < MAX_POS_X()):
return (x+1,y)
else:
return (x,y)
TestLevel.py
from Constants import SCREEN_WIDTH, SCREEN_HEIGHT, EMPTY, GOAL, BOX, PLAYER, \
WALL
from Level import parseCode, initializeCoordMap, populateCoordMap, level1, \
level1Size, mkCoordMap, level2, level2Size, newLevel
from Resources import resourceNames
import pygame
import unittest
class Test(unittest.TestCase):
def setUp(self):
pygame.init()
pygame.display.set_mode((SCREEN_WIDTH(), SCREEN_HEIGHT()))
def test_parseCode(self):
self.assertEquals(parseCode(E), EMPTY(), La letra E se debe
corresponder con EMPTY)
self.assertEquals(parseCode(G), GOAL(), La letra G se debe
corresponder con GOAL)
self.assertEquals(parseCode(B), BOX(), La letra B se debe
corresponder con EMPTY)
self.assertEquals(parseCode(P), PLAYER(), La letra P se debe
corresponder con PLAYER)
self.assertEquals(parseCode(W), WALL(), La letra P se debe
corresponder con WALL)
def test_initializeCoordMap(self):
coordMap = {}
coordMap2 = initializeCoordMap(coordMap)
def test_mkCoordMap(self):
level = level1()
levelSize = level1Size()
coordMap = {}
initializeCoordMap(coordMap)
populateCoordMap(coordMap, level, levelSize)
self.assertEquals(coordMap, coordMap2,
El diccionario debe contener todas las
coordenadas de cada elemento del
nivel a construir
)
def test_newLevel(self):
coordMap1 = {}
initializeCoordMap(coordMap1)
populateCoordMap(coordMap1, level1(), level1Size())
coordMap2 = {}
initializeCoordMap(coordMap2)
populateCoordMap(coordMap2, level2(), level2Size())
levelMap1 = newLevel(1)
levelMap2 = newLevel(2)
if __name__ == "__main__":
unittest.main()
TestResources.py
from Constants import SCREEN_WIDTH, SCREEN_HEIGHT
from Resources import resourceNames, loadResource
from Resources import loadResources
import pygame
import unittest
class Test(unittest.TestCase):
def setUp(self):
pygame.init()
pygame.display.set_mode((SCREEN_WIDTH(), SCREEN_HEIGHT()))
def test_loadResource(self):
oldDict = {}
aDict = loadResource(dict(oldDict), "box")
self.assertTrue(len(oldDict) == len(aDict) - 1,
Se debe agregar exactamente un nuevo elemento al
diccionario)
self.assertTrue("box" in aDict.keys(),
Se debe agregar como nueva clave al diccionario el
resourceName pasado por parametro)
def test_loadResources(self):
aDict = loadResources()
for res in resourceNames():
self.assertTrue(aDict,
"El diccionario debe contener la imagen: " + res)
if __name__ == "__main__":
unittest.main()